lavalink-client 2.5.1 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/structures/Filters.js +3 -2
- package/dist/cjs/structures/LavalinkManager.d.ts +1 -1
- package/dist/cjs/structures/LavalinkManager.js +11 -11
- package/dist/cjs/structures/LavalinkManagerStatics.js +1 -1
- package/dist/cjs/structures/Node.d.ts +1 -1
- package/dist/cjs/structures/Node.js +11 -8
- package/dist/cjs/structures/Player.js +20 -13
- package/dist/cjs/structures/Queue.js +7 -6
- package/dist/cjs/structures/Utils.d.ts +1 -0
- package/dist/cjs/structures/Utils.js +19 -1
- package/dist/esm/structures/Filters.js +3 -2
- package/dist/esm/structures/LavalinkManager.d.ts +1 -1
- package/dist/esm/structures/LavalinkManager.js +12 -12
- package/dist/esm/structures/LavalinkManagerStatics.js +1 -1
- package/dist/esm/structures/Node.d.ts +1 -1
- package/dist/esm/structures/Node.js +12 -9
- package/dist/esm/structures/Player.js +21 -14
- package/dist/esm/structures/Queue.js +7 -6
- package/dist/esm/structures/Utils.d.ts +1 -0
- package/dist/esm/structures/Utils.js +18 -1
- package/dist/types/structures/LavalinkManager.d.ts +1 -1
- package/dist/types/structures/Node.d.ts +1 -1
- package/dist/types/structures/Utils.d.ts +1 -0
- package/package.json +8 -8
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FilterManager = void 0;
|
|
4
4
|
const Constants_1 = require("./Constants.js");
|
|
5
|
+
const Utils_1 = require("./Utils.js");
|
|
5
6
|
/**
|
|
6
7
|
* The FilterManager for each player
|
|
7
8
|
*/
|
|
@@ -673,7 +674,7 @@ class FilterManager {
|
|
|
673
674
|
async setEQ(bands) {
|
|
674
675
|
if (!Array.isArray(bands))
|
|
675
676
|
bands = [bands];
|
|
676
|
-
if (!bands.length || !bands.every((band) =>
|
|
677
|
+
if (!bands.length || !bands.every((band) => (0, Utils_1.safeStringify)(Object.keys(band).sort()) === '["band","gain"]'))
|
|
677
678
|
throw new TypeError("Bands must be a non-empty object array containing 'band' and 'gain' properties.");
|
|
678
679
|
for (const { band, gain } of bands)
|
|
679
680
|
this.equalizerBands[band] = { band, gain };
|
|
@@ -693,7 +694,7 @@ class FilterManager {
|
|
|
693
694
|
}
|
|
694
695
|
/** Clears the equalizer bands. */
|
|
695
696
|
async clearEQ() {
|
|
696
|
-
return this.setEQ(
|
|
697
|
+
return this.setEQ(Array.from({ length: 15 }, () => ({ band: 0, gain: 0 })));
|
|
697
698
|
}
|
|
698
699
|
}
|
|
699
700
|
exports.FilterManager = FilterManager;
|
|
@@ -2,9 +2,9 @@ import { EventEmitter } from "events";
|
|
|
2
2
|
import { NodeManager } from "./NodeManager.js";
|
|
3
3
|
import { Player } from "./Player.js";
|
|
4
4
|
import { ManagerUtils, MiniMap } from "./Utils.js";
|
|
5
|
+
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils.js";
|
|
5
6
|
import type { BotClientOptions, LavalinkManagerEvents, ManagerOptions } from "./Types/Manager.js";
|
|
6
7
|
import type { PlayerOptions } from "./Types/Player.js";
|
|
7
|
-
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils.js";
|
|
8
8
|
export declare class LavalinkManager extends EventEmitter {
|
|
9
9
|
/**
|
|
10
10
|
* Emit an event
|
|
@@ -71,7 +71,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
71
71
|
applyOptions(options) {
|
|
72
72
|
this.options = {
|
|
73
73
|
client: {
|
|
74
|
-
...
|
|
74
|
+
...options?.client,
|
|
75
75
|
id: options?.client?.id,
|
|
76
76
|
username: options?.client?.username ?? "lavalink-client"
|
|
77
77
|
},
|
|
@@ -314,7 +314,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
314
314
|
// oldPlayer.connected is operational. you could also do oldPlayer.voice?.token
|
|
315
315
|
if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
|
|
316
316
|
if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError)
|
|
317
|
-
throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${
|
|
317
|
+
throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${(0, Utils_1.safeStringify)(oldPlayer.toJSON?.())}`);
|
|
318
318
|
else if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
319
319
|
this.emit("debug", Constants_1.DebugEvents.PlayerDeleteInsteadOfDestroy, {
|
|
320
320
|
state: "warn",
|
|
@@ -356,13 +356,13 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
356
356
|
if (this.initiated)
|
|
357
357
|
return this;
|
|
358
358
|
clientData = clientData ?? {};
|
|
359
|
-
this.options.client = { ...
|
|
359
|
+
this.options.client = { ...this.options?.client, ...clientData };
|
|
360
360
|
if (!this.options?.client.id)
|
|
361
361
|
throw new Error('"client.id" is not set. Pass it in Manager#init() or as a option in the constructor.');
|
|
362
362
|
if (typeof this.options?.client.id !== "string")
|
|
363
363
|
throw new Error('"client.id" set is not type of "string"');
|
|
364
364
|
let success = 0;
|
|
365
|
-
for (const node of
|
|
365
|
+
for (const node of this.nodeManager.nodes.values()) {
|
|
366
366
|
try {
|
|
367
367
|
await node.connect();
|
|
368
368
|
success++;
|
|
@@ -439,7 +439,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
439
439
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
440
440
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
441
441
|
state: "warn",
|
|
442
|
-
message: `No Update data found in payload :: ${
|
|
442
|
+
message: `No Update data found in payload :: ${(0, Utils_1.safeStringify)(data, 2)}`,
|
|
443
443
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
444
444
|
});
|
|
445
445
|
}
|
|
@@ -451,7 +451,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
451
451
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
452
452
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
453
453
|
state: "error",
|
|
454
|
-
message: `No 'token' nor 'session_id' found in payload :: ${
|
|
454
|
+
message: `No 'token' nor 'session_id' found in payload :: ${(0, Utils_1.safeStringify)(data, 2)}`,
|
|
455
455
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
456
456
|
});
|
|
457
457
|
}
|
|
@@ -464,7 +464,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
464
464
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
465
465
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
466
466
|
state: "warn",
|
|
467
|
-
message: `No Lavalink Player found via key: 'guild_id' of update-data :: ${
|
|
467
|
+
message: `No Lavalink Player found via key: 'guild_id' of update-data :: ${(0, Utils_1.safeStringify)(update, 2)}`,
|
|
468
468
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
469
469
|
});
|
|
470
470
|
}
|
|
@@ -491,7 +491,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
491
491
|
if (!sessionId2Use) {
|
|
492
492
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
493
493
|
state: "error",
|
|
494
|
-
message: `Can't send updatePlayer for voice token session - Missing sessionId :: ${
|
|
494
|
+
message: `Can't send updatePlayer for voice token session - Missing sessionId :: ${(0, Utils_1.safeStringify)({ voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, update, playerVoice: player.voice }, 2)}`,
|
|
495
495
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
496
496
|
});
|
|
497
497
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
@@ -511,7 +511,7 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
511
511
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
512
512
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
513
513
|
state: "log",
|
|
514
|
-
message: `Sent updatePlayer for voice token session :: ${
|
|
514
|
+
message: `Sent updatePlayer for voice token session :: ${(0, Utils_1.safeStringify)({ voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, update, playerVoice: player.voice }, 2)}`,
|
|
515
515
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
516
516
|
});
|
|
517
517
|
}
|
|
@@ -544,12 +544,12 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
544
544
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
545
545
|
this.emit("debug", Constants_1.DebugEvents.NoAudioDebug, {
|
|
546
546
|
state: "warn",
|
|
547
|
-
message: `Function to assing sessionId provided, but no found in Payload: ${
|
|
547
|
+
message: `Function to assing sessionId provided, but no found in Payload: ${(0, Utils_1.safeStringify)({ update, playerVoice: player.voice }, 2)}`,
|
|
548
548
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
549
549
|
});
|
|
550
550
|
}
|
|
551
551
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
552
|
-
console.debug(`Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Function to assing sessionId provided, but no found in Payload: ${
|
|
552
|
+
console.debug(`Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Function to assing sessionId provided, but no found in Payload: ${(0, Utils_1.safeStringify)(update, 2)}`);
|
|
553
553
|
}
|
|
554
554
|
player.voiceChannelId = update.channel_id;
|
|
555
555
|
const selfMuteChanged = typeof update.self_mute === "boolean" && player.voiceState.selfMute !== update.self_mute;
|
|
@@ -140,7 +140,7 @@ exports.SourceLinksRegexes = {
|
|
|
140
140
|
/** From tidal */
|
|
141
141
|
tidal: /https?:\/\/?(?:www\.)?(?:tidal|listen)\.tidal\.com\/(?<type>track|album|playlist|artist)\/(?<identifier>[a-zA-Z0-9-_]+)/,
|
|
142
142
|
/** From jiosaavn-plugin */
|
|
143
|
-
jiosaavn: /(https?:\/\/)(www\.)?jiosaavn\.com\/(?<type>song|album|featured|artist)\/([a-zA-Z0-9-_
|
|
143
|
+
jiosaavn: /(https?:\/\/)(www\.)?jiosaavn\.com\/(?<type>song|album|featured|artist)\/([a-zA-Z0-9-_/,]+)/,
|
|
144
144
|
/** FROM DUNCTE BOT PLUGIN */
|
|
145
145
|
tiktok: /https:\/\/www\.tiktok\.com\//,
|
|
146
146
|
mixcloud: /https:\/\/www\.mixcloud\.com\//,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils.js";
|
|
1
2
|
import type { Player } from "./Player.js";
|
|
2
3
|
import type { DestroyReasonsType, DisconnectReasonsType } from "./Types/Player.js";
|
|
3
4
|
import type { Track } from "./Types/Track.js";
|
|
4
|
-
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils.js";
|
|
5
5
|
import type { NodeManager } from "./NodeManager.js";
|
|
6
6
|
import type { BaseNodeStats, LavalinkInfo, LavalinkNodeOptions, LyricsResult, ModifyRequest, NodeStats, SponsorBlockSegment } from "./Types/Node.js";
|
|
7
7
|
/**
|
|
@@ -134,7 +134,7 @@ class LavalinkNode {
|
|
|
134
134
|
if (["DELETE", "PUT"].includes(options.method))
|
|
135
135
|
return;
|
|
136
136
|
if (response.status === 404)
|
|
137
|
-
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${
|
|
137
|
+
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${(0, Utils_1.safeStringify)(response.headers)}`);
|
|
138
138
|
return parseAsText ? await response.text() : await response.json();
|
|
139
139
|
}
|
|
140
140
|
/**
|
|
@@ -266,7 +266,7 @@ class LavalinkNode {
|
|
|
266
266
|
const res = await this.request(`/sessions/${this.sessionId}/players/${data.guildId}`, r => {
|
|
267
267
|
r.method = "PATCH";
|
|
268
268
|
r.headers["Content-Type"] = "application/json";
|
|
269
|
-
r.body =
|
|
269
|
+
r.body = (0, Utils_1.safeStringify)(data.playerOptions);
|
|
270
270
|
if (data.noReplace) {
|
|
271
271
|
const url = new URL(`${this.restAddress}${r.path}`);
|
|
272
272
|
url.searchParams.append("noReplace", data.noReplace === true && typeof data.noReplace === "boolean" ? "true" : "false");
|
|
@@ -276,7 +276,7 @@ class LavalinkNode {
|
|
|
276
276
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
277
277
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerUpdateSuccess, {
|
|
278
278
|
state: "log",
|
|
279
|
-
message: `Player get's updated with following payload :: ${
|
|
279
|
+
message: `Player get's updated with following payload :: ${(0, Utils_1.safeStringify)(data.playerOptions, 3)}`,
|
|
280
280
|
functionLayer: "LavalinkNode > node > updatePlayer()",
|
|
281
281
|
});
|
|
282
282
|
}
|
|
@@ -588,7 +588,7 @@ class LavalinkNode {
|
|
|
588
588
|
return this.request(`/sessions/${this.sessionId}`, r => {
|
|
589
589
|
r.method = "PATCH";
|
|
590
590
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
591
|
-
r.body =
|
|
591
|
+
r.body = (0, Utils_1.safeStringify)(data);
|
|
592
592
|
});
|
|
593
593
|
}
|
|
594
594
|
/**
|
|
@@ -632,7 +632,7 @@ class LavalinkNode {
|
|
|
632
632
|
// return the decoded + builded tracks
|
|
633
633
|
return await this.request(`/decodetracks`, r => {
|
|
634
634
|
r.method = "POST";
|
|
635
|
-
r.body =
|
|
635
|
+
r.body = (0, Utils_1.safeStringify)(encodeds);
|
|
636
636
|
r.headers["Content-Type"] = "application/json";
|
|
637
637
|
}).then((r) => r.map(track => this.NodeManager.LavalinkManager.utils.buildTrack(track, requester)));
|
|
638
638
|
}
|
|
@@ -808,7 +808,7 @@ class LavalinkNode {
|
|
|
808
808
|
return await this.request(`/routeplanner/free/address`, r => {
|
|
809
809
|
r.method = "POST";
|
|
810
810
|
r.headers["Content-Type"] = "application/json";
|
|
811
|
-
r.body =
|
|
811
|
+
r.body = (0, Utils_1.safeStringify)({ address });
|
|
812
812
|
});
|
|
813
813
|
},
|
|
814
814
|
/**
|
|
@@ -1218,6 +1218,9 @@ class LavalinkNode {
|
|
|
1218
1218
|
return this.queueEnd(player, track, payload);
|
|
1219
1219
|
// If a track had an error while starting
|
|
1220
1220
|
if (["loadFailed", "cleanup"].includes(payload.reason)) {
|
|
1221
|
+
//Dont add tracks if the player is already destroying.
|
|
1222
|
+
if (player.get("internal_destroystatus") === true)
|
|
1223
|
+
return;
|
|
1221
1224
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
1222
1225
|
// if no track available, end queue
|
|
1223
1226
|
if (!player.queue.current)
|
|
@@ -1273,7 +1276,7 @@ class LavalinkNode {
|
|
|
1273
1276
|
// If there are no songs in the queue
|
|
1274
1277
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying"))) {
|
|
1275
1278
|
try { //Sometimes the trackStuck event triggers from the Lavalink server, but the track continues playing or resumes after. We explicitly end the track in such cases
|
|
1276
|
-
await player.node.updatePlayer({ guildId: player.guildId, playerOptions: { track: { encoded: null } } }); //trackEnd -> queueEnd
|
|
1279
|
+
await player.node.updatePlayer({ guildId: player.guildId, playerOptions: { track: { encoded: null } } }); //trackEnd -> queueEnd
|
|
1277
1280
|
return;
|
|
1278
1281
|
}
|
|
1279
1282
|
catch {
|
|
@@ -1381,7 +1384,7 @@ class LavalinkNode {
|
|
|
1381
1384
|
await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
|
|
1382
1385
|
r.method = "PUT";
|
|
1383
1386
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
1384
|
-
r.body =
|
|
1387
|
+
r.body = (0, Utils_1.safeStringify)(segments.map(v => v.toLowerCase()));
|
|
1385
1388
|
});
|
|
1386
1389
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1387
1390
|
this.NodeManager.LavalinkManager.emit("debug", Constants_1.DebugEvents.SetSponsorBlock, {
|
|
@@ -187,7 +187,11 @@ class Player {
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
if ((typeof options.track?.userData === "object" || typeof options.clientTrack?.userData === "object") && options.clientTrack)
|
|
190
|
-
options.clientTrack.userData = {
|
|
190
|
+
options.clientTrack.userData = {
|
|
191
|
+
...(typeof options?.clientTrack?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(options?.clientTrack?.requester || {}) } : {}),
|
|
192
|
+
...options?.clientTrack.userData,
|
|
193
|
+
...options.track?.userData,
|
|
194
|
+
};
|
|
191
195
|
options.track = {
|
|
192
196
|
encoded: options.clientTrack?.encoded,
|
|
193
197
|
requester: options.clientTrack?.requester,
|
|
@@ -209,16 +213,11 @@ class Player {
|
|
|
209
213
|
const track = Object.fromEntries(Object.entries({
|
|
210
214
|
encoded: options.track.encoded,
|
|
211
215
|
identifier: options.track.identifier,
|
|
216
|
+
userData: {
|
|
217
|
+
...(typeof options?.track?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(options?.track?.requester || {}) } : {}),
|
|
218
|
+
...options.track.userData,
|
|
219
|
+
}
|
|
212
220
|
}).filter(v => typeof v[1] !== "undefined"));
|
|
213
|
-
if (typeof options.track.userData === "object")
|
|
214
|
-
track.userData = {
|
|
215
|
-
...(options.track.userData || {})
|
|
216
|
-
};
|
|
217
|
-
if (typeof options?.track?.requester === "object")
|
|
218
|
-
track.userData = {
|
|
219
|
-
...(track.userData || {}),
|
|
220
|
-
requester: this.LavalinkManager.utils.getTransformedRequester(options?.track?.requester || {})
|
|
221
|
-
};
|
|
222
221
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
223
222
|
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerPlayWithTrackReplace, {
|
|
224
223
|
state: "log",
|
|
@@ -254,7 +253,11 @@ class Player {
|
|
|
254
253
|
// resolve the unresolved track
|
|
255
254
|
await this.queue.current.resolve(this);
|
|
256
255
|
if (typeof options.track?.userData === "object" && this.queue.current)
|
|
257
|
-
this.queue.current.userData = {
|
|
256
|
+
this.queue.current.userData = {
|
|
257
|
+
...(typeof this.queue.current?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(this.queue.current?.requester || {}) } : {}),
|
|
258
|
+
...this.queue.current?.userData,
|
|
259
|
+
...options.track?.userData
|
|
260
|
+
};
|
|
258
261
|
}
|
|
259
262
|
catch (error) {
|
|
260
263
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
@@ -292,7 +295,11 @@ class Player {
|
|
|
292
295
|
track: {
|
|
293
296
|
encoded: this.queue.current?.encoded || null,
|
|
294
297
|
// identifier: options.identifier,
|
|
295
|
-
userData:
|
|
298
|
+
userData: {
|
|
299
|
+
...(typeof this.queue.current?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(this.queue.current?.requester || {}) } : {}),
|
|
300
|
+
...options?.track?.userData,
|
|
301
|
+
...this.queue.current?.userData,
|
|
302
|
+
},
|
|
296
303
|
},
|
|
297
304
|
volume: this.lavalinkVolume,
|
|
298
305
|
position: options?.position ?? 0,
|
|
@@ -705,7 +712,7 @@ class Player {
|
|
|
705
712
|
await this.node.request(endpoint, r => {
|
|
706
713
|
r.method = "PATCH";
|
|
707
714
|
r.headers["Content-Type"] = "application/json";
|
|
708
|
-
r.body =
|
|
715
|
+
r.body = (0, Utils_1.safeStringify)({
|
|
709
716
|
voice: {
|
|
710
717
|
token: voiceData.token,
|
|
711
718
|
endpoint: voiceData.endpoint,
|
|
@@ -207,15 +207,16 @@ class Queue {
|
|
|
207
207
|
* @returns {number} Queue-Size (for the next Tracks)
|
|
208
208
|
*/
|
|
209
209
|
async add(TrackOrTracks, index) {
|
|
210
|
-
if (typeof index === "number" && index >= 0 && index < this.tracks.length)
|
|
211
|
-
return await this.splice(index, 0,
|
|
210
|
+
if (typeof index === "number" && index >= 0 && index < this.tracks.length) {
|
|
211
|
+
return await this.splice(index, 0, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
212
|
+
}
|
|
212
213
|
const oldStored = typeof this.queueChanges?.tracksAdd === "function" ? this.utils.toJSON() : null;
|
|
213
214
|
// add the track(s)
|
|
214
|
-
this.tracks.push(...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
215
|
+
this.tracks.push(...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
215
216
|
// log if available
|
|
216
217
|
if (typeof this.queueChanges?.tracksAdd === "function")
|
|
217
218
|
try {
|
|
218
|
-
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), this.tracks.length, oldStored, this.utils.toJSON());
|
|
219
|
+
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), this.tracks.length, oldStored, this.utils.toJSON());
|
|
219
220
|
}
|
|
220
221
|
catch { /* */ }
|
|
221
222
|
// save the queue
|
|
@@ -241,11 +242,11 @@ class Queue {
|
|
|
241
242
|
// Log if available
|
|
242
243
|
if ((TrackOrTracks) && typeof this.queueChanges?.tracksAdd === "function")
|
|
243
244
|
try {
|
|
244
|
-
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), index, oldStored, this.utils.toJSON());
|
|
245
|
+
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), index, oldStored, this.utils.toJSON());
|
|
245
246
|
}
|
|
246
247
|
catch { /* */ }
|
|
247
248
|
// remove the tracks (and add the new ones)
|
|
248
|
-
let spliced = TrackOrTracks ? this.tracks.splice(index, amount, ...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v))) : this.tracks.splice(index, amount);
|
|
249
|
+
let spliced = TrackOrTracks ? this.tracks.splice(index, amount, ...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v))) : this.tracks.splice(index, amount);
|
|
249
250
|
// get the spliced array
|
|
250
251
|
spliced = (Array.isArray(spliced) ? spliced : [spliced]);
|
|
251
252
|
// Log if available
|
|
@@ -113,3 +113,4 @@ export declare class MiniMap<K, V> extends Map<K, V> {
|
|
|
113
113
|
map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[];
|
|
114
114
|
}
|
|
115
115
|
export declare function queueTrackEnd(player: Player, dontShiftQueue?: boolean): Promise<Track>;
|
|
116
|
+
export declare function safeStringify(obj: any, padding?: number): string;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MiniMap = exports.ManagerUtils = exports.NodeSymbol = exports.QueueSymbol = exports.UnresolvedTrackSymbol = exports.TrackSymbol = void 0;
|
|
4
4
|
exports.parseLavalinkConnUrl = parseLavalinkConnUrl;
|
|
5
5
|
exports.queueTrackEnd = queueTrackEnd;
|
|
6
|
+
exports.safeStringify = safeStringify;
|
|
6
7
|
const node_url_1 = require("node:url");
|
|
7
8
|
const types_1 = require("node:util/types");
|
|
8
9
|
const Constants_1 = require("./Constants.js");
|
|
@@ -452,7 +453,7 @@ async function queueTrackEnd(player, dontShiftQueue = false) {
|
|
|
452
453
|
// and if repeatMode == queue, add it back to the queue!
|
|
453
454
|
if (player.repeatMode === "queue" && player.queue.current)
|
|
454
455
|
player.queue.tracks.push(player.queue.current);
|
|
455
|
-
// change the current Track to the next upcoming one
|
|
456
|
+
// change the current Track to the next upcoming one
|
|
456
457
|
const nextSong = dontShiftQueue ? null : player.queue.tracks.shift();
|
|
457
458
|
try {
|
|
458
459
|
if (nextSong && player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
@@ -547,3 +548,20 @@ async function getClosestTrack(data, player) {
|
|
|
547
548
|
return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
|
|
548
549
|
});
|
|
549
550
|
}
|
|
551
|
+
function safeStringify(obj, padding = 0) {
|
|
552
|
+
const seen = new WeakSet();
|
|
553
|
+
return JSON.stringify(obj, (key, value) => {
|
|
554
|
+
if (typeof value === "function")
|
|
555
|
+
return undefined; // Funktion skippen
|
|
556
|
+
if (typeof value === "symbol")
|
|
557
|
+
return undefined; // Symbol skippen
|
|
558
|
+
if (typeof value === "bigint")
|
|
559
|
+
return value.toString(); // BigInt to String
|
|
560
|
+
if (typeof value === "object" && value !== null) {
|
|
561
|
+
if (seen.has(value))
|
|
562
|
+
return "[Circular]";
|
|
563
|
+
seen.add(value);
|
|
564
|
+
}
|
|
565
|
+
return value;
|
|
566
|
+
}, padding);
|
|
567
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { audioOutputsData } from "./Constants.js";
|
|
2
|
+
import { safeStringify } from "./Utils.js";
|
|
2
3
|
/**
|
|
3
4
|
* The FilterManager for each player
|
|
4
5
|
*/
|
|
@@ -670,7 +671,7 @@ export class FilterManager {
|
|
|
670
671
|
async setEQ(bands) {
|
|
671
672
|
if (!Array.isArray(bands))
|
|
672
673
|
bands = [bands];
|
|
673
|
-
if (!bands.length || !bands.every((band) =>
|
|
674
|
+
if (!bands.length || !bands.every((band) => safeStringify(Object.keys(band).sort()) === '["band","gain"]'))
|
|
674
675
|
throw new TypeError("Bands must be a non-empty object array containing 'band' and 'gain' properties.");
|
|
675
676
|
for (const { band, gain } of bands)
|
|
676
677
|
this.equalizerBands[band] = { band, gain };
|
|
@@ -690,6 +691,6 @@ export class FilterManager {
|
|
|
690
691
|
}
|
|
691
692
|
/** Clears the equalizer bands. */
|
|
692
693
|
async clearEQ() {
|
|
693
|
-
return this.setEQ(
|
|
694
|
+
return this.setEQ(Array.from({ length: 15 }, () => ({ band: 0, gain: 0 })));
|
|
694
695
|
}
|
|
695
696
|
}
|
|
@@ -2,9 +2,9 @@ import { EventEmitter } from "events";
|
|
|
2
2
|
import { NodeManager } from "./NodeManager.js";
|
|
3
3
|
import { Player } from "./Player.js";
|
|
4
4
|
import { ManagerUtils, MiniMap } from "./Utils.js";
|
|
5
|
+
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils.js";
|
|
5
6
|
import type { BotClientOptions, LavalinkManagerEvents, ManagerOptions } from "./Types/Manager.js";
|
|
6
7
|
import type { PlayerOptions } from "./Types/Player.js";
|
|
7
|
-
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils.js";
|
|
8
8
|
export declare class LavalinkManager extends EventEmitter {
|
|
9
9
|
/**
|
|
10
10
|
* Emit an event
|
|
@@ -3,7 +3,7 @@ import { DebugEvents, DestroyReasons } from "./Constants.js";
|
|
|
3
3
|
import { NodeManager } from "./NodeManager.js";
|
|
4
4
|
import { Player } from "./Player.js";
|
|
5
5
|
import { DefaultQueueStore } from "./Queue.js";
|
|
6
|
-
import { ManagerUtils, MiniMap } from "./Utils.js";
|
|
6
|
+
import { ManagerUtils, MiniMap, safeStringify } from "./Utils.js";
|
|
7
7
|
export class LavalinkManager extends EventEmitter {
|
|
8
8
|
/**
|
|
9
9
|
* Emit an event
|
|
@@ -68,7 +68,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
68
68
|
applyOptions(options) {
|
|
69
69
|
this.options = {
|
|
70
70
|
client: {
|
|
71
|
-
...
|
|
71
|
+
...options?.client,
|
|
72
72
|
id: options?.client?.id,
|
|
73
73
|
username: options?.client?.username ?? "lavalink-client"
|
|
74
74
|
},
|
|
@@ -311,7 +311,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
311
311
|
// oldPlayer.connected is operational. you could also do oldPlayer.voice?.token
|
|
312
312
|
if (oldPlayer.voiceChannelId === "string" && oldPlayer.connected && !oldPlayer.get("internal_destroywithoutdisconnect")) {
|
|
313
313
|
if (!this.options?.advancedOptions?.debugOptions?.playerDestroy?.dontThrowError)
|
|
314
|
-
throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${
|
|
314
|
+
throw new Error(`Use Player#destroy() not LavalinkManager#deletePlayer() to stop the Player ${safeStringify(oldPlayer.toJSON?.())}`);
|
|
315
315
|
else if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
316
316
|
this.emit("debug", DebugEvents.PlayerDeleteInsteadOfDestroy, {
|
|
317
317
|
state: "warn",
|
|
@@ -353,13 +353,13 @@ export class LavalinkManager extends EventEmitter {
|
|
|
353
353
|
if (this.initiated)
|
|
354
354
|
return this;
|
|
355
355
|
clientData = clientData ?? {};
|
|
356
|
-
this.options.client = { ...
|
|
356
|
+
this.options.client = { ...this.options?.client, ...clientData };
|
|
357
357
|
if (!this.options?.client.id)
|
|
358
358
|
throw new Error('"client.id" is not set. Pass it in Manager#init() or as a option in the constructor.');
|
|
359
359
|
if (typeof this.options?.client.id !== "string")
|
|
360
360
|
throw new Error('"client.id" set is not type of "string"');
|
|
361
361
|
let success = 0;
|
|
362
|
-
for (const node of
|
|
362
|
+
for (const node of this.nodeManager.nodes.values()) {
|
|
363
363
|
try {
|
|
364
364
|
await node.connect();
|
|
365
365
|
success++;
|
|
@@ -436,7 +436,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
436
436
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
437
437
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
438
438
|
state: "warn",
|
|
439
|
-
message: `No Update data found in payload :: ${
|
|
439
|
+
message: `No Update data found in payload :: ${safeStringify(data, 2)}`,
|
|
440
440
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
441
441
|
});
|
|
442
442
|
}
|
|
@@ -448,7 +448,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
448
448
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
449
449
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
450
450
|
state: "error",
|
|
451
|
-
message: `No 'token' nor 'session_id' found in payload :: ${
|
|
451
|
+
message: `No 'token' nor 'session_id' found in payload :: ${safeStringify(data, 2)}`,
|
|
452
452
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
453
453
|
});
|
|
454
454
|
}
|
|
@@ -461,7 +461,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
461
461
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
462
462
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
463
463
|
state: "warn",
|
|
464
|
-
message: `No Lavalink Player found via key: 'guild_id' of update-data :: ${
|
|
464
|
+
message: `No Lavalink Player found via key: 'guild_id' of update-data :: ${safeStringify(update, 2)}`,
|
|
465
465
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
466
466
|
});
|
|
467
467
|
}
|
|
@@ -488,7 +488,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
488
488
|
if (!sessionId2Use) {
|
|
489
489
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
490
490
|
state: "error",
|
|
491
|
-
message: `Can't send updatePlayer for voice token session - Missing sessionId :: ${
|
|
491
|
+
message: `Can't send updatePlayer for voice token session - Missing sessionId :: ${safeStringify({ voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, update, playerVoice: player.voice }, 2)}`,
|
|
492
492
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
493
493
|
});
|
|
494
494
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
@@ -508,7 +508,7 @@ export class LavalinkManager extends EventEmitter {
|
|
|
508
508
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
509
509
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
510
510
|
state: "log",
|
|
511
|
-
message: `Sent updatePlayer for voice token session :: ${
|
|
511
|
+
message: `Sent updatePlayer for voice token session :: ${safeStringify({ voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, update, playerVoice: player.voice }, 2)}`,
|
|
512
512
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
513
513
|
});
|
|
514
514
|
}
|
|
@@ -541,12 +541,12 @@ export class LavalinkManager extends EventEmitter {
|
|
|
541
541
|
if (this.options?.advancedOptions?.enableDebugEvents) {
|
|
542
542
|
this.emit("debug", DebugEvents.NoAudioDebug, {
|
|
543
543
|
state: "warn",
|
|
544
|
-
message: `Function to assing sessionId provided, but no found in Payload: ${
|
|
544
|
+
message: `Function to assing sessionId provided, but no found in Payload: ${safeStringify({ update, playerVoice: player.voice }, 2)}`,
|
|
545
545
|
functionLayer: "LavalinkManager > sendRawData()",
|
|
546
546
|
});
|
|
547
547
|
}
|
|
548
548
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
549
|
-
console.debug(`Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Function to assing sessionId provided, but no found in Payload: ${
|
|
549
|
+
console.debug(`Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Function to assing sessionId provided, but no found in Payload: ${safeStringify(update, 2)}`);
|
|
550
550
|
}
|
|
551
551
|
player.voiceChannelId = update.channel_id;
|
|
552
552
|
const selfMuteChanged = typeof update.self_mute === "boolean" && player.voiceState.selfMute !== update.self_mute;
|
|
@@ -137,7 +137,7 @@ export const SourceLinksRegexes = {
|
|
|
137
137
|
/** From tidal */
|
|
138
138
|
tidal: /https?:\/\/?(?:www\.)?(?:tidal|listen)\.tidal\.com\/(?<type>track|album|playlist|artist)\/(?<identifier>[a-zA-Z0-9-_]+)/,
|
|
139
139
|
/** From jiosaavn-plugin */
|
|
140
|
-
jiosaavn: /(https?:\/\/)(www\.)?jiosaavn\.com\/(?<type>song|album|featured|artist)\/([a-zA-Z0-9-_
|
|
140
|
+
jiosaavn: /(https?:\/\/)(www\.)?jiosaavn\.com\/(?<type>song|album|featured|artist)\/([a-zA-Z0-9-_/,]+)/,
|
|
141
141
|
/** FROM DUNCTE BOT PLUGIN */
|
|
142
142
|
tiktok: /https:\/\/www\.tiktok\.com\//,
|
|
143
143
|
mixcloud: /https:\/\/www\.mixcloud\.com\//,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils.js";
|
|
1
2
|
import type { Player } from "./Player.js";
|
|
2
3
|
import type { DestroyReasonsType, DisconnectReasonsType } from "./Types/Player.js";
|
|
3
4
|
import type { Track } from "./Types/Track.js";
|
|
4
|
-
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils.js";
|
|
5
5
|
import type { NodeManager } from "./NodeManager.js";
|
|
6
6
|
import type { BaseNodeStats, LavalinkInfo, LavalinkNodeOptions, LyricsResult, ModifyRequest, NodeStats, SponsorBlockSegment } from "./Types/Node.js";
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAbsolute } from "path";
|
|
2
2
|
import WebSocket from "ws";
|
|
3
3
|
import { DebugEvents, DestroyReasons, validSponsorBlocks } from "./Constants.js";
|
|
4
|
-
import { NodeSymbol, queueTrackEnd } from "./Utils.js";
|
|
4
|
+
import { NodeSymbol, queueTrackEnd, safeStringify } from "./Utils.js";
|
|
5
5
|
/**
|
|
6
6
|
* Lavalink Node creator class
|
|
7
7
|
*/
|
|
@@ -130,7 +130,7 @@ export class LavalinkNode {
|
|
|
130
130
|
if (["DELETE", "PUT"].includes(options.method))
|
|
131
131
|
return;
|
|
132
132
|
if (response.status === 404)
|
|
133
|
-
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${
|
|
133
|
+
throw new Error(`Node Request resulted into an error, request-PATH: ${options.path} | headers: ${safeStringify(response.headers)}`);
|
|
134
134
|
return parseAsText ? await response.text() : await response.json();
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
@@ -262,7 +262,7 @@ export class LavalinkNode {
|
|
|
262
262
|
const res = await this.request(`/sessions/${this.sessionId}/players/${data.guildId}`, r => {
|
|
263
263
|
r.method = "PATCH";
|
|
264
264
|
r.headers["Content-Type"] = "application/json";
|
|
265
|
-
r.body =
|
|
265
|
+
r.body = safeStringify(data.playerOptions);
|
|
266
266
|
if (data.noReplace) {
|
|
267
267
|
const url = new URL(`${this.restAddress}${r.path}`);
|
|
268
268
|
url.searchParams.append("noReplace", data.noReplace === true && typeof data.noReplace === "boolean" ? "true" : "false");
|
|
@@ -272,7 +272,7 @@ export class LavalinkNode {
|
|
|
272
272
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
273
273
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.PlayerUpdateSuccess, {
|
|
274
274
|
state: "log",
|
|
275
|
-
message: `Player get's updated with following payload :: ${
|
|
275
|
+
message: `Player get's updated with following payload :: ${safeStringify(data.playerOptions, 3)}`,
|
|
276
276
|
functionLayer: "LavalinkNode > node > updatePlayer()",
|
|
277
277
|
});
|
|
278
278
|
}
|
|
@@ -584,7 +584,7 @@ export class LavalinkNode {
|
|
|
584
584
|
return this.request(`/sessions/${this.sessionId}`, r => {
|
|
585
585
|
r.method = "PATCH";
|
|
586
586
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
587
|
-
r.body =
|
|
587
|
+
r.body = safeStringify(data);
|
|
588
588
|
});
|
|
589
589
|
}
|
|
590
590
|
/**
|
|
@@ -628,7 +628,7 @@ export class LavalinkNode {
|
|
|
628
628
|
// return the decoded + builded tracks
|
|
629
629
|
return await this.request(`/decodetracks`, r => {
|
|
630
630
|
r.method = "POST";
|
|
631
|
-
r.body =
|
|
631
|
+
r.body = safeStringify(encodeds);
|
|
632
632
|
r.headers["Content-Type"] = "application/json";
|
|
633
633
|
}).then((r) => r.map(track => this.NodeManager.LavalinkManager.utils.buildTrack(track, requester)));
|
|
634
634
|
}
|
|
@@ -804,7 +804,7 @@ export class LavalinkNode {
|
|
|
804
804
|
return await this.request(`/routeplanner/free/address`, r => {
|
|
805
805
|
r.method = "POST";
|
|
806
806
|
r.headers["Content-Type"] = "application/json";
|
|
807
|
-
r.body =
|
|
807
|
+
r.body = safeStringify({ address });
|
|
808
808
|
});
|
|
809
809
|
},
|
|
810
810
|
/**
|
|
@@ -1214,6 +1214,9 @@ export class LavalinkNode {
|
|
|
1214
1214
|
return this.queueEnd(player, track, payload);
|
|
1215
1215
|
// If a track had an error while starting
|
|
1216
1216
|
if (["loadFailed", "cleanup"].includes(payload.reason)) {
|
|
1217
|
+
//Dont add tracks if the player is already destroying.
|
|
1218
|
+
if (player.get("internal_destroystatus") === true)
|
|
1219
|
+
return;
|
|
1217
1220
|
await queueTrackEnd(player);
|
|
1218
1221
|
// if no track available, end queue
|
|
1219
1222
|
if (!player.queue.current)
|
|
@@ -1269,7 +1272,7 @@ export class LavalinkNode {
|
|
|
1269
1272
|
// If there are no songs in the queue
|
|
1270
1273
|
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying"))) {
|
|
1271
1274
|
try { //Sometimes the trackStuck event triggers from the Lavalink server, but the track continues playing or resumes after. We explicitly end the track in such cases
|
|
1272
|
-
await player.node.updatePlayer({ guildId: player.guildId, playerOptions: { track: { encoded: null } } }); //trackEnd -> queueEnd
|
|
1275
|
+
await player.node.updatePlayer({ guildId: player.guildId, playerOptions: { track: { encoded: null } } }); //trackEnd -> queueEnd
|
|
1273
1276
|
return;
|
|
1274
1277
|
}
|
|
1275
1278
|
catch {
|
|
@@ -1377,7 +1380,7 @@ export class LavalinkNode {
|
|
|
1377
1380
|
await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
|
|
1378
1381
|
r.method = "PUT";
|
|
1379
1382
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
1380
|
-
r.body =
|
|
1383
|
+
r.body = safeStringify(segments.map(v => v.toLowerCase()));
|
|
1381
1384
|
});
|
|
1382
1385
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1383
1386
|
this.NodeManager.LavalinkManager.emit("debug", DebugEvents.SetSponsorBlock, {
|
|
@@ -2,7 +2,7 @@ import { DebugEvents } from "./Constants.js";
|
|
|
2
2
|
import { bandCampSearch } from "./CustomSearches/BandCampSearch.js";
|
|
3
3
|
import { FilterManager } from "./Filters.js";
|
|
4
4
|
import { Queue, QueueSaver } from "./Queue.js";
|
|
5
|
-
import { queueTrackEnd } from "./Utils.js";
|
|
5
|
+
import { queueTrackEnd, safeStringify } from "./Utils.js";
|
|
6
6
|
export class Player {
|
|
7
7
|
/** Filter Manager per player */
|
|
8
8
|
filterManager;
|
|
@@ -184,7 +184,11 @@ export class Player {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
if ((typeof options.track?.userData === "object" || typeof options.clientTrack?.userData === "object") && options.clientTrack)
|
|
187
|
-
options.clientTrack.userData = {
|
|
187
|
+
options.clientTrack.userData = {
|
|
188
|
+
...(typeof options?.clientTrack?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(options?.clientTrack?.requester || {}) } : {}),
|
|
189
|
+
...options?.clientTrack.userData,
|
|
190
|
+
...options.track?.userData,
|
|
191
|
+
};
|
|
188
192
|
options.track = {
|
|
189
193
|
encoded: options.clientTrack?.encoded,
|
|
190
194
|
requester: options.clientTrack?.requester,
|
|
@@ -206,16 +210,11 @@ export class Player {
|
|
|
206
210
|
const track = Object.fromEntries(Object.entries({
|
|
207
211
|
encoded: options.track.encoded,
|
|
208
212
|
identifier: options.track.identifier,
|
|
213
|
+
userData: {
|
|
214
|
+
...(typeof options?.track?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(options?.track?.requester || {}) } : {}),
|
|
215
|
+
...options.track.userData,
|
|
216
|
+
}
|
|
209
217
|
}).filter(v => typeof v[1] !== "undefined"));
|
|
210
|
-
if (typeof options.track.userData === "object")
|
|
211
|
-
track.userData = {
|
|
212
|
-
...(options.track.userData || {})
|
|
213
|
-
};
|
|
214
|
-
if (typeof options?.track?.requester === "object")
|
|
215
|
-
track.userData = {
|
|
216
|
-
...(track.userData || {}),
|
|
217
|
-
requester: this.LavalinkManager.utils.getTransformedRequester(options?.track?.requester || {})
|
|
218
|
-
};
|
|
219
218
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
220
219
|
this.LavalinkManager.emit("debug", DebugEvents.PlayerPlayWithTrackReplace, {
|
|
221
220
|
state: "log",
|
|
@@ -251,7 +250,11 @@ export class Player {
|
|
|
251
250
|
// resolve the unresolved track
|
|
252
251
|
await this.queue.current.resolve(this);
|
|
253
252
|
if (typeof options.track?.userData === "object" && this.queue.current)
|
|
254
|
-
this.queue.current.userData = {
|
|
253
|
+
this.queue.current.userData = {
|
|
254
|
+
...(typeof this.queue.current?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(this.queue.current?.requester || {}) } : {}),
|
|
255
|
+
...this.queue.current?.userData,
|
|
256
|
+
...options.track?.userData
|
|
257
|
+
};
|
|
255
258
|
}
|
|
256
259
|
catch (error) {
|
|
257
260
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
@@ -289,7 +292,11 @@ export class Player {
|
|
|
289
292
|
track: {
|
|
290
293
|
encoded: this.queue.current?.encoded || null,
|
|
291
294
|
// identifier: options.identifier,
|
|
292
|
-
userData:
|
|
295
|
+
userData: {
|
|
296
|
+
...(typeof this.queue.current?.requester === "object" ? { requester: this.LavalinkManager.utils.getTransformedRequester(this.queue.current?.requester || {}) } : {}),
|
|
297
|
+
...options?.track?.userData,
|
|
298
|
+
...this.queue.current?.userData,
|
|
299
|
+
},
|
|
293
300
|
},
|
|
294
301
|
volume: this.lavalinkVolume,
|
|
295
302
|
position: options?.position ?? 0,
|
|
@@ -702,7 +709,7 @@ export class Player {
|
|
|
702
709
|
await this.node.request(endpoint, r => {
|
|
703
710
|
r.method = "PATCH";
|
|
704
711
|
r.headers["Content-Type"] = "application/json";
|
|
705
|
-
r.body =
|
|
712
|
+
r.body = safeStringify({
|
|
706
713
|
voice: {
|
|
707
714
|
token: voiceData.token,
|
|
708
715
|
endpoint: voiceData.endpoint,
|
|
@@ -202,15 +202,16 @@ export class Queue {
|
|
|
202
202
|
* @returns {number} Queue-Size (for the next Tracks)
|
|
203
203
|
*/
|
|
204
204
|
async add(TrackOrTracks, index) {
|
|
205
|
-
if (typeof index === "number" && index >= 0 && index < this.tracks.length)
|
|
206
|
-
return await this.splice(index, 0,
|
|
205
|
+
if (typeof index === "number" && index >= 0 && index < this.tracks.length) {
|
|
206
|
+
return await this.splice(index, 0, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
207
|
+
}
|
|
207
208
|
const oldStored = typeof this.queueChanges?.tracksAdd === "function" ? this.utils.toJSON() : null;
|
|
208
209
|
// add the track(s)
|
|
209
|
-
this.tracks.push(...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
210
|
+
this.tracks.push(...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)));
|
|
210
211
|
// log if available
|
|
211
212
|
if (typeof this.queueChanges?.tracksAdd === "function")
|
|
212
213
|
try {
|
|
213
|
-
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), this.tracks.length, oldStored, this.utils.toJSON());
|
|
214
|
+
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), this.tracks.length, oldStored, this.utils.toJSON());
|
|
214
215
|
}
|
|
215
216
|
catch { /* */ }
|
|
216
217
|
// save the queue
|
|
@@ -236,11 +237,11 @@ export class Queue {
|
|
|
236
237
|
// Log if available
|
|
237
238
|
if ((TrackOrTracks) && typeof this.queueChanges?.tracksAdd === "function")
|
|
238
239
|
try {
|
|
239
|
-
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), index, oldStored, this.utils.toJSON());
|
|
240
|
+
this.queueChanges.tracksAdd(this.guildId, (Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v)), index, oldStored, this.utils.toJSON());
|
|
240
241
|
}
|
|
241
242
|
catch { /* */ }
|
|
242
243
|
// remove the tracks (and add the new ones)
|
|
243
|
-
let spliced = TrackOrTracks ? this.tracks.splice(index, amount, ...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v))) : this.tracks.splice(index, amount);
|
|
244
|
+
let spliced = TrackOrTracks ? this.tracks.splice(index, amount, ...(Array.isArray(TrackOrTracks) ? TrackOrTracks : [TrackOrTracks]).flat(2).filter(v => this.managerUtils.isTrack(v) || this.managerUtils.isUnresolvedTrack(v))) : this.tracks.splice(index, amount);
|
|
244
245
|
// get the spliced array
|
|
245
246
|
spliced = (Array.isArray(spliced) ? spliced : [spliced]);
|
|
246
247
|
// Log if available
|
|
@@ -113,3 +113,4 @@ export declare class MiniMap<K, V> extends Map<K, V> {
|
|
|
113
113
|
map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[];
|
|
114
114
|
}
|
|
115
115
|
export declare function queueTrackEnd(player: Player, dontShiftQueue?: boolean): Promise<Track>;
|
|
116
|
+
export declare function safeStringify(obj: any, padding?: number): string;
|
|
@@ -445,7 +445,7 @@ export async function queueTrackEnd(player, dontShiftQueue = false) {
|
|
|
445
445
|
// and if repeatMode == queue, add it back to the queue!
|
|
446
446
|
if (player.repeatMode === "queue" && player.queue.current)
|
|
447
447
|
player.queue.tracks.push(player.queue.current);
|
|
448
|
-
// change the current Track to the next upcoming one
|
|
448
|
+
// change the current Track to the next upcoming one
|
|
449
449
|
const nextSong = dontShiftQueue ? null : player.queue.tracks.shift();
|
|
450
450
|
try {
|
|
451
451
|
if (nextSong && player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
@@ -540,3 +540,20 @@ async function getClosestTrack(data, player) {
|
|
|
540
540
|
return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
|
|
541
541
|
});
|
|
542
542
|
}
|
|
543
|
+
export function safeStringify(obj, padding = 0) {
|
|
544
|
+
const seen = new WeakSet();
|
|
545
|
+
return JSON.stringify(obj, (key, value) => {
|
|
546
|
+
if (typeof value === "function")
|
|
547
|
+
return undefined; // Funktion skippen
|
|
548
|
+
if (typeof value === "symbol")
|
|
549
|
+
return undefined; // Symbol skippen
|
|
550
|
+
if (typeof value === "bigint")
|
|
551
|
+
return value.toString(); // BigInt to String
|
|
552
|
+
if (typeof value === "object" && value !== null) {
|
|
553
|
+
if (seen.has(value))
|
|
554
|
+
return "[Circular]";
|
|
555
|
+
seen.add(value);
|
|
556
|
+
}
|
|
557
|
+
return value;
|
|
558
|
+
}, padding);
|
|
559
|
+
}
|
|
@@ -2,9 +2,9 @@ import { EventEmitter } from "events";
|
|
|
2
2
|
import { NodeManager } from "./NodeManager";
|
|
3
3
|
import { Player } from "./Player";
|
|
4
4
|
import { ManagerUtils, MiniMap } from "./Utils";
|
|
5
|
+
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils";
|
|
5
6
|
import type { BotClientOptions, LavalinkManagerEvents, ManagerOptions } from "./Types/Manager";
|
|
6
7
|
import type { PlayerOptions } from "./Types/Player";
|
|
7
|
-
import type { ChannelDeletePacket, VoicePacket, VoiceServer, VoiceState } from "./Types/Utils";
|
|
8
8
|
export declare class LavalinkManager extends EventEmitter {
|
|
9
9
|
/**
|
|
10
10
|
* Emit an event
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils";
|
|
1
2
|
import type { Player } from "./Player";
|
|
2
3
|
import type { DestroyReasonsType, DisconnectReasonsType } from "./Types/Player";
|
|
3
4
|
import type { Track } from "./Types/Track";
|
|
4
|
-
import type { Base64, InvalidLavalinkRestRequest, LavalinkPlayer, LavaSearchQuery, LavaSearchResponse, PlayerUpdateInfo, RoutePlanner, SearchQuery, SearchResult, Session } from "./Types/Utils";
|
|
5
5
|
import type { NodeManager } from "./NodeManager";
|
|
6
6
|
import type { BaseNodeStats, LavalinkInfo, LavalinkNodeOptions, LyricsResult, ModifyRequest, NodeStats, SponsorBlockSegment } from "./Types/Node";
|
|
7
7
|
/**
|
|
@@ -113,3 +113,4 @@ export declare class MiniMap<K, V> extends Map<K, V> {
|
|
|
113
113
|
map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[];
|
|
114
114
|
}
|
|
115
115
|
export declare function queueTrackEnd(player: Player, dontShiftQueue?: boolean): Promise<Track>;
|
|
116
|
+
export declare function safeStringify(obj: any, padding?: number): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lavalink-client",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.3",
|
|
4
4
|
"description": "Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -59,18 +59,18 @@
|
|
|
59
59
|
"homepage": "https://tomato6966.github.io/lavalink-client/",
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@eslint/eslintrc": "^3.3.1",
|
|
62
|
-
"@eslint/js": "^9.
|
|
63
|
-
"@types/node": "^22.
|
|
62
|
+
"@eslint/js": "^9.27.0",
|
|
63
|
+
"@types/node": "^22.15.18",
|
|
64
64
|
"@types/ws": "^8.18.1",
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
66
|
-
"@typescript-eslint/parser": "^8.
|
|
67
|
-
"eslint": "^9.
|
|
68
|
-
"tsc-alias": "^1.8.
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
|
66
|
+
"@typescript-eslint/parser": "^8.32.1",
|
|
67
|
+
"eslint": "^9.27.0",
|
|
68
|
+
"tsc-alias": "^1.8.16",
|
|
69
69
|
"typescript": "^5.8.3"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"tslib": "^2.8.1",
|
|
73
|
-
"ws": "^8.18.
|
|
73
|
+
"ws": "^8.18.2"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=18.0.0",
|