-
Notifications
You must be signed in to change notification settings - Fork 3
Interactions
This guide will show you how to create and handle interactions (excluding commands).
- Creating Buttons
- Listening to Buttons
- Creating Select Menus
- Listening to Select Menus
- Using Modals
- Using InteractionMenus
In Colossus, buttons are created using the BaseButton class. There are several way to instantiate a button:
-
new BaseButton(button)
Creates a simple button with no functionality. Useful for e.g. link buttons.-
Buttonbutton - A JDA Button object. Refer to JDA documentation for more info. Example:Button.secondary("createticket", "Create Ticket")
-
-
new BaseButton(button, onClick)
Creates a button with a consumer. Anyone who can see this button, can use it.-
Buttonbutton - A JDA Button object. -
CommandConsumer<ButtonClickEvent>onClick - The code to execute in case the button is clicked, with the click event (subclass of RepliableEvent) provided as parameter. Example:event -> event.reply("Clicked!")
-
-
BaseButton.predicate(predicate, ifFalse, button, onClick)
Creates a button which can only be executed if the provided predicate returns true.-
CommandPredicate<ButtonClickEvent>predicate - The predicate to check. Example:event -> event.getMember().isOwner() -
CommandConsumer<ButtonClickEvent>ifFalse - The code to execute in case the button is clicked and the predicate returns false. -
Buttonbutton - A JDA Button object. -
CommandConsumer<ButtonClickEvent>onClick - The code to execute in case the button is clicked and the predicate returns true.
-
-
BaseButton.user(userId, button, onClick)
Creates a button which can only be used by a specific user, otherwise returns an error message indicating they are not allowed to use this button.-
LonguserId - The ID of the user which may use this button -
Buttonbutton - A JDA Button object -
CommandConsumer<ButtonClickEvent>onClick - The code to execute in case the button is clicked and the executing user's ID matchesuserId.
-
-
BaseButton.group(userIds, button, onClick)
Creates a button which can only be used by a specific few users, otherwise returns an error message indicating they are not allowed to use this button.-
Long[]userIds - The IDs of the users who may use this button -
Buttonbutton - A JDA Button object -
CommandConsumer<ButtonClickEvent>onClick - The code to execute in case the button is clicked and the executing user's ID is insideuserIds.
-
Hint
You can throwCommandExceptions inside ofCommandPredicateandCommandConsumer, and Colossus will return an error embed to the user.
There are several ways to listen to buttons. The easiest way is to use the PresetBuilder, which will register listeners automatically.
You can add buttons to a PresetBuilder using the PresetBuilder#addButtons(BaseButton...) method.
A call to this method will create a ButtonRow, which is a row of buttons. A row of buttons can contain up to 5 buttons.
If you provide more than 5 buttons, multiple rows of buttons will be created.
Once you reply to a RepliableEvent using a PresetBuilder, listeners for the buttons will be automatically registered.
If, for some reason, you do not have access to a RepliableEvent object, you can use the PresetBuilder#addComponentRowListeners method to register the listeners manually.
Example:
BaseButton button = new BaseButton(
Button.primary("test", "Test"), // create a button with ID "test" and label "Test"
clickEvent -> clickEvent.reply("Clicked!", true) // reply "Clicked!" in an ephemeral message to users who click the button
);
PresetBuilder pb = new PresetBuilder()
.setTitle("Buttons")
.setDescription("Click the button below!")
.addButtons(button); // add the button to a PresetBuilder
event.reply(pb); // reply to the RepliableEvent with this PresetBuilderResult:

Please note: Buttons registered this way will stop working after a bot restart.
They will also be destroyed after 24 hours by default. This time period can be modified using ColossusBuilder#setDefaultComponentListenerExpirationTime.
If you want to listen to buttons permanently, please keep reading:
There are two key differences between this approach and the approach described above:
- These listeners will be registered permanently, even after a bot restart.
- These listeners are not bound to a specific instance of a message, the other approach is. This means that any button with the provided ID will execute the given code.
To start listening, you need to create a static method annotated with @ButtonListener and precisely one parameter of type ButtonClickEvent.
This method may live in any class.
The method body will be executed immediately after a button with the provided ID is clicked.
The listener will be automatically registered using ColossusBuilder#scanPackage.
Example:
@Override
public void run(SlashCommandEvent event) throws CommandException {
PresetBuilder pb = new PresetBuilder()
.setTitle("Manage Ticket")
.setDescription("Use the buttons below to manage your ticket.")
.addButtons(Button.danger("close", "Close Ticket")); // add the button to a PresetBuilder
event.reply(pb);
}
@ButtonListener("close")
private static void onCloseButtonClick(ButtonClickEvent event) {
event.reply("Ticket closed", true);
}Result:

Instead of checking if the button ID exactly matches, you may also choose to check if the button ID starts with a certain string.
This functionality can be enabled using the startsWith parameter inside the @ButtonListener annotation.
This feature may be useful for storing data like IDs, primary/foreign keys, etc. inside button IDs.
Example:
@Override
public void run(SlashCommandEvent event) throws CommandException {
PresetBuilder pb = new PresetBuilder()
.setTitle("Manage Ticket")
.setDescription("Use the buttons below to manage your ticket.")
.addButtons(Button.danger("close-"+event.getUser().getId(), "Close Ticket"));
event.reply(pb);
}
@ButtonListener(value = "close-", startsWith = true)
private static void onCloseButtonClick(ButtonClickEvent event) {
String userId = event.getButtonId().split("-")[1];
event.reply("Ticket closed for user <@"+userId+">", true);
}Result:

Select Menus can be created using the BaseSelectMenu class. It works in a very similar way to buttons.
-
new BaseSelectMenu(selectMenu, onSubmit)
Creates a select menu with a consumer. Anyone who can see this select menu, can use it.-
SelectMenuselectMenu - A JDA SelectMenu object. Refer to JDA documentation for more info. Example:StringSelectMenu.create("food").addOption("Pizza", "pizza").build() -
CommandConsumer<SelectMenuEvent>onSubmit - The code to execute every time the select menu is used, with the submit event (subclass of RepliableEvent) provided as parameter. Example:event -> event.reply("Selected "+event.getValues().size()+" options!")
-
-
BaseSelectMenu.predicate(predicate, ifFalse, selectMenu, onSubmit)
Creates a select menu which can only be executed if the provided predicate returns true.-
CommandPredicate<SelectMenuEvent>predicate - The predicate to check. Example:event -> event.getMember().isOwner() -
CommandConsumer<SelectMenuEvent>ifFalse - The code to execute in case the select menu is used and the predicate returns false. -
SelectMenuselectMenu - A JDA SelectMenu object. -
CommandConsumer<SelectMenuEvent>onSubmit - The code to execute every time the select menu is used and the predicate returns true.
-
-
BaseSelectMenu.user(userId, selectMenu, onSubmit)
Creates a select menu which can only be used by a specific user, otherwise returns an error message indicating they are not allowed to use this select menu.-
LonguserId - The ID of the user which may use this select menu -
SelectMenuselectMenu - A JDA SelectMenu object -
CommandConsumer<SelectMenuEvent>onSubmit - The code to execute in case the select menu is used and the executing user's ID matchesuserId.
-
-
BaseSelectMenu.group(userIds, selectMenu, onSubmit)
Creates a select menu which can only be used by a specific few users, otherwise returns an error message indicating they are not allowed to use this select menu.-
Long[]userIds - The IDs of the users who may use this button -
SelectMenuselectMenu - A JDA SelectMenu object -
CommandConsumer<SelectMenuEvent>onSubmit - The code to execute in case the select menu is used and the executing user's ID is insideuserIds.
-
Hint
You can throwCommandExceptions inside ofCommandPredicateandCommandConsumer, and Colossus will return an error embed to the user.
Listening to select menus is similar to listening to buttons.
You can add select menus to a PresetBuilder using the PresetBuilder#addComponentRow(ComponentRow) method.
Once you reply to a RepliableEvent using a PresetBuilder, listeners for the select menus will be automatically registered.
If, for some reason, you do not have access to a RepliableEvent object, you can use the PresetBuilder#addComponentRowListeners method to register the listeners manually.
Example:
BaseSelectMenu selectMenu = new BaseSelectMenu(
StringSelectMenu.create("food")
.addOption("Pizza", "pizza", Emoji.fromUnicode("π"))
.addOption("Burger", "burger", Emoji.fromUnicode("π"))
.addOption("Pasta", "pasta", Emoji.fromUnicode("π"))
.addOption("Salad", "salad", Emoji.fromUnicode("π₯"))
.build(),
submitEvent -> submitEvent.reply("You selected "+submitEvent.getValue(), true)
);
PresetBuilder pb = new PresetBuilder()
.setTitle("Select Food")
.setDescription("Please select the food that you would like to order below.")
.addComponentRow(selectMenu);
event.reply(pb);Result:

