More Automod updates

This commit is contained in:
Dragory 2020-07-28 21:51:58 +03:00
parent e359fc46b2
commit 07da88b7cb
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
13 changed files with 88 additions and 28 deletions

View file

@ -16,6 +16,9 @@ import { clearOldRecentSpam } from "./functions/clearOldRecentSpam";
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels"; import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
import { GuildArchives } from "../../data/GuildArchives"; import { GuildArchives } from "../../data/GuildArchives";
import { clearOldRecentNicknameChanges } from "./functions/clearOldNicknameChanges"; import { clearOldRecentNicknameChanges } from "./functions/clearOldNicknameChanges";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { ModActionsPlugin } from "../ModActions/ModActionsPlugin";
import { MutesPlugin } from "../Mutes/MutesPlugin";
const defaultOptions = { const defaultOptions = {
config: { config: {
@ -106,16 +109,22 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = options => {
}; };
export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", { export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", {
dependencies: [LogsPlugin, ModActionsPlugin, MutesPlugin],
configSchema: ConfigSchema, configSchema: ConfigSchema,
defaultOptions, defaultOptions,
configPreprocessor, configPreprocessor,
customOverrideMatcher(pluginData, criteria, matchParams) {
return criteria?.antiraid_level && criteria.antiraid_level === pluginData.state.cachedAntiraidLevel;
},
events: [ events: [
RunAutomodOnJoinEvt, RunAutomodOnJoinEvt,
// Messages use message events from SavedMessages, see onLoad below // Messages use message events from SavedMessages, see onLoad below
], ],
onLoad(pluginData) { async onLoad(pluginData) {
pluginData.state.queue = new Queue(); pluginData.state.queue = new Queue();
pluginData.state.recentActions = []; pluginData.state.recentActions = [];
@ -130,8 +139,6 @@ export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", {
30 * SECONDS, 30 * SECONDS,
); );
pluginData.state.cachedAntiraidLevel = null; // TODO
pluginData.state.logs = new GuildLogs(pluginData.guild.id); pluginData.state.logs = new GuildLogs(pluginData.guild.id);
pluginData.state.savedMessages = GuildSavedMessages.getGuildInstance(pluginData.guild.id); pluginData.state.savedMessages = GuildSavedMessages.getGuildInstance(pluginData.guild.id);
pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id); pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id);
@ -142,6 +149,8 @@ export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", {
pluginData.state.onMessageUpdateFn = message => runAutomodOnMessage(pluginData, message, true); pluginData.state.onMessageUpdateFn = message => runAutomodOnMessage(pluginData, message, true);
pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn); pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn);
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
}, },
onUnload(pluginData) { onUnload(pluginData) {

View file

@ -6,6 +6,7 @@ import { resolveActionContactMethods } from "../functions/resolveActionContactMe
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin"; import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin";
import { TextChannel } from "eris"; import { TextChannel } from "eris";
import { renderTemplate } from "../../../templateFormatter"; import { renderTemplate } from "../../../templateFormatter";
import { LogsPlugin } from "../../Logs/LogsPlugin";
export const AlertAction = automodAction({ export const AlertAction = automodAction({
configType: t.type({ configType: t.type({
@ -15,6 +16,7 @@ export const AlertAction = automodAction({
async apply({ pluginData, contexts, actionConfig, ruleName, matchResult }) { async apply({ pluginData, contexts, actionConfig, ruleName, matchResult }) {
const channel = pluginData.guild.channels.get(actionConfig.channel); const channel = pluginData.guild.channels.get(actionConfig.channel);
const logs = pluginData.getPlugin(LogsPlugin);
if (channel && channel instanceof TextChannel) { if (channel && channel instanceof TextChannel) {
const text = actionConfig.text; const text = actionConfig.text;
@ -23,26 +25,31 @@ export const AlertAction = automodAction({
const safeUsers = contexts.map(c => c.user && stripObjectToScalars(c.user)).filter(Boolean); const safeUsers = contexts.map(c => c.user && stripObjectToScalars(c.user)).filter(Boolean);
const safeUser = safeUsers[0]; const safeUser = safeUsers[0];
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions);
const takenActions = Object.keys(pluginData.config.get().rules[ruleName].actions); const logMessage = logs.getLogMessage(LogType.AUTOMOD_ACTION, {
// TODO: Generate logMessage rule: ruleName,
const logMessage = ""; user: safeUser,
users: safeUsers,
actionsTaken,
matchSummary: matchResult.summary,
});
const rendered = await renderTemplate(actionConfig.text, { const rendered = await renderTemplate(actionConfig.text, {
rule: ruleName, rule: ruleName,
user: safeUser, user: safeUser,
users: safeUsers, users: safeUsers,
text, text,
actionsTaken,
matchSummary: matchResult.summary, matchSummary: matchResult.summary,
messageLink: theMessageLink, messageLink: theMessageLink,
logMessage, logMessage,
}); });
channel.createMessage(rendered); channel.createMessage(rendered);
} else { } else {
// TODO: Post BOT_ALERT log logs.log(LogType.BOT_ALERT, {
/*this.getLogs().log(LogType.BOT_ALERT, { body: `Invalid channel id \`${actionConfig.channel}\` for alert action in automod rule **${ruleName}**`,
body: `Invalid channel id \`${actionConfig.channel}\` for alert action in automod rule **${rule.name}**`, });
});*/
} }
}, },
}); });

View file

@ -13,7 +13,7 @@ export const BanAction = automodAction({
deleteMessageDays: tNullable(t.number), deleteMessageDays: tNullable(t.number),
}), }),
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, actionConfig, matchResult }) {
const reason = actionConfig.reason || "Kicked automatically"; const reason = actionConfig.reason || "Kicked automatically";
const contactMethods = resolveActionContactMethods(pluginData, actionConfig); const contactMethods = resolveActionContactMethods(pluginData, actionConfig);
const deleteMessageDays = actionConfig.deleteMessageDays; const deleteMessageDays = actionConfig.deleteMessageDays;
@ -21,7 +21,7 @@ export const BanAction = automodAction({
const caseArgs = { const caseArgs = {
modId: pluginData.client.user.id, modId: pluginData.client.user.id,
extraNotes: [ extraNotes: [
/* TODO */ matchResult.summary, // TODO
], ],
}; };

View file

@ -1,9 +1,7 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { asyncMap, resolveMember, tNullable } from "../../../utils"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { resolveActionContactMethods } from "../functions/resolveActionContactMethods";
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin";
export const ChangeNicknameAction = automodAction({ export const ChangeNicknameAction = automodAction({
configType: t.type({ configType: t.type({
@ -18,7 +16,9 @@ export const ChangeNicknameAction = automodAction({
if (pluginData.state.recentNicknameChanges.has(member.id)) continue; if (pluginData.state.recentNicknameChanges.has(member.id)) continue;
member.edit({ nick: actionConfig.name }).catch(err => { member.edit({ nick: actionConfig.name }).catch(err => {
/* TODO: Log this error */ pluginData.getPlugin(LogsPlugin).log(LogType.BOT_ALERT, {
body: `Failed to change the nickname of \`${member.id}\``,
});
}); });
pluginData.state.recentNicknameChanges.set(member.id, { timestamp: Date.now() }); pluginData.state.recentNicknameChanges.set(member.id, { timestamp: Date.now() });

View file

@ -12,14 +12,14 @@ export const KickAction = automodAction({
notifyChannel: tNullable(t.string), notifyChannel: tNullable(t.string),
}), }),
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, actionConfig, matchResult }) {
const reason = actionConfig.reason || "Kicked automatically"; const reason = actionConfig.reason || "Kicked automatically";
const contactMethods = resolveActionContactMethods(pluginData, actionConfig); const contactMethods = resolveActionContactMethods(pluginData, actionConfig);
const caseArgs = { const caseArgs = {
modId: pluginData.client.user.id, modId: pluginData.client.user.id,
extraNotes: [ extraNotes: [
/* TODO */ matchResult.summary, // TODO
], ],
}; };

View file

@ -1,10 +1,23 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { LogsPlugin } from "../../Logs/LogsPlugin";
import { LogType } from "../../../data/LogType";
import { stripObjectToScalars } from "../../../utils";
export const LogAction = automodAction({ export const LogAction = automodAction({
configType: t.boolean, configType: t.boolean,
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, ruleName, matchResult }) {
// TODO: Everything const safeUsers = contexts.map(c => c.user && stripObjectToScalars(c.user)).filter(Boolean);
const safeUser = safeUsers[0];
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions);
pluginData.getPlugin(LogsPlugin).log(LogType.AUTOMOD_ACTION, {
rule: ruleName,
user: safeUser,
users: safeUsers,
actionsTaken,
matchSummary: matchResult.summary,
});
}, },
}); });

View file

@ -14,7 +14,7 @@ export const MuteAction = automodAction({
notifyChannel: tNullable(t.string), notifyChannel: tNullable(t.string),
}), }),
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, actionConfig, matchResult }) {
const duration = actionConfig.duration ? convertDelayStringToMS(actionConfig.duration) : null; const duration = actionConfig.duration ? convertDelayStringToMS(actionConfig.duration) : null;
const reason = actionConfig.reason || "Muted automatically"; const reason = actionConfig.reason || "Muted automatically";
const contactMethods = resolveActionContactMethods(pluginData, actionConfig); const contactMethods = resolveActionContactMethods(pluginData, actionConfig);
@ -22,7 +22,7 @@ export const MuteAction = automodAction({
const caseArgs = { const caseArgs = {
modId: pluginData.client.user.id, modId: pluginData.client.user.id,
extraNotes: [ extraNotes: [
/* TODO */ matchResult.summary, // TODO
], ],
}; };

View file

@ -12,14 +12,14 @@ export const WarnAction = automodAction({
notifyChannel: tNullable(t.string), notifyChannel: tNullable(t.string),
}), }),
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, actionConfig, matchResult }) {
const reason = actionConfig.reason || "Warned automatically"; const reason = actionConfig.reason || "Warned automatically";
const contactMethods = resolveActionContactMethods(pluginData, actionConfig); const contactMethods = resolveActionContactMethods(pluginData, actionConfig);
const caseArgs = { const caseArgs = {
modId: pluginData.client.user.id, modId: pluginData.client.user.id,
extraNotes: [ extraNotes: [
/* TODO */ matchResult.summary, // TODO
], ],
}; };

View file

@ -1,6 +1,9 @@
import { User } from "eris"; import { User } from "eris";
import { PluginData } from "knub"; import { PluginData } from "knub";
import { AutomodPluginType } from "../types"; import { AutomodPluginType } from "../types";
import { LogsPlugin } from "../../Logs/LogsPlugin";
import { LogType } from "../../../data/LogType";
import { stripObjectToScalars } from "../../../utils";
export async function setAntiraidLevel( export async function setAntiraidLevel(
pluginData: PluginData<AutomodPluginType>, pluginData: PluginData<AutomodPluginType>,
@ -10,9 +13,16 @@ export async function setAntiraidLevel(
pluginData.state.cachedAntiraidLevel = newLevel; pluginData.state.cachedAntiraidLevel = newLevel;
await pluginData.state.antiraidLevels.set(newLevel); await pluginData.state.antiraidLevels.set(newLevel);
const logs = pluginData.getPlugin(LogsPlugin);
if (user) { if (user) {
// TODO: Log user action logs.log(LogType.SET_ANTIRAID_USER, {
level: newLevel ?? "off",
user: stripObjectToScalars(user),
});
} else { } else {
// TODO: Log automatic action logs.log(LogType.SET_ANTIRAID_AUTO, {
level: newLevel ?? "off",
});
} }
} }

View file

@ -34,6 +34,11 @@ export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export interface AutomodPluginType extends BasePluginType { export interface AutomodPluginType extends BasePluginType {
config: TConfigSchema; config: TConfigSchema;
customOverrideCriteria: {
antiraid_level?: string;
};
state: { state: {
/** /**
* Automod checks/actions are handled in a queue so we don't get overlap on the same user * Automod checks/actions are handled in a queue so we don't get overlap on the same user

View file

@ -17,6 +17,8 @@ import { LogsChannelCreateEvt, LogsChannelDeleteEvt } from "./events/LogsChannel
import { LogsRoleCreateEvt, LogsRoleDeleteEvt } from "./events/LogsRoleModifyEvts"; import { LogsRoleCreateEvt, LogsRoleDeleteEvt } from "./events/LogsRoleModifyEvts";
import { LogsVoiceJoinEvt, LogsVoiceLeaveEvt, LogsVoiceSwitchEvt } from "./events/LogsVoiceChannelEvts"; import { LogsVoiceJoinEvt, LogsVoiceLeaveEvt, LogsVoiceSwitchEvt } from "./events/LogsVoiceChannelEvts";
import { log } from "./util/log"; import { log } from "./util/log";
import { LogType } from "../../data/LogType";
import { getLogMessage } from "./util/getLogMessage";
const defaultOptions: PluginOptions<LogsPluginType> = { const defaultOptions: PluginOptions<LogsPluginType> = {
config: { config: {
@ -58,6 +60,20 @@ export const LogsPlugin = zeppelinPlugin<LogsPluginType>()("logs", {
LogsVoiceSwitchEvt, LogsVoiceSwitchEvt,
], ],
public: {
log(pluginData) {
return (type: LogType, data: any) => {
return log(pluginData, type, data);
};
},
getLogMessage(pluginData) {
return (type: LogType, data: any) => {
return getLogMessage(pluginData, type, data);
};
},
},
onLoad(pluginData) { onLoad(pluginData) {
const { state, guild } = pluginData; const { state, guild } = pluginData;

View file

@ -7,7 +7,7 @@ import { renderTemplate, TemplateParseError } from "src/templateFormatter";
import { logger } from "src/logger"; import { logger } from "src/logger";
import moment from "moment-timezone"; import moment from "moment-timezone";
export async function getLogMessage(pluginData: PluginData<LogsPluginType>, type, data): Promise<string> { export async function getLogMessage(pluginData: PluginData<LogsPluginType>, type: LogType, data: any): Promise<string> {
const config = pluginData.config.get(); const config = pluginData.config.get();
const format = config.format[LogType[type]] || ""; const format = config.format[LogType[type]] || "";
if (format === "") return; if (format === "") return;

View file

@ -5,7 +5,7 @@ import { TextChannel } from "eris";
import { createChunkedMessage, noop } from "src/utils"; import { createChunkedMessage, noop } from "src/utils";
import { getLogMessage } from "./getLogMessage"; import { getLogMessage } from "./getLogMessage";
export async function log(pluginData: PluginData<LogsPluginType>, type, data) { export async function log(pluginData: PluginData<LogsPluginType>, type: LogType, data: any) {
const logChannels: TLogChannelMap = pluginData.config.get().channels; const logChannels: TLogChannelMap = pluginData.config.get().channels;
const typeStr = LogType[type]; const typeStr = LogType[type];