Added ability to white or blacklist attachment filetype in automod

Intended to allow certain channels (i.e. bug reporting ones) to only allow .log files with uploads enabled, making it impossible to upload mp4s to troll or similar
This commit is contained in:
Dark 2020-03-20 18:04:37 +01:00 committed by Miikka
parent 22982b8113
commit 2c63509084
2 changed files with 72 additions and 0 deletions

View file

@ -60,10 +60,12 @@ import {
TMatchWordsTrigger, TMatchWordsTrigger,
TMemberJoinTrigger, TMemberJoinTrigger,
TRule, TRule,
TMatchAttachmentTypeTrigger,
} from "./types"; } from "./types";
import { pluginInfo } from "./info"; import { pluginInfo } from "./info";
import { ERRORS, RecoverablePluginError } from "../../RecoverablePluginError"; import { ERRORS, RecoverablePluginError } from "../../RecoverablePluginError";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
import { StrictValidationError } from "src/validatorUtils";
const unactioned = (action: TextRecentAction | OtherRecentAction) => !action.actioned; const unactioned = (action: TextRecentAction | OtherRecentAction) => !action.actioned;
@ -116,6 +118,19 @@ const defaultMatchLinksTrigger: Partial<TMatchLinksTrigger> = {
match_custom_status: false, match_custom_status: false,
}; };
const defaultMatchAttachmentTypeTrigger: Partial<TMatchAttachmentTypeTrigger> = {
filetype_blacklist: [],
blacklist_enabled: false,
filetype_whitelist: [],
whitelist_enabled: false,
match_messages: true,
match_embeds: true,
match_visible_names: false,
match_usernames: false,
match_nicknames: false,
match_custom_status: false,
};
const defaultTextSpamTrigger: Partial<t.TypeOf<typeof BaseTextSpamTrigger>> = { const defaultTextSpamTrigger: Partial<t.TypeOf<typeof BaseTextSpamTrigger>> = {
per_channel: true, per_channel: true,
}; };
@ -130,6 +145,7 @@ const defaultTriggers = {
match_regex: defaultMatchRegexTrigger, match_regex: defaultMatchRegexTrigger,
match_invites: defaultMatchInvitesTrigger, match_invites: defaultMatchInvitesTrigger,
match_links: defaultMatchLinksTrigger, match_links: defaultMatchLinksTrigger,
match_attachment_type: defaultMatchAttachmentTypeTrigger,
message_spam: defaultTextSpamTrigger, message_spam: defaultTextSpamTrigger,
mention_spam: defaultTextSpamTrigger, mention_spam: defaultTextSpamTrigger,
link_spam: defaultTextSpamTrigger, link_spam: defaultTextSpamTrigger,
@ -249,6 +265,21 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema, ICustomOverride
trigger[defaultTriggerName] = configUtils.mergeConfig({}, defaultTrigger, trigger[defaultTriggerName]); trigger[defaultTriggerName] = configUtils.mergeConfig({}, defaultTrigger, trigger[defaultTriggerName]);
} }
} }
if (trigger.match_attachment_type) {
const white = trigger.match_attachment_type.whitelist_enabled;
const black = trigger.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>`,
]);
}
}
} }
} }
@ -457,6 +488,23 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema, ICustomOverride
return null; return null;
} }
protected evaluateMatchAttachmentTypeTrigger(trigger: TMatchAttachmentTypeTrigger, msg: SavedMessage): null | string {
if (!msg.data.attachments) return null;
const attachments: any[] = msg.data.attachments;
for (const attachment of attachments) {
const attachment_type = attachment.filename.split(`.`).pop();
if (trigger.blacklist_enabled && trigger.filetype_blacklist.includes(attachment_type)) {
return `${attachment_type} - blacklisted`;
}
if (trigger.whitelist_enabled && !trigger.filetype_whitelist.includes(attachment_type)) {
return `${attachment_type} - not whitelisted`;
}
}
return null;
}
protected matchTextSpamTrigger( protected matchTextSpamTrigger(
recentActionType: RecentActionType, recentActionType: RecentActionType,
trigger: TBaseTextSpamTrigger, trigger: TBaseTextSpamTrigger,
@ -626,6 +674,13 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema, ICustomOverride
if (match) return { ...match, trigger: "match_links" } as TextTriggerMatchResult; if (match) return { ...match, trigger: "match_links" } as TextTriggerMatchResult;
} }
if (trigger.match_attachment_type) {
const match = await this.matchMultipleTextTypesOnMessage(trigger.match_attachment_type, msg, str => {
return this.evaluateMatchAttachmentTypeTrigger(trigger.match_attachment_type, msg);
});
if (match) return { ...match, trigger: "match_attachment_type" } as TextTriggerMatchResult;
}
if (trigger.message_spam) { if (trigger.message_spam) {
const match = this.matchTextSpamTrigger(RecentActionType.Message, trigger.message_spam, msg); const match = this.matchTextSpamTrigger(RecentActionType.Message, trigger.message_spam, msg);
if (match) return { ...match, rule, trigger: "message_spam" }; if (match) return { ...match, rule, trigger: "message_spam" };
@ -1319,6 +1374,8 @@ export class AutomodPlugin extends ZeppelinPlugin<TConfigSchema, ICustomOverride
return `invite code \`${disableInlineCode(matchResult.matchedValue)}\``; return `invite code \`${disableInlineCode(matchResult.matchedValue)}\``;
} else if (matchResult.trigger === "match_links") { } else if (matchResult.trigger === "match_links") {
return `link \`${disableInlineCode(matchResult.matchedValue)}\``; return `link \`${disableInlineCode(matchResult.matchedValue)}\``;
} else if (matchResult.trigger === "match_attachment_type") {
return `attachment type \`${disableInlineCode(matchResult.matchedValue)}\``;
} }
return typeof matchResult.matchedValue === "string" ? `\`${disableInlineCode(matchResult.matchedValue)}\`` : null; return typeof matchResult.matchedValue === "string" ? `\`${disableInlineCode(matchResult.matchedValue)}\`` : null;

