Skip to content

Configuration

import { LavalinkManager, QueueChangesWatcher, QueueStoreManager } from "lavalink-client";
import { RedisClientType } from "redis"; // example for custom queue store
import { Client, GatewayIntentBits } from "discord.js"; // example for a discord bot
// you might want to extend the types of the client, to bind lavalink to it.
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
]
});
const previouslyUsedSessions = new Map<string, string>(); //nodeManager.on("connect", node => previouslyUsedSessions.set(node.id, node.sessionId))
client.lavalink = new LavalinkManager({
nodes: [
{
authorization: "localhoist",
host: "localhost",
port: 2333,
id: "testnode",
// get the previously used session, to restart with "resuming" enabled
sessionId: previouslyUsedSessions.get("testnode"),
requestSignalTimeoutMS: 3000,
closeOnError: true,
heartBeatInterval: 30_000,
enablePingOnStatsCheck: true,
retryDelay: 10e3,
secure: false,
retryAmount: 5,
}
],
sendToShard: (guildId, payload) => client.guilds.cache.get(guildId)?.shard?.send(payload),
autoSkip: true,
client: { // client: client.user
id: envConfig.clientId, // REQUIRED! (at least after the .init)
username: "TESTBOT",
},
autoSkipOnResolveError: true, // skip song, if resolving an unresolved song fails
emitNewSongsOnly: true, // don't emit "looping songs"
playerOptions: {
// These are the default prevention methods
maxErrorsPerTime: {
threshold: 10_000,
maxAmount: 3,
},
// only allow an autoplay function to execute, if the previous function was longer ago than this number.
minAutoPlayMs: 10_000,
applyVolumeAsFilter: false,
clientBasedPositionUpdateInterval: 50, // in ms to up-calc player.position
defaultSearchPlatform: "ytmsearch",
volumeDecrementer: 0.75, // on client 100% == on lavalink 75%
requesterTransformer: requesterTransformer,
onDisconnect: {
autoReconnect: true, // automatically attempts a reconnect, if the bot disconnects from the voice channel, if it fails, it get's destroyed
destroyPlayer: false // overrides autoReconnect and directly destroys the player if the bot disconnects from the vc
},
onEmptyQueue: {
// will auto destroy the player after 30s if the queue got empty and autoplay function does not add smt to the queue
destroyAfterMs: 30_000, // 1 === instantly destroy | don't provide the option, to don't destroy the player
autoPlayFunction: autoPlayFunction,
},
useUnresolvedData: true,
},
queueOptions: {
maxPreviousTracks: 10,
// only needed if you want and need external storage, don't provide if you don't need to
queueStore: new myCustomStore(client.redis), // client.redis = new redis()
// only needed, if you want to watch changes in the queue via a custom class,
queueChangesWatcher: new myCustomWatcher(client)
},
linksAllowed: true,
// example: don't allow p*rn / youtube links., you can also use a regex pattern if you want.
// linksBlacklist: ["porn", "youtube.com", "youtu.be"],
linksBlacklist: [],
linksWhitelist: [],
advancedOptions: {
enableDebugEvents: true,
maxFilterFixDuration: 600_000, // only allow instafixfilterupdate for tracks sub 10mins
debugOptions: {
noAudio: false,
playerDestroy: {
dontThrowError: false,
debugLog: false,
},
logCustomSearches: false,
}
}
});
// IMPORTANT- Send voice data to lavalink
client.on("raw", d => client.lavalink.sendRawData(d));
client.on("ready", () => {
client.lavalink.init(client.user); // init lavalink
});
// for the custom queue Store create a redis instance
client.redis = createClient({ url: "redis://localhost:6379", password: "securepass" });
client.redis.connect();
// Custom external queue Store
// if queueStore is not provided on default it uses MiniMap
export class myCustomStore implements QueueStoreManager {
private redis:RedisClientType;
constructor(redisClient:RedisClientType) {
this.redis = redisClient;
}
async get(guildId): Promise<any> {
return await this.redis.get(this.id(guildId));
}
async set(guildId, stringifiedQueueData): Promise<any> {
return await this.redis.set(this.id(guildId), stringifiedQueueData);
}
async delete(guildId): Promise<any> {
return await this.redis.del(this.id(guildId));
}
async parse(stringifiedQueueData): Promise<Partial<StoredQueue>> {
return JSON.parse(stringifiedQueueData);
}
async stringify(parsedQueueData): Promise<any> {
return JSON.stringify(parsedQueueData);
}
private id(guildId) {
return `lavalinkqueue_${guildId}`; // transform the id to your belikings
}
}
// Custom Queue Watcher Functions
export class myCustomWatcher implements QueueChangesWatcher {
constructor() {
}
shuffled(guildId, oldStoredQueue, newStoredQueue) {
console.log(`${this.client.guilds.cache.get(guildId)?.name || guildId}: Queue got shuffled`)
}
tracksAdd(guildId, tracks, position, oldStoredQueue, newStoredQueue) {
console.log(`${this.client.guilds.cache.get(guildId)?.name || guildId}: ${tracks.length} Tracks got added into the Queue at position #${position}`);
}
tracksRemoved(guildId, tracks, position, oldStoredQueue, newStoredQueue) {
console.log(`${this.client.guilds.cache.get(guildId)?.name || guildId}: ${tracks.length} Tracks got removed from the Queue at position #${position}`);
}
}