Skip to content

Instantly share code, notes, and snippets.

@ivmirx
Forked from rcx/delete-all-messages.js
Created November 9, 2023 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivmirx/7d147d35e6a67881e998c74d0fe150ab to your computer and use it in GitHub Desktop.
Save ivmirx/7d147d35e6a67881e998c74d0fe150ab to your computer and use it in GitHub Desktop.
Delete all your messages in a Discord channel
/*
* Discord: Don't copy stuff into this box
* Me: dOn'T COpy sTuFf iNtO tHIs bOx
*/
clearMessages = function (guild_id, author_id, authToken, deleted = new Set()) {
if (guild_id[0] == "_" && guild_id[guild_id.length - 1] == "_") {
alert("Oops! You forgot to set the guild_id. Please fill it in.")
return;
}
if (author_id[0] == "_" && author_id[author_id.length - 1] == "_") {
alert("Oops! You forgot to set the author_id. Please fill it in.")
return;
}
const searchURL = `https://discordapp.com/api/v9/guilds/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true&sort_by=timestamp&sort_order=asc`
const headers = { Authorization: authToken }
let clock = 0
interval = 3000
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration)
})
}
function loadMessages() {
return fetch(searchURL, { headers })
}
function tryDeleteMessage(message) {
// RAce coNDItiOn
if (!deleted.has(message.id)) { // skip already deleted messages
console.log(`Deleting message ${message.id} from ${message.author.username} (${message.content}...)`)
return fetch(`https://discordapp.com/api/v9/channels/${message.channel_id}/messages/${message.id}`, { headers, method: 'DELETE' })
}
}
let messagesStore = []
loadMessages()
.then(resp => resp.json())
.then(messages => {
messages = messages.messages
if (messages === undefined || messages === null || messages.length == 0) {
console.log(`Couldn't load messages. Check guild id, author id, and auth token.`)
return
}
messages = messages.filter(m => m) // clean undefined
messages = [].concat.apply([], messages); // flatten
messages = messages.filter(m => m) // clean undefined
if (messages.length === 0) {
console.log(`Couldn't load messages. Check guild id, author id, and auth token.`)
return
}
// only delete hits
messages = messages.filter(m => m.hit == true)
// unique by id
messages = messages.filter((e, i) => messages.findIndex(a => a.id === e.id) === i);
beforeId = messages[messages.length-1].id
messagesStore = messagesStore.concat(messages)
return Promise.all(messagesStore.map(message => {
return delay(clock += interval)
.then(() => tryDeleteMessage(message))
.then(resp => {
if (resp) {
if (resp.status == 429) {
interval += 100
console.log(`Too fast; bumping interval to ${interval}`)
} else if (resp.status === 204) {
deleted.add(message.id) // mark deleted
return resp.text()
}
}
})
}))
})
.then(function() {
if (messagesStore.length !== 0) {
clearMessages(guild_id, author_id, authToken, deleted)
} else {
console.log(`We have loaded all messages in this chat.`)
}
})
}
// If the script is having trouble automatically grabbing auth token, please fill it in manually here. Check README for instructions.
authToken = "";
guild_id = '____________guild_id_here_______________'
author_id = '____________author_id_here______________'
function grabAuthTokenFast() {
var localToken = document.body.appendChild(document.createElement(`iframe`)).contentWindow.localStorage.token;
if (localToken !== undefined) {
authToken = JSON.parse(localToken);
return true;
}
return false;
}
function grabAuthToken() {
if (authToken.length === 0) {
// Lmao bypass token security measures
window.onbeforeunload = grabAuthToken;
window.location.reload();
// yoink
var localToken = document.body.appendChild(document.createElement(`iframe`)).contentWindow.localStorage.token;
if (localToken !== undefined) {
authToken = JSON.parse(localToken);
setTimeout(main, 100, authToken);
}
}
return false;
}
function main(authToken) {
if (authToken.length !== 0) {
console.log(`Successfully grabbed your auth token: ` + authToken)
console.log(`Don't share this token with anyone!`)
clearMessages(guild_id, author_id, authToken);
} else {
console.log(`Getting the auth token from localStorage isn't supported on your client. Use Firefox or grab it from a network request's headers.`)
console.log(`To do that go to the Network tab of your inspector and copy the Authorization header of a request. There are detailed instructions in the README.`)
}
}
if (grabAuthTokenFast()) {
console.log("Successfully grabbed auth token using easy method");
main(authToken);
} else {
window.alert("Grabbing your auth token. If a confirm window shows up, please click 'Cancel' in Chrome / 'Stay on Page' in Firefox.");
if (authToken.length !== 0) {
main(authToken);
} else {
grabAuthToken();
}
}

