lavalink-client 2.3.6 → 2.4.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 +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 +36 -14
- 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 +36 -14
- 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 +29 -18
|
@@ -17,6 +17,7 @@ class LavalinkNode {
|
|
|
17
17
|
}
|
|
18
18
|
heartBeatInterval;
|
|
19
19
|
pingTimeout;
|
|
20
|
+
isAlive = false;
|
|
20
21
|
/** The provided Options of the Node */
|
|
21
22
|
options;
|
|
22
23
|
/** The amount of rest calls the node has made. */
|
|
@@ -78,7 +79,7 @@ class LavalinkNode {
|
|
|
78
79
|
retryAmount: 5,
|
|
79
80
|
retryDelay: 10e3,
|
|
80
81
|
requestSignalTimeoutMS: 10000,
|
|
81
|
-
heartBeatInterval:
|
|
82
|
+
heartBeatInterval: 30_000,
|
|
82
83
|
closeOnError: true,
|
|
83
84
|
enablePingOnStatsCheck: true,
|
|
84
85
|
...options
|
|
@@ -141,32 +142,22 @@ class LavalinkNode {
|
|
|
141
142
|
const url = new URL(`${this.restAddress}${options.path}`);
|
|
142
143
|
url.searchParams.append("trace", "true");
|
|
143
144
|
const urlToUse = this.getRequestingUrl(url, options?.extraQueryUrlParams);
|
|
145
|
+
const originalOptions = structuredClone(options);
|
|
144
146
|
delete options.path;
|
|
145
147
|
delete options.extraQueryUrlParams;
|
|
146
|
-
const
|
|
148
|
+
const response = await fetch(urlToUse, options);
|
|
147
149
|
this.calls++;
|
|
148
|
-
return {
|
|
150
|
+
return { response, options: originalOptions };
|
|
149
151
|
}
|
|
150
|
-
|
|
151
|
-
* Makes an API call to the Node. Should only be used for manual parsing like for not supported plugins
|
|
152
|
-
* @param endpoint The endpoint that we will make the call to
|
|
153
|
-
* @param modify Used to modify the request before being sent
|
|
154
|
-
* @returns The returned data
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* ```ts
|
|
158
|
-
* player.node.request(`/loadtracks?identifier=Never gonna give you up`, (options) => options.method = "GET", false);
|
|
159
|
-
* ```
|
|
160
|
-
*/
|
|
161
|
-
async request(endpoint, modify, parseAsText = false) {
|
|
152
|
+
async request(endpoint, modify, parseAsText) {
|
|
162
153
|
if (!this.connected)
|
|
163
154
|
throw new Error("The node is not connected to the Lavalink Server!, Please call node.connect() first!");
|
|
164
|
-
const {
|
|
155
|
+
const { response, options } = await this.rawRequest(endpoint, modify);
|
|
165
156
|
if (["DELETE", "PUT"].includes(options.method))
|
|
166
157
|
return;
|
|
167
|
-
if (
|
|
168
|
-
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${JSON.stringify(
|
|
169
|
-
return parseAsText ? await
|
|
158
|
+
if (response.status === 404)
|
|
159
|
+
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${JSON.stringify(response.headers)}`);
|
|
160
|
+
return parseAsText ? await response.text() : await response.json();
|
|
170
161
|
}
|
|
171
162
|
/**
|
|
172
163
|
* Search something raw on the node, please note only add tracks to players of that node
|
|
@@ -241,7 +232,7 @@ class LavalinkNode {
|
|
|
241
232
|
* @param query LavaSearchQuery Object
|
|
242
233
|
* @param requestUser Request User for creating the player(s)
|
|
243
234
|
* @param throwOnEmpty Wether to throw on an empty result or not
|
|
244
|
-
* @returns LavaSearchresult
|
|
235
|
+
* @returns LavaSearchresult (SearchResult if link is provided)
|
|
245
236
|
*
|
|
246
237
|
* @example
|
|
247
238
|
* ```ts
|
|
@@ -261,8 +252,8 @@ class LavalinkNode {
|
|
|
261
252
|
throw new RangeError(`there is no lavasearch-plugin available in the lavalink node: ${this.id}`);
|
|
262
253
|
if (!this.info.plugins.find(v => v.name === "lavasrc-plugin"))
|
|
263
254
|
throw new RangeError(`there is no lavasrc-plugin available in the lavalink node: ${this.id}`);
|
|
264
|
-
const {
|
|
265
|
-
const res = (
|
|
255
|
+
const { response } = await this.rawRequest(`/loadsearch?query=${Query.source ? `${Query.source}:` : ""}${encodeURIComponent(Query.query)}${Query.types?.length ? `&types=${Query.types.join(",")}` : ""}`);
|
|
256
|
+
const res = (response.status === 204 ? {} : await response.json());
|
|
266
257
|
if (throwOnEmpty === true && !Object.entries(res).flat().filter(Boolean).length) {
|
|
267
258
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
268
259
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.LavaSearchNothingFound, {
|
|
@@ -299,7 +290,6 @@ class LavalinkNode {
|
|
|
299
290
|
this.syncPlayerData(data);
|
|
300
291
|
const res = await this.request(`/sessions/${this.sessionId}/players/${data.guildId}`, r => {
|
|
301
292
|
r.method = "PATCH";
|
|
302
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
303
293
|
r.headers["Content-Type"] = "application/json";
|
|
304
294
|
r.body = JSON.stringify(data.playerOptions);
|
|
305
295
|
if (data.noReplace) {
|
|
@@ -315,7 +305,8 @@ class LavalinkNode {
|
|
|
315
305
|
functionLayer: "LavalinkNode > node > updatePlayer()",
|
|
316
306
|
});
|
|
317
307
|
}
|
|
318
|
-
|
|
308
|
+
this.syncPlayerData({}, res);
|
|
309
|
+
return res;
|
|
319
310
|
}
|
|
320
311
|
/**
|
|
321
312
|
* Destroys the Player on the Lavalink Server
|
|
@@ -384,6 +375,7 @@ class LavalinkNode {
|
|
|
384
375
|
if (this.pingTimeout)
|
|
385
376
|
clearTimeout(this.pingTimeout);
|
|
386
377
|
this.pingTimeout = setTimeout(() => {
|
|
378
|
+
this.pingTimeout = null;
|
|
387
379
|
if (!this.socket) {
|
|
388
380
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
389
381
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.NoSocketOnDestroy, {
|
|
@@ -403,7 +395,7 @@ class LavalinkNode {
|
|
|
403
395
|
}
|
|
404
396
|
this.isAlive = false;
|
|
405
397
|
this.socket.terminate();
|
|
406
|
-
},
|
|
398
|
+
}, 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
|
|
407
399
|
}
|
|
408
400
|
/**
|
|
409
401
|
* Get the id of the node
|
|
@@ -419,7 +411,7 @@ class LavalinkNode {
|
|
|
419
411
|
}
|
|
420
412
|
/**
|
|
421
413
|
* Destroys the Node-Connection (Websocket) and all player's of the node
|
|
422
|
-
* @param destroyReason
|
|
414
|
+
* @param destroyReason Destroy Reason to use when destroying the players
|
|
423
415
|
* @param deleteNode wether to delete the nodte from the nodes list too, if false it will emit a disconnect. @default true
|
|
424
416
|
* @returns void
|
|
425
417
|
*
|
|
@@ -450,6 +442,28 @@ class LavalinkNode {
|
|
|
450
442
|
}
|
|
451
443
|
return;
|
|
452
444
|
}
|
|
445
|
+
/**
|
|
446
|
+
* Disconnects the Node-Connection (Websocket)
|
|
447
|
+
* @param disconnectReason Disconnect Reason to use when disconnecting Node
|
|
448
|
+
* @returns void
|
|
449
|
+
*
|
|
450
|
+
* Also the node will not get re-connected again.
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```ts
|
|
454
|
+
* player.node.destroy("custom Player Destroy Reason", true);
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
disconnect(disconnectReason) {
|
|
458
|
+
if (!this.connected)
|
|
459
|
+
return;
|
|
460
|
+
this.socket.close(1000, "Node-Disconnect");
|
|
461
|
+
this.socket.removeAllListeners();
|
|
462
|
+
this.socket = null;
|
|
463
|
+
this.reconnectAttempts = 1;
|
|
464
|
+
clearTimeout(this.reconnectTimeout);
|
|
465
|
+
this.NodeManager.emit("disconnect", this, { code: 1000, reason: disconnectReason });
|
|
466
|
+
}
|
|
453
467
|
/**
|
|
454
468
|
* Returns if connected to the Node.
|
|
455
469
|
*
|
|
@@ -460,11 +474,8 @@ class LavalinkNode {
|
|
|
460
474
|
* ```
|
|
461
475
|
*/
|
|
462
476
|
get connected() {
|
|
463
|
-
|
|
464
|
-
return false;
|
|
465
|
-
return this.socket.readyState === ws_1.default.OPEN;
|
|
477
|
+
return this.socket && this.socket.readyState === ws_1.default.OPEN;
|
|
466
478
|
}
|
|
467
|
-
isAlive = false;
|
|
468
479
|
/**
|
|
469
480
|
* Returns the current ConnectionStatus
|
|
470
481
|
*
|
|
@@ -585,7 +596,6 @@ class LavalinkNode {
|
|
|
585
596
|
return await this.request(`/decodetracks`, r => {
|
|
586
597
|
r.method = "POST";
|
|
587
598
|
r.body = JSON.stringify(encodeds);
|
|
588
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
589
599
|
r.headers["Content-Type"] = "application/json";
|
|
590
600
|
}).then((r) => r.map(track => this.NodeManager.LavalinkManager.utils.buildTrack(track, requester)));
|
|
591
601
|
}
|
|
@@ -661,7 +671,7 @@ class LavalinkNode {
|
|
|
661
671
|
throw new RangeError(`there is no lyrics source (via lavasrc-plugin / java-lyrics-plugin) available in the lavalink node (required for lyrics): ${this.id}`);
|
|
662
672
|
return await this.request(`/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe`, (options) => {
|
|
663
673
|
options.method = "POST";
|
|
664
|
-
})
|
|
674
|
+
});
|
|
665
675
|
},
|
|
666
676
|
/**
|
|
667
677
|
* unsubscribe from lyrics updates for a guild
|
|
@@ -685,7 +695,7 @@ class LavalinkNode {
|
|
|
685
695
|
throw new RangeError(`there is no lyrics source (via lavasrc-plugin / java-lyrics-plugin) available in the lavalink node (required for lyrics): ${this.id}`);
|
|
686
696
|
return await this.request(`/sessions/${this.sessionId}/players/${guildId}/lyrics/unsubscribe`, (options) => {
|
|
687
697
|
options.method = "DELETE";
|
|
688
|
-
})
|
|
698
|
+
});
|
|
689
699
|
},
|
|
690
700
|
};
|
|
691
701
|
/**
|
|
@@ -760,9 +770,8 @@ class LavalinkNode {
|
|
|
760
770
|
unmarkFailedAddress: async (address) => {
|
|
761
771
|
if (!this.sessionId)
|
|
762
772
|
throw new Error("the Lavalink-Node is either not ready, or not up to date!");
|
|
763
|
-
await this.request(`/routeplanner/free/address`, r => {
|
|
773
|
+
return await this.request(`/routeplanner/free/address`, r => {
|
|
764
774
|
r.method = "POST";
|
|
765
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
766
775
|
r.headers["Content-Type"] = "application/json";
|
|
767
776
|
r.body = JSON.stringify({ address });
|
|
768
777
|
});
|
|
@@ -781,7 +790,6 @@ class LavalinkNode {
|
|
|
781
790
|
throw new Error("the Lavalink-Node is either not ready, or not up to date!");
|
|
782
791
|
return await this.request(`/routeplanner/free/all`, r => {
|
|
783
792
|
r.method = "POST";
|
|
784
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
785
793
|
r.headers["Content-Type"] = "application/json";
|
|
786
794
|
});
|
|
787
795
|
}
|
|
@@ -794,6 +802,7 @@ class LavalinkNode {
|
|
|
794
802
|
throw new SyntaxError("LavalinkNode requires 'host'");
|
|
795
803
|
if (!this.options.port)
|
|
796
804
|
throw new SyntaxError("LavalinkNode requires 'port'");
|
|
805
|
+
// TODO add more validations
|
|
797
806
|
}
|
|
798
807
|
/**
|
|
799
808
|
* Sync the data of the player you make an action to lavalink to
|
|
@@ -858,11 +867,13 @@ class LavalinkNode {
|
|
|
858
867
|
const player = this.NodeManager.LavalinkManager.getPlayer(data.guildId);
|
|
859
868
|
if (!player)
|
|
860
869
|
return;
|
|
861
|
-
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false)
|
|
862
|
-
|
|
870
|
+
if (typeof res?.voice?.connected === "boolean" && res.voice.connected === false) {
|
|
871
|
+
player.destroy(Constants_1.DestroyReasons.LavalinkNoVoice);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
863
874
|
player.ping.ws = res?.voice?.ping || player?.ping.ws;
|
|
864
875
|
}
|
|
865
|
-
return
|
|
876
|
+
return;
|
|
866
877
|
}
|
|
867
878
|
/**
|
|
868
879
|
* Get the rest Adress for making requests
|
|
@@ -896,6 +907,7 @@ class LavalinkNode {
|
|
|
896
907
|
return;
|
|
897
908
|
}
|
|
898
909
|
this.reconnectTimeout = setTimeout(() => {
|
|
910
|
+
this.reconnectTimeout = null;
|
|
899
911
|
if (this.reconnectAttempts >= this.options.retryAmount) {
|
|
900
912
|
const error = new Error(`Unable to connect after ${this.options.retryAmount} attempts.`);
|
|
901
913
|
this.NodeManager.emit("error", this, error);
|
|
@@ -931,7 +943,7 @@ class LavalinkNode {
|
|
|
931
943
|
this.isAlive = false;
|
|
932
944
|
this.heartBeatPingTimestamp = performance.now();
|
|
933
945
|
this.socket.ping();
|
|
934
|
-
}, this.options.heartBeatInterval ||
|
|
946
|
+
}, this.options.heartBeatInterval || 30_000);
|
|
935
947
|
}
|
|
936
948
|
if (this.reconnectTimeout)
|
|
937
949
|
clearTimeout(this.reconnectTimeout);
|
|
@@ -952,6 +964,8 @@ class LavalinkNode {
|
|
|
952
964
|
clearInterval(this.heartBeatInterval);
|
|
953
965
|
if (code === 1006 && !reason)
|
|
954
966
|
reason = "Socket got terminated due to no ping connection";
|
|
967
|
+
if (code === 1000 && reason === "Node-Disconnect")
|
|
968
|
+
return; // manually disconnected and already emitted the event.
|
|
955
969
|
this.NodeManager.emit("disconnect", this, { code, reason });
|
|
956
970
|
if (code !== 1000 || reason !== "Node-Destroy")
|
|
957
971
|
this.reconnect();
|
|
@@ -976,7 +990,14 @@ class LavalinkNode {
|
|
|
976
990
|
d = Buffer.concat(d);
|
|
977
991
|
else if (d instanceof ArrayBuffer)
|
|
978
992
|
d = Buffer.from(d);
|
|
979
|
-
|
|
993
|
+
let payload;
|
|
994
|
+
try {
|
|
995
|
+
payload = JSON.parse(d.toString());
|
|
996
|
+
}
|
|
997
|
+
catch (e) {
|
|
998
|
+
this.NodeManager.emit("error", this, e);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
980
1001
|
if (!payload.op)
|
|
981
1002
|
return;
|
|
982
1003
|
this.NodeManager.emit("raw", this, payload);
|
|
@@ -1007,7 +1028,7 @@ class LavalinkNode {
|
|
|
1007
1028
|
player.ping.ws = payload.state.ping >= 0 ? payload.state.ping : player.ping.ws <= 0 && player.connected ? null : player.ping.ws || 0;
|
|
1008
1029
|
if (!player.createdTimeStamp && payload.state.time)
|
|
1009
1030
|
player.createdTimeStamp = payload.state.time;
|
|
1010
|
-
if (player.filterManager.filterUpdatedState === true && ((player.queue.current?.info?.duration || 0) <= (player.LavalinkManager.options.advancedOptions.maxFilterFixDuration ||
|
|
1031
|
+
if (player.filterManager.filterUpdatedState === true && ((player.queue.current?.info?.duration || 0) <= (player.LavalinkManager.options.advancedOptions.maxFilterFixDuration || 600_000) || (0, path_1.isAbsolute)(player.queue.current?.info?.uri))) {
|
|
1011
1032
|
player.filterManager.filterUpdatedState = false;
|
|
1012
1033
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1013
1034
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerUpdateFilterFixApply, {
|
|
@@ -1099,7 +1120,7 @@ class LavalinkNode {
|
|
|
1099
1120
|
}
|
|
1100
1121
|
return;
|
|
1101
1122
|
}
|
|
1102
|
-
|
|
1123
|
+
getTrackOfPayload(payload) {
|
|
1103
1124
|
return "track" in payload
|
|
1104
1125
|
? this.NodeManager.LavalinkManager.utils.buildTrack(payload.track, undefined)
|
|
1105
1126
|
: null;
|
|
@@ -1120,7 +1141,7 @@ class LavalinkNode {
|
|
|
1120
1141
|
return;
|
|
1121
1142
|
}
|
|
1122
1143
|
if (!player.queue.current) {
|
|
1123
|
-
player.queue.current =
|
|
1144
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1124
1145
|
if (player.queue.current) {
|
|
1125
1146
|
await player.queue.utils.save();
|
|
1126
1147
|
}
|
|
@@ -1134,11 +1155,12 @@ class LavalinkNode {
|
|
|
1134
1155
|
}
|
|
1135
1156
|
}
|
|
1136
1157
|
}
|
|
1137
|
-
|
|
1158
|
+
this.NodeManager.LavalinkManager.emit("trackStart", player, player.queue.current, payload);
|
|
1159
|
+
return;
|
|
1138
1160
|
}
|
|
1139
1161
|
/** @private util function for handling trackEnd event */
|
|
1140
1162
|
async trackEnd(player, track, payload) {
|
|
1141
|
-
const trackToUse = track ||
|
|
1163
|
+
const trackToUse = track || this.getTrackOfPayload(payload);
|
|
1142
1164
|
// If a track was forcibly played
|
|
1143
1165
|
if (payload.reason === "replaced") {
|
|
1144
1166
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
@@ -1148,7 +1170,8 @@ class LavalinkNode {
|
|
|
1148
1170
|
functionLayer: "LavalinkNode > trackEnd()",
|
|
1149
1171
|
});
|
|
1150
1172
|
}
|
|
1151
|
-
|
|
1173
|
+
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1174
|
+
return;
|
|
1152
1175
|
}
|
|
1153
1176
|
// If there are no songs in the queue
|
|
1154
1177
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
@@ -1162,7 +1185,10 @@ class LavalinkNode {
|
|
|
1162
1185
|
// fire event
|
|
1163
1186
|
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1164
1187
|
// play track if autoSkip is true
|
|
1165
|
-
|
|
1188
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1189
|
+
player.play({ noReplace: true });
|
|
1190
|
+
}
|
|
1191
|
+
return;
|
|
1166
1192
|
}
|
|
1167
1193
|
// remove tracks from the queue
|
|
1168
1194
|
if (player.repeatMode !== "track" || player.get("internal_skipped"))
|
|
@@ -1180,7 +1206,10 @@ class LavalinkNode {
|
|
|
1180
1206
|
// fire event
|
|
1181
1207
|
this.NodeManager.LavalinkManager.emit("trackEnd", player, trackToUse, payload);
|
|
1182
1208
|
// play track if autoSkip is true
|
|
1183
|
-
|
|
1209
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1210
|
+
player.play({ noReplace: true });
|
|
1211
|
+
}
|
|
1212
|
+
return;
|
|
1184
1213
|
}
|
|
1185
1214
|
/** @private util function for handling trackStuck event */
|
|
1186
1215
|
async trackStuck(player, track, payload) {
|
|
@@ -1196,21 +1225,25 @@ class LavalinkNode {
|
|
|
1196
1225
|
functionLayer: "LavalinkNode > trackStuck()",
|
|
1197
1226
|
});
|
|
1198
1227
|
}
|
|
1199
|
-
|
|
1228
|
+
player.destroy(Constants_1.DestroyReasons.TrackStuckMaxTracksErroredPerTime);
|
|
1229
|
+
return;
|
|
1200
1230
|
}
|
|
1201
1231
|
}
|
|
1202
|
-
this.NodeManager.LavalinkManager.emit("trackStuck", player, track ||
|
|
1232
|
+
this.NodeManager.LavalinkManager.emit("trackStuck", player, track || this.getTrackOfPayload(payload), payload);
|
|
1203
1233
|
// If there are no songs in the queue
|
|
1204
1234
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
1205
|
-
return this.queueEnd(player, track ||
|
|
1235
|
+
return this.queueEnd(player, track || this.getTrackOfPayload(payload), payload);
|
|
1206
1236
|
// remove the current track, and enqueue the next one
|
|
1207
1237
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
1208
1238
|
// if no track available, end queue
|
|
1209
1239
|
if (!player.queue.current) {
|
|
1210
|
-
return this.queueEnd(player, track ||
|
|
1240
|
+
return this.queueEnd(player, track || this.getTrackOfPayload(payload), payload);
|
|
1211
1241
|
}
|
|
1212
1242
|
// play track if autoSkip is true
|
|
1213
|
-
|
|
1243
|
+
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1244
|
+
player.play({ noReplace: true });
|
|
1245
|
+
}
|
|
1246
|
+
return;
|
|
1214
1247
|
}
|
|
1215
1248
|
/** @private util function for handling trackError event */
|
|
1216
1249
|
async trackError(player, track, payload) {
|
|
@@ -1226,46 +1259,37 @@ class LavalinkNode {
|
|
|
1226
1259
|
functionLayer: "LavalinkNode > trackError()",
|
|
1227
1260
|
});
|
|
1228
1261
|
}
|
|
1229
|
-
|
|
1262
|
+
player.destroy(Constants_1.DestroyReasons.TrackErrorMaxTracksErroredPerTime);
|
|
1263
|
+
return;
|
|
1230
1264
|
}
|
|
1231
1265
|
}
|
|
1232
|
-
this.NodeManager.LavalinkManager.emit("trackError", player, track ||
|
|
1233
|
-
return;
|
|
1234
|
-
// If there are no songs in the queue
|
|
1235
|
-
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
1236
|
-
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
1237
|
-
// remove the current track, and enqueue the next one
|
|
1238
|
-
await (0, Utils_1.queueTrackEnd)(player);
|
|
1239
|
-
// if no track available, end queue
|
|
1240
|
-
if (!player.queue.current)
|
|
1241
|
-
return this.queueEnd(player, track || await this.getTrackOfPayload(payload), payload);
|
|
1242
|
-
// play track if autoSkip is true
|
|
1243
|
-
return (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) && player.play({ noReplace: true });
|
|
1266
|
+
this.NodeManager.LavalinkManager.emit("trackError", player, track || this.getTrackOfPayload(payload), payload);
|
|
1267
|
+
return;
|
|
1244
1268
|
}
|
|
1245
1269
|
/** @private util function for handling socketClosed event */
|
|
1246
1270
|
socketClosed(player, payload) {
|
|
1247
1271
|
this.NodeManager.LavalinkManager.emit("playerSocketClosed", player, payload);
|
|
1248
|
-
// i don't think this is needed.
|
|
1249
|
-
// this.socket = null;
|
|
1250
|
-
// // causing a socket reconnect
|
|
1251
|
-
// this.connect();
|
|
1252
1272
|
return;
|
|
1253
1273
|
}
|
|
1254
1274
|
/** @private util function for handling SponsorBlock Segmentloaded event */
|
|
1255
1275
|
async SponsorBlockSegmentLoaded(player, track, payload) {
|
|
1256
|
-
|
|
1276
|
+
this.NodeManager.LavalinkManager.emit("SegmentsLoaded", player, track || this.getTrackOfPayload(payload), payload);
|
|
1277
|
+
return;
|
|
1257
1278
|
}
|
|
1258
1279
|
/** @private util function for handling SponsorBlock SegmentSkipped event */
|
|
1259
1280
|
async SponsorBlockSegmentSkipped(player, track, payload) {
|
|
1260
|
-
|
|
1281
|
+
this.NodeManager.LavalinkManager.emit("SegmentSkipped", player, track || this.getTrackOfPayload(payload), payload);
|
|
1282
|
+
return;
|
|
1261
1283
|
}
|
|
1262
1284
|
/** @private util function for handling SponsorBlock Chaptersloaded event */
|
|
1263
1285
|
async SponsorBlockChaptersLoaded(player, track, payload) {
|
|
1264
|
-
|
|
1286
|
+
this.NodeManager.LavalinkManager.emit("ChaptersLoaded", player, track || this.getTrackOfPayload(payload), payload);
|
|
1287
|
+
return;
|
|
1265
1288
|
}
|
|
1266
1289
|
/** @private util function for handling SponsorBlock Chaptersstarted event */
|
|
1267
1290
|
async SponsorBlockChapterStarted(player, track, payload) {
|
|
1268
|
-
|
|
1291
|
+
this.NodeManager.LavalinkManager.emit("ChapterStarted", player, track || this.getTrackOfPayload(payload), payload);
|
|
1292
|
+
return;
|
|
1269
1293
|
}
|
|
1270
1294
|
/**
|
|
1271
1295
|
* Get the current sponsorblocks for the sponsorblock plugin
|
|
@@ -1412,8 +1436,10 @@ class LavalinkNode {
|
|
|
1412
1436
|
await player.queue.utils.save();
|
|
1413
1437
|
}
|
|
1414
1438
|
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) {
|
|
1415
|
-
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0)
|
|
1416
|
-
|
|
1439
|
+
if (this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs === 0) {
|
|
1440
|
+
player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1417
1443
|
else {
|
|
1418
1444
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1419
1445
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.TriggerQueueEmptyInterval, {
|
|
@@ -1422,16 +1448,23 @@ class LavalinkNode {
|
|
|
1422
1448
|
functionLayer: "LavalinkNode > queueEnd() > destroyAfterMs",
|
|
1423
1449
|
});
|
|
1424
1450
|
}
|
|
1451
|
+
this.NodeManager.LavalinkManager.emit("playerQueueEmptyStart", player, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs);
|
|
1425
1452
|
if (player.get("internal_queueempty")) {
|
|
1426
1453
|
clearTimeout(player.get("internal_queueempty"));
|
|
1427
1454
|
player.set("internal_queueempty", undefined);
|
|
1428
1455
|
}
|
|
1429
1456
|
player.set("internal_queueempty", setTimeout(() => {
|
|
1457
|
+
player.set("internal_queueempty", undefined);
|
|
1458
|
+
if (player.queue.current) {
|
|
1459
|
+
return this.NodeManager.LavalinkManager.emit("playerQueueEmptyCancel", player);
|
|
1460
|
+
}
|
|
1461
|
+
this.NodeManager.LavalinkManager.emit("playerQueueEmptyEnd", player);
|
|
1430
1462
|
player.destroy(Constants_1.DestroyReasons.QueueEmpty);
|
|
1431
1463
|
}, this.NodeManager.LavalinkManager.options.playerOptions.onEmptyQueue?.destroyAfterMs));
|
|
1432
1464
|
}
|
|
1433
1465
|
}
|
|
1434
|
-
|
|
1466
|
+
this.NodeManager.LavalinkManager.emit("queueEnd", player, track, payload);
|
|
1467
|
+
return;
|
|
1435
1468
|
}
|
|
1436
1469
|
/**
|
|
1437
1470
|
* Emitted whenever a line of lyrics gets emitted
|
|
@@ -1440,8 +1473,24 @@ class LavalinkNode {
|
|
|
1440
1473
|
* @param {Track} track The track that emitted the event
|
|
1441
1474
|
* @param {LyricsLineEvent} payload The payload of the event
|
|
1442
1475
|
*/
|
|
1443
|
-
LyricsLine(player, track, payload) {
|
|
1444
|
-
|
|
1476
|
+
async LyricsLine(player, track, payload) {
|
|
1477
|
+
if (!player.queue.current) {
|
|
1478
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1479
|
+
if (player.queue.current) {
|
|
1480
|
+
await player.queue.utils.save();
|
|
1481
|
+
}
|
|
1482
|
+
else {
|
|
1483
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1484
|
+
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.TrackStartNoTrack, {
|
|
1485
|
+
state: "warn",
|
|
1486
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1487
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1488
|
+
});
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
this.NodeManager.LavalinkManager.emit("LyricsLine", player, track, payload);
|
|
1493
|
+
return;
|
|
1445
1494
|
}
|
|
1446
1495
|
/**
|
|
1447
1496
|
* Emitted whenever the lyrics for a track got found
|
|
@@ -1450,8 +1499,24 @@ class LavalinkNode {
|
|
|
1450
1499
|
* @param {Track} track The track that emitted the event
|
|
1451
1500
|
* @param {LyricsFoundEvent} payload The payload of the event
|
|
1452
1501
|
*/
|
|
1453
|
-
LyricsFound(player, track, payload) {
|
|
1454
|
-
|
|
1502
|
+
async LyricsFound(player, track, payload) {
|
|
1503
|
+
if (!player.queue.current) {
|
|
1504
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1505
|
+
if (player.queue.current) {
|
|
1506
|
+
await player.queue.utils.save();
|
|
1507
|
+
}
|
|
1508
|
+
else {
|
|
1509
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1510
|
+
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.TrackStartNoTrack, {
|
|
1511
|
+
state: "warn",
|
|
1512
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1513
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
this.NodeManager.LavalinkManager.emit("LyricsFound", player, track, payload);
|
|
1519
|
+
return;
|
|
1455
1520
|
}
|
|
1456
1521
|
/**
|
|
1457
1522
|
* Emitted whenever the lyrics for a track got not found
|
|
@@ -1460,8 +1525,24 @@ class LavalinkNode {
|
|
|
1460
1525
|
* @param {Track} track The track that emitted the event
|
|
1461
1526
|
* @param {LyricsNotFoundEvent} payload The payload of the event
|
|
1462
1527
|
*/
|
|
1463
|
-
LyricsNotFound(player, track, payload) {
|
|
1464
|
-
|
|
1528
|
+
async LyricsNotFound(player, track, payload) {
|
|
1529
|
+
if (!player.queue.current) {
|
|
1530
|
+
player.queue.current = this.getTrackOfPayload(payload);
|
|
1531
|
+
if (player.queue.current) {
|
|
1532
|
+
await player.queue.utils.save();
|
|
1533
|
+
}
|
|
1534
|
+
else {
|
|
1535
|
+
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1536
|
+
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.TrackStartNoTrack, {
|
|
1537
|
+
state: "warn",
|
|
1538
|
+
message: `Trackstart emitted but there is no track on player.queue.current, trying to get the track of the payload failed too.`,
|
|
1539
|
+
functionLayer: "LavalinkNode > trackStart()",
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
this.NodeManager.LavalinkManager.emit("LyricsNotFound", player, track, payload);
|
|
1545
|
+
return;
|
|
1465
1546
|
}
|
|
1466
1547
|
}
|
|
1467
1548
|
exports.LavalinkNode = LavalinkNode;
|
|
@@ -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
|