disable sudo alert on antispam rules, add trycatch
This commit is contained in:
parent
3b64fbb587
commit
b1612824dd
4 changed files with 114 additions and 106 deletions
|
@ -1,11 +1,10 @@
|
||||||
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { client, dbs } from "../..";
|
import { dbs } from "../..";
|
||||||
import AntispamRule from "../../struct/antispam/AntispamRule";
|
import AntispamRule from "../../struct/antispam/AntispamRule";
|
||||||
import Infraction from "../../struct/antispam/Infraction";
|
import Infraction from "../../struct/antispam/Infraction";
|
||||||
import InfractionType from "../../struct/antispam/InfractionType";
|
import InfractionType from "../../struct/antispam/InfractionType";
|
||||||
import ModerationAction from "../../struct/antispam/ModerationAction";
|
import ModerationAction from "../../struct/antispam/ModerationAction";
|
||||||
import ServerConfig from "../../struct/ServerConfig";
|
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import { isModerator, storeInfraction } from "../util";
|
import { isModerator, storeInfraction } from "../util";
|
||||||
|
|
||||||
|
@ -17,81 +16,86 @@ let msgCountStore: Map<string, { users: any }> = new Map();
|
||||||
* @returns true if ok, false if spam rule triggered
|
* @returns true if ok, false if spam rule triggered
|
||||||
*/
|
*/
|
||||||
async function antispam(message: Message): Promise<boolean> {
|
async function antispam(message: Message): Promise<boolean> {
|
||||||
let serverRules = await dbs.SERVERS.findOne({ id: message.channel!.server_id! });
|
try {
|
||||||
if (!serverRules?.automodSettings) return true;
|
let serverRules = await dbs.SERVERS.findOne({ id: message.channel!.server_id! });
|
||||||
|
if (!serverRules?.automodSettings) return true;
|
||||||
|
|
||||||
let ruleTriggered = false;
|
let ruleTriggered = false;
|
||||||
|
|
||||||
for (const rule of serverRules.automodSettings.spam) {
|
for (const rule of serverRules.automodSettings.spam) {
|
||||||
if (msgCountStore.get(rule.id) == null) {
|
if (msgCountStore.get(rule.id) == null) {
|
||||||
msgCountStore.set(rule.id, { users: {} });
|
msgCountStore.set(rule.id, { users: {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.author?.bot != null) break;
|
if (message.author?.bot != null) break;
|
||||||
if (serverRules.whitelist?.users?.includes(message.author_id)) break;
|
if (serverRules.whitelist?.users?.includes(message.author_id)) break;
|
||||||
if (message.member?.roles?.filter(r => serverRules!.whitelist?.roles?.includes(r)).length) break;
|
if (message.member?.roles?.filter(r => serverRules!.whitelist?.roles?.includes(r)).length) break;
|
||||||
if (serverRules.whitelist?.managers !== false && await isModerator(message)) break;
|
if (serverRules.whitelist?.managers !== false && await isModerator(message, false)) break;
|
||||||
if (rule.channels?.length && rule.channels.indexOf(message.channel_id) == -1) break;
|
if (rule.channels?.length && rule.channels.indexOf(message.channel_id) == -1) break;
|
||||||
|
|
||||||
let store = msgCountStore.get(rule.id)!;
|
let store = msgCountStore.get(rule.id)!;
|
||||||
if (!store.users[message.channel_id]) store.users[message.channel_id] = {}
|
if (!store.users[message.channel_id]) store.users[message.channel_id] = {}
|
||||||
let userStore = store.users[message.channel_id];
|
let userStore = store.users[message.channel_id];
|
||||||
|
|
||||||
if (!userStore.count) userStore.count = 1;
|
if (!userStore.count) userStore.count = 1;
|
||||||
else userStore.count++;
|
else userStore.count++;
|
||||||
|
|
||||||
setTimeout(() => userStore.count--, rule.timeframe * 1000);
|
setTimeout(() => userStore.count--, rule.timeframe * 1000);
|
||||||
|
|
||||||
if (userStore.count > rule.max_msg) {
|
if (userStore.count > rule.max_msg) {
|
||||||
logger.info(`Antispam rule triggered: ${rule.max_msg}/${rule.timeframe} -> ${ModerationAction[rule.action]}`);
|
logger.info(`Antispam rule triggered: ${rule.max_msg}/${rule.timeframe} -> ${ModerationAction[rule.action]}`);
|
||||||
ruleTriggered = true;
|
ruleTriggered = true;
|
||||||
|
|
||||||
switch(Number(rule.action)) {
|
switch(Number(rule.action)) {
|
||||||
case ModerationAction.Delete:
|
case ModerationAction.Delete:
|
||||||
message.delete()
|
message.delete()
|
||||||
.catch(() => logger.warn('Antispam: Failed to delete message') );
|
.catch(() => logger.warn('Antispam: Failed to delete message') );
|
||||||
break;
|
break;
|
||||||
case ModerationAction.Message:
|
case ModerationAction.Message:
|
||||||
if (!userStore.warnTriggered) {
|
if (!userStore.warnTriggered) {
|
||||||
userStore.warnTriggered = true;
|
userStore.warnTriggered = true;
|
||||||
setTimeout(() => userStore.warnTriggered = false, 5000);
|
setTimeout(() => userStore.warnTriggered = false, 5000);
|
||||||
message.channel?.sendMessage(getWarnMsg(rule, message))
|
message.channel?.sendMessage(getWarnMsg(rule, message))
|
||||||
.catch(() => logger.warn('Antispam: Failed to send message'));
|
.catch(() => logger.warn('Antispam: Failed to send message'));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ModerationAction.Warn:
|
case ModerationAction.Warn:
|
||||||
if (!userStore.warnTriggered) {
|
if (!userStore.warnTriggered) {
|
||||||
userStore.warnTriggered = true;
|
userStore.warnTriggered = true;
|
||||||
setTimeout(() => userStore.warnTriggered = false, 5000);
|
setTimeout(() => userStore.warnTriggered = false, 5000);
|
||||||
|
|
||||||
let inf = {
|
let inf = {
|
||||||
_id: ulid(),
|
_id: ulid(),
|
||||||
createdBy: null,
|
createdBy: null,
|
||||||
date: Date.now(),
|
date: Date.now(),
|
||||||
reason: `Automatic moderation rule triggered: More than ${rule.max_msg} messages per ${rule.timeframe} seconds.`,
|
reason: `Automatic moderation rule triggered: More than ${rule.max_msg} messages per ${rule.timeframe} seconds.`,
|
||||||
server: message.channel?.server_id,
|
server: message.channel?.server_id,
|
||||||
type: InfractionType.Automatic,
|
type: InfractionType.Automatic,
|
||||||
user: message.author_id,
|
user: message.author_id,
|
||||||
} as Infraction;
|
} as Infraction;
|
||||||
|
|
||||||
message.channel?.sendMessage('## User has been warned.\n\u200b\n' + getWarnMsg(rule, message))
|
message.channel?.sendMessage('## User has been warned.\n\u200b\n' + getWarnMsg(rule, message))
|
||||||
.catch(() => logger.warn('Antispam: Failed to send warn message'));
|
.catch(() => logger.warn('Antispam: Failed to send warn message'));
|
||||||
|
|
||||||
await storeInfraction(inf);
|
await storeInfraction(inf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ModerationAction.Kick:
|
case ModerationAction.Kick:
|
||||||
message.reply('(Kick user)');
|
message.reply('(Kick user)');
|
||||||
break;
|
break;
|
||||||
case ModerationAction.Ban:
|
case ModerationAction.Ban:
|
||||||
message.reply('(Ban user)');
|
message.reply('(Ban user)');
|
||||||
break;
|
break;
|
||||||
default: logger.warn(`Unknown Moderation Action: ${rule.action}`);
|
default: logger.warn(`Unknown Moderation Action: ${rule.action}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return !ruleTriggered;
|
return !ruleTriggered;
|
||||||
|
} catch(e) {
|
||||||
|
console.error(''+e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWarnMsg(rule: AntispamRule, message: Message) {
|
function getWarnMsg(rule: AntispamRule, message: Message) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ let commands: SimpleCommand[];
|
||||||
logger.info(`Command: ${message.author?.username} (${message.author?._id}) in ${message.channel?.server?.name} (${message.channel?.server?._id}): ${message.content}`);
|
logger.info(`Command: ${message.author?.username} (${message.author?._id}) in ${message.channel?.server?.name} (${message.channel?.server?._id}): ${message.content}`);
|
||||||
|
|
||||||
// Create document for server in DB, if not already present
|
// Create document for server in DB, if not already present
|
||||||
if (JSON.stringify(config) == '{}') await dbs.SERVERS.insert({ id: message.channel!.server_id! });
|
if (JSON.stringify(config) == '{}' || !config) await dbs.SERVERS.insert({ id: message.channel!.server_id! });
|
||||||
|
|
||||||
if (cmd.removeEmptyArgs !== false) {
|
if (cmd.removeEmptyArgs !== false) {
|
||||||
args = args.filter(a => a.length > 0);
|
args = args.filter(a => a.length > 0);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
||||||
import { client } from "../../..";
|
import { dbs } from "../../..";
|
||||||
import ServerConfig from "../../../struct/ServerConfig";
|
|
||||||
import logger from "../../logger";
|
import logger from "../../logger";
|
||||||
import messageContentTrigger from "./message_content_trigger";
|
import messageContentTrigger from "./message_content_trigger";
|
||||||
|
|
||||||
|
@ -8,47 +7,50 @@ import custom_sendMessage from "./actions/sendMessage";
|
||||||
import custom_delete from "./actions/delete";
|
import custom_delete from "./actions/delete";
|
||||||
import custom_warn from "./actions/warn";
|
import custom_warn from "./actions/warn";
|
||||||
import { getOwnMemberInServer, hasPermForChannel } from "../../util";
|
import { getOwnMemberInServer, hasPermForChannel } from "../../util";
|
||||||
import MessageCommandContext from "../../../struct/MessageCommandContext";
|
|
||||||
|
|
||||||
async function checkCustomRules(message: Message, isEdit: boolean = false) {
|
async function checkCustomRules(message: Message, isEdit: boolean = false) {
|
||||||
let serverConfig: ServerConfig = await client.db.get('servers').findOne({ id: message.channel?.server_id }) ?? {};
|
try {
|
||||||
let rules = serverConfig?.automodSettings?.custom;
|
let serverConfig = await dbs.SERVERS.findOne({ id: message.channel!.server_id! });
|
||||||
if (!rules) return;
|
let rules = serverConfig?.automodSettings?.custom;
|
||||||
|
if (!rules) return;
|
||||||
|
|
||||||
for (let rule of rules) {
|
for (let rule of rules) {
|
||||||
if (!rule?.trigger?.on) continue;
|
if (!rule?.trigger?.on) continue;
|
||||||
let onEdit = rule.trigger.on.includes('message/update');
|
let onEdit = rule.trigger.on.includes('message/update');
|
||||||
let onNew = rule.trigger.on.includes('message/create');
|
let onNew = rule.trigger.on.includes('message/create');
|
||||||
|
|
||||||
// tired
|
// tired
|
||||||
if (!((onEdit && isEdit) || (onNew && !isEdit) || (onNew && onEdit))) break;
|
if (!((onEdit && isEdit) || (onNew && !isEdit) || (onNew && onEdit))) break;
|
||||||
|
|
||||||
if (await messageContentTrigger(message, rule.trigger)) {
|
if (await messageContentTrigger(message, rule.trigger)) {
|
||||||
for (const action of rule.action) {
|
for (const action of rule.action) {
|
||||||
switch(action.action) {
|
switch(action.action) {
|
||||||
case 'sendMessage':
|
case 'sendMessage':
|
||||||
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage'))
|
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage'))
|
||||||
await custom_sendMessage(message, action);
|
await custom_sendMessage(message, action);
|
||||||
else
|
else
|
||||||
logger.warn(`Custom rule ${rule._id}: 'sendMessage' action lacks permission`);
|
logger.warn(`Custom rule ${rule._id}: 'sendMessage' action lacks permission`);
|
||||||
break;
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'ManageMessages'))
|
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'ManageMessages'))
|
||||||
await custom_delete(message, action);
|
await custom_delete(message, action);
|
||||||
else
|
else
|
||||||
logger.warn(`Custom rule ${rule._id}: 'delete' action lacks permission`);
|
logger.warn(`Custom rule ${rule._id}: 'delete' action lacks permission`);
|
||||||
break;
|
break;
|
||||||
case 'warn':
|
case 'warn':
|
||||||
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage'))
|
if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage'))
|
||||||
await custom_warn(message, action);
|
await custom_warn(message, action);
|
||||||
else
|
else
|
||||||
logger.warn(`Custom rule ${rule._id}: 'warn' action lacks permission`);
|
logger.warn(`Custom rule ${rule._id}: 'warn' action lacks permission`);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn(`Unknown action ${action.action} in custom rule ${rule._id} in server ${message.channel?.server_id}`);
|
logger.warn(`Unknown action ${action.action} in custom rule ${rule._id} in server ${message.channel?.server_id}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error(''+e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ async function parseUserOrId(text: string): Promise<User|{_id: string}|null> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isModerator(message: Message) {
|
async function isModerator(message: Message, announceSudo?: boolean) {
|
||||||
let member = message.member!, server = message.channel!.server!;
|
let member = message.member!, server = message.channel!.server!;
|
||||||
|
|
||||||
if (hasPerm(member, 'KickMembers')) return true;
|
if (hasPerm(member, 'KickMembers')) return true;
|
||||||
|
@ -83,32 +83,34 @@ async function isModerator(message: Message) {
|
||||||
const [ isManager, mods, isSudo ] = await Promise.all([
|
const [ isManager, mods, isSudo ] = await Promise.all([
|
||||||
isBotManager(message),
|
isBotManager(message),
|
||||||
dbs.SERVERS.findOne({ id: server._id }),
|
dbs.SERVERS.findOne({ id: server._id }),
|
||||||
checkSudoPermission(message),
|
checkSudoPermission(message, announceSudo),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return isManager
|
return isManager
|
||||||
|| (mods?.moderators?.indexOf(member.user?._id!) ?? -1) > -1
|
|| (mods?.moderators?.indexOf(member.user?._id!) ?? -1) > -1
|
||||||
|| isSudo;
|
|| isSudo;
|
||||||
}
|
}
|
||||||
async function isBotManager(message: Message) {
|
async function isBotManager(message: Message, announceSudo?: boolean) {
|
||||||
let member = message.member!, server = message.channel!.server!;
|
let member = message.member!, server = message.channel!.server!;
|
||||||
|
|
||||||
if (hasPerm(member, 'ManageServer')) return true;
|
if (hasPerm(member, 'ManageServer')) return true;
|
||||||
|
|
||||||
const [ managers, isSudo ] = await Promise.all([
|
const [ managers, isSudo ] = await Promise.all([
|
||||||
dbs.SERVERS.findOne({ id: server._id }),
|
dbs.SERVERS.findOne({ id: server._id }),
|
||||||
checkSudoPermission(message),
|
checkSudoPermission(message, announceSudo),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (managers?.botManagers?.indexOf(member.user?._id!) ?? -1) > -1
|
return (managers?.botManagers?.indexOf(member.user?._id!) ?? -1) > -1
|
||||||
|| isSudo;
|
|| isSudo;
|
||||||
}
|
}
|
||||||
async function checkSudoPermission(message: Message): Promise<boolean> {
|
async function checkSudoPermission(message: Message, announce?: boolean): Promise<boolean> {
|
||||||
const hasPerm = isSudo(message.author!);
|
const hasPerm = isSudo(message.author!);
|
||||||
if (!hasPerm) return false;
|
if (!hasPerm) return false;
|
||||||
else {
|
else {
|
||||||
await message.reply(`# :unlock: Bypassed permission check\n`
|
if (announce !== false) {
|
||||||
+ `Sudo mode is enabled for @${message.author!.username}.\n`);
|
await message.reply(`# :unlock: Bypassed permission check\n`
|
||||||
|
+ `Sudo mode is enabled for @${message.author!.username}.\n`);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue