-
Star
(156)
You must be signed in to star a gist -
Fork
(56)
You must be signed in to fork a gist
-
-
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, ''); |
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 hereHi, 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.
thanks to @firatkucuk and @JonathanNobrega , this script worked fine for me!