Skip to content

Recipes

Note

Contributions to recipes are welcome, you can do so by contributing directly, or by suggesting (in the support server) what topics should be explained, how they should be structured, give relevant use cases/examples...

Components

Awaiting a component with coroutines

You can also use components without setting a handler, and instead await the event:

@Command
class SlashClickWaiter(private val buttons: Buttons) : ApplicationCommand() {
    @JDASlashCommand(name = "click_waiter", description = "Sends a button and waits for it to be clicked")
    suspend fun onSlashClickWaiter(event: GuildSlashEvent) {
        val button = buttons.primary("Click me").ephemeral {
            // Make it so this button is only usable once
            singleUse = true

            // Only allow the caller to use the button
            constraints += event.user
        }
        event.replyComponents(row(button)).await()

        // Wait for the allowed user to click the button
        val buttonEvent: ButtonEvent = button.awaitOrNull() // (1)!
            ?: return event.hook
                .replaceWith("Expired!")
                .awaitUnit() // (2)!

        buttonEvent.editMessage("!")
            // Replace the entire message
            .setReplace(true)
            // Delete after 5 seconds
            .deleteDelayed(5.seconds)
            // Note that the coroutine will resume *after the message is deleted*
            .await()
    }
}
  1. AwaitableComponent<T>.awaitOrNull returns null when the component expired, useful when combined with an elvis operator, this is the equivalent of a try catch on TimeoutCancellationException. Since there is no timeout set here, the default duration is used.

  2. RestAction<*>.awaitUnit is an extension to await and then return Unit, which helps in common scenarios where you want to reply using an elvis operator.