Add auto-delete plugin
This commit is contained in:
parent
c0b12254b1
commit
dc27821a63
4 changed files with 157 additions and 0 deletions
|
@ -31,6 +31,7 @@
|
|||
"MESSAGE_DELETE": "🗑 Message (`{message.id}`) from {userMention(user)} deleted in {channelMention(channel)} (originally posted at **{messageDate}**):{messageSummary(message)}",
|
||||
"MESSAGE_DELETE_BULK": "🗑 **{count}** messages deleted in {channelMention(channel)} ({archiveUrl})",
|
||||
"MESSAGE_DELETE_BARE": "🗑 Message (`{messageId}`) deleted in {channelMention(channel)} (no more info available)",
|
||||
"MESSAGE_DELETE_AUTO": "🗑 Auto-deleted message (`{message.id}`) from {userMention(user)} in {channelMention(channel)} (originally posted at **{messageDate}**):{messageSummary(message)}",
|
||||
|
||||
"VOICE_CHANNEL_JOIN": "🎙 🔵 {userMention(member)} joined **{channel.name}**",
|
||||
"VOICE_CHANNEL_MOVE": "🎙 ↔ {userMention(member)} moved from **{oldChannel.name}** to **{newChannel.name}**",
|
||||
|
|
|
@ -62,4 +62,6 @@ export enum LogType {
|
|||
|
||||
SCHEDULED_REPEATED_MESSAGE,
|
||||
REPEATED_MESSAGE,
|
||||
|
||||
MESSAGE_DELETE_AUTO,
|
||||
}
|
||||
|
|
152
backend/src/plugins/AutoDelete.ts
Normal file
152
backend/src/plugins/AutoDelete.ts
Normal file
|
@ -0,0 +1,152 @@
|
|||
import { IPluginOptions, logger } from "knub";
|
||||
import * as t from "io-ts";
|
||||
import { ZeppelinPlugin } from "./ZeppelinPlugin";
|
||||
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||
import { SavedMessage } from "../data/entities/SavedMessage";
|
||||
import { convertDelayStringToMS, MINUTES, sorter, stripObjectToScalars, tDelayString } from "../utils";
|
||||
import { GuildLogs } from "../data/GuildLogs";
|
||||
import { LogType } from "../data/LogType";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
const ConfigSchema = t.type({
|
||||
enabled: t.boolean,
|
||||
delay: tDelayString,
|
||||
});
|
||||
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||
|
||||
interface IDeletionQueueItem {
|
||||
deleteAt: number;
|
||||
message: SavedMessage;
|
||||
}
|
||||
|
||||
const MAX_DELAY = 5 * MINUTES;
|
||||
|
||||
export class AutoDeletePlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||
public static pluginName = "auto_delete";
|
||||
public static showInDocs = true;
|
||||
|
||||
public static configSchema = ConfigSchema;
|
||||
|
||||
public static pluginInfo = {
|
||||
prettyName: "Auto-delete",
|
||||
description: "Allows Zeppelin to auto-delete messages from a channel after a delay",
|
||||
configurationGuide: "Maximum deletion delay is currently 5 minutes",
|
||||
};
|
||||
|
||||
protected guildSavedMessages: GuildSavedMessages;
|
||||
protected guildLogs: GuildLogs;
|
||||
|
||||
protected onMessageCreateFn;
|
||||
protected onMessageDeleteFn;
|
||||
protected onMessageDeleteBulkFn;
|
||||
|
||||
protected deletionQueue: IDeletionQueueItem[];
|
||||
protected nextDeletion: number;
|
||||
protected nextDeletionTimeout;
|
||||
|
||||
protected maxDelayWarningSent = false;
|
||||
|
||||
public static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
enabled: false,
|
||||
delay: "5s",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected onLoad() {
|
||||
this.guildSavedMessages = GuildSavedMessages.getGuildInstance(this.guildId);
|
||||
this.guildLogs = new GuildLogs(this.guildId);
|
||||
|
||||
this.deletionQueue = [];
|
||||
|
||||
this.onMessageCreateFn = this.onMessageCreate.bind(this);
|
||||
this.onMessageDeleteFn = this.onMessageDelete.bind(this);
|
||||
this.onMessageDeleteBulkFn = this.onMessageDeleteBulk.bind(this);
|
||||
|
||||
this.guildSavedMessages.events.on("create", this.onMessageCreateFn);
|
||||
this.guildSavedMessages.events.on("delete", this.onMessageDeleteFn);
|
||||
this.guildSavedMessages.events.on("deleteBulk", this.onMessageDeleteBulkFn);
|
||||
}
|
||||
|
||||
protected onUnload() {
|
||||
this.guildSavedMessages.events.off("create", this.onMessageCreateFn);
|
||||
this.guildSavedMessages.events.off("delete", this.onMessageDeleteFn);
|
||||
this.guildSavedMessages.events.off("deleteBulk", this.onMessageDeleteFn);
|
||||
clearTimeout(this.nextDeletionTimeout);
|
||||
}
|
||||
|
||||
protected addMessageToDeletionQueue(msg: SavedMessage, delay: number) {
|
||||
const deleteAt = Date.now() + delay;
|
||||
this.deletionQueue.push({ deleteAt, message: msg });
|
||||
this.deletionQueue.sort(sorter("deleteAt"));
|
||||
|
||||
this.scheduleNextDeletion();
|
||||
}
|
||||
|
||||
protected scheduleNextDeletion() {
|
||||
if (this.deletionQueue.length === 0) {
|
||||
clearTimeout(this.nextDeletionTimeout);
|
||||
return;
|
||||
}
|
||||
|
||||
const firstDeleteAt = this.deletionQueue[0].deleteAt;
|
||||
clearTimeout(this.nextDeletionTimeout);
|
||||
this.nextDeletionTimeout = setTimeout(() => this.deleteNextItem(), firstDeleteAt - Date.now());
|
||||
}
|
||||
|
||||
protected async deleteNextItem() {
|
||||
const [itemToDelete] = this.deletionQueue.splice(0, 1);
|
||||
if (!itemToDelete) return;
|
||||
|
||||
this.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
||||
this.bot.deleteMessage(itemToDelete.message.channel_id, itemToDelete.message.id).catch(logger.warn);
|
||||
|
||||
this.scheduleNextDeletion();
|
||||
|
||||
const user = await this.resolveUser(itemToDelete.message.user_id);
|
||||
const channel = this.guild.channels.get(itemToDelete.message.channel_id);
|
||||
const messageDate = moment(itemToDelete.message.data.timestamp, "x").format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
this.guildLogs.log(LogType.MESSAGE_DELETE_AUTO, {
|
||||
message: itemToDelete.message,
|
||||
user: stripObjectToScalars(user),
|
||||
channel: stripObjectToScalars(channel),
|
||||
messageDate,
|
||||
});
|
||||
}
|
||||
|
||||
protected onMessageCreate(msg: SavedMessage) {
|
||||
const config = this.getConfigForMemberIdAndChannelId(msg.user_id, msg.channel_id);
|
||||
if (config.enabled) {
|
||||
let delay = convertDelayStringToMS(config.delay);
|
||||
|
||||
if (delay > MAX_DELAY) {
|
||||
delay = MAX_DELAY;
|
||||
if (!this.maxDelayWarningSent) {
|
||||
this.guildLogs.log(LogType.BOT_ALERT, {
|
||||
body: `Clamped auto-deletion delay in <#${msg.channel_id}> to 5 minutes`,
|
||||
});
|
||||
this.maxDelayWarningSent = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.addMessageToDeletionQueue(msg, delay);
|
||||
}
|
||||
}
|
||||
|
||||
protected onMessageDelete(msg: SavedMessage) {
|
||||
const indexToDelete = this.deletionQueue.findIndex(item => item.message.id === msg.id);
|
||||
if (indexToDelete > -1) {
|
||||
this.deletionQueue.splice(indexToDelete, 1);
|
||||
this.scheduleNextDeletion();
|
||||
}
|
||||
}
|
||||
|
||||
protected onMessageDeleteBulk(messages: SavedMessage[]) {
|
||||
for (const msg of messages) {
|
||||
this.onMessageDelete(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import { GuildConfigReloader } from "./GuildConfigReloader";
|
|||
import { ChannelArchiverPlugin } from "./ChannelArchiver";
|
||||
import { AutomodPlugin } from "./Automod";
|
||||
import { RolesPlugin } from "./Roles";
|
||||
import { AutoDeletePlugin } from "./AutoDelete";
|
||||
|
||||
/**
|
||||
* Plugins available to be loaded for individual guilds
|
||||
|
@ -60,6 +61,7 @@ export const availablePlugins = [
|
|||
LocatePlugin,
|
||||
ChannelArchiverPlugin,
|
||||
RolesPlugin,
|
||||
AutoDeletePlugin,
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue