feat: add button to clear reminder #3

Merged
naomi merged 5 commits from Add-button-to-clear-reminder-#2 into main 2025-11-02 09:23:30 -08:00
3 changed files with 68 additions and 42 deletions
Showing only changes of commit 22f741e585 - Show all commits
+22 -13
View File
@@ -14,7 +14,7 @@ import {
ActionRowBuilder, ActionRowBuilder,
} from "discord.js"; } from "discord.js";
export const blocks = [ const blocks = [
new ContainerBuilder(). new ContainerBuilder().
addTextDisplayComponents( addTextDisplayComponents(
new TextDisplayBuilder().setContent("# About Altaria"), new TextDisplayBuilder().setContent("# About Altaria"),
@@ -65,20 +65,29 @@ export const blocks = [
), ),
]; ];
// config for the acknowledgment button // Config for the acknowledgment button
export const createAckButton = (userId: string) => { /**
const button = new ButtonBuilder() * Creates an acknowledgment button for alt-text reminders.
.setCustomId(`ack-${userId}`) * @param userId - The ID of the user who can acknowledge the reminder.
.setLabel("Got it!") * @returns An array containing an ActionRow with the acknowledgment button.
.setStyle(ButtonStyle.Secondary) */
.setEmoji("✅"); const createAckButton = (
Outdated
Review

This function should be in its own src/modules/createAckButton.ts file.

This function should be in its own `src/modules/createAckButton.ts` file.
userId: string,
): Array<ActionRowBuilder<ButtonBuilder>> => {
const button = new ButtonBuilder().
setCustomId(`ack-${userId}`).
setLabel("Got it!").
setStyle(ButtonStyle.Secondary).
setEmoji("✅");
const actionRow = new ActionRowBuilder<ButtonBuilder>().
addComponents(button);
const actionRow = new ActionRowBuilder<ButtonBuilder>() return [ actionRow ];
.addComponents(button); };
return [actionRow]; const replyForUnauthorized
}; = "❌ This button is only for the person who received the reminder.";
export const replyForUnauthorized = "❌ This button is only for the person who received the reminder."; export { blocks, createAckButton, replyForUnauthorized };
+2 -1
View File
1
@@ -33,9 +33,10 @@ export const checkAltText = async(message: Message): Promise<void> => {
if (noDescription.size > 0) { if (noDescription.size > 0) {
const reminder = getRandomValue(reminders); const reminder = getRandomValue(reminders);
// Button for acknowledgment
await message.reply({ await message.reply({
components: createAckButton(message.author.id), components: createAckButton(message.author.id),
content: `${reminder}\n-# If you do not know how to do this, check [Discord's help article](<https://support.discord.com/hc/en-us/articles/211866427-How-do-I-upload-images-and-GIFs>)!\n-# Need help writing descriptive text? Our bot [Cordelia](<https://cordelia.nhcarrigan.com>) can do it for you!`, // Button for acknowledgment content: `${reminder}\n-# If you do not know how to do this, check [Discord's help article](<https://support.discord.com/hc/en-us/articles/211866427-How-do-I-upload-images-and-GIFs>)!\n-# Need help writing descriptive text? Our bot [Cordelia](<https://cordelia.nhcarrigan.com>) can do it for you!`,
}).catch(() => { }).catch(() => {
return null; return null;
}); });
+42 -26
View File
@@ -4,37 +4,53 @@
* @author Gurkirat Singh - Technical volunteer * @author Gurkirat Singh - Technical volunteer
*/ */
import { ButtonInteraction, MessageFlags } from "discord.js"; import { type ButtonInteraction, MessageFlags } from "discord.js";
import { createAckButton as createAckButtonConfig } from "../config/blocks.js"; import {
import { replyForUnauthorized } from "../config/blocks.js"; createAckButton as createAckButtonConfig,
replyForUnauthorized,
} from "../config/blocks.js";
/** /**
* Creates an acknowledgment button for alt-text reminders * Creates an acknowledgment button for alt-text reminders.
* @param userId - The ID of the user who can acknowledge the reminder * @param userId - The ID of the user who can acknowledge the reminder.
* @returns ActionRow with the acknowledgment button * @returns ActionRow with the acknowledgment button.
*/ */
const createAckButton = (
Outdated
Review

This function is entirely unnecessary - after moving the other function to a module file, we can just use that directly.

This function is entirely unnecessary - after moving the other function to a module file, we can just use that directly.
userId: string,
export const createAckButton = (userId: string) => { ): ReturnType<typeof createAckButtonConfig> => {
return createAckButtonConfig(userId); return createAckButtonConfig(userId);
}; };
// function to handle button interaction /**
export const handleAckButton = async (interaction: ButtonInteraction) => { * Handles button interaction for acknowledgment buttons.
if (!interaction.customId.startsWith("ack-")) { * @param interaction - The button interaction to handle.
return false; // Not our button * @returns Promise that resolves to true if the button was handled, false otherwise.
} */
const handleAckButton = async(
Outdated
Review

This should get its own module file as well, in src/modules/handleAckButton.ts.

This should get its own module file as well, in `src/modules/handleAckButton.ts`.
interaction: ButtonInteraction,
): Promise<boolean> => {
if (!interaction.customId.startsWith("ack-")) {
// Not our button
return false;
}
const authorizedUserId = interaction.customId.split("-")[1]; const [ , authorizedUserId ] = interaction.customId.split("-");
if (interaction.user.id !== authorizedUserId) { if (interaction.user.id !== authorizedUserId) {
// Show error that auto-deletes after 2 seconds // Show error that auto-deletes after 2 seconds
await interaction.reply({ content: replyForUnauthorized, flags: MessageFlags.Ephemeral }); await interaction.reply({
setTimeout(() => interaction.deleteReply().catch(() => {}), 2000); content: replyForUnauthorized,
return true; flags: MessageFlags.Ephemeral,
} });
setTimeout(() => {
await interaction.message.delete(); void interaction.deleteReply().catch(() => {
// Intentionally empty - ignore deletion errors
});
}, 2000);
return true; return true;
} }
await interaction.message.delete();
return true;
};
export { createAckButton, handleAckButton };