lavalink-client 2.9.10 → 2.10.0

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/dist/index.js CHANGED
@@ -339,9 +339,6 @@ var NodeLinkExclusiveEvents = [
339
339
  "LyricsNotFoundEvent"
340
340
  ];
341
341
 
342
- // src/structures/NodeManager.ts
343
- import { EventEmitter } from "events";
344
-
345
342
  // src/structures/Node.ts
346
343
  import { isAbsolute } from "path";
347
344
  import WebSocket from "ws";
@@ -354,6 +351,11 @@ var ReconnectionState = /* @__PURE__ */ ((ReconnectionState2) => {
354
351
  ReconnectionState2["DESTROYING"] = "DESTROYING";
355
352
  return ReconnectionState2;
356
353
  })(ReconnectionState || {});
354
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
355
+ NodeType2["Lavalink"] = "Lavalink";
356
+ NodeType2["NodeLink"] = "NodeLink";
357
+ return NodeType2;
358
+ })(NodeType || {});
357
359
 
358
360
  // src/structures/Utils.ts
359
361
  import { URL as URL2 } from "url";
@@ -525,12 +527,14 @@ var QueueSymbol = /* @__PURE__ */ Symbol("LC-Queue");
525
527
  var NodeSymbol = /* @__PURE__ */ Symbol("LC-Node");
526
528
  var escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
