Releases: Kaktushose/jda-commands
v4.0.0-beta.4 | Bug Fixes & Enhancements
Overview
This is a small followup release for beta.3 which fixes some bugs and has some smaller enhancements
1) New Features
- N/A
2) Changes
Components from different classes (#147)
You can now attach components that are defined in a different class. Be aware that these components will always be runtime-independent:
event.with().components(MyComponents.class, "onYes", "onNo").reply("Do you want to proceed?");
Message Builder Callback (#156)
You can now access the underlying MessageCreateBuilder
of a ConfigurableReply
via a callback:
event.with().builder(builder -> builder.setFiles(myFile)).reply("Hello World!");
Improved AutoComplete
Auto complete handlers now also work with method references:
@SlashCommand("favourite fruit")
public void fruitCommand(CommandEvent event, String fruit) {
event.reply("You've chosen: %s", fruit);
}
@AutoComplete("fruitCommand")
public void onFruitAutoComplete(AutoCompleteEvent event) {
event.replyChoices(...);
}
See the javadocs for details
3) Bug Fixes
- fixed wrong default value in
TextInput
(#155) - fixed that
SelectOptions
didn't register (694f657)
4) Internal changes
- jda-commands now uses gradle as its build system and is structured as a multi-module project. This has no effects on the end user
You can find the complete changelog here.
Note
While we are working on a new Wiki check out the JavaDocs which got heavily improved.
Maven
Warning
JDA-Commands is now distributed via Maven Central. Thus, the domain changed to io.github.kaktushose
. JitPack is longer required
<dependency>
<groupId>io.github.kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>4.0.0-beta.4</version>
</dependency>
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation("io.github.kaktushose:jda-commands:v4.0.0-beta.4")
}
v4.0.0-beta.3 | Refactoring
Overview
This release brings in a de facto rewrite of jda-commands. While the user API remained mostly unaffected, the backbone of jda-commands underwent a major rewrite.
Important
From now on, jda-commands will use the latest Java release. For the time being this is Java 23.
With Java 23, we can heavily benefit from modern features like virtual threads, records, sealed classes, pattern matching or markdown documentation.
New Dispatching Model
In older versions we had a concept called InteractionRuntime
, which only purpose was to store instances of interaction classes. Every interaction was then executed on the JDA MainWS-ReadThread
. We expanded this concept and gave every interaction execution a new virtual thread. The now-called Runtime
delegates the jda events to their corresponding EventHandlers
and manages the used virtual threads.
A new Runtime
is created each time a SlashCommandInteractionEvent
, GenericContextInteractionEvent
or CommandAutoCompleteInteractionEvent
is provided by JDA or if an interaction is marked as independent.
Runtimes are executed in parallel, but events are processed sequentially by each runtime.
Every EventHandler
called by this Runtime
is executed in its own virtual thread, isolated from the runtime one.
See ExpirationStrategy
for details when a Runtime
will close.
1) New Features
Java Platform Module System (JPMS) support
JDA-Commands now ships with a module-info.java
file, which enables fluent integration with JPMS.
For projects that aren't using the so called "module-path" this change doesn't have an impact.
All packages belonging to the user API are listed there, making this file a perfect references for which parts of the framework are internal or not. Also, only classes exported by this file have java docs publicly accessible.
Reply API
The reply API had some small changes. The event classes now only have the reply(content)
methods. If you want to apply settings or add components, you first have to call with()
. The withButtons()
and withSelectMenus()
methods have been combined into the components()
method.
Example:
event.with().ephemeral(true).components("onConfirm", "onCancel").reply("Are you sure?");
2) Changes
Although we are already in beta state and thus try to avoid breaking changes, many smaller breaking changes were needed. We've decided to set a clean cut with this release instead of marking everything as deprecated and changing things gracefully.
Please let us know if you miss any functionality that was previously available.
JDA-Commands Builder
The start methods of JDACommands
now are simplified to just the minimum and all additionally configuration have to be made through the builder returned by JDACommands#builder(...)
.
Events
The events AutoCompleteEvent
, CommandEvent
, ComponentEvent
and ModalEvent
were all moved to com.github.kaktushose.jda.commands.dispatching.events.interactions
.
ReplyConfig
The fields keepComponents
, editReply
and ephemeral
were removed from the respective interaction annotations. From now on, you have to use the @ReplyConfig
annotation. You can annoate either classes or methods. Example:
@ReplyConfig(ephemeral = true)
@SlashCommand("example")
public void onCommand(CommandEvent event) {...}
@StaticInstance
This functionality got removed. Declare your variables as static instead or store them properly elsewhere.
@Implementation
Warning
This functionality got removed for the moment. With the beta.4 release we will introduce proper DI.
Middlewares
TypeAdapter#parse(Object, Context)
->TypeAdapter#apply(Object, GenericInteractionCreateEvent)
Middleware#execute(Context)
->Middleware#accept(InvocationContext)
Validator#validate(Object, Object, Context)
->Validator#apply(Object, Object, InvocationContext)
ErrorMessageFactory
The method signatures have changed. The methods now get the ErrorContext
and the error specific arguments, e.g. remaining cooldown.
PermissionsProvider
getUsersWithPermission
andgetRolesWithPermission
methods were removed- Context got replaced with InvocationContext in
hasPermission
methods
GuildScopeProvider
GuildScopeProvider#getGuildsForCommand(CommandData)
->GuildScopeProvider#apply(CommandData)
Other changes
SlashCommand.CommandScope
->com.github.kaktushose.jda.commands.annotations.interactions.CommandScope
com.github.kaktushose.jda.commands.data
->com.github.kaktushose.jda.commands.embeds
ErrorMessageFactory
,DefaultErrorMessageFactory
andJsonErrorMessageFactory
were moved tocom.github.kaktushose.jda.commands.embeds.error
KeyValueStore
was moved tocom.github.kaktushose.jda.commands.dispatching.context
3) Bug Fixes
- N/A
4) Internal changes
-
The
com.github.kaktushose.jda.commands.reflect
package was replaced with thecom.github.kaktushose.jda.commands.definitions
package, see the Javadocs for details -
Many classes have become
final
and / or were marked asApiStatus.Internal
, reducing the API surface
You can find the complete changelog here.
Note
While we are working on a new Wiki check out the JavaDocs which got heavily improved.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-beta.3</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-beta.3'
}
v4.0.0-beta.2 | Static Interactions and QoL changes
Overview
This release introduces many small QoL features as well as lots of bug fixes.
Static Interactions
You can now disable the request-scoped instances by annotating the interaction class with StaticInstance
. This will create one instance of the class that will be used until jda-commands shuts down.
In the following example every global counter
command will use the same counter
variable. Thus, if you have 2 commands active, pressing the button on the first command will also increase the count for the second command.
@Interaction
@StaticInstance
public class StaticTest {
private int counter;
@SlashCommand("global counter")
public void onCommand(CommandEvent event) {
event.withButtons("onButton").reply("Global counter");
}
@Button("click me")
public void onButton(ComponentEvent event) {
counter++;
event.reply("counter: " + counter);
}
}
MessageBuilder Components
In the past components were only usable in combination with commands. However, sometimes you want to add a component to a MessageBuilder.
From now on you can use JDACommands#getButton(String id)
or respectively JDACommands#getSelectMenu(String id)
to access a component outside of commands. The component can be defined anywhere inside the project. The id consists of the simple class name and the method name, e.g. VoteButtons.onUpvote
.
Example:
@Interaction
@StaticInstance
public class ComponentAPITest extends ListenerAdapter {
@Override
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (!event.getMessage().getContentDisplay().startsWith("!greet")) {
return;
}
var builder = new MessageCreateBuilder().setContent("Hello").addActionRow(jdaCommands.getButton("ComponentAPITest.onButton"));
event.getChannel().sendMessage(builder.build()).queue();
}
@Button("Greet me!")
public void onButton(ComponentEvent event) {
event.editReply(false).reply("Hello %s", event.getUser());
}
}
Please note that the onButton
method doesn't need to be defined in the same class it is referred in. This was only done here to keep the example short and sweet. Also be aware that the keepComponents
feature doesn't work in this case, because it requires request-scoped instances. Thus you'd need to reattach the button if you set editReply to true.
1) New Features
-
added the
skipIndexing
boolean to@Produces
annotation. If set totrue
jda-commands will ignore this producer method at indexing. This is useful if you wish to register your dependency providers manually by callingDependencyInjector#registerProvider(Object)
. -
Implemented a simple
KeyValueStore
that can be accessed from every event class by callingkv()
2) Changes
-
jda-commands will now ignore any incoming component or modal events that weren't created by jda-commands. However, foreign commands will still create a error message.
-
when starting jda-commands you can now provide your own
DependencyInjector
implementation
3) Bug Fixes
- fixed that
Constraints
didn't get applied to parameters - fixed that using an
EmbedDTO
to reply overwrote components - fixed incorrect parameter name sanitation
- fixed that root commands didn't adopt the configuration of their subcommands
- fixed a bug where
Modals
sometimes didn't get executed
4) Internal changes
- the
SlashCommandUpdater
now uses theGuildReadyEvent
for initial command setup - made the
DependencyInjector
class an interface and added a default implementation - changed the naming scheme of internal ids for defintions and runtimes
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-beta.2</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-beta.2'
}
v4.0.0-beta.1 | Middleware API
Overview
This release comes in with a rework of the Filter API and some minor bug fixes. But most importantly: with this release we were also finally able to end the alpha period and slowly but surely move into a constant and more stable development 🎉
Middleware API
In previous jda-commands versions you were able to add Filters to apply certain business rules on your command executions. The Filter API got removed in the last release and now there is a replacement in the form of middlewares. Essentially, they do the same thing as Filters but with a more generalized approach.
The Filter implementations for cooldowns, permissions and validators were migrated to the new Middleware API. However the UserMuteFilter
and DirectMessageFilter
were obsolte and thus removed.
Middlewares are always executed just before the interaction method will be called. This ensures that definition binding, type adapting and runtime resolving is already done.
Middlewares can choose one of four priorities always running in that order:
- PERMISSIONS (ensures that the PermissionsMiddleware is always executed first)
- HIGH
- NORMAL (default)
- LOW
Here is a quick example on how to add your own middlewares. Let's say we want to prevent all users named Kaktushose
from executing interactions:
@Implementation(priority = Priority.HIGH)
public class KakutsFilter implements Middleware {
@Override
public void execute(Context context) {
if (context.getEvent().getUser().getEffectiveName().equals("Kaktushose")) {
context.setCancelled(MessageCreateData.fromContent("Users named Kaktushose aren't allowed to execute interactions!"));
}
}
}
1) New Features
- Permissions got simplified. Muting users now also works via the
PermissionsProvider
. Furthermore, you can now apply permissions to all types of interactions, not only slash commands.
2) Changes
- Updated a lot of the Javadocs, the Wiki will be updated soon as well. For the moment please refer to the release notes
Context#setCancelled(true)
got changed toContext#setCancelled(MessageCreateData)
. This ensures that there is always an error message to display. Thus,Context#setErrorMessage
got removed andContext#setUncancelled
got introduced to undo the cancelation
3) Bug Fixes
- fixed that other interaction types besides of slash commands had an incorrect display name in error messages
- fixed localization not working for sub commands and sub command groups
- fixed that failing events (e.g. unknown button) couldn't send an error message
- fixed that despite
editReply
set totrue
a new message was always sent
4) Internal changes
- Introduced
GenericComponentDefinition
to remove the type parameters forCommandEvent
undComponentEvent
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-beta.1</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-beta.1'
}
v4.0.0-alpha.5 | Modals & Context Menus
Overview
This release brings in the last two missing interaction types as well as some major internal refactoring, which comes at the cost of some breaking changes.
Modals
Modals are another way of replying to a command event. They will open a popup on the target user's Discord client. You build Modals just like any other interaction, but instead of attaching them to your response like you would do with components, you have to use a seperate reply method:
@Interaction
public class ModalTest {
@SlashCommand(value = "modmail")
public void onCommand(CommandEvent event) {
event.replyModal("onModal");
}
@Modal("Modmail")
public void onModal(ModalEvent event,
@TextInput(label = "Subject of this ticket", style = TextInputStyle.SHORT) String subject,
@TextInput(label = "Your concerns go here") String body) {
createSupportTicket(subject, body);
event.reply("Thanks for your request!");
}
}
Context Menus
Context Menus are a special type of commands that can be invoked on a user or message by right-clicking on them. In jda-commands you use them just like normal slash commands:
@Interaction
public class ContextMenuTest {
@ContextCommand(value = "Count words", type = Command.Type.MESSAGE)
public void onMessageCommand(CommandEvent event, Message message) {
event.reply("Words: " + message.getContentRaw().split("\\s+").length);
}
@ContextCommand(value = "Get user avatar", type = Command.Type.USER)
public void onUserCommand(CommandEvent event, User user) {
event.reply("Avatar: " + user.getEffectiveAvatarUrl());
}
}
1) New Features
- AutoComplete handlers now also accept the top level command name and don't require a full command path anymore
2) Changes
Important
Temporarely removed Filter functionality. This is due to internal changes and preperation of the upcoming Filter API rewrite
- Merged
ButtonEvent
andSelectMenuEvent
intoComponentEvent
Note
CommandEvent
and ComponentEvent
are currently parameterized classes. This can be ignored and will change with the next release
- Removed the
@Optional
annotation. Instead you pass the default value now directly to the@Param
annotation - Events are now only acknowledegd when they passed the execution chain as well as your code completelty
- Added access to the
RuntimeSupversior
via theJDACommands
instance - Renamed
GenericContext
toContext
and removed all of its subtypes except for slash command interactions - Removed key store value functionality from
GenericEvent
- Added access to the success callback and failure callback directly through the event class
3) Bug Fixes
- Fixed a bug where auto complete listeners didn't get registered
4) Internal changes
- Merged
ParserSupervisor
intoDispatcherSupervisor
and thus removed GenericParser and it's subtypes - Merged
ButtonDispatcher
andSelectMenuDispatcher
intoComponentDispatcher
- Renamed:
CommandDefinition
->SlashCommandDefinition
GenericContext
->Context
Context#getInteraction
->Context#getInteractionDefinition
ControllerDefinition
->InteractionControllerDefinition
EphemeralInteraction
->EphemeralInteractionDefinition
GenericInteraction
->GenericInteractionDefinition
- Made
GenericEvent
a subtype ofGenericInteractionCreateEvent
and removed method overload - Added static instance creation to the
RuntimeSupervisor
- Implemented a default implementation of the
reply
method inside theReplyable
interface
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-alpha.5</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-alpha.5'
}
v4.0.0-alpha.4 | Select Menus & Auto Complete
Overview
This release complements the component api with the implementation of Select Menus. Furthermore, autocomplete can now be used as an alternative to Command Choices.
Select Menus
SelectMenus work in the same way as Buttons do. Please refer to the 4.0.0-alpha.3 release notes for further explanation. Below are two brief examples of the use of select menus:
EntitySelectMenus
@Interaction
public class MenuTest {
@SlashCommand("select")
public void onCommand(CommandEvent event) {
event.withSelectMenus("onUserSelect").reply("Select menu demonstration");
}
@EntitySelectMenu(value = SelectTarget.USER, placeholder = "Please select a user")
public void onUserSelect(SelectMenuEvent event, Mentions mentions) {
event.reply("You selected %s", mentions.getMembers().get(0).getAsMention());
}
StringSelectMenus
@Interaction
public class MenuTest {
@SlashCommand("select")
public void onCommand(CommandEvent event) {
event.withSelectMenus("onStringSelect").reply("Select menu demonstration");
}
@StringSelectMenu("What's your favourite food?")
@SelectOption(value = "pizza", label = "Pizza", description = "Who doesn't like pizza?")
@SelectOption(value = "hamburger", label = "Hamburger", description = "yummy.", emoji = "\uD83C\uDF54")
@SelectOption(value = "fries", label = "Fries", description = "quick and good.", isDefault = true)
public void onStringSelect(SelectMenuEvent event, List<String> values) {
event.keepComponents(false).reply("You've selected %s", values.get(0));
}
AutoComplete
When having parameters you can specify up to 25 predefined choices. But sometimes that isn't enough. That's where AutoComplete comes in handy. See the following example for a quick overview over this feature:
@Interaction
public class AutoCompleteTest {
private final String[] words = new String[]{"apple", "apricot", "banana", "cherry", "coconut", "cranberry"};
@SlashCommand("fruit")
public void onCommand(CommandEvent event, @Param("fruit to find") String name) {
event.reply("You selected %s", name);
}
@AutoComplete("fruit")
public void onAutoComplete(AutoCompleteEvent event) {
event.replyChoices(Stream.of(words)
.filter(word -> word.startsWith(event.getValue()))
.map(word -> new Command.Choice(word, word))
.collect(Collectors.toList())
);
}
}
Note, that you can have the same AutoCompleteDefintion assigned to multiple commands but not multiple AutoCompleteDefintions assigned to the same command.
1) New Features
- see above
2) Changes
- moved
dispatching/commands|buttons|menus|autocomplete
todispatching/interactions
- moved
components
todispatching/reply/components
3) Bug Fixes
- Buttons now adopt the ephemeral settings of the controller class
4) Internal changes
- added static instance creation to the
RuntimeSupervisor
- implemented a default implementation of the
reply
method inside theReplyable
interface
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-alpha.4</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-alpha.4'
}
v4.0.0-alpha.3 | Buttons & Localization
Overview
This release brings in Buttons, Localization and some minor changes and improvements.
Buttons
Writing Buttons
Buttons are defined in the same way as Slash Commands are:
@Button("Click Me!")
public void clickMe(ButtonEvent event) {
event.reply("You clicked the button!");
}
As you can see above, you can respond to ButtonEvents in the same way as to CommandEvents. Use event#editReply(boolean)
to decide if you want to send a new message or edit the previous one. By default, this is set to true.
The @Button
annotation has the following fields:
- value (for to the label)
- style (default
ButtonStyle.PRIMARY
) - emoji
- link
- ephemeral (identical to
@SlashCommand
)
Buttons will work for up to 15 mins, after that users cannot interact with the Button anymore. This is an arbitrary time period and might change in the future.
Using Buttons
To attach a button just refer the method name inside the event#withButtons(name)
method.
@Interaction
public class ButtonExample {
private int count;
@SlashCommand(value = "hello", desc = "says hello")
public void onCommand(CommandEvent event) {
event.withButtons("clickMe").reply("Hello World!");
}
@Button(value = "Click Me!", style = ButtonStyle.PRIMARY)
public void clickMe(ButtonEvent event) {
count++;
event.reply("You' ve clicked me %s time(s)", count);
}
}
Notice that we can just store the count inside the class. This is due to the request-scoped instances that got introduced with release v4.0.0-alpha.1.
event#withButtons
will always enable the button. Use event#with(Buttons#disabled(name))
to attach a disabled button.
Localization
You can integrate Localization with jda-commands by passing a ResourceBundleLocalizationFunction
to the start method of jda-commands:
JDACommands.start(jda, Main.class, ResourceBundleLocalizationFunction.fromBundles("Commands", DiscordLocale.GERMAN).build());
See the JDA example
for details on how to use localization.
1) New Features
-
you can now use
event#keepComponents(boolean)
to decide whether the reply should keep all components that are attached to the previous message. The default value istrue
-
event#removeComponents()
has been added to remove all components from the last message that was sent. This will only work witheditReply(boolean)
set totrue
2) Changes
- added
getUnknownInteractionMessage
toErrorMessageFactory
which replaces the previous placeholder response
3) Bug Fixes
- fixed a type adapting bug resulting in IndexOutOfBoundsException [#124]
- fixed a bug where response request exceptions got omitted
4) Internal changes
- generified
ReplyContext
in order to make it work with all type of events - generified
getCommandExecutionFailedMessage
in order to make it work with all type of events
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-alpha.3</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-alpha.3'
}
v4.0.0-alpha.2 | Improvements & Bug Fixes
Overview
This is a small followup release that brings in some bug fixes and smaller improvements.
1) New Features
N/A
2) Changes
- the
setConsumer(Consumer<Message>)
method has been split into two seperate methods: [#117]
- added a
reply(Consumer<Message>)
andreply(Consumer<Message>, Consumer<Throwable>
method [#114]
Instead of:
event.getReplyContext().getBuilder().setFiles(myFile).setContent("My message");
event.getReplyContext().setConsumer((m) -> myFile.delete());
event.reply();
you can now do:
event.getReplyContext().getBuilder().setFiles(myFile).setContent("My message");
event.reply((m) -> myFile.delete());
- slighlty adjusted the error message of the
CooldownFilter
:- changed color from red to orange
- made time unit more human readable
3) Bug Fixes
- reimplemented the
CooldownFilter
[#118] - fixed a bug that didn't reset the callback consumers of a reply, which resulted in deadlocks
4) Internal changes
N/A
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-alpha.2</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-alpha.2'
}
v4.0.0-alpha.1 | Slash Commands and Restructuring
Overview
This is the first alpha release of the upcoming version 4. As mentioned in the previous release, version 4 will discontinue support for text commands. Thus, in this release all text related components have been removed and many things have been restructured to fit interactions.
Writing Slash Commands
@Interaction
public class SlashCommandExample {
@SlashCommand(value = "hello", desc = "say hello to the bot", isGuildOnly = true, isNSFW = false, ephemeral = true, enabledFor = Permission.ADMINISTRATOR)
public void onPing(CommandEvent event) {
event.reply("Hello human!");
}
}
Some used fields are optional, but were added to this example to show the whole bandwidth of the new
@SlashCommand
annotation.
As you can see the core concepts of jda-commands haven't changed. Nevertheless, some changes were necessary, which will be explained in the following
Global and Guild scoped Commands
By default, all commands are registered globally. You can make a command guild scoped like this:
@Interaction
public class SlashCommandExample {
@SlashCommand(value = "hello", desc = "say hello to the bot", scope = CommandScope.GUILD)
public void onPing(CommandEvent event) {
event.reply("Hello human!");
}
}
Then you need to implement the GuildScopeProvider interface to tell jda-commands which guilds you wish your command to be registered for.
@Component
public class CustomGuildScopeProvider implements GuildScopeProvider {
@Override
public Set<Long> getGuildsForCommand(CommandData commandData) {
return new HashSet<>() {{
add(0123456789L);
}};
}
}
Permissions
The new permission system might be confusing, so here is a quick overview:
Bot side features (since version 2)
Mute
You can mute users which will reject any command interaction even before the execution chain has started. Use the PermissionsProvider interface for this.
Permissions (Bot side check)
Annotate commands with @Permission
and use the PermissionsProvider interface to implement your own permissions system.
Discord side feature (since version 4)
Use the @SlashCommand(enabledFor)
field to tell Discord which permission is needed to execute the command.
⚠ This can be overwritten by discord moderators and admins at any time. Do not rely on this permission check for critical commands like ban or eval.
1) New Features
Request-scoped Instances
For every command execution a new instance of the controller class is created. Subsequent executions of components are
executed in the same instance.
This allows you to store stateful objects, like the target of a ban command, inside the controller class.
ReplyContext
The MessageSender and ReplyCallback got replaced by the ReplyContext.
You can access the ReplyContext by calling event#getReplyContext
. Then, you can edit flags like ephemeral, edit reply, remove components, etc., which is however also possible directly via the event object. The important change is that you can also access the MessageCreateBuilder that is used for constructing the reply, allowing you to do crazy things like attaching files.
The Reply API didn't changed fundamentally, however the method overloads for ephemeral replies got removed. Instead, you need to call event#setEphemeral()
directly or use the @SlashCommand
annotation.
Example
@SlashCommand(value = "cat", desc = "sends a photo of lovely cat", ephemeral=true)
public void onCommand(CommandEvent event) {
event.getReplyContext().getBuilder().setFiles(lovelyCatFile);
event.reply(); // no args call equals to calling event.getReplyContext().queue()
}
@Param
Annotation
The @Param
annotation got introduced to supply the metadata of command options. The following fields are available:
- value (description)
- name
Parameter Name Auto Detection
jda-commands can now resolve the name of your parameters from the method signature. In order to enable this feature you need to compile your code with the -parameters
flag
IntelliJ
Settings > Build, Execution, Deployment > Compiler > Java Compiler > Javac Options
Maven
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
Gradle
compileJava {
options.compilerArgs += "-parameters"
}
JDAContext
Added the JDAContext as a bridge between JDA and ShardManager objects.
2) Changes
-
The following features got changed/removed because they are now natively supported by slash commands:
-
Optional parameter now longer needs to be at the end of a command
-
SyntaxErrorMessage got renamed to TypeAdaptingFailedMessage
-
Removed help commands and embeds
-
Removed
@Conact
annotation -
Removed CommandList and MarkdownGenerator
-
Removed GuildSettings
-
Removed Repository, JsonRepository, GuildSettingsRepository
-
-
DependencyInjector can now resolve static fields
-
Added default mappings for primitive optionals
-
Added type adapters for all new channel types
Annotations
-
Renamed annotations:
@Controller
->@Interaction
@Command
->@SlashCommand
@Permission
->@Permissions
-
Renamed the following attributes from
@SlashCommand
(former@Command
):- isDM -> isGuildOnly
- label -> name
-
Removed the following attributes from
@SlashCommand
(former@Command
):- help
- category
- usage
- isSuper
3) Bug Fixes
- Custom filters in the FilterRegistry are now registered correctly
4) Internal changes
-
Introduced CommandTree class, which generates a valid command tree respecting subcommand groups and subcommands
-
The CommandContext and CommandDispatcher got abstracted, similar to the CommandParser
-
Reimplementation of the GenericEvent class
-
Introduced the RuntimeSupervisor that takes care of the request-scoped instances
-
Removed CommandRouter
You can find the complete changelog here.
Also, checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v4.0.0-alpha.1</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v4.0.0-alpha.1'
}
3.0.0
Overview
This release marks a breaking point in the development of jda-commands.
The past work on version 2.3.0 (and respectively the first two alpha releases) tried to combine both systems: text input based commands and the new interaction based commands. Keeping backwards- and cross-compatibility was a desirable but ambitious goal from the very beginning. However, with JDA 5 adding more and more breaking changes and new interaction types like Modals, this task became nearly impossible. Thus, I've decided to split things up:
-
This and future v3 releases are based on jda-commands 2.2.0 and will only add longterm support for JDA 5. There will be no new features added.
-
At the same time I'll be working on v4, which will drop support for text commands and will only be based on interactions.
-
2.3.0-alpha.2 will be left untouched in its current state.
1) New Features
N/A
2) Changes
-
Added type adapters for new channel types (
AudioChannel
,GuildChannel
,GuildMessageChannel
,NewsChannel
,StageChannel
,ThreadChannel
,VoiceChannel
) -
changed
Message
toMessageCreateData
in the following interfaces or classes:MessageSender
andDefaultMessageSender
ErrorMessageFactory
,DefaultErrorMessageFactory
andJsonErrorMessageFactory
HelpMessageFactory
,DefaultHelpMessageFactory
andJsonHelpMessageFactory
CommandEvent
CommandContext
-
EmbedDTO#toMessage
has been deprectated and replaced byEmbedDTO#toMessageCreateData()
3) Bug Fixes
N/A
4) Internal changes
N/A
You can find the complete changelog here.
Also checkout the Wiki or the JavaDoc.
Maven
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<dependency>
<groupId>com.github.Kaktushose</groupId>
<artifactId>jda-commands</artifactId>
<version>v3.0.0</version>
</dependency>
Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Kaktushose:jda-commands:v3.0.0'
}