lavalink-client 2.4.1 → 2.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -789,3 +789,11 @@ if(previousTrack) {
789
789
  *Allows you to inmplement a custom playerVoiceEmpty handler*
790
790
 
791
791
  - Added the new events and configuration to the docs
792
+
793
+ ## **Version 2.4.3**
794
+ - `managerOptions#playerOptions.onDisconnect.autoReconnect`:
795
+ - Added the option `managerOptions#playerOptions.onDisconnect.autoReconnectOnlyWithTracks` to control wether to try reconnecting only when there are tracks in the queue / current track or not
796
+ - Added a new debug log for that
797
+ - Added the try to play the next track if there is no current track
798
+ - *There was a problem trying to auto-reconnect on "empty-queue" events, which caused the player to get destroyed by that and log the error in console "`There is no Track in the Queue, nor provided in the PlayOptions`"*
799
+ - *Now you have to handle that case manually if you want to or set autoReconnectOnlyWithTracks to false (default)*
@@ -150,7 +150,7 @@ class FilterManager {
150
150
  sendData.equalizer = [...this.equalizerBands];
151
151
  if (sendData.equalizer.length === 0)
152
152
  delete sendData.equalizer;
153
- for (const key of [...Object.keys(sendData)]) {
153
+ for (const key of Object.keys(sendData)) {
154
154
  // delete disabled filters
155
155
  if (key === "pluginFilters") {
156
156
  // for(const key of [...Object.keys(sendData.pluginFilters)]) {
@@ -181,7 +181,7 @@ class FilterManager {
181
181
  this.filters.rotation = this.data.rotation.rotationHz !== 0;
182
182
  this.filters.vibrato = this.data.vibrato.frequency !== 0 || this.data.vibrato.depth !== 0;
183
183
  this.filters.tremolo = this.data.tremolo.frequency !== 0 || this.data.tremolo.depth !== 0;
184
- const lavalinkFilterData = (this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...((this.data.pluginFilters.reverb) || {}) } });
184
+ const lavalinkFilterData = (this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...(this.data.pluginFilters.reverb) } });
185
185
  this.filters.lavalinkFilterPlugin.echo = lavalinkFilterData.echo.decay !== 0 || lavalinkFilterData.echo.delay !== 0;
186
186
  this.filters.lavalinkFilterPlugin.reverb = lavalinkFilterData.reverb?.delays?.length !== 0 || lavalinkFilterData.reverb?.gains?.length !== 0;
187
187
  this.filters.lavalinkLavaDspxPlugin.highPass = Object.values(this.data.pluginFilters["high-pass"] || {}).length > 0;
@@ -83,7 +83,8 @@ class LavalinkManager extends events_1.EventEmitter {
83
83
  defaultSearchPlatform: options?.playerOptions?.defaultSearchPlatform ?? "ytsearch",
84
84
  onDisconnect: {
85
85
  destroyPlayer: options?.playerOptions?.onDisconnect?.destroyPlayer ?? true,
86
- autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false
86
+ autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false,
87
+ autoReconnectOnlyWithTracks: options?.playerOptions?.onDisconnect?.autoReconnectOnlyWithTracks ?? false,
87
88
  },
88
89
  onEmptyQueue: {
89
90
  autoPlayFunction: options?.playerOptions?.onEmptyQueue?.autoPlayFunction ?? null,
@@ -569,13 +570,14 @@ class LavalinkManager extends events_1.EventEmitter {
569
570
  this.emit("playerSuppressChange", player, player.voiceState.suppress);
570
571
  }
571
572
  else {
572
- if (this.options?.playerOptions?.onDisconnect?.destroyPlayer === true) {
573
+ const { autoReconnectOnlyWithTracks, destroyPlayer, autoReconnect } = this.options?.playerOptions?.onDisconnect ?? {};
574
+ if (destroyPlayer === true) {
573
575
  return void await player.destroy(Constants_1.DestroyReasons.Disconnected);
574
576
  }
575
- this.emit("playerDisconnect", player, player.voiceChannelId);
576
- if (this.options?.playerOptions?.onDisconnect?.autoReconnect === true) {
577
+ if (autoReconnect === true) {
577
578
  try {
578
- const positionPrevios = player.position;
579
+ const previousPosition = player.position;
580
+ const previousPaused = player.paused;
579
581
  if (this.options?.advancedOptions?.enableDebugEvents) {
580
582
  this.emit("debug", Constants_1.DebugEvents.PlayerAutoReconnect, {
581
583
  state: "log",
@@ -583,12 +585,23 @@ class LavalinkManager extends events_1.EventEmitter {
583
585
  functionLayer: "LavalinkManager > sendRawData()",
584
586
  });
585
587
  }
586
- await player.connect();
588
+ // connect if there are tracks & autoReconnectOnlyWithTracks = true or autoReconnectOnlyWithTracks is false
589
+ if (!autoReconnectOnlyWithTracks || (autoReconnectOnlyWithTracks && (player.queue.current || player.queue.tracks.length))) {
590
+ await player.connect();
591
+ }
587
592
  // replay the current playing stream
588
- await player.play({
589
- position: positionPrevios,
590
- paused: player.paused,
591
- clientTrack: player.queue.current,
593
+ if (player.queue.current) {
594
+ return void await player.play({ position: previousPosition, paused: previousPaused, clientTrack: player.queue.current, });
595
+ }
596
+ // try to play the next track
597
+ if (player.queue.tracks.length) {
598
+ return void await player.play({ paused: previousPaused });
599
+ }
600
+ // debug log if nothing was possible
601
+ this.emit("debug", Constants_1.DebugEvents.PlayerAutoReconnect, {
602
+ state: "log",
603
+ message: `Auto reconnected, but nothing to play`,
604
+ functionLayer: "LavalinkManager > sendRawData()",
592
605
  });
593
606
  }
594
607
  catch (e) {
@@ -596,6 +609,7 @@ class LavalinkManager extends events_1.EventEmitter {
596
609
  return void await player.destroy(Constants_1.DestroyReasons.PlayerReconnectFail);
597
610
  }
598
611
  }
612
+ this.emit("playerDisconnect", player, player.voiceChannelId);
599
613
  player.voiceChannelId = null;
600
614
  player.voice = Object.assign({});
601
615
  return;
@@ -811,7 +811,7 @@ class LavalinkNode {
811
811
  * @returns boolean
812
812
  */
813
813
  syncPlayerData(data, res) {
814
- if (typeof data === "object" && typeof data?.guildId === "string" && typeof data.playerOptions === "object" && Object.keys(data.playerOptions).length > 1) {
814
+ if (typeof data === "object" && typeof data?.guildId === "string" && typeof data.playerOptions === "object" && Object.keys(data.playerOptions).length > 0) {
815
815
  const player = this.NodeManager.LavalinkManager.getPlayer(data.guildId);
816
816
  if (!player)
817
817
  return;
@@ -837,7 +837,7 @@ class LavalinkNode {
837
837
  }
838
838
  }
839
839
  if (typeof data.playerOptions.filters !== "undefined") {
840
- const oldFilterTimescale = { ...(player.filterManager.data.timescale || {}) };
840
+ const oldFilterTimescale = { ...player.filterManager.data.timescale };
841
841
  Object.freeze(oldFilterTimescale);
842
842
  if (data.playerOptions.filters.timescale)
843
843
  player.filterManager.data.timescale = data.playerOptions.filters.timescale;
@@ -200,6 +200,8 @@ export interface ManagerPlayerOptions {
200
200
  onDisconnect?: {
201
201
  /** Try to reconnect? -> If fails -> Destroy */
202
202
  autoReconnect?: boolean;
203
+ /** Only try to reconnect if there are tracks in the queue */
204
+ autoReconnectOnlyWithTracks?: boolean;
203
205
  /** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
204
206
  destroyPlayer?: boolean;
205
207
  };
@@ -230,7 +230,7 @@ export interface NodeManagerEvents {
230
230
  * Aka for that you need to be able to save player data like vc channel + text channel in a db and then sync it again
231
231
  * @event Manager.nodeManager#nodeResumed
232
232
  */
233
- "resumed": (node: LavalinkNode, paylaod: {
233
+ "resumed": (node: LavalinkNode, payload: {
234
234
  resumed: true;
235
235
  sessionId: string;
236
236
  op: "ready";
@@ -37,7 +37,7 @@ class ManagerUtils {
37
37
  buildPluginInfo(data, clientData = {}) {
38
38
  return {
39
39
  clientData: clientData,
40
- ...(data.pluginInfo || data.plugin || {})
40
+ ...(data.pluginInfo || data.plugin),
41
41
  };
42
42
  }
43
43
  buildTrack(data, requester) {
@@ -67,7 +67,7 @@ class ManagerUtils {
67
67
  isrc: data.info.isrc,
68
68
  },
69
69
  userData: {
70
- ...(data.userData || {}),
70
+ ...data.userData,
71
71
  requester: transformedRequester
72
72
  },
73
73
  pluginInfo: this.buildPluginInfo(data, "clientData" in data ? data.clientData : {}),
@@ -147,7 +147,7 @@ export class FilterManager {
147
147
  sendData.equalizer = [...this.equalizerBands];
148
148
  if (sendData.equalizer.length === 0)
149
149
  delete sendData.equalizer;
150
- for (const key of [...Object.keys(sendData)]) {
150
+ for (const key of Object.keys(sendData)) {
151
151
  // delete disabled filters
152
152
  if (key === "pluginFilters") {
153
153
  // for(const key of [...Object.keys(sendData.pluginFilters)]) {
@@ -178,7 +178,7 @@ export class FilterManager {
178
178
  this.filters.rotation = this.data.rotation.rotationHz !== 0;
179
179
  this.filters.vibrato = this.data.vibrato.frequency !== 0 || this.data.vibrato.depth !== 0;
180
180
  this.filters.tremolo = this.data.tremolo.frequency !== 0 || this.data.tremolo.depth !== 0;
181
- const lavalinkFilterData = (this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...((this.data.pluginFilters.reverb) || {}) } });
181
+ const lavalinkFilterData = (this.data.pluginFilters?.["lavalink-filter-plugin"] || { echo: { decay: this.data.pluginFilters?.echo?.decay && !this.data.pluginFilters?.echo?.echoLength ? this.data.pluginFilters.echo.decay : 0, delay: this.data.pluginFilters?.echo?.delay || 0 }, reverb: { gains: [], delays: [], ...(this.data.pluginFilters.reverb) } });
182
182
  this.filters.lavalinkFilterPlugin.echo = lavalinkFilterData.echo.decay !== 0 || lavalinkFilterData.echo.delay !== 0;
183
183
  this.filters.lavalinkFilterPlugin.reverb = lavalinkFilterData.reverb?.delays?.length !== 0 || lavalinkFilterData.reverb?.gains?.length !== 0;
184
184
  this.filters.lavalinkLavaDspxPlugin.highPass = Object.values(this.data.pluginFilters["high-pass"] || {}).length > 0;
@@ -80,7 +80,8 @@ export class LavalinkManager extends EventEmitter {
80
80
  defaultSearchPlatform: options?.playerOptions?.defaultSearchPlatform ?? "ytsearch",
81
81
  onDisconnect: {
82
82
  destroyPlayer: options?.playerOptions?.onDisconnect?.destroyPlayer ?? true,
83
- autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false
83
+ autoReconnect: options?.playerOptions?.onDisconnect?.autoReconnect ?? false,
84
+ autoReconnectOnlyWithTracks: options?.playerOptions?.onDisconnect?.autoReconnectOnlyWithTracks ?? false,
84
85
  },
85
86
  onEmptyQueue: {
86
87
  autoPlayFunction: options?.playerOptions?.onEmptyQueue?.autoPlayFunction ?? null,
@@ -566,13 +567,14 @@ export class LavalinkManager extends EventEmitter {
566
567
  this.emit("playerSuppressChange", player, player.voiceState.suppress);
567
568
  }
568
569
  else {
569
- if (this.options?.playerOptions?.onDisconnect?.destroyPlayer === true) {
570
+ const { autoReconnectOnlyWithTracks, destroyPlayer, autoReconnect } = this.options?.playerOptions?.onDisconnect ?? {};
571
+ if (destroyPlayer === true) {
570
572
  return void await player.destroy(DestroyReasons.Disconnected);
571
573
  }
572
- this.emit("playerDisconnect", player, player.voiceChannelId);
573
- if (this.options?.playerOptions?.onDisconnect?.autoReconnect === true) {
574
+ if (autoReconnect === true) {
574
575
  try {
575
- const positionPrevios = player.position;
576
+ const previousPosition = player.position;
577
+ const previousPaused = player.paused;
576
578
  if (this.options?.advancedOptions?.enableDebugEvents) {
577
579
  this.emit("debug", DebugEvents.PlayerAutoReconnect, {
578
580
  state: "log",
@@ -580,12 +582,23 @@ export class LavalinkManager extends EventEmitter {
580
582
  functionLayer: "LavalinkManager > sendRawData()",
581
583
  });
582
584
  }
583
- await player.connect();
585
+ // connect if there are tracks & autoReconnectOnlyWithTracks = true or autoReconnectOnlyWithTracks is false
586
+ if (!autoReconnectOnlyWithTracks || (autoReconnectOnlyWithTracks && (player.queue.current || player.queue.tracks.length))) {
587
+ await player.connect();
588
+ }
584
589
  // replay the current playing stream
585
- await player.play({
586
- position: positionPrevios,
587
- paused: player.paused,
588
- clientTrack: player.queue.current,
590
+ if (player.queue.current) {
591
+ return void await player.play({ position: previousPosition, paused: previousPaused, clientTrack: player.queue.current, });
592
+ }
593
+ // try to play the next track
594
+ if (player.queue.tracks.length) {
595
+ return void await player.play({ paused: previousPaused });
596
+ }
597
+ // debug log if nothing was possible
598
+ this.emit("debug", DebugEvents.PlayerAutoReconnect, {
599
+ state: "log",
600
+ message: `Auto reconnected, but nothing to play`,
601
+ functionLayer: "LavalinkManager > sendRawData()",
589
602
  });
590
603
  }
591
604
  catch (e) {
@@ -593,6 +606,7 @@ export class LavalinkManager extends EventEmitter {
593
606
  return void await player.destroy(DestroyReasons.PlayerReconnectFail);
594
607
  }
595
608
  }
609
+ this.emit("playerDisconnect", player, player.voiceChannelId);
596
610
  player.voiceChannelId = null;
597
611
  player.voice = Object.assign({});
598
612
  return;
@@ -807,7 +807,7 @@ export class LavalinkNode {
807
807
  * @returns boolean
808
808
  */
809
809
  syncPlayerData(data, res) {
810
- if (typeof data === "object" && typeof data?.guildId === "string" && typeof data.playerOptions === "object" && Object.keys(data.playerOptions).length > 1) {
810
+ if (typeof data === "object" && typeof data?.guildId === "string" && typeof data.playerOptions === "object" && Object.keys(data.playerOptions).length > 0) {
811
811
  const player = this.NodeManager.LavalinkManager.getPlayer(data.guildId);
812
812
  if (!player)
813
813
  return;
@@ -833,7 +833,7 @@ export class LavalinkNode {
833
833
  }
834
834
  }
835
835
  if (typeof data.playerOptions.filters !== "undefined") {
836
- const oldFilterTimescale = { ...(player.filterManager.data.timescale || {}) };
836
+ const oldFilterTimescale = { ...player.filterManager.data.timescale };
837
837
  Object.freeze(oldFilterTimescale);
838
838
  if (data.playerOptions.filters.timescale)
839
839
  player.filterManager.data.timescale = data.playerOptions.filters.timescale;
@@ -200,6 +200,8 @@ export interface ManagerPlayerOptions {
200
200
  onDisconnect?: {
201
201
  /** Try to reconnect? -> If fails -> Destroy */
202
202
  autoReconnect?: boolean;
203
+ /** Only try to reconnect if there are tracks in the queue */
204
+ autoReconnectOnlyWithTracks?: boolean;
203
205
  /** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
204
206
  destroyPlayer?: boolean;
205
207
  };
@@ -230,7 +230,7 @@ export interface NodeManagerEvents {
230
230
  * Aka for that you need to be able to save player data like vc channel + text channel in a db and then sync it again
231
231
  * @event Manager.nodeManager#nodeResumed
232
232
  */
233
- "resumed": (node: LavalinkNode, paylaod: {
233
+ "resumed": (node: LavalinkNode, payload: {
234
234
  resumed: true;
235
235
  sessionId: string;
236
236
  op: "ready";
@@ -32,7 +32,7 @@ export class ManagerUtils {
32
32
  buildPluginInfo(data, clientData = {}) {
33
33
  return {
34
34
  clientData: clientData,
35
- ...(data.pluginInfo || data.plugin || {})
35
+ ...(data.pluginInfo || data.plugin),
36
36
  };
37
37
  }
38
38
  buildTrack(data, requester) {
@@ -62,7 +62,7 @@ export class ManagerUtils {
62
62
  isrc: data.info.isrc,
63
63
  },
64
64
  userData: {
65
- ...(data.userData || {}),
65
+ ...data.userData,
66
66
  requester: transformedRequester
67
67
  },
68
68
  pluginInfo: this.buildPluginInfo(data, "clientData" in data ? data.clientData : {}),
@@ -200,6 +200,8 @@ export interface ManagerPlayerOptions {
200
200
  onDisconnect?: {
201
201
  /** Try to reconnect? -> If fails -> Destroy */
202
202
  autoReconnect?: boolean;
203
+ /** Only try to reconnect if there are tracks in the queue */
204
+ autoReconnectOnlyWithTracks?: boolean;
203
205
  /** Instantly destroy player (overrides autoReconnect) | Don't provide == disable feature*/
204
206
  destroyPlayer?: boolean;
205
207
  };
@@ -230,7 +230,7 @@ export interface NodeManagerEvents {
230
230
  * Aka for that you need to be able to save player data like vc channel + text channel in a db and then sync it again
231
231
  * @event Manager.nodeManager#nodeResumed
232
232
  */
233
- "resumed": (node: LavalinkNode, paylaod: {
233
+ "resumed": (node: LavalinkNode, payload: {
234
234
  resumed: true;
235
235
  sessionId: string;
236
236
  op: "ready";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lavalink-client",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",