3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-16 14:11:50 +00:00

automod: don't use log system for alert actions, require channel id directly instead; allow disabling logging from specific rules

This commit is contained in:
Dragory 2019-10-11 23:16:15 +03:00
parent 40af0f2359
commit 713333f35e
4 changed files with 50 additions and 22 deletions

View file

@ -58,6 +58,5 @@
"POSTED_SCHEDULED_MESSAGE": "\uD83D\uDCE8 Posted scheduled message (`{messageId}`) to {channelMention(channel)} as scheduled by {userMention(author)}", "POSTED_SCHEDULED_MESSAGE": "\uD83D\uDCE8 Posted scheduled message (`{messageId}`) to {channelMention(channel)} as scheduled by {userMention(author)}",
"BOT_ALERT": "⚠ {tmplEval(body)}", "BOT_ALERT": "⚠ {tmplEval(body)}",
"AUTOMOD_ALERT": "{text}",
"AUTOMOD_ACTION": "\uD83E\uDD16 Automod rule **{rule}** triggered by {userMention(user)}. Actions taken: **{actionsTaken}**\n{matchSummary}" "AUTOMOD_ACTION": "\uD83E\uDD16 Automod rule **{rule}** triggered by {userMention(user)}. Actions taken: **{actionsTaken}**\n{matchSummary}"
} }

View file

@ -58,6 +58,5 @@ export enum LogType {
POSTED_SCHEDULED_MESSAGE, POSTED_SCHEDULED_MESSAGE,
BOT_ALERT, BOT_ALERT,
AUTOMOD_ALERT,
AUTOMOD_ACTION, AUTOMOD_ACTION,
} }

View file

