/lavalink-client

Lavalink client for lavalink v4

Primary LanguageKotlinMIT LicenseMIT

Java Lavalink client

Warning

This is a client for Lavalink v4 only. You cannot use this with Lavalink v3.

Feature overview:

  • Uses reactor (please make sure you understand how reactor works)
  • Works with any discord library (as long as they allow for sending direct request to discord)
  • Load balancing based on server metrics and voice server region.
  • Make your own custom load balancers and penalty providers!
  • Lightweight
  • Compiled for java 17

Current version (remove the v prefix): Latest version

Or copy/download it here

Documentation can be found over at https://client.lavalink.dev/

If you prefer javadoc-style documentation, you can find those here

Gradle instructions

repositories {
    maven("https://maven.lavalink.dev/releases") // Required for the protocol library
}

dependencies {
    implementation("dev.arbjerg:lavalink-client:VERSION")
}

Maven instructions

<repositories>
    <repository>
        <id>ll-releases</id>
        <name>Lavalink Releases</name>
        <url>https://maven.lavalink.dev/releases</url>
    </repository>
</repositories>

<dependency>
  <groupId>dev.arbjerg</groupId>
  <artifactId>lavalink-client</artifactId>
  <version>VERSION</version>
</dependency>

Installation and usage with JDA

Lavalink client ships with a voice interceptor for JDA

// Helpers is a class provided by this lib!
String botToken = System.getenv("BOT_TOKEN");
LavalinkClient client = new LavalinkClient(
    Helpers.getUserIdFromToken(botToken)
);

JDABuilder.createDefault(botToken)
    // .... your jda configuration
    .setVoiceDispatchInterceptor(new JDAVoiceUpdateListener(client))
    // .... your jda configuration
    .build();

then connect to vc by using the direct audio controller like this:

jda.getDirectAudioController().connect(voiceChannel);

Important

Using Guild#getAudioManager() will NOT work. This is because the audio manager makes JDA connect to the voice channel, and we want to send the event to LavaLink. You can however use Member#getVoiceState perfectly fine, this is also how you get the voice channel that your bot is in.

You can get the current voice channel of your bot by calling Guild#getSelfMember()#getVoiceState()#getChannel

Installation and usage with Discord4j

Installation for D4J is a little bit different from usual, mainly because D4j does not have a voice intercepting system.

// Helpers is a class provided by this lib!
String botToken = System.getenv("BOT_TOKEN");
LavalinkClient client = new LavalinkClient(
    Helpers.getUserIdFromToken(botToken)
);
        
DiscordClient discord = DiscordClientBuilder.create(botToken)
    .build()
    .gateway()
    .setEnabledIntents(IntentSet.all())
    .login()
    .block();

D4JVoiceHandler.install(discord, client);

or if you're using kotlin

discord.installVoiceHandler(client)

Then connect like this

var voiceState = /* Get the voice state of the member that ran the command */;
var memberVoice = voiceState.getChannel().block();

memberVoice.sendConnectVoiceState(false, false).subscribe();

And disconnect like this

var voiceState = /* Get the voice state of the member that ran the command */;
var memberVoice = voiceState.getChannel().block();

memberVoice.sendDisconnectVoiceState().subscribe();

Alternatively, you can use Discord4JUtils.leave(gatewayClient, guildId); as that does not access any voice states.

Examples

The following examples are minimal implementations but show how the library works.

  • Java examples
    • JDA (simple): link
    • JDA (Bigger example with queue system): link
  • Kotlin examples

Standalone usage

This library is made to not rely on and discord libraries and can be used as such. In order to connect to a voice channel without any library you will need a voice server update event from discord containing the token, endpoint and session id. In this example it is assumed that you have this information as an object named event.

Sample code for connecting to a voice channel without a discord library:

import dev.arbjerg.lavalink.client.LavalinkClient;
import dev.arbjerg.lavalink.client.Link;
import dev.arbjerg.lavalink.client.loadbalancing.VoiceRegion;
import dev.arbjerg.lavalink.protocol.v4.VoiceState;

// This is your lavalink client
LavalinkClient client = new LavalinkClient(/* your bot user id */);

// This is sample code, it will need modifications to work for you
public void onDiscordVoiceServerUpdate(VoiceServerUpdateEvent event) {
    VoiceState lavalinkVoiceState = new VoiceState(
        event.getToken(),
        event.getEndpoint(),
        event.getSessionId()
    );

    // If you want load-balancing based on the region of the voice server, use the enum.
    VoiceRegion region = VoiceRegion.fromEndpoint(event.getEndpoint());

    // You can omit the region parameter if you dont need region balancing.
    Link link = lavalink.getOrCreateLink(event.getGuildId(), region);

    // Finally, tell lavalink to connect.
    link.onVoiceServerUpdate(lavalinkVoiceState);
}