Please note: Select Menus registered this way will stop working after a bot restart.
They will also be destroyed after 24 hours by default. This time period can be modified using ColossusBuilder#setDefaultComponentListenerExpirationTime.
If you want to listen to select menus permanently, please keep reading:
There are two key differences between this approach and the approach described above:
- These listeners will be registered permanently, even after a bot restart.
- These listeners are not bound to a specific instance of a message, the other approach is. This means that any select menu with the provided ID will execute the given code.
To start listening, you need to create a static method annotated with @SelectMenuListener and precisely one parameter of type SelectMenuEvent.
This method may live in any class.
The method body will be executed immediately after a select menu with the provided ID is used.
The listener will be automatically registered using ColossusBuilder#scanPackage.
Example:
@Override
public void run(SlashCommandEvent event) throws CommandException {
BaseSelectMenu selectMenu = new BaseSelectMenu(
StringSelectMenu.create("food")
.addOption("Pizza", "pizza", Emoji.fromUnicode("π"))
.addOption("Burger", "burger", Emoji.fromUnicode("π"))
.addOption("Pasta", "pasta", Emoji.fromUnicode("π"))
.addOption("Salad", "salad", Emoji.fromUnicode("π₯"))
.build()
);
PresetBuilder pb = new PresetBuilder()
.setTitle("Select Food")
.setDescription("Please select the food that you would like to order below.")
.addComponentRow(selectMenu);
event.reply(pb);
}
@SelectMenuListener("food")
private static void onFoodPicked(SelectMenuEvent event) {
event.reply("You selected "+event.getValue(), true);
}Result:

Instead of checking if the select menu ID exactly matches, you may also choose to check if the select menu ID starts with a certain string.
This functionality can be enabled using the startsWith parameter inside the @SelectMenuListener annotation.
This feature may be useful for storing data like IDs, primary/foreign keys, etc. inside select menu IDs.
You can show a modal to a user using the RepliableEvent#reply(Modal, CommandConsumer<ModalSubmitEvent>) method.
The modal will be displayed to the user, and the code inside the CommandConsumer will be executed when the user presses the "Submit" button.
Example:
event.reply(
Modal.create("entername", "Enter Name")
.addActionRow(
TextInput.create("name", "Name", TextInputStyle.SHORT)
.setPlaceholder("Enter your name")
.setMaxLength(50)
.build()
)
.build(),
submitEvent -> {
event.reply("You entered: "+submitEvent.getValue("name").getAsString(), true);
}
);Result:

Colossus provides a way to create and manage menus, which are a combination of embeds, buttons, select menus, and modals.
To send a menu, simply use RepliableEvent#reply(InteractionMenu) - event.reply(menu).
We also provide a few pre-made menus, which can be used to create a rich menu with a single line of code.
Presents the user with an option to either go through with an action or cancel it. Create one using:
-
new ConfirmMenu(description, confirmedDescription, ephemeral, confirmAction)
-
Stringdescription - The description of the embed to confirm the action -
StringconfirmedDescription - The description of the embed after the user has clicked the Confirm button -
booleanephemeral - Whether this menu should be sent as an ephemeral message -
CommandConsumer<ButtonClickEvent>confirmAction - Code to perform when the user has clicked the Confirm button
-
Preview:

An advanced menu to browse custom defined pages and (nested) subpages using tabs. Create one using TabMenuBuilder.
Try it out by using the default help command. You can find the code for the command here.
A menu to switch between different pages using a select menu. This can be useful for e.g. a settings command.
To create one, you will need to get a list of SelectRowOption first. These represent all the pages in the select menu.
SelectRowOption cardOption = new SelectRowOption(
"Credit Card", "Edit card details.", Emoji.fromUnicode("π³"), selectEvent -> {
BotUser user = selectEvent.getUserEntity();
return new PresetBuilder().setDescription("Current card number: "+user.getCardNumber());
}
);
// Please note: There are simpler constructors available for SelectRowOption. Refer to the class for more info.Then, create a SelectRowMenu using the SelectRowMenuBuilder.
SelectRowMenu menu = new SelectRowMenuBuilder()
.setStartMessage(new PresetBuilder("Settings", "Modify user settings."))
.setPlaceholder("Pick a setting...")
.addOptions(cardOption)
.build();
menu.send(event);Preview:

A menu to scroll through different pages using buttons. To create one, create a list of PresetBuilder, representing the pages.
Optionally, you can provide a page number to start on. By default, this will be the first page.
event.reply(new ScrollPageMenu(pages));Preview of a simple ScrollPageMenu:

You can create your own menu by implementing the InteractionMenu interface (and optionally InteractionMenuBuilder as well).
Feel free to take a look at the code of the pre-made menus to get an idea of how to create your own and to get inspiration.