Delete all messages in a Discord channel

This works best in Firefox, I haven't tested it in Chrome. On the desktop client, it may have trouble getting the Auth token from LocalStorage so you need to grab it from a request's headers and replace the parameter "authToken" on the last line with it. There's instructions on how to do that below.

Preqrequisites:

  • computer
  • general knowledge of your browser's inspector/developer tools
  • possibly even a brain

1. Grab guild and author ids

The script uses the internal id values Discord refers to the selected server and user by. The easy way to do this is to enable Developer Mode in your Discord settings, after which you can simply right click the server's icon and your name and click "Copy ID". Otherwise, you can grab the server's id from the URL, and you can get your own id using the network tab of your browser's inspector.

2. Get your authorization token (now automated)

This is now automated thanks to @cntVertex, despite Discord "hiding" the token from localStorage and the DOM. If it isn't able to automatically grab it then you need to get it from a network request. Follow these easy steps:

  1. Open the inspector (Ctrl-Shift-I)
  2. Open the Network tab of your inspector
  3. Open any request to Discord's servers
  4. Look for the "Authorization" request header. Copy that into the line var authToken = "". For example it might look like var authToken = "mfa.a9ushg92ru9gh9ufhsgjuidfhsgiojfhgjishefrgih3er9u3rg_asdfu9ghauisdfhguiahsdguiahsdigua"

3. Get the script

Copy-paste the script into the javascript console, and replace ____________guild_id_here_______________ and ____________author_id_here______________ with the respective ids copied in Step 1.

4. Launch

Strike the Return key on your keyboard...come on, this is not rocket science man.

Also if it does not get your auth token successfully the first time just try running it again.

FAQ

  • How do I use this to delete DMs? Replace searchURL with https://discordapp.com/api/v6/channels/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true. For example, replace this line:
const searchURL = `https://discordapp.com/api/v8/guilds/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true`

with

const searchURL = `https://discordapp.com/api/v8/channels/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true`

The guild_id however isn't the ID of the person who you are DMing. It is actually the ID of the channel of the DM which is a subtle but important distinction. I'm not aware of any easy way to grab this other than to just look at the network inspector under the developer tools.

  • How to delete by oldest messages first?

Add &sort_by=timestamp&sort_order=asc to searchURL

  • How to only delete messages containing some text "abcd"?

Add &content=whatever into the searchURL. For example, https://discordapp.com/api/v6/channels/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true&content=badword to delete only messages containing "badword".

  • (By @ivmirx) If you want to delete messages before a specific date, do the following:
  1. Open any server to make the search field visible.
  2. Open the "Network" tab in the inspector and clean it from old requests with the trash can icon.
  3. Click in Discord's search field to show the dropdown, then click the "before" option.
  4. Select the date in the calendar.
  5. In the "Network" tab look for the request that contains ?max_id=....
  6. Click on it and copy the max_id=... part from the URL on the right.
  7. Append it to the script's request in the Line 6 by using &.

So now you should have something like: https://discordapp.com/api/v6/guilds/${guild_id}/messages/search?author_id=${author_id}&include_nsfw=true&max_id=540727993958400000 (this example is for 2019-02-01). Also, by manually picking searchURL, you can delete messages matching a certain query, like mentioning someone, containing certain words, etc.

  • Is there a python version of this script so I can run it without opening Discord

Yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment