diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3060ce3..f10f68f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -50,6 +50,7 @@ model Guild { VerifyTempPaused Boolean @default(false) VerifyVerifiedRoleId String @default("") VerifyUnverifiedRoleId String @default("") + CreateCaseFromAutoMod Boolean @default(true) EnabledGuildFeatures GuildFeatures[] ModerationCase ModerationCase[] Tag Tag[] diff --git a/src/events/autoModDetect.ts b/src/events/autoModDetect.ts new file mode 100644 index 0000000..cb518e8 --- /dev/null +++ b/src/events/autoModDetect.ts @@ -0,0 +1,35 @@ +import { AutoModerationActionType } from "discord.js"; +import { GuildFeatures, ModerationAction } from "@prisma/client"; +import type { MeteoriumEvent } from "./eventsEntry.js"; + +export const Event: MeteoriumEvent<"autoModerationActionExecution"> = { + event: "autoModerationActionExecution", + async callback(client, exec) { + const guildSettings = await client.db.guild.findUnique({ where: { GuildId: exec.guild.id } }); + if (!guildSettings) throw new Error("could not get settings from database"); + if (!guildSettings.CreateCaseFromAutoMod) return; + if (!client.guildFeatures.hasFeatureEnabled(exec.guild.id, GuildFeatures.Moderation)) return; + + const rule = + exec.autoModerationRule || (await exec.guild.autoModerationRules.fetch(exec.ruleId).catch(() => null)); + if (!rule) return; + + await client.dbUtils.createModerationCase({ + Action: + exec.action.type == AutoModerationActionType.Timeout ? ModerationAction.Mute : ModerationAction.Warn, + GuildId: exec.guild.id, + TargetUserId: exec.userId, + ModeratorUserId: rule.creatorId, + Reason: `Automatically generated case from Auto Moderation (automod) trigger:\n${rule.name}`, + Duration: + exec.action.type == AutoModerationActionType.Timeout + ? exec.action.metadata.durationSeconds + ? (exec.action.metadata.durationSeconds * 1000).toString() + : "0" + : undefined, + }); + + return; + }, + once: false, +}; diff --git a/src/events/eventsEntry.ts b/src/events/eventsEntry.ts index baadb53..eee14d8 100644 --- a/src/events/eventsEntry.ts +++ b/src/events/eventsEntry.ts @@ -7,6 +7,7 @@ export * as PresenceResumption from "./presenceResumption.js"; export * as GuildDataSetup from "./guildDataSetup.js"; export * as GuildMemberJoinLogging from "./guildMemberJoinLogging.js"; export * as GuildMemberLeaveLogging from "./guildMemberLeaveLogging.js"; +export * as AutoModDetect from "./autoModDetect.js"; export type MeteoriumEvent = { event: EventName; diff --git a/src/index.ts b/src/index.ts index 27bc0d9..d6cb20d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,8 @@ const client = new MeteoriumClient({ IntentsBitField.Flags.GuildModeration, IntentsBitField.Flags.GuildVoiceStates, IntentsBitField.Flags.GuildPresences, + IntentsBitField.Flags.AutoModerationConfiguration, + IntentsBitField.Flags.AutoModerationExecution, ], }); diff --git a/src/interactions/commands/management/settings.ts b/src/interactions/commands/management/settings.ts index 0297690..d97f058 100644 --- a/src/interactions/commands/management/settings.ts +++ b/src/interactions/commands/management/settings.ts @@ -22,7 +22,8 @@ type DbSettingNames = | "VerifyAttachEnabled" | "VerifyTempPaused" | "VerifyVerifiedRoleId" - | "VerifyUnverifiedRoleId"; + | "VerifyUnverifiedRoleId" + | "CreateCaseFromAutoMod"; type SettingData = { type: SettingType; inName: string; dbName: DbSettingNames; description: string }; const settingsMapping: Array = [ { @@ -85,6 +86,12 @@ const settingsMapping: Array = [ dbName: "VerifyUnverifiedRoleId", description: "The role to be given for those who failed verification", }, + { + type: SettingType.Boolean, + inName: "casefromautomod", + dbName: "CreateCaseFromAutoMod", + description: "Detect automod events and automatically create a case from it", + }, ]; const interactionData = new SlashCommandBuilder()