Merge pull request #87 from DarkView/k30_autoDelete
[K30] Migrated AutoDelete
This commit is contained in:
commit
8c7cd245f6
9 changed files with 194 additions and 0 deletions
48
backend/src/plugins/AutoDelete/AutoDeletePlugin.ts
Normal file
48
backend/src/plugins/AutoDelete/AutoDeletePlugin.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { PluginOptions } from "knub";
|
||||||
|
import { AutoDeletePluginType, ConfigSchema } from "./types";
|
||||||
|
import { zeppelinPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
|
import { GuildSavedMessages } from "src/data/GuildSavedMessages";
|
||||||
|
import { GuildLogs } from "src/data/GuildLogs";
|
||||||
|
import { onMessageCreate } from "./util/onMessageCreate";
|
||||||
|
import { onMessageDelete } from "./util/onMessageDelete";
|
||||||
|
import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk";
|
||||||
|
|
||||||
|
const defaultOptions: PluginOptions<AutoDeletePluginType> = {
|
||||||
|
config: {
|
||||||
|
enabled: false,
|
||||||
|
delay: "5s",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AutoDeletePlugin = zeppelinPlugin<AutoDeletePluginType>()("auto_delete", {
|
||||||
|
configSchema: ConfigSchema,
|
||||||
|
defaultOptions,
|
||||||
|
|
||||||
|
onLoad(pluginData) {
|
||||||
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
|
state.guildSavedMessages = GuildSavedMessages.getGuildInstance(guild.id);
|
||||||
|
state.guildLogs = new GuildLogs(guild.id);
|
||||||
|
|
||||||
|
state.deletionQueue = [];
|
||||||
|
state.nextDeletion = null;
|
||||||
|
state.nextDeletionTimeout = null;
|
||||||
|
|
||||||
|
state.maxDelayWarningSent = false;
|
||||||
|
|
||||||
|
state.onMessageCreateFn = msg => onMessageCreate(pluginData, msg);
|
||||||
|
state.guildSavedMessages.events.on("create", state.onMessageCreateFn);
|
||||||
|
|
||||||
|
state.onMessageDeleteFn = msg => onMessageDelete(pluginData, msg);
|
||||||
|
state.guildSavedMessages.events.on("delete", state.onMessageDeleteFn);
|
||||||
|
|
||||||
|
state.onMessageDeleteBulkFn = msgs => onMessageDeleteBulk(pluginData, msgs);
|
||||||
|
state.guildSavedMessages.events.on("deleteBulk", state.onMessageDeleteBulkFn);
|
||||||
|
},
|
||||||
|
|
||||||
|
onUnload(pluginData) {
|
||||||
|
pluginData.state.guildSavedMessages.events.off("create", pluginData.state.onMessageCreateFn);
|
||||||
|
pluginData.state.guildSavedMessages.events.off("delete", pluginData.state.onMessageDeleteFn);
|
||||||
|
pluginData.state.guildSavedMessages.events.off("deleteBulk", pluginData.state.onMessageDeleteBulkFn);
|
||||||
|
},
|
||||||
|
});
|
37
backend/src/plugins/AutoDelete/types.ts
Normal file
37
backend/src/plugins/AutoDelete/types.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import * as t from "io-ts";
|
||||||
|
import { BasePluginType } from "knub";
|
||||||
|
import { tDelayString, MINUTES } from "src/utils";
|
||||||
|
import { GuildLogs } from "src/data/GuildLogs";
|
||||||
|
import { GuildSavedMessages } from "src/data/GuildSavedMessages";
|
||||||
|
import { SavedMessage } from "src/data/entities/SavedMessage";
|
||||||
|
|
||||||
|
export const MAX_DELAY = 5 * MINUTES;
|
||||||
|
|
||||||
|
export interface IDeletionQueueItem {
|
||||||
|
deleteAt: number;
|
||||||
|
message: SavedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConfigSchema = t.type({
|
||||||
|
enabled: t.boolean,
|
||||||
|
delay: tDelayString,
|
||||||
|
});
|
||||||
|
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||||
|
|
||||||
|
export interface AutoDeletePluginType extends BasePluginType {
|
||||||
|
config: TConfigSchema;
|
||||||
|
state: {
|
||||||
|
guildSavedMessages: GuildSavedMessages;
|
||||||
|
guildLogs: GuildLogs;
|
||||||
|
|
||||||
|
deletionQueue: IDeletionQueueItem[];
|
||||||
|
nextDeletion: number;
|
||||||
|
nextDeletionTimeout;
|
||||||
|
|
||||||
|
maxDelayWarningSent: boolean;
|
||||||
|
|
||||||
|
onMessageCreateFn;
|
||||||
|
onMessageDeleteFn;
|
||||||
|
onMessageDeleteBulkFn;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { AutoDeletePluginType } from "../types";
|
||||||
|
import { SavedMessage } from "src/data/entities/SavedMessage";
|
||||||
|
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
||||||
|
import { sorter } from "src/utils";
|
||||||
|
|
||||||
|
export function addMessageToDeletionQueue(
|
||||||
|
pluginData: PluginData<AutoDeletePluginType>,
|
||||||
|
msg: SavedMessage,
|
||||||
|
delay: number,
|
||||||
|
) {
|
||||||
|
const deleteAt = Date.now() + delay;
|
||||||
|
pluginData.state.deletionQueue.push({ deleteAt, message: msg });
|
||||||
|
pluginData.state.deletionQueue.sort(sorter("deleteAt"));
|
||||||
|
|
||||||
|
scheduleNextDeletion(pluginData);
|
||||||
|
}
|
28
backend/src/plugins/AutoDelete/util/deleteNextItem.ts
Normal file
28
backend/src/plugins/AutoDelete/util/deleteNextItem.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { AutoDeletePluginType } from "../types";
|
||||||
|
import moment from "moment-timezone";
|
||||||
|
import { LogType } from "src/data/LogType";
|
||||||
|
import { stripObjectToScalars, resolveUser } from "src/utils";
|
||||||
|
import { logger } from "src/logger";
|
||||||
|
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
||||||
|
|
||||||
|
export async function deleteNextItem(pluginData: PluginData<AutoDeletePluginType>) {
|
||||||
|
const [itemToDelete] = pluginData.state.deletionQueue.splice(0, 1);
|
||||||
|
if (!itemToDelete) return;
|
||||||
|
|
||||||
|
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
||||||
|
pluginData.client.deleteMessage(itemToDelete.message.channel_id, itemToDelete.message.id).catch(logger.warn);
|
||||||
|
|
||||||
|
scheduleNextDeletion(pluginData);
|
||||||
|
|
||||||
|
const user = await resolveUser(pluginData.client, itemToDelete.message.user_id);
|
||||||
|
const channel = pluginData.guild.channels.get(itemToDelete.message.channel_id);
|
||||||
|
const messageDate = moment(itemToDelete.message.data.timestamp, "x").format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
|
||||||
|
pluginData.state.guildLogs.log(LogType.MESSAGE_DELETE_AUTO, {
|
||||||
|
message: itemToDelete.message,
|
||||||
|
user: stripObjectToScalars(user),
|
||||||
|
channel: stripObjectToScalars(channel),
|
||||||
|
messageDate,
|
||||||
|
});
|
||||||
|
}
|
26
backend/src/plugins/AutoDelete/util/onMessageCreate.ts
Normal file
26
backend/src/plugins/AutoDelete/util/onMessageCreate.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { AutoDeletePluginType, MAX_DELAY } from "../types";
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { SavedMessage } from "src/data/entities/SavedMessage";
|
||||||
|
import { convertDelayStringToMS, resolveMember } from "src/utils";
|
||||||
|
import { LogType } from "src/data/LogType";
|
||||||
|
import { addMessageToDeletionQueue } from "./addMessageToDeletionQueue";
|
||||||
|
|
||||||
|
export async function onMessageCreate(pluginData: PluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
||||||
|
const member = await resolveMember(pluginData.client, pluginData.guild, msg.user_id);
|
||||||
|
const config = pluginData.config.getMatchingConfig({ member, channelId: msg.channel_id });
|
||||||
|
if (config.enabled) {
|
||||||
|
let delay = convertDelayStringToMS(config.delay);
|
||||||
|
|
||||||
|
if (delay > MAX_DELAY) {
|
||||||
|
delay = MAX_DELAY;
|
||||||
|
if (!pluginData.state.maxDelayWarningSent) {
|
||||||
|
pluginData.state.guildLogs.log(LogType.BOT_ALERT, {
|
||||||
|
body: `Clamped auto-deletion delay in <#${msg.channel_id}> to 5 minutes`,
|
||||||
|
});
|
||||||
|
pluginData.state.maxDelayWarningSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageToDeletionQueue(pluginData, msg, delay);
|
||||||
|
}
|
||||||
|
}
|
12
backend/src/plugins/AutoDelete/util/onMessageDelete.ts
Normal file
12
backend/src/plugins/AutoDelete/util/onMessageDelete.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { AutoDeletePluginType } from "../types";
|
||||||
|
import { SavedMessage } from "src/data/entities/SavedMessage";
|
||||||
|
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
||||||
|
|
||||||
|
export function onMessageDelete(pluginData: PluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
||||||
|
const indexToDelete = pluginData.state.deletionQueue.findIndex(item => item.message.id === msg.id);
|
||||||
|
if (indexToDelete > -1) {
|
||||||
|
pluginData.state.deletionQueue.splice(indexToDelete, 1);
|
||||||
|
scheduleNextDeletion(pluginData);
|
||||||
|
}
|
||||||
|
}
|
10
backend/src/plugins/AutoDelete/util/onMessageDeleteBulk.ts
Normal file
10
backend/src/plugins/AutoDelete/util/onMessageDeleteBulk.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { AutoDeletePluginType } from "../types";
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { SavedMessage } from "src/data/entities/SavedMessage";
|
||||||
|
import { onMessageDelete } from "./onMessageDelete";
|
||||||
|
|
||||||
|
export function onMessageDeleteBulk(pluginData: PluginData<AutoDeletePluginType>, messages: SavedMessage[]) {
|
||||||
|
for (const msg of messages) {
|
||||||
|
onMessageDelete(pluginData, msg);
|
||||||
|
}
|
||||||
|
}
|
14
backend/src/plugins/AutoDelete/util/scheduleNextDeletion.ts
Normal file
14
backend/src/plugins/AutoDelete/util/scheduleNextDeletion.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { PluginData } from "knub";
|
||||||
|
import { AutoDeletePluginType } from "../types";
|
||||||
|
import { deleteNextItem } from "./deleteNextItem";
|
||||||
|
|
||||||
|
export function scheduleNextDeletion(pluginData: PluginData<AutoDeletePluginType>) {
|
||||||
|
if (pluginData.state.deletionQueue.length === 0) {
|
||||||
|
clearTimeout(pluginData.state.nextDeletionTimeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstDeleteAt = pluginData.state.deletionQueue[0].deleteAt;
|
||||||
|
clearTimeout(pluginData.state.nextDeletionTimeout);
|
||||||
|
pluginData.state.nextDeletionTimeout = setTimeout(() => deleteNextItem(pluginData), firstDeleteAt - Date.now());
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import { GuildConfigReloaderPlugin } from "./GuildConfigReloader/GuildConfigRelo
|
||||||
import { CasesPlugin } from "./Cases/CasesPlugin";
|
import { CasesPlugin } from "./Cases/CasesPlugin";
|
||||||
import { MutesPlugin } from "./Mutes/MutesPlugin";
|
import { MutesPlugin } from "./Mutes/MutesPlugin";
|
||||||
import { TagsPlugin } from "./Tags/TagsPlugin";
|
import { TagsPlugin } from "./Tags/TagsPlugin";
|
||||||
|
import { AutoDeletePlugin } from "./AutoDelete/AutoDeletePlugin";
|
||||||
import { GuildInfoSaverPlugin } from "./GuildInfoSaver/GuildInfoSaverPlugin";
|
import { GuildInfoSaverPlugin } from "./GuildInfoSaver/GuildInfoSaverPlugin";
|
||||||
import { CensorPlugin } from "./Censor/CensorPlugin";
|
import { CensorPlugin } from "./Censor/CensorPlugin";
|
||||||
import { RolesPlugin } from "./Roles/RolesPlugin";
|
import { RolesPlugin } from "./Roles/RolesPlugin";
|
||||||
|
@ -22,6 +23,7 @@ import { ChannelArchiverPlugin } from "./ChannelArchiver/ChannelArchiverPlugin";
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
||||||
|
AutoDeletePlugin,
|
||||||
AutoReactionsPlugin,
|
AutoReactionsPlugin,
|
||||||
GuildInfoSaverPlugin,
|
GuildInfoSaverPlugin,
|
||||||
CensorPlugin,
|
CensorPlugin,
|
||||||
|
|
Loading…
Add table
Reference in a new issue