lavalink-client 2.5.0 → 2.5.2
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 +15 -15
- package/dist/cjs/structures/LavalinkManagerStatics.js +15 -1
- package/dist/cjs/structures/Node.d.ts +1 -1
- package/dist/cjs/structures/Node.js +20 -10
- package/dist/cjs/structures/Player.js +56 -13
- package/dist/cjs/structures/Types/Manager.d.ts +2 -0
- package/dist/cjs/structures/Types/Track.d.ts +1 -1
- package/dist/cjs/structures/Types/Utils.d.ts +5 -5
- package/dist/cjs/structures/Utils.d.ts +2 -1
- package/dist/cjs/structures/Utils.js +46 -4
- package/dist/esm/structures/Filters.js +3 -2
- package/dist/esm/structures/LavalinkManager.d.ts +1 -1
- package/dist/esm/structures/LavalinkManager.js +16 -16
- package/dist/esm/structures/LavalinkManagerStatics.js +15 -1
- package/dist/esm/structures/Node.d.ts +1 -1
- package/dist/esm/structures/Node.js +21 -11
- package/dist/esm/structures/Player.js +57 -14
- package/dist/esm/structures/Types/Manager.d.ts +2 -0
- package/dist/esm/structures/Types/Track.d.ts +1 -1
- package/dist/esm/structures/Types/Utils.d.ts +5 -5
- package/dist/esm/structures/Utils.d.ts +2 -1
- package/dist/esm/structures/Utils.js +45 -4
- package/dist/types/structures/LavalinkManager.d.ts +1 -1
- package/dist/types/structures/Node.d.ts +1 -1
- package/dist/types/structures/Types/Manager.d.ts +2 -0
- package/dist/types/structures/Types/Track.d.ts +1 -1
- package/dist/types/structures/Types/Utils.d.ts +5 -5
- package/dist/types/structures/Utils.d.ts +2 -1
- package/package.json +11 -11
|
@@ -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,11 +491,11 @@ 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)
|
|
498
|
-
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function,
|
|
498
|
+
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Can't send updatePlayer for voice token session - Missing sessionId", { voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, update, playerVoice: player.voice });
|
|
499
499
|
}
|
|
500
500
|
else {
|
|
501
501
|
await player.node.updatePlayer({
|
|
@@ -505,18 +505,18 @@ class LavalinkManager extends events_1.EventEmitter {
|
|
|
505
505
|
token: update.token,
|
|
506
506
|
endpoint: update.endpoint,
|
|
507
507
|
sessionId: sessionId2Use,
|
|
508
|
-
}
|
|
509
|
-
}
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
510
|
});
|
|
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
|
}
|
|
518
518
|
if (this.options?.advancedOptions?.debugOptions?.noAudio === true)
|
|
519
|
-
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function,
|
|
519
|
+
console.debug("Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Sent updatePlayer for voice token session", { voice: { token: update.token, endpoint: update.endpoint, sessionId: sessionId2Use, }, playerVoice: player.voice, update });
|
|
520
520
|
}
|
|
521
521
|
return;
|
|
522
522
|
}
|
|
@@ -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;
|
|
@@ -51,6 +51,12 @@ exports.DefaultSources = {
|
|
|
51
51
|
"vkmusic": "vksearch",
|
|
52
52
|
"vk music": "vksearch",
|
|
53
53
|
"vkrec": "vkrec",
|
|
54
|
+
"vk": "vksearch",
|
|
55
|
+
// Qobuz (lavasrc)
|
|
56
|
+
"qbsearch": "qbsearch",
|
|
57
|
+
"qobuz": "qbsearch",
|
|
58
|
+
"qbisrc": "qbisrc",
|
|
59
|
+
"qbrec": "qbrec",
|
|
54
60
|
// speak PLUGIN
|
|
55
61
|
"speak": "speak",
|
|
56
62
|
"tts": "tts",
|
|
@@ -73,6 +79,12 @@ exports.DefaultSources = {
|
|
|
73
79
|
"https": "https",
|
|
74
80
|
"link": "link",
|
|
75
81
|
"uri": "uri",
|
|
82
|
+
// tidal
|
|
83
|
+
"tidal": "tdsearch",
|
|
84
|
+
"td": "tdsearch",
|
|
85
|
+
"tidal music": "tdsearch",
|
|
86
|
+
"tdsearch": "tdsearch",
|
|
87
|
+
"tdrec": "tdrec",
|
|
76
88
|
// jiosaavn
|
|
77
89
|
"jiosaavn": "jssearch",
|
|
78
90
|
"js": "jssearch",
|
|
@@ -125,8 +137,10 @@ exports.SourceLinksRegexes = {
|
|
|
125
137
|
SpotifyAlbumRegex: /(https?:\/\/)(www\.)?open\.spotify\.com\/((?<region>[a-zA-Z-]+)\/)?(user\/(?<user>[a-zA-Z0-9-_]+)\/)?album\/(?<identifier>[a-zA-Z0-9-_]+)/,
|
|
126
138
|
AllSpotifyRegex: /(https?:\/\/)(www\.)?open\.spotify\.com\/((?<region>[a-zA-Z-]+)\/)?(user\/(?<user>[a-zA-Z0-9-_]+)\/)?(?<type>track|album|playlist|artist|episode|show)\/(?<identifier>[a-zA-Z0-9-_]+)/,
|
|
127
139
|
appleMusic: /https?:\/\/?(?:www\.)?music\.apple\.com\/(\S+)/,
|
|
140
|
+
/** From tidal */
|
|
141
|
+
tidal: /https?:\/\/?(?:www\.)?(?:tidal|listen)\.tidal\.com\/(?<type>track|album|playlist|artist)\/(?<identifier>[a-zA-Z0-9-_]+)/,
|
|
128
142
|
/** From jiosaavn-plugin */
|
|
129
|
-
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-_/,]+)/,
|
|
130
144
|
/** FROM DUNCTE BOT PLUGIN */
|
|
131
145
|
tiktok: /https:\/\/www\.tiktok\.com\//,
|
|
132
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)
|
|
@@ -1271,8 +1274,15 @@ class LavalinkNode {
|
|
|
1271
1274
|
}
|
|
1272
1275
|
this.NodeManager.LavalinkManager.emit("trackStuck", player, track || this.getTrackOfPayload(payload), payload);
|
|
1273
1276
|
// If there are no songs in the queue
|
|
1274
|
-
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying")))
|
|
1275
|
-
|
|
1277
|
+
if (!player.queue.tracks.length && (player.repeatMode === "off" || player.get("internal_stopPlaying"))) {
|
|
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
|
|
1279
|
+
await player.node.updatePlayer({ guildId: player.guildId, playerOptions: { track: { encoded: null } } }); //trackEnd -> queueEnd
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
catch {
|
|
1283
|
+
return this.queueEnd(player, track || this.getTrackOfPayload(payload), payload);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1276
1286
|
// remove the current track, and enqueue the next one
|
|
1277
1287
|
await (0, Utils_1.queueTrackEnd)(player);
|
|
1278
1288
|
// if no track available, end queue
|
|
@@ -1281,7 +1291,7 @@ class LavalinkNode {
|
|
|
1281
1291
|
}
|
|
1282
1292
|
// play track if autoSkip is true
|
|
1283
1293
|
if (this.NodeManager.LavalinkManager.options.autoSkip && player.queue.current) {
|
|
1284
|
-
player.play({ noReplace:
|
|
1294
|
+
player.play({ track: player.queue.current, noReplace: false }); // Replace the stuck track with the new track.
|
|
1285
1295
|
}
|
|
1286
1296
|
return;
|
|
1287
1297
|
}
|
|
@@ -1374,7 +1384,7 @@ class LavalinkNode {
|
|
|
1374
1384
|
await this.request(`/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, (r) => {
|
|
1375
1385
|
r.method = "PUT";
|
|
1376
1386
|
r.headers = { Authorization: this.options.authorization, 'Content-Type': 'application/json' };
|
|
1377
|
-
r.body =
|
|
1387
|
+
r.body = (0, Utils_1.safeStringify)(segments.map(v => v.toLowerCase()));
|
|
1378
1388
|
});
|
|
1379
1389
|
if (this.NodeManager.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
1380
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) {
|
|
@@ -270,6 +273,8 @@ class Player {
|
|
|
270
273
|
delete options.clientTrack;
|
|
271
274
|
if (options && "track" in options)
|
|
272
275
|
delete options.track;
|
|
276
|
+
// get rid of the current song without shifting the queue, so that the shifting can happen inside the next .play() call when "autoSkipOnResolveError" is true
|
|
277
|
+
await (0, Utils_1.queueTrackEnd)(this, true);
|
|
273
278
|
// try to play the next track if possible
|
|
274
279
|
if (this.LavalinkManager.options?.autoSkipOnResolveError === true && this.queue.tracks[0])
|
|
275
280
|
return this.play(options);
|
|
@@ -290,7 +295,11 @@ class Player {
|
|
|
290
295
|
track: {
|
|
291
296
|
encoded: this.queue.current?.encoded || null,
|
|
292
297
|
// identifier: options.identifier,
|
|
293
|
-
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
|
+
},
|
|
294
303
|
},
|
|
295
304
|
volume: this.lavalinkVolume,
|
|
296
305
|
position: options?.position ?? 0,
|
|
@@ -405,6 +414,8 @@ class Player {
|
|
|
405
414
|
const now = performance.now();
|
|
406
415
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: true } });
|
|
407
416
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
417
|
+
// emit the event
|
|
418
|
+
this.LavalinkManager.emit("playerPaused", this, this.queue.current);
|
|
408
419
|
return this;
|
|
409
420
|
}
|
|
410
421
|
/**
|
|
@@ -417,6 +428,8 @@ class Player {
|
|
|
417
428
|
const now = performance.now();
|
|
418
429
|
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { paused: false } });
|
|
419
430
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
431
|
+
// emit the event
|
|
432
|
+
this.LavalinkManager.emit("playerResumed", this, this.queue.current);
|
|
420
433
|
return this;
|
|
421
434
|
}
|
|
422
435
|
/**
|
|
@@ -682,6 +695,7 @@ class Player {
|
|
|
682
695
|
}
|
|
683
696
|
const data = this.toJSON();
|
|
684
697
|
const currentTrack = this.queue.current;
|
|
698
|
+
const segments = await this.getSponsorBlock().catch(() => []);
|
|
685
699
|
const voiceData = this.voice;
|
|
686
700
|
if (!voiceData.endpoint ||
|
|
687
701
|
!voiceData.sessionId ||
|
|
@@ -698,7 +712,7 @@ class Player {
|
|
|
698
712
|
await this.node.request(endpoint, r => {
|
|
699
713
|
r.method = "PATCH";
|
|
700
714
|
r.headers["Content-Type"] = "application/json";
|
|
701
|
-
r.body =
|
|
715
|
+
r.body = (0, Utils_1.safeStringify)({
|
|
702
716
|
voice: {
|
|
703
717
|
token: voiceData.token,
|
|
704
718
|
endpoint: voiceData.endpoint,
|
|
@@ -706,6 +720,33 @@ class Player {
|
|
|
706
720
|
}
|
|
707
721
|
});
|
|
708
722
|
});
|
|
723
|
+
const hasSponsorBlock = this.node.info?.plugins?.find(v => v.name === "sponsorblock-plugin");
|
|
724
|
+
if (hasSponsorBlock) {
|
|
725
|
+
if (segments.length) {
|
|
726
|
+
await this.setSponsorBlock(segments).catch(error => {
|
|
727
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
728
|
+
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerChangeNode, {
|
|
729
|
+
state: "error",
|
|
730
|
+
error: error,
|
|
731
|
+
message: `Player > changeNode() Unable to set SponsorBlock Segments`,
|
|
732
|
+
functionLayer: "Player > changeNode()",
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
await this.setSponsorBlock().catch(error => {
|
|
739
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
740
|
+
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerChangeNode, {
|
|
741
|
+
state: "error",
|
|
742
|
+
error: error,
|
|
743
|
+
message: `Player > changeNode() Unable to set SponsorBlock Segments`,
|
|
744
|
+
functionLayer: "Player > changeNode()",
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
}
|
|
709
750
|
if (currentTrack) { // If there is a current track, send it to the new node.
|
|
710
751
|
await this.node.updatePlayer({
|
|
711
752
|
guildId: this.guildId,
|
|
@@ -719,6 +760,8 @@ class Player {
|
|
|
719
760
|
}
|
|
720
761
|
});
|
|
721
762
|
}
|
|
763
|
+
this.paused = data.paused;
|
|
764
|
+
this.playing = data.playing;
|
|
722
765
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
723
766
|
return this.node.id;
|
|
724
767
|
}
|
|
@@ -172,6 +172,8 @@ export interface LavalinkManagerEvents {
|
|
|
172
172
|
* @event Manager#LyricsNotFound
|
|
173
173
|
*/
|
|
174
174
|
"LyricsNotFound": (player: Player, track: Track | UnresolvedTrack | null, payload: LyricsNotFoundEvent) => void;
|
|
175
|
+
"playerResumed": (player: Player, track: Track | UnresolvedTrack | null) => void;
|
|
176
|
+
"playerPaused": (player: Player, track: Track | UnresolvedTrack | null) => void;
|
|
175
177
|
}
|
|
176
178
|
/**
|
|
177
179
|
* The Bot client Options needed for the manager
|
|
@@ -4,7 +4,7 @@ import type { Base64 } from "./Utils.js";
|
|
|
4
4
|
/** Sourcenames provided by lavalink server */
|
|
5
5
|
export type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch";
|
|
6
6
|
/** Source Names provided by lava src plugin */
|
|
7
|
-
export type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts";
|
|
7
|
+
export type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz";
|
|
8
8
|
/** Source Names provided by jiosaavan plugin */
|
|
9
9
|
export type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn";
|
|
10
10
|
/** The SourceNames provided by lavalink */
|
|
@@ -11,7 +11,7 @@ export type Opaque<T, K> = T & {
|
|
|
11
11
|
export type IntegerNumber = Opaque<number, 'Int'>;
|
|
12
12
|
/** Opqaue tyep for floatnumber */
|
|
13
13
|
export type FloatNumber = Opaque<number, 'Float'>;
|
|
14
|
-
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec";
|
|
14
|
+
export type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec" | "tdsearch" | "tdrec" | "qbsearch" | "qbisrc" | "qbrec";
|
|
15
15
|
export type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts";
|
|
16
16
|
export type JioSaavnSearchPlatform = "jssearch" | "jsrec";
|
|
17
17
|
export type DuncteSearchPlatform = "speak" | "phsearch" | "pornhub" | "porn" | "tts";
|
|
@@ -20,9 +20,9 @@ export type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc";
|
|
|
20
20
|
export type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | JioSaavnSearchPlatform | LavalinkClientSearchPlatform;
|
|
21
21
|
export type ClientCustomSearchPlatformUtils = "local" | "http" | "https" | "link" | "uri";
|
|
22
22
|
export type ClientSearchPlatform = ClientCustomSearchPlatformUtils | // for file/link requests
|
|
23
|
-
"youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk music" | "vkmusic" | "flowerytts" | "flowery" | "flowery.tts" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform | "js" | "jiosaavn";
|
|
23
|
+
"youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk" | "vk music" | "vkmusic" | "tidal" | "tidal music" | "qobuz" | "flowerytts" | "flowery" | "flowery.tts" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform | "js" | "jiosaavn" | "td" | "tidal" | "tdrec";
|
|
24
24
|
export type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform;
|
|
25
|
-
export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "jiosaavn" | "appleMusic" | "TwitchTv" | "vimeo";
|
|
25
|
+
export type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "jiosaavn" | "appleMusic" | "tidal" | "TwitchTv" | "vimeo";
|
|
26
26
|
export interface PlaylistInfo {
|
|
27
27
|
/** The playlist name */
|
|
28
28
|
name: string;
|
|
@@ -92,13 +92,13 @@ export interface TrackEndEvent extends PlayerEvent {
|
|
|
92
92
|
export interface TrackExceptionEvent extends PlayerEvent {
|
|
93
93
|
type: "TrackExceptionEvent";
|
|
94
94
|
exception?: Exception;
|
|
95
|
-
|
|
95
|
+
track: LavalinkTrack;
|
|
96
96
|
error: string;
|
|
97
97
|
}
|
|
98
98
|
export interface TrackStuckEvent extends PlayerEvent {
|
|
99
99
|
type: "TrackStuckEvent";
|
|
100
100
|
thresholdMs: number;
|
|
101
|
-
|
|
101
|
+
track: LavalinkTrack;
|
|
102
102
|
}
|
|
103
103
|
export interface WebSocketClosedEvent extends PlayerEvent {
|
|
104
104
|
type: "WebSocketClosedEvent";
|
|
@@ -112,4 +112,5 @@ export declare class MiniMap<K, V> extends Map<K, V> {
|
|
|
112
112
|
map<T>(fn: (value: V, key: K, miniMap: this) => T): T[];
|
|
113
113
|
map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[];
|
|
114
114
|
}
|
|
115
|
-
export declare function queueTrackEnd(player: Player): Promise<Track>;
|
|
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");
|
|
@@ -307,6 +308,9 @@ class ManagerUtils {
|
|
|
307
308
|
if (LavalinkManagerStatics_1.SourceLinksRegexes.jiosaavn.test(queryString) && !node.info?.sourceManagers?.includes("jiosaavn")) {
|
|
308
309
|
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'jiosaavn' (via jiosaavn-plugin) enabled");
|
|
309
310
|
}
|
|
311
|
+
if (LavalinkManagerStatics_1.SourceLinksRegexes.tidal.test(queryString) && !node.info?.sourceManagers?.includes("tidal")) {
|
|
312
|
+
throw new Error("Query / Link Provided for this Source but Lavalink Node has not 'tidal' enabled");
|
|
313
|
+
}
|
|
310
314
|
return;
|
|
311
315
|
}
|
|
312
316
|
transformQuery(query) {
|
|
@@ -371,6 +375,12 @@ class ManagerUtils {
|
|
|
371
375
|
if (source === "speak" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.DuncteBot_Plugin.toLowerCase()))) {
|
|
372
376
|
throw new Error("Lavalink Node has not 'speak' enabled, which is required to have 'speak' work");
|
|
373
377
|
}
|
|
378
|
+
if (source === "tdsearch" && !node.info?.sourceManagers?.includes("tidal")) {
|
|
379
|
+
throw new Error("Lavalink Node has not 'tidal' enabled, which is required to have 'tdsearch' work");
|
|
380
|
+
}
|
|
381
|
+
if (source === "tdrec" && !node.info?.sourceManagers?.includes("tidal")) {
|
|
382
|
+
throw new Error("Lavalink Node has not 'tidal' enabled, which is required to have 'tdrec' work");
|
|
383
|
+
}
|
|
374
384
|
if (source === "tts" && !node.info?.plugins?.find(c => c.name.toLowerCase().includes(LavalinkManagerStatics_1.LavalinkPlugins.GoogleCloudTTS.toLowerCase()))) {
|
|
375
385
|
throw new Error("Lavalink Node has not 'tts' enabled, which is required to have 'tts' work");
|
|
376
386
|
}
|
|
@@ -386,6 +396,21 @@ class ManagerUtils {
|
|
|
386
396
|
if (source === "ytsearch" && !node.info?.sourceManagers?.includes("youtube")) {
|
|
387
397
|
throw new Error("Lavalink Node has not 'youtube' enabled, which is required to have 'ytsearch' work");
|
|
388
398
|
}
|
|
399
|
+
if (source === "vksearch" && !node.info?.sourceManagers?.includes("vkmusic")) {
|
|
400
|
+
throw new Error("Lavalink Node has not 'vkmusic' enabled, which is required to have 'vksearch' work");
|
|
401
|
+
}
|
|
402
|
+
if (source === "vkrec" && !node.info?.sourceManagers?.includes("vkmusic")) {
|
|
403
|
+
throw new Error("Lavalink Node has not 'vkmusic' enabled, which is required to have 'vkrec' work");
|
|
404
|
+
}
|
|
405
|
+
if (source === "qbsearch" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
406
|
+
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbsearch' work");
|
|
407
|
+
}
|
|
408
|
+
if (source === "qbisrc" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
409
|
+
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbisrc' work");
|
|
410
|
+
}
|
|
411
|
+
if (source === "qbrec" && !node.info?.sourceManagers?.includes("qobuz")) {
|
|
412
|
+
throw new Error("Lavalink Node has not 'qobuz' enabled, which is required to have 'qbrec' work");
|
|
413
|
+
}
|
|
389
414
|
return;
|
|
390
415
|
}
|
|
391
416
|
}
|
|
@@ -418,7 +443,7 @@ class MiniMap extends Map {
|
|
|
418
443
|
}
|
|
419
444
|
}
|
|
420
445
|
exports.MiniMap = MiniMap;
|
|
421
|
-
async function queueTrackEnd(player) {
|
|
446
|
+
async function queueTrackEnd(player, dontShiftQueue = false) {
|
|
422
447
|
if (player.queue.current && !player.queue.current?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
423
448
|
player.queue.previous.unshift(player.queue.current);
|
|
424
449
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
@@ -429,9 +454,9 @@ async function queueTrackEnd(player) {
|
|
|
429
454
|
if (player.repeatMode === "queue" && player.queue.current)
|
|
430
455
|
player.queue.tracks.push(player.queue.current);
|
|
431
456
|
// change the current Track to the next upcoming one
|
|
432
|
-
const nextSong = player.queue.tracks.shift();
|
|
457
|
+
const nextSong = dontShiftQueue ? null : player.queue.tracks.shift();
|
|
433
458
|
try {
|
|
434
|
-
if (player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
459
|
+
if (nextSong && player.LavalinkManager.utils.isUnresolvedTrack(nextSong))
|
|
435
460
|
await nextSong.resolve(player);
|
|
436
461
|
player.queue.current = nextSong || null;
|
|
437
462
|
// save it in the DB
|
|
@@ -448,7 +473,7 @@ async function queueTrackEnd(player) {
|
|
|
448
473
|
}
|
|
449
474
|
player.LavalinkManager.emit("trackError", player, player.queue.current, error);
|
|
450
475
|
// try to play the next track if possible
|
|
451
|
-
if (player.LavalinkManager.options?.autoSkipOnResolveError === true && player.queue.tracks[0])
|
|
476
|
+
if (!dontShiftQueue && player.LavalinkManager.options?.autoSkipOnResolveError === true && player.queue.tracks[0])
|
|
452
477
|
return queueTrackEnd(player);
|
|
453
478
|
}
|
|
454
479
|
// return the new current Track
|
|
@@ -523,3 +548,20 @@ async function getClosestTrack(data, player) {
|
|
|
523
548
|
return applyUnresolvedData(trackToUse || res.tracks[0], data, player.LavalinkManager.utils);
|
|
524
549
|
});
|
|
525
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
|
+
}
|