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):
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
repositories {
maven("https://maven.lavalink.dev/releases") // Required for the protocol library
}
dependencies {
implementation("dev.arbjerg:lavalink-client:VERSION")
}
<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>
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 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.
The following examples are minimal implementations but show how the library works.
- Java examples
- Kotlin examples
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);
}