Skip to content

Releases: discord-jda/JDA

v6.0.0-rc.5 | Modal Components and Serialization

14 Sep 13:57
c606efb
Compare
Choose a tag to compare

Overview

This release adds support for more components in Modals and reintroduces serialization for all components.

Modal Components (#2913)

In the previous release, support for StringSelectMenu within modals has been added. This is now expanded to also include EntitySelectMenu and TextDisplay components.

The TextDisplay component has full markdown support, which allows you to create more fleshed out modals than before:

Modal.create("modal", "Role Request Form")
    .addComponents(
        TextDisplay.of("""
            **Welcome!**
            
            Please read the following before continuing:
            
            - Select a user to request a role for
            - A moderator will review your request
            - Abuse of this system may result in penalties
            """),
        Label.of(
            "Role",
            EntitySelectMenu.create("role-select", SelectTarget.ROLE).build()
        )
    )
    .build();

Results in this modal being shown:

image

Serialization and Deserialization (#2906)

We've added a new ComponentSerializer and ComponentDeserializer, which can be used to serialize components into DataObject and FileUpload instances. This replaces the previous component.toData() from JDA 5, with a new serializer.serialize(component).

Example:

ComponentSerializer serializer = new ComponentSerializer();

List<DataObject> serializedComponents = serializer.serializeAll(message.getComponents());
List<FileUpload> files = serializer.getFileUploads(message.getComponents());

// use serialized component
// ...

// Or deserialize them if you get them from another source
// Here we pass in the List<FileUpload> used by the components
ComponentDeserializer deserializer = new ComponentDeserializer(files);
MessageComponentTree tree = deserializer.deserializeAsTree(MessageComponentTree.class, serializedComponents);

New Features

Changes

  • Deprecate and replace TextInput.Builder#setId with setCustomId by @freya022 in #2909

Bug Fixes

  • Remove unnecessary escaping while creating a masked link by @Alf-Melmac in #2910

Full Changelog: v6.0.0-rc.4...v6.0.0-rc.5

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:6.0.0-rc.5")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>6.0.0-rc.5</version> 
</dependency>

v6.0.0-rc.4 | Change to Modals

02 Sep 14:08
dd9d743
Compare
Choose a tag to compare
Pre-release

Overview

This release primarily introduces breaking changes to Modals. Discord has finally added support for StringSelectMenu in Modals, which comes with a minor breaking change in how Modals are created.

image

Breaking Changes

With the update to Modals, we removed legacy functionality around ActionRow in Modal. Instead of using ActionRow.of(...), modals make use of the new Label components instead.

Before:

Modal.create("modal", "My Modal")
    .addComponents(
      ActionRow.of(TextInput.create("input", "My Custom Label", TextInputStyle.SHORT).build()))
    .build();

After:

Modal.create("modal", "My Modal")
    .addComponents(
      Label.of("My Custom Label", TextInput.create("input", TextInputStyle.SHORT).build()))
    .build();

With this update, you can now also use StringSelectMenu in Modals, which can also be added using the Label component.

Label.of("My Custom Label",
    StringSelectMenu.create("menu-custom-id")
        .addOption("My option", "option-1")
        .build())

When a user submits a modal with a select menu, the values are available in the ModalInteractionEvent using getValue("menu-custom-id").getAsStringList().

New Features

  • Add support for Label and StringSelectMenu in Modals by @Xirado in #2162

Bug Fixes

Full Changelog: v6.0.0-rc.3...v6.0.0-rc.4

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:6.0.0-rc.4")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>6.0.0-rc.4</version> 
</dependency>

v6.0.0-rc.3 | New pin permissions and removal of bot owned guilds

23 Aug 14:38
ddd00bc
Compare
Choose a tag to compare

Overview

Another release candidate for JDA 6.0.0 with some more minor breaking changes. Modal features have been moved to a new package and functionality to bot owned guilds has been removed, including Guild#delete, Guild#transferOwnership, JDA#createGuild, and GuildManager#setMFALevel.

This release candidate also includes some underlying API changes and bug fixes that are backwards compatible, as well as some minor feature additions.

Breaking Changes

Some of these changes have been integrated into the 6.0.0 OpenRewrite recipe, please re-apply it if necessary. See the release notes for 6.0.0-rc.1 for details.

New Features

Other Changes

Bug Fixes

Full Changelog: v6.0.0-rc.2...v6.0.0-rc.3

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:6.0.0-rc.3")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>6.0.0-rc.3</version> 
</dependency>

v6.0.0-rc.2 | New Pin Pagination API

27 Jul 19:35
3f04b55
Compare
Choose a tag to compare
Pre-release

Overview

This release includes a minor breaking change to the retrievePinnedMessages method.

Originally, this method could only fetch up to 50 pinned messages. However, the underlying endpoint has been deprecated and replaced with a new paginated endpoint, as detailed in the Discord Changelog.

We have updated our API to utilize a PaginationAction. The callback response is now a list of PinnedMessage objects instead of a list of messages. Each PinnedMessage instance contains the timestamp when the message was pinned and the pinned message object. With this pagination action, the retrieval of pinned messages is no longer limited to 50 messages and can now fetch more, for instance by using takeAsync(200).

To replicate the previous behavior (retrieving only up to 50 pinned messages), you can use queue() as before, but you will need to map the list to a List<Message> as follows:

channel.retrievePinnedMessages()
  .map(list -> list.stream().map(PinnedMessage::getMessage).toList())
  .queue(list -> ...);

Changes

Full Changelog: v6.0.0-rc.1...v6.0.0-rc.2

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:6.0.0-rc.2")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>6.0.0-rc.2</version> 
</dependency>

v6.0.0-rc.1 | New Components

20 Jul 14:51
8bc17a4
Compare
Choose a tag to compare
Pre-release

Overview

Warning

This is the first release candidate for JDA 6.0.0. The major version bump reflects several breaking changes to the message and modal component APIs. Additional breaking changes may still be introduced before the final stable release of 6.0.0.

This version introduces support for Components Version 2, a significant update to Discord's component system. To accommodate this new API, we’ve made a number of key changes to our component implementation:

  • All components are now immutable
    Previously, ActionRow allowed modification of its contained components. To simplify and modernize the API, this mutability has been removed.

  • New top-level component interfaces
    The LayoutComponent interface (previously only implemented by ActionRow) has been replaced by two new interfaces:
    - MessageTopLevelComponent
    - ModalTopLevelComponent
    This change reflects the increased flexibility introduced in Components V2, where top-level components are no longer restricted to layout containers like ActionRow. Components such as TextDisplay and FileDisplay can now appear directly at the top level.

  • Renamed getIdgetCustomId
    The original getId method has been renamed to getCustomId to avoid confusion with Discord's new getUniqueId, which is a numeric, auto-generated identifier.

  • Temporary removal of toData for components
    Some components now require attachments to function properly, complicating serialization. We’ve removed the toData method for now and are working on a new, more capable serialization API that will be introduced in a later update.

Big thanks to @freya022 and @DV8FromTheWorld for contributing on this giant feature!

Using Components V2

To use the new components introduced in this release, you must enable the Components V2 feature flag on your message request. This can be done using the useComponentsV2 method on MessageRequest.

Tip

Enabling this flag comes with certain limitations, so we strongly recommend reviewing the documentation for important details before integrating it into your project.

To get started, check out the new ComponentsV2Example to explore the possibilities of this updated API. You can also see it in action in a demo project by @DV8FromTheWorld: discord-pokedex.

pokemon-card

New Components

JDA 6 introduces several new component types as part of the Components V2 system:

  • Container
    Displays components inside a visually distinct box — similar to how embeds are styled.

  • Thumbnail
    Shows a small image next to text. Commonly used as an accessory within a Section component.

  • FileDisplay
    Displays a file attachment as a downloadable item. For visual file content (e.g., images), consider using MediaGallery instead.

  • MediaGallery
    Shows multiple images in a gallery layout — similar to a list of image attachments in Discord.

  • Section
    Displays a block of text content with optional accessories like thumbnails or buttons.

  • Separator
    Adds vertical spacing between components, helping visually organize content.

  • TextDisplay
    A simple text component used to display content without relying on the content field of a message.

Note

Components that use files, such as FileDisplay or MediaGallery, will automatically attach files as message attachments in your requests.

New Utilities For Components

Several new utilities have been added to simplify working with complex component structures — including traversal, replacement, and deserialization:

Migrating To 6.0.0

To help ease the upgrade to JDA 6.0.0, we've provided an OpenRewrite recipe that can automatically refactor parts of your codebase. This will update imports and replace a few method calls with their new equivalents in JDA 6.0.0.

However, not all breaking changes can be handled automatically — for example, code that relied on the mutability of ActionRow will require manual adjustments.

The OpenRewrite Recipe

Before applying the recipe, make sure you’re using version control (e.g., Git) or back up your project manually. You’ll also need to be using Gradle or Maven to apply the migration.

Gradle

We are using the OpenRewrite Gradle Plugin. Before changing your JDA version in gradle, you can add the rewrite plugin and use the recipe to migrate your code:

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

repositories {
    mavenCentral()
}

dependencies {
    // Your current JDA version before upgrading to 6.0.0
    implementation("net.dv8tion:JDA:5.+")

    // The current 6.0.0 release version
    rewrite("net.dv8tion:JDA:6.0.0-rc.1")
    rewrite("org.openrewrite.recipe:rewrite-java-dependencies:1.37.0")
}

rewrite {
    activeRecipe("net.dv8tion.MigrateComponentsV2")
}

Once you configured this plugin, you can use the rewriteDryRun task to generate a git patch in build/reports/rewrite/rewrite.patch to see what the plugin will do with your source code. To apply the changes, either use this patch or use rewriteRun.

After migrating your code, you can then update your JDA version (if the rewrite hasn't done it already) and remove the plugin again.

Maven

We are using the OpenRewrite Maven Plugin. Before changing your JDA version in your pom, you can add the rewrite plugin and use the recipe to migrate your code:

<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>6.13.0</version>
  <configuration>
    <activeRecipes>
      <recipe>net.dv8tion.MigrateComponentsV2</recipe>
    </activeRecipes>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.openrewrite.recipe</groupId>
      <artifactId>rewrite-java-dependencies</artifactId>
      <version>1.37.0</version>
    </dependency>
    <dependency>
      <groupId>net.dv8tion</groupId>
      <artifactId>JDA</artifactId>
      <version>6.0.0-rc.1</version>
    </dependency>
  </dependencies>
</plugin>

Once you configured this plugin, you can use the rewrite:dryRun task to generate a git patch in target/site/rewrite/rewrite.patch to see what the plugin will do with your source code. To apply the changes, either use this patch or use rewrite:run.

After migrating your code, you can then update your JDA version (if the rewrite hasn't done it already) and remove the plugin again.

The ComponentReplacer

If you previously used LayoutComponent.updateComponents or changed an action row with the mutable getComponents(), you will have to migrate your code to the new ComponentReplacer instead.

Before:

List<LayoutComponent> components = message.getComponents();

LayoutComponent.updateComponent(
    components,
    "my-component-id",
    Button.primary("button-id", "Click me").asDisabled()
);

After:

MessageComponentTree components = message.getComponentTree();
...
Read more

v5.6.1

08 Jun 18:44
f8e78d6
Compare
Choose a tag to compare

Bug Fixes

Full Changelog: v5.6.0...v5.6.1

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:5.6.1")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>5.6.1</version> 
</dependency>

v5.6.0 | ApplicationManager and minor improvements

07 Jun 21:09
8e687c8
Compare
Choose a tag to compare

Overview

This release introduces the ApplicationManager, which can be used to update the application's description and other settings through JDA.

New Features

Changes

  • Add with_components=true query param to WebhookClient requests by @Xirado in #2850
  • Set thread ID when manipulating message objects made by webhooks by @freya022 in #2849

Bug Fixes

Full Changelog: v5.5.1...v5.6.0

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:5.6.0")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>5.6.0</version> 
</dependency>

v5.5.1 | Bug fixes and performance improvements

03 May 11:31
99d1f98
Compare
Choose a tag to compare

Overview

This is a small release, including a bug fix for editCommand and editCommandById, as well as some performance improvements for looking up members by roles.

Additionally, you can now create threads with a custom slowmode.

New Features

Bug Fixes

Full Changelog: v5.5.0...v5.5.1

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:5.5.1")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>5.5.1</version> 
</dependency>

v5.5.0 | Improved voice state cache and file proxies

27 Apr 14:01
b919401
Compare
Choose a tag to compare

Changes to voice state cache (#2835)

Voice states are now cached independently of guild members. JDA can now detect when a member connects or disconnects from an audio channel, even when the member is not currently cached.

With this change, you can technically use MemberCachePolicy.NONE and will still receive voice join / leave events, as long as CacheFlag.VOICE_STATE is enabled.

To reduce the memory footprint, we now only cache voice states if the member is connected to an audio channel. While disconnected, we will not keep the voice state cached, meaning we lose track of muted/deafend state and return an "empty" voice state for Member#getVoiceState.

Improvements to FileProxy (#2782 and #2727)

The FileProxy, ImageProxy, and AttachmentProxy now all support downloadAsFileUpload to easily stream a Discord proxies URL to a message.

@Override
public void onMessageReceived(MessageReceivedEvent event) {
    List<Message.Attachment> attachments = event.getMessage().getAttachments();

    List<FileUpload> uploads = attachments.stream()
        .map(attachment ->
            attachment
                .getProxy()
                .downloadAsFileUpload(attachment.getWidth(), attachment.getHeight()))
        .collect(Collectors.toList());
    
    event.getChannel().sendFiles(uploads).queue();
}

New Features

Changes

Bug Fixes

Full Changelog: v5.4.0...v5.5.0

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:5.5.0")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>5.5.0</version> 
</dependency>

v5.4.0 | Interaction callback response and security incidents

20 Apr 14:42
2b972ab
Compare
Choose a tag to compare

Access the created or updated message from interaction replies (#2798)

You can now use InteractionHook#getCallbackResponse to access the messages created by interaction replies.

@Override
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
  event.reply("React with your favorite emoji")
    .map(hook -> hook.getCallbackResponse().getMessage())
    .flatMap(message -> message.addReaction(emoji))
    .queue();
}

Previously, this could be done using an additional retrieveOriginal request. To reduce requests and improve responsiveness, we recommend preferring this new getter instead.

Guild security incidents (#2577)

With guild security incidents, you can now be aware when Discord detects raids or spam in direct messages in a guild. These detections are available with Guild#getSecurityIncidentDetections and are updated with GuildUpdateSecurityIncidentDetectionsEvent.

Additionally, you can modify the security incident actions to temporarily pause invites or disable direct messages in your guild. See Guild#modifySecurityIncidents for details.

guild.modifySecurityIncidents(SecurityIncidentActions.enabled(
        // Pause invites for 2 hours
        OffsetDateTime.now().plusHours(2),
        // Disable direct messages for 1 hour
        OffsetDateTime.now().plusHours(1)
)).queue();

// Or disable security incident actions prematurely
guild.modifySecurityIncidents(SecurityIncidentActions.disabled()).queue();

New Features

Changes

  • Add missing exceptions when attempting to move entities before selecting by @freya022 in #2797

Bug Fixes

  • Prevent firing voice state update events if member is not cached by @freya022 in #2773
  • Fix FileProxy#withClient return types by @freya022 in #2698

Full Changelog: v5.3.2...v5.4.0

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    implementation("net.dv8tion:JDA:5.4.0")
}

Maven

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>5.4.0</version> 
</dependency>