jda.wiki Open in urlscan Pro
185.199.110.153  Public Scan

URL: https://jda.wiki/using-jda/interactions/
Submission: On October 05 via api from US — Scanned from IT

Form analysis 2 forms found in the DOM

<form class="md-header__option" data-md-component="palette">
  <input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="purple" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette"
    id="__palette_0">
  <label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path
        d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31">
      </path>
    </svg>
  </label>
  <input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="purple" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
  <label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden="">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path
        d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z">
      </path>
    </svg>
  </label>
</form>

Name: search

<form class="md-search__form" name="search">
  <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required="">
  <label class="md-search__icon md-icon" for="__search">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path>
    </svg>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path>
    </svg>
  </label>
  <nav class="md-search__options" aria-label="Search">
    <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
      </svg>
    </button>
  </nav>
</form>

Text Content

Skip to content

JDA Wiki
Interactions

Type to start searching
JDA
 * v5.1.2
 * 4.3k
 * 737

 * Getting Started
 * Setup
 * Using JDA
 * Contributing
 * Javadocs

JDA Wiki
JDA
 * v5.1.2
 * 4.3k
 * 737

 * Getting Started
   Getting Started
    * JDA
    * Using Events
    * List of Events
    * FAQ
    * Migration V3 -> V4
    * Migration V4 -> V5

 * Setup
   Setup
    * IntelliJ IDEA Setup
    * Eclipse Setup
    * Netbeans Setup
    * Logging (SLF4J)

 * Using JDA
   Using JDA
    * Getting Started
    * Making a Music Bot
    * Using RestAction
    * Interactions Interactions
      Table of contents
       * Ephemeral Messages
       * Command Interactions
          * Slash Commands
             * Creating Slash Commands
             * Responding to Slash Commands
             * Managing Slash Command Permissions
         
          * Slash Command Autocomplete
             * Handling Autocomplete
         
          * Context Menus
      
       * Component Interactions
          * Buttons
             * Handling ButtonInteractionEvent
         
          * Select Menus (Dropdowns)
             * String Select Menus
             * Entity Select Menus
             * Handling Select Menus
      
       * Modals
          * Replying with a Modal
          * Handling ModalInteractionEvent
   
    * Paginating Entities
    * Gateway Intents and Member Cache Policy
    * Webhooks
    * Managers and Moderation
    * Using New Features
    * Troubleshooting

 * Contributing
   Contributing
    * Contributing
    * Structure Guide
    * Repository Structure

 * Javadocs


INTERACTIONS¶

Interactions differ between JDA v4 and JDA v5. This page covers JDA v5.

This guide will give you a brief introduction to an API for adding and handling
interactions in Discord. Interactions are a way to integrate your bot features
directly into the Discord User Interface. These things include features such as:

 * Slash Commands
 * Slash Command Autocomplete
 * Context Menus
 * Buttons
 * Select Menus (Dropdowns)
 * Modals


EPHEMERAL MESSAGES¶

Ephemeral messages are only visible to the user who used your Interaction. They
are similar to the messages Discord sends you when you update your nickname with
/nick.

There are many limitations to ephemeral messages, a few of which are listed
below:

 * Cannot be reacted to
 * Cannot be retrieved
 * Will be removed after a client restart

Example



You can only create ephemeral messages with interactions. For example with
deferReply(true), reply(content).setEphemeral(true), or
getHook().sendMessage(content).setEphemeral(true). For convenience, you can also
configure the InteractionHook to default to ephemeral messages with
hook.setEphemeral(true).


COMMAND INTERACTIONS¶


SLASH COMMANDS¶

A slash command is something you might already be familiar with from the olden
times of Discord. Commands such as /shrug or /me have existed for quite a long
time. With Slash Command interactions you can now make your very own commands
like this! But these commands come with some limitations, which I have explained
in this gist: Slash Command Limitations



All of these commands are used through the interactions API. They do not require
the user to send an actual message in the channel and you don't have to do
string parsing either.

To create commands you need to make some API requests. There are 2 types of
commands you can create called global commands and guild commands.

 * Global: These commands are available in every server your bot is in
   (regardless of sharding!) and direct message (Private Channels).
 * Guild: These commands are only in the specific guild that you created them in
   and cannot be used in direct messages.

