-
-
Notifications
You must be signed in to change notification settings - Fork 90
Component IDs
Component IDs are, among other things, used to carry information through an event.
For example the user who triggered a slash command or details to the query, which are then stored "inside" a button to retrieve the associated information back when it is clicked. By that, it can be implemented for example that a button can only be clicked by the original message author.
Component IDs in our system have to follow certain rules, which are explained in detail later.
Our API offers two options to work with component IDs.
If your command happens to extend SlashCommandAdapter
(our helper class), you can easily generate valid component IDs using the helper method generateComponentId
. The method optionally accepts additional strings which can be used to carry information through the event.
For example, let us suppose you want to create a button that can only be clicked by the user who also triggered the command initially. Then you would create your buttons as such:
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
event.reply("Do you want to continue?")
.addActionRow(
Button.of(ButtonStyle.SUCCESS, generateComponentId(event.getMember().getId()), "Yes"),
Button.of(ButtonStyle.DANGER, generateComponentId(event.getMember().getId()), "No")
.queue();
)
and then later, when retrieving the ButtonClickEvent
, you get back the list of arguments:
@Override
public void onButtonClick(@NotNull ButtonClickEvent event, @NotNull List<String> args) {
// Ignore if another user clicked the button
String userId = args.get(0);
if (!userId.equals(Objects.requireNonNull(event.getMember()).getId())) {
event.reply("Sorry, but only the user who triggered the command can use these buttons.")
.setEphemeral(true)
.queue();
return;
}
event.reply("Nice!").queue();
}
Alternatively, commands can also implement the interface SlashCommand
directly, instead of using the helper class SlashCommandAdapter
. In that case, in order to use component IDs, one has to do some basic setup first.
Component IDs can be generated by using a ComponentIdGenerator
, which the command system will provide to the command by calling the acceptComponentIdGenerator
method, that each command has to implement, once during setup.
So as first step, you have to memorize this generator:
public final class MyCommand implements SlashCommand {
private ComponentIdGenerator componentIdGenerator;
...
@Override
public void acceptComponentIdGenerator(@NotNull ComponentIdGenerator generator) {
componentIdGenerator = generator;
}
}
After that is done, component IDs can be generated easily as well, for example:
componentIdGenerator.generate(new ComponentId(getName(), ...), Lifespan.REGULAR);
where ...
are the optional arguments you want to pass.
The previous button example would now look like:
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
event.reply("Do you want to continue?")
.addActionRow(
Button.of(
ButtonStyle.SUCCESS,
componentIdGenerator.generate(
new ComponentId(getName(), Arrays.asList(event.getMember().getId()),
Lifespan.REGULAR),
"Yes"),
Button.of(
ButtonStyle.DANGER,
componentIdGenerator.generate(
new ComponentId(getName(), Arrays.asList(event.getMember().getId()),
Lifespan.REGULAR),
"No")
.queue();
)
Component IDs can have different lifespans. If a component ID has expired, associated events can not be used anymore. For example, a button can not be clicked anymore.
The default lifespan to use is Lifespan.REGULAR
. IDs associated with this lifespan will generally be valid long enough for most use cases (multiple days). However, in some cases it might be necessary to create IDs that will not expire. Lifespan.PERMANENT
can be used for that, but do not overuse it.
Note that the lifetime of a component ID is refreshed each time it is used. Hence, IDs only expire if they have not been used by anyone for a long time.
Technically, for JDA, component IDs could be any text, as long as it is:
- unique among other components in the event
- not longer than 100 characters
To overcome those limitations and ease the workflow for users, our API generates component IDs as UUIDs (which are unique by default).
In order to attach arbitrary information (that also might be longer than just 100 characters) to the component ID, we store the actual information (the payload) externally in a database instead of stuffing it into the component ID itself. So while the actual component ID is just a UUID, we associate it to the corresponding information in a database.
See Component ID Store for more details on the underlying system and the implementation.