lavalink-client 2.4.3 → 2.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/dist/cjs/structures/Node.js +9 -6
- package/dist/cjs/structures/Player.d.ts +2 -1
- package/dist/cjs/structures/Player.js +81 -18
- package/dist/cjs/structures/Queue.js +7 -7
- package/dist/esm/structures/Node.js +9 -6
- package/dist/esm/structures/Player.d.ts +2 -1
- package/dist/esm/structures/Player.js +81 -18
- package/dist/esm/structures/Queue.js +7 -7
- package/dist/types/structures/Player.d.ts +2 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -790,10 +790,21 @@ if(previousTrack) {
|
|
|
790
790
|
|
|
791
791
|
- Added the new events and configuration to the docs
|
|
792
792
|
|
|
793
|
+
## **Version 2.4.1**
|
|
794
|
+
|
|
795
|
+
- Did some cleanup and comment removal + removed the playerVoiceEmptyStart because it would mean i'd need to add voice-state tracking, which wasn't the plan of doing by the client.
|
|
796
|
+
|
|
797
|
+
## **Verison 2.4.2**
|
|
798
|
+
|
|
799
|
+
- Merged [PR#78](https://github.com/Tomato6966/lavalink-client/pull/78) from @hwangsihu - Added the configs to eslint ignore
|
|
800
|
+
- Merged [PR#80](https://github.com/Tomato6966/lavalink-client/pull/80) from @EvilG-MC - Argument Typo fix in resume event type declaration
|
|
801
|
+
- Merged [PR#83](https://github.com/Tomato6966/lavalink-client/pull/83) from @EvilG-MC - Fix if statement in Node#syncPlayerData() to allow syncing of "single entry objects"
|
|
802
|
+
- Some minor improvements by removing unnecessary spreading
|
|
803
|
+
|
|
793
804
|
## **Version 2.4.3**
|
|
794
805
|
- `managerOptions#playerOptions.onDisconnect.autoReconnect`:
|
|
795
806
|
- Added the option `managerOptions#playerOptions.onDisconnect.autoReconnectOnlyWithTracks` to control wether to try reconnecting only when there are tracks in the queue / current track or not
|
|
796
807
|
- Added a new debug log for that
|
|
797
808
|
- Added the try to play the next track if there is no current track
|
|
798
|
-
|
|
799
|
-
|
|
809
|
+
- *There was a problem trying to auto-reconnect on-Disconnect while the queue was empty, which caused the player to get destroyed by that and log the error in console "`There is no Track in the Queue, nor provided in the PlayOptions`"*
|
|
810
|
+
- *Now you have to handle that case manually if you want to or set autoReconnectOnlyWithTracks to false (default)*
|
|
@@ -142,12 +142,11 @@ class LavalinkNode {
|
|
|
142
142
|
const url = new URL(`${this.restAddress}${options.path}`);
|
|
143
143
|
url.searchParams.append("trace", "true");
|
|
144
144
|
const urlToUse = this.getRequestingUrl(url, options?.extraQueryUrlParams);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const response = await fetch(urlToUse, options);
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
146
|
+
const { path, extraQueryUrlParams, ...fetchOptions } = options; // destructure fetch only options
|
|
147
|
+
const response = await fetch(urlToUse, fetchOptions);
|
|
149
148
|
this.calls++;
|
|
150
|
-
return { response, options:
|
|
149
|
+
return { response, options: options };
|
|
151
150
|
}
|
|
152
151
|
async request(endpoint, modify, parseAsText) {
|
|
153
152
|
if (!this.connected)
|
|
@@ -1160,6 +1159,8 @@ class LavalinkNode {
|
|
|
1160
1159
|
}
|
|
1161
1160
|
/** @private util function for handling trackEnd event */
|
|
1162
1161
|
async trackEnd(player, track, payload) {
|
|
1162
|
+
if (player.get('internal_nodeChanging') === true)
|
|
1163
|
+
return; // Check if nodeChange is in Progress than stop the trackEnd Event from being triggered.
|
|
1163
1164
|
const trackToUse = track || this.getTrackOfPayload(payload);
|
|
1164
1165
|
// If a track was forcibly played
|
|
1165
1166
|
if (payload.reason === "replaced") {
|
|
@@ -1375,6 +1376,8 @@ class LavalinkNode {
|
|
|
1375
1376
|
}
|
|
1376
1377
|
/** private util function for handling the queue end event */
|
|
1377
1378
|
async queueEnd(player, track, payload) {
|
|
1379
|
+
if (player.get('internal_nodeChanging') === true)
|
|
1380
|
+
return; // Check if nodeChange is in Progress than stop the queueEnd Event from being triggered.
|
|
1378
1381
|
// add previous track to the queue!
|
|
1379
1382
|
player.queue.current = null;
|
|
1380
1383
|
player.playing = false;
|
|
@@ -1425,7 +1428,7 @@ class LavalinkNode {
|
|
|
1425
1428
|
}
|
|
1426
1429
|
}
|
|
1427
1430
|
player.set("internal_skipped", false);
|
|
1428
|
-
player.set("internal_autoplayStopPlaying",
|
|
1431
|
+
player.set("internal_autoplayStopPlaying", undefined);
|
|
1429
1432
|
if (track && !track?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
1430
1433
|
player.queue.previous.unshift(track);
|
|
1431
1434
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
@@ -217,8 +217,9 @@ export declare class Player {
|
|
|
217
217
|
/**
|
|
218
218
|
* Move the player on a different Audio-Node
|
|
219
219
|
* @param newNode New Node / New Node Id
|
|
220
|
+
* @param checkSources If it should check if the sources are supported by the new node
|
|
220
221
|
*/
|
|
221
|
-
changeNode(newNode: LavalinkNode | string): Promise<string>;
|
|
222
|
+
changeNode(newNode: LavalinkNode | string, checkSources?: boolean): Promise<string>;
|
|
222
223
|
/** Converts the Player including Queue to a Json state */
|
|
223
224
|
toJSON(): PlayerJson;
|
|
224
225
|
}
|
|
@@ -459,11 +459,11 @@ class Player {
|
|
|
459
459
|
throw new RangeError("Can't skip more than the queue size");
|
|
460
460
|
await this.queue.splice(0, skipTo - 1);
|
|
461
461
|
}
|
|
462
|
-
if (!this.playing)
|
|
462
|
+
if (!this.playing && !this.queue.current)
|
|
463
463
|
return (this.play(), this);
|
|
464
464
|
const now = performance.now();
|
|
465
465
|
this.set("internal_skipped", true);
|
|
466
|
-
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { track: { encoded: null } } });
|
|
466
|
+
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { track: { encoded: null }, paused: false } });
|
|
467
467
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
468
468
|
return this;
|
|
469
469
|
}
|
|
@@ -639,11 +639,37 @@ class Player {
|
|
|
639
639
|
/**
|
|
640
640
|
* Move the player on a different Audio-Node
|
|
641
641
|
* @param newNode New Node / New Node Id
|
|
642
|
+
* @param checkSources If it should check if the sources are supported by the new node
|
|
642
643
|
*/
|
|
643
|
-
async changeNode(newNode) {
|
|
644
|
+
async changeNode(newNode, checkSources = true) {
|
|
644
645
|
const updateNode = typeof newNode === "string" ? this.LavalinkManager.nodeManager.nodes.get(newNode) : newNode;
|
|
645
646
|
if (!updateNode)
|
|
646
647
|
throw new Error("Could not find the new Node");
|
|
648
|
+
if (!updateNode.connected)
|
|
649
|
+
throw new Error("The provided Node is not active or disconnected");
|
|
650
|
+
if (this.node.id === updateNode.id)
|
|
651
|
+
throw new Error("Player is already on the provided Node");
|
|
652
|
+
if (this.get("internal_nodeChanging") === true)
|
|
653
|
+
throw new Error("Player is already changing the node please wait");
|
|
654
|
+
if (checkSources) {
|
|
655
|
+
const isDefaultSource = () => {
|
|
656
|
+
try {
|
|
657
|
+
this.LavalinkManager.utils.validateSourceString(updateNode, this.LavalinkManager.options.playerOptions.defaultSearchPlatform);
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
660
|
+
catch {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
if (!isDefaultSource())
|
|
665
|
+
throw new RangeError(`defaultSearchPlatform "${this.LavalinkManager.options.playerOptions.defaultSearchPlatform}" is not supported by the newNode`);
|
|
666
|
+
if (this.queue.current || this.queue.tracks.length) { // Check if all queued track sources are supported by the new node
|
|
667
|
+
const trackSources = new Set([this.queue.current, ...this.queue.tracks].map(track => track.info.sourceName));
|
|
668
|
+
const missingSources = [...trackSources].filter(source => !updateNode.info.sourceManagers.includes(source));
|
|
669
|
+
if (missingSources.length)
|
|
670
|
+
throw new RangeError(`Sources missing for Node ${updateNode.id}: ${missingSources.join(', ')}`);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
647
673
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
648
674
|
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerChangeNode, {
|
|
649
675
|
state: "log",
|
|
@@ -653,23 +679,60 @@ class Player {
|
|
|
653
679
|
}
|
|
654
680
|
const data = this.toJSON();
|
|
655
681
|
const currentTrack = this.queue.current;
|
|
656
|
-
|
|
682
|
+
const voiceData = this.voice;
|
|
683
|
+
if (!voiceData.endpoint ||
|
|
684
|
+
!voiceData.sessionId ||
|
|
685
|
+
!voiceData.token)
|
|
686
|
+
throw new Error("Voice Data is missing, can't change the node");
|
|
687
|
+
this.set("internal_nodeChanging", true); // This will stop execution of trackEnd or queueEnd event while changing the node
|
|
688
|
+
if (this.node.connected)
|
|
689
|
+
await this.node.destroyPlayer(this.guildId); // destroy the player on the currentNode if it's connected
|
|
657
690
|
this.node = updateNode;
|
|
658
691
|
const now = performance.now();
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
692
|
+
try {
|
|
693
|
+
await this.connect();
|
|
694
|
+
const endpoint = `/sessions/${this.node.sessionId}/players/${this.guildId}`; //Send the VoiceData to the newly connected node.
|
|
695
|
+
await this.node.request(endpoint, r => {
|
|
696
|
+
r.method = "PATCH";
|
|
697
|
+
r.headers["Content-Type"] = "application/json";
|
|
698
|
+
r.body = JSON.stringify({
|
|
699
|
+
voice: {
|
|
700
|
+
token: voiceData.token,
|
|
701
|
+
endpoint: voiceData.endpoint,
|
|
702
|
+
sessionId: voiceData.sessionId
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
if (currentTrack) { // If there is a current track, send it to the new node.
|
|
707
|
+
await this.node.updatePlayer({
|
|
708
|
+
guildId: this.guildId,
|
|
709
|
+
noReplace: false,
|
|
710
|
+
playerOptions: {
|
|
711
|
+
track: currentTrack ?? null,
|
|
712
|
+
position: currentTrack ? data.position : 0,
|
|
713
|
+
volume: data.lavalinkVolume,
|
|
714
|
+
paused: data.paused,
|
|
715
|
+
//filters: { ...data.filters, equalizer: data.equalizer }, Sending filters on nodeChange causes issues (player gets dicsonnected)
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
720
|
+
return this.node.id;
|
|
721
|
+
}
|
|
722
|
+
catch (error) {
|
|
723
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
724
|
+
this.LavalinkManager.emit("debug", Constants_1.DebugEvents.PlayerChangeNode, {
|
|
725
|
+
state: "error",
|
|
726
|
+
error: error,
|
|
727
|
+
message: `Player.changeNode() execution failed`,
|
|
728
|
+
functionLayer: "Player > changeNode()",
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
throw new Error(`Failed to change the node: ${error}`);
|
|
732
|
+
}
|
|
733
|
+
finally {
|
|
734
|
+
this.set("internal_nodeChanging", undefined);
|
|
735
|
+
}
|
|
673
736
|
}
|
|
674
737
|
/** Converts the Player including Queue to a Json state */
|
|
675
738
|
toJSON() {
|
|
@@ -217,7 +217,7 @@ class Queue {
|
|
|
217
217
|
try {
|
|
218
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
219
|
}
|
|
220
|
-
catch
|
|
220
|
+
catch { /* */ }
|
|
221
221
|
// save the queue
|
|
222
222
|
await this.utils.save();
|
|
223
223
|
// return the amount of the tracks
|
|
@@ -243,7 +243,7 @@ class Queue {
|
|
|
243
243
|
try {
|
|
244
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
245
|
}
|
|
246
|
-
catch
|
|
246
|
+
catch { /* */ }
|
|
247
247
|
// remove the tracks (and add the new ones)
|
|
248
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
249
|
// get the spliced array
|
|
@@ -253,7 +253,7 @@ class Queue {
|
|
|
253
253
|
try {
|
|
254
254
|
this.queueChanges.tracksRemoved(this.guildId, spliced, index, oldStored, this.utils.toJSON());
|
|
255
255
|
}
|
|
256
|
-
catch
|
|
256
|
+
catch { /* */ }
|
|
257
257
|
// save the queue
|
|
258
258
|
await this.utils.save();
|
|
259
259
|
// return the things
|
|
@@ -302,7 +302,7 @@ class Queue {
|
|
|
302
302
|
try {
|
|
303
303
|
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
304
304
|
}
|
|
305
|
-
catch
|
|
305
|
+
catch { /* */ }
|
|
306
306
|
await this.utils.save();
|
|
307
307
|
return { removed };
|
|
308
308
|
}
|
|
@@ -321,7 +321,7 @@ class Queue {
|
|
|
321
321
|
try {
|
|
322
322
|
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
323
323
|
}
|
|
324
|
-
catch
|
|
324
|
+
catch { /* */ }
|
|
325
325
|
await this.utils.save();
|
|
326
326
|
return { removed };
|
|
327
327
|
}
|
|
@@ -345,7 +345,7 @@ class Queue {
|
|
|
345
345
|
try {
|
|
346
346
|
this.queueChanges.tracksRemoved(this.guildId, removed, tracksToRemove.map(v => v.i), oldStored, this.utils.toJSON());
|
|
347
347
|
}
|
|
348
|
-
catch
|
|
348
|
+
catch { /* */ }
|
|
349
349
|
await this.utils.save();
|
|
350
350
|
return { removed };
|
|
351
351
|
}
|
|
@@ -363,7 +363,7 @@ class Queue {
|
|
|
363
363
|
try {
|
|
364
364
|
this.queueChanges.tracksRemoved(this.guildId, removed, toRemove, oldStored, this.utils.toJSON());
|
|
365
365
|
}
|
|
366
|
-
catch
|
|
366
|
+
catch { /* */ }
|
|
367
367
|
await this.utils.save();
|
|
368
368
|
return { removed };
|
|
369
369
|
}
|
|
@@ -138,12 +138,11 @@ export class LavalinkNode {
|
|
|
138
138
|
const url = new URL(`${this.restAddress}${options.path}`);
|
|
139
139
|
url.searchParams.append("trace", "true");
|
|
140
140
|
const urlToUse = this.getRequestingUrl(url, options?.extraQueryUrlParams);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const response = await fetch(urlToUse, options);
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
142
|
+
const { path, extraQueryUrlParams, ...fetchOptions } = options; // destructure fetch only options
|
|
143
|
+
const response = await fetch(urlToUse, fetchOptions);
|
|
145
144
|
this.calls++;
|
|
146
|
-
return { response, options:
|
|
145
|
+
return { response, options: options };
|
|
147
146
|
}
|
|
148
147
|
async request(endpoint, modify, parseAsText) {
|
|
149
148
|
if (!this.connected)
|
|
@@ -1156,6 +1155,8 @@ export class LavalinkNode {
|
|
|
1156
1155
|
}
|
|
1157
1156
|
/** @private util function for handling trackEnd event */
|
|
1158
1157
|
async trackEnd(player, track, payload) {
|
|
1158
|
+
if (player.get('internal_nodeChanging') === true)
|
|
1159
|
+
return; // Check if nodeChange is in Progress than stop the trackEnd Event from being triggered.
|
|
1159
1160
|
const trackToUse = track || this.getTrackOfPayload(payload);
|
|
1160
1161
|
// If a track was forcibly played
|
|
1161
1162
|
if (payload.reason === "replaced") {
|
|
@@ -1371,6 +1372,8 @@ export class LavalinkNode {
|
|
|
1371
1372
|
}
|
|
1372
1373
|
/** private util function for handling the queue end event */
|
|
1373
1374
|
async queueEnd(player, track, payload) {
|
|
1375
|
+
if (player.get('internal_nodeChanging') === true)
|
|
1376
|
+
return; // Check if nodeChange is in Progress than stop the queueEnd Event from being triggered.
|
|
1374
1377
|
// add previous track to the queue!
|
|
1375
1378
|
player.queue.current = null;
|
|
1376
1379
|
player.playing = false;
|
|
@@ -1421,7 +1424,7 @@ export class LavalinkNode {
|
|
|
1421
1424
|
}
|
|
1422
1425
|
}
|
|
1423
1426
|
player.set("internal_skipped", false);
|
|
1424
|
-
player.set("internal_autoplayStopPlaying",
|
|
1427
|
+
player.set("internal_autoplayStopPlaying", undefined);
|
|
1425
1428
|
if (track && !track?.pluginInfo?.clientData?.previousTrack) { // If there was a current Track already and repeatmode === true, add it to the queue.
|
|
1426
1429
|
player.queue.previous.unshift(track);
|
|
1427
1430
|
if (player.queue.previous.length > player.queue.options.maxPreviousTracks)
|
|
@@ -217,8 +217,9 @@ export declare class Player {
|
|
|
217
217
|
/**
|
|
218
218
|
* Move the player on a different Audio-Node
|
|
219
219
|
* @param newNode New Node / New Node Id
|
|
220
|
+
* @param checkSources If it should check if the sources are supported by the new node
|
|
220
221
|
*/
|
|
221
|
-
changeNode(newNode: LavalinkNode | string): Promise<string>;
|
|
222
|
+
changeNode(newNode: LavalinkNode | string, checkSources?: boolean): Promise<string>;
|
|
222
223
|
/** Converts the Player including Queue to a Json state */
|
|
223
224
|
toJSON(): PlayerJson;
|
|
224
225
|
}
|
|
@@ -456,11 +456,11 @@ export class Player {
|
|
|
456
456
|
throw new RangeError("Can't skip more than the queue size");
|
|
457
457
|
await this.queue.splice(0, skipTo - 1);
|
|
458
458
|
}
|
|
459
|
-
if (!this.playing)
|
|
459
|
+
if (!this.playing && !this.queue.current)
|
|
460
460
|
return (this.play(), this);
|
|
461
461
|
const now = performance.now();
|
|
462
462
|
this.set("internal_skipped", true);
|
|
463
|
-
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { track: { encoded: null } } });
|
|
463
|
+
await this.node.updatePlayer({ guildId: this.guildId, playerOptions: { track: { encoded: null }, paused: false } });
|
|
464
464
|
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
465
465
|
return this;
|
|
466
466
|
}
|
|
@@ -636,11 +636,37 @@ export class Player {
|
|
|
636
636
|
/**
|
|
637
637
|
* Move the player on a different Audio-Node
|
|
638
638
|
* @param newNode New Node / New Node Id
|
|
639
|
+
* @param checkSources If it should check if the sources are supported by the new node
|
|
639
640
|
*/
|
|
640
|
-
async changeNode(newNode) {
|
|
641
|
+
async changeNode(newNode, checkSources = true) {
|
|
641
642
|
const updateNode = typeof newNode === "string" ? this.LavalinkManager.nodeManager.nodes.get(newNode) : newNode;
|
|
642
643
|
if (!updateNode)
|
|
643
644
|
throw new Error("Could not find the new Node");
|
|
645
|
+
if (!updateNode.connected)
|
|
646
|
+
throw new Error("The provided Node is not active or disconnected");
|
|
647
|
+
if (this.node.id === updateNode.id)
|
|
648
|
+
throw new Error("Player is already on the provided Node");
|
|
649
|
+
if (this.get("internal_nodeChanging") === true)
|
|
650
|
+
throw new Error("Player is already changing the node please wait");
|
|
651
|
+
if (checkSources) {
|
|
652
|
+
const isDefaultSource = () => {
|
|
653
|
+
try {
|
|
654
|
+
this.LavalinkManager.utils.validateSourceString(updateNode, this.LavalinkManager.options.playerOptions.defaultSearchPlatform);
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
657
|
+
catch {
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
if (!isDefaultSource())
|
|
662
|
+
throw new RangeError(`defaultSearchPlatform "${this.LavalinkManager.options.playerOptions.defaultSearchPlatform}" is not supported by the newNode`);
|
|
663
|
+
if (this.queue.current || this.queue.tracks.length) { // Check if all queued track sources are supported by the new node
|
|
664
|
+
const trackSources = new Set([this.queue.current, ...this.queue.tracks].map(track => track.info.sourceName));
|
|
665
|
+
const missingSources = [...trackSources].filter(source => !updateNode.info.sourceManagers.includes(source));
|
|
666
|
+
if (missingSources.length)
|
|
667
|
+
throw new RangeError(`Sources missing for Node ${updateNode.id}: ${missingSources.join(', ')}`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
644
670
|
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
645
671
|
this.LavalinkManager.emit("debug", DebugEvents.PlayerChangeNode, {
|
|
646
672
|
state: "log",
|
|
@@ -650,23 +676,60 @@ export class Player {
|
|
|
650
676
|
}
|
|
651
677
|
const data = this.toJSON();
|
|
652
678
|
const currentTrack = this.queue.current;
|
|
653
|
-
|
|
679
|
+
const voiceData = this.voice;
|
|
680
|
+
if (!voiceData.endpoint ||
|
|
681
|
+
!voiceData.sessionId ||
|
|
682
|
+
!voiceData.token)
|
|
683
|
+
throw new Error("Voice Data is missing, can't change the node");
|
|
684
|
+
this.set("internal_nodeChanging", true); // This will stop execution of trackEnd or queueEnd event while changing the node
|
|
685
|
+
if (this.node.connected)
|
|
686
|
+
await this.node.destroyPlayer(this.guildId); // destroy the player on the currentNode if it's connected
|
|
654
687
|
this.node = updateNode;
|
|
655
688
|
const now = performance.now();
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
689
|
+
try {
|
|
690
|
+
await this.connect();
|
|
691
|
+
const endpoint = `/sessions/${this.node.sessionId}/players/${this.guildId}`; //Send the VoiceData to the newly connected node.
|
|
692
|
+
await this.node.request(endpoint, r => {
|
|
693
|
+
r.method = "PATCH";
|
|
694
|
+
r.headers["Content-Type"] = "application/json";
|
|
695
|
+
r.body = JSON.stringify({
|
|
696
|
+
voice: {
|
|
697
|
+
token: voiceData.token,
|
|
698
|
+
endpoint: voiceData.endpoint,
|
|
699
|
+
sessionId: voiceData.sessionId
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
if (currentTrack) { // If there is a current track, send it to the new node.
|
|
704
|
+
await this.node.updatePlayer({
|
|
705
|
+
guildId: this.guildId,
|
|
706
|
+
noReplace: false,
|
|
707
|
+
playerOptions: {
|
|
708
|
+
track: currentTrack ?? null,
|
|
709
|
+
position: currentTrack ? data.position : 0,
|
|
710
|
+
volume: data.lavalinkVolume,
|
|
711
|
+
paused: data.paused,
|
|
712
|
+
//filters: { ...data.filters, equalizer: data.equalizer }, Sending filters on nodeChange causes issues (player gets dicsonnected)
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
this.ping.lavalink = Math.round((performance.now() - now) / 10) / 100;
|
|
717
|
+
return this.node.id;
|
|
718
|
+
}
|
|
719
|
+
catch (error) {
|
|
720
|
+
if (this.LavalinkManager.options?.advancedOptions?.enableDebugEvents) {
|
|
721
|
+
this.LavalinkManager.emit("debug", DebugEvents.PlayerChangeNode, {
|
|
722
|
+
state: "error",
|
|
723
|
+
error: error,
|
|
724
|
+
message: `Player.changeNode() execution failed`,
|
|
725
|
+
functionLayer: "Player > changeNode()",
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
throw new Error(`Failed to change the node: ${error}`);
|
|
729
|
+
}
|
|
730
|
+
finally {
|
|
731
|
+
this.set("internal_nodeChanging", undefined);
|
|
732
|
+
}
|
|
670
733
|
}
|
|
671
734
|
/** Converts the Player including Queue to a Json state */
|
|
672
735
|
toJSON() {
|
|
@@ -212,7 +212,7 @@ export class Queue {
|
|
|
212
212
|
try {
|
|
213
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
214
|
}
|
|
215
|
-
catch
|
|
215
|
+
catch { /* */ }
|
|
216
216
|
// save the queue
|
|
217
217
|
await this.utils.save();
|
|
218
218
|
// return the amount of the tracks
|
|
@@ -238,7 +238,7 @@ export class Queue {
|
|
|
238
238
|
try {
|
|
239
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
240
|
}
|
|
241
|
-
catch
|
|
241
|
+
catch { /* */ }
|
|
242
242
|
// remove the tracks (and add the new ones)
|
|
243
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
244
|
// get the spliced array
|
|
@@ -248,7 +248,7 @@ export class Queue {
|
|
|
248
248
|
try {
|
|
249
249
|
this.queueChanges.tracksRemoved(this.guildId, spliced, index, oldStored, this.utils.toJSON());
|
|
250
250
|
}
|
|
251
|
-
catch
|
|
251
|
+
catch { /* */ }
|
|
252
252
|
// save the queue
|
|
253
253
|
await this.utils.save();
|
|
254
254
|
// return the things
|
|
@@ -297,7 +297,7 @@ export class Queue {
|
|
|
297
297
|
try {
|
|
298
298
|
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
299
299
|
}
|
|
300
|
-
catch
|
|
300
|
+
catch { /* */ }
|
|
301
301
|
await this.utils.save();
|
|
302
302
|
return { removed };
|
|
303
303
|
}
|
|
@@ -316,7 +316,7 @@ export class Queue {
|
|
|
316
316
|
try {
|
|
317
317
|
this.queueChanges.tracksRemoved(this.guildId, removed, removeQueryTrack, oldStored, this.utils.toJSON());
|
|
318
318
|
}
|
|
319
|
-
catch
|
|
319
|
+
catch { /* */ }
|
|
320
320
|
await this.utils.save();
|
|
321
321
|
return { removed };
|
|
322
322
|
}
|
|
@@ -340,7 +340,7 @@ export class Queue {
|
|
|
340
340
|
try {
|
|
341
341
|
this.queueChanges.tracksRemoved(this.guildId, removed, tracksToRemove.map(v => v.i), oldStored, this.utils.toJSON());
|
|
342
342
|
}
|
|
343
|
-
catch
|
|
343
|
+
catch { /* */ }
|
|
344
344
|
await this.utils.save();
|
|
345
345
|
return { removed };
|
|
346
346
|
}
|
|
@@ -358,7 +358,7 @@ export class Queue {
|
|
|
358
358
|
try {
|
|
359
359
|
this.queueChanges.tracksRemoved(this.guildId, removed, toRemove, oldStored, this.utils.toJSON());
|
|
360
360
|
}
|
|
361
|
-
catch
|
|
361
|
+
catch { /* */ }
|
|
362
362
|
await this.utils.save();
|
|
363
363
|
return { removed };
|
|
364
364
|
}
|
|
@@ -217,8 +217,9 @@ export declare class Player {
|
|
|
217
217
|
/**
|
|
218
218
|
* Move the player on a different Audio-Node
|
|
219
219
|
* @param newNode New Node / New Node Id
|
|
220
|
+
* @param checkSources If it should check if the sources are supported by the new node
|
|
220
221
|
*/
|
|
221
|
-
changeNode(newNode: LavalinkNode | string): Promise<string>;
|
|
222
|
+
changeNode(newNode: LavalinkNode | string, checkSources?: boolean): Promise<string>;
|
|
222
223
|
/** Converts the Player including Queue to a Json state */
|
|
223
224
|
toJSON(): PlayerJson;
|
|
224
225
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lavalink-client",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5",
|
|
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",
|
|
@@ -58,22 +58,22 @@
|
|
|
58
58
|
},
|
|
59
59
|
"homepage": "https://tomato6966.github.io/lavalink-client/",
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@eslint/eslintrc": "^3.
|
|
62
|
-
"@eslint/js": "^9.
|
|
63
|
-
"@types/node": "^22.
|
|
64
|
-
"@types/ws": "^8.5.
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
66
|
-
"@typescript-eslint/parser": "^8.
|
|
67
|
-
"eslint": "^9.
|
|
61
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
62
|
+
"@eslint/js": "^9.18.0",
|
|
63
|
+
"@types/node": "^22.10.5",
|
|
64
|
+
"@types/ws": "^8.5.13",
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
|
66
|
+
"@typescript-eslint/parser": "^8.20.0",
|
|
67
|
+
"eslint": "^9.18.0",
|
|
68
68
|
"tsc-alias": "^1.8.10",
|
|
69
|
-
"typescript": "^5.
|
|
69
|
+
"typescript": "^5.7.3"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"tslib": "^2.
|
|
72
|
+
"tslib": "^2.8.1",
|
|
73
73
|
"ws": "^8.18.0"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=18.0.0",
|
|
77
|
-
"bun": ">=1.
|
|
77
|
+
"bun": ">=1.1.27"
|
|
78
78
|
}
|
|
79
79
|
}
|