CREATING SLASH COMMANDS¶

You can create commands through these methods in JDA:

 * updateCommands()
 * upsertCommand(name, description)

Example

JavaKotlin

guild.updateCommands().addCommands(
        Commands.slash("echo", "Repeats messages back to you.")
            .addOption(OptionType.STRING, "message", "The message to repeat.")
            .addOption(OptionType.INTEGER, "times", "The number of times to repeat the message.")
            .addOption(OptionType.BOOLEAN, "ephemeral", "Whether or not the message should be sent as an ephemeral message."),
        Commands.slash("animal", "Finds a random animal")
             .addOptions(
                 new OptionData(OptionType.STRING, "type", "The type of animal to find")
                     .addChoice("Bird", "bird")
                     .addChoice("Big Cat", "bigcat")
                     .addChoice("Canine", "canine")
                     .addChoice("Fish", "fish")
             )
).queue();


guild.updateCommands().addCommands(
        Commands.slash("echo", "Repeats messages back to you.")
            .addOption(OptionType.STRING, "message", "The message to repeat.")
            .addOption(OptionType.INTEGER, "times", "The number of times to repeat the message.")
            .addOption(OptionType.BOOLEAN, "ephemeral", "Whether or not the message should be sent as an ephemeral message."),
        Commands.slash("animal", "Finds a random animal")
             .addOptions(
                 OptionData(OptionType.STRING, "type", "The type of animal to find")
                     .addChoice("Bird", "bird")
                     .addChoice("Big Cat", "bigcat")
                     .addChoice("Canine", "canine")
                     .addChoice("Fish", "fish")
             )
).queue()





You need to call these on a JDA instance to create global commands, and on a
Guild instance to create guild commands . Your bot needs the
applications.commands scope in addition to the bot scope for your bot invite
link. Example:
https://discord.com/oauth2/authorize?client_id=123456789&scope=bot+applications.commands

Warning

If the applications.commands scope is not present, JDA will fail to create guild
commands, and global commands will not be shown in the client.

Once a command is created, it will continue persisting even when your bot
restarts. Commands stay until the bot is either kicked or your bot explicitly
deletes the command. You don't need to create your commands every time your bot
starts!

RESPONDING TO SLASH COMMANDS¶

When a user tries to use one of your commands you will receive a
SlashCommandInteractionEvent. This event needs to be handled by your event
listener. The flow of a slash command response is as follows:

 1. Acknowledge the command
    
    This means you need to either reply or deferReply. You only have 3 SECONDS
    to acknowledge a command. Since some commands may take longer than 3 seconds
    you may want to use deferReply to have more time for handling. This will
    instead send a Thinking... message to channel which is later updated by a
    followup message (see step 2).
    
    

 2. Send followup messages
    
    Sometimes commands need more than one response. However, you can only send
    one initial reply to a command. To send additional messages for the same
    slash command you need to use the InteractionHook attached to the event with
    getHook(). This is a webhook that allows you to send additional messages for
    up to 15 minutes after the initial command.

When you use deferReply the first message sent to this webhook will act
identically to using editOriginal(...). The message you send is also referred to
as deferred reply in this case. Your deferred reply will edit your initial
Thinking... message instead of sending an additional message to channel. This
means you cannot use setEphemeral on this deferred reply since you already
decided whether the message will be ephemeral through your initial
acknowledgment.

Example Reply

JavaKotlin

public class SayCommand extends ListenerAdapter {
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        if (event.getName().equals("say")) {
          event.reply(event.getOption("content").getAsString()).queue(); // reply immediately
        }
    }
}


object SayCommand : ListenerAdapter() {
  override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
    if (event.name == "say") {
      event.reply(event.getOption("content")!!.asString).queue()
    }
  }
}





Example Deferred Reply

JavaKotlin

public class TagCommand extends ListenerAdapter {
  @Override
  public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
    if (event.getName().equals("tag")) {
      event.deferReply().queue(); // Tell discord we received the command, send a thinking... message to the user
      String tagName = event.getOption("name").getAsString();
      TagDatabase.fingTag(tagName,
        (tag) -> event.getHook().sendMessage(tag).queue() // delayed response updates our inital "thinking..." message with the tag value
      );
    }
  }
}


object TagCommand : ListenerAdapter() {
    override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
        if (event.name == "tag") {
            event.deferReply().queue() // Tell discord we received the command, send a thinking... message to the user
            val tagName = event.getOption("name")!!.asString
            TagDatabase.fingTag(tagName) { tag ->
                event.hook.sendMessage(tag).queue() // delayed response updates our inital "thinking..." message with the tag value
            }
        }
    }
}





MANAGING SLASH COMMAND PERMISSIONS¶

Restricting slash commands to specific roles or members is up to the admins of
the guild. However, bots can specify a set of permissions that sets who can use
those commands by default.

Note that members with Permission.ADMINISTRATOR can always use commands, and
they can override which roles or members can run the command. JDA only changes
the default members and roles that can access it.

In order to set this default, .setDefaultPermissions() can be called on the
command before you register it. DefaultMemberPermissions.DISABLED can be used to
only allow administrators by default, and DefaultMemberPermissions.ENABLED can
be used to allow all members by default.

Example

This will restrict the command so that only members with the
Permission.MANAGE_CHANNEL and Permission.MODERATE_MEMBERS permissions can use
the command:

JavaKotlin

guild.updateCommands().addCommands(
    Commands.slash("meeting", "Creates a new channel for an emergency meeting")
        .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_CHANNEL, Permission.MODERATE_MEMBERS))
).queue();


guild.updateCommands().addCommands(
    Commands.slash("meeting", "Creates a new channel for an emergency meeting")
        .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_CHANNEL, Permission.MODERATE_MEMBERS))
).queue()






SLASH COMMAND AUTOCOMPLETE¶

Slash command autocompletion is a feature that allows users to begin typing
arguments to a command, and suggestions from the bot will be displayed to the
user, in-client.

Any slash command arguments using the String, Integer or Number types can be
autocompleted. By default, options are not autocompleted. In order to make an
option autocompleted, OptionData#setAutoComplete(true) may be used.



HANDLING AUTOCOMPLETE¶

As the user is typing an argument that has autocomplete enabled for it, the bot
will receive an CommandAutoCompleteInteractionEvent. This event isn't fired for
each keystroke, but is sent when Discord determines the user has paused typing
for a bit.

Autocompletions can suggest up to 25 options, and users do not have to send a
command with one of the options.

Example

Creating the command:

JavaKotlin

guild.updateCommands().addCommands(
        Commands.slash("fruit", "find a given fruit")
            .addOption(OptionType.STRING, "name", "fruit to find", true, true)
).queue();


guild.updateCommands().addCommands(
        Commands.slash("fruit", "find a given fruit")
            .addOption(OptionType.STRING, "name", "fruit to find", required=true, autocomplete=true)
).queue()





Handling the event:

JavaKotlin
AutoCompleteBot.java

public class AutoCompleteBot extends ListenerAdapter {
    private String[] words = new String[]{"apple", "apricot", "banana", "cherry", "coconut", "cranberry"};

    @Override
    public void onCommandAutoCompleteInteraction(CommandAutoCompleteInteractionEvent event) {
        if (event.getName().equals("fruit") && event.getFocusedOption().getName().equals("name")) {
            List<Command.Choice> options = Stream.of(words)
                    .filter(word -> word.startsWith(event.getFocusedOption().getValue())) // only display words that start with the user's current input
                    .map(word -> new Command.Choice(word, word)) // map the words to choices
                    .collect(Collectors.toList());
            event.replyChoices(options).queue();
        }
    }
}


AutoCompleteBot.kt

object AutoCompleteBot : ListenerAdapter() {
    private val words = arrayOf("apple", "apricot", "banana", "cherry", "coconut", "cranberry")

    override fun onCommandAutoCompleteInteraction(event: CommandAutoCompleteInteractionEvent) {
        if (event.name == "fruit" && event.focusedOption.name == "name") {
            event.replyChoiceStrings(words.filter {
                it.startsWith(event.focusedOption.value)
            }).queue()
        }
    }
}






CONTEXT MENUS¶

Context Menu commands are a special type of command that can be invoked on a
user or message by right-clicking on them. These commands take no arguments, and
are useful for providing a quick way to perform actions on a user or message.





Example

Creating the commands:

guild.updateCommands().addCommands(
        Commands.context(Command.Type.USER, "Get user avatar"),
        Commands.message("Count words")
).queue()