527
529
  function parseLavalinkConnUrl(connectionUrl) {
528
- if (!connectionUrl.startsWith("lavalink://") && !connectionUrl.startsWith("nodelink://"))
530
+ if (!connectionUrl) throw new Error("ConnectionUrl is required");
531
+ const lowered = connectionUrl.toLowerCase();
532
+ if (!lowered.startsWith("lavalink://") && !lowered.startsWith("nodelink://"))
529
533
  throw new Error(`ConnectionUrl (${connectionUrl}) must start with 'lavalink://' or 'nodelink://'`);
530
534
  const parsed = new URL2(connectionUrl);
531
535
  return {
532
536
  authorization: parsed.password,
533
- nodeType: connectionUrl.startsWith("lavalink://") ? "Lavalink" : "NodeLink",
537
+ nodeType: lowered.startsWith("lavalink://") ? "Lavalink" /* Lavalink */ : "NodeLink" /* NodeLink */,
534
538
  id: parsed.username,
535
539
  host: parsed.hostname,
536
540
  port: Number(parsed.port)
@@ -1184,7 +1188,7 @@ var LavalinkNode = class _LavalinkNode {
1184
1188
  heartBeatPongTimestamp = 0;
1185
1189
  heartBeatInterval;
1186
1190
  pingTimeout;
1187
- nodeType = "Lavalink";
1191
+ nodeType = "Lavalink" /* Lavalink */;
1188
1192
  isAlive = false;
1189
1193
  static _NodeLinkClass = null;
1190
1194
  /** The provided Options of the Node */
@@ -1258,7 +1262,7 @@ var LavalinkNode = class _LavalinkNode {
1258
1262
  * Returns wether the plugin validations are enabled or not
1259
1263
  */
1260
1264
  get _checkForPlugins() {
1261
- if (this.nodeType === "NodeLink") return false;
1265
+ if (this.nodeType === "NodeLink" /* NodeLink */) return false;
1262
1266
  return !!this.options?.autoChecks?.pluginValidations;
1263
1267
  }
1264
1268
  /**
@@ -1328,16 +1332,17 @@ var LavalinkNode = class _LavalinkNode {
1328
1332
  heartBeatInterval: 3e4,
1329
1333
  enablePingOnStatsCheck: true,
1330
1334
  closeOnError: true,
1335
+ nodeType: "Lavalink" /* Lavalink */,
1331
1336
  ...options,
1332
1337
  autoChecks: {
1333
1338
  sourcesValidations: options?.autoChecks?.sourcesValidations ?? true,
1334
1339
  pluginValidations: options?.autoChecks?.pluginValidations ?? true
1335
1340
  }
1336
1341
  };
1337
- if (this.options.nodeType === "NodeLink" && this.constructor.name === "LavalinkNode" && _LavalinkNode._NodeLinkClass) {
1342
+ if (this.options.nodeType === "NodeLink" /* NodeLink */ && this.constructor.name === "LavalinkNode" && _LavalinkNode._NodeLinkClass) {
1338
1343
  return new _LavalinkNode._NodeLinkClass(options, manager);
1339
1344
  }
1340
- this.nodeType = this.options.nodeType || "Lavalink";
1345
+ this.nodeType = this.options.nodeType;
1341
1346
  this.NodeManager = manager;
1342
1347
  this.validate();
1343
1348
  if (this.options.secure && this.options.port !== 443)
@@ -2280,20 +2285,22 @@ var LavalinkNode = class _LavalinkNode {
2280
2285
  throw new SyntaxError("LavalinkNode.autoChecks.pluginValidations must be either false | true aka boolean");
2281
2286
  if (this.options.regions !== void 0 && (!Array.isArray(this.options.regions) || !this.options.regions.every((r) => typeof r === "string")))
2282
2287
  throw new SyntaxError("LavalinkNode.regions must be an Array of strings");
2288
+ if (this.options.nodeType && !NodeType[this.options.nodeType])
2289
+ throw new SyntaxError("LavalinkNode.nodeType must be a valid NodeType enum value");
2283
2290
  }
2284
2291
  /**
2285
2292
  * Checks if the node is a NodeLink node
2286
2293
  * @returns true if the node is a NodeLink node
2287
2294
  */
2288
2295
  isNodeLink() {
2289
- return this.nodeType === "NodeLink";
2296
+ return this.nodeType === "NodeLink" /* NodeLink */;
2290
2297
  }
2291
2298
  /**
2292
2299
  * Checks if the node is a Lavalink node
2293
2300
  * @returns true if the node is a Lavalink node
2294
2301
  */
2295
2302
  isLavalinkNode() {
2296
- return this.nodeType === "Lavalink";
2303
+ return this.nodeType === "Lavalink" /* Lavalink */;
2297
2304
  }
2298
2305
  /**
2299
2306
  * Sync the data of the player you make an action to lavalink to
@@ -2679,7 +2686,7 @@ var LavalinkNode = class _LavalinkNode {
2679
2686
  }
2680
2687
  /** @private util function for handling trackStart event */
2681
2688
  async trackStart(player, track, payload) {
2682
- if (!player.get("internal_nodeChanging")) {
2689
+ if (!player.getData("internal_nodeChanging")) {
2683
2690
  player.playing = true;
2684
2691
  player.paused = false;
2685
2692
  }
@@ -2707,7 +2714,7 @@ var LavalinkNode = class _LavalinkNode {
2707
2714
  }
2708
2715
  /** @private util function for handling trackEnd event */
2709
2716
  async trackEnd(player, track, payload) {
2710
- if (player.get("internal_nodeChanging") === true) return;
2717
+ if (player.getData("internal_nodeChanging") === true) return;
2711
2718
  const trackToUse = track || this.getTrackOfPayload(payload);
2712
2719
  if (payload.reason === "replaced") {
2713
2720
  this._emitDebugEvent("TrackEndReplaced" /* TrackEndReplaced */, {
@@ -2718,10 +2725,10 @@ var LavalinkNode = class _LavalinkNode {
2718
2725
  this._LManager.emit("trackEnd", player, trackToUse, payload);
2719
2726
  return;
2720
2727
  }
2721
- if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
2728
+ if (!player.queue.tracks.length && (player.repeatMode === "off" || player.getData("internal_stopPlaying")))
2722
2729
  return this.queueEnd(player, track, payload);
2723
2730
  if (["loadFailed", "cleanup"].includes(payload.reason)) {
2724
- if (player.get("internal_destroystatus") === true) return;
2731
+ if (player.getData("internal_destroystatus") === true) return;
2725
2732
  await queueTrackEnd(player);
2726
2733
  if (!player.queue.current) return this.queueEnd(player, trackToUse, payload);
2727
2734
  this._LManager.emit("trackEnd", player, trackToUse, payload);
@@ -2730,7 +2737,7 @@ var LavalinkNode = class _LavalinkNode {
2730
2737
  }
2731
2738
  return;
2732
2739
  }
2733
- if (player.repeatMode !== "track" || player.get("internal_skipped")) await queueTrackEnd(player);
2740
+ if (player.repeatMode !== "track" || player.getData("internal_skipped")) await queueTrackEnd(player);
2734
2741
  else if (trackToUse && !trackToUse?.pluginInfo?.clientData?.previousTrack) {
2735
2742
  player.queue.previous.unshift(trackToUse);
2736
2743
  if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
@@ -2738,7 +2745,7 @@ var LavalinkNode = class _LavalinkNode {
2738
2745
  await player.queue.utils.save();
2739
2746
  }
2740
2747
  if (!player.queue.current) return this.queueEnd(player, trackToUse, payload);
2741
- player.set("internal_skipped", false);
2748
+ player.setData("internal_skipped", false);
2742
2749
  this._LManager.emit("trackEnd", player, trackToUse, payload);
2743
2750
  if (this._LManager.options.autoSkip && player.queue.current) {
2744
2751
  player.play({ noReplace: true });
@@ -2748,10 +2755,10 @@ var LavalinkNode = class _LavalinkNode {
2748
2755
  /** @private util function for handling trackStuck event */
2749
2756
  async trackStuck(player, track, payload) {
2750
2757
  if (this._LManager.options.playerOptions.maxErrorsPerTime?.threshold > 0 && this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount >= 0) {
2751
- const oldTimestamps = (player.get("internal_erroredTracksTimestamps") || []).filter(
2758
+ const oldTimestamps = (player.getData("internal_erroredTracksTimestamps") || []).filter(
2752
2759
  (v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
2753
2760
  );
2754
- player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
2761
+ player.setData("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
2755
2762
  if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
2756
2763
  this._emitDebugEvent("TrackStuckMaxTracksErroredPerTime" /* TrackStuckMaxTracksErroredPerTime */, {
2757
2764
  state: "log",
@@ -2763,7 +2770,7 @@ var LavalinkNode = class _LavalinkNode {
2763
2770
  }
2764
2771
  }
2765
2772
  this._LManager.emit("trackStuck", player, track || this.getTrackOfPayload(payload), payload);
2766
- if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying"))) {
2773
+ if (!player.queue.tracks.length && (player.repeatMode === "off" || player.getData("internal_stopPlaying"))) {
2767
2774
  try {
2768
2775
  await player.node.updatePlayer({
2769
2776
  guildId: player.guildId,
@@ -2786,10 +2793,10 @@ var LavalinkNode = class _LavalinkNode {
2786
2793
  /** @private util function for handling trackError event */
2787
2794
  async trackError(player, track, payload) {
2788
2795
  if (this._LManager.options.playerOptions.maxErrorsPerTime?.threshold > 0 && this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount >= 0) {
2789
- const oldTimestamps = (player.get("internal_erroredTracksTimestamps") || []).filter(
2796
+ const oldTimestamps = (player.getData("internal_erroredTracksTimestamps") || []).filter(
2790
2797
  (v) => Date.now() - v < this._LManager.options.playerOptions.maxErrorsPerTime?.threshold
2791
2798
  );
2792
- player.set("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
2799
+ player.setData("internal_erroredTracksTimestamps", [...oldTimestamps, Date.now()]);
2793
2800
  if (oldTimestamps.length >= this._LManager.options.playerOptions.maxErrorsPerTime?.maxAmount) {
2794
2801
  this._emitDebugEvent("TrackErrorMaxTracksErroredPerTime" /* TrackErrorMaxTracksErroredPerTime */, {
2795
2802
  state: "log",
@@ -2873,7 +2880,7 @@ var LavalinkNode = class _LavalinkNode {
2873
2880
  };
2874
2881
  r.body = safeStringify(segments.map((v) => v.toLowerCase()));
2875
2882
  });
2876
- player.set(
2883
+ player.setData(
2877
2884
  "internal_sponsorBlockCategories",
2878
2885
  segments.map((v) => v.toLowerCase())
2879
2886
  );
@@ -2901,7 +2908,7 @@ var LavalinkNode = class _LavalinkNode {
2901
2908
  await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
2902
2909
  r.method = "DELETE";
2903
2910
  });
2904
- player.set("internal_sponsorBlockCategories", []);
2911
+ player.setData("internal_sponsorBlockCategories", []);
2905
2912
  this._emitDebugEvent("DeleteSponsorBlock" /* DeleteSponsorBlock */, {
2906
2913
  state: "log",
2907
2914
  message: `SponsorBlock was deleted for Player: ${player.guildId}`,
@@ -2911,26 +2918,26 @@ var LavalinkNode = class _LavalinkNode {
2911
2918
  }
2912
2919
  /** private util function for handling the queue end event */
2913
2920
  async queueEnd(player, track, payload) {
2914
- if (player.get("internal_nodeChanging") === true) return;
2921
+ if (player.getData("internal_nodeChanging") === true) return;
2915
2922
  player.queue.current = null;
2916
2923
  player.playing = false;
2917
- player.set("internal_stopPlaying", void 0);
2924
+ player.setData("internal_stopPlaying", void 0);
2918
2925
  this._emitDebugEvent("QueueEnded" /* QueueEnded */, {
2919
2926
  state: "log",
2920
2927
  message: `Queue Ended because no more Tracks were in the Queue, due to EventName: "${payload.type}"`,
2921
2928
  functionLayer: "LavalinkNode > queueEnd()"
2922
2929
  });
2923
- if (typeof this._LManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function" && typeof player.get("internal_autoplayStopPlaying") === "undefined") {
2930
+ if (typeof this._LManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction === "function" && typeof player.getData("internal_autoplayStopPlaying") === "undefined") {
2924
2931
  this._emitDebugEvent("AutoplayExecution" /* AutoplayExecution */, {
2925
2932
  state: "log",
2926
2933
  message: `Now Triggering Autoplay.`,
2927
2934
  functionLayer: "LavalinkNode > queueEnd() > autoplayFunction"
2928
2935
  });
2929
- const previousAutoplayTime = player.get("internal_previousautoplay");
2936
+ const previousAutoplayTime = player.getData("internal_previousautoplay");
2930
2937
  const duration = previousAutoplayTime ? Date.now() - previousAutoplayTime : 0;
2931
- if (!duration || duration > this._LManager.options.playerOptions.minAutoPlayMs || !!player.get("internal_skipped")) {
2938
+ if (!duration || duration > this._LManager.options.playerOptions.minAutoPlayMs || !!player.getData("internal_skipped")) {
2932
2939
  await this._LManager.options?.playerOptions?.onEmptyQueue?.autoPlayFunction(player, track);
2933
- player.set("internal_previousautoplay", Date.now());
2940
+ player.setData("internal_previousautoplay", Date.now());
2934
2941
  if (player.queue.tracks.length > 0) await queueTrackEnd(player);
2935
2942
  else
2936
2943
  this._emitDebugEvent("AutoplayNoSongsAdded" /* AutoplayNoSongsAdded */, {
@@ -2950,8 +2957,8 @@ var LavalinkNode = class _LavalinkNode {
2950
2957
  });
2951
2958
  }
2952
2959
  }
2953
- player.set("internal_skipped", false);
2954
- player.set("internal_autoplayStopPlaying", void 0);
2960
+ player.setData("internal_skipped", false);
2961
+ player.setData("internal_autoplayStopPlaying", void 0);
2955
2962
  if (track && !track?.pluginInfo?.clientData?.previousTrack) {
2956
2963
  player.queue.previous.unshift(track);
2957
2964
  if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
@@ -2976,11 +2983,11 @@ var LavalinkNode = class _LavalinkNode {
2976
2983
  player,
2977
2984
  this._LManager.options.playerOptions.onEmptyQueue?.destroyAfterMs
2978
2985
  );
2979
- if (player.get("internal_queueempty")) clearTimeout(player.get("internal_queueempty"));
2980
- player.set(
2986
+ if (player.getData("internal_queueempty")) clearTimeout(player.getData("internal_queueempty"));
2987
+ player.setData(
2981
2988
  "internal_queueempty",
2982
2989
  setTimeout(() => {
2983
- player.set("internal_queueempty", void 0);
2990
+ player.setData("internal_queueempty", void 0);
2984
2991
  if (player.queue.current) {
2985
2992
  return this._LManager.emit("playerQueueEmptyCancel", player);
2986
2993
  }
@@ -3066,13 +3073,13 @@ var LavalinkNode = class _LavalinkNode {
3066
3073
 
3067
3074
  // src/structures/NodeLink.ts
3068
3075
  var NodeLinkNode = class extends LavalinkNode {
3069
- nodeType = "NodeLink";
3076
+ nodeType = "NodeLink" /* NodeLink */;
3070
3077
  constructor(options, manager) {
3071
3078
  super(options, manager);
3072
- if (this.options.nodeType === "Lavalink" && this.constructor.name === "NodeLink") {
3079
+ if (this.options.nodeType === "Lavalink" /* Lavalink */ && (this.constructor.name === "NodeLinkNode" || this.constructor.name === "NodeLink")) {
3073
3080
  return new LavalinkNode(options, manager);
3074
3081
  }
3075
- this.nodeType = "NodeLink";
3082
+ this.nodeType = "NodeLink" /* NodeLink */;
3076
3083
  }
3077
3084
  /**
3078
3085
  * Uses the gapless feature to set the next track to be played.
@@ -3090,6 +3097,20 @@ var NodeLinkNode = class extends LavalinkNode {
3090
3097
  });
3091
3098
  return true;
3092
3099
  }
3100
+ /**
3101
+ * Removes the nextTrackGapLess configuration
3102
+ * @param player current player
3103
+ * @param track if no track provided, it will use the next track from queue
3104
+ */
3105
+ async removeNextTrackGapLess(player) {
3106
+ if (!this.sessionId) throw new Error("The Lavalink Node is either not ready, or not up to date!");
3107
+ await this.updatePlayer({
3108
+ guildId: player.guildId,
3109
+ // @ts-expect-error - nextTrack is not a valid property of LavalinkPlayOptions but for NodeLink it is
3110
+ playerOptions: { nextTrack: { encoded: null } }
3111
+ });
3112
+ return true;
3113
+ }
3093
3114
  /**
3094
3115
  * Retrieves the meaning of a track.
3095
3116
  * @param track
@@ -3399,6 +3420,7 @@ var NodeLinkNode = class extends LavalinkNode {
3399
3420
  LavalinkNode._NodeLinkClass = NodeLinkNode;
3400
3421
 
3401
3422
  // src/structures/NodeManager.ts
3423
+ import { EventEmitter } from "events";
3402
3424
  var NodeManager = class extends EventEmitter {
3403
3425
  /**
3404
3426
  * Emit an event
@@ -3460,9 +3482,7 @@ var NodeManager = class extends EventEmitter {
3460
3482
  super();
3461
3483
  this.LavalinkManager = LavalinkManager2;
3462
3484
  if (this.LavalinkManager.options.nodes)
3463
- this.LavalinkManager.options.nodes.forEach((node) => {
3464
- this.createNode(node);
3465
- });
3485
+ this.LavalinkManager.options.nodes.forEach((node) => this.createNode(node));
3466
3486
  }
3467
3487
  /**
3468
3488
  * Disconnects all Nodes from lavalink ws sockets
@@ -3523,9 +3543,21 @@ var NodeManager = class extends EventEmitter {
3523
3543
  * @returns The node that was created
3524
3544
  */
3525
3545
  createNode(options) {
3546
+ if (options instanceof NodeLinkNode) {
3547
+ const preExistingNode = this.nodes.get(options.id);
3548
+ if (preExistingNode) return preExistingNode;
3549
+ this.nodes.set(options.id, options);
3550
+ return options;
3551
+ }
3552
+ if (options instanceof LavalinkNode) {
3553
+ const preExistingNode = this.nodes.get(options.id);
3554
+ if (preExistingNode) return preExistingNode;
3555
+ this.nodes.set(options.id, options);
3556
+ return options;
3557
+ }
3526
3558
  if (this.nodes.has(options.id || `${options.host}:${options.port}`))
3527
3559
  return this.nodes.get(options.id || `${options.host}:${options.port}`);
3528
- const newNode = options.nodeType === "NodeLink" ? new NodeLinkNode(options, this) : new LavalinkNode(options, this);
3560
+ const newNode = options.nodeType === "NodeLink" /* NodeLink */ ? new NodeLinkNode(options, this) : new LavalinkNode(options, this);
3529
3561
  this.nodes.set(newNode.id, newNode);
3530
3562
  return newNode;
3531
3563
  }
@@ -3534,48 +3566,57 @@ var NodeManager = class extends EventEmitter {
3534
3566
  * @param sortType The type of sorting to use
3535
3567
  * @returns
3536
3568
  */
3537
- leastUsedNodes(sortType = "players") {
3569
+ leastUsedNodes(sortType = "players", filterForNodeTypes) {
3570
+ const normalizedFilterForNodeTypes = filterForNodeTypes?.length ? filterForNodeTypes : ["Lavalink" /* Lavalink */, "NodeLink" /* NodeLink */];
3538
3571
  const connectedNodes = Array.from(this.nodes.values()).filter((node) => node.connected);
3572
+ const normalizedNodeTypes = new Set(
3573
+ normalizedFilterForNodeTypes.map(
3574
+ (nodeTypeFilter) => Object.values(NodeType).includes(nodeTypeFilter) ? nodeTypeFilter : nodeTypeFilter.nodeType
3575
+ )
3576
+ );
3577
+ const filteredConnectedNodes = connectedNodes.filter((node) => normalizedNodeTypes.has(node.nodeType));
3539
3578
  switch (sortType) {
3540
3579
  case "memory":
3541
3580
  {
3542
- return connectedNodes.sort((a, b) => (a.stats?.memory?.used || 0) - (b.stats?.memory?.used || 0));
3581
+ return filteredConnectedNodes.sort(
3582
+ (a, b) => (a.stats?.memory?.used || 0) - (b.stats?.memory?.used || 0)
3583
+ );
3543
3584
  }
3544
3585
  break;
3545
3586
  case "cpuLavalink":
3546
3587
  {
3547
- return connectedNodes.sort(
3588
+ return filteredConnectedNodes.sort(
3548
3589
  (a, b) => (a.stats?.cpu?.lavalinkLoad || 0) - (b.stats?.cpu?.lavalinkLoad || 0)
3549
3590
  );
3550
3591
  }
3551
3592
  break;
3552
3593
  case "cpuSystem":
3553
3594
  {
3554
- return connectedNodes.sort(
3595
+ return filteredConnectedNodes.sort(
3555
3596
  (a, b) => (a.stats?.cpu?.systemLoad || 0) - (b.stats?.cpu?.systemLoad || 0)
3556
3597
  );
3557
3598
  }
3558
3599
  break;
3559
3600
  case "calls":
3560
3601
  {
3561
- return connectedNodes.sort((a, b) => a.calls - b.calls);
3602
+ return filteredConnectedNodes.sort((a, b) => a.calls - b.calls);
3562
3603
  }
3563
3604
  break;
3564
3605
  case "playingPlayers":
3565
3606
  {
3566
- return connectedNodes.sort(
3607
+ return filteredConnectedNodes.sort(
3567
3608
  (a, b) => (a.stats?.playingPlayers || 0) - (b.stats?.playingPlayers || 0)
3568
3609
  );
3569
3610
  }
3570
3611
  break;
3571
3612
  case "players":
3572
3613
  {
3573
- return connectedNodes.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
3614
+ return filteredConnectedNodes.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
3574
3615
  }
3575
3616
  break;
3576
3617
  default:
3577
3618
  {
3578
- return connectedNodes.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
3619
+ return filteredConnectedNodes.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0));
3579
3620
  }
3580
3621
  break;
3581
3622
  }
@@ -3608,13 +3649,22 @@ var NodeManager = class extends EventEmitter {
3608
3649
  }
3609
3650
  /**
3610
3651
  * Get a node from the nodeManager
3611
- * @param node The node to get
3652
+ * @param node The node to get either by idetnifier, by class or by enum
3612
3653
  * @returns The node that was retrieved
3613
3654
  */
3614
3655
  getNode(node) {
3656
+ if (!!node && Object.values(NodeType).includes(node)) {
3657
+ return this.leastUsedNodes().filter((node2) => node2.nodeType === node2)[0];
3658
+ }
3659
+ if (!!node && node instanceof NodeLinkNode) {
3660
+ return this.leastUsedNodes().filter((node2) => node2 instanceof NodeLinkNode)[0];
3661
+ }
3662
+ if (!!node && node instanceof LavalinkNode) {
3663
+ return this.leastUsedNodes().filter((node2) => node2 instanceof LavalinkNode)[0];
3664
+ }
3615
3665
  const decodeNode = typeof node === "string" ? this.nodes.get(node) : node;
3616
3666
  if (!decodeNode) return void 0;
3617
- if (decodeNode.nodeType === "NodeLink") return decodeNode;
3667
+ if (decodeNode.nodeType === "NodeLink" /* NodeLink */) return decodeNode;
3618
3668
  return decodeNode;
3619
3669
  }
3620
3670
  };
@@ -3890,8 +3940,8 @@ var FilterManager = class {
3890
3940
  this.player.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
3891
3941
  return;
3892
3942
  }
3893
- privateNot0(value) {
3894
- return typeof value === "number" && value !== 0;
3943
+ privateNot0(value, numToCheckAgains = 0) {
3944
+ return typeof value === "number" && value !== numToCheckAgains;
3895
3945
  }
3896
3946
  getLavalinkFilterData() {
3897
3947
  return this.data.pluginFilters?.["lavalink-filter-plugin"] || {
@@ -3938,7 +3988,8 @@ var FilterManager = class {
3938
3988
  this.filters.lowPass = this.privateNot0(this.data.lowPass?.smoothing);
3939
3989
  this.filters.nodeLinkEcho = this.privateNot0(this.data.echo?.delay) || this.privateNot0(this.data.echo?.feedback) || this.privateNot0(this.data.echo?.mix);
3940
3990
  this.filters.nodeLinkChorus = this.privateNot0(this.data.chorus?.rate) || this.privateNot0(this.data.chorus?.depth) || this.privateNot0(this.data.chorus?.delay) || this.privateNot0(this.data.chorus?.mix) || this.privateNot0(this.data.chorus?.feedback);
3941
- this.filters.nodeLinkCompressor = this.privateNot0(this.data.compressor?.threshold) || this.privateNot0(this.data.compressor?.ratio) || this.privateNot0(this.data.compressor?.attack) || this.privateNot0(this.data.compressor?.release) || this.privateNot0(this.data.compressor?.gain);
3991
+ this.filters.nodeLinkCompressor = this.privateNot0(this.data.compressor?.threshold) || this.privateNot0(this.data.compressor?.ratio, 1) || // here "1" is the default
3992
+ this.privateNot0(this.data.compressor?.attack) || this.privateNot0(this.data.compressor?.release) || this.privateNot0(this.data.compressor?.gain);
3942
3993
  this.filters.nodeLinkHighPass = this.privateNot0(this.data.highPass?.smoothing);
3943
3994
  this.filters.nodeLinkPhaser = this.privateNot0(this.data.phaser?.stages) || this.privateNot0(this.data.phaser?.rate) || this.privateNot0(this.data.phaser?.depth) || this.privateNot0(this.data.phaser?.feedback) || this.privateNot0(this.data.phaser?.mix) || this.privateNot0(this.data.phaser?.minFrequency) || this.privateNot0(this.data.phaser?.maxFrequency);
3944
3995
  this.filters.nodeLinkSpatial = this.privateNot0(this.data.spatial?.depth) || this.privateNot0(this.data.spatial?.rate);
@@ -5301,7 +5352,7 @@ var Player = class {
5301
5352
  */
5302
5353
  constructor(options, LavalinkManager2, dontEmitPlayerCreateEvent) {
5303
5354
  if (typeof options?.customData === "object")
5304
- for (const [key, value] of Object.entries(options.customData)) this.set(key, value);
5355
+ for (const [key, value] of Object.entries(options.customData)) this.setData(key, value);
5305
5356
  this.options = options;
5306
5357
  this.filterManager = new FilterManager(this);
5307
5358
  this.LavalinkManager = LavalinkManager2;
@@ -5410,15 +5461,15 @@ var Player = class {
5410
5461
  * @param options
5411
5462
  */
5412
5463
  async play(options = {}) {
5413
- if (this.get("internal_queueempty")) {
5464
+ if (this.getData("internal_queueempty")) {
5414
5465
  this._emitDebugEvent("PlayerPlayQueueEmptyTimeoutClear" /* PlayerPlayQueueEmptyTimeoutClear */, {
5415
5466
  state: "log",
5416
5467
  message: `Player was called to play something, while there was a queueEmpty Timeout set, clearing the timeout.`,
5417
5468
  functionLayer: "Player > play()"
5418
5469
  });
5419
5470
  this.LavalinkManager.emit("playerQueueEmptyCancel", this);
5420
- clearTimeout(this.get("internal_queueempty"));
5421
- this.set("internal_queueempty", void 0);
5471
+ clearTimeout(this.getData("internal_queueempty"));
5472
+ this.setData("internal_queueempty", void 0);
5422
5473
  }
5423
5474
  if (options?.clientTrack && (this.LavalinkManager.utils.isTrack(options?.clientTrack) || this.LavalinkManager.utils.isUnresolvedTrack(options.clientTrack))) {
5424
5475
  if (this.LavalinkManager.utils.isUnresolvedTrack(options.clientTrack)) {
@@ -5766,7 +5817,7 @@ var Player = class {
5766
5817
  }
5767
5818
  if (!this.playing && !this.queue.current) return this.play(), this;
5768
5819
  const now = performance.now();
5769
- this.set("internal_skipped", true);
5820
+ this.setData("internal_skipped", true);
5770
5821
  await this.node.updatePlayer({
5771
5822
  guildId: this.guildId,
5772
5823
  playerOptions: { track: { encoded: null }, paused: false }
@@ -5779,14 +5830,20 @@ var Player = class {
5779
5830
  * @returns
5780
5831
  */
5781
5832
  async stopPlaying(clearQueue = true, executeAutoplay = false) {
5782
- this.set("internal_stopPlaying", true);
5833
+ this.setData("internal_stopPlaying", true);
5783
5834
  if (this.queue.tracks.length && clearQueue === true) await this.queue.splice(0, this.queue.tracks.length);
5784
- if (executeAutoplay === false) this.set("internal_autoplayStopPlaying", true);
5785
- else this.set("internal_autoplayStopPlaying", void 0);
5835
+ if (executeAutoplay === false) this.setData("internal_autoplayStopPlaying", true);
5836
+ else this.setData("internal_autoplayStopPlaying", void 0);
5786
5837
  const now = performance.now();
5787
5838
  await this.node.updatePlayer({
5788
5839
  guildId: this.guildId,
5789
- playerOptions: { track: { encoded: null } }
5840
+ playerOptions: this.node.isNodeLink() ? {
5841
+ track: { encoded: null },
5842
+ // @ts-expect-error - nextTrack is not a valid property of LavalinkPlayOptions but for NodeLink it is
5843
+ nextTrack: { encoded: null }
5844
+ } : {
5845
+ track: { encoded: null }
5846
+ }
5790
5847
  });
5791
5848
  this.paused = false;
5792
5849
  this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
@@ -5857,11 +5914,11 @@ var Player = class {
5857
5914
  console.log(
5858
5915
  `Lavalink-Client-Debug | PlayerDestroy [::] destroy Function, [guildId ${this.guildId}] - Destroy-Reason: ${String(reason)}`
5859
5916
  );
5860
- if (this.get("internal_queueempty")) {
5861
- clearTimeout(this.get("internal_queueempty"));
5862
- this.set("internal_queueempty", void 0);
5917
+ if (this.getData("internal_queueempty")) {
5918
+ clearTimeout(this.getData("internal_queueempty"));
5919
+ this.setData("internal_queueempty", void 0);
5863
5920
  }
5864
- if (this.get("internal_destroystatus") === true) {
5921
+ if (this.getData("internal_destroystatus") === true) {
5865
5922
  this._emitDebugEvent("PlayerDestroyingSomewhereElse" /* PlayerDestroyingSomewhereElse */, {
5866
5923
  state: "warn",
5867
5924
  message: `Player is already destroying somewhere else..`,
@@ -5873,9 +5930,9 @@ var Player = class {
5873
5930
  );
5874
5931
  return;
5875
5932
  }
5876
- this.set("internal_destroystatus", true);
5933
+ this.setData("internal_destroystatus", true);
5877
5934
  if (disconnect) await this.disconnect(true);
5878
- else this.set("internal_destroywithoutdisconnect", true);
5935
+ else this.setData("internal_destroywithoutdisconnect", true);
5879
5936
  await this.queue.utils.destroy();
5880
5937
  this.LavalinkManager.deletePlayer(this.guildId);
5881
5938
  await this.node.destroyPlayer(this.guildId);
@@ -5950,7 +6007,7 @@ var Player = class {
5950
6007
  if (!updateNode) throw new Error("Could not find the new Node");
5951
6008
  if (!updateNode.connected) throw new Error("The provided Node is not active or disconnected");
5952
6009
  if (this.node.id === updateNode.id) throw new Error("Player is already on the provided Node");
5953
- if (this.get("internal_nodeChanging") === true)
6010
+ if (this.getData("internal_nodeChanging") === true)
5954
6011
  throw new Error("Player is already changing the node please wait");
5955
6012
  if (checkSources) {
5956
6013
  const isDefaultSource = () => {
@@ -5988,7 +6045,7 @@ var Player = class {
5988
6045
  const currentTrack = this.queue.current;
5989
6046
  if (!this.voice.endpoint || !this.voice.sessionId || !this.voice.token)
5990
6047
  throw new Error("Voice Data is missing, can't change the node");
5991
- this.set("internal_nodeChanging", true);
6048
+ this.setData("internal_nodeChanging", true);
5992
6049
  if (this.node.connected) await this.node.destroyPlayer(this.guildId);
5993
6050
  this.node = updateNode;
5994
6051
  const now = performance.now();
@@ -5996,7 +6053,7 @@ var Player = class {
5996
6053
  await this.connect();
5997
6054
  const hasSponsorBlock = !this.node._checkForPlugins || this.node.info?.plugins?.find((v) => v.name === "sponsorblock-plugin");
5998
6055
  if (hasSponsorBlock) {
5999
- const sponsorBlockCategories = this.get("internal_sponsorBlockCategories");
6056
+ const sponsorBlockCategories = this.getData("internal_sponsorBlockCategories");
6000
6057
  if (Array.isArray(sponsorBlockCategories) && sponsorBlockCategories.length) {
6001
6058
  await this.setSponsorBlock(sponsorBlockCategories).catch((error) => {
6002
6059
  this._emitDebugEvent("PlayerChangeNode" /* PlayerChangeNode */, {
@@ -6047,7 +6104,7 @@ var Player = class {
6047
6104
  });
6048
6105
  throw new Error(`Failed to change the node: ${error}`);
6049
6106
  } finally {
6050
- this.set("internal_nodeChanging", void 0);
6107
+ this.setData("internal_nodeChanging", void 0);
6051
6108
  }
6052
6109
  }
6053
6110
  /**
@@ -6246,9 +6303,11 @@ var LavalinkManager = class _LavalinkManager extends EventEmitter2 {
6246
6303
  throw new SyntaxError("ManagerOption.autoSkipOnResolveError must be either false | true aka boolean");
6247
6304
  if (options?.emitNewSongsOnly && typeof options?.emitNewSongsOnly !== "boolean")
6248
6305
  throw new SyntaxError("ManagerOption.emitNewSongsOnly must be either false | true aka boolean");
6249
- if (!options?.nodes || !Array.isArray(options?.nodes) || !options?.nodes.every((node) => this.utils.isNodeOptions(node)))
6306
+ if (!options?.nodes || !Array.isArray(options?.nodes) || !options?.nodes.every(
6307
+ (node) => node instanceof NodeLinkNode || node instanceof LavalinkNode || this.utils.isNodeOptions(node)
6308
+ ))
6250
6309
  throw new SyntaxError(
6251
- "ManagerOption.nodes must be an Array of NodeOptions and is required of at least 1 Node"
6310
+ "ManagerOption.nodes must be an Array of NodeOptions or the Node-Classes 'NodeLinkNode' or 'LavalinkNode' and is required of at least 1 Node"
6252
6311
  );
6253
6312
  if (options?.queueOptions?.queueStore) {
6254
6313
  const keys = Object.getOwnPropertyNames(Object.getPrototypeOf(options?.queueOptions?.queueStore));
@@ -6304,48 +6363,50 @@ var LavalinkManager = class _LavalinkManager extends EventEmitter2 {
6304
6363
  * port: 2333,
6305
6364
  * id: "testnode"
6306
6365
  * },
6366
+ * // you can also use the util like this, and it will return a valid node option object. must start with: lavalink:// | nodelink://
6367
+ * // parseLavalinkConnUrl("nodelink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>")
6307
6368
  * sendToShard(guildId, payload) => client.guilds.cache.get(guildId)?.shard?.send(payload),
6308
- * client: {
6309
- * id: process.env.CLIENT_ID,
6310
- * username: "TESTBOT"
6311
- * },
6312
- * // optional Options:
6313
- * autoSkip: true,
6314
- * playerOptions: {
6315
- * applyVolumeAsFilter: false,
6316
- * clientBasedPositionUpdateInterval: 150,
6317
- * defaultSearchPlatform: "ytmsearch",
6318
- * allowCustomSources: false,
6319
- * volumeDecrementer: 0.75,
6320
- * //requesterTransformer: YourRequesterTransformerFunction,
6321
- * onDisconnect: {
6322
- * autoReconnect: true,
6323
- * destroyPlayer: false
6324
- * },
6325
- * onEmptyQueue: {
6326
- * destroyAfterMs: 30_000,
6327
- * //autoPlayFunction: YourAutoplayFunction,
6328
- * },
6329
- * useUnresolvedData: true
6369
+ * ],
6370
+ * client: {
6371
+ * id: process.env.CLIENT_ID,
6372
+ * username: "TESTBOT"
6373
+ * },
6374
+ * // optional Options:
6375
+ * autoSkip: true,
6376
+ * playerOptions: {
6377
+ * applyVolumeAsFilter: false,
6378
+ * clientBasedPositionUpdateInterval: 150,
6379
+ * defaultSearchPlatform: "ytmsearch",
6380
+ * allowCustomSources: false,
6381
+ * volumeDecrementer: 0.75,
6382
+ * //requesterTransformer: YourRequesterTransformerFunction,
6383
+ * onDisconnect: {
6384
+ * autoReconnect: true,
6385
+ * destroyPlayer: false
6330
6386
  * },
6331
- * queueOptions: {
6332
- * maxPreviousTracks: 25,
6333
- * //queueStore: yourCustomQueueStoreManagerClass,
6334
- * //queueChangesWatcher: yourCustomQueueChangesWatcherClass
6387
+ * onEmptyQueue: {
6388
+ * destroyAfterMs: 30_000,
6389
+ * //autoPlayFunction: YourAutoplayFunction,
6335
6390
  * },
6336
- * linksBlacklist: [],
6337
- * linksWhitelist: [],
6338
- * advancedOptions: {
6339
- * maxFilterFixDuration: 600_000,
6340
- * debugOptions: {
6341
- * noAudio: false,
6342
- * playerDestroy: {
6343
- * dontThrowError: false,
6344
- * debugLogs: false
6345
- * }
6391
+ * useUnresolvedData: true
6392
+ * },
6393
+ * queueOptions: {
6394
+ * maxPreviousTracks: 25,
6395
+ * //queueStore: yourCustomQueueStoreManagerClass,
6396
+ * //queueChangesWatcher: yourCustomQueueChangesWatcherClass
6397
+ * },
6398
+ * linksBlacklist: [],
6399
+ * linksWhitelist: [],
6400
+ * advancedOptions: {
6401
+ * maxFilterFixDuration: 600_000,
6402
+ * debugOptions: {
6403
+ * noAudio: false,
6404
+ * playerDestroy: {
6405
+ * dontThrowError: false,
6406
+ * debugLogs: false
6346
6407
  * }
6347
6408
  * }
6348
- * ]
6409
+ * }
6349
6410
  * })
6350
6411
  * ```
6351
6412
  */
@@ -6437,7 +6498,7 @@ var LavalinkManager = class _LavalinkManager extends EventEmitter2 {
6437
6498
  deletePlayer(guildId) {
6438
6499
  const oldPlayer = this.getPlayer(guildId);
6439
6500
  if (!oldPlayer) return;
6440
- if (typeof oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
6501
+ if (typeof oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.getData("internal_destroywithoutdisconnect")) {
6441
6502
  if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError)
6442
6503
  throw new Error(
6443
6504
  `Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${safeStringify(oldPlayer.toJSON?.())}`
@@ -6584,7 +6645,7 @@ var LavalinkManager = class _LavalinkManager extends EventEmitter2 {
6584
6645
  );
6585
6646
  return;
6586
6647
  }
6587
- if (player.get("internal_destroystatus") === true) {
6648
+ if (player.getData("internal_destroystatus") === true) {
6588
6649
  this._debugNoAudio("warn", "LavalinkManager > sendRawData()", {
6589
6650
  message: "Player is in a destroying state. can't signal the voice states"
6590
6651
  });
@@ -6753,6 +6814,7 @@ export {
6753
6814
  NodeLinkNode,
6754
6815
  NodeManager,
6755
6816
  NodeSymbol,
6817
+ NodeType,
6756
6818
  Player,
6757
6819
  Queue,
6758
6820
  QueueSaver,