lavalink-client 2.3.6 → 2.4.1
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 +56 -7
- package/dist/cjs/structures/Constants.d.ts +4 -0
- package/dist/cjs/structures/Constants.js +7 -2
- package/dist/cjs/structures/Filters.d.ts +24 -0
- package/dist/cjs/structures/Filters.js +34 -10
- package/dist/cjs/structures/LavalinkManager.d.ts +4 -5
- package/dist/cjs/structures/LavalinkManager.js +75 -30
- package/dist/cjs/structures/Node.d.ts +30 -16
- package/dist/cjs/structures/Node.js +165 -84
- package/dist/cjs/structures/NodeManager.d.ts +2 -2
- package/dist/cjs/structures/NodeManager.js +19 -19
- package/dist/cjs/structures/Player.d.ts +10 -3
- package/dist/cjs/structures/Player.js +12 -0
- package/dist/cjs/structures/Queue.d.ts +9 -10
- package/dist/cjs/structures/Queue.js +3 -3
- package/dist/cjs/structures/Types/Manager.d.ts +40 -0
- package/dist/cjs/structures/Types/Node.d.ts +0 -1
- package/dist/cjs/structures/Types/Player.d.ts +5 -1
- package/dist/cjs/structures/Types/Queue.d.ts +6 -6
- package/dist/cjs/structures/Types/Track.d.ts +3 -1
- package/dist/cjs/structures/Types/Utils.d.ts +17 -2
- package/dist/cjs/structures/Utils.js +3 -10
- package/dist/esm/structures/Constants.d.ts +4 -0
- package/dist/esm/structures/Constants.js +6 -1
- package/dist/esm/structures/Filters.d.ts +24 -0
- package/dist/esm/structures/Filters.js +34 -10
- package/dist/esm/structures/LavalinkManager.d.ts +4 -5
- package/dist/esm/structures/LavalinkManager.js +75 -30
- package/dist/esm/structures/Node.d.ts +30 -16
- package/dist/esm/structures/Node.js +165 -84
- package/dist/esm/structures/NodeManager.d.ts +2 -2
- package/dist/esm/structures/NodeManager.js +20 -20
- package/dist/esm/structures/Player.d.ts +10 -3
- package/dist/esm/structures/Player.js +12 -0
- package/dist/esm/structures/Queue.d.ts +9 -10
- package/dist/esm/structures/Queue.js +3 -3
- package/dist/esm/structures/Types/Manager.d.ts +40 -0
- package/dist/esm/structures/Types/Node.d.ts +0 -1
- package/dist/esm/structures/Types/Player.d.ts +5 -1
- package/dist/esm/structures/Types/Queue.d.ts +6 -6
- package/dist/esm/structures/Types/Track.d.ts +3 -1
- package/dist/esm/structures/Types/Utils.d.ts +17 -2
- package/dist/esm/structures/Utils.js +0 -7
- package/dist/types/structures/Constants.d.ts +4 -0
- package/dist/types/structures/Filters.d.ts +24 -0
- package/dist/types/structures/LavalinkManager.d.ts +4 -5
- package/dist/types/structures/Node.d.ts +30 -16
- package/dist/types/structures/NodeManager.d.ts +2 -2
- package/dist/types/structures/Player.d.ts +10 -3
- package/dist/types/structures/Queue.d.ts +9 -10
- package/dist/types/structures/Types/Manager.d.ts +40 -0
- package/dist/types/structures/Types/Node.d.ts +0 -1
- package/dist/types/structures/Types/Player.d.ts +5 -1
- package/dist/types/structures/Types/Queue.d.ts +6 -6
- package/dist/types/structures/Types/Track.d.ts +3 -1
- package/dist/types/structures/Types/Utils.d.ts +17 -2
- package/package.json +23 -18
|
@@ -13,6 +13,7 @@ export class LavalinkNode {
|
|
|
13
13
|
}
|
|
14
14
|
heartBeatInterval;
|
|
15
15
|
pingTimeout;
|
|
16
|
+
isAlive = false;
|
|
16
17
|
/** The provided Options of the Node */
|
|
17
18
|
options;
|
|
18
19
|
/** The amount of rest calls the node has made. */
|
|
@@ -74,7 +75,7 @@ export class LavalinkNode {
|
|
|
74
75
|
retryAmount: 5,
|
|
75
76
|
retryDelay: 10e3,
|
|
76
77
|
requestSignalTimeoutMS: 10000,
|
|
77
|
-
heartBeatInterval:
|
|
78
|
+
heartBeatInterval: 30_000,
|
|
78
79
|
closeOnError: true,
|
|
79
80
|
enablePingOnStatsCheck: true,
|
|
80
81
|
...options
|
|
@@ -137,32 +138,22 @@ export class LavalinkNode {
|
|
|
137
138
|
const url = new URL(`${this.restAddress}${options.path}`);
|
|
138
139
|
url.searchParams.append("trace", "true");
|
|
139
140
|
const urlToUse = this.getRequestingUrl(url, options?.extraQueryUrlParams);
|
|
141
|
+
const originalOptions = structuredClone(options);
|
|
140
142
|
delete options.path;
|
|
141
143
|
delete options.extraQueryUrlParams;
|
|
142
|
-
const
|
|
144
|
+
const response = await fetch(urlToUse, options);
|
|
143
145
|
this.calls++;
|
|
144
|
-
return {
|
|
146
|
+
return { response, options: originalOptions };
|
|
145
147
|
}
|
|
146
|
-
|
|
147
|
-
* Makes an API call to the Node. Should only be used for manual parsing like for not supported plugins
|
|
148
|
-
* @param endpoint The endpoint that we will make the call to
|
|
149
|
-
* @param modify Used to modify the request before being sent
|
|
150
|
-
* @returns The returned data
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```ts
|
|
154
|
-
* player.node.request(`/loadtracks?identifier=Never gonna give you up`, (options) => options.method = "GET", false);
|
|
155
|
-
* ```
|
|
156
|
-
*/
|
|
157
|
-
async request(endpoint, modify, parseAsText = false) {
|
|
148
|
+
async request(endpoint, modify, parseAsText) {
|
|
158
149
|
if (!this.connected)
|
|
159
150
|
throw new Error("The node is not connected to the Lavalink Server!, Please call node.connect() first!");
|
|
160
|
-
const {
|
|
151
|
+
const { response, options } = await this.rawRequest(endpoint, modify);
|
|
161
152
|
if (["DELETE", "PUT"].includes(options.method))
|
|
162
153
|
return;
|
|
163
|
-
if (
|
|
164
|
-
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${JSON.stringify(
|
|
165
|
-
return parseAsText ? await
|
|
154
|
+
if (response.status === 404)
|
|
155
|
+
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${JSON.stringify(response.headers)}`);
|
|
156
|
+
return parseAsText ? await response.text() : await response.json();
|
|
166
157
|
}
|
|
167
158
|
/**
|
|
168
159
|
* Search something raw on the node, please note only add tracks to players of that node
|
|
@@ -237,7 +228,7 @@ export class LavalinkNode {
|
|
|
237
228
|
* @param query LavaSearchQuery Object
|
|
238
229
|
* @param requestUser Request User for creating the player(s)
|
|
239
230
|
* @param throwOnEmpty Wether to throw on an empty result or not
|
|
240
|
-
* @returns LavaSearchresult
|
|
231
|
+
* @returns LavaSearchresult (SearchResult if link is provided)
|
|
241
232
|
*
|
|
242
233
|
* @example
|
|
243
234
|
* ```ts
|
|
@@ -257,8 +248,8 @@ export class LavalinkNode {
|
|
|
257
248
|
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.id}`);
|
|
258
249
|
if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
|
|
259
250
|
throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
|
|
260
|
-
const {
|
|
261
|
-
const res = (
|
|
251
|
+
const { response } = await this.rawRequest(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
252
|
+
const res = (response.status === 204 ? {} : await response.json());
|
|
262
253
|
if (throwOnEmpty === true && !Object.entries(res).flat().filter(Boolean).length) {
|
|
263
254
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
264
255
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.LavaSearchNothingFound, {
|
|
@@ -295,7 +286,6 @@ export class LavalinkNode {
|
|
|
295
286
|
this.syncPlayerData(data);
|
|
296
287
|
const res = await this.request(`/sessions/${this.sessionId}/players/${data.guildId}`, r => {
|
|
297
288
|
r.method = "PATCH";
|
|
298
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
299
289
|
r.headers["Content-Type"] = "application/json";
|
|
300
290
|
r.body = JSON.stringify(data.playerOptions);
|
|
301
291
|
if (data.noReplace) {
|
|
@@ -311,7 +301,8 @@ export class LavalinkNode {
|
|
|
311
301
|
functionLayer: "LavalinkNode > node > updatePlayer()",
|
|
312
302
|
});
|
|
313
303
|
}
|
|
314
|
-
|
|
304
|
+
this.syncPlayerData({}, res);
|
|
305
|
+
return res;
|
|
315
306
|
}
|
|
316
307
|
/**
|
|
317
308
|
* Destroys the Player on the Lavalink Server
|
|
@@ -380,6 +371,7 @@ export class LavalinkNode {
|
|
|
380
371
|
if (this.pingTimeout)
|
|
381
372
|
clearTimeout(this.pingTimeout);
|
|
382
373
|
this.pingTimeout = setTimeout(() => {
|
|
374
|
+
this.pingTimeout = null;
|
|
383
375
|
if (!this.socket) {
|
|
384
376
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
385
377
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.NoSocketOnDestroy, {
|
|
@@ -399,7 +391,7 @@ export class LavalinkNode {
|
|
|
399
391
|
}
|
|
400
392
|
this.isAlive = false;
|
|
401
393
|
this.socket.terminate();
|
|
402
|
-
},
|
|
394
|
+
}, 65_000); // the stats endpoint get's sent every 60s. se wee add a 5s buffer to make sure we don't miss any stats message
|
|
403
395
|
}
|
|
404
396
|
/**
|
|
405
397
|
* Get the id of the node
|
|
@@ -415,7 +407,7 @@ export class LavalinkNode {
|
|
|
415
407
|
}
|
|
416
408
|
/**
|
|
417
409
|
* Destroys the Node-Connection (Websocket) and all player's of the node
|
|
418
|
-
* @param destroyReason
|
|
410
|
+
* @param destroyReason Destroy Reason to use when destroying the players
|
|
419
411
|
* @param deleteNode wether to delete the nodte from the nodes list too, if false it will emit a disconnect. @default true
|
|
420
412
|
* @returns void
|
|
421
413
|
*
|
|
@@ -446,6 +438,28 @@ export class LavalinkNode {
|
|
|
446
438
|
}
|
|
447
439
|
return;
|
|
448
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Disconnects the Node-Connection (Websocket)
|
|
443
|
+
* @param disconnectReason Disconnect Reason to use when disconnecting Node
|
|
444
|
+
* @returns void
|
|
445
|
+
*
|
|
446
|
+
* Also the node will not get re-connected again.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* player.node.destroy("custom Player Destroy Reason", true);
|
|
451
|
+
* ```
|
|
452
|
+
*/
|
|
453
|
+
disconnect(disconnectReason) {
|
|
454
|
+
if (!this.connected)
|
|
455
|
+
return;
|
|
456
|
+
this.socket.close(1000, "Node-Disconnect");
|
|
457
|
+
this.socket.removeAllListeners();
|
|
458
|
+
this.socket = null;
|
|
459
|
+
this.reconnectAttempts = 1;
|
|
460
|
+
clearTimeout(this.reconnectTimeout);
|
|
461
|
+
this.NodeManager.emit("disconnect", this, { code: 1000, reason: disconnectReason });
|
|
462
|
+
}
|
|
449
463
|
/**
|
|
450
464
|
* Returns if connected to the Node.
|
|
451
465
|
*
|
|
@@ -456,11 +470,8 @@ export class LavalinkNode {
|
|
|
456
470
|
* ```
|
|
457
471
|
*/
|
|
458
472
|
get connected() {
|
|
459
|
-
|
|
460
|
-
return false;
|
|
461
|
-
return this.socket.readyState === WebSocket.OPEN;
|
|
473
|
+
return this.socket && this.socket.readyState === WebSocket.OPEN;
|
|
462
474
|
}
|
|
463
|
-
isAlive = false;
|
|
464
475
|
/**
|
|
465
476
|
* Returns the current ConnectionStatus
|
|
466
477
|
*
|
|
@@ -581,7 +592,6 @@ export class LavalinkNode {
|
|
|
581
592
|
return await this.request(`/decodetracks`, r => {
|
|
582
593
|
r.method = "POST";
|
|
583
594
|
r.body = JSON.stringify(encodeds);
|
|
584
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
585
595
|
r.headers["Content-Type"] = "application/json";
|
|
586
596
|
}).then((r) => r.map(track => this.NodeManager.LavalinkManager.utils.buildTrack(track, requester)));
|
|
587
597
|
}
|
|
@@ -657,7 +667,7 @@ export class LavalinkNode {
|
|
|
657
667
|
throw new RangeError(`there is no lyrics source (via lavasrc-plugin / java-lyrics-plugin) available in the lavalink node (required for lyrics): ${this.id}`);
|
|
658
668
|
return await this.request(`/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe`, (options) => {
|
|
659
669
|
options.method = "POST";
|
|
660
|
-
})
|
|
670
|
+
});
|
|
661
671
|
},
|
|
662
672
|
/**
|
|
663
673
|
* unsubscribe from lyrics updates for a guild
|
|
@@ -681,7 +691,7 @@ export class LavalinkNode {
|
|
|
681
691
|
throw new RangeError(`there is no lyrics source (via lavasrc-plugin / java-lyrics-plugin) available in the lavalink node (required for lyrics): ${this.id}`);
|
|
682
692
|
return await this.request(`/sessions/${this.sessionId}/players/${guildId}/lyrics/unsubscribe`, (options) => {
|
|
683
693
|
options.method = "DELETE";
|
|
684
|
-
})
|
|
694
|
+
});
|
|
685
695
|
},
|
|
686
696
|
};
|
|
687
697
|
/**
|
|
@@ -756,9 +766,8 @@ export class LavalinkNode {
|
|
|
756
766
|
unmarkFailedAddress: async (address) => {
|
|
757
767
|
if (!this.sessionId)
|
|
758
768
|
throw new Error("the Lavalink-Node is either not ready, or not up to date!");
|
|
759
|
-
await this.request(`/routeplanner/free/address`, r => {
|
|
769
|
+
return await this.request(`/routeplanner/free/address`, r => {
|
|
760
770
|
r.method = "POST";
|
|
761
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
762
771
|
r.headers["Content-Type"] = "application/json";
|
|
763
772
|
r.body = JSON.stringify({ address });
|
|
764
773
|
});
|
|
@@ -777,7 +786,6 @@ export class LavalinkNode {
|
|
|
777
786
|
throw new Error("the Lavalink-Node is either not ready, or not up to date!");
|
|
778
787
|
return await this.request(`/routeplanner/free/all`, r => {
|
|
779
788
|
r.method = "POST";
|
|
780
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
781
789
|
r.headers["Content-Type"] = "application/json";
|
|
782
790
|
});
|
|
783
791
|
}
|
|
@@ -790,6 +798,7 @@ export class LavalinkNode {
|
|
|
790
798
|
throw new SyntaxError("LavalinkNode requires 'host'");
|
|
791
799
|
if (!this.options.port)
|
|
792
800
|
throw new SyntaxError("LavalinkNode requires 'port'");
|
|
801
|
+
// TODO add more validations
|
|
793
802
|
}
|
|
794
803
|
/**
|
|
795
804
|
* Sync the data of the player you make an action to lavalink to
|
|
@@ -854,11 +863,13 @@ export class LavalinkNode {
|
|
|
854
863
|
const player = this.NodeManager.LavalinkManager.getPlayer(data.guildId);
|
|
855
864
|
if (!player)
|
|
856
865
|
return;
|
|
857
|
-
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false)
|
|
858
|
-
|
|
866
|
+
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false) {
|
|
867
|
+
player.destroy(DestroyReasons.LavalinkNoVoice);
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
859
870
|
player.ping.ws = res?.voice?.ping || player?.ping.ws;
|
|
860
871
|
}
|
|
861
|
-
return
|
|
872
|
+
return;
|
|
862
873
|
}
|
|
863
874
|
/**
|
|
864
875
|
* Get the rest Adress for making requests
|
|
@@ -892,6 +903,7 @@ export class LavalinkNode {
|
|
|
892
903
|
return;
|
|
893
904
|
}
|
|
894
905
|
this.reconnectTimeout = setTimeout(() => {
|
|
906
|
+
this.reconnectTimeout = null;
|
|
895
907
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
896
908
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
897
909
|
this.NodeManager.emit("error", this, error);
|
|
@@ -927,7 +939,7 @@ export class LavalinkNode {
|
|
|
927
939
|
this.isAlive = false;
|
|
928
940
|
this.heartBeatPingTimestamp = performance.now();
|
|
929
941
|
this.socket.ping();
|
|
930
|
-
}, this.options.heartBeatInterval ||
|
|
942
|
+
}, this.options.heartBeatInterval || 30_000);
|
|
931
943
|
}
|
|
932
944
|
if (this.reconnectTimeout)
|
|
933
945
|
clearTimeout(this.reconnectTimeout);
|
|
@@ -948,6 +960,8 @@ export class LavalinkNode {
|
|
|
948
960
|
clearInterval(this.heartBeatInterval);
|
|
949
961
|
if (code === 1006 && !reason)
|
|
950
962
|
reason = "Socket got terminated due to no ping connection";
|
|
963
|
+
if (code === 1000 && reason === "Node-Disconnect")
|
|
964
|
+
return; // manually disconnected and already emitted the event.
|
|
951
965
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
952
966
|
if (code !== 1000 || reason !== "Node-Destroy")
|
|
953
967
|
this.reconnect();
|
|
@@ -972,7 +986,14 @@ export class LavalinkNode {
|
|
|
972
986
|
d = Buffer.concat(d);
|
|
973
987
|
else if (d instanceof ArrayBuffer)
|
|
974
988
|
d = Buffer.from(d);
|
|
975
|
-
|
|
989
|
+
let payload;
|
|
990
|
+
try {
|
|
991
|
+
payload = JSON.parse(d.toString());
|
|
992
|
+
}
|
|
993
|
+
catch (e) {
|
|
994
|
+
this.NodeManager.emit("error", this, e);
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
976
997
|
if (!payload.op)
|
|
977
998
|
return;
|
|
978
999
|
this.NodeManager.emit("raw", this, payload);
|
|
@@ -1003,7 +1024,7 @@ export class LavalinkNode {
|
|
|
1003
1024
|
player.ping.ws = payload.state.ping >= 0 ? payload.state.ping : player.ping.ws <= 0 && player.connected ? null : player.ping.ws || 0;
|
|
1004
1025
|
if (!player.createdTimeStamp && payload.state.time)
|
|
1005
1026
|
player.createdTimeStamp = payload.state.time;
|
|
1006
|
-
if (player.filterManager.filterUpdatedState === true && ((player.queue.current?.info?.duration || 0) <= (player.LavalinkManager.options.advancedOptions.maxFilterFixDuration ||
|
|
1027
|
+
if (player.filterManager.filterUpdatedState === true && ((player.queue.current?.info?.duration || 0) <= (player.LavalinkManager.options.advancedOptions.maxFilterFixDuration || 600_000) || isAbsolute(player.queue.current?.info?.uri))) {
|
|
1007
1028
|
player.filterManager.filterUpdatedState = false;
|
|
1008
1029
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1009
1030
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.PlayerUpdateFilterFixApply, {
|
|
@@ -1095,7 +1116,7 @@ export class LavalinkNode {
|
|
|
1095
1116
|
}
|
|
1096
1117
|
return;
|
|
1097
1118
|
}
|
|
1098
|
-
|
|
1119
|
+
getTrackOfPayload(payload) {
|
|
1099
1120
|
return "track" in payload
|
|
1100
1121
|
? this.NodeManager.LavalinkManager.utils.buildTrack(payload.track, undefined)
|
|
1101
1122
|
: null;
|
|
@@ -1116,7 +1137,7 @@ export class LavalinkNode {
|
|
|
1116
1137
|
return;
|
|
1117
1138
|
}
|
|
1118
1139
|
if (!player.queue.current) {
|
|
1119
|
-
player.queue.current =
|
|
1140
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1120
1141
|
if (player.queue.current) {
|
|
1121
1142
|
await player.queue.utils.save();
|
|
1122
1143
|
}
|
|
@@ -1130,11 +1151,12 @@ export class LavalinkNode {
|
|
|
1130
1151
|
}
|
|
1131
1152
|
}
|
|
1132
1153
|
}
|
|
1133
|
-
|
|
1154
|
+
this.NodeManager.LavalinkManager.emit("trackStart", player, player.queue.current, payload);
|
|
1155
|
+
return;
|
|
1134
1156
|
}
|
|
1135
1157
|
/** @private util function for handling trackEnd event */
|
|
1136
1158
|
async trackEnd(player, track, payload) {
|
|
1137
|
-
const trackToUse = track ||
|
|
1159
|
+
const trackToUse = track || this.getTrackOfPayload(payload);
|
|
1138
1160
|
// If a track was forcibly played
|
|
1139
1161
|
if (payload.reason === "replaced") {
|
|
1140
1162
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
@@ -1144,7 +1166,8 @@ export class LavalinkNode {
|
|
|
1144
1166
|
functionLayer: "LavalinkNode > trackEnd()",
|
|
1145
1167
|
});
|
|
1146
1168
|
}
|
|
1147
|
-
|
|
1169
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1170
|
+
return;
|
|
1148
1171
|
}
|
|
1149
1172
|
// If there are no songs in the queue
|
|
1150
1173
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
@@ -1158,7 +1181,10 @@ export class LavalinkNode {
|
|
|
1158
1181
|
// fire event
|
|
1159
1182
|
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1160
1183
|
// play track if autoSkip is true
|
|
1161
|
-
|
|
1184
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1185
|
+
player.play({ noReplace: true });
|
|
1186
|
+
}
|
|
1187
|
+
return;
|
|
1162
1188
|
}
|
|
1163
1189
|
// remove tracks from the queue
|
|
1164
1190
|
if (player.repeatMode !== "track" || player.get("internal_skipped"))
|
|
@@ -1176,7 +1202,10 @@ export class LavalinkNode {
|
|
|
1176
1202
|
// fire event
|
|
1177
1203
|
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1178
1204
|
// play track if autoSkip is true
|
|
1179
|
-
|
|
1205
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1206
|
+
player.play({ noReplace: true });
|
|
1207
|
+
}
|
|
1208
|
+
return;
|
|
1180
1209
|
}
|
|
1181
1210
|
/** @private util function for handling trackStuck event */
|
|
1182
1211
|
async trackStuck(player, track, payload) {
|
|
@@ -1192,21 +1221,25 @@ export class LavalinkNode {
|
|
|
1192
1221
|
functionLayer: "LavalinkNode > trackStuck()",
|
|
1193
1222
|
});
|
|
1194
1223
|
}
|
|
1195
|
-
|
|
1224
|
+
player.destroy(DestroyReasons.TrackStuckMaxTracksErroredPerTime);
|
|
1225
|
+
return;
|
|
1196
1226
|
}
|
|
1197
1227
|
}
|
|
1198
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track ||
|
|
1228
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track || this.getTrackOfPayload(payload), payload);
|
|
1199
1229
|
// If there are no songs in the queue
|
|
1200
1230
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
1201
|
-
return this.queueEnd(player, track ||
|
|
1231
|
+
return this.queueEnd(player, track || this.getTrackOfPayload(payload), payload);
|
|
1202
1232
|
// remove the current track, and enqueue the next one
|
|
1203
1233
|
await queueTrackEnd(player);
|
|
1204
1234
|
// if no track available, end queue
|
|
1205
1235
|
if (!player.queue.current) {
|
|
1206
|
-
return this.queueEnd(player, track ||
|
|
1236
|
+
return this.queueEnd(player, track || this.getTrackOfPayload(payload), payload);
|
|
1207
1237
|
}
|
|
1208
1238
|
// play track if autoSkip is true
|
|
1209
|
-
|
|
1239
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1240
|
+
player.play({ noReplace: true });
|
|
1241
|
+
}
|
|
1242
|
+
return;
|
|
1210
1243
|
}
|
|
1211
1244
|
/** @private util function for handling trackError event */
|
|
1212
1245
|
async trackError(player, track, payload) {
|
|
@@ -1222,46 +1255,37 @@ export class LavalinkNode {
|
|
|
1222
1255
|
functionLayer: "LavalinkNode > trackError()",
|
|
1223
1256
|
});
|
|
1224
1257
|
}
|
|
1225
|
-
|
|
1258
|
+
player.destroy(DestroyReasons.TrackErrorMaxTracksErroredPerTime);
|
|
1259
|
+
return;
|
|
1226
1260
|
}
|
|
1227
1261
|
}
|
|
1228
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track ||
|
|
1229
|
-
return;
|
|
1230
|
-
// If there are no songs in the queue
|
|
1231
|
-
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
1232
|
-
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
1233
|
-
// remove the current track, and enqueue the next one
|
|
1234
|
-
await queueTrackEnd(player);
|
|
1235
|
-
// if no track available, end queue
|
|
1236
|
-
if (!player.queue.current)
|
|
1237
|
-
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
1238
|
-
// play track if autoSkip is true
|
|
1239
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
1262
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track || this.getTrackOfPayload(payload), payload);
|
|
1263
|
+
return;
|
|
1240
1264
|
}
|
|
1241
1265
|
/** @private util function for handling socketClosed event */
|
|
1242
1266
|
socketClosed(player, payload) {
|
|
1243
1267
|
this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
1244
|
-
// i don't think this is needed.
|
|
1245
|
-
// this.socket = null;
|
|
1246
|
-
// // causing a socket reconnect
|
|
1247
|
-
// this.connect();
|
|
1248
1268
|
return;
|
|
1249
1269
|
}
|
|
1250
1270
|
/** @private util function for handling SponsorBlock Segmentloaded event */
|
|
1251
1271
|
async SponsorBlockSegmentLoaded(player, track, payload) {
|
|
1252
|
-
|
|
1272
|
+
this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track || this.getTrackOfPayload(payload), payload);
|
|
1273
|
+
return;
|
|
1253
1274
|
}
|
|
1254
1275
|
/** @private util function for handling SponsorBlock SegmentSkipped event */
|
|
1255
1276
|
async SponsorBlockSegmentSkipped(player, track, payload) {
|
|
1256
|
-
|
|
1277
|
+
this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track || this.getTrackOfPayload(payload), payload);
|
|
1278
|
+
return;
|
|
1257
1279
|
}
|
|
1258
1280
|
/** @private util function for handling SponsorBlock Chaptersloaded event */
|
|
1259
1281
|
async SponsorBlockChaptersLoaded(player, track, payload) {
|
|
1260
|
-
|
|
1282
|
+
this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track || this.getTrackOfPayload(payload), payload);
|
|
1283
|
+
return;
|
|
1261
1284
|
}
|
|
1262
1285
|
/** @private util function for handling SponsorBlock Chaptersstarted event */
|
|
1263
1286
|
async SponsorBlockChapterStarted(player, track, payload) {
|
|
1264
|
-
|
|
1287
|
+
this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track || this.getTrackOfPayload(payload), payload);
|
|
1288
|
+
return;
|
|
1265
1289
|
}
|
|
1266
1290
|
/**
|
|
1267
1291
|
* Get the current sponsorblocks for the sponsorblock plugin
|
|
@@ -1408,8 +1432,10 @@ export class LavalinkNode {
|
|
|
1408
1432
|
await player.queue.utils.save();
|
|
1409
1433
|
}
|
|
1410
1434
|
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) {
|
|
1411
|
-
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0)
|
|
1412
|
-
|
|
1435
|
+
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0) {
|
|
1436
|
+
player.destroy(DestroyReasons.QueueEmpty);
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1413
1439
|
else {
|
|
1414
1440
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1415
1441
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.TriggerQueueEmptyInterval, {
|
|
@@ -1418,16 +1444,23 @@ export class LavalinkNode {
|
|
|
1418
1444
|
functionLayer: "LavalinkNode > queueEnd() > destroyAfterMs",
|
|
1419
1445
|
});
|
|
1420
1446
|
}
|
|
1447
|
+
this.NodeManager.LavalinkManager.emit("playerQueueEmptyStart", player, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs);
|
|
1421
1448
|
if (player.get("internal_queueempty")) {
|
|
1422
1449
|
clearTimeout(player.get("internal_queueempty"));
|
|
1423
1450
|
player.set("internal_queueempty", undefined);
|
|
1424
1451
|
}
|
|
1425
1452
|
player.set("internal_queueempty", setTimeout(() => {
|
|
1453
|
+
player.set("internal_queueempty", undefined);
|
|
1454
|
+
if (player.queue.current) {
|
|
1455
|
+
return this.NodeManager.LavalinkManager.emit("playerQueueEmptyCancel", player);
|
|
1456
|
+
}
|
|
1457
|
+
this.NodeManager.LavalinkManager.emit("playerQueueEmptyEnd", player);
|
|
1426
1458
|
player.destroy(DestroyReasons.QueueEmpty);
|
|
1427
1459
|
}, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs));
|
|
1428
1460
|
}
|
|
1429
1461
|
}
|
|
1430
|
-
|
|
1462
|
+
this.NodeManager.LavalinkManager.emit("queueEnd", player, track, payload);
|
|
1463
|
+
return;
|
|
1431
1464
|
}
|
|
1432
1465
|
/**
|
|
1433
1466
|
* Emitted whenever a line of lyrics gets emitted
|
|
@@ -1436,8 +1469,24 @@ export class LavalinkNode {
|
|
|
1436
1469
|
* @param {Track} track The track that emitted the event
|
|
1437
1470
|
* @param {LyricsLineEvent} payload The payload of the event
|
|
1438
1471
|
*/
|
|
1439
|
-
LyricsLine(player, track, payload) {
|
|
1440
|
-
|
|
1472
|
+
async LyricsLine(player, track, payload) {
|
|
1473
|
+
if (!player.queue.current) {
|
|
1474
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1475
|
+
if (player.queue.current) {
|
|
1476
|
+
await player.queue.utils.save();
|
|
1477
|
+
}
|
|
1478
|
+
else {
|
|
1479
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1480
|
+
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.TrackStartNoTrack, {
|
|
1481
|
+
state: "warn",
|
|
1482
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1483
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
this.NodeManager.LavalinkManager.emit("LyricsLine", player, track, payload);
|
|
1489
|
+
return;
|
|
1441
1490
|
}
|
|
1442
1491
|
/**
|
|
1443
1492
|
* Emitted whenever the lyrics for a track got found
|
|
@@ -1446,8 +1495,24 @@ export class LavalinkNode {
|
|
|
1446
1495
|
* @param {Track} track The track that emitted the event
|
|
1447
1496
|
* @param {LyricsFoundEvent} payload The payload of the event
|
|
1448
1497
|
*/
|
|
1449
|
-
LyricsFound(player, track, payload) {
|
|
1450
|
-
|
|
1498
|
+
async LyricsFound(player, track, payload) {
|
|
1499
|
+
if (!player.queue.current) {
|
|
1500
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1501
|
+
if (player.queue.current) {
|
|
1502
|
+
await player.queue.utils.save();
|
|
1503
|
+
}
|
|
1504
|
+
else {
|
|
1505
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1506
|
+
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.TrackStartNoTrack, {
|
|
1507
|
+
state: "warn",
|
|
1508
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1509
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
this.NodeManager.LavalinkManager.emit("LyricsFound", player, track, payload);
|
|
1515
|
+
return;
|
|
1451
1516
|
}
|
|
1452
1517
|
/**
|
|
1453
1518
|
* Emitted whenever the lyrics for a track got not found
|
|
@@ -1456,7 +1521,23 @@ export class LavalinkNode {
|
|
|
1456
1521
|
* @param {Track} track The track that emitted the event
|
|
1457
1522
|
* @param {LyricsNotFoundEvent} payload The payload of the event
|
|
1458
1523
|
*/
|
|
1459
|
-
LyricsNotFound(player, track, payload) {
|
|
1460
|
-
|
|
1524
|
+
async LyricsNotFound(player, track, payload) {
|
|
1525
|
+
if (!player.queue.current) {
|
|
1526
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1527
|
+
if (player.queue.current) {
|
|
1528
|
+
await player.queue.utils.save();
|
|
1529
|
+
}
|
|
1530
|
+
else {
|
|
1531
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1532
|
+
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.TrackStartNoTrack, {
|
|
1533
|
+
state: "warn",
|
|
1534
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1535
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
this.NodeManager.LavalinkManager.emit("LyricsNotFound", player, track, payload);
|
|
1541
|
+
return;
|
|
1461
1542
|
}
|
|
1462
1543
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { EventEmitter } from "events";
|
|
3
2
|
import { LavalinkNode } from "./Node.js";
|
|
4
3
|
import { MiniMap } from "./Utils.js";
|
|
@@ -55,9 +54,10 @@ export declare class NodeManager extends EventEmitter {
|
|
|
55
54
|
/**
|
|
56
55
|
* Disconnects all Nodes from lavalink ws sockets
|
|
57
56
|
* @param deleteAllNodes if the nodes should also be deleted from nodeManager.nodes
|
|
57
|
+
* @param destroyPlayers if the players should be destroyed
|
|
58
58
|
* @returns amount of disconnected Nodes
|
|
59
59
|
*/
|
|
60
|
-
disconnectAll(deleteAllNodes?: boolean): Promise<number>;
|
|
60
|
+
disconnectAll(deleteAllNodes?: boolean, destroyPlayers?: boolean): Promise<number>;
|
|
61
61
|
/**
|
|
62
62
|
* Connects all not connected nodes
|
|
63
63
|
* @returns Amount of connected Nodes
|