Handling the events:

JavaKotlin
ContextMenuBot.java

public class ContextMenuBot extends ListenerAdapter {
    @Override
    public void onUserContextInteraction(UserContextInteractionEvent event) {
        if (event.getName().equals("Get user avatar")) {
            event.reply("Avatar: " + event.getTarget().getEffectiveAvatarUrl()).queue();
        }
    }

    @Override
    public void onMessageContextInteraction(MessageContextInteractionEvent event) {
        if (event.getName().equals("Count words")) {
            event.reply("Words: " + event.getTarget().getContentRaw().split("\\s+").length).queue();
        }
    }
}


ContextMenuBot.kt

object ContextMenuBot : ListenerAdapter() {
    override fun onUserContextInteraction(event: UserContextInteractionEvent) {
        if (event.name == "Get user avatar") {
            event.reply("Avatar: " + event.target.effectiveAvatarUrl).queue()
        }
    }

    override fun onMessageContextInteraction(event: MessageContextInteractionEvent) {
        if (event.name == "Count words") {
            event.reply("Words: " + event.target.contentRaw.split(Regex("\\s+")).size).queue()
        }
    }
}






COMPONENT INTERACTIONS¶

To add components to a message you can use up to 5 ActionRows.

You can add multiple ActionRows with either setComponents or addComponents. For
the common case of a single ActionRow you can also use
setActionRow(Component...) or addActionRow(Component...).

Each ActionRow can hold up to a certain amount of components:

 * 5 Buttons
 * 1 Select Menu (Dropdown)
 * 1 Text Input (Restricted to Modals)

These component interactions offer 4 response types:

 * Reply
 * Deferred Reply
 * Edit Message
 * Deferred Edit Message

The reply and deferred reply responses are identical to the Slash-Commands
response types. However, these new edit response types are used to update the
existing message the component is attached to. If you just want to acknowledge
that the component was successfully interacted with, you can simply call
deferEdit() without any further updates, which will prevent the interaction from
failing on the user side.

To properly use an interactive component, you need to use the Component ID (aka
Custom ID). This ID can also be used to then identify which component was
pressed by the user.

Such Component ID is provided by getComponentId() on every Component
Interaction.

Keep in mind that these Component IDs must be unique across all components in
one message.


BUTTONS¶

Each button can be enabled or disabled, have a specific style, label, and emoji:



HANDLING BUTTONINTERACTIONEVENT¶

When a user presses one of these buttons, you will receive a
ButtonInteractionEvent for the respective interaction.

Each non-link button requires such an ID in order to be used.

Example

JavaKotlin

public class HelloBot extends ListenerAdapter {
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        if (event.getName().equals("hello")) {
            event.reply("Click the button to say hello")
                .addActionRow(
                  Button.primary("hello", "Click Me"), // Button with only a label
                  Button.success("emoji", Emoji.fromFormatted("<:minn:245267426227388416>"))) // Button with only an emoji
                .queue();
        } else if (event.getName().equals("info")) {
            event.reply("Click the buttons for more info")
                .addActionRow( // link buttons don't send events, they just open a link in the browser when clicked
                    Button.link("https://github.com/discord-jda/JDA", "GitHub")
                      .withEmoji(Emoji.fromFormatted("<:github:849286315580719104>")), // Link Button with label and emoji
                    Button.link("https://docs.jda.wiki/", "Javadocs")) // Link Button with only a label
                .queue();
        }
    }

    @Override
    public void onButtonInteraction(ButtonInteractionEvent event) {
        if (event.getComponentId().equals("hello")) {
            event.reply("Hello :)").queue(); // send a message in the channel
        } else if (event.getComponentId().equals("emoji")) {
            event.editMessage("That button didn't say click me").queue(); // update the message
        }
    }
}


