-
Notifications
You must be signed in to change notification settings - Fork 2
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.-
Button
button - 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.-
Button
button - 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. -
Button
button - 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.-
Long
userId - The ID of the user which may use this button -
Button
button - 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 -
Button
button - 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 throwCommandException
s inside ofCommandPredicate
andCommandConsumer
, 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 PresetBuilder
Result:
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.-
SelectMenu
selectMenu - 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. -
SelectMenu
selectMenu - 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.-
Long
userId - The ID of the user which may use this select menu -
SelectMenu
selectMenu - 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 -
SelectMenu
selectMenu - 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 throwCommandException
s inside ofCommandPredicate
andCommandConsumer
, 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)
-
String
description - The description of the embed to confirm the action -
String
confirmedDescription - The description of the embed after the user has clicked the Confirm button -
boolean
ephemeral - 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.