-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
feat: add generalized action confirmations
Showing
10 changed files
with
144 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { SlashCommandBuilder } from 'discord.js'; | ||
import { command, confirmationResponse, reply } from 'utils'; | ||
|
||
// NOTE: this is just an example command to demonstrate the confirmation response | ||
// you can remove this file and the import from `src/commands/debug/index.ts` | ||
|
||
const meta = new SlashCommandBuilder() | ||
.setName('confirm') | ||
.setDescription('Test the confirmation response.'); | ||
|
||
export default command({ | ||
meta, | ||
private: true, | ||
exec: async ({ interaction }) => { | ||
await reply( | ||
interaction, | ||
confirmationResponse('example'), | ||
); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
import { category } from 'utils'; | ||
import ping from './ping.ts'; | ||
import confirm from './confirm.ts'; | ||
|
||
export default category( | ||
{ name: 'Debug', description: 'Commands used for debugging.', emoji: '🐛' }, | ||
[ping], | ||
[ping, confirm], | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { confirmationHandlers, EMOJIS, event, Namespace, parseId } from 'utils'; | ||
|
||
export default event('interactionCreate', async (ctx, interaction) => { | ||
if (!interaction.isButton()) return; | ||
const [namespace, action, key, ...args] = parseId(interaction.customId); | ||
if (namespace !== Namespace.Confirmation) return; | ||
|
||
const confirmed = action === 'confirm'; | ||
if (key in confirmationHandlers) { | ||
await confirmationHandlers[key as keyof typeof confirmationHandlers]( | ||
confirmed, | ||
ctx, | ||
interaction, | ||
args, | ||
); | ||
} else { | ||
await interaction.deferUpdate(); | ||
await interaction.editReply({ | ||
content: `${EMOJIS.error} Oops. Something went wrong!`, | ||
embeds: [], | ||
components: [], | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
import commands from './commands.ts'; | ||
import help from './help.ts'; | ||
import pagination from './pagination.ts'; | ||
import confirmation from './confirmation.ts'; | ||
|
||
const events = [commands, help, pagination]; | ||
const events = [commands, help, pagination, confirmation]; | ||
|
||
export default events; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { | ||
ActionRowBuilder, | ||
ButtonBuilder, | ||
ButtonInteraction, | ||
ButtonStyle, | ||
EmbedBuilder, | ||
InteractionReplyOptions, | ||
} from 'discord.js'; | ||
import { COLORS, confirmationHandlers, createId, Namespace } from 'utils'; | ||
import { EventContext } from 'types'; | ||
|
||
/** | ||
* Builds the reply options for a confirmation message. | ||
* The key is used to determine the confirmation handler to use. | ||
* If no embeds are provided in the reply options, a default embed will be added. | ||
* @param key - The key for the confirmation handler. | ||
* @param opts - The options for the confirmation message (optional). | ||
* @param args - The arguments to pass to the confirmation handler (optional). | ||
* @returns The given reply options with an added row of buttons and a default embed if none was provided. | ||
* @example | ||
* await interaction.reply(confirmationResponse('example')); | ||
*/ | ||
export const confirmationResponse = ( | ||
key: keyof typeof confirmationHandlers, | ||
opts?: InteractionReplyOptions, | ||
args?: string[], | ||
): InteractionReplyOptions => { | ||
const buttonsRow = new ActionRowBuilder<ButtonBuilder>().addComponents( | ||
new ButtonBuilder() | ||
.setCustomId(createId(Namespace.Confirmation, 'cancel', key, args)) | ||
.setLabel('Cancel') | ||
.setStyle(ButtonStyle.Secondary), | ||
new ButtonBuilder() | ||
.setCustomId(createId(Namespace.Confirmation, 'confirm', key, args)) | ||
.setLabel('Confirm') | ||
.setStyle(ButtonStyle.Primary), | ||
); | ||
|
||
return { | ||
...opts, | ||
components: [...(opts?.components ?? []), buttonsRow], | ||
embeds: opts?.embeds ?? | ||
[ | ||
new EmbedBuilder().setColor(COLORS.embed).setTitle('Confirmation') | ||
.setDescription('Are you sure you want to continue?'), | ||
], | ||
}; | ||
}; | ||
|
||
type ConfirmationHandler = ( | ||
/** Whether the confirmation was confirmed or cancelled. */ | ||
confirmed: boolean, | ||
/** The standard event context. */ | ||
ctx: EventContext, | ||
/** The button interaction that triggered the confirmation. */ | ||
interaction: ButtonInteraction, | ||
/** The optional list of arguments passed when creating the confirmation response. */ | ||
args: string[], | ||
) => Promise<void>; | ||
|
||
/** Simple function to type check the provided confirmation handler */ | ||
export function confirmation( | ||
handler: ConfirmationHandler, | ||
) { | ||
return handler; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { confirmation } from 'utils'; | ||
|
||
export default confirmation( | ||
// confirmed indicates whether the confirmation was confirmed or cancelled. | ||
// ctx contains the context with the bot client, etc. | ||
// interaction is the interaction that triggered the confirmation (button click). | ||
// args is the list of arguments passed to the confirmation handler (optional). | ||
async (confirmed, _ctx, interaction, _args) => { | ||
// This example just edits the message that contains the confirmation embed | ||
// to show a message indicating whether the confirmation was confirmed or cancelled. | ||
await interaction.deferUpdate(); | ||
await interaction.editReply({ | ||
content: confirmed ? 'Confirmed!' : 'Cancelled!', | ||
embeds: [], | ||
components: [], | ||
}); | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import example from './example.ts'; | ||
|
||
export const confirmationHandlers = { | ||
// NOTE: this is just an example handler to demonstrate the confirmation response | ||
// This handler is used by the `/confirm` command in `src/commands/debug/confirm.ts` | ||
'example': example, | ||
// Add more confirmation handlers here | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters