Last active
November 8, 2024 21:19
-
-
Save jeffhandley/9ce8af90ee54a15c4e80831b919f31a8 to your computer and use it in GitHub Desktop.
Bulk delete Twitter data through the UI
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
let lastTweet = null, | |
lastReply = null, | |
lastRetweet = null, | |
lastFollower = null, | |
lastConversation = null; | |
const initialBackoff = 10000; | |
const backoffIncrease = 5000; | |
let backoff = initialBackoff; | |
function deleteNextTweet() { | |
const [pinned, nextTweet] = [...document.querySelectorAll("button[data-testid='caret']")]; | |
if (!nextTweet || !nextTweet.click) { | |
window.scrollBy(0, 250); | |
return; | |
} | |
if (nextTweet == lastTweet) { | |
console.log(`Last Tweet was not deleted. Waiting ${backoff}ms...`); | |
window.setTimeout(deleteNextTweet, backoff); | |
backoff += backoffIncrease; | |
return; | |
} | |
nextTweet.scrollIntoViewIfNeeded(); | |
nextTweet.click(); | |
window.setTimeout(() => { | |
const deleteMenu = [...document.querySelectorAll("div[data-testid='Dropdown'] div[role='menuitem']")] | |
.filter(m => m.innerText == 'Delete'); | |
if (!deleteMenu || deleteMenu.length != 1 || !deleteMenu[0].click) return; | |
deleteMenu[0].click(); | |
window.setTimeout(() => { | |
const deleteConfirm = document.querySelector("button[data-testid='confirmationSheetConfirm']"); | |
if (!deleteConfirm || !deleteConfirm.click) return; | |
lastTweet = nextTweet; | |
backoff = initialBackoff; | |
deleteConfirm.click(); | |
console.log('Tweet Deleted. Next...'); | |
window.setTimeout(deleteNextTweet, 100); | |
}, 50); | |
}, 50); | |
} | |
function deleteNextReply() { | |
let [pinned, nextReply] = [...document.querySelectorAll("article[data-testid='tweet']:has(div[data-testid='User-Name'] a[href='/jeffhandley']) button[data-testid='caret']")]; | |
if (!nextReply || !nextReply.click) { | |
window.scrollBy(0, 250); | |
return; | |
} | |
if (nextReply == lastReply) { | |
console.log(`Last Reply was not deleted. Waiting ${backoff}ms...`); | |
window.setTimeout(deleteNextReply, backoff); | |
backoff += backoffIncrease; | |
return; | |
} | |
nextReply.scrollIntoViewIfNeeded(); | |
nextReply.click(); | |
window.setTimeout(() => { | |
const deleteMenu = [...document.querySelectorAll("div[data-testid='Dropdown'] div[role='menuitem']")] | |
.filter(m => m.innerText == 'Delete'); | |
if (!deleteMenu || deleteMenu.length != 1 || !deleteMenu[0].click) return; | |
deleteMenu[0].click(); | |
window.setTimeout(() => { | |
const deleteConfirm = document.querySelector("button[data-testid='confirmationSheetConfirm']"); | |
if (!deleteConfirm || !deleteConfirm.click) return; | |
lastReply = nextReply; | |
backoff = initialBackoff; | |
deleteConfirm.click(); | |
console.log('Reply Deleted. Next...'); | |
window.setTimeout(deleteNextReply, 100); | |
}, 50); | |
}, 50); | |
} | |
function deleteNextRetweet() { | |
const nextRetweet = document.querySelector("button[data-testid='unretweet']"); | |
if (!nextRetweet || !nextRetweet.click) { | |
window.scrollBy(0, 250); | |
return; | |
} | |
if (nextRetweet == lastRetweet) { | |
console.log(`Last Retweet was not deleted. Waiting ${backoff}ms...`); | |
window.setTimeout(deleteNextRetweet, backoff); | |
backoff += backoffIncrease; | |
return; | |
} | |
nextRetweet.scrollIntoViewIfNeeded() | |
nextRetweet.click(); | |
window.setTimeout(() => { | |
const nextConfirm = document.querySelector("div[data-testid='unretweetConfirm']"); | |
if (!nextConfirm || !nextConfirm.click) return; | |
lastRetweet = nextRetweet; | |
backoff = initialBackoff; | |
nextConfirm.click(); | |
console.log('Retweet Deleted. Next...'); | |
window.setTimeout(deleteNextRetweet, 100); | |
}, 50); | |
} | |
function deleteNextFollower() { | |
const nextFollower = document.querySelector("button[data-testid='UserCell']:has(div[data-testid='userFollowIndicator']) button[aria-label='More']"); | |
if (!nextFollower || !nextFollower.click) { | |
window.scrollBy(0, 75); | |
return; | |
} | |
if (nextFollower == lastFollower) { | |
console.log(`Last Follower was not removed. Waiting ${backoff}ms...`); | |
window.setTimeout(deleteNextFollower, backoff); | |
backoff += backoffIncrease; | |
return; | |
} | |
nextFollower.scrollIntoViewIfNeeded(); | |
nextFollower.click(); | |
window.setTimeout(() => { | |
const deleteMenuItem = document.querySelector("div[role='menu'] div[data-testid='Dropdown'] div[data-testid='removeFollower']"); | |
if (!deleteMenuItem || !deleteMenuItem.click) return; | |
deleteMenuItem.click(); | |
window.setTimeout(() => { | |
const deleteConfirm = document.querySelector("button[data-testid='confirmationSheetConfirm']"); | |
if (!deleteConfirm || !deleteConfirm.click) return; | |
lastFollower = nextFollower; | |
backoff = initialBackoff; | |
deleteConfirm.click(); | |
console.log('Follower Removed. Next...'); | |
window.setTimeout(deleteNextFollower, 100); | |
}, 50); | |
}, 50); | |
} | |
function deleteNextConversation() { | |
const nextConversation = document.querySelector("div[data-testid='conversation'] button[aria-label='More']"); | |
if (!nextConversation || !nextConversation.click) { | |
window.scrollBy(0, 100); | |
return; | |
} | |
if (nextConversation == lastConversation) { | |
console.log(`Last Conversation was not deleted. Waiting ${backoff}ms...`); | |
window.setTimeout(deleteNextConversation, backoff); | |
backoff += backoffIncrease; | |
return; | |
} | |
nextConversation.scrollIntoViewIfNeeded(); | |
nextConversation.click(); | |
window.setTimeout(() => { | |
const deleteMenu = [...document.querySelectorAll("div[role='menu'] div[data-testid='Dropdown'] div[role='menuitem']")] | |
.filter(m => m.innerText == 'Delete conversation'); | |
if (!deleteMenu || deleteMenu.length != 1 || !deleteMenu[0].click) return; | |
deleteMenu[0].click(); | |
window.setTimeout(() => { | |
const deleteConfirm = document.querySelector("button[data-testid='confirmationSheetConfirm']"); | |
if (!deleteConfirm || !deleteConfirm.click) return; | |
lastConversation = nextConversation; | |
backoff = initialBackoff; | |
deleteConfirm.click(); | |
console.log('Conversation Deleted. Next...'); | |
window.setTimeout(deleteNextConversation, 100); | |
}, 50); | |
}, 50); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment