88 lines
3.4 KiB
TypeScript
88 lines
3.4 KiB
TypeScript
import { GuildPluginData } from "knub";
|
|
import { SpamPluginType, RecentActionType } from "../types";
|
|
import { addRecentAction } from "./addRecentAction";
|
|
import { getRecentActionCount } from "./getRecentActionCount";
|
|
import { resolveMember, convertDelayStringToMS, stripObjectToScalars } from "../../../utils";
|
|
import { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin";
|
|
import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin";
|
|
import { CaseTypes } from "../../../data/CaseTypes";
|
|
import { clearRecentUserActions } from "./clearRecentUserActions";
|
|
import { LogType } from "../../../data/LogType";
|
|
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|
|
|
export async function logAndDetectOtherSpam(
|
|
pluginData: GuildPluginData<SpamPluginType>,
|
|
type: RecentActionType,
|
|
spamConfig: any,
|
|
userId: string,
|
|
actionCount: number,
|
|
actionGroupId: string,
|
|
timestamp: number,
|
|
extraData = null,
|
|
description: string,
|
|
) {
|
|
pluginData.state.spamDetectionQueue = pluginData.state.spamDetectionQueue.then(async () => {
|
|
// Log this action...
|
|
addRecentAction(pluginData, type, userId, actionGroupId, extraData, timestamp, actionCount);
|
|
|
|
// ...and then check if it trips the spam filters
|
|
const since = timestamp - 1000 * spamConfig.interval;
|
|
const recentActionsCount = getRecentActionCount(pluginData, type, userId, actionGroupId, since);
|
|
|
|
if (recentActionsCount > spamConfig.count) {
|
|
const member = await resolveMember(pluginData.client, pluginData.guild, userId);
|
|
const details = `${description} (over ${spamConfig.count} in ${spamConfig.interval}s)`;
|
|
const logs = pluginData.getPlugin(LogsPlugin);
|
|
|
|
if (spamConfig.mute && member) {
|
|
const mutesPlugin = pluginData.getPlugin(MutesPlugin);
|
|
const muteTime =
|
|
(spamConfig.mute_time && convertDelayStringToMS(spamConfig.mute_time.toString())) ?? 120 * 1000;
|
|
|
|
try {
|
|
await mutesPlugin.muteUser(
|
|
member.id,
|
|
muteTime,
|
|
"Automatic spam detection",
|
|
{
|
|
caseArgs: {
|
|
modId: pluginData.client.user!.id,
|
|
extraNotes: [`Details: ${details}`],
|
|
},
|
|
},
|
|
spamConfig.remove_roles_on_mute,
|
|
spamConfig.restore_roles_on_mute,
|
|
);
|
|
} catch (e) {
|
|
if (e instanceof RecoverablePluginError && e.code === ERRORS.NO_MUTE_ROLE_IN_CONFIG) {
|
|
logs.log(LogType.BOT_ALERT, {
|
|
body: `Failed to mute <@!${member.id}> in \`spam\` plugin because a mute role has not been specified in server config`,
|
|
});
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
} else {
|
|
// If we're not muting the user, just add a note on them
|
|
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
|
await casesPlugin.createCase({
|
|
userId,
|
|
modId: pluginData.client.user!.id,
|
|
type: CaseTypes.Note,
|
|
reason: `Automatic spam detection: ${details}`,
|
|
});
|
|
}
|
|
|
|
// Clear recent cases
|
|
clearRecentUserActions(pluginData, RecentActionType.VoiceChannelMove, userId, actionGroupId);
|
|
|
|
logs.log(LogType.OTHER_SPAM_DETECTED, {
|
|
member: stripObjectToScalars(member, ["user", "roles"]),
|
|
description,
|
|
limit: spamConfig.count,
|
|
interval: spamConfig.interval,
|
|
});
|
|
}
|
|
});
|
|
}
|