3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-19 07:20:00 +00:00
zeppelin/backend/src/plugins/Automod/AutomodPlugin.ts

222 lines
8.2 KiB
TypeScript
Raw Normal View History

import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
2020-07-27 20:42:10 +03:00
import { AutomodPluginType, ConfigSchema } from "./types";
import { RunAutomodOnJoinEvt } from "./events/RunAutomodOnJoinEvt";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { runAutomodOnMessage } from "./events/runAutomodOnMessage";
import { Queue } from "../../Queue";
2020-07-30 01:54:18 +03:00
import { configUtils, CooldownManager } from "knub";
2020-07-27 20:42:10 +03:00
import { availableTriggers } from "./triggers/availableTriggers";
import { StrictValidationError } from "../../validatorUtils";
import { ConfigPreprocessorFn } from "knub/dist/config/configTypes";
import { availableActions } from "./actions/availableActions";
import { clearOldRecentActions } from "./functions/clearOldRecentActions";
import { disableCodeBlocks, MINUTES, SECONDS } from "../../utils";
2020-07-27 20:42:10 +03:00
import { clearOldRecentSpam } from "./functions/clearOldRecentSpam";
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
import { GuildArchives } from "../../data/GuildArchives";
import { clearOldRecentNicknameChanges } from "./functions/clearOldNicknameChanges";
2020-07-28 21:51:58 +03:00
import { LogsPlugin } from "../Logs/LogsPlugin";
import { ModActionsPlugin } from "../ModActions/ModActionsPlugin";
import { MutesPlugin } from "../Mutes/MutesPlugin";
2020-07-30 00:58:34 +03:00
import { AntiraidClearCmd } from "./commands/AntiraidClearCmd";
import { SetAntiraidCmd } from "./commands/SetAntiraidCmd";
import { ViewAntiraidCmd } from "./commands/ViewAntiraidCmd";
2020-07-30 13:08:06 +03:00
import { pluginInfo } from "./info";
import { RegExpRunner } from "../../RegExpRunner";
import { LogType } from "../../data/LogType";
import { logger } from "../../logger";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { RunAutomodOnMemberUpdate } from "./events/RunAutomodOnMemberUpdate";
2020-07-27 20:42:10 +03:00
const defaultOptions = {
config: {
rules: {},
antiraid_levels: ["low", "medium", "high"],
can_set_antiraid: false,
can_view_antiraid: false,
},
overrides: [
{
level: ">=50",
config: {
can_view_antiraid: true,
},
},
{
level: ">=100",
config: {
can_set_antiraid: true,
},
},
],
};
/**
* Config preprocessor to set default values for triggers
*/
const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = options => {
if (options.config?.rules) {
// Loop through each rule
for (const [name, rule] of Object.entries(options.config.rules)) {
if (rule == null) {
delete options.config.rules[name];
continue;
}
2020-07-27 20:42:10 +03:00
rule["name"] = name;
// If the rule doesn't have an explicitly set "enabled" property, set it to true
if (rule["enabled"] == null) {
rule["enabled"] = true;
}
if (rule["affects_bots"] == null) {
rule["affects_bots"] = false;
}
// Loop through the rule's triggers
if (rule["triggers"]) {
for (const triggerObj of rule["triggers"]) {
for (const triggerName in triggerObj) {
if (!availableTriggers[triggerName]) {
throw new StrictValidationError([`Unknown trigger '${triggerName}' in rule '${rule.name}'`]);
}
const triggerBlueprint = availableTriggers[triggerName];
if (typeof triggerBlueprint.defaultConfig === "object" && triggerBlueprint.defaultConfig != null) {
triggerObj[triggerName] = configUtils.mergeConfig(
triggerBlueprint.defaultConfig,
triggerObj[triggerName] || {},
);
} else {
triggerObj[triggerName] = triggerObj[triggerName] || triggerBlueprint.defaultConfig;
}
2020-07-27 20:42:10 +03:00
if (triggerObj[triggerName].match_attachment_type) {
const white = triggerObj[triggerName].match_attachment_type.whitelist_enabled;
const black = triggerObj[triggerName].match_attachment_type.blacklist_enabled;
if (white && black) {
throw new StrictValidationError([
`Cannot have both blacklist and whitelist enabled at rule <${rule.name}/match_attachment_type>`,
]);
} else if (!white && !black) {
throw new StrictValidationError([
`Must have either blacklist or whitelist enabled at rule <${rule.name}/match_attachment_type>`,
]);
}
}
}
}
}
if (rule["actions"]) {
for (const actionName in rule["actions"]) {
if (!availableActions[actionName]) {
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule.name}'`]);
}
const actionBlueprint = availableActions[actionName];
const actionConfig = rule["actions"][actionName];
if (typeof actionConfig !== "object" || Array.isArray(actionConfig) || actionConfig == null) {
rule["actions"][actionName] = actionConfig;
} else {
rule["actions"][actionName] = configUtils.mergeConfig(actionBlueprint.defaultConfig, actionConfig);
}
}
}
2020-07-27 20:42:10 +03:00
// Enable logging of automod actions by default
if (rule["actions"]) {
for (const actionName in rule.actions) {
if (!availableActions[actionName]) {
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule.name}'`]);
}
}
if (rule["actions"]["log"] == null) {
rule["actions"]["log"] = true;
}
2020-07-27 20:42:10 +03:00
}
}
}
return options;
};
export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()("automod", {
2020-07-30 13:08:06 +03:00
showInDocs: true,
info: pluginInfo,
2020-07-28 21:51:58 +03:00
dependencies: [LogsPlugin, ModActionsPlugin, MutesPlugin],
2020-07-27 20:42:10 +03:00
configSchema: ConfigSchema,
defaultOptions,
configPreprocessor,
2020-07-28 21:51:58 +03:00
customOverrideMatcher(pluginData, criteria, matchParams) {
return criteria?.antiraid_level ? criteria.antiraid_level === pluginData.state.cachedAntiraidLevel : false;
2020-07-28 21:51:58 +03:00
},
2020-07-27 20:42:10 +03:00
events: [
RunAutomodOnJoinEvt,
RunAutomodOnMemberUpdate,
2020-07-27 20:42:10 +03:00
// Messages use message events from SavedMessages, see onLoad below
],
2020-07-30 00:58:34 +03:00
commands: [AntiraidClearCmd, SetAntiraidCmd, ViewAntiraidCmd],
2020-07-28 21:51:58 +03:00
async onLoad(pluginData) {
2020-07-27 20:42:10 +03:00
pluginData.state.queue = new Queue();
pluginData.state.regexRunner = getRegExpRunner(`guild-${pluginData.guild.id}`);
2020-07-27 20:42:10 +03:00
pluginData.state.recentActions = [];
pluginData.state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES);
pluginData.state.recentSpam = [];
pluginData.state.clearRecentSpamInterval = setInterval(() => clearOldRecentSpam(pluginData), 1 * SECONDS);
pluginData.state.recentNicknameChanges = new Map();
pluginData.state.clearRecentNicknameChangesInterval = setInterval(
() => clearOldRecentNicknameChanges(pluginData),
30 * SECONDS,
);
pluginData.state.ignoredRoleChanges = new Set();
2020-07-30 01:54:18 +03:00
pluginData.state.cooldownManager = new CooldownManager();
2020-07-27 20:42:10 +03:00
pluginData.state.logs = new GuildLogs(pluginData.guild.id);
pluginData.state.savedMessages = GuildSavedMessages.getGuildInstance(pluginData.guild.id);
pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id);
pluginData.state.archives = GuildArchives.getGuildInstance(pluginData.guild.id);
pluginData.state.onMessageCreateFn = message => runAutomodOnMessage(pluginData, message, false);
pluginData.state.savedMessages.events.on("create", pluginData.state.onMessageCreateFn);
pluginData.state.onMessageUpdateFn = message => runAutomodOnMessage(pluginData, message, true);
pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn);
2020-07-28 21:51:58 +03:00
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
2020-07-27 20:42:10 +03:00
},
async onUnload(pluginData) {
2020-07-27 20:42:10 +03:00
pluginData.state.queue.clear();
discardRegExpRunner(`guild-${pluginData.guild.id}`);
2020-07-27 20:42:10 +03:00
clearInterval(pluginData.state.clearRecentActionsInterval);
clearInterval(pluginData.state.clearRecentSpamInterval);
clearInterval(pluginData.state.clearRecentNicknameChangesInterval);
2020-07-27 20:42:10 +03:00
pluginData.state.savedMessages.events.off("create", pluginData.state.onMessageCreateFn);
pluginData.state.savedMessages.events.off("update", pluginData.state.onMessageUpdateFn);
},
});