-
-
Save firatkucuk/ee898bc919021da621689f5e47e7abac to your computer and use it in GitHub Desktop.
#!/usr/bin/env node | |
// Channel ID is on the the browser URL.: https://mycompany.slack.com/messages/MYCHANNELID/ | |
// Pass it as a parameter: node ./delete-slack-messages.js CHANNEL_ID | |
// CONFIGURATION ####################################################################################################### | |
const token = 'SLACK TOKEN'; | |
// Legacy tokens are no more supported. | |
// Please create an app or use an existing Slack App | |
// Add following scopes in your app from "OAuth & Permissions" | |
// - channels:history | |
// - groups:history | |
// - im:history | |
// - mpim:history | |
// - chat:write | |
// VALIDATION ########################################################################################################## | |
if (token === 'SLACK TOKEN') { | |
console.error('Token seems incorrect. Please open the file with an editor and modify the token variable.'); | |
} | |
let channel = ''; | |
if (process.argv[0].indexOf('node') !== -1 && process.argv.length > 2) { | |
channel = process.argv[2]; | |
} else if (process.argv.length > 1) { | |
channel = process.argv[1]; | |
} else { | |
console.log('Usage: node ./delete-slack-messages.js CHANNEL_ID'); | |
process.exit(1); | |
} | |
// GLOBALS ############################################################################################################# | |
const https = require('https') | |
const historyApiUrl = `/api/conversations.history?channel=${channel}&count=1000&cursor=`; | |
const deleteApiUrl = '/api/chat.delete'; | |
const repliesApiUrl = `/api/conversations.replies?channel=${channel}&ts=` | |
let delay = 300; // Delay between delete operations in milliseconds | |
// --------------------------------------------------------------------------------------------------------------------- | |
const sleep = delay => new Promise(r => setTimeout(r, delay)); | |
const request = (path, data) => new Promise((resolve, reject) => { | |
const options = { | |
hostname: 'slack.com', | |
port : 443, | |
path : path, | |
method : data ? 'POST' : 'GET', | |
headers : { | |
'Authorization': `Bearer ${token}`, | |
'Content-Type' : 'application/json; charset=utf-8', | |
'Accept' : 'application/json' | |
} | |
}; | |
const req = https.request(options, res => { | |
let body = ''; | |
res.on('data', chunk => (body += chunk)); | |
res.on('end', () => resolve(JSON.parse(body))); | |
}); | |
req.on('error', reject); | |
if (data) { | |
req.write(JSON.stringify(data)); | |
} | |
req.end(); | |
}); | |
// --------------------------------------------------------------------------------------------------------------------- | |
async function deleteMessages(threadTs, messages) { | |
if (messages.length == 0) { | |
return; | |
} | |
const message = messages.shift(); | |
if (message.thread_ts !== threadTs) { | |
await fetchAndDeleteMessages(message.thread_ts, ''); // Fetching replies, it will delete main message as well. | |
} else { | |
const response = await request(deleteApiUrl, {channel: channel, ts: message.ts}); | |
if (response.ok === true) { | |
console.log(message.ts + (threadTs ? ' reply' : '') + ' deleted!'); | |
} else if (response.ok === false) { | |
console.log(message.ts + ' could not be deleted! (' + response.error + ')'); | |
if (response.error === 'ratelimited') { | |
await sleep(1000); | |
delay += 100; // If rate limited error caught then we need to increase delay. | |
messages.unshift(message); | |
} | |
} | |
} | |
await sleep(delay); | |
await deleteMessages(threadTs, messages); | |
} | |
// --------------------------------------------------------------------------------------------------------------------- | |
async function fetchAndDeleteMessages(threadTs, cursor) { | |
const response = await request((threadTs ? repliesApiUrl + threadTs + '&cursor=' : historyApiUrl) + cursor); | |
if (!response.ok) { | |
console.error(response.error); | |
return; | |
} | |
if (!response.messages || response.messages.length === 0) { | |
return; | |
} | |
await deleteMessages(threadTs, response.messages); | |
if (response.has_more) { | |
await fetchAndDeleteMessages(threadTs, response.response_metadata.next_cursor); | |
} | |
} | |
// --------------------------------------------------------------------------------------------------------------------- | |
fetchAndDeleteMessages(null, ''); |
@firatkucuk thank you very much for the effort!
FWIW, this was not working for me too but i gave up because it is not that important for me.
my understanding is that, if a message is created by bot using webhook, then it is unable to delete such messages but i need it for exact same purpose.
thanks.
I have created a clone app that is identical to the working one and seems there's an issue on the slack side. I have contacted slack support.
@kadiiskiFFW and @lorvent for the new application they are no longer support tokens from query string so I've updated the code using as Authorization Bearer
header.
@firatkucuk teşekkürler hocam sorunsuz hallettik.
@akintt super.
Thanks, Fırat :) Very useful snippet.
How crazy that this work around is needed... surely it would be easier for Slack to offer this rather than getting hundreds of users spamming them with delete API calls.
Thanks for this script, it made the reset far, far, easier... even if i did need to leave it running over the weekend.
+1 much-needed feature. Thank you for the script!.
Hey, thanks for the script but i have a little problem...
I have a channel_not_found
when i run the code, yet i have the right id of the channel
Any idea ?
@Bumpyshot
channel id is at the end of the URL: https://COMPANY.slack.com/archives/CHANNEL_ID
if you're sure about that in that case maybe your token has no adequate access for that operation.
How to use this script?
First: Get your Slack Api Token
- Login to Your Apps
- Create a new app and select the workplace you would like to connect to
- From the sidebar, go to “OAuth & Permissions” page
- Under “Scopes” section -> “User Token Scopes” select the following scopes:
channels:history
groups:history
im:history
mpim:history
chat:write
- Under “OAuth Tokens for Your Workspace” section, click “Install App to Workspace” and follow the instructions
- Now, under “OAuth Tokens for Your Workspace” section, copy the “User OAuth Token”: this is your token
How to get the Channel ID which I want to delete the messages?
- Go to your Slack from the web, and navigate to the desired channel
- You can see the channel ID from the url (https://app.slack.com/client/{TEAM_ID}/{CHANNEL_ID})
- Copy the last part of the URL, this is your CHANNEL_ID
Now download the script in this page, and insert your token inside the file (under SLACK TOKEN), then save
Now, run the script: node ./delete-slack-messages.js CHANNEL_ID
(Instructions adapted from: https://gist.github.com/gummi-io/f3dbfebfcd5fd1fc4e42da1c0e2b41c8)
@JonathanNobrega
Thanks, your discription helped me!
Please tell me.
Is it possible to specify the period to be deleted by this script?
thanks to @firatkucuk and @JonathanNobrega , this script worked fine for me!
Glad to help @im-syk and @doschkinow!
Hey! When deleting messages from a DM, I got the message:
vada {
ok: false,
error: 'cant_delete_message',
warning: 'missing_charset',
response_metadata: { warnings: [ 'missing_charset' ] }
}
1650841222.763739 could not be deleted! (cant_delete_message)
Any ideas?
Thanks, I was using the bot token. Changed to user token and reinstalled the app. It worked.
Is there any chance to run this script just with 'node ./slack-delete-messages', without the channel id in the terminal?
@alevaldiviezo what do you want to achieve? Deleting all messages in all channels or just running without channel_id.?
let channel = 'put your channel id here';
// ------------------- delete following section from here
if (process.argv[0].indexOf('node') !== -1 && process.argv.length > 2) {
channel = process.argv[2];
} else if (process.argv.length > 1) {
channel = process.argv[1];
} else {
console.log('Usage: node ./delete-slack-messages.js CHANNEL_ID');
process.exit(1);
}
// ------------------- to here
Hi, thanks for your reply, I got it, the idea is to run the script as a second process with the fork command, many thanks I got it now.
Excellent script - thanks @firatkucuk !
@im-syk et al. - if anyone is interested in a version of this that deletes last 30 days, I made a version that does that. To change how long it keeps things for, update the keepTime
variable as needed.
Thanks a lot, all work fine.
@kadiiskiFFW No problem. I'll try to create an app from scratch in my spare time. It was old-style tokens and was really easy to use then slack changed to tokens with scopes. Now it's really hard to adjust things.