Confirmation prompts
Ask for a second click before something destructive with getConfirmation(). Covers its options, replacing the prompt after an answer, building the prompt's buttons yourself, and when a prompt is the wrong tool.
A ban or a wipe should ask before it runs. Written by hand, that's a message with two buttons, a collector that ignores everyone but the caller, a timeout, and a cleanup of the prompt once someone answers.
getConfirmation does all of that in one await. It sends a prompt with Confirm and Cancel buttons and resolves to true only when the person who ran the command clicks confirm. A cancel click and a timeout both resolve to false.
import {
getConfirmation,
SlashHandler,
SlashRoute
} from '@seedcord/gateway';
@SlashRoute('ban')
export class Ban extends SlashHandler<'ban'> {
public async execute(): Promise<void> {
const target = this.options.getUser('target');
const confirmed = await getConfirmation(
this,
`Ban ${target.username}?`
);
if (!confirmed) return;
await this.event.guild?.members.ban(target.id);
}
}Pass this as the first argument. The prompt uses your handler's own reply surface. That surface picks reply, edit, or follow-up from the interaction's current state.
seedcord ignores a click from anyone else, whether the prompt is ephemeral or public. Nothing answers that click, so Discord shows the other person its own failure message.
The options
| option | default | what it does |
|---|---|---|
ephemeral | true | shows the prompt to the invoking user alone |
timeoutMs | 30_000 | how long to wait before resolving false |
confirmLabel | 'Confirm' | the confirm button's text |
cancelLabel | 'Cancel' | the cancel button's text |
confirmStyle | ButtonStyle.Danger | the confirm button's color |
onConfirm | replaces the prompt after a confirm click | |
onCancel | replaces the prompt after a cancel click | |
onTimeout | replaces the prompt when the wait runs out |
Only the string form takes the label and style options.
Replacing the prompt
seedcord deletes the prompt once someone answers or the wait runs out. If it vanishes with nothing in its place, your caller never learns what happened. Set one of the three outcome options to replace the prompt with your reply.
const status = (text: string) => ({
components: [new StatusCard(text).component]
});
const confirmed = await getConfirmation(
this,
`Ban ${target.username}?`,
{
onConfirm: () => status('Banning now.'),
onTimeout: status('No answer. Nobody was banned.')
}
);
Each one takes a reply or a function returning one. The fence above passes both shapes, a function to onConfirm and a plain reply to onTimeout. seedcord calls the function after the click, so it reads whatever is true by then.
Without an outcome option, send the result with a fresh this.followUp(), since a deleted prompt leaves nothing to edit.
Building the prompt yourself
The string form draws one line of text above Confirm and Cancel. For a card, an image, or a summary of what's about to change, use the second form. You pass a function, and seedcord hands it the two button ids. Put them on your own buttons and return the whole reply.
const confirmed = await getConfirmation(this, (ids) => ({
components: [new GrantRow(ids).component]
}));
seedcord's router skips those two ids, so only the prompt's collector gets the click. Use ids.confirm and ids.cancel as is, since a button carrying any other id never reaches the collector.
Calling getConfirmation from a ModalHandler fails to compile, since its first parameter accepts every handler kind except a modal one.
Gateway only
getConfirmation ships in @seedcord/gateway alone. It holds a collector in the running process. An http bot answers each interaction as its own request, with nothing kept between them.
When a prompt is the wrong tool
The collector runs inside your bot's process. A restart ends every open prompt, and a later click gets Discord's own failure message.
Use a prompt for a decision someone makes in seconds. timeoutMs defaults to 30 seconds. Put an approval a moderator might answer hours later on a routed button with a custom id, which still works after a restart.