From 7b12f2d6c8648dd4aafe32f5381992652b8c1dc2 Mon Sep 17 00:00:00 2001 From: Rei Star Date: Thu, 12 Jun 2025 15:26:06 +0400 Subject: [PATCH] feat: support polls --- backend/src/data/GuildSavedMessages.ts | 10 ++++++++++ backend/src/data/entities/SavedMessage.ts | 11 ++++++++++- .../Automod/functions/getTextMatchPartialSummary.ts | 6 ++++++ .../functions/matchMultipleTextTypesOnMessage.ts | 7 ++++++- backend/src/plugins/Automod/triggers/matchInvites.ts | 1 + backend/src/plugins/Automod/triggers/matchLinks.ts | 1 + backend/src/plugins/Automod/triggers/matchRegex.ts | 1 + backend/src/plugins/Automod/triggers/matchWords.ts | 1 + backend/src/utils.ts | 11 +++++++++++ 9 files changed, 47 insertions(+), 2 deletions(-) diff --git a/backend/src/data/GuildSavedMessages.ts b/backend/src/data/GuildSavedMessages.ts index 3edc2810..a979ad84 100644 --- a/backend/src/data/GuildSavedMessages.ts +++ b/backend/src/data/GuildSavedMessages.ts @@ -119,6 +119,16 @@ export class GuildSavedMessages extends BaseGuildRepository { })); } + if (msg.poll) { + data.poll = { + question: msg.poll.question, + answers: msg.poll.answers.map((answer) => ({ + id: answer.id, + text: answer.text, + })), + }; + } + return data; } diff --git a/backend/src/data/entities/SavedMessage.ts b/backend/src/data/entities/SavedMessage.ts index 9a0b310f..e9a0940a 100644 --- a/backend/src/data/entities/SavedMessage.ts +++ b/backend/src/data/entities/SavedMessage.ts @@ -1,4 +1,4 @@ -import { EmbedType, Snowflake, StickerFormatType, StickerType } from "discord.js"; +import { EmbedType, Snowflake, StickerFormatType, StickerType, PollQuestionMedia } from "discord.js"; import { Column, Entity, PrimaryColumn } from "typeorm"; export interface ISavedMessageAttachmentData { @@ -65,6 +65,14 @@ export interface ISavedMessageStickerData { type: StickerType | null; } +export interface ISavedMessagePollData { + question: PollQuestionMedia; + answers: { + id: number; + text: string | null; + }[]; +} + export interface ISavedMessageData { attachments?: ISavedMessageAttachmentData[]; author: { @@ -74,6 +82,7 @@ export interface ISavedMessageData { content: string; embeds?: ISavedMessageEmbedData[]; stickers?: ISavedMessageStickerData[]; + poll?: ISavedMessagePollData; timestamp: number; } diff --git a/backend/src/plugins/Automod/functions/getTextMatchPartialSummary.ts b/backend/src/plugins/Automod/functions/getTextMatchPartialSummary.ts index 3feb5eea..5053daaa 100644 --- a/backend/src/plugins/Automod/functions/getTextMatchPartialSummary.ts +++ b/backend/src/plugins/Automod/functions/getTextMatchPartialSummary.ts @@ -30,5 +30,11 @@ export function getTextMatchPartialSummary( return `visible name: ${visibleName}`; } else if (type === "customstatus") { return `custom status: ${context.member!.presence?.activities.find((a) => a.type === ActivityType.Custom)?.name}`; + } else if (type === "poll") { + const message = context.message!; + const channel = pluginData.guild.channels.cache.get(message.channel_id as Snowflake); + const channelMention = channel ? verboseChannelMention(channel) : `\`#${message.channel_id}\``; + + return `poll in ${channelMention}:\n${messageSummary(message)}`; } } diff --git a/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts b/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts index 2152b4c2..40b92dd1 100644 --- a/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts +++ b/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts @@ -12,9 +12,10 @@ type TextTriggerWithMultipleMatchTypes = { match_usernames: boolean; match_nicknames: boolean; match_custom_status: boolean; + match_polls: boolean; }; -export type MatchableTextType = "message" | "embed" | "visiblename" | "username" | "nickname" | "customstatus"; +export type MatchableTextType = "message" | "embed" | "visiblename" | "username" | "nickname" | "customstatus" | "poll"; type YieldedContent = [MatchableTextType, string]; @@ -59,4 +60,8 @@ export async function* matchMultipleTextTypesOnMessage( break; } } + + if (trigger.match_polls && msg.data.poll) { + yield ["poll", JSON.stringify(msg.data.poll)]; + } } diff --git a/backend/src/plugins/Automod/triggers/matchInvites.ts b/backend/src/plugins/Automod/triggers/matchInvites.ts index cf77fe7e..464cd53b 100644 --- a/backend/src/plugins/Automod/triggers/matchInvites.ts +++ b/backend/src/plugins/Automod/triggers/matchInvites.ts @@ -24,6 +24,7 @@ const configSchema = z.strictObject({ match_usernames: z.boolean().default(false), match_nicknames: z.boolean().default(false), match_custom_status: z.boolean().default(false), + match_polls: z.boolean().default(false), }); export const MatchInvitesTrigger = automodTrigger()({ diff --git a/backend/src/plugins/Automod/triggers/matchLinks.ts b/backend/src/plugins/Automod/triggers/matchLinks.ts index 9955b310..8258062e 100644 --- a/backend/src/plugins/Automod/triggers/matchLinks.ts +++ b/backend/src/plugins/Automod/triggers/matchLinks.ts @@ -47,6 +47,7 @@ const configSchema = z.strictObject({ match_usernames: z.boolean().default(false), match_nicknames: z.boolean().default(false), match_custom_status: z.boolean().default(false), + match_polls: z.boolean().default(false), }); export const MatchLinksTrigger = automodTrigger()({ diff --git a/backend/src/plugins/Automod/triggers/matchRegex.ts b/backend/src/plugins/Automod/triggers/matchRegex.ts index 4298cfc3..d75f3f42 100644 --- a/backend/src/plugins/Automod/triggers/matchRegex.ts +++ b/backend/src/plugins/Automod/triggers/matchRegex.ts @@ -24,6 +24,7 @@ const configSchema = z.strictObject({ match_usernames: z.boolean().default(false), match_nicknames: z.boolean().default(false), match_custom_status: z.boolean().default(false), + match_polls: z.boolean().default(false), }); const regexCache = new WeakMap(); diff --git a/backend/src/plugins/Automod/triggers/matchWords.ts b/backend/src/plugins/Automod/triggers/matchWords.ts index 0c324e53..fb4359f1 100644 --- a/backend/src/plugins/Automod/triggers/matchWords.ts +++ b/backend/src/plugins/Automod/triggers/matchWords.ts @@ -28,6 +28,7 @@ const configSchema = z.strictObject({ match_usernames: z.boolean().default(false), match_nicknames: z.boolean().default(false), match_custom_status: z.boolean().default(false), + match_polls: z.boolean().default(false), }); export const MatchWordsTrigger = automodTrigger()({ diff --git a/backend/src/utils.ts b/backend/src/utils.ts index a6c949ed..9b3d7e82 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -1337,6 +1337,17 @@ export function messageSummary(msg: SavedMessage) { "\n"; } + if (msg.data.poll) { + const { poll } = msg.data; + result += + "Poll: ```" + + escapeCodeBlock( + `Question: ${poll.question.text} + Answers: ${poll.answers.map((answer) => `${answer.text}`).join(" | ")}` + ) + + "```"; + } + return result; }