@ -13,11 +13,12 @@ import {
SECONDS, SECONDS,
stripObjectToScalars, stripObjectToScalars,
tNullable, tNullable,
UnknownUser,
verboseChannelMention, verboseChannelMention,
} from "../utils"; } from "../utils";
import { decorators as d } from "knub"; import { decorators as d } from "knub";
import { mergeConfig } from "knub/dist/configUtils"; import { mergeConfig } from "knub/dist/configUtils";
import { Invite, Member, Message } from "eris"; import { Invite, Member, Message, TextChannel } from "eris";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import { SimpleCache } from "../SimpleCache"; import { SimpleCache } from "../SimpleCache";
import { Queue } from "../Queue"; import { Queue } from "../Queue";
@ -32,6 +33,7 @@ import { GuildArchives } from "../data/GuildArchives";
import { GuildLogs } from "../data/GuildLogs"; import { GuildLogs } from "../data/GuildLogs";
import { SavedMessage } from "../data/entities/SavedMessage"; import { SavedMessage } from "../data/entities/SavedMessage";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { renderTemplate } from "../templateFormatter";
type MessageInfo = { channelId: string; messageId: string }; type MessageInfo = { channelId: string; messageId: string };
@ -81,7 +83,7 @@ interface RaidSpamTriggerMatchResult extends TriggerMatchResult {
interface OtherSpamTriggerMatchResult extends TriggerMatchResult { interface OtherSpamTriggerMatchResult extends TriggerMatchResult {
type: "otherspam"; type: "otherspam";
actionType: RecentActionType; actionType: RecentActionType;
userIds: string[]; userId: string;
} }
type AnyTriggerMatchResult = type AnyTriggerMatchResult =
@ -233,6 +235,7 @@ const BanAction = t.type({
}); });
const AlertAction = t.type({ const AlertAction = t.type({
channel: t.string,
text: t.string, text: t.string,
}); });
@ -240,6 +243,8 @@ const ChangeNicknameAction = t.type({
name: t.string, name: t.string,
}); });
const LogAction = t.boolean;
/** /**
* FULL CONFIG SCHEMA * FULL CONFIG SCHEMA
*/ */
@ -273,6 +278,7 @@ const Rule = t.type({
ban: tNullable(BanAction), ban: tNullable(BanAction),
alert: tNullable(AlertAction), alert: tNullable(AlertAction),
change_nickname: tNullable(ChangeNicknameAction), change_nickname: tNullable(ChangeNicknameAction),
log: tNullable(LogAction),
}), }),
}); });
type TRule = t.TypeOf<typeof Rule>; type TRule = t.TypeOf<typeof Rule>;
@ -487,6 +493,13 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema> {
} }
} }
} }
// Enable logging of automod actions by default
if (rule["actions"] && typeof rule["actions"] === "object") {
if (rule["actions"]["log"] == null) {
rule["actions"]["log"] = true;
}
}
} }
} }
@ -1153,10 +1166,7 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema> {
} }
if (rule.actions.change_nickname) { if (rule.actions.change_nickname) {
const userIdsToChange = const userIdsToChange = matchResult.type === "raidspam" ? matchResult.userIds : [matchResult.userId];
matchResult.type === "raidspam" || matchResult.type === "otherspam"
? matchResult.userIds
: [matchResult.userId];
for (const userId of userIdsToChange) { for (const userId of userIdsToChange) {
if (this.recentNicknameChanges.has(userId)) continue; if (this.recentNicknameChanges.has(userId)) continue;
@ -1175,30 +1185,45 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema> {
actionsTaken.push("nickname"); actionsTaken.push("nickname");
} }
if (rule.actions.alert || matchResult.type !== "raidspam") { // Don't wait for the rest before continuing to other automod items in the queue
const user = await this.resolveUser((matchResult as any).userId || "0"); (async () => {
const user = matchResult.type !== "raidspam" ? this.getUser(matchResult.userId) : new UnknownUser();
const users = matchResult.type === "raidspam" ? matchResult.userIds.map(id => this.getUser(id)) : [];
const safeUser = stripObjectToScalars(user);
const safeUsers = users.map(u => stripObjectToScalars(u));
if (rule.actions.alert) { if (rule.actions.alert) {
const text = rule.actions.alert.text; const channel = this.guild.channels.get(rule.actions.alert.channel);
this.getLogs().log(LogType.AUTOMOD_ALERT, { if (channel && channel instanceof TextChannel) {
rule: rule.name, const text = rule.actions.alert.text;
user: stripObjectToScalars(user), const rendered = await renderTemplate(rule.actions.alert.text, {
text, rule: rule.name,
matchSummary, user: safeUser,
}); users: safeUsers,
text,
actionsTaken.push("alert"); matchSummary,
});
channel.createMessage(rendered);
actionsTaken.push("alert");
} else {
this.getLogs().log(LogType.BOT_ALERT, {
body: `Invalid channel id \`${rule.actions.alert.channel}\` for alert action in automod rule **${
rule.name
}**`,
});
}
} }
if (matchResult.type !== "raidspam") { if (rule.actions.log) {
this.getLogs().log(LogType.AUTOMOD_ACTION, { this.getLogs().log(LogType.AUTOMOD_ACTION, {
rule: rule.name, rule: rule.name,
user: stripObjectToScalars(user), user: safeUser,
users: safeUsers,
actionsTaken: actionsTaken.length ? actionsTaken.join(", ") : "<none>", actionsTaken: actionsTaken.length ? actionsTaken.join(", ") : "<none>",
matchSummary, matchSummary,
}); });
} }
} })();
} }
protected onMessageCreate(msg: SavedMessage) { protected onMessageCreate(msg: SavedMessage) {

View file

@ -204,6 +204,11 @@ export class ZeppelinPlugin<TConfig extends {} = IBasePluginConfig> extends Plug
return this.getMergedOptions(); return this.getMergedOptions();
} }
getUser(userResolvable: string): User | UnknownUser {
const id = resolveUserId(this.bot, userResolvable);
return id ? this.bot.users.get(id) || new UnknownUser({ id }) : new UnknownUser();
}
/** /**
* Resolves a user from the passed string. The passed string can be a user id, a user mention, a full username (with discrim), etc. * Resolves a user from the passed string. The passed string can be a user id, a user mention, a full username (with discrim), etc.
* If the user is not found in the cache, it's fetched from the API. * If the user is not found in the cache, it's fetched from the API.