Skip to content

Resuming

  1. You need to enable resuming on a connected Lavalink node : node.updateSession(true, 360e3)
  2. The NodeManager#resumed event will emit when the node resumes, you retrieves all fetchedPlayers (fetched by the client), and thus all you need to do is re-create all player instances (and possibly the queues too)
  • For that is the queuestore useful
  • To save the playerData you can utilize smt like playerUpdate event.

Resuming full Example

Full code sample: can be found on the Testbot in here

// but here is the schema:
client.lavalink.nodeManager.on("connect", (node) => node.updateSession(true, 360e3));
client.lavalink.nodeManager.on("resumed", (node, payload, fetchedPlayers) => {
// create players:
for(const fetchedPlayer of fetchedPlayers) {
// fetchedPlayer is the live data from lavalink
// saved Player data is the config you should save in a database / file or smt
const savedPlayerData = await getSavedPlayerData(fetchedPlayer.guildId);
const player = client.lavalink.createPlayer({
guildId: fetchedPlayer.guildId,
});
// if lavalink says the bot got disconnected, we can skip the resuming, or force reconnect whatever you want!, here we choose to not do anything and thus delete the saved player data
if(!data.state.connected) {
console.log("skipping resuming player, because it already disconnected");
await deletedSavedPlayerData(data.guildId);
continue;
}
// now you can create the player based on the live and saved data
const player = client.lavalink.createPlayer({
guildId: data.guildId,
node: node.id,
// you need to update the volume of the player by the volume of lavalink which might got decremented by the volume decrementer
volume: client.lavalink.options.playerOptions?.volumeDecrementer
? Math.round(data.volume / client.lavalink.options.playerOptions.volumeDecrementer)
: data.volume,
// all of the following options are needed to be provided by some sort of player saving
voiceChannelId: dataOfSaving.voiceChannelId,
textChannelId: dataOfSaving.textChannelId,
// all of the following options can either be saved too, or you can use pre-defined defaults
selfDeaf: dataOfSaving.options?.selfDeaf || true,
selfMute: dataOfSaving.options?.selfMute || false,
applyVolumeAsFilter: dataOfSaving.options.applyVolumeAsFilter,
instaUpdateFiltersFix: dataOfSaving.options.instaUpdateFiltersFix,
vcRegion: dataOfSaving.options.vcRegion,
});
// player.voice = data.voice;
// normally just player.voice is enough, but if you restart the entire bot, you need to create a new connection, thus call player.connect();
await player.connect();
player.filterManager.data = data.filters; // override the filters data
await player.queue.utils.sync(true, false); // get the queue data including the current track (for the requester)
// override the current track with the data from lavalink
if(data.track) player.queue.current = client.lavalink.utils.buildTrack(data.track, player.queue.current?.requester || client.user);
// override the position of the player
player.lastPosition = data.state.position;
player.lastPositionChange = Date.now();
// you can also override the ping of the player, or wait about 30s till it's done automatically
player.ping.lavalink = data.state.ping;
// important to have skipping work correctly later
player.paused = data.paused;
player.playing = !data.paused && !!data.track;
// That's about it
}
})
client.lavalink.on("playerUpdate", (oldPlayer, newPlayer) => { // automatically sync player data on updates. if you don'T want to save everything you can instead also just save the data on playerCreate
setSavedPlayerData(newPlayer.toJSON());
});
// delete the player again
client.lavalink.on("playerDestroy", (player) => {
deleteSavedPlayerData(player.guildId);
})