Skip to content

Instantly share code, notes, and snippets.

@jeffhandley
Last active November 8, 2024 21:19
Show Gist options
  • Save jeffhandley/9ce8af90ee54a15c4e80831b919f31a8 to your computer and use it in GitHub Desktop.
Save jeffhandley/9ce8af90ee54a15c4e80831b919f31a8 to your computer and use it in GitHub Desktop.
Bulk delete Twitter data through the UI
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