Skip to content

Instantly share code, notes, and snippets.

@Vractos
Forked from firatkucuk/delete-slack-messages.js
Last active November 10, 2021 23:16
Show Gist options
  • Save Vractos/8a725b825d4122a56ce0d20128afa6c5 to your computer and use it in GitHub Desktop.
Save Vractos/8a725b825d4122a56ce0d20128afa6c5 to your computer and use it in GitHub Desktop.
Deletes slack public/private channel messages, private chat messages and channel thread replies.
#!/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 baseApiUrl = 'slack.com';
const historyApiUrl = `/api/conversations.history?channel=${channel}&count=1000&cursor=`;
const deleteApiUrl = `/api/chat.delete?channel=${channel}&ts=`;
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 get = url => new Promise((resolve, reject) =>
https
.get({hostname: baseApiUrl, path: url, headers: { Authorization: `Bearer ${token}` }}, res => {
let body = ''
res.on('data', chunk => (body += chunk))
res.on('end', () => resolve(JSON.parse(body)))
})
.on('error', reject)
);
// ---------------------------------------------------------------------------------------------------------------------
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 get(deleteApiUrl + 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 get((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, '');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment