lavalink-client 2.2.1 → 2.3.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/README.md +140 -20
- package/dist/cjs/index.d.ts +7 -1
- package/dist/cjs/index.js +7 -1
- package/dist/cjs/structures/Constants.d.ts +40 -0
- package/dist/cjs/structures/Constants.js +244 -0
- package/dist/cjs/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/cjs/structures/Filters.d.ts +2 -217
- package/dist/cjs/structures/Filters.js +12 -236
- package/dist/cjs/structures/LavalinkManager.d.ts +31 -166
- package/dist/cjs/structures/LavalinkManager.js +60 -8
- package/dist/cjs/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/cjs/structures/LavalinkManagerStatics.js +1 -1
- package/dist/cjs/structures/Node.d.ts +15 -156
- package/dist/cjs/structures/Node.js +140 -51
- package/dist/cjs/structures/NodeManager.d.ts +54 -52
- package/dist/cjs/structures/NodeManager.js +77 -5
- package/dist/cjs/structures/Player.d.ts +31 -124
- package/dist/cjs/structures/Player.js +78 -43
- package/dist/cjs/structures/Queue.d.ts +113 -42
- package/dist/cjs/structures/Queue.js +169 -8
- package/dist/cjs/structures/Types/Filters.d.ts +190 -0
- package/dist/cjs/structures/Types/Manager.d.ts +184 -0
- package/dist/cjs/structures/Types/Manager.js +2 -0
- package/dist/cjs/structures/Types/Node.d.ts +216 -0
- package/dist/cjs/structures/Types/Node.js +2 -0
- package/dist/cjs/structures/Types/Player.d.ts +108 -0
- package/dist/cjs/structures/Types/Player.js +2 -0
- package/dist/cjs/structures/Types/Queue.d.ts +34 -0
- package/dist/cjs/structures/Types/Queue.js +2 -0
- package/dist/cjs/structures/{Track.d.ts → Types/Track.d.ts} +4 -2
- package/dist/cjs/structures/Types/Track.js +2 -0
- package/dist/cjs/structures/Types/Utils.d.ts +367 -0
- package/dist/cjs/structures/Types/Utils.js +2 -0
- package/dist/cjs/structures/Utils.d.ts +13 -369
- package/dist/cjs/structures/Utils.js +40 -18
- package/dist/esm/index.d.ts +7 -1
- package/dist/esm/index.js +7 -1
- package/dist/esm/structures/Constants.d.ts +40 -0
- package/dist/esm/structures/Constants.js +241 -0
- package/dist/esm/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/esm/structures/Filters.d.ts +2 -217
- package/dist/esm/structures/Filters.js +7 -231
- package/dist/esm/structures/LavalinkManager.d.ts +31 -166
- package/dist/esm/structures/LavalinkManager.js +58 -6
- package/dist/esm/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/esm/structures/LavalinkManagerStatics.js +1 -1
- package/dist/esm/structures/Node.d.ts +15 -156
- package/dist/esm/structures/Node.js +132 -43
- package/dist/esm/structures/NodeManager.d.ts +54 -52
- package/dist/esm/structures/NodeManager.js +74 -2
- package/dist/esm/structures/Player.d.ts +31 -124
- package/dist/esm/structures/Player.js +77 -42
- package/dist/esm/structures/Queue.d.ts +113 -42
- package/dist/esm/structures/Queue.js +169 -8
- package/dist/esm/structures/Types/Filters.d.ts +190 -0
- package/dist/esm/structures/Types/Manager.d.ts +184 -0
- package/dist/esm/structures/Types/Manager.js +1 -0
- package/dist/esm/structures/Types/Node.d.ts +216 -0
- package/dist/esm/structures/Types/Node.js +1 -0
- package/dist/esm/structures/Types/Player.d.ts +108 -0
- package/dist/esm/structures/Types/Player.js +1 -0
- package/dist/esm/structures/Types/Queue.d.ts +34 -0
- package/dist/esm/structures/Types/Queue.js +1 -0
- package/dist/{types/structures → esm/structures/Types}/Track.d.ts +4 -2
- package/dist/esm/structures/Types/Track.js +1 -0
- package/dist/esm/structures/Types/Utils.d.ts +367 -0
- package/dist/esm/structures/Types/Utils.js +1 -0
- package/dist/esm/structures/Utils.d.ts +13 -369
- package/dist/esm/structures/Utils.js +40 -18
- package/dist/types/index.d.ts +7 -1
- package/dist/types/structures/Constants.d.ts +40 -0
- package/dist/types/structures/CustomSearches/BandCampSearch.d.ts +2 -2
- package/dist/types/structures/Filters.d.ts +2 -217
- package/dist/types/structures/LavalinkManager.d.ts +31 -166
- package/dist/types/structures/LavalinkManagerStatics.d.ts +1 -1
- package/dist/types/structures/Node.d.ts +15 -156
- package/dist/types/structures/NodeManager.d.ts +54 -52
- package/dist/types/structures/Player.d.ts +31 -124
- package/dist/types/structures/Queue.d.ts +113 -42
- package/dist/types/structures/Types/Filters.d.ts +190 -0
- package/dist/types/structures/Types/Manager.d.ts +184 -0
- package/dist/types/structures/Types/Node.d.ts +216 -0
- package/dist/types/structures/Types/Player.d.ts +108 -0
- package/dist/types/structures/Types/Queue.d.ts +34 -0
- package/dist/{esm/structures → types/structures/Types}/Track.d.ts +4 -2
- package/dist/types/structures/Types/Utils.d.ts +367 -0
- package/dist/types/structures/Utils.d.ts +13 -369
- package/package.json +1 -1
- /package/dist/cjs/structures/{Track.js → Types/Filters.js} +0 -0
- /package/dist/esm/structures/{Track.js → Types/Filters.js} +0 -0
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LavalinkNode =
|
|
3
|
+
exports.LavalinkNode = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
7
|
-
const
|
|
7
|
+
const Constants_1 = require("./Constants");
|
|
8
8
|
const Utils_1 = require("./Utils");
|
|
9
|
-
exports.validSponsorBlocks = ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "filler"];
|
|
10
9
|
/**
|
|
11
10
|
* Lavalink Node creator class
|
|
12
11
|
*/
|
|
13
12
|
class LavalinkNode {
|
|
13
|
+
heartBeatPingTimestamp = 0;
|
|
14
|
+
heartBeatPongTimestamp = 0;
|
|
15
|
+
get heartBeatPing() {
|
|
16
|
+
return this.heartBeatPongTimestamp - this.heartBeatPingTimestamp;
|
|
17
|
+
}
|
|
18
|
+
heartBeatInterval;
|
|
19
|
+
pingTimeout;
|
|
14
20
|
/** The provided Options of the Node */
|
|
15
21
|
options;
|
|
16
22
|
/** The amount of rest calls the node has made. */
|
|
@@ -70,8 +76,11 @@ class LavalinkNode {
|
|
|
70
76
|
this.options = {
|
|
71
77
|
secure: false,
|
|
72
78
|
retryAmount: 5,
|
|
73
|
-
retryDelay:
|
|
79
|
+
retryDelay: 10e3,
|
|
74
80
|
requestSignalTimeoutMS: 10000,
|
|
81
|
+
heartBeatInterval: 30000,
|
|
82
|
+
closeOnError: true,
|
|
83
|
+
enablePingOnStatsCheck: true,
|
|
75
84
|
...options
|
|
76
85
|
};
|
|
77
86
|
this.NodeManager = manager;
|
|
@@ -150,6 +159,8 @@ class LavalinkNode {
|
|
|
150
159
|
* ```
|
|
151
160
|
*/
|
|
152
161
|
async request(endpoint, modify, parseAsText = false) {
|
|
162
|
+
if (!this.connected)
|
|
163
|
+
throw new Error("The node is not connected to the Lavalink Server!, Please call node.connect() first!");
|
|
153
164
|
const { request, options } = await this.rawRequest(endpoint, modify);
|
|
154
165
|
if (["DELETE", "PUT"].includes(options.method))
|
|
155
166
|
return;
|
|
@@ -234,7 +245,7 @@ class LavalinkNode {
|
|
|
234
245
|
if (Query.source)
|
|
235
246
|
this.NodeManager.LavalinkManager.utils.validateSourceString(this, Query.source);
|
|
236
247
|
if (/^https?:\/\//.test(Query.query))
|
|
237
|
-
return
|
|
248
|
+
return this.search({ query: Query.query, source: Query.source }, requestUser);
|
|
238
249
|
if (!["spsearch", "sprec", "amsearch", "dzsearch", "dzisrc", "ytmsearch", "ytsearch"].includes(Query.source))
|
|
239
250
|
throw new SyntaxError(`Query.source must be a source from LavaSrc: "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "ytmsearch" | "ytsearch"`);
|
|
240
251
|
if (!this.info.plugins.find(v => v.name === "lavasearch-plugin"))
|
|
@@ -296,7 +307,7 @@ class LavalinkNode {
|
|
|
296
307
|
async destroyPlayer(guildId) {
|
|
297
308
|
if (!this.sessionId)
|
|
298
309
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
299
|
-
return
|
|
310
|
+
return this.request(`/sessions/${this.sessionId}/players/${guildId}`, r => { r.method = "DELETE"; });
|
|
300
311
|
}
|
|
301
312
|
/**
|
|
302
313
|
* Connect to the Lavalink Node
|
|
@@ -328,6 +339,17 @@ class LavalinkNode {
|
|
|
328
339
|
this.socket.on("close", (code, reason) => this.close(code, reason?.toString()));
|
|
329
340
|
this.socket.on("message", this.message.bind(this));
|
|
330
341
|
this.socket.on("error", this.error.bind(this));
|
|
342
|
+
// this.socket.on("ping", () => this.heartBeat("ping")); // lavalink doesn'T send ping periodically, therefore we use the stats message
|
|
343
|
+
}
|
|
344
|
+
heartBeat() {
|
|
345
|
+
if (this.pingTimeout)
|
|
346
|
+
clearTimeout(this.pingTimeout);
|
|
347
|
+
this.pingTimeout = setTimeout(() => {
|
|
348
|
+
if (!this.socket)
|
|
349
|
+
return console.error("Node-Ping-Acknowledge-Timeout - Socket not available - maybe reconnecting?");
|
|
350
|
+
this.isAlive = false;
|
|
351
|
+
this.socket.terminate();
|
|
352
|
+
}, 65000); // the stats endpoint get's sent every 60s. se wee add a 5s buffer to make sure we don't miss any stats message
|
|
331
353
|
}
|
|
332
354
|
/**
|
|
333
355
|
* Get the id of the node
|
|
@@ -355,9 +377,11 @@ class LavalinkNode {
|
|
|
355
377
|
destroy(destroyReason, deleteNode = true) {
|
|
356
378
|
if (!this.connected)
|
|
357
379
|
return;
|
|
358
|
-
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id
|
|
380
|
+
const players = this.NodeManager.LavalinkManager.players.filter(p => p.node.id === this.id);
|
|
359
381
|
if (players)
|
|
360
|
-
players.forEach(p =>
|
|
382
|
+
players.forEach(p => {
|
|
383
|
+
p.destroy(destroyReason || Constants_1.DestroyReasons.NodeDestroy);
|
|
384
|
+
});
|
|
361
385
|
this.socket.close(1000, "Node-Destroy");
|
|
362
386
|
this.socket.removeAllListeners();
|
|
363
387
|
this.socket = null;
|
|
@@ -386,6 +410,7 @@ class LavalinkNode {
|
|
|
386
410
|
return false;
|
|
387
411
|
return this.socket.readyState === ws_1.default.OPEN;
|
|
388
412
|
}
|
|
413
|
+
isAlive = false;
|
|
389
414
|
/**
|
|
390
415
|
* Returns the current ConnectionStatus
|
|
391
416
|
*
|
|
@@ -417,11 +442,7 @@ class LavalinkNode {
|
|
|
417
442
|
async fetchAllPlayers() {
|
|
418
443
|
if (!this.sessionId)
|
|
419
444
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
420
|
-
|
|
421
|
-
if (!Array.isArray(players))
|
|
422
|
-
return [];
|
|
423
|
-
else
|
|
424
|
-
return players;
|
|
445
|
+
return this.request(`/sessions/${this.sessionId}/players`) || [];
|
|
425
446
|
}
|
|
426
447
|
/**
|
|
427
448
|
* Gets specific Player Information
|
|
@@ -436,7 +457,7 @@ class LavalinkNode {
|
|
|
436
457
|
async fetchPlayer(guildId) {
|
|
437
458
|
if (!this.sessionId)
|
|
438
459
|
throw new Error("The Lavalink-Node is either not ready, or not up to date!");
|
|
439
|
-
return
|
|
460
|
+
return this.request(`/sessions/${this.sessionId}/players/${guildId}`);
|
|
440
461
|
}
|
|
441
462
|
/**
|
|
442
463
|
* Updates the session with and enables/disables resuming and timeout
|
|
@@ -462,7 +483,7 @@ class LavalinkNode {
|
|
|
462
483
|
enabled: typeof resuming === "boolean" ? resuming : false,
|
|
463
484
|
timeout: typeof resuming === "boolean" && resuming === true ? timeout : null,
|
|
464
485
|
};
|
|
465
|
-
return
|
|
486
|
+
return this.request(`/sessions/${this.sessionId}`, r => {
|
|
466
487
|
r.method = "PATCH";
|
|
467
488
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
468
489
|
r.body = JSON.stringify(data);
|
|
@@ -686,7 +707,7 @@ class LavalinkNode {
|
|
|
686
707
|
if (!player)
|
|
687
708
|
return;
|
|
688
709
|
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false)
|
|
689
|
-
return player.destroy(
|
|
710
|
+
return player.destroy(Constants_1.DestroyReasons.LavalinkNoVoice);
|
|
690
711
|
player.ping.ws = res?.voice?.ping || player?.ping.ws;
|
|
691
712
|
}
|
|
692
713
|
return true;
|
|
@@ -708,11 +729,12 @@ class LavalinkNode {
|
|
|
708
729
|
* ```
|
|
709
730
|
*/
|
|
710
731
|
reconnect(instaReconnect = false) {
|
|
732
|
+
this.NodeManager.emit("reconnectinprogress", this);
|
|
711
733
|
if (instaReconnect) {
|
|
712
734
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
713
735
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
714
736
|
this.NodeManager.emit("error", this, error);
|
|
715
|
-
return this.destroy(
|
|
737
|
+
return this.destroy(Constants_1.DestroyReasons.NodeReconnectFail);
|
|
716
738
|
}
|
|
717
739
|
this.socket.removeAllListeners();
|
|
718
740
|
this.socket = null;
|
|
@@ -725,7 +747,7 @@ class LavalinkNode {
|
|
|
725
747
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
726
748
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
727
749
|
this.NodeManager.emit("error", this, error);
|
|
728
|
-
return this.destroy(
|
|
750
|
+
return this.destroy(Constants_1.DestroyReasons.NodeReconnectFail);
|
|
729
751
|
}
|
|
730
752
|
this.socket.removeAllListeners();
|
|
731
753
|
this.socket = null;
|
|
@@ -736,6 +758,29 @@ class LavalinkNode {
|
|
|
736
758
|
}
|
|
737
759
|
/** @private util function for handling opening events from websocket */
|
|
738
760
|
async open() {
|
|
761
|
+
this.isAlive = true;
|
|
762
|
+
// trigger heartbeat-ping timeout - this is to check wether the client lost connection without knowing it
|
|
763
|
+
if (this.options.enablePingOnStatsCheck)
|
|
764
|
+
this.heartBeat();
|
|
765
|
+
if (this.heartBeatInterval)
|
|
766
|
+
clearInterval(this.heartBeatInterval);
|
|
767
|
+
if (this.options.heartBeatInterval > 0) {
|
|
768
|
+
// everytime a pong happens, set this.isAlive to true
|
|
769
|
+
this.socket.on("pong", () => {
|
|
770
|
+
this.heartBeatPongTimestamp = performance.now();
|
|
771
|
+
this.isAlive = true;
|
|
772
|
+
});
|
|
773
|
+
// every x ms send a ping to lavalink to retrieve a pong later on
|
|
774
|
+
this.heartBeatInterval = setInterval(() => {
|
|
775
|
+
if (!this.socket)
|
|
776
|
+
return console.error("Node-Heartbeat-Interval - Socket not available - maybe reconnecting?");
|
|
777
|
+
if (!this.isAlive)
|
|
778
|
+
this.close(500, "Node-Heartbeat-Timeout");
|
|
779
|
+
this.isAlive = false;
|
|
780
|
+
this.heartBeatPingTimestamp = performance.now();
|
|
781
|
+
this.socket.ping();
|
|
782
|
+
}, this.options.heartBeatInterval || 30000);
|
|
783
|
+
}
|
|
739
784
|
if (this.reconnectTimeout)
|
|
740
785
|
clearTimeout(this.reconnectTimeout);
|
|
741
786
|
// reset the reconnect attempts amount
|
|
@@ -749,6 +794,12 @@ class LavalinkNode {
|
|
|
749
794
|
}
|
|
750
795
|
/** @private util function for handling closing events from websocket */
|
|
751
796
|
close(code, reason) {
|
|
797
|
+
if (this.pingTimeout)
|
|
798
|
+
clearTimeout(this.pingTimeout);
|
|
799
|
+
if (this.heartBeatInterval)
|
|
800
|
+
clearInterval(this.heartBeatInterval);
|
|
801
|
+
if (code === 1006 && !reason)
|
|
802
|
+
reason = "Socket got terminated due to no ping connection";
|
|
752
803
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
753
804
|
if (code !== 1000 || reason !== "Node-Destroy")
|
|
754
805
|
this.reconnect();
|
|
@@ -758,6 +809,14 @@ class LavalinkNode {
|
|
|
758
809
|
if (!error)
|
|
759
810
|
return;
|
|
760
811
|
this.NodeManager.emit("error", this, error);
|
|
812
|
+
if (this.options.closeOnError) {
|
|
813
|
+
if (this.heartBeatInterval)
|
|
814
|
+
clearInterval(this.heartBeatInterval);
|
|
815
|
+
if (this.pingTimeout)
|
|
816
|
+
clearTimeout(this.pingTimeout);
|
|
817
|
+
this.socket?.close(500, "Node-Error - Force Reconnect");
|
|
818
|
+
}
|
|
819
|
+
;
|
|
761
820
|
}
|
|
762
821
|
/** @private util function for handling message events from websocket */
|
|
763
822
|
async message(d) {
|
|
@@ -771,6 +830,8 @@ class LavalinkNode {
|
|
|
771
830
|
this.NodeManager.emit("raw", this, payload);
|
|
772
831
|
switch (payload.op) {
|
|
773
832
|
case "stats":
|
|
833
|
+
if (this.options.enablePingOnStatsCheck)
|
|
834
|
+
this.heartBeat(); // lavalink doesn'T send "ping" periodically, therefore we use the stats message to check for a ping
|
|
774
835
|
delete payload.op;
|
|
775
836
|
this.stats = { ...payload };
|
|
776
837
|
break;
|
|
@@ -800,7 +861,13 @@ class LavalinkNode {
|
|
|
800
861
|
this.sessionId = payload.sessionId;
|
|
801
862
|
this.resuming.enabled = payload.resumed;
|
|
802
863
|
if (payload.resumed === true) {
|
|
803
|
-
|
|
864
|
+
try {
|
|
865
|
+
this.NodeManager.emit("resumed", this, payload, await this.fetchAllPlayers());
|
|
866
|
+
}
|
|
867
|
+
catch (e) {
|
|
868
|
+
console.error("Failed to fetch players for resumed event, falling back without players array", e);
|
|
869
|
+
this.NodeManager.emit("resumed", this, payload, []);
|
|
870
|
+
}
|
|
804
871
|
}
|
|
805
872
|
break;
|
|
806
873
|
default:
|
|
@@ -810,7 +877,7 @@ class LavalinkNode {
|
|
|
810
877
|
}
|
|
811
878
|
/** @private middleware util function for handling all kind of events from websocket */
|
|
812
879
|
async handleEvent(payload) {
|
|
813
|
-
if (!payload
|
|
880
|
+
if (!payload?.guildId)
|
|
814
881
|
return;
|
|
815
882
|
const player = this.NodeManager.LavalinkManager.getPlayer(payload.guildId);
|
|
816
883
|
if (!player)
|
|
@@ -849,39 +916,51 @@ class LavalinkNode {
|
|
|
849
916
|
}
|
|
850
917
|
return;
|
|
851
918
|
}
|
|
919
|
+
async getTrackOfPayload(payload) {
|
|
920
|
+
return "track" in payload
|
|
921
|
+
? this.NodeManager.LavalinkManager.utils.buildTrack(payload.track, undefined)
|
|
922
|
+
: null;
|
|
923
|
+
}
|
|
852
924
|
/** @private util function for handling trackStart event */
|
|
853
|
-
trackStart(player, track, payload) {
|
|
925
|
+
async trackStart(player, track, payload) {
|
|
854
926
|
player.playing = true;
|
|
855
927
|
player.paused = false;
|
|
856
928
|
// don't emit the event if previous track == new track aka track loop
|
|
857
929
|
if (this.NodeManager.LavalinkManager.options?.emitNewSongsOnly === true && player.queue.previous[0]?.info?.identifier === track?.info?.identifier)
|
|
858
930
|
return;
|
|
859
|
-
|
|
931
|
+
if (!player.queue.current) {
|
|
932
|
+
player.queue.current = await this.getTrackOfPayload(payload);
|
|
933
|
+
if (player.queue.current)
|
|
934
|
+
await player.queue.utils.save();
|
|
935
|
+
}
|
|
936
|
+
return this.NodeManager.LavalinkManager.emit("trackStart", player, player.queue.current, payload);
|
|
860
937
|
}
|
|
861
938
|
/** @private util function for handling trackEnd event */
|
|
862
939
|
async trackEnd(player, track, payload) {
|
|
940
|
+
const trackToUse = track || await this.getTrackOfPayload(payload);
|
|
941
|
+
// If a track was forcibly played
|
|
942
|
+
if (payload.reason === "replaced") {
|
|
943
|
+
return this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
944
|
+
}
|
|
863
945
|
// If there are no songs in the queue
|
|
864
946
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
865
947
|
return this.queueEnd(player, track, payload);
|
|
866
|
-
// If a track was forcibly played
|
|
867
|
-
if (payload.reason === "replaced")
|
|
868
|
-
return this.NodeManager.LavalinkManager.emit("trackEnd", player, track, payload);
|
|
869
948
|
// If a track had an error while starting
|
|
870
949
|
if (["loadFailed", "cleanup"].includes(payload.reason)) {
|
|
871
950
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
872
951
|
// if no track available, end queue
|
|
873
952
|
if (!player.queue.current)
|
|
874
|
-
return this.queueEnd(player,
|
|
953
|
+
return this.queueEnd(player, trackToUse, payload);
|
|
875
954
|
// fire event
|
|
876
|
-
this.NodeManager.LavalinkManager.emit("trackEnd", player,
|
|
955
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
877
956
|
// play track if autoSkip is true
|
|
878
957
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
879
958
|
}
|
|
880
959
|
// remove tracks from the queue
|
|
881
960
|
if (player.repeatMode !== "track" || player.get("internal_skipped"))
|
|
882
961
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
883
|
-
else if (
|
|
884
|
-
player.queue.previous.unshift(
|
|
962
|
+
else if (trackToUse && !trackToUse?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
963
|
+
player.queue.previous.unshift(trackToUse);
|
|
885
964
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
886
965
|
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
887
966
|
await player.queue.utils.save();
|
|
@@ -889,60 +968,65 @@ class LavalinkNode {
|
|
|
889
968
|
player.set("internal_skipped", false);
|
|
890
969
|
// if no track available, end queue
|
|
891
970
|
if (!player.queue.current)
|
|
892
|
-
return this.queueEnd(player,
|
|
971
|
+
return this.queueEnd(player, trackToUse, payload);
|
|
893
972
|
// fire event
|
|
894
|
-
this.NodeManager.LavalinkManager.emit("trackEnd", player,
|
|
973
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
895
974
|
// play track if autoSkip is true
|
|
896
975
|
return this.NodeManager.LavalinkManager.options.autoSkip && player.play({ noReplace: true });
|
|
897
976
|
}
|
|
898
977
|
/** @private util function for handling trackStuck event */
|
|
899
978
|
async trackStuck(player, track, payload) {
|
|
900
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track, payload);
|
|
979
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track || await this.getTrackOfPayload(payload), payload);
|
|
901
980
|
// If there are no songs in the queue
|
|
902
981
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
903
|
-
return this.queueEnd(player, track, payload);
|
|
982
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
904
983
|
// remove the current track, and enqueue the next one
|
|
905
984
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
906
985
|
// if no track available, end queue
|
|
907
986
|
if (!player.queue.current)
|
|
908
|
-
return this.queueEnd(player, track, payload);
|
|
987
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
909
988
|
// play track if autoSkip is true
|
|
910
989
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
911
990
|
}
|
|
912
991
|
/** @private util function for handling trackError event */
|
|
913
992
|
async trackError(player, track, payload) {
|
|
914
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track, payload);
|
|
993
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track || await this.getTrackOfPayload(payload), payload);
|
|
915
994
|
return; // get's handled by trackEnd
|
|
916
995
|
// If there are no songs in the queue
|
|
917
996
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
918
|
-
return this.queueEnd(player, track, payload);
|
|
997
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
919
998
|
// remove the current track, and enqueue the next one
|
|
920
999
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
921
1000
|
// if no track available, end queue
|
|
922
1001
|
if (!player.queue.current)
|
|
923
|
-
return this.queueEnd(player, track, payload);
|
|
1002
|
+
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
924
1003
|
// play track if autoSkip is true
|
|
925
1004
|
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
926
1005
|
}
|
|
927
1006
|
/** @private util function for handling socketClosed event */
|
|
928
1007
|
socketClosed(player, payload) {
|
|
929
|
-
|
|
1008
|
+
this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
1009
|
+
// i don't think this is needed.
|
|
1010
|
+
// this.socket = null;
|
|
1011
|
+
// // causing a socket reconnect
|
|
1012
|
+
// this.connect();
|
|
1013
|
+
return;
|
|
930
1014
|
}
|
|
931
1015
|
/** @private util function for handling SponsorBlock Segmentloaded event */
|
|
932
|
-
SponsorBlockSegmentLoaded(player, track, payload) {
|
|
933
|
-
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track, payload);
|
|
1016
|
+
async SponsorBlockSegmentLoaded(player, track, payload) {
|
|
1017
|
+
return this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track || await this.getTrackOfPayload(payload), payload);
|
|
934
1018
|
}
|
|
935
1019
|
/** @private util function for handling SponsorBlock SegmentSkipped event */
|
|
936
|
-
SponsorBlockSegmentSkipped(player, track, payload) {
|
|
937
|
-
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track, payload);
|
|
1020
|
+
async SponsorBlockSegmentSkipped(player, track, payload) {
|
|
1021
|
+
return this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track || await this.getTrackOfPayload(payload), payload);
|
|
938
1022
|
}
|
|
939
1023
|
/** @private util function for handling SponsorBlock Chaptersloaded event */
|
|
940
|
-
SponsorBlockChaptersLoaded(player, track, payload) {
|
|
941
|
-
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track, payload);
|
|
1024
|
+
async SponsorBlockChaptersLoaded(player, track, payload) {
|
|
1025
|
+
return this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track || await this.getTrackOfPayload(payload), payload);
|
|
942
1026
|
}
|
|
943
1027
|
/** @private util function for handling SponsorBlock Chaptersstarted event */
|
|
944
|
-
SponsorBlockChapterStarted(player, track, payload) {
|
|
945
|
-
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track, payload);
|
|
1028
|
+
async SponsorBlockChapterStarted(player, track, payload) {
|
|
1029
|
+
return this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track || await this.getTrackOfPayload(payload), payload);
|
|
946
1030
|
}
|
|
947
1031
|
/**
|
|
948
1032
|
* Get the current sponsorblocks for the sponsorblock plugin
|
|
@@ -981,8 +1065,8 @@ class LavalinkNode {
|
|
|
981
1065
|
if (!segments.length)
|
|
982
1066
|
throw new RangeError("No Segments provided. Did you ment to use 'deleteSponsorBlock'?");
|
|
983
1067
|
// a not valid segment
|
|
984
|
-
if (segments.some(v => !
|
|
985
|
-
throw new SyntaxError(`You provided a sponsorblock which isn't valid, valid ones are: ${
|
|
1068
|
+
if (segments.some(v => !Constants_1.validSponsorBlocks.includes(v.toLowerCase())))
|
|
1069
|
+
throw new SyntaxError(`You provided a sponsorblock which isn't valid, valid ones are: ${Constants_1.validSponsorBlocks.map(v => `'${v}'`).join(", ")}`);
|
|
986
1070
|
// do the request
|
|
987
1071
|
await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
|
|
988
1072
|
r.method = "PUT";
|
|
@@ -1029,20 +1113,25 @@ class LavalinkNode {
|
|
|
1029
1113
|
}
|
|
1030
1114
|
}
|
|
1031
1115
|
player.set("internal_autoplayStopPlaying", undefined);
|
|
1032
|
-
|
|
1116
|
+
if (track && !track?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
1117
|
+
player.queue.previous.unshift(track);
|
|
1118
|
+
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
1119
|
+
player.queue.previous.splice(player.queue.options.maxPreviousTracks, player.queue.previous.length);
|
|
1120
|
+
await player.queue.utils.save();
|
|
1121
|
+
}
|
|
1033
1122
|
if (payload?.reason !== "stopped") {
|
|
1034
1123
|
await player.queue.utils.save();
|
|
1035
1124
|
}
|
|
1036
1125
|
if (typeof this.NodeManager.LavalinkManager.options.playerOptions?.onEmptyQueue?.destroyAfterMs === "number" && !isNaN(this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs) && this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs >= 0) {
|
|
1037
1126
|
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0)
|
|
1038
|
-
return player.destroy(
|
|
1127
|
+
return player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1039
1128
|
else {
|
|
1040
1129
|
if (player.get("internal_queueempty")) {
|
|
1041
1130
|
clearTimeout(player.get("internal_queueempty"));
|
|
1042
1131
|
player.set("internal_queueempty", undefined);
|
|
1043
1132
|
}
|
|
1044
1133
|
player.set("internal_queueempty", setTimeout(() => {
|
|
1045
|
-
player.destroy(
|
|
1134
|
+
player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1046
1135
|
}, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs));
|
|
1047
1136
|
}
|
|
1048
1137
|
}
|
|
@@ -1,68 +1,56 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from "stream";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
export interface NodeManagerEvents {
|
|
3
|
+
import { LavalinkNode } from "./Node";
|
|
4
|
+
import { MiniMap } from "./Utils";
|
|
5
|
+
import type { LavalinkNodeIdentifier, LavalinkNodeOptions, NodeManagerEvents } from "./Types/Node";
|
|
6
|
+
import type { LavalinkManager } from "./LavalinkManager";
|
|
7
|
+
export declare class NodeManager extends EventEmitter {
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @event
|
|
9
|
+
* Emit an event
|
|
10
|
+
* @param event The event to emit
|
|
11
|
+
* @param args The arguments to pass to the event
|
|
12
|
+
* @returns
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
emit<Event extends keyof NodeManagerEvents>(event: Event, ...args: Parameters<NodeManagerEvents[Event]>): boolean;
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @event
|
|
16
|
+
* Add an event listener
|
|
17
|
+
* @param event The event to listen to
|
|
18
|
+
* @param listener The listener to add
|
|
19
|
+
* @returns
|
|
17
20
|
*/
|
|
18
|
-
|
|
21
|
+
on<Event extends keyof NodeManagerEvents>(event: Event, listener: NodeManagerEvents[Event]): this;
|
|
19
22
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @event
|
|
23
|
+
* Add an event listener that only fires once
|
|
24
|
+
* @param event The event to listen to
|
|
25
|
+
* @param listener The listener to add
|
|
26
|
+
* @returns
|
|
22
27
|
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Emitted when a Node is reconnecting.
|
|
26
|
-
* @event Manager.nodeManager#reconnecting
|
|
27
|
-
*/
|
|
28
|
-
"reconnecting": (node: LavalinkNode) => void;
|
|
29
|
-
/**
|
|
30
|
-
* Emitted when a Node is disconnects.
|
|
31
|
-
* @event Manager.nodeManager#disconnect
|
|
32
|
-
*/
|
|
33
|
-
"disconnect": (node: LavalinkNode, reason: {
|
|
34
|
-
code?: number;
|
|
35
|
-
reason?: string;
|
|
36
|
-
}) => void;
|
|
28
|
+
once<Event extends keyof NodeManagerEvents>(event: Event, listener: NodeManagerEvents[Event]): this;
|
|
37
29
|
/**
|
|
38
|
-
*
|
|
39
|
-
* @event
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
* Remove an event listener
|
|
31
|
+
* @param event The event to remove the listener from
|
|
32
|
+
* @param listener The listener to remove
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
off<Event extends keyof NodeManagerEvents>(event: Event, listener: NodeManagerEvents[Event]): this;
|
|
42
36
|
/**
|
|
43
|
-
*
|
|
44
|
-
* @event
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
* Remove an event listener
|
|
38
|
+
* @param event The event to remove the listener from
|
|
39
|
+
* @param listener The listener to remove
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
removeListener<Event extends keyof NodeManagerEvents>(event: Event, listener: NodeManagerEvents[Event]): this;
|
|
47
43
|
/**
|
|
48
|
-
*
|
|
49
|
-
* 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
|
|
50
|
-
* @event Manager.nodeManager#nodeResumed
|
|
44
|
+
* The LavalinkManager that created this NodeManager
|
|
51
45
|
*/
|
|
52
|
-
"resumed": (node: LavalinkNode, paylaod: {
|
|
53
|
-
resumed: true;
|
|
54
|
-
sessionId: string;
|
|
55
|
-
op: "ready";
|
|
56
|
-
}, players: LavalinkPlayer[]) => void;
|
|
57
|
-
}
|
|
58
|
-
export declare interface NodeManager {
|
|
59
|
-
on<U extends keyof NodeManagerEvents>(event: U, listener: NodeManagerEvents[U]): this;
|
|
60
|
-
emit<U extends keyof NodeManagerEvents>(event: U, ...args: Parameters<NodeManagerEvents[U]>): boolean;
|
|
61
|
-
/** @private */
|
|
62
46
|
LavalinkManager: LavalinkManager;
|
|
63
|
-
|
|
64
|
-
|
|
47
|
+
/**
|
|
48
|
+
* A map of all nodes in the nodeManager
|
|
49
|
+
*/
|
|
65
50
|
nodes: MiniMap<string, LavalinkNode>;
|
|
51
|
+
/**
|
|
52
|
+
* @param LavalinkManager The LavalinkManager that created this NodeManager
|
|
53
|
+
*/
|
|
66
54
|
constructor(LavalinkManager: LavalinkManager);
|
|
67
55
|
/**
|
|
68
56
|
* Disconnects all Nodes from lavalink ws sockets
|
|
@@ -80,8 +68,22 @@ export declare class NodeManager extends EventEmitter {
|
|
|
80
68
|
* @returns amount of nodes
|
|
81
69
|
*/
|
|
82
70
|
reconnectAll(): Promise<number>;
|
|
71
|
+
/**
|
|
72
|
+
* Create a node and add it to the nodeManager
|
|
73
|
+
* @param options The options for the node
|
|
74
|
+
* @returns The node that was created
|
|
75
|
+
*/
|
|
83
76
|
createNode(options: LavalinkNodeOptions): LavalinkNode;
|
|
77
|
+
/**
|
|
78
|
+
* Get the nodes sorted for the least usage, by a sorttype
|
|
79
|
+
* @param sortType The type of sorting to use
|
|
80
|
+
* @returns
|
|
81
|
+
*/
|
|
84
82
|
leastUsedNodes(sortType?: "memory" | "cpuLavalink" | "cpuSystem" | "calls" | "playingPlayers" | "players"): LavalinkNode[];
|
|
83
|
+
/**
|
|
84
|
+
* Delete a node from the nodeManager and destroy it
|
|
85
|
+
* @param node The node to delete
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
85
88
|
deleteNode(node: LavalinkNodeIdentifier | LavalinkNode): void;
|
|
86
89
|
}
|
|
87
|
-
export {};
|