Skip to content

Releases: freya022/BotCommands

v3.0.0-beta.7 | Modal file uploads

18 Oct 20:35
eaabac3

Choose a tag to compare

JDA

Overview

This release primarily adds support for file uploads in modals.

Creating a Modal accepting file uploads

Kotlin
modals.create("modal-id") {
    label("Banner image") {
        child = AttachmentUpload("banner-file")
    }
}
Java
modals.create("modal-id")
  .addComponents(Label.of("Banner Image", AttachmentUpload.of("banner-file")))
  .build()

Using the uploaded file

If you use @ModalHandler, you can add a @ModalInput parameter with a List<Message.Attachment> type.

@ModalHandler(name = "modal-id")
fun onModal(event: ModalEvent, @ModalInput("banner-file") bannerAttachments: List<Message.Attachment>) { ... }

If you use coroutines, you can use modalEvent[attachmentUpload] instead.

val bannerFileComponent = AttachmentUpload("banner-file")

val modal = modals.create("modal-id") {
    label("Banner image") {
        child = bannerFileComponent
    }
}

// Reply with the modal 

val event = modal.await()
val bannerFile = event[bannerFileComponent].asAttachmentList.single()

Changes

Dependencies

  • Updated to JDA 6.1.0
  • Updated to Kotlin 2.2.20

jda-ktx

  • Added customId to [Type]SelectMenu and TextInput DSLs

Fixes

jda-ktx

  • Fixed Label DSL not checking if a label was set

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-beta.6...v3.0.0-beta.7


Installation

As a reminder, the minimum Java version supported is Java 17.

Kotlin Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:3.0.0-beta.7")
}

Maven

<dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>3.0.0-beta.7</version>
</dependency>

v3.0.0-beta.6 | Components V2 and new modal components

16 Sep 11:59
35feea1

Choose a tag to compare

JDA

Overview

This release updates to JDA 6 and adds support for Components V2 as well as new modal components such as text displays, labels and select menus.

Components V2 (#233)

Please refer to the JDA 6.0.0-rc.1 release for details on this feature.

Deprecations

  • UsedComponentSet#setComponents(Iterable) was deprecated
    • Replaced by setComponents(ComponentTree)

New features

  • Added deleteTree in services which can create components (Buttons/SelectMenus)

Kotlin extensions

Several factory functions were added:

  • ActionRow
  • Container
  • FileDisplay
  • MediaGallery
  • MediaGalleryItem
  • Section
  • Separator
  • TextDisplay
  • Thumbnail

Additionally, functions were added in inline builders to directly insert components where they can:

  • actionRow
    • linkButton
  • container
  • fileDisplay
  • mediaGallery
    • item
  • section
  • separator
  • text

For example,

val message = MessageCreate {
    components += Container { /* */ }
}

can also be written as

val message = MessageCreate {
    container { /* */ }
}

Note: These functions are available only in components which accept multiple child components (ActionRow, Container, Section content), for fields such as the accessory of Section, you will need to set the component manually.


Labels and string select menus in modals (#242)

Alongside with the new JDA additions, instead of having "input names" to match with your handler's @ModalInput, you can now use the native custom ID, note that it must be unique per modal.

Adding a text input, a label or a string select menu, now only uses the native JDA components.

See the JDA 6.0.0-rc.4 release for more details.

Example changes:

@Command
public class SlashFormat extends ApplicationCommand {

    private static final String MODAL_NAME = "SlashFormat: formatModal";
-   private static final String CODE_INPUT_NAME = "SlashFormat: formatModal codeInput";
+   private static final String CODE_INPUT_ID = "SlashFormat: formatModal codeInput";

    private final Modals modals;

    public SlashFormat(Modals modals) {
        this.modals = modals;
    }

    @JDASlashCommand(name = "format")
    public void onSlashFormat(GuildSlashEvent event) {
        Modal modal = modals.create("Format your code")
                .bindTo(MODAL_NAME)
                .addComponents(
-                       modals.createTextInput(CODE_INPUT_NAME, "Code", TextInputStyle.SHORT)
+                       Label.of(
+                               "Code",
+                               TextInput.create(CODE_INPUT_ID, TextInputStyle.SHORT).build()
+                       )
                )
                .build();

        event.replyModal(modal).queue();
    }

    @ModalHandler(MODAL_NAME)
-   public void onFormatModal(ModalEvent event, @ModalInput(CODE_INPUT_NAME) String code) {
+   public void onFormatModal(ModalEvent event, @ModalInput(CODE_INPUT_ID) String code) {
        // ...
    }
}

You can see a more complete example in the "Entity select menus and text displays in modals" section.

Breaking changes

  • (Kotlin only) name of @ModalInput has been updated to customId
  • Removed custom TextInputBuilder
    • Use TextInput.create (Java) or TextInput(...) { ... } (Kotlin) instead
    • The given custom ID will be used to match against @ModalInput parameters

New features

  • @ModalInput(...) List<String> parameters can now be resolved
  • Added Kotlin DSLs:
    • Modals (Modals#create(...) { ... })
    • Labels (Label(...) { ... })
    • Text inputs (TextInput(...) { ... })
    • String select menus (StringSelectMenu(...) { ... })

Entity select menus and text displays in modals

Similarly to string select menus, entity select menus can now be added to modals using the native JDA component, the same can be said for text displays.

Please see the JDA 6.0.0-rc.5 release for more details.

Here is an example modal using text inputs, text displays, labels, string select menus and entity select menus:

Modal example
Kotlin example
private const val MODAL_NAME = "request role"
private const val INPUT_REASON = "reason"
private const val INPUT_ROLE = "role"
private const val INPUT_DETAILS = "details"

@Command
class SlashRequestRole(private val modals: Modals) {

    @JDASlashCommand(name = "request_role", description = "Request a role")
    fun onSlashRequestRole(event: GuildSlashEvent) {
        val modal = modals.create("Role Request Form") {
            text(
                """
                    ### Welcome!
                    Please read the following before continuing:
                    1. Select the role you wish to get
                    2. Select the reason why you want this role
                    3. (Optional) Add any detail about your request
                    
                    -# Abuse of this system may result in penalties
                """.trimIndent()
            )

            label("Role") {
                child = EntitySelectMenu(INPUT_ROLE, SelectTarget.ROLE)
            }

            label("Reason") {
                child = StringSelectMenu(INPUT_REASON) {
                    option("It looks cool!", "cool")
                    option("I like the color", "color")
                    option("I am interested in the relevant discussions", "discussions")
                }
            }

            label("Details") {
                child = TextInput(INPUT_DETAILS, TextInputStyle.PARAGRAPH, isRequired = false)
            }

            bindTo(MODAL_NAME)
        }

        event.replyModal(modal).queue()
    }

    @ModalHandler(MODAL_NAME)
    fun onRequestRoleModal(
        event: ModalEvent,
        @ModalInput(INPUT_REASON) reason: List<String>,
        @ModalInput(INPUT_ROLE) roles: List<Role>,
        @ModalInput(INPUT_DETAILS) details: String,
    ) {
        event.reply("Your request has been submitted!")
            .setEphemeral(true)
            .queue()
    }
}
Java example
@Command
public class SlashRequestRole extends ApplicationCommand {

    private static final String MODAL_NAME = "request role";
    private static final String INPUT_ROLE = "role";
    private static final String INPUT_REASON = "reason";
    private static final String INPUT_DETAILS = "details";

    private final Modals modals;

    public SlashRequestRole(Modals modals) {
        this.modals = modals;
    }

    @JDASlashCommand(name = "request_role", description = "Request a role")
    public void onSlashRequestRole(GuildSlashEvent event) {
        var modal = modals.create("Role Request Form")
                .addComponents(
                        TextDisplay.of("""
                                ### Welcome!
                                Please read the following before continuing:
                                1. Select the role you wish to get
                                2. Select the reason why you want this role
                                3. (Optional) Add any detail about your request
                                
                                -# Abuse of this system may result in penalties
                                """),
                        Label.of(
                                "Role",
                                EntitySelectMenu.create(INPUT_ROLE, SelectTarget.ROLE).build()
                        ),
                        Label.of(
                                "Reason",
                                StringSelectMenu.create(INPUT_REASON)
                                        .addOption("It looks cool!", "cool")
                                        .addOption("I like the color", "color")
                                        .addOption("I am interested in the relevant discussions", "discussions")
                                        .build()
                        ),
                        Label.of(
                                "Details",
                                TextInput.create(INPUT_DETAILS, TextInputStyle.PARAGRAPH)
                                        .setRequired(false)
                                        .build()
                        )
                )
                .bindTo(MODAL_NAME)
                .build();

        event.replyModal(modal).queue();
    }

    @ModalHandler(MODAL_NAME)
    public void onRequestRoleModal(
            ModalEvent event,
            @ModalInput(INPUT_ROLE) List<Role> roles,
            @ModalInput(INPUT_REASON) List<String> reason,
            @ModalInput(INPUT_DETAILS) String details
    ) {
        event.reply("Your request has been submitted!")
                .setEphemeral(true)
                .queue();
    }
}

New features

  • @ModalInput parameters can now resolve Mentions and T/List<T> where T is one of: IMentionable, Role, User, InputUser, Member, GuildChannel
  • Added Kotlin DSLs:
    • text(...) in InlineModal
    • EntitySelectMenu(...) { ... } factory

Breaking changes

  • Updated to JDA 6.0.0-rc.5

New features

  • Added Mentions.inputUsers
    • Ret...
Read more

v3.0.0-beta.5

03 Sep 10:04
91eb5dc

Choose a tag to compare

JDA

Bug fix release, please refer to previous release for the changelog.


Changes

  • Removed BotCommands-method-accessor-classfile
    • Can now be optionally included

Bug fixes

  • Fixed assignment of parameters
  • Fixed handling of value class return types

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-beta.4...v3.0.0-beta.5


Installation

As a reminder, the minimum Java version supported is Java 17.

Kotlin Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:3.0.0-beta.5")
}

Maven

<dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>3.0.0-beta.5</version>
</dependency>

v3.0.0-beta.4

02 Sep 18:39
ef70908

Choose a tag to compare

JDA

Replaced jda-ktx with a new module (#239)

Removes jda-ktx and introduces a new BotCommands-jda-ktx module, this is done for a few reasons:

  1. A significant part of it is unused, because the framework already provides the functionality in a similar way, such as creating commands, components and modals
  2. It depends on JDA, meaning we can't upgrade to a new major JDA version without also updating jda-ktx, and in some cases it forces us to use Jitpack for it, we don't want that
  3. Along with the previous point, adding utilities is faster if we maintain it ourselves

This will no longer include jda-ktx transitively, you are recommended to migrate, but if you choose to add it back, be aware that functions relying on CoroutineEventManager, such as JDA#await/listen will no longer work.

Please look at the README for more details.

Differences with jda-ktx

Changes to the CoroutineEventManager

The core module includes its own event manager, you can configure its default timeout at BEventManagerConfig#defaultTimeout, and the CoroutineScope in BCoroutineScopesConfig#eventManagerScope.

As a result, extensions from jda-ktx relying on its CoroutineEventManager no longer work, but you can fix this by importing the extension from this module.

You can still register CoroutineEventListeners (the one from BotCommands-core, not jda-ktx!) if required.

Changed functionalities

If you decide to switch, some functions have replacements:

  • awaitMessage must now be used on an EventWaiter instance
  • awaitButton is now Button#await (the framework's Button class)
  • jda-ktx's Paginator is replaced by the core Paginators

Incompatible functionalities

If you keep using jda-ktx, some functions will not work or behave unexpectedly:

  • scope on JDA/ShardManager
  • Any function related to build JDA or shard managers, it is recommended you use the helper functions in JDAService.

Missing functionalities

Additionally, jda-ktx has additional extensions that were not ported:

  • String#toEmoji()
  • String#toCustomEmoji()
  • String#toUnicodeEmoji()
    • It is recommended to use jda-emojis's UnicodeEmojis class (included by default)
  • getDefaultScope
    • Replaced with namedDefaultScope
  • All extensions already handled by the framework, such as creating/listening to commands, components and modals
  • The WebhookAppender
  • named, String#invoke and some into extensions from messages/utils.kt
  • OkHttp's Call extensions awaitWith and await
  • SLF4J logger delegation (private val logger by SLF4J)
    • I recommend using kotlin-logging instead (private val logger = KotlinLogging.logger { })
    • The Logging class may also be of interest
  • ref extensions on entities
    • I don't recommend using them because while they keep entities up to date between reconnects, they don't prevent you from sending requests to deleted entities

Please open an issue if you feel like one of these extensions are worth porting, an alternative is to port them locally.

Migrating

You can apply an OpenRewrite recipe to change all relevant imports, note that this could still require you to do some changes after it.

Before migrating, your codebase must compile, so you must not update any versions yet.

Make sure you have committed your current changes, or make a back-up of your project.

Registering the recipe

Note

This will log warnings for Kotlin sources, but the recipes still work fine.

(Kotlin) Gradle
plugins {
    // ...
    id("org.openrewrite.rewrite") version "7.11.0"
}

repositories {
    // ...
    maven("https://jitpack.io")
}

dependencies {
    // Existing dependencies, DO NOT UPDATE THEM YET
    // ...

    rewrite("io.github.freya022:BotCommands-jda-ktx:{{NEW_VERSION}}")
    rewrite("org.openrewrite.recipe:rewrite-java-dependencies:1.37.0")
}

rewrite {
    // Use 'dev.freya02.MigrateToBcJdaKtx' if you want to migrate from jda-ktx (recommended)
    // Use 'dev.freya02.MigrateFromBcCoreToBcJdaKtx' if you want to keep using jda-ktx
    activeRecipe("dev.freya02.MigrateToBcJdaKtx")
}

Checking changes (dry run)

Run the rewriteDryRun task, this can be done by pressing CTRL twice on IntelliJ then running gradle rewriteDryRun.
This will generate a diff file at build/reports/rewrite/rewrite.patch, you can check the possible changes there.

Applying changes

Run the rewriteRun task.

Maven
  1. Add the following repository:
<repository>
    <id>jitpack</id>
    <url>https://jitpack.io</url>
</repository>
  1. Add the following plugin:
<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>6.13.0</version>
  <configuration>
    <activeRecipes>
      <!-- Use 'dev.freya02.MigrateToBcJdaKtx' if you want to migrate from jda-ktx (recommended) -->
      <!-- Use 'dev.freya02.MigrateFromBcCoreToBcJdaKtx' if you want to keep using jda-ktx -->
      <recipe>dev.freya02.MigrateToBcJdaKtx</recipe>
    </activeRecipes>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.openrewrite.recipe</groupId>
      <artifactId>rewrite-java-dependencies</artifactId>
      <version>1.37.0</version>
    </dependency>
    <dependency>
      <groupId>io.github.freya022</groupId>
      <artifactId>BotCommands-jda-ktx</artifactId>
      <version>{{NEW_VERSION}}</version>
    </dependency>
  </dependencies>
</plugin>

Checking changes (dry run)

Run the rewrite:dryRun goal, this can be done by pressing CTRL twice on IntelliJ then running mvn rewrite:dryRun.
This will generate a diff file at target/site/rewrite/rewrite.patch, you can check the possible changes there.

Applying changes

Run the rewrite:run goal.

You can then update BotCommands-core and add BotCommands-jda-ktx, if you do use it.

It is recommended to optimize imports (Code | Optimize imports in IntelliJ) after migrating.

Notes

Breaking changes

  • Removed ICoroutineEventManagerSupplier
    • If you want to configure the default timeout, set BEventManagerConfig#defaultTimeout
    • If you want to configure the coroutine scope, set BCoroutineScopesConfig#eventManagerScope
  • Removed the jda-ktx api dependency
    • You can add it back if you want, but I'd recommend migrating to BotCommands-jda-ktx

New Features

  • Added CoroutineEventListener
  • Ported part of jda-ktx to BotCommands-jda-ktx
  • Added more extensions, see the readme

Changes

  • Moved JDA extensions from the core modules to BotCommands-jda-ktx
    • Deprecated accessors were made to help migrate
  • Extensions for RestAction, RestResult and related, which have vararg parameters, now require at least 1 argument

Added generate method accessors (#241)

For Java 24+ users, this feature allows using improved method calls (event listeners, commands and service initialization),
reducing the size of stack traces in exceptions and in your debugger, as well as slightly improved performance.

More technical details are in the README.

New features

  • Added BotCommand.preferClassFileAccessors()

Breaking changes

  • Replaced jda-ktx with a new module (#239)

New features

  • Added generate method accessors (#241)

Changes

  • Added missing static methods for function and properties in objects
  • Added missing overloads using Java reflection (instead of Kotlin reflect)
  • Added missing overloads using Java durations (instead of Kotlin durations)
  • Removed data modifier from TimeoutInfo

Bug fixes

  • BCServiceContainer can now be injected
  • Unknown event types no longer log twice per function

Don't hesitate to check out the examples and the wiki.

Full Changelog: https://github.com/freya022/BotComm...

Read more

v3.0.0-beta.3

22 Jul 15:46
21a46a6

Choose a tag to compare

JDA

Added BotCommandsMessages and PermissionLocalization (#236)

DefaultMessages and DefaultMessagesFactory are deprecated in favor of:

  • BotCommandsMessages for the messages used by the framework
  • PermissionLocalization for DefaultMessage#getPermission

Deprecation process

If a non-default configuration of DefaultMessages is detected, the auto-configured BotCommandsMessagesFactory instance will delegate to it instead, and you will see a warning about the deprecation.

Differences

BotCommandsMessages is similar to DefaultMessages, however:

  • The template keys have been changed as to allow nesting in some cases
  • Each method returns a MessageCreateData instead of a String, allowing you to fully customize the responses (such as by using Components V2 👀)
  • The method names were shortened

The default strings were unchanged.

Migrating

If you made DefaultMessages[language].json files, you will need to replace DefaultMessages by BotCommandsMessages, then migrate the keys to the new ones found in BotCommandsMessages-default.json.


Breaking changes

Modules

  • Spring support was moved to a separate BotCommands-spring artifact

Dependencies

  • Some compile dependencies are no longer included transitively:

    You do not need to depend on them unless your code compiles against them in your project

  • Optional dependencies are no longer in the published POM, this does not affect your project at all

Rate limiting

  • Generics were removed from RateLimitHandler methods

Deprecations

Default DI

  • Deprecated DefaultServiceContainer, renamed to BCServiceContainer

Changes

Modules

  • The BotCommands artifact will be split in more submodules, those new modules will still be included transitively

Slash commands

  • Allows vararg parameters to be received with 0 required options (#234)

Text commands

  • Enforce at least 1 required option when using varargs (#234)

Core configuration

  • JDAService#getDefaultRestConfig() now appends a link to itself in the HTTP User-Agent

Extensions

  • Some extensions had a wrong contract with the block specified as being called EXACTLY_ONCE, this has been corrected to AT_MOST_ONCE

    • runCatchingResponse
    • runIgnoringResponse
    • runIgnoringResponseOrNull
    • runCatchingRest

    See c4deec1152 for more details

Dependencies

  • Updated Kotlin to 2.2.0
  • Updated JDA to 5.6.1
  • Updated Jackson to 2.19.1

New features

Components

  • Added ButtonFactory#toLabelButton() (e.g. buttons.primary("Page 1/5").toLabelButton())
    • Allows creating disabled buttons for display purposes

Default DI

  • Added @ConditionalOnMissingService

Reflection

  • Added ClassGraphProcessorProvider
    • This is an SPI returning ClassGraphProcessor instances at startup, mainly used by other modules
    • Is opt-in via @ExperimentalReflectionApi

Bug fixes

Default DI

  • Fix BServiceConfig#serviceSupplier not being used
  • Fix supplied services being unable to be retrieved by their primary type

Database

  • Fix DBResult's iterator not fetching values when hasNext() was not called

Rate limiting

  • Don't attempt to delete rate limit message if the channel was deleted

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-beta.2...v3.0.0-beta.3


Installation

As a reminder, the minimum Java version supported is Java 17.

Kotlin Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:3.0.0-beta.3")
}

Maven

<dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>3.0.0-beta.3</version>
</dependency>

v3.0.0-beta.2 | JDA 5.5.0, improvements and fixes

30 Apr 11:00
0a6f94a

Choose a tag to compare

JDA version

Changes

Components

  • label and emoji combinations in button factories are now nullable
    • At least one of them is required
  • Added a disabled parameter to Button#of(ButtonStyle, String?, Emoji?)

Modals

  • Removed context receivers from modal extensions
    • Requires recompilation but no source changes

Dependencies

  • Updated JDA to 5.5.0
    • Updated Jackson to 2.18.3
    • Updated JetBrains annotations to 26.0.2
  • Excluded Tink from JDA
    • Unsure whether this is taken into account by Maven and/or Gradle
    • See JDA's readme on how to exclude them yourself

New features

Components

  • Added Collection overloads in persistent timeout extensions

Serialization

  • Added Kotlin support to DefaultObjectMapper

Bug fixes

Components

  • Fixed type-safe timeout extensions saving arguments in a nested list

Database

  • Fixed warning due to a ByteArray placeholder trying to be replaced in query logs

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-beta.1...v3.0.0-beta.2

Installation

As a reminder, the minimum Java version supported is Java 17.

Kotlin Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:3.0.0-beta.2")
}

Maven

<dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>3.0.0-beta.2</version>
</dependency>

v3.0.0-beta.1 | Component data serialization, removed old declarations

18 Feb 22:46
d2c6123

Choose a tag to compare

JDA version

Overview

Added component data serialization, few minor additions and finally removed old declarations.

It has been 84 years...
As a reminder, while the major changes are done, some smaller changes and/or deprecations might be necessary in the future, to always improve the development experience, adopt newer features and better practices.

While there is no complete migration guide, you are welcome to ask in the support server.

Note about the previous release

The meaning of CommandScope#GLOBAL was changed in the previous release; You can learn more about it in the "Breaking changes" section.

Removed all deprecated declarations (#212)

If you're having compilation errors, downgrade to 3.0.0-alpha.24 and:

  • Do a full recompile to see the deprecation warnings,
  • Or, use your IDE to inspect your project.

Support for component data serialization (#231)

This enables you to pass any data to your component and timeout handlers, as long as they are serializable.

Any serialization library can be used, Jackson, Gson, kotlinx.serialization, Protobuf, Java's serialization (???), you name it.

Breaking changes

  • The String arg parameter have been replaced with a data argument of type SerializedComponentData
  • A SerializedComponentData serialize(R) method has been added
  • A new migration script has been added, if you are using a migration tool already, you do not need to do anything

New features

  • Added @SerializableComponentData and @SerializableTimeoutData
    • Can be used instead of @ComponentData/@TimeoutData to (de)serialize objects using GlobalComponentDataSerializer
    • GlobalComponentDataSerializer has a default instance, which can be overridden by creating your own instance.

Breaking changes

Components

  • Require >=42.7.5 of the PostgreSQL first party driver (required by #231)
    • You can still use H2, which does not require a minimum version
    • You will be warned when using a third party PostgreSQL driver

Deprecations

Misc

  • Deprecated typeReferenceOf
    • Replaced by jackson-module-kotlin's jacksonTypeRef

Changes

Dependencies

  • Added jackson-module-kotlin v2.17.2, same version as what JDA uses

New features

Misc

  • Added static factories for KotlinTypeToken
    • Similar to Gson's TypeToken static methods, or the Jackson ObjectMapper's methods returning TypeReferences
  • Added ParameterWrapper#typeToken
    • Return a KotlinTypeToken, a more general purpose object

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-alpha.24...v3.0.0-beta.1

Installation

As a reminder, the minimum Java version supported is Java 17.

Kotlin Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:3.0.0-beta.1")
}

Maven

<dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>3.0.0-beta.1</version>
</dependency>

v3.0.0-alpha.24 | User-installable apps, jda-emojis

04 Feb 15:37
be0fded

Choose a tag to compare

JDA version

Overview

Added user-installable apps and jda-emojis.

Note: This should be the last V3 alpha.

User-installable apps (#163)

These will allow you to use interactions anywhere on Discord, by installing them on users directly instead of guilds.
You can read more about them on the JDA release notes.

After installing your app on the user, allowing a command to be installed on the user requires you to add USER_INSTALL to the integrationTypes property of your top level command.

Then, you can define the contexts property (again, on the top-level command), this property defines where the command can be used (Guild, Bot DMs, Friend DMs, Group DMs).

You can also check out the wiki for more details.

Breaking changes

  • Meaning of CommandScope#GLOBAL has changed, it previously meant having a command accessible on both the installed Guild, and the Bot's DMs
    However, since then, it only specifies the scope on which the command is added.

    If you have used this scope, you will likely get a warning which recommends you to use the "Guild" variant of the event,
    to fix this and restore previous behavior, you will need to add InteractionContextType.GUILD and InteractionContextType.BOT_DM in the contexts property, alongside your existing scope = CommandScope.GLOBAL.

    Kotlin example:

    @TopLevelSlashCommandData(scope = CommandScope.GLOBAL)
    @JDASlashCommand(name = "foo")
    fun onSlashFoo(event: GlobalSlashEvent) {
        
    }

    when updating to 3.0.0-alpha.24, becomes:

    // Same as @TopLevelSlashCommandData(scope = CommandScope.GLOBAL, contexts = [InteractionContextType.GUILD, InteractionContextType.BOT_DM])
    @TopLevelSlashCommandData(contexts = [InteractionContextType.GUILD, InteractionContextType.BOT_DM])
    @JDASlashCommand(name = "foo")
    fun onSlashFoo(event: GlobalSlashEvent) {
        
    }

Deprecations

  • Deprecated CommandScope#GLOBAL_NO_DM, set contexts on your top-level command to InteractionContextType.GUILD instead
  • Deprecated CommandScope in code-declared commands, use interaction contexts instead

New features

  • Can now set interaction contexts (where a command can run)
  • Can now set integration types (where a command can be installed)
  • Default integration types and interaction contexts can be changed
    • In GuildApplicationCommandManager for guild-scoped commands
    • In GlobalApplicationCommandManager for global-scoped commands
    • These defaults apply for both annotated and code-declared commands

Added jda-emojis (#229)

This library was added to allow a more seamless usage of emojis in your JDA code.

When you previously had to take the proper Unicode manually, or using JEmoji and converting to JDA's UnicodeEmoji, you can now directly take the same emoji Discord supports, from Emojis (in the dev.freya02.jda.emojis.unicode package) or UnicodeEmojis.

Remember, if you are converting from JEmoji to jda-emojis, you will find the emoji names using Discord's names.

Check out the wiki for more details.

Deprecations

  • ButtonContent: fromUnicode, fromShortcode

New features

  • Added an withEmoji overload with JDA's Emoji in ButtonContent/ButtonFactory (when building a button)

New features

Components

  • Added withDisabled on ButtonContent and ButtonFactory
    • This allows disabling a component before it is built

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-alpha.23...v3.0.0-alpha.24

v3.0.0-alpha.23 | Improved dynamic DI, simplified runtime filters, and general improvements

25 Jan 17:56
378dc06

Choose a tag to compare

JDA version

Overview

Improved built-in DI capabilities, simplified runtime filters, and general usability improvements.

Replaced DynamicSupplier with user-defined service suppliers (#225, #226)

This aims to allow defining services earlier in the loading process, for example, when initializing the framework, or while discovering classes.

One use case is to define services when discovering an interface with a given annotation; a similar example in Spring would be JPA repositories (using @Repository on an interface that gets implemented automatically).

Breaking changes

  • Removed DynamicSupplier

Deprecations

  • Deprecated instance suppliers
    • InstanceSupplier
    • BServiceConfig#instanceSupplierMap
    • BServiceConfigBuilder#registerInstanceSupplier

Changes

  • Passed a ServiceContainer in ClassGraphProcessor methods
  • Annotations are no longer read from classes supplied by InstanceSuppliers
    • This shouldn't affect anyone as you would use a service factory instead

New features

  • Added ServiceSupplier
    • This lets you configure a service with a bit more depth
  • Added DefaultServiceContainer#putSuppliedService(ServiceSupplier)
    • You should be able to call this from a ClassGraphProcessor, for example, if you want to register proxied interfaces as services
  • Added BServiceConfigBuilder#registerServiceSupplier(...)

Removed append attributes from @UserPermission, @BotPermissions and @Test (#227)

You will now have to annotate the affected function directly, to clarify what affects a function, however, to reduce repetition, you can use them as meta-annotations, combine them and override them.

Breaking changes

  • Removed the append attribute
  • Removed the CLASS target
  • If findAllAnnotations encounters the target annotation, this will override meta-annotations (children annotations) if directOverrides is true
  • findAllAnnotations has no defined order anymore

Changes

  • Added the ANNOTATION_CLASS target

Slightly simplified filters (#228)

A rejection handler is no longer mandatory, however, you can keep using it if you wish, by calling it yourself.

Breaking changes

  • You no longer need to make rejection handlers
    • Instead of returning arbitrary data, you handle the rejection in the filter directly, and return a string for logging purposes
    • I recommend using a separate function/class to reduce maintenance
  • The global property of filters is now abstract
    • Clarifies which filter is global or command-specific

Breaking changes

Built-in dependency injection

  • Removed ServiceContainer#lazyService
    • This already existed as lazy

Changes

Dependencies

  • Kotlin: 2.0.0 -> 2.1.0
  • kotlinx-coroutines: 1.9.2 -> 1.10.1
  • (Optional) Spring boot: 3.2.12 -> 3.4.2
  • kotlinx-datetime: 0.5.0 -> 0.6.1
  • ClassGraph: 4.8.175 -> 4.8.179
  • Caffeine: 3.1.8 -> 3.2.0
  • slf4j-api: 2.0.13 -> 2.0.16
  • kotlin-logging: 7.0.0 -> 7.0.3
  • (Optional) HikariCP: 5.1.0 -> 6.2.1

App emojis

  • Throw exception if not enough slots are available

New features

App emojis

  • Added BAppEmojisConfig#deleteOnOutOfSlots
    • If there are not enough slots, it will delete the oldest application emojis that aren't required by the bot

Localization

  • Added LocalizationContext#fromLocaleProviders
    • This helps you create a localization context using the same locales as using the events would
    • This can be useful when replying in an interaction filter
  • Adding a / prefix to your template key will make the library ignore any set prefix
    • Example: /my.command.responses.ok will stay as my.command.responses.ok even if a prefix is set

Components

  • Added a few helpers to create IdentifiableComponent from JDA components
  • Added a few helpers to remove stored components using JDA components

Misc

  • Added a few utilities to convert from/to Kotlin/Java functions in ReflectionUtils

Bug fixes

Built-in dependency injection

  • Fixed using LazyService in Java constructors

App emojis

  • Fixed app emojis being enabled by default on Spring apps

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-alpha.22...v3.0.0-alpha.23

v3.0.0-alpha.22 | App emoji registry, QoL additions and fixes

29 Dec 20:23
734bd68

Choose a tag to compare

JDA version

Overview

Added an application emoji registry, some quality of life additions and fixes.

Application emoji registry (opt-in, #221)

This adds support for automatic loading and setup of your bot's application emojis.
The emojis are loaded from the classpath, typically in your resources folder,
and are pushed to Discord before JDA logs in, meaning the emojis are always present when the bot can respond.

More details on the wiki.

New Features

  • Added a appEmojis configuration function
    • This is where you enable the application emoji registry and loading
    • Enable it with botcommands.app.emojis.enable in Spring properties
  • Added AppEmojisRegistry and
    • This is where you will get your emojis, after they are loaded
  • Added @AppEmojiContainer
    • Declares a class holding ApplicationEmoji properties
    • Java user can use eagerly-loaded emojis
    • Kotlin users can use both eager and lazy emojis

Breaking changes

Misc

  • Methods in AnnotationUtils visible to Java users now accepts KAnnotatedElement instead of AnnotatedElement
    • These methods were made to be used with functions managed by the framework, such as command functions, and are KFunctions

Changes

Dependencies

  • JDA: 5.2.1 -> 5.2.2

Run-time filters

  • Allowed using @Filter as a meta-annotation

New features

Application commands

  • Added ApplicationCommandsContext#findTopLevelSlashCommand
    • Gets a TopLevelSlashCommandInfo from a guild (or global scope) and name

Command introspection

  • Added a few helpers to retrieve annotations from command functions
    • Identical to the AnnotationUtils functions, but adding convenience

Event listeners

  • Added ignoredIntents to @BEventListener
    • Allows you to ignore specific missing intents for an event listener
    • This is useful especially for message listeners, where missing the DIRECT_MESSAGES intent can be intended

Bug fixes

Application commands

  • Fixed missing description on annotated commands
  • Fixed the default command cache on macOS (#223)

Run-time filters

  • Fixed detection of run-time filters when using Spring

Don't hesitate to check out the examples and the wiki.

Full Changelog: v3.0.0-alpha.21...v3.0.0-alpha.22