object HelloBot: ListenerAdapter() {
    override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
        if (event.name == "hello") {
            event.reply("Click the button to say hello")
                .addActionRow(
                    Button.primary("hello", "Click Me"),  // Button with only a label
                    Button.success("emoji", Emoji.fromFormatted("<:minn:245267426227388416>"))) // Button with only an emoji
                .queue()
        } else if (event.name == "info") {
            event.reply("Click the buttons for more info")
                .addActionRow( // link buttons don't send events, they just open a link in the browser when clicked
                    Button.link("https://github.com/discord-jda/JDA", "GitHub")
                        .withEmoji(Emoji.fromFormatted("<:github:849286315580719104>")),  // Link Button with label and emoji
                    Button.link("https://docs.jda.wiki/", "Javadocs")) // Link Button with only a label
                .queue()
        }
    }

    override fun onButtonInteraction(event: ButtonInteractionEvent) {
        when (event.componentId) {
            "hello" -> event.reply("Hello :)").queue() // send a message in the channel
            "emoji" -> event.editMessage("That button didn't say click me").queue() // update the message
        }
    }
}






SELECT MENUS (DROPDOWNS)¶

Select Menus can be disabled.

It's possible to set the minimum and maximum number of options to be selected.

There are two implementations for SelectMenus:

 * StringSelectMenu supports custom string choices
 * EntitySelectMenu derives its choices from mentionable entities (such as
   Users, Channels, etc)

STRING SELECT MENUS¶

String Select Menus support up to 25 options.

Each option can have its own label, description, and emoji. There can be
multiple options selected and set as default.



ENTITY SELECT MENUS¶

Entity Select Menus do not support custom choices. Instead, they derive their
choices from mentionable Discord entities such as Users, Channels, etc.



You can specify which entity types you wish to appear as choices by specifying
the SelectTargets in EntitySelectMenu.create. If you create an entity select
menu with channel type targets, the same menu may not utilize user or role
select targets, and vice versa.

You can limit channel selections to specific channel types by using the
setChannelTypes method on EntitySelectMenu.Builder.

Info

These Select Menus do not support setting a custom list of options or
customizing the appearance in any way. They always show the complete list of
possible entities for the specified types.

HANDLING SELECT MENUS¶

When a user selects their options from a dropdown and submits their choices, you
will receive either one of the following for the respective interaction:

 * A StringSelectInteractionEvent for a String Select Menu interaction
 * An EntitySelectInteractionEvent for an Entity Select Menu interaction

Both interaction events provide the values that were selected by the user.

Example String Select Handling

JavaKotlin

public class StringDropdownBot extends ListenerAdapter {
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        if (event.getName().equals("food")) {
            event.reply("Choose your favorite food")
                .addActionRow(
                    StringSelectMenu.create("choose-food")
                      .addOption("Pizza", "pizza", "Classic") // SelectOption with only the label, value, and description
                      .addOptions(SelectOption.of("Hamburger", "hamburger") // another way to create a SelectOption
                            .withDescription("Tasty") // this time with a description
                            .withEmoji(Emoji.fromUnicode("\uD83C\uDF54")) // and an emoji
                            .withDefault(true)) // while also being the default option
                    .build())
                .queue();
        }
    }

    @Override
    public void onStringSelectInteraction(StringSelectInteractionEvent event) {
        if (event.getComponentId().equals("choose-food")) {
            event.reply("You chose " + event.getValues().get(0)).queue();
        }
    }
}


object StringDropdownBot : ListenerAdapter() {
    override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
        if (event.name == "food") {
            val selectMenu = StringSelectMenu.create("choose-food")
                .addOption("Pizza", "pizza", "Classic") // SelectOption with only the label, value, and description
                .addOptions(SelectOption.of("Hamburger", "hamburger") // another way to create a SelectOption
                    .withDescription("Tasty") // this time with a description
                    .withEmoji(Emoji.fromUnicode("\uD83C\uDF54")) // and an emoji
                    .withDefault(true)) // while also being the default option
                .build()

            event.reply("Choose your favorite food")
                .addActionRow(selectMenu)
                .queue()
        }
    }

    override fun onStringSelectInteraction(event: StringSelectInteractionEvent) {
        if (event.componentId == "choose-food") {
            event.reply("You chose " + event.values[0]).queue()
        }
    }
}





Example Entity Select Handling

JavaKotlin

public class EntityDropdownBot extends ListenerAdapter {
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        if (event.getName().equals("highfive")) {
            event.reply("Choose the user to high-five")
                .addActionRow(
                    EntitySelectMenu.create("choose-user", SelectTarget.USER)
                    .build())
                .queue();
        }
    }

    @Override
    public void onEntitySelectInteraction(EntitySelectInteractionEvent event) {
        if (event.getComponentId().equals("choose-user")) {
            // Mentions provide the selected values using familiar getters
            List<User> users = event.getMentions().getUsers();
            event.reply("You high-fived " + users.get(0).getAsMention()).queue();
        }
    }
}


