Skip to content

Releases: Kaktushose/jda-commands

v4.0.0-beta.4 | Bug Fixes & Enhancements

12 Jan 20:35
b31d38d
Compare
Choose a tag to compare

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

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

07 Jan 20:05
546dc42
Compare
Choose a tag to compare

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.

image

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 and getRolesWithPermission 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 and JsonErrorMessageFactory were moved to com.github.kaktushose.jda.commands.embeds.error
  • KeyValueStore was moved to com.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 the com.github.kaktushose.jda.commands.definitions package, see the Javadocs for details

  • Many classes have become final and / or were marked as ApiStatus.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

19 Apr 10:00
Compare
Choose a tag to compare

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 to true jda-commands will ignore this producer method at indexing. This is useful if you wish to register your dependency providers manually by calling DependencyInjector#registerProvider(Object).

  • Implemented a simple KeyValueStore that can be accessed from every event class by calling kv()

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 the GuildReadyEvent 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

25 Nov 17:30
Compare
Choose a tag to compare

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:

  1. PERMISSIONS (ensures that the PermissionsMiddleware is always executed first)
  2. HIGH
  3. NORMAL (default)
  4. 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 to Context#setCancelled(MessageCreateData). This ensures that there is always an error message to display. Thus, Context#setErrorMessage got removed and Context#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 to true a new message was always sent

4) Internal changes

  • Introduced GenericComponentDefinition to remove the type parameters for CommandEvent und ComponentEvent

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

31 Oct 15:17
Compare
Choose a tag to compare

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 and SelectMenuEvent into ComponentEvent

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 the JDACommands instance
  • Renamed GenericContext to Context 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 into DispatcherSupervisor and thus removed GenericParser and it's subtypes
  • Merged ButtonDispatcher and SelectMenuDispatcher into ComponentDispatcher
  • Renamed:
    • CommandDefinition -> SlashCommandDefinition
    • GenericContext -> Context
    • Context#getInteraction -> Context#getInteractionDefinition
    • ControllerDefinition -> InteractionControllerDefinition
    • EphemeralInteraction -> EphemeralInteractionDefinition
    • GenericInteraction -> GenericInteractionDefinition
  • Made GenericEvent a subtype of GenericInteractionCreateEvent and removed method overload
  • Added static instance creation to the RuntimeSupervisor
  • Implemented a default implementation of the reply method inside the Replyable 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

15 Oct 12:32
Compare
Choose a tag to compare

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())
        );
    }
}

GIF 13-10-2023 14-24-01

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 to dispatching/interactions
  • moved components to dispatching/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 the Replyable 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

01 Oct 14:30
Compare
Choose a tag to compare

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.

GIF 01-10-2023 16-05-05

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

2) Changes

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

31 May 21:33
Compare
Choose a tag to compare

Overview

This is a small followup release that brings in some bug fixes and smaller improvements.

1) New Features

N/A

2) Changes


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

image

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

26 Apr 20:24
Compare
Choose a tag to compare

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

image

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

20 Dec 15:03
Compare
Choose a tag to compare

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 to MessageCreateData in the following interfaces or classes:

    • MessageSender and DefaultMessageSender
    • ErrorMessageFactory, DefaultErrorMessageFactory and JsonErrorMessageFactory
    • HelpMessageFactory, DefaultHelpMessageFactory and JsonHelpMessageFactory
    • CommandEvent
    • CommandContext
  • EmbedDTO#toMessage has been deprectated and replaced by EmbedDTO#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'
}