Last active
September 7, 2024 14:33
-
-
Save RELNO/8d2a5c19c5c8d7244661cccdd39378d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! 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