Last active
January 10, 2024 21:15
-
-
Save JamieMason/f8992ebf95423244b730b2c393c321ef to your computer and use it in GitHub Desktop.
Bulk Delete every WhatsApp Chat Message
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
// Delete every Chat in WhatsApp, by Jamie Mason (https://twitter.com/fold_left) | |
// https://gist.github.com/JamieMason/f8992ebf95423244b730b2c393c321ef | |
// | |
// 1. Go to https://web.whatsapp.com/ and sign in. | |
// 2. Archive any messages you don't want deleting, you can unarchive them after. | |
// 3. Open the Developer Console. (COMMAND+ALT+I on Mac) | |
// 4. Paste this into the Developer Console and run it. | |
// 5. If it gets stuck, scroll up and down in the list of chats. | |
// 6. Refresh the page and run again if you have any problems. | |
// 7. This Script does not Exit Groups or clear messages in them. | |
// | |
// Last Updated: 08 December 2020 | |
// Only tested in Firefox and Chrome for Mac | |
(async () => { | |
const $profilePic = '[src^="https://web.whatsapp.com/pp"]'; | |
const $defaultUserProfilePic = '[data-icon="default-user"]'; | |
const $defaultGroupPic = '[data-icon="default-group"]'; | |
const $chatItem = '#pane-side [role="option"]'; | |
const $selectedChatName = '#main header span'; | |
const $chatMenu = '#main header [data-testid="menu"]'; | |
const $deleteChatButton = '#main header [role="button"][title="Delete chat"]'; | |
const $exitGroupButton = '#main header [role="button"][title="Exit group"]'; | |
const $overlayButton = '.overlay [role="button"]'; | |
const qsa = (selector) => Array.from(document.querySelectorAll(selector)); | |
const leftClick = (el) => { | |
['mousedown', 'click', 'mouseup'].forEach((mouseEventType) => | |
el.dispatchEvent( | |
new MouseEvent(mouseEventType, { | |
view: window, | |
bubbles: true, | |
cancelable: true, | |
buttons: 1, | |
}) | |
) | |
); | |
}; | |
const sleep = ({ seconds }) => | |
new Promise((proceed) => { | |
console.log(`WAITING FOR ${seconds} SECONDS...`); | |
setTimeout(proceed, seconds * 1000); | |
}); | |
const waitFor = (isReady) => | |
new Promise((resolve) => { | |
const checkAgain = () => { | |
if (isReady()) { | |
resolve(); | |
} else { | |
requestIdleCallback(checkAgain, { timeout: 1000 }); | |
} | |
}; | |
checkAgain(); | |
}); | |
const isChatNameElement = (el) => { | |
const hasNoChildren = el.firstElementChild === null; | |
const hasLargeText = getComputedStyle(el)['font-size'] === '16px'; | |
return hasNoChildren && hasLargeText; | |
}; | |
const chatList = { | |
item: { | |
getName(item) { | |
const spans = Array.from(item.querySelectorAll('span')); | |
const name = spans.find(isChatNameElement); | |
return name ? name.innerText : ''; | |
}, | |
getByName(name) { | |
return qsa($chatItem).find((item) => chatList.item.getName(item) === name); | |
}, | |
getProfilePic(item) { | |
return ( | |
item.querySelector($profilePic) || | |
item.querySelector($defaultUserProfilePic) || | |
item.querySelector($defaultGroupPic) | |
); | |
}, | |
isSelected(item) { | |
return selectedChat.getName() === chatList.item.getName(item); | |
}, | |
async select(item) { | |
leftClick(chatList.item.getProfilePic(item)); | |
await waitFor(() => chatList.item.isSelected(item)); | |
}, | |
}, | |
getNames() { | |
return qsa($chatItem).map(chatList.item.getName); | |
}, | |
async resetList() { | |
const el = document.querySelector('#pane-side'); | |
el.scrollTop = el.scrollHeight; | |
await sleep({ seconds: 0.5 }); | |
el.scrollTop = 0; | |
}, | |
}; | |
const selectedChat = { | |
getName() { | |
const spans = Array.from(document.querySelectorAll($selectedChatName)); | |
const name = spans.find(isChatNameElement); | |
return name ? name.innerText : ''; | |
}, | |
overlay: { | |
getConfirmDeleteButton() { | |
return Array.from(document.querySelectorAll($overlayButton)).find( | |
(button) => button.innerText === 'DELETE' | |
); | |
}, | |
}, | |
menu: { | |
getMenuButton() { | |
return document.querySelector($chatMenu); | |
}, | |
getDeleteChatButton() { | |
return document.querySelector($deleteChatButton); | |
}, | |
getExitGroupButton() { | |
return document.querySelector($exitGroupButton); | |
}, | |
hasDeleteOrExitButton() { | |
return Boolean( | |
selectedChat.menu.getDeleteChatButton() || selectedChat.menu.getExitGroupButton() | |
); | |
}, | |
async open() { | |
leftClick(selectedChat.menu.getMenuButton()); | |
await waitFor(selectedChat.menu.hasDeleteOrExitButton); | |
}, | |
async deleteChat() { | |
if (selectedChat.menu.getDeleteChatButton()) { | |
console.log('Clicking "Delete chat" Button...'); | |
leftClick(selectedChat.menu.getDeleteChatButton()); | |
console.log('Waiting for "Delete chat with <name>?" Window...'); | |
await waitFor(selectedChat.overlay.getConfirmDeleteButton); | |
console.log('Clicking "Delete" Button...'); | |
leftClick(selectedChat.overlay.getConfirmDeleteButton()); | |
} else { | |
console.log('Skipping because "%s" is a Group'); | |
leftClick(document.body); | |
} | |
}, | |
}, | |
}; | |
const deleteAnotherBatch = async (visibleNames) => { | |
console.log('%s Chats found...', visibleNames); | |
for (const name of visibleNames) { | |
console.group(name); | |
console.log('Looking for Chat...'); | |
var item = chatList.item.getByName(name); | |
if (item) { | |
console.log('Scrolling to Chat...'); | |
item.scrollIntoView(); | |
} | |
var item = chatList.item.getByName(name); | |
if (item) { | |
console.log('Opening Chat...'); | |
await chatList.item.select(item); | |
console.log('Opening Chat Menu...'); | |
await selectedChat.menu.open(); | |
console.log('Deleting Chat...'); | |
await selectedChat.menu.deleteChat(); | |
} | |
console.groupEnd(name); | |
} | |
}; | |
let visibleNames; | |
while ((visibleNames = chatList.getNames().filter(Boolean)).length > 0) { | |
await deleteAnotherBatch(visibleNames); | |
} | |
})(); |
I know this isn't much help but when I ran this for myself I was using Firefox on Mac. If you got no output whatsoever my guess is that it didn't find any chats on the first attempt. I've updated the script to output some information about this, which will help debug the problem.
Thanks for efforts man, tho it just flooded Array(0) Chats found...
in the output, i could've tried to debug if it were in python but no hope in JAVA.
OK cool, I tried it in Chrome just now and that wasn't working – that's fixed now so hopefully it will fix your Browsers too.
I just installed and ran it in Microsoft Edge for Mac Version 87.0.664.57 (Official build) (64-bit) and it's all good. I can't do much more to help from here unfortunately.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried on MSEdge And Brave Browser but ended up with same result.
no output - nothing and the the tab gets hanged should i already open a chat or not.. cuz i tried both..
i tried different whatsapp accounts too (ya it doesn't matter but still)..
Look at this Screen Shot