diff --git a/src/config/blocks.ts b/src/config/blocks.ts index 8a71c7f..1afa722 100644 --- a/src/config/blocks.ts +++ b/src/config/blocks.ts @@ -64,3 +64,21 @@ export const blocks = [ setURL("https://forum.nhcarrigan.com"), ), ]; + +// config for the acknowledgment button + +export const createAckButton = (userId: string) => { + const button = new ButtonBuilder() + .setCustomId(`ack-${userId}`) + .setLabel("Got it!") + .setStyle(ButtonStyle.Secondary) + .setEmoji("✅"); + + + const actionRow = new ActionRowBuilder() + .addComponents(button); + + return [actionRow]; + }; + +export const replyForUnauthorized = "❌ This button is only for the person who received the reminder."; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index a41ee18..6b45884 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import { Client, GatewayIntentBits, Events, MessageFlags } from "discord.js"; import { blocks } from "./config/blocks.js"; import { checkAltText } from "./modules/checkAltText.js"; import { instantiateServer } from "./server/serve.js"; +import { handleAckButton } from "./utils/buttonAck.js"; import { logger } from "./utils/logger.js"; const client = new Client({ @@ -35,13 +36,22 @@ client.on(Events.MessageCreate, (message) => { client.on(Events.InteractionCreate, (interaction) => { void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction }); - if (!interaction.isChatInputCommand()) { + if (!interaction.isChatInputCommand() && !interaction.isButton()) { return; } - void interaction.reply({ - components: blocks, - flags: MessageFlags.IsComponentsV2, - }); + // Existing logic for slash commands + if (interaction.isChatInputCommand()) { + void interaction.reply({ + components: blocks, + flags: MessageFlags.IsComponentsV2, + }); + return; + } + + // Handle button clicks + if (interaction.isButton()) { + void handleAckButton(interaction); + } }); await client.login(process.env.BOT_TOKEN); diff --git a/src/modules/checkAltText.ts b/src/modules/checkAltText.ts index 2883567..34bc288 100644 --- a/src/modules/checkAltText.ts +++ b/src/modules/checkAltText.ts @@ -5,6 +5,7 @@ */ import { reminders } from "../config/reminders.js"; +import { createAckButton } from "../utils/buttonAck.js"; import { getRandomValue } from "../utils/getRandomValue.js"; import { logger } from "../utils/logger.js"; import type { Message } from "discord.js"; @@ -33,7 +34,8 @@ export const checkAltText = async(message: Message): Promise => { if (noDescription.size > 0) { const reminder = getRandomValue(reminders); await message.reply({ - content: `${reminder}\n-# If you do not know how to do this, check [Discord's help article]()!\n-# Need help writing descriptive text? Our bot [Cordelia]() can do it for you!`, + components: createAckButton(message.author.id), + content: `${reminder}\n-# If you do not know how to do this, check [Discord's help article]()!\n-# Need help writing descriptive text? Our bot [Cordelia]() can do it for you!`, // Button for acknowledgment }).catch(() => { return null; }); diff --git a/src/utils/buttonAck.ts b/src/utils/buttonAck.ts new file mode 100644 index 0000000..8e6edb6 --- /dev/null +++ b/src/utils/buttonAck.ts @@ -0,0 +1,40 @@ +/** + * @copyright NHCarrigan + * @license Naomi's Public License + * @author Gurkirat Singh - Technical volunteer + */ + +import { ButtonInteraction, MessageFlags } from "discord.js"; +import { createAckButton as createAckButtonConfig } from "../config/blocks.js"; +import { replyForUnauthorized } from "../config/blocks.js"; + + + +/** + * Creates an acknowledgment button for alt-text reminders + * @param userId - The ID of the user who can acknowledge the reminder + * @returns ActionRow with the acknowledgment button + */ + + +export const createAckButton = (userId: string) => { + return createAckButtonConfig(userId); +}; + +// function to handle button interaction +export const handleAckButton = async (interaction: ButtonInteraction) => { + if (!interaction.customId.startsWith("ack-")) { + return false; // Not our button + } + + const authorizedUserId = interaction.customId.split("-")[1]; + if (interaction.user.id !== authorizedUserId) { + // Show error that auto-deletes after 2 seconds + await interaction.reply({ content: replyForUnauthorized, flags: MessageFlags.Ephemeral }); + setTimeout(() => interaction.deleteReply().catch(() => {}), 2000); + return true; + } + + await interaction.message.delete(); + return true; +}