Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Deletes slack public/private channel and chat messages.
#!/usr/bin/env node
// To get stats on all channels, call:
// node ./delete-slack-messages.js
// To delete messages for a particular channel, get the Channel ID and pass as a param:
// node ./delete-slack-messages.js CHANNEL_ID
// Channel ID is on the the browser URL.: https://mycompany.slack.com/messages/MYCHANNELID/
// CONFIGURATION #######################################################################################################
const token = 'xoxp-TOKEN';
const tokenUser = 'user';
// ACCESS required:
// >> For delete:
// - chat:write:user
// - channels:history
// - groups:history
// - mpim:history
// - im:history
// >> For stats:
// - channels:read
// - groups:read
// - mpim:read
// - im:read
// - users:read
// - channels:history
// - groups:history
// - mpim:history
// - im:history
// GLOBALS #############################################################################################################
const https = require('https');
const baseApiUrl = 'https://slack.com/api/';
const messages = [];
let delay = 300; // Delay between delete operations in milliseconds
let nextCursor = '';
// ---------------------------------------------------------------------------------------------------------------------
function deleteMessage(channel) {
if (messages.length == 0) {
if (nextCursor) {
processHistory();
}
return;
}
const ts = messages.shift();
https.get(`${baseApiUrl}chat.delete?token=${token}&channel=${channel}&ts=${ts}`, function (res) {
let body = '';
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function(){
const response = JSON.parse(body);
if (response.ok === true) {
console.log(ts + ' deleted!');
} else if (response.ok === false) {
console.log(ts + ' could not be deleted! (' + response.error + ')');
console.log(response)
if (response.error === 'ratelimited') {
delay += 100; // If rate limited error caught then we need to increase delay.
messages.push(ts);
}
}
setTimeout(function() {deleteMessage(channel);}, delay);
});
}).on('error', function (e) {
console.error("Got an error: ", e);
});
}
// ---------------------------------------------------------------------------------------------------------------------
function processHistory(channel) {
https.get(`${baseApiUrl}conversations.history?token=${token}&limit=1000&channel=${channel}&cursor=${nextCursor}`, function(res) {
let body = '';
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
nextCursor = null;
const response = JSON.parse(body);
if (response.messages && response.messages.length > 0) {
console.log(`Got ${response.messages.length}${response.has_more?'+':''} messages`);
if (response.has_more) {
nextCursor = response.response_metadata.next_cursor;
}
for (let i = 0; i < response.messages.length; i++) {
messages.push(response.messages[i].ts);
}
deleteMessage(channel);
}
});
}).on('error', function (e) {
console.error("Got an error: ", e);
});
}
function getChannelStats() {
https.get(`${baseApiUrl}conversations.list?token=${token}&types=public_channel,private_channel,mpim,im&limit=1000`, function(res) {
let body = '';
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
const response = JSON.parse(body);
if (response.channels || response.groups) {
let channels = response.channels? response.channels: [];
channels = channels.concat(response.groups? response.groups: []);
channels = channels.sort(function (chan) { return chan.name; });
console.log(`Found ${channels.length} channels`);
function getChannelHist() {
const channel = channels.shift();
if (!channel) {
return;
}
// Get channel name (if a private user chat - get that)
let channelName = channel.name;
if (!channelName && channel.user) {
channelName = channel.user;
https.get(`${baseApiUrl}users.info?token=${token}&user=${channel.user}`, function(userRes) {
let userBody = '';
userRes.on('data', function (chunk) {
userBody += chunk;
})
userRes.on('end', function () {
const userResponse = JSON.parse(userBody);
if (userResponse.user && userResponse.user.name) {
channelName = `user-${tokenUser}--${userResponse.user.name}`;
} else {
console.log(userResponse);
}
});
});
}
// Get history of the channel to find all chat messages
https.get(`${baseApiUrl}conversations.history?token=${token}&limit=1000&channel=${channel.id}`, function(channelRes) {
let channelBody = '';
channelRes.on('data', function (chunk) {
channelBody += chunk;
})
channelRes.on('end', function () {
const channelResponse = JSON.parse(channelBody);
if (channelResponse.messages) {
console.log(`${channel.id}; ${channelName}; ${channelResponse.messages.length}${channelResponse.has_more?'+':''}`);
} else if (response.error === 'ratelimited') {
delay += 100; // If rate limited error caught then we need to increase delay.
channels.push(channel);
} else {
console.log(`${channel.id}; ${channelName}; ${JSON.stringify(channelResponse)}`);
}
setTimeout(getChannelHist, delay);
});
});
}
getChannelHist();
} else {
console.log(response);
}
});
});
}
// ---------------------------------------------------------------------------------------------------------------------
let args = [];
if (process.argv[0].indexOf('node') !== -1) {
args = process.argv.slice(2, process.argv.length)
channel = process.argv[2];
} else {
args = process.argv.slice(1, process.argv.length)
}
if (args.length == 0) {
console.log('To delete messages in a channel, give the channel ID as an argument')
console.log('Fetching number of messages in each channel ...')
getChannelStats();
} else {
processHistory(args[0]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment