Giter Site home page Giter Site logo

dv8fromtheworld / jda Goto Github PK

View Code? Open in Web Editor NEW
4.1K 83.0 712.0 32.3 MB

Java wrapper for the popular chat & VOIP service: Discord https://discord.com

License: Apache License 2.0

Java 99.96% HTML 0.04%
discord rest-api websocket java rest javadoc bot bot-api jda promoted-downloads api-wrapper api hacktoberfest

jda's Introduction

maven-central jitpack jenkins-shield license-shield

discord-shield faq-shield docs-shield troubleshooting-shield migration-shield

JDA (Java Discord API)

JDA strives to provide a clean and full wrapping of the Discord REST API and its WebSocket-Events for Java. This library is a helpful tool that provides the functionality to create a Discord bot in Java.

Summary

  1. Introduction
  2. Sharding
  3. Entity Lifetimes
  4. Download
  5. Documentation
  6. Support
  7. Extensions And Plugins
  8. Contributing
  9. Dependencies
  10. Other Libraries

UserBots and SelfBots

Discord is currently prohibiting creation and usage of automated client accounts (AccountType.CLIENT). We have officially dropped support for client login as of version 4.2.0! If you need a bot, use a bot account from the Application Dashboard.

Read More

Creating the JDA Object

Creating the JDA Object is done via the JDABuilder class. After setting the token and other options via setters, the JDA Object is then created by calling the build() method. When build() returns, JDA might not have finished starting up. However, you can use awaitReady() on the JDA object to ensure that the entire cache is loaded before proceeding. Note that this method is blocking and will cause the thread to sleep until startup has completed.

Example:

JDA jda = JDABuilder.createDefault("token").build();

Configuration

Both the JDABuilder and the DefaultShardManagerBuilder allow a set of configurations to improve the experience.

Example:

public static void main(String[] args) {
    JDABuilder builder = JDABuilder.createDefault(args[0]);
    
    // Disable parts of the cache
    builder.disableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE);
    // Enable the bulk delete event
    builder.setBulkDeleteSplittingEnabled(false);
    // Set activity (like "playing Something")
    builder.setActivity(Activity.watching("TV"));
    
    builder.build();
}

See JDABuilder and DefaultShardManagerBuilder

You can configure the memory usage by changing enabled CacheFlags on the JDABuilder. Additionally, you can change the handling of the member/user cache by disabling intents or changing the member cache policy. To learn more about intents and member loading/caching, read the Gateway Intents Guide.

public void configureMemoryUsage(JDABuilder builder) {
    // Disable cache for member activities (streaming/games/spotify)
    builder.disableCache(CacheFlag.ACTIVITY);

    // Only cache members who are either in a voice channel or owner of the guild
    builder.setMemberCachePolicy(MemberCachePolicy.VOICE.or(MemberCachePolicy.OWNER));

    // Disable member chunking on startup
    builder.setChunkingFilter(ChunkingFilter.NONE);

    // Disable presence updates and typing events
    builder.disableIntents(GatewayIntent.GUILD_PRESENCE, GatewayIntent.GUILD_MESSAGE_TYPING);

    // Consider guilds with more than 50 members as "large". 
    // Large guilds will only provide online members in their setup and thus reduce bandwidth if chunking is disabled.
    builder.setLargeThreshold(50);
}

Listening for Events

The event system in JDA is configured through a hierarchy of classes/interfaces. We offer two implementations for the IEventManager:

  • InterfacedEventManager which uses an EventListener interface and the ListenerAdapter abstract class
  • AnnotatedEventManager which uses the @SubscribeEvent annotation which can be applied to methods

By default, the InterfacedEventManager is used. Since you can create your own implementation of IEventManager, this is a very versatile and configurable system. If the aforementioned implementations don't suit your use-case you can simply create a custom implementation and configure it on the JDABuilder with setEventManager(...).

Examples:

Using EventListener:

public class ReadyListener implements EventListener {
    public static void main(String[] args) throws InterruptedException {
        // Note: It is important to register your ReadyListener before building
        JDA jda = JDABuilder.createDefault("token")
            .addEventListeners(new ReadyListener())
            .build();

        // optionally block until JDA is ready
        jda.awaitReady();
    }

    @Override
    public void onEvent(GenericEvent event) {
        if (event instanceof ReadyEvent) {
            System.out.println("API is ready!");
        }
    }
}

Using ListenerAdapter:

public class MessageListener extends ListenerAdapter {
    public static void main(String[] args) {
        JDA jda = JDABuilder.createDefault("token")
                .enableIntents(GatewayIntent.MESSAGE_CONTENT) // enables explicit access to message.getContentDisplay()
                .build();
        //You can also add event listeners to the already built JDA instance
        // Note that some events may not be received if the listener is added after calling build()
        // This includes events such as the ReadyEvent
        jda.addEventListener(new MessageListener());
    }

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        if (event.isFromType(ChannelType.PRIVATE)) {
            System.out.printf("[PM] %s: %s\n", event.getAuthor().getName(),
                                    event.getMessage().getContentDisplay());
        } else {
            System.out.printf("[%s][%s] %s: %s\n", event.getGuild().getName(),
                        event.getTextChannel().getName(), event.getMember().getEffectiveName(),
                        event.getMessage().getContentDisplay());
        }
    }
}

Slash-Commands:

public class Bot extends ListenerAdapter {
    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("You have to provide a token as first argument!");
            System.exit(1);
        }
        // args[0] would be the token (using an environment variable or config file is preferred for security)
        // We don't need any intents for this bot. Slash commands work without any intents!
        JDA jda = JDABuilder.createLight(args[0], Collections.emptyList())
            .addEventListeners(new Bot())
            .setActivity(Activity.playing("Type /ping"))
            .build();

        // Sets the global command list to the provided commands (removing all others)
        jda.updateCommands().addCommands(
            Commands.slash("ping", "Calculate ping of the bot"),
            Commands.slash("ban", "Ban a user from the server")
                    .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.BAN_MEMBERS)) // only usable with ban permissions
                    .setGuildOnly(true) // Ban command only works inside a guild
                    .addOption(OptionType.USER, "user", "The user to ban", true) // required option of type user (target to ban)
                    .addOption(OptionType.STRING, "reason", "The ban reason") // optional reason
        ).queue();
    }
    
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
        // make sure we handle the right command
        switch (event.getName()) {
            case "ping":
                long time = System.currentTimeMillis();
                event.reply("Pong!").setEphemeral(true) // reply or acknowledge
                     .flatMap(v ->
                          event.getHook().editOriginalFormat("Pong: %d ms", System.currentTimeMillis() - time) // then edit original
                     ).queue(); // Queue both reply and edit
                break;
            case "ban":
                // double check permissions, don't trust Discord on this!
                if (!event.getMember().hasPermission(Permission.BAN_MEMBERS)) {
                    event.reply("You cannot ban members! Nice try ;)").setEphemeral(true).queue();
                    break;
                }
                User target = event.getOption("user", OptionMapping::getUser);
                // optionally check for member information
                Member member = event.getOption("user", OptionMapping::getMember);
                if (!event.getMember().canInteract(member)) {
                    event.reply("You cannot ban this user.").setEphemeral(true).queue();
                    break;
                }
                // Before starting our ban request, tell the user we received the command
                // This sends a "Bot is thinking..." message which is later edited once we finished
                event.deferReply().queue();
                String reason = event.getOption("reason", OptionMapping::getAsString);
                AuditableRestAction<Void> action = event.getGuild().ban(target, 0); // Start building our ban request
                if (reason != null) // reason is optional
                    action = action.reason(reason); // set the reason for the ban in the audit logs and ban log
                action.queue(v -> {
                    // Edit the thinking message with our response on success
                    event.getHook().editOriginal("**" + target.getAsTag() + "** was banned by **" + event.getUser().getAsTag() + "**!").queue();
                }, error -> {
                    // Tell the user we encountered some error
                    event.getHook().editOriginal("Some error occurred, try again!").queue();
                    error.printStackTrace();
                });
                break;
            default:
                System.out.printf("Unknown command %s used by %#s%n", event.getName(), event.getUser());
        }
    }
}

RestAction

Through RestAction we provide request handling with

and it is up to the user to decide which pattern to utilize. It can be combined with reactive libraries such as reactor-core due to being lazy.

The RestAction interface also supports a number of operators to avoid callback hell:

  • map Convert the result of the RestAction to a different value
  • flatMap Chain another RestAction on the result
  • delay Delay the element of the previous step

Example:

public RestAction<Void> selfDestruct(MessageChannel channel, String content) {
    return channel.sendMessage("The following message will destroy itself in 1 minute!")
        .delay(10, SECONDS, scheduler) // edit 10 seconds later
        .flatMap((it) -> it.editMessage(content))
        .delay(1, MINUTES, scheduler) // delete 1 minute later
        .flatMap(Message::delete);
}

More Examples

We provide a small set of Examples in the Example Directory.

Sharding a Bot

When your bot joins over 2500 guilds, it is required to perform Sharding. This means, your connection is split up into multiple shards, each only accessing a fraction of your total available guilds. A shard can at most contain 2500 guilds when starting up the bot.

Each shard is assigned a shard id and shard total (usually shown as id / total), which uniquely identifies which guilds are accessible on that shard. For instance, the first of 2 shards would be 0 / 2 and the second would be 1 / 2.

If you want to use sharding with your bot, make use of the DefaultShardManager as seen in the example below. This manager automatically assigns the right number of shards to your bot, so you do not need to do any math yourself.

Internally, this shard manager also handles the proper scaling of threads for connections and handles the login rate-limit (Identify Rate-Limit) to properly startup without issues.

If you do not want to use the shard manager, and instead manage sharding yourself, you can use JDABuilder#useSharding and ConcurrentSessionController.

Example Sharding - Using DefaultShardManager

public static void main(String[] args) {
    DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(args[0]);
    builder.addEventListeners(new MessageListener());
    builder.build();
}

Entity Lifetimes

An Entity is the term used to describe types such as GuildChannel/Message/User and other entities that Discord provides. Instances of these entities are created and deleted by JDA when Discord instructs it. This means the lifetime depends on signals provided by the Discord API which are used to create/update/delete entities. This is done through Gateway Events known as "dispatches" that are handled by the JDA WebSocket handlers. When Discord instructs JDA to delete entities, they are simply removed from the JDA cache and lose their references. Once that happens, nothing in JDA interacts or updates the instances of those entities, and they become outdated. Discord may instruct to delete these entities randomly for cache synchronization with the API.

It is not recommended to store any of these entities for a longer period of time! Instead of keeping (e.g.) a User instance in some field, an ID should be used. With the ID of a user, you can use getUserById(id) to get and keep the user reference in a local variable (see below).

Entity Updates

When an entity is updated through its manager, they will send a request to the Discord API which will update the state of the entity. The success of this request does not imply the entity has been updated yet. All entities are updated by the aforementioned Gateway Events which means you cannot rely on the cache being updated yet once the execution of a RestAction has completed. Some requests rely on the cache being updated to correctly update the entity. An example of this is updating roles of a member which overrides all roles of the member by sending a list of the new set of roles. This is done by first checking the current cache, the roles the member has right now, and appending or removing the requested roles. If the cache has not yet been updated by an event, this will result in unexpected behavior.

Entity Deletion

Discord may request that a client (the JDA session) invalidates its entire cache. When this happens, JDA will remove all of its current entities and reconnect the session. This is signaled through the SessionRecreateEvent. When entities are removed from the JDA cache, your instance will keep stale entities in memory. This results in memory duplication, potential memory leaks, and outdated state. It is highly recommended to only keep references to entities by storing their id and using the respective get...ById(id) method when needed. Alternatively, keep the entity stored and make sure to replace it as soon as possible when the cache is replaced.

Example

public class UserLogger extends ListenerAdapter {
    private final User user;
    
    public UserLogger(User user) {
        this.user = user;
    }
    
    private User getUser(JDA api) {
        // Acquire a reference to the User instance through the id
        User newUser = api.getUserById(this.user.getIdLong());
        if (newUser != null)
            this.user = newUser;
        return this.user;
    }
    
    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        User author = event.getAuthor();
        Message message = event.getMessage();
        if (author.getIdLong() == this.user.getIdLong()) {
            // Update user from message instance (likely more up-to-date)
            this.user = author;
            // Print the message of the user
            System.out.println(author.getAsTag() + ": " + message.getContentDisplay());
        }
    }
    
    @Override
    public void onGuildJoin(GuildJoinEvent event) {
        JDA api = event.getJDA();
        User user = getUser(); // use getter to refresh user automatically on access
        user.openPrivateChannel().queue((channel) -> {
            // Send a private message to the user
            channel.sendMessageFormat("I have joined a new guild: **%s**", event.getGuild().getName()).queue();
        });
    }
}

Download

maven-central jitpack

Latest Release: GitHub Release

Be sure to replace the VERSION key below with the one of the versions shown above! For snapshots, please use the instructions provided by JitPack.

Maven

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

Maven without Audio

<dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId>
    <version>VERSION</version>
    <exclusions>
        <exclusion>
            <groupId>club.minnced</groupId>
            <artifactId>opus-java</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Gradle

repositories {
    mavenCentral()
}

dependencies {
    //Change 'implementation' to 'compile' in old Gradle versions
    implementation("net.dv8tion:JDA:VERSION")
}

Gradle without Audio

dependencies {
    //Change 'implementation' to 'compile' in old Gradle versions
    implementation("net.dv8tion:JDA:VERSION") {
        exclude module: 'opus-java'
    }
}

The snapshot builds are only available via JitPack and require adding the JitPack resolver, you need to specify specific commits to access those builds. Stable releases are published to maven-central.

If you do not need any opus de-/encoding done by JDA (voice receive/send with PCM) you can exclude opus-java entirely. This can be done if you only send audio with an AudioSendHandler which only sends opus (isOpus() = true). (See lavaplayer)

If you want to use a custom opus library you can provide the absolute path to OpusLibrary.loadFrom(String) before using the audio API of JDA. This works without opus-java-natives as it only requires opus-java-api.
For this setup you should only exclude opus-java-natives as opus-java-api is a requirement for en-/decoding.

See opus-java

Logging Framework - SLF4J

JDA is using SLF4J to log its messages.

That means you should add some SLF4J implementation to your build path in addition to JDA. If no implementation is found, following message will be printed to the console on startup:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

JDA currently provides a fallback Logger in case that no SLF4J implementation is present. We strongly recommend to use one though, as that can improve speed and allows you to customize the Logger as well as log to files

There is a guide for logback-classic available in our wiki: Logging Setup

Documentation

Docs can be found on the GitHub Pages
We also have a wiki filled with information and troubleshooting guides at jda.wiki

Annotations

We use a number of annotations to indicate future plans for implemented functionality such as new features of the Discord API.

  • Incubating
    This annotation is used to indicate that functionality may change in the future. Often used when a new feature is added.
  • ReplaceWith
    Paired with @Deprecated this is used to inform you how the new code-fragment is supposed to look once the hereby annotated functionality is removed.
  • ForRemoval
    Paired with @Deprecated this indicates that we plan to entirely remove the hereby annotated functionality in the future.
  • DeprecatedSince
    Paired with @Deprecated this specifies when a feature was marked as deprecated.

Sources

Getting Help

For general troubleshooting you can visit our wiki Troubleshooting and FAQ.
If you need help, or just want to talk with the JDA or other Devs, you can join the Official JDA Discord Guild.

Alternatively you can also join the Unofficial Discord API Guild. Once you joined, you can find JDA-specific help in the #java_jda channel.

For guides and setup help you can also take a look at the wiki
Especially interesting are the Getting Started and Setup Pages.

Third Party Recommendations

Created by sedmelluq and now maintained by the lavalink community
Lavaplayer is the most popular library used by Music Bots created in Java. It is highly compatible with JDA and Discord4J and allows to play audio from Youtube, Soundcloud, Twitch, Bandcamp and more providers.
The library can easily be expanded to more services by implementing your own AudioSourceManager and registering it.

It is recommended to read the Usage section of Lavaplayer to understand a proper implementation.
Sedmelluq provided a demo in his repository which presents an example implementation for JDA: https://github.com/lavalink-devs/lavaplayer/tree/master/demo-jda

Created by Freya Arbjerg and now maintained by the lavalink community.

Lavalink is a popular standalone audio sending node based on Lavaplayer. Lavalink was built with scalability in mind, and allows streaming music via many servers. It supports most of Lavaplayer's features.

Lavalink is used by many large bots, as well as bot developers who can not use a Java library like Lavaplayer. If you plan on serving music on a smaller scale with JDA it is often preferable to just use Lavaplayer directly as it is easier.

Lavalink-Client is the official Lavalink client for JDA.

Created and maintained by sedmelluq and extended by MinnDevelopment
Provides a native implementation for the JDA Audio Send-System to avoid GC pauses.

Note that this send system creates an extra UDP-Client which causes audio receive to no longer function properly, since Discord identifies the sending UDP-Client as the receiver.

JDABuilder builder = JDABuilder.createDefault(BOT_TOKEN)
    .setAudioSendFactory(new NativeAudioSendFactory());

Created and maintained by MinnDevelopment.
Provides Kotlin extensions for RestAction and events that provide a more idiomatic Kotlin experience.

fun main() {
    val jda = light(BOT_TOKEN)
    
    jda.onCommand("ping") { event ->
        val time = measureTime {
            event.reply("Pong!").await() // suspending
        }.inWholeMilliseconds

        event.hook.editOriginal("Pong: $time ms").queue()
    }
}

There is a number of examples available in the README.


More can be found in our github organization: JDA-Applications

Contributing to JDA

If you want to contribute to JDA, make sure to base your branch off of our master branch (or a feature-branch) and create your PR into that same branch.

More information can be found at the wiki page Contributing.

Versioning and Deprecation Policy

Since the Discord API is in itself a moving standard, the stability is never guaranteed. For this reason, JDA does not follow the common semver versioning strategy.

The JDA version is structured with a looser definition, where the version change indicates the significance of changes. For instance, using 5.1.2 as a baseline:

  • A change to the major like 6.0.0 indicates that a lot of code has to be adjusted due to major changes to the interfaces. A change like this always comes with a full migration guide like Migrating from 4.X to 5.X.
  • A change to the minor like 5.2.0 indicates some code may need to be adjusted due to the removal or change of interfaces. You can usually find the necessary changes in the release documentation.
  • A change to the patch like 5.1.3 indicates bug fixes and new feature additions that are backwards compatible.

If a feature is marked as deprecated, it usually also indicates an alternative. For instance:

@Deprecated
@DeprecatedSince("5.1.2")
@ForRemoval(deadline="5.2.0")
@ReplaceWith("setFoo(foo)")
public void changeFoo(Foo foo) { ... }

The method changeFoo was deprecated in release 5.1.2 and is going to be removed in 5.2.0. Your change should replace all usage of changeFoo(foo) with setFoo(foo).

Sometimes, a feature might be removed without a replacement. This will be clearly explained in the documentation.

Dependencies:

This project requires Java 8+.
All dependencies are managed automatically by Gradle.

  • NV WebSocket Client
  • OkHttp
  • Apache Commons Collections4
  • jackson
  • Trove4j
  • slf4j-api
  • opus-java (optional)

Related Projects

See also: Discord API Community Libraries

jda's People

Contributors

almighty-alpaca avatar almighty-satan avatar andre601 avatar artuto avatar arynxd avatar averen avatar cheesygamer77 avatar dmanstrator avatar duncte123 avatar dv8fromtheworld avatar fabricio20 avatar freya022 avatar freyacodes avatar implosions avatar jagrosh avatar kantenkugel avatar kazuryyx avatar minndevelopment avatar mitmocc avatar mlnrdev avatar natanbc avatar nikammerlaan avatar oliver276 avatar randomnetcat avatar reddaedalus avatar sanduhr32 avatar schnapster avatar shredder121 avatar tais993 avatar xirado avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jda's Issues

Example 2 does not work - MessageChannel.getName() does not exist

The second example does not work - the getName() call in event.getChannel().getName() does not work.

I think this is potentially related to the fact that although the Channel interface has a getName(), the MessageChannel interface, which getChannel() returns, does not.

event.getTextChannel().getName() works, but I don't think it would work in a private chat, as that's a separate interface.

Minor issue, but I felt that I should mention it, since it's on the front page of the API, essentially.

JDASocket unable to reconnect

It looks like my music bot got disconnected from the web socket, so it attempted to reconnect. However, when it does reconnect it throws this IllegalStateException and it disconnects. It looks like this in the log:

[17:08:19] [Warning] [JDASocket]: Got disconnected from WebSocket (Internet?!)... Attempting to reconnect in 2s
[17:08:21] [Warning] [JDASocket]: Attempting to reconnect!
[17:08:22] [Info] [JDASocket]: Connected to WebSocket
[17:08:22] [Fatal] [JDASocket]: Encountered an exception:
[17:08:22] [Fatal] [JDASocket]: java.lang.IllegalStateException: Already attempting to start an AudioConnection with a VoiceChannel!
Currently Attempting Channel ID: 204878762926407681  |  New Attempt Channel ID: 204878762926407681
    at net.dv8tion.jda.managers.impl.AudioManagerImpl.openAudioConnection(AudioManagerImpl.java:71)
    at net.dv8tion.jda.requests.WebSocketClient.reconnectAudioConnections(WebSocketClient.java:535)
    at net.dv8tion.jda.requests.WebSocketClient.ready(WebSocketClient.java:133)
    at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:584)
    at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:324)
    at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352)
    at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233)
    at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211)
    at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910)
    at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693)
    at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102)
    at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

[17:08:22] [Warning] [JDASocket]: Got disconnected from WebSocket (Internet?!)... Attempting to reconnect in 2s
[17:08:24] [Warning] [JDASocket]: Attempting to reconnect!
[17:08:25] [Info] [JDASocket]: Connected to WebSocket
[etc]

This cycle would then repeat until I terminated my bot, but it was unusable until then. This is possibly related to #110.

ConcurrentModificationException

I booted my bot today and it caught this error. To me, it looks like an error with JDA but I could be wrong. Could somebody confirm?

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at net.dv8tion.jda.utils.PermissionUtil.getEffectivePermission(PermissionUtil.java:215)
at net.dv8tion.jda.utils.PermissionUtil.getEffectivePermission(PermissionUtil.java:240)
at net.dv8tion.jda.utils.PermissionUtil.checkPermission(PermissionUtil.java:234)
at net.dv8tion.jda.utils.PermissionUtil.checkPermission(PermissionUtil.java:129)
at net.dv8tion.jda.entities.impl.TextChannelImpl.checkPermission(TextChannelImpl.java:289)
at net.dv8tion.jda.entities.impl.TextChannelImpl.sendMessageAsync(TextChannelImpl.java:208)
at net.dv8tion.jda.entities.impl.TextChannelImpl.sendMessageAsync(TextChannelImpl.java:200)
at com.erisbot.listeners.OtherListener.onReady(OtherListener.java:23)
at net.dv8tion.jda.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:149)
at net.dv8tion.jda.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:64)
at net.dv8tion.jda.requests.WebSocketClient.ready(WebSocketClient.java:120)
at net.dv8tion.jda.handle.ReadyHandler.finishReady(ReadyHandler.java:137)
at net.dv8tion.jda.handle.ReadyHandler.onGuildInit(ReadyHandler.java:122)
at net.dv8tion.jda.handle.GuildJoinHandler.lambda$handleInternally$45(GuildJoinHandler.java:44)
at net.dv8tion.jda.handle.EntityBuilder.createGuildFirstPass(EntityBuilder.java:213)
at net.dv8tion.jda.handle.GuildJoinHandler.handleInternally(GuildJoinHandler.java:38)
at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:38)
at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:607)
at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:315)
at net.dv8tion.jda.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:680)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:368)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:243)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:937)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:696)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102)
at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

EventListener and ListenerAdapter at the same time

Can't use EventListener and ListenerAdapter at the same time. JDA forces itself to just use EventListener. It should at least throw an exception instead of being silently quiet.

public class DiscordBotMain {
    public static void main(String[] args) {
        JDA jda = new JDABuilder().setBotToken(###).buildBlocking();
        jda.addEventListener(new DiscordBot());
    }
}
public class DiscordBot extends ListenerAdapter implements EventListener {
    @Override
    public void onMessageReceived(MessageReceivedEvent event)
    {
        System.out.println("Message");
    }

    @Override
    public void onEvent(Event event)
    {
        System.out.println("Event!");
    }
}

VoiceStatus of users is not correct at startup

VoiceStatus appears to only be correct for joins/changes/leaves made after the bot has connected.
Example Scenario:

  1. User joins a voice channel
  2. Bot starts up
  3. User uses a command that requires being in a voice channel
  4. According to bot, user is not in the voice channel
  5. User moves to a different channel and back
  6. User uses same command; success.

Note: Might be related to #112

Receive Audio

I got sending audio working, but what I need is to receive audio.
I understand that I need to create an AudioReceiveHandler and play sound from the AudioPacket provided in the handleReceivedAudio function.
The problem is how do I play the audio from the byte array?
Hope someone can help me

LOADING_SUBSYSTEMS doesn't reset to CONNECTED on reconnect

After a few hours of operation, my bot will disconnect from Discord randomly.

Upon reconnect, JDA will setup everything as usual and will change it's status as it should. Once it's ready, it should set it to "CONNECTED" but it doesn't. It'll sometimes find it's self stuck on "LOADING_SUBSYSTEMS" but JDA will be operational. Responding to commands, processing data.

I'm not exactly sure what this could be but I'm guessing upon reconnect it's failing to set it's status. Everything else seems fine.

Running 5 shards with around 900 guilds per shard if that helps anything. Could be a sharding issue, not sure.

Image: https://i.imgur.com/h67Uonb.png

MP3 music files throwing IOException: Resetting to invalid mark

When reading certain mp3 files i get the following:

java.io.IOException: Resetting to invalid mark at java.io.BufferedInputStream.reset(BufferedInputStream.java:448) at org.tritonus.share.sampled.file.TAudioFileReader.getAudioInputStream(TAudioFileReader.java:339) at javazoom.spi.mpeg.sampled.file.MpegAudioFileReader.getAudioInputStream(MpegAudioFileReader.java:583) at javazoom.spi.mpeg.sampled.file.MpegAudioFileReader.getAudioInputStream(MpegAudioFileReader.java:493) at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1181) at com.ddoggy99.discordbot.handlers.MusicHandler.playMusic(MusicHandler.java:108) at com.ddoggy99.discordbot.handlers.CommandHandler.onCommandPlay(CommandHandler.java:37) at com.ddoggy99.discordbot.handlers.CommandHandler.processCommand(CommandHandler.java:87) at com.ddoggy99.discordbot.handlers.CommandHandler.onMessageReceived(CommandHandler.java:75) at net.dv8tion.jda.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:178) at net.dv8tion.jda.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:64) at net.dv8tion.jda.handle.MessageReceivedHandler.handleInternally(MessageReceivedHandler.java:79) at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:38) at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:571) at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:310) at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211) at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910) at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693) at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102) at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61) Caused by: java.io.IOException: Resetting to invalid mark at java.io.BufferedInputStream.reset(BufferedInputStream.java:448) at org.tritonus.share.sampled.file.TAudioFileReader.getAudioInputStream(TAudioFileReader.java:390) at org.tritonus.share.sampled.file.TAudioFileReader.getAudioInputStream(TAudioFileReader.java:329) ... 20 more

Some do work normally using mp3 and using Intellij's IDEA Debugging I can set the mark to 0 and it will then load the file fine and play it.
I am using the latest dev build 2.0.0_283 and have tried with the recommended 2.0.0_243

.getAudioManager() isn't independent

I'm not sure if this is a design flaw or intended but when using the audio feature of the bot on multiple servers, it struggles to work out which is which. I'm able to control the music for 1 server from another. Is this intended?

Missing Permission bit

I was taking a look at your source for Permission as I was having a weird issue with the position of permissions in my library and it seems that you are missing the Use External Emojis bit which is at position 18.

Muted channels not found

Message from the API (is this just an error log?):
I have removed the json because it contains information from my server. I don't know what response is this that you are logging for this error. If you need it in order to fix, tell me.

Got an unexpected Json-parse error. Please redirect following message to the devs:
JSONObject["muted_channels"] not found.
READY -> {"user_settings":{"inline_embed_media":true,"render_embeds":true,"inline_attachment_media":true,"show_current_game":true,"theme":"dark","enable_tts_command":true,"locale":"pt-BR","convert_emoticons":true,"message_display_compact":true},"read_state": ...

sendMessage in onPrivateMessageReceived causes message spamming.

First let me say i picked up this API around midnight last night and thanks to its ease of use i had a working bot in 5 hours. Thanks for making this.

Now for the issue. It was rather random so therefore i have no idea what could be causing it, but essentially when sendMessage is called in onPrivateMessageReceived (as well as onMessageRecieved with isPrivate check), it causes the bot to spam the message infinitley until the 'TOO MUCH TOO FAST' exception is thrown.

At first i was thinking it was an error in my code, but after commenting literally everything that isnt just the main startup and the onPrivateMessageReceived event, ive come to the conclusion that it is something to do with JDA.

This is pretty much the program after all the commenting

The imports

import net.dv8tion.jda.JDABuilder;
import net.dv8tion.jda.entities.;
import net.dv8tion.jda.entities.Guild;
import net.dv8tion.jda.events.ReadyEvent;
import net.dv8tion.jda.events.audio.
;
import net.dv8tion.jda.events.DisconnectEvent;
import net.dv8tion.jda.events.ReconnectedEvent;
import net.dv8tion.jda.events.message.priv.PrivateMessageReceivedEvent;
import net.dv8tion.jda.events.message.MessageReceivedEvent;
import net.dv8tion.jda.hooks.ListenerAdapter;
import net.dv8tion.jda.audio.player.FilePlayer;
import net.dv8tion.jda.audio.player.Player;

import javax.security.auth.login.LoginException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public static void main(String[] args)
{
    try {
        new JDABuilder().setBotToken(m_botToken).addListener(new highNoonBot()).buildBlocking();
    }
    catch (IllegalArgumentException e) {
        System.out.println("ERROR: No token entered, fix it.");
    }
    catch (LoginException e) {
        System.out.println("ERROR: The token entered is invalid, fix it.");
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Override
public void onPrivateMessageReceived(PrivateMessageReceivedEvent event) {
    event.getChannel().sendMessage("Test");
    return;
}

The main is pretty much pure copy and paste from your examples and the on onPrivateMessageReceived just does the sendMessage, but when you message the bot you get this.

http://puu.sh/oSehN/dde45f3700.png

Here is the console log up to the point of the exception

[21:25:13] [Info] [JDAAudioManager]: Audio System successfully setup! [21:25:13] [Info] [JDA]: JDA starting... [21:25:14] [Info] [JDA]: Login Successful! [21:25:14] [Info] [JDASocket]: Connected to WebSocket [21:25:15] [Info] [JDA]: Finished Loading! [21:25:20] [Fatal] [JDA]: One of the EventListeners had an uncaught exception [21:25:20] [Fatal] [JDA]: Encountered an exception: net.dv8tion.jda.exceptions.RateLimitedException: The message got Rate-Limited. You are able to send messages again in 4589 ms at net.dv8tion.jda.entities.impl.PrivateChannelImpl.sendMessage(PrivateChannelImpl.java:88) at net.dv8tion.jda.entities.impl.PrivateChannelImpl.sendMessage(PrivateChannelImpl.java:70) at its.high.noon.highNoonBot.onPrivateMessageReceived(highNoonBot.java:180) at net.dv8tion.jda.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:167) at net.dv8tion.jda.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:57) at net.dv8tion.jda.handle.MessageReceivedHandler.handleInternally(MessageReceivedHandler.java:59) at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:36) at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:545) at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:296) at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211) at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910) at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693) at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102) at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

Massively distorted audio on some files

I have been testing out the sending audio part of the api.

It works great aside from for some files where it is horribly distorted.

For example :

https://hydra-media.cursecdn.com/dota2.gamepedia.com/4/42/Bane_spawn_01.mp3

(I downloaded it and used the FilePlayer not URLPlayer)

was massively distorted for me

If it helps, I checked the bitrate on that file, 64kbps. The files it worked well on were around 200kbps

Another file which was very distorted was a .wav file with 700+ kbps bitrate

[Fatal] [JDA]: One of the EventListeners had an uncaught exception

Cannot get my simple ping bot to work~
getting the following errors

[21:55:03] [Fatal] [JDA]: One of the EventListeners had an uncaught exception [21:55:03] [Fatal] [JDA]: Encountered an exception: java.lang.NullPointerException at Commands.PingCommand.action(PingCommand.java:19) at Bot1.handleCommand(Bot1.java:41) at BotListener.onMessageReceived(BotListener.java:13) at net.dv8tion.jda.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:176) at net.dv8tion.jda.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:57) at net.dv8tion.jda.handle.MessageReceivedHandler.handleInternally(MessageReceivedHandler.java:65) at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:36) at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:545) at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:296) at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211) at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910) at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693) at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102) at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

JDASocket Disconnect and Audio Connections

Hello. I am using JDA2 with my Discord bot and I am encountering the following issue while leaving my bot running and it being already connected with an audio connection to a voice channel. If disconnected from the WebSocket:

[06:55:02] [Warning] [JDASocket]: Got disconnected from WebSocket (Internet?!)... Attempting to reconnect in 2s

I will eventually run into an IllegalStateException:

java.lang.IllegalStateException: Cannot have more than 1 audio connection at a time. Please close existing connection before attempting to open a new connection.
at net.dv8tion.jda.managers.impl.AudioManagerImpl.openAudioConnection(AudioManagerImpl.java:66)
at net.dv8tion.jda.requests.WebSocketClient.reconnectAudioConnections(WebSocketClient.java:483)
at net.dv8tion.jda.requests.WebSocketClient.ready(WebSocketClient.java:117)
at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:533)
at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:296)
at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352)
at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233)
at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211)
at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102)
at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

Any idea how I should resolve this? What essentially happens is the bot leaves the voice channel and is no longer able to rejoin it or any other channel in that particular guild.

Issue When Removing 2 Roles Then Adding A Role

I've come across some weird issue. Basically this is what I want to accomplish:

  • Remove all roles from a specific user
  • Afterwards, give the user a specific role.

The code works perfectly fine when I want to remove a single role from a user/the user only has a single role. But when there are multiple roles, it has issues.

What ends up happening/my issue:

  • Code successfully removes all of the roles from the user
  • When I give them the specific role, it also adds one of the roles I removed (gets a random one)

The user has these 2 roles by default: Red and Regular. I want to remove those 2, and give them the role of Member.

I made a class called ChatHelper. It has methods that simplify my code. The methods are self explanatory and don't interfere with the problem.

This is the code

    User user = CHATHELPER.getUserByUsername("testbot_wckp");
    ArrayList<Role> usersRoles = new ArrayList<Role>();

            // Store current roles in an array
    for (Role role : CHATHELPER.getGuild().getRolesForUser(user)) {
        usersRoles.add(role);
        System.out.println("Added " + role.getName() + " to the array");
    }
            // Remove those roles from the user
    for (Role role : usersRoles) {
        CHATHELPER.getGuild().getManager().removeRoleFromUser(user, role).update();
    }

    CHATHELPER.getGuild().getManager().addRoleToUser(user, CHATHELPER.getRoleByName("Member")).update();

Console output:
Added Regular to the array
Added Red to the array

Here is the output log from my server listener:

  • testbot_wckp just had the following roles removed:
    Regular
  • testbot_wckp just had the following roles removed:
    Red
  • testbot_wckp was just given the following roles:
    Regular
  • testbot_wckp just had the following roles removed:
    Regular
  • testbot_wckp was just given the following roles:
    Red
  • testbot_wckp was just given the following roles:
    Member

The ending result is the user ending up with 2 roles: Member and Red, or Member and Regular.

UnsatisfiedLinkError on startup

I'm working on a small, silly project in Eclipse on Windows 8.1, 64-bit. I've been using JDK 1.8.0_20 and JDA 1.2.2_139. My project is working fine in Eclipse, but when I try to pack and run it as a jar, I keep getting the same response:

Connecting to Discord...
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\toders\AppDa
ta\Local\Temp\opus360617407824081820.dll: The process cannot access the file bec
ause it is being used by another process
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(Unknown Source)
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.load0(Unknown Source)
        at java.lang.System.load(Unknown Source)
        at net.dv8tion.jda.utils.NativeUtils.loadLibraryFromJar(NativeUtils.java
:121)
        at net.dv8tion.jda.managers.AudioManager.<clinit>(AudioManager.java:311)

        at net.dv8tion.jda.entities.impl.JDAImpl.<init>(JDAImpl.java:62)
        at net.dv8tion.jda.JDABuilder.buildAsync(JDABuilder.java:235)
        at JohnCenaBot.<init>(JohnCenaBot.java:42)
        at JohnCenaBot.main(JohnCenaBot.java:33)

(The exact numbers after opus vary)

I am relatively new to creating jar files, so it's possible that I'm making a mistake, but I've tried this every way I can find and it still doesn't work. Using a Gradle command to pack all dependencies, referencing the library in the jar's manifest, using Eclipse to pack all referenced libraries. Once or twice it's run perfectly, but the next time it crashes again, with no changes to the files or commands. I started out with Gradle, but after a while I tried making a new, non-Gradle project and just linking to the "Dependencies Included" JDA jar. This does not appear to have had any effect on the outcome. Attached is my non-Gradle Eclipse project; it's really just one class and a sound file.

Edit by Kantenkugel: Removed token-file from zip-file
JohnCenaBot_noToken.zip

Bot can attempt to make private channel for itself

image

user = the current jda instance bot that is being used. See the memory object reference is being SelfInfoImpl = the bot itself.

The bot should not be allowed to attempt and a create a private channel for itself as this is not allowed by discord.

aarch64-linux-gnu libopus.so inclusion

Hey guys,

I have a pine64 which has an arm64 processor.
Whenever I want to use the audiomanager, it crashes since the natives for aarch64-linux-gnu aren't there.

This is easily fixed by recompiling JDA from the source and adding the libopus.so (I could provide that, if necessary) into main/resources/natives/linux-aarch64

[2.2.1_358] Long message doesn't sending

When I trying to send a bit long message (http://pastebin.com/3J9iD3Dq) it simply doesn't sending, if i remove the logest line it works perfectly, but adding \n in middle doesn't help.
Method call:
reply(msg, "ะšะพะผะผะฐะฝะดั‹:\n" + FormatUtils.foramtHelp());
(FormatUtils.formateHelp() return the message i gave link before)

Methods:

public static void reply(Message orig, String reply) { reply(orig.getChannel(), orig.getAuthor(), reply); }

public static void reply(MessageChannel cn, User sender, String text) { sendMessage(cn, new MessageBuilder().appendMention(sender).appendString(" " + text).build()); }

public static void sendMessage(MessageChannel cn, Message msg) { cn.sendMessage(msg); }

Main websocket's exponential backoff time is not reset IMMEDIATELY after a connection is successfully established

The main websocket uses a 2^n backoff when trying to reestablish connection to Discord. Each failed attempt increments n up to a max value of 900 or 15 minutes. When a JDA successfully reconnects to Discord it resets the backoff time back to 2 after all re-initialization has completed. This is the problem. If JDA loses connection again during a reconnect, the backoff value hasn't been reset yet, so it starts already significantly backoff'd.

To fix: Make the backoff time be reset immediately after reconnect. Don't wait for reconnect to finish.

JDA 3.0: No way to play audio to VoiceChannel?

I am working on co-developing a Discord bot which needs to be able to play audio to a voice channel.

We are working on updating to JDA 3.0, but we have found that AudioManager has been removed, so we don't know how to play audio. Is there any other way which we could do this?

Thank you for your time,
MeowingTwurtle

Audio sometimes doesn't play

I noticed an issue where audio doesn't play at times, usually when it's the first time calling
player.play()
if I do player.stop(), load my file again, and then do player.play() again, audio plays fine for the rest of the player's usage.

If you need any more info, please let me know

Getting Message for an unknown user will not work in MessageChannels.

Currently if a user is not known (specifically in Guilds) EntityBuilder#createMessage will throw an IllegalArgumentException (for Group and TextChannel).

This should not happen since it is possible that Messages exist with an actual user that is not contained in the local cache. However the usual Message JSON provided by discord does contain information with which we can build a fake User (just like we do for WebHook Messages)!

Methods requiring this functionality to be changed:

  • MessageChannel#getMessageById
  • MessageHistory#retrieveFuture
  • MessageHistory#retrievePast
  • MessageHistory.getHistoryAround(...)

java.lang.NoSuchMethodError: org.tritonus.share.sampled.AudioUtils.millis2Frames(JF)J

I tried using your audio example and it gave this error.

java.lang.NoSuchMethodError: org.tritonus.share.sampled.AudioUtils.millis2Frames(JF)J at org.tritonus.sampled.convert.SampleRateConversionProvider$SampleRateConverterStream.resizeBuffers(SampleRateConversionProvider.java:292) at org.tritonus.sampled.convert.SampleRateConversionProvider$SampleRateConverterStream.<init>(SampleRateConversionProvider.java:276) at org.tritonus.sampled.convert.SampleRateConversionProvider.getAudioInputStream(SampleRateConversionProvider.java:111) at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source) at net.dv8tion.jda.audio.player.Player.setAudioSource(Player.java:79) at net.dv8tion.jda.audio.player.FilePlayer.setAudioFile(FilePlayer.java:46) at net.dv8tion.jda.audio.player.FilePlayer.<init>(FilePlayer.java:34) at com.CreepersHelp.jda.AudioExample.onGuildMessageReceived(AudioExample.java:101) at net.dv8tion.jda.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:140) at net.dv8tion.jda.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:54) at net.dv8tion.jda.handle.MessageReceivedHandler.handle(MessageReceivedHandler.java:45) at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:141) at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233) at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211) at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910) at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693) at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102) at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

JSONException when retrieving history with Webhooks Messages

When I retrieve an history with a Webhook Message inside it, JDA throws a JSONException because the object "url" is not found.

org.json.JSONException: JSONObject["url"] not found.
        at org.json.JSONObject.get(JSONObject.java:477)
        at org.json.JSONObject.getString(JSONObject.java:723)
        at net.dv8tion.jda.handle.EntityBuilder.createMessageEmbed(EntityBuilder.java:591)
        at net.dv8tion.jda.handle.EntityBuilder.createMessage(EntityBuilder.java:508)
        at net.dv8tion.jda.MessageHistory.retrieve(MessageHistory.java:113)
        at net.dv8tion.jda.MessageHistory.retrieve(MessageHistory.java:80)```

I've tried with JDA 2.2.1_353 and JDA 2.3.0_379, the error occurs on both.

Recording Audion in the Channel and trying to write to a WAV file.

We are developing a discord bot and we open the an audio connection and use an AudioReceiveHandler to record audio from the channel. Then when writing it to the wav or before we get this error with the JDA Library.

[17:32:54] [Fatal] [JDAAudioConn]: Encountered an exception:
java.lang.NegativeArraySizeException
    at net.dv8tion.jda.audio.Decoder.decodeFromOpus(Decoder.java:79)
    at net.dv8tion.jda.audio.AudioConnection$3.run(AudioConnection.java:366)

Memory leak in net.dv8tion.jda.requests.WebSocketClient

I discovered some huge spikes in my music bot that causes the program to run out of memory without exiting the process properly.
image
I obtained a memory dump from a crash I had while sleeping. Turns out that most of the memory usage comes from net.dv8tion.jda.requests.WebSocketClient. Here's a summary:
image
Here's a report I generated:
report378760232241.pdf
I can provide the memory dump if necessary.

Edit: I suspect this has to do with event caching

Extremely distorted audio

When I try to load an audio file (MP3 or WAV) 90% of the time it plays extremely distorted... (Bit crushing, pitch way too high etc.) And it does this on virtually any file. I've tested it on multiple machines. What could be causing this?

Error on updating Bot's Icon

While using 2.2.0_334, I updated the bot's icon, and found this in console. It doesn't seem major, but it does say to report it!

[22:21:40] [Warning] [JDASocket]: Got an unexpected Json-parse error. Please redirect following message to the devs:
JSONObject["verified"] not found.
USER_UPDATE -> {"bot":true,"id":"[REDACTED]","avatar":"[REDACTED]","username":"[REDACTED]","discriminator":"6748"}

Note, I've removed the bot's id, avatar, and username because I don't know how dangerous each code is.

ClassCastException on message receive (I think)

Happens right when I start my bot, maybe it happens when it receives a message. I have one message listener. Full source of my bot is on https://github.com/xXAndrew28Xx/SMORE-BOT

[18:06:38] [Fatal] [JDASocket]: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        at net.dv8tion.jda.handle.EntityBuilder.createGuildFirstPass(EntityBuilder.java:144)
        at net.dv8tion.jda.handle.GuildJoinHandler.handleInternally(GuildJoinHandler.java:38)
        at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:38)
        at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:629)
        at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:324)
        at net.dv8tion.jda.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:705)
        at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:368)
        at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:243)
        at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:937)
        at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:696)
        at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102)
        at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)

Connection reset when attempting to join voice channel

I'm getting this exception sometimes when someone requests my music bot to join a voice channel:

[21:31:55] [Fatal] [JDASocket]: Encountered an exception:
[21:31:55] [Fatal] [JDASocket]: java.lang.RuntimeException: com.neovisionaries.ws.client.WebSocketException: Failed to send an opening handshake request to the server: Connection reset
        at net.dv8tion.jda.audio.AudioWebSocket.<init>(AudioWebSocket.java:109)
        at net.dv8tion.jda.handle.VoiceServerUpdateHandler.handleInternally(VoiceServerUpdateHandler.java:68)
        at net.dv8tion.jda.handle.SocketHandler.handle(SocketHandler.java:38)
        at net.dv8tion.jda.requests.WebSocketClient.handleEvent(WebSocketClient.java:615)
        at net.dv8tion.jda.requests.WebSocketClient.onTextMessage(WebSocketClient.java:324)
        at com.neovisionaries.ws.client.ListenerManager.callOnTextMessage(ListenerManager.java:352)
        at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:233)
        at com.neovisionaries.ws.client.ReadingThread.callOnTextMessage(ReadingThread.java:211)
        at com.neovisionaries.ws.client.ReadingThread.handleTextFrame(ReadingThread.java:910)
        at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:693)
        at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:102)
        at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)
Caused by: com.neovisionaries.ws.client.WebSocketException: Failed to send an opening handshake request to the server: Connection reset
        at com.neovisionaries.ws.client.WebSocket.writeHandshake(WebSocket.java:2546)
        at com.neovisionaries.ws.client.WebSocket.shakeHands(WebSocket.java:2437)
        at com.neovisionaries.ws.client.WebSocket.connect(WebSocket.java:1583)
        at net.dv8tion.jda.audio.AudioWebSocket.<init>(AudioWebSocket.java:104)
        ... 11 more
Caused by: java.net.SocketException: Connection reset
        at java.net.SocketInputStream.read(SocketInputStream.java:209)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
        at sun.security.ssl.InputRecord.read(InputRecord.java:503)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
        at com.neovisionaries.ws.client.WebSocket.writeHandshake(WebSocket.java:2539)
        ... 14 more

As a result of this the bot doesn't actually connect to the voice channel, but the audio manager will still think it is trying to connect to the voice channel, since it throws this exception the second time:

java.lang.IllegalStateException: Already attempting to start an AudioConnection with a VoiceChannel!
Currently Attempting Channel ID: 99619915127848960  |  New Attempt Channel ID: 99619915127848960
        net.dv8tion.jda.managers.impl.AudioManagerImpl.openAudioConnection(AudioManagerImpl.java:71)
        fredboat.audio.GuildPlayer.joinChannel(GuildPlayer.java:70)
        fredboat.audio.GuildPlayer.joinChannel(GuildPlayer.java:47)
        fredboat.command.music.JoinCommand.onInvoke(JoinCommand.java:17)
        fredboat.commandmeta.CommandManager.prefixCalled(CommandManager.java:39)

I have also noticed that sometimes the bot will appear to be connected to a voice channel on the client but is unable to play audio or closing the connection with AudioManager.closeAudioConnection(), having no effect at all. In this case trying to connect to the voice channel results in the same IllegalStateException.

Restarting the bot seems to be the only temporary fix, as kicking and reinviting the bot will not fix it.
It might be that the WebSocketException is only triggered after the bug has first occurred and the bot is reinvited.

This has been going on for several versions now. The bot is currently running JDA 2.2.1_355.

Very Distorted Audio When Playing Short Files

If I play a short mp3, that seems to be if it's less than 30 seconds, it turns out VERY distorted and sounds awful. I read in another issue that it might be if the audio was mono, so I converted all audio to stereo, but that's not it. I have verified that the mp3 sounds normal if played outside the bot.
Here's the code that pertains to playing:

            event.getTextChannel().sendMessage("Playing " + video.title + " ID is " + video.id);
            File audioFile  = null;
            try {

                System.out.println("playing!");
                audioFile = new File(video.id+".mp3");
                System.out.println(audioFile.getName());
                player = new FilePlayer(audioFile);
                TimerTask playerStop = new PlayerStop(player);
                event.getGuild().getAudioManager().setSendingHandler(player);
                player.play();
                t.schedule(playerStop, (long) video.duration*1000);
                System.out.println("Scheduled player to stop in " + (long) video.duration + " seconds!");
            } catch (IOException | UnsupportedAudioFileException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

If needed I'll give a comparison of the mp3 being played and the audio that actually is played.

Maven can't resolve some dependencies

In the latest version maven is unable to resolve jflac and tritonus-dsp.

<repositories>
    <repository>
        <id>letece</id>
        <url>http://lutece.paris.fr/nexus/content/repositories/lutece_third_party</url>
    </repository>
    <repository>
        <id>DV8FromTheWorld</id>
        <url>https://github.com/DV8FromTheWorld/Maven-Repository/raw/master/repo</url>
    </repository>
</repositories>

Manually adding the repositories seems to fix it. As far as I know this isn't an issue on my side.

WebSockets timing out

I am trying to start up my Discord bot on an Ubuntu 16.04 Server, and it cannot maintain a websocket apparently (as I've been told)

Here is the error associated with it

I am not sure if this has to do with something I am doing wrong or not...
Thanks!

Timeout Method

I am trying to fix a weird issue that is causing me to not be able to stay connected and/or start a connection to the Discord API.

Is there a method to set the timeout of the bot when it is first connecting?

Error connecting to voice on Raspberry Pi

I haven't had time to test this on another Linux device yet, but I know my code works fine on Windows.

When my bot tries to connect to voice, although actually connecting to the channel succeeds, opening the audio connection fails.

The following error occurs:

java.lang.NullPointerException
        at net.dv8tion.jda.audio.AudioWebSocket.send(AudioWebSocket.java:110)
        at net.dv8tion.jda.audio.AudioWebSocket.onConnected(AudioWebSocket.java:124)
        at com.neovisionaries.ws.client.ListenerManager.callOnConnected(ListenerManager.java:189)
        at com.neovisionaries.ws.client.WebSocket.callOnConnectedIfNotYet(WebSocket.java:3207)
        at com.neovisionaries.ws.client.WebSocket.onReadingThreadStarted(WebSocket.java:3152)
        at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:80)
        at com.neovisionaries.ws.client.ReadingThread.run(ReadingThread.java:61)
Exception in thread "Thread-5" Exception in thread "Thread-6" java.lang.NullPointerException
        at net.dv8tion.jda.audio.AudioConnection$3.run(AudioConnection.java:224)
java.lang.NullPointerException
        at net.dv8tion.jda.audio.AudioConnection$2.run(AudioConnection.java:151)

Other than that, I'd like to say that this API is brilliant and really easy to use, so thanks for all the hard work.

Error when handle a private call

With my own Discord app, when i launch a private call, it says error :

Got an unexpected Json-parse error. Please redirect following message to the devs:
JSONObject["guild_id"] not found.
VOICE_STATE_UPDATE -> {"self_deaf":false,"user_id":"189701620606673921","deaf":false,"session_id":"122732r4a68blq253159b477c1p61b1","mute":false,"suppress":false,"self_mute":false,"channel_id":null}

Got an unexpected Json-parse error. Please redirect following message to the devs:
JSONObject["embeds"] not found.
MESSAGE_UPDATE -> {"call":{"ended_timestamp":"2016-11-09T20:20:25.371089+00:00","participants":["189701620606673921"]},"id":"341012509319336417","channel_id":"17369222125631656"}

Thank you ! (It's using JDAClient but the bug is in a JDA class)

PS : i modified the ids.

JDA occasionally fails to detect a socket being disconnected.

After reviewing reports of my bot, ErisBot disappearing from a set amount of guilds, I've found that JDA will sometimes struggle to detect the socket being closed.
I'm assuming this only affects a timeout since it doesn't always happen but have not tested.

After around 10-20 minutes after the connection has died, it finally realizes and closes, thus attempting a reconnect.

I've reported it in the Discord and @Almighty-Alpaca found that there is no timeout set on the websocket. I got asked to open a Github issue to help track this so hello!

New Application API Example

Hello, I've been using your library for my own project, but with the new Applications migration I'm left wondering how to authenticate my bot now since there is no password. Could you provide a complete example of how to initialize a bot under this new system? Thank you.

Route endpoints

In JDA 3.x, we now specify all Discord Routes. These are the routes left to be added.
Class can be seen here: link
Thanks to @MinnDevelopment for writing up this list.

Base: https://discordapp.com/api/

Global Endpoints

  • voice/regions GET // Voice Regions
  • gateway GET
  • invites/:code DELETE // Delete invite
  • invites/:code GET // Get invite
  • invites/:code POST // Accept invite
  • users/@me GET // Get self
  • users/@me PATCH // Update self
  • users/@me/guilds/:guild_id DELETE // leave guild
  • users/@me/channels GET // Private channels
  • users/@me/channels POST // Create Private Channel
  • channels/:channel_id DELETE // Delete channel/close PM or group
  • channels/:channel_id PATCH
  • channels/:channel_id/messages GET
  • channels/:channel_id/messages POST
  • channels/:channel_id/messages/:message_id DELETE
  • channels/:channel_id/messages/:message_id PATCH
  • channels/:channel_id/messages/:message_id/reactions/:encoded/@me PUT
  • channels/:channel_id/messages/:message_id/reactions/:encoded/@me DELETE
  • channels/:channel_id/messages/:message_id/reactions DELETE // delete all reactions
  • channels/:channel_id/typing POST
  • channels/:channel_id/pins GET
  • channels/:channel_id/pins/:message_id PUT
  • channels/:channel_id/pins/:message_id DELETE
  • channels/:channel_id/invites GET
  • channels/:channel_id/invites POST
  • channels/:channel_id/permissions GET
  • channels/:channel_id/permissions/:permissionoverride_id GET
  • channels/:channel_id/permissions/:permissionoverride_id PUT //Create permoverride
  • channels/:channel_id/permissions/:permissionoverride_id PATCH
  • channels/:channel_id/permissions/:permissionoverride_id DELETE
  • channels/:channel_id/webhooks POST // Create Webhook
  • channels/:channel_id/webhooks GET // Get channel webhooks
  • users/@me/guilds GET
  • guilds/:guild_id GET
  • guilds/:guild_id PATCH
  • guilds/:guild_id/channels GET
  • guilds/:guild_id/channels POST
  • guilds/:guild_id/channels PATCH //Batch modify channel positions
  • guilds/:guild_id/bans GET
  • guilds/:guild_id/bans/:user_id PUT
  • guilds/:guild_id/bans/:user_id DELETE
  • guilds/:guild_id/members/:user_id DELETE // kick user
  • guilds/:guild_id/members/:user_id PATCH
  • guilds/:guild_id/members/@me/nick PATCH // Update own nick
  • guilds/:guild_id/prune POST
  • guilds/:guild_id/prune GET // Get users that would be kicked by prune?
  • guilds/:guild_id/roles POST
  • guilds/:guild_id/roles GET
  • guilds/:guild_id/roles/:role_id GET
  • guilds/:guild_id/roles/:role_id DELETE
  • guilds/:guild_id/roles/:role_id PATCH
  • guilds/:guild_id/invites GET
  • guilds/:guild_id/integrations GET
  • guilds/:guild_id/integrations POST // Create Guild integrations
  • guilds/:guild_id/integrations/:integration_id PATCH
  • guilds/:guild_id/integrations/:integration_id DELETE
  • guilds/:guild_id/integrations/:integration_id/sync POST
  • guilds/:guild_id/embed GET //Guild Embed
  • guilds/:guild_id/embed PATCH
  • guilds/:guild_id/emojis GET
  • guilds/:guild_id/webhooks GET // Get guild webhooks
  • webhooks/:webhook_id GET // Get Webhook
  • webhooks/:webhook_id PATCH //Modify webhook
  • webhooks/:webhook_id DELETE //Delete webhook
  • webhooks/:webhook_id/:webhook_token GET // Get webhook with token
  • webhooks/:webhook_id/:webhook_token PATCH //modify webhook with token
  • webhooks/:webhook_id/:webhook_token DELETE //Delete webhook with token
  • webhooks/:webhook_id/:webhook_token POST //Execture webhook
  • webhooks/:webhook_id/:webhook_token/slack POST //Execture slack webhook

Bot Only

  • channel/:channel_id/messages/bulk-delete POST // Bulk delete(guild only)
  • channel/:channel_id/messages/:message_id GET // Get Message By ID
  • oauth2/applications/@me GET

Client Only

  • friend-suggestions GET // Get friend suggestions (displayed in the add friend tab)
  • track POST // Track endpoint
  • guilds POST // Create guild, duh... {name: "fgh", region: "eu-central", icon: null}
  • guilds/:guild_id/delete POST // Delete guild with 2fa code
  • guilds/:guild_id/ack POST // Ack a guild
  • guilds/:guild_id/emojis POST //Create emoji
  • guilds/:guild_id/emojis/:id PATCH //Edit emoji
  • guilds/:guild_id/emojis/:id DELETE //Remove emoji
  • users/@me/connections GET // Get Connections (twitch,steam,skype...)
  • users/@me/settings PATCH // User-/Privacy Settings
  • users/@me/notes/:user_id PUT // Notes
  • users/@me/guilds/:guild_id/settings PATCH // Notification Settings for a Guild
  • users/@me/mentions?limit=25&roles=true&everyone=false GET // Recent Mentions
  • users/@me/mfa/codes POST // Backup codes
  • users/@me/mfa/totp/disable POST // Disable 2FA
  • users/@me/mfa/totp/enable POST // Enable 2FA
  • users/@me/relationships GET // Get Friends/Blocks/Incoming/Outgoing
  • users/@me/relationships/:user_id PUT // Add Friend/ Block
  • users/@me/relationships/:user_id DELETE // Delete Block/Unfriend/Ignore Request/Cancel Outgoing
  • channels/:channel_id/recipients GET // Get Group members
  • channels/:channel_id/recipients/:user_id PUT // Add Group member by id
  • channels/:channel_id/recipients/:user_id GET // Group member by id
  • channels/:channel_id/recipients/:user_id DELETE // Kick member
  • channels/:channel_id/messages/:messages_id/ack // Ack a message
  • channels/:channel_id/call/ring POST //start call
  • channels/:channel_id/call/stop-ringing POST //deny call
  • oauth2/applications GET
  • oauth2/applications POST
  • oauth2/applications/:application_id GET
  • oauth2/applications/:application_id PUT
  • oauth2/applications/:application_id DELETE
  • oauth2/applications/:application_id/bot POST
  • oauth2/applications/:application_id/reset POST
  • oauth2/applications/:application_id/bot/reset POST
  • oauth2/tokens GET
  • oauth2/tokens/:auth_id GET
  • oauth2/tokens/:auth_id DELETE

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.