automod: tweaks/fixes to spam detection

This commit is contained in:
Dragory 2020-07-30 22:47:33 +03:00
parent 4931c95872
commit 80fb9d7b6b
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
7 changed files with 18 additions and 11 deletions

View file

@ -6,6 +6,7 @@ import { humanizeDurationShort } from "../../../humanizeDurationShort";
import { findRecentSpam } from "./findRecentSpam"; import { findRecentSpam } from "./findRecentSpam";
import { getMatchingMessageRecentActions } from "./getMatchingMessageRecentActions"; import { getMatchingMessageRecentActions } from "./getMatchingMessageRecentActions";
import * as t from "io-ts"; import * as t from "io-ts";
import { getMessageSpamIdentifier } from "./getSpamIdentifier";
const MessageSpamTriggerConfig = t.type({ const MessageSpamTriggerConfig = t.type({
amount: t.number, amount: t.number,
@ -28,7 +29,9 @@ export function createMessageSpamTrigger(spamType: RecentActionType, prettyName:
return; return;
} }
const recentSpam = findRecentSpam(pluginData, spamType, context.message.user_id); const spamIdentifier = getMessageSpamIdentifier(context.message, triggerConfig.per_channel);
const recentSpam = findRecentSpam(pluginData, spamType, spamIdentifier);
if (recentSpam) { if (recentSpam) {
await pluginData.state.archives.addSavedMessagesToArchive( await pluginData.state.archives.addSavedMessagesToArchive(
recentSpam.archiveId, recentSpam.archiveId,
@ -46,9 +49,9 @@ export function createMessageSpamTrigger(spamType: RecentActionType, prettyName:
pluginData, pluginData,
context.message, context.message,
spamType, spamType,
spamIdentifier,
triggerConfig.amount, triggerConfig.amount,
within, within,
triggerConfig.per_channel,
); );
if (matchedSpam) { if (matchedSpam) {
@ -61,7 +64,7 @@ export function createMessageSpamTrigger(spamType: RecentActionType, prettyName:
pluginData.state.recentSpam.push({ pluginData.state.recentSpam.push({
type: spamType, type: spamType,
userIds: [context.message.user_id], identifiers: [spamIdentifier],
archiveId, archiveId,
timestamp: Date.now(), timestamp: Date.now(),
}); });

View file

@ -2,8 +2,8 @@ import { PluginData } from "knub";
import { AutomodPluginType } from "../types"; import { AutomodPluginType } from "../types";
import { RecentActionType } from "../constants"; import { RecentActionType } from "../constants";
export function findRecentSpam(pluginData: PluginData<AutomodPluginType>, type: RecentActionType, userId?: string) { export function findRecentSpam(pluginData: PluginData<AutomodPluginType>, type: RecentActionType, identifier?: string) {
return pluginData.state.recentSpam.find(spam => { return pluginData.state.recentSpam.find(spam => {
return spam.type === type && (!userId || spam.userIds.includes(userId)); return spam.type === type && (!identifier || spam.identifiers.includes(identifier));
}); });
} }

View file

@ -9,19 +9,17 @@ export function getMatchingMessageRecentActions(
pluginData: PluginData<AutomodPluginType>, pluginData: PluginData<AutomodPluginType>,
message: SavedMessage, message: SavedMessage,
type: RecentActionType, type: RecentActionType,
identifier: string,
count: number, count: number,
within: number, within: number,
perChannel: boolean,
) { ) {
const since = moment.utc(message.posted_at).valueOf() - within; const since = moment.utc(message.posted_at).valueOf() - within;
const to = moment.utc(message.posted_at).valueOf(); const to = moment.utc(message.posted_at).valueOf();
const identifier = perChannel ? `${message.channel_id}-${message.user_id}` : message.user_id;
const recentActions = getMatchingRecentActions(pluginData, type, identifier, since, to); const recentActions = getMatchingRecentActions(pluginData, type, identifier, since, to);
const totalCount = recentActions.reduce((total, action) => total + action.count, 0); const totalCount = recentActions.reduce((total, action) => total + action.count, 0);
if (totalCount >= count) { if (totalCount >= count) {
return { return {
identifier,
recentActions, recentActions,
}; };
} }

View file

@ -16,7 +16,8 @@ export function getMatchingRecentActions(
action.type === type && action.type === type &&
(!identifier || action.identifier === identifier) && (!identifier || action.identifier === identifier) &&
action.context.timestamp >= since && action.context.timestamp >= since &&
action.context.timestamp <= to action.context.timestamp <= to &&
!action.context.actioned
); );
}); });
} }

View file

@ -0,0 +1,5 @@
import { SavedMessage } from "../../../data/entities/SavedMessage";
export function getMessageSpamIdentifier(message: SavedMessage, perChannel: boolean) {
return perChannel ? `${message.channel_id}-${message.user_id}` : message.user_id;
}

View file

@ -36,7 +36,7 @@ export const MemberJoinSpamTrigger = automodTrigger<unknown>()({
type: RecentActionType.MemberJoin, type: RecentActionType.MemberJoin,
timestamp: Date.now(), timestamp: Date.now(),
archiveId: null, archiveId: null,
userIds: [], identifiers: [],
}); });
return { return {

View file

@ -97,6 +97,6 @@ export interface RecentAction {
export interface RecentSpam { export interface RecentSpam {
archiveId: string; archiveId: string;
type: RecentActionType; type: RecentActionType;
userIds: string[]; identifiers: string[];
timestamp: number; timestamp: number;
} }