Skip to content

Instantly share code, notes, and snippets.

@RELNO
Last active September 7, 2024 14:33
Show Gist options
  • Save RELNO/8d2a5c19c5c8d7244661cccdd39378d7 to your computer and use it in GitHub Desktop.
Save RELNO/8d2a5c19c5c8d7244661cccdd39378d7 to your computer and use it in GitHub Desktop.
//! SET YOUR TWITTER HANDLE IN THE NEXT LINE!
const yourTwitterHandle = "@XXXXXX";
//! days to keep tweets
const daysToKeep = 0;
// -------------------------------------------------------------------------------
// Random wait time between 0.5 and 1.5 seconds to avoid detection
const waitTimeSeconds = () => Math.random() + 0.5;
const sleep = (seconds) => new Promise(resolve => setTimeout(resolve, seconds * 1000));
const waitForElement = async (selectorFunc, timeout = 5000) => {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
const element = selectorFunc();
if (element) return element;
await sleep(100);
}
return null;
};
const findButtonByText = (text) =>
[...document.querySelectorAll("span, div, button")]
.find(el => el.textContent.trim() === text);
const isOlderThanDays = (datetime, days) => {
const tweetDate = new Date(datetime);
const thresholdDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
return tweetDate < thresholdDate;
};
const deleteTweet = async (article, datetime) => {
const moreButton = article.querySelector('[aria-label="More"]');
if (!moreButton) return false;
article.scrollIntoView({ behavior: 'smooth', block: 'center' });
moreButton.click();
const deleteButton = await waitForElement(() => findButtonByText("Delete"));
if (!deleteButton) {
console.error("Delete button not found.");
return false;
}
deleteButton.click();
const confirmButton = await waitForElement(() => document.querySelector('[data-testid="confirmationSheetConfirm"]'));
if (!confirmButton) {
console.error("Confirmation button not found.");
return false;
}
confirmButton.click();
console.log(`Tweet from ${datetime} deleted.`);
return true;
};
const processArticle = async (article) => {
const spanElements = article.querySelectorAll("span");
const isUserTweet = Array.from(spanElements).some(span => span.textContent === yourTwitterHandle);
if (!isUserTweet) return;
const timeElement = article.querySelector("time");
if (!timeElement) return;
const datetime = timeElement.getAttribute("datetime");
if (!datetime || !isOlderThanDays(datetime, daysToKeep)) return;
try {
await deleteTweet(article, datetime);
} catch (e) {
console.error(`Error deleting tweet: ${e}`);
}
};
const walkTweets = async () => {
const articles = document.getElementsByTagName("article");
for (const article of articles) {
await processArticle(article);
await sleep(waitTimeSeconds());
}
};
const main = async () => {
while (true) {
await walkTweets();
await sleep(waitTimeSeconds());
}
};
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment