+const BEFORE_MSG_ID = '';
+ * Completely wipes a channel starting at a message ID.
+ * Automatically throttles based on responses from Discord servers.
+class DiscordChannelWiper {
+ constructor({beforeMsgId, authToken, batchSize, channelId}) {
+ this.beforeMsgId = beforeMsgId;
+ this.authToken = authToken;
+ this.batchSize = batchSize;
+ this.baseUrl = `https://discordapp.com/api/channels/${channelId}/messages`;
+ return this._getMessages()
+ return this._deleteMessageBatch(_messages);
+ .then(result => this._determineCompletion(result, messages))
+ .then(() => console.info('[DiscordChannelWiper] - Done Wiping Channel!'))
+ .catch(err => console.error('[DiscordChannelWiper] - Serious Failure: ', err));
+ Authorization: this.authToken
+ `${this.baseUrl}?before=${this.beforeMsgId}&limit=10`,
+ .then(resp => resp.json());
+ _deleteMessageBatch(messages) {
+ let initPromise = Promise.resolve();
+ // Iterate over every message and SEQUENTIALLY DELETE!
+ messages.forEach(msg => {
+ initPromise = initPromise
+ .then(() => this._deleteMessage(msg))
+ .then(result => this._determineDeleteSuccess(result, msg))
+ _deleteMessage(message) {
+ console.log(`[DiscordChannelWiper] - Deleting Message from ${message.author.username}, ${message.id}`);
+ return fetch(`${this.baseUrl}/${message.id}`, Object.assign(
+ return resp.text().then(text => {
+ return text ? JSON.parse(text) : {}
+ _determineDeleteSuccess(result, lastMsg) {
+ if (result.retry_after) {
+ return this._delayAndRetry(result.retry_after);
+ this.beforeMsgId = lastMsg.id;
+ _determineCompletion(result, messages) {
+ if (messages.length > 0) {
+ _delayAndRetry(delay) {
+ return new Promise(resolve => {
+ console.log(`[DiscordChannelWiper] - Delaying batch for ${delay / 1000} seconds`);
+ setTimeout(resolve, delay);
+ }).then(() => this.wipe());
+ beforeMsgId: BEFORE_MSG_ID,
+ channelId: window.location.href.split('/').pop()
+console.info(initConfig);
+new DiscordChannelWiper(initConfig).wipe();