object EntityDropdownBot : ListenerAdapter() {
    override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
        if (event.name == "food") {
            val selectMenu = EntitySelectMenu.create("choose-user", SelectTarget.USER)
                .build()

            event.reply("Choose the user to high-five")
                .addActionRow(selectMenu)
                .queue()
        }
    }

    override fun onEntitySelectInteraction(event: EntitySelectInteractionEvent) {
        if (event.componentId == "choose-user") {
            // Mentions provide the selected values using familiar getters
            val users = event.mentions.users;
            event.reply("You high-fived " + users.first().asMention).queue()
        }
    }
}






MODALS¶

Modals are pop-ups that appear in a user's Discord client.



Similarly to messages, Modals can contain up to 5 ActionRows, although the only
component that can be put inside Modals at the moment (TextInput) takes up a
whole ActionRow.


REPLYING WITH A MODAL¶

Example

JavaKotlin

public class SupportCommand extends ListenerAdapter {
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        if (event.getName().equals("modmail")) {
            TextInput subject = TextInput.create("subject", "Subject", TextInputStyle.SHORT)
                    .setPlaceholder("Subject of this ticket")
                    .setMinLength(10)
                    .setMaxLength(100) // or setRequiredRange(10, 100)
                    .build();

            TextInput body = TextInput.create("body", "Body", TextInputStyle.PARAGRAPH)
                    .setPlaceholder("Your concerns go here")
                    .setMinLength(30)
                    .setMaxLength(1000)
                    .build();

            Modal modal = Modal.create("modmail", "Modmail")
                    .addComponents(ActionRow.of(subject), ActionRow.of(body))
                    .build();

            event.replyModal(modal).queue();
        }
    }
}


object SupportCommand : ListenerAdapter() {
    override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
        if (event.name == "modmail") {
            val subject = TextInput.create("subject", "Subject", TextInputStyle.SHORT)
                .setPlaceholder("Subject of this ticket")
                .setMinLength(10)
                .setMaxLength(100) // or setRequiredRange(10, 100)
                .build()

            val body = TextInput.create("body", "Body", TextInputStyle.PARAGRAPH)
                .setPlaceholder("Your concerns go here")
                .setMinLength(30)
                .setMaxLength(1000)
                .build()

            val modal = Modal.create("modmail", "Modmail")
                .addComponents(ActionRow.of(subject), ActionRow.of(body))
                .build()

            event.replyModal(modal).queue()
        }
    }
}






HANDLING MODALINTERACTIONEVENT¶

When the user clicks the "Submit" button on the Modal, you will receive an
ModalInteractionEvent, containing all the values the user put in it.

Warning

Acknowledging a ModalInteractionEvent is necessary. Failing to respond to the
event will not close it on the user's client, and will show them an error.

Info

If the Modal originated from a Component-Interaction (Buttons, SelectMenus), it
is possible to acknowledge the interaction using an edit to the original Message
using editMessage() or similar.

Example

JavaKotlin

public class ModalListener extends ListenerAdapter {
    @Override
    public void onModalInteraction(@Nonnull ModalInteractionEvent event) {
        if (event.getModalId().equals("modmail")) {
            String subject = event.getValue("subject").getAsString();
            String body = event.getValue("body").getAsString();

            createSupportTicket(subject, body);

            event.reply("Thanks for your request!").setEphemeral(true).queue();
        }
    }
}


object ModalListener : ListenerAdapter() {
    override fun onModalInteraction(event: ModalInteractionEvent) {
        if (event.modalId == "modmail") {
            val subject = event.getValue("subject") ?: return
            val body = event.getValue("body") ?: return

            createSupportTicket(subject, body)

            event.reply("Thanks for your request!").setEphemeral(true).queue()
        }
    }
}






RESOURCES

 * Javadocs
 * GitHub (JDA)
 * GitHub (Wiki)
 * Discord API Docs


COMMUNITY

 * Discord Server
 * Open Collective

Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and Wiki
Contributors