View file

@ -179,6 +179,20 @@ export const MatchLinksTrigger = t.type({
}); });
export type TMatchLinksTrigger = t.TypeOf<typeof MatchLinksTrigger>; export type TMatchLinksTrigger = t.TypeOf<typeof MatchLinksTrigger>;
export const MatchAttachmentTypeTrigger = t.type({
filetype_blacklist: t.array(t.string),
blacklist_enabled: t.boolean,
filetype_whitelist: t.array(t.string),
whitelist_enabled: t.boolean,
match_messages: t.boolean,
match_embeds: t.boolean,
match_visible_names: t.boolean,
match_usernames: t.boolean,
match_nicknames: t.boolean,
match_custom_status: t.boolean,
});
export type TMatchAttachmentTypeTrigger = t.TypeOf<typeof MatchAttachmentTypeTrigger>;
export const BaseSpamTrigger = t.type({ export const BaseSpamTrigger = t.type({
amount: t.number, amount: t.number,
within: t.string, within: t.string,
@ -280,6 +294,7 @@ export const Rule = t.type({
match_regex: tNullable(MatchRegexTrigger), match_regex: tNullable(MatchRegexTrigger),
match_invites: tNullable(MatchInvitesTrigger), match_invites: tNullable(MatchInvitesTrigger),
match_links: tNullable(MatchLinksTrigger), match_links: tNullable(MatchLinksTrigger),
match_attachment_type: tNullable(MatchAttachmentTypeTrigger),
message_spam: tNullable(MessageSpamTrigger), message_spam: tNullable(MessageSpamTrigger),
mention_spam: tNullable(MentionSpamTrigger), mention_spam: tNullable(MentionSpamTrigger),
link_spam: tNullable(LinkSpamTrigger), link_spam: tNullable(LinkSpamTrigger),