summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-10-18 16:05:45 +0200
committerRory& <root@rory.gay>2025-10-18 16:31:11 +0200
commite4714b426b84abe8b7145f0c309ec12a6fc3c6a5 (patch)
treece7d4fc6593dc766ede2f6d9f57cd9da8bf9d8fa /src/api
parentfix: typo, additional `m` lol (diff)
downloadserver-ts-e4714b426b84abe8b7145f0c309ec12a6fc3c6a5.tar.xz
Automod mayhaps?
Diffstat (limited to 'src/api')
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts91
1 files changed, 84 insertions, 7 deletions
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts

index 482db1d7..d6df9995 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -19,30 +19,41 @@ import { handleMessage, postHandleMessage, route } from "@spacebar/api"; import { Attachment, + AutomodRule, + AutomodTriggerTypes, Channel, Config, DmChannelDTO, + emitEvent, FieldErrors, + getPermission, + getUrlSignature, Member, Message, MessageCreateEvent, + NewUrlSignatureData, + NewUrlUserSignatureData, ReadState, Rights, Snowflake, - User, - emitEvent, - getPermission, - getUrlSignature, uploadFile, - NewUrlSignatureData, - NewUrlUserSignatureData, + User, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import multer from "multer"; import { FindManyOptions, FindOperator, LessThan, MoreThan, MoreThanOrEqual } from "typeorm"; import { URL } from "url"; -import { isTextChannel, MessageCreateAttachment, MessageCreateCloudAttachment, MessageCreateSchema, Reaction } from "@spacebar/schemas"; +import { + AutomodCustomWordsRule, + AutomodRuleActionType, + AutomodRuleEventType, + isTextChannel, + MessageCreateAttachment, + MessageCreateCloudAttachment, + MessageCreateSchema, + Reaction, +} from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); @@ -404,6 +415,72 @@ router.post( // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore message.member.roles = message.member.roles.filter((x) => x.id != x.guild_id).map((x) => x.id); + + try { + if (message.content) + for (const rule of await AutomodRule.find({ where: { guild_id: message.guild_id, enabled: true, event_type: AutomodRuleEventType.MESSAGE_SEND } })) { + if (rule.exempt_channels.includes(channel_id)) continue; + if (message.member.roles.some((x) => rule.exempt_roles.includes(x.id))) continue; + if (rule.trigger_type == AutomodTriggerTypes.CUSTOM_WORDS) { + const triggerMeta = rule.trigger_metadata as AutomodCustomWordsRule; + const regexes = triggerMeta.regex_patterns + .map((x) => new RegExp(x, "i")) + .concat( + triggerMeta.keyword_filter + .map((k) => + k + // Convert simple wildcard patterns to regex + .replace(".", "\\.") + .replace("?", ".") + .replace("*", ".*"), + ) + .map((k) => new RegExp(k, "i")), + ); + const allowedRegexes = triggerMeta.allow_list + .map((k) => + k + // Convert simple wildcard patterns to regex + .replace(".", "\\.") + .replace("?", ".") + .replace("*", ".*"), + ) + .map((k) => new RegExp(k, "i")); + + const matches = regexes + .map((r) => message.content!.match(r)) + .filter((x) => x !== null && x.length > 0) + .filter((x) => !allowedRegexes.some((ar) => ar.test(x![0]))); + if (matches.length > 0) { + console.log("Automod triggered by message:", message.id, "matches:", matches); + if (rule.actions.some((x) => x.type == AutomodRuleActionType.SEND_ALERT_MESSAGE && x.metadata.channel_id)) { + const alertActions = rule.actions.filter((x) => x.type == AutomodRuleActionType.SEND_ALERT_MESSAGE); + for (const action of alertActions) { + const alertChannel = await Channel.findOne({ where: { id: action.metadata.channel_id } }); + if (!alertChannel) continue; + const msg = Message.create({ + channel_id: alertChannel.id, + content: `Automod Alert: Message ${message.id} by <@${message.author_id}> in <#${channel.id}> triggered automod rule "${rule.name}".\nMatched terms: ${matches + .map((x) => `\`${x![0]}\``) + .join(", ")}`, + author: message.author, + guild_id: message.channel.guild_id, + }); + await Promise.all([ + Message.insert(message), + emitEvent({ + event: "MESSAGE_CREATE", + channel_id: msg.channel_id, + data: msg.toJSON(), + } as MessageCreateEvent), + ]); + } + } + } + } + } + } catch (e) { + console.log("[Automod] failed to process message:", e); + } } let read_state = await ReadState.findOne({