magmastream 2.9.0-dev.2 → 2.9.0-dev.21
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 +2 -2
- package/dist/index.d.ts +169 -46
- package/dist/storage/CollectionPlayerStore.js +77 -0
- package/dist/storage/RedisPlayerStore.js +156 -0
- package/dist/structures/Manager.js +419 -179
- package/dist/structures/Node.js +47 -38
- package/dist/structures/Player.js +59 -55
- package/dist/structures/Queue.js +92 -32
- package/dist/structures/RedisQueue.js +309 -0
- package/dist/structures/Utils.js +400 -343
- package/dist/utils/managerCheck.js +8 -5
- package/package.json +12 -11
package/dist/structures/Node.js
CHANGED
|
@@ -235,11 +235,11 @@ class Node {
|
|
|
235
235
|
identifier: this.options.identifier,
|
|
236
236
|
address: this.address,
|
|
237
237
|
sessionId: this.sessionId,
|
|
238
|
-
playerCount: this.manager.players.filter((p) => p.node == this).size,
|
|
238
|
+
playerCount: (await this.manager.players.filter((p) => p.node == this)).size,
|
|
239
239
|
};
|
|
240
240
|
this.manager.emit(Manager_1.ManagerEventTypes.Debug, `[NODE] Destroying node: ${JSON.stringify(debugInfo)}`);
|
|
241
241
|
// Automove all players connected to that node
|
|
242
|
-
const players = this.manager.players.filter((p) => p.node == this);
|
|
242
|
+
const players = await this.manager.players.filter((p) => p.node == this);
|
|
243
243
|
if (players.size) {
|
|
244
244
|
players.forEach(async (player) => {
|
|
245
245
|
await player.autoMoveNode();
|
|
@@ -405,7 +405,7 @@ class Node {
|
|
|
405
405
|
this.stats = { ...payload };
|
|
406
406
|
break;
|
|
407
407
|
case "playerUpdate":
|
|
408
|
-
player = this.manager.players.get(payload.guildId);
|
|
408
|
+
player = await this.manager.players.get(payload.guildId);
|
|
409
409
|
if (player && player.node.options.identifier !== this.options.identifier) {
|
|
410
410
|
return;
|
|
411
411
|
}
|
|
@@ -413,7 +413,7 @@ class Node {
|
|
|
413
413
|
player.position = payload.state.position || 0;
|
|
414
414
|
break;
|
|
415
415
|
case "event":
|
|
416
|
-
player = this.manager.players.get(payload.guildId);
|
|
416
|
+
player = await this.manager.players.get(payload.guildId);
|
|
417
417
|
if (player && player.node.options.identifier !== this.options.identifier) {
|
|
418
418
|
return;
|
|
419
419
|
}
|
|
@@ -452,10 +452,10 @@ class Node {
|
|
|
452
452
|
async handleEvent(payload) {
|
|
453
453
|
if (!payload.guildId)
|
|
454
454
|
return;
|
|
455
|
-
const player = this.manager.players.get(payload.guildId);
|
|
455
|
+
const player = await this.manager.players.get(payload.guildId);
|
|
456
456
|
if (!player)
|
|
457
457
|
return;
|
|
458
|
-
const track = player.queue.
|
|
458
|
+
const track = await player.queue.getCurrent();
|
|
459
459
|
const type = payload.type;
|
|
460
460
|
let error;
|
|
461
461
|
switch (type) {
|
|
@@ -478,16 +478,16 @@ class Node {
|
|
|
478
478
|
this.socketClosed(player, payload);
|
|
479
479
|
break;
|
|
480
480
|
case "SegmentsLoaded":
|
|
481
|
-
this.sponsorBlockSegmentLoaded(player,
|
|
481
|
+
this.sponsorBlockSegmentLoaded(player, track, payload);
|
|
482
482
|
break;
|
|
483
483
|
case "SegmentSkipped":
|
|
484
|
-
this.sponsorBlockSegmentSkipped(player,
|
|
484
|
+
this.sponsorBlockSegmentSkipped(player, track, payload);
|
|
485
485
|
break;
|
|
486
486
|
case "ChaptersLoaded":
|
|
487
|
-
this.sponsorBlockChaptersLoaded(player,
|
|
487
|
+
this.sponsorBlockChaptersLoaded(player, track, payload);
|
|
488
488
|
break;
|
|
489
489
|
case "ChapterStarted":
|
|
490
|
-
this.sponsorBlockChapterStarted(player,
|
|
490
|
+
this.sponsorBlockChapterStarted(player, track, payload);
|
|
491
491
|
break;
|
|
492
492
|
default:
|
|
493
493
|
error = new Error(`Node#event unknown event '${type}'.`);
|
|
@@ -536,12 +536,14 @@ class Node {
|
|
|
536
536
|
async trackEnd(player, track, payload) {
|
|
537
537
|
const { reason } = payload;
|
|
538
538
|
const skipFlag = player.get("skipFlag");
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
539
|
+
const previous = await player.queue.getPrevious();
|
|
540
|
+
const current = await player.queue.getCurrent();
|
|
541
|
+
if (!skipFlag && (previous.length === 0 || (previous[0] && previous[0].track !== current?.track))) {
|
|
542
|
+
await player.queue.addPrevious(current);
|
|
543
|
+
const updated = await player.queue.getPrevious();
|
|
544
|
+
if (updated.length > this.manager.options.maxPreviousTracks) {
|
|
545
|
+
const trimmed = updated.slice(0, this.manager.options.maxPreviousTracks);
|
|
546
|
+
await player.queue.setPrevious(trimmed);
|
|
545
547
|
}
|
|
546
548
|
}
|
|
547
549
|
const oldPlayer = player;
|
|
@@ -557,7 +559,7 @@ class Node {
|
|
|
557
559
|
break;
|
|
558
560
|
case Utils_1.TrackEndReasonTypes.Stopped:
|
|
559
561
|
// If the track was forcibly replaced
|
|
560
|
-
if (player.queue.
|
|
562
|
+
if (await player.queue.size()) {
|
|
561
563
|
await this.playNextTrack(player, track, payload);
|
|
562
564
|
}
|
|
563
565
|
else {
|
|
@@ -571,7 +573,7 @@ class Node {
|
|
|
571
573
|
break;
|
|
572
574
|
}
|
|
573
575
|
// If there's another track in the queue
|
|
574
|
-
if (player.queue.
|
|
576
|
+
if (await player.queue.size()) {
|
|
575
577
|
await this.playNextTrack(player, track, payload);
|
|
576
578
|
}
|
|
577
579
|
else {
|
|
@@ -602,13 +604,16 @@ class Node {
|
|
|
602
604
|
*/
|
|
603
605
|
async handleAutoplay(player, attempt = 0) {
|
|
604
606
|
// If autoplay is not enabled or all attempts have failed, early exit
|
|
605
|
-
if (!player.isAutoplay || attempt
|
|
607
|
+
if (!player.isAutoplay || attempt > player.autoplayTries || !(await player.queue.getPrevious()).length)
|
|
606
608
|
return false;
|
|
607
|
-
const
|
|
609
|
+
const PreviousQueue = await player.queue.getPrevious();
|
|
610
|
+
const lastTrack = PreviousQueue?.at(-1);
|
|
608
611
|
lastTrack.requester = player.get("Internal_BotUser");
|
|
609
|
-
|
|
612
|
+
if (!lastTrack)
|
|
613
|
+
return false;
|
|
614
|
+
const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(lastTrack);
|
|
610
615
|
if (tracks.length) {
|
|
611
|
-
player.queue.add(tracks[0]);
|
|
616
|
+
await player.queue.add(tracks[0]);
|
|
612
617
|
await player.play();
|
|
613
618
|
return true;
|
|
614
619
|
}
|
|
@@ -629,8 +634,8 @@ class Node {
|
|
|
629
634
|
* @private
|
|
630
635
|
*/
|
|
631
636
|
async handleFailedTrack(player, track, payload) {
|
|
632
|
-
player.queue.
|
|
633
|
-
if (!player.queue.
|
|
637
|
+
await player.queue.setCurrent(await player.queue.dequeue());
|
|
638
|
+
if (!(await player.queue.getCurrent())) {
|
|
634
639
|
await this.queueEnd(player, track, payload);
|
|
635
640
|
return;
|
|
636
641
|
}
|
|
@@ -655,24 +660,28 @@ class Node {
|
|
|
655
660
|
const { playNextOnEnd } = this.manager.options;
|
|
656
661
|
if (trackRepeat) {
|
|
657
662
|
// Prevent duplicate repeat insertion
|
|
658
|
-
if (queue[0] !== queue.
|
|
659
|
-
queue.
|
|
663
|
+
if (queue[0] !== (await queue.getCurrent())) {
|
|
664
|
+
await queue.enqueueFront(await queue.getCurrent());
|
|
660
665
|
}
|
|
661
666
|
}
|
|
662
667
|
else if (queueRepeat) {
|
|
663
668
|
// Prevent duplicate queue insertion
|
|
664
|
-
if (queue[queue.
|
|
665
|
-
queue.add(queue.
|
|
669
|
+
if (queue[(await queue.size()) - 1] !== (await queue.getCurrent())) {
|
|
670
|
+
await queue.add(await queue.getCurrent());
|
|
666
671
|
}
|
|
667
672
|
}
|
|
668
673
|
// Move to the next track
|
|
669
|
-
queue.
|
|
674
|
+
await queue.setCurrent(await queue.dequeue());
|
|
670
675
|
// Emit track end event
|
|
671
676
|
this.manager.emit(Manager_1.ManagerEventTypes.TrackEnd, player, track, payload);
|
|
672
677
|
// If the track was stopped manually and no more tracks exist, end the queue
|
|
673
|
-
if (payload.reason === Utils_1.TrackEndReasonTypes.Stopped
|
|
674
|
-
await
|
|
675
|
-
|
|
678
|
+
if (payload.reason === Utils_1.TrackEndReasonTypes.Stopped) {
|
|
679
|
+
const next = await queue.dequeue();
|
|
680
|
+
await queue.setCurrent(next ?? null);
|
|
681
|
+
if (!next) {
|
|
682
|
+
await this.queueEnd(player, track, payload);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
676
685
|
}
|
|
677
686
|
// If autoplay is enabled, play the next track
|
|
678
687
|
if (playNextOnEnd)
|
|
@@ -691,7 +700,7 @@ class Node {
|
|
|
691
700
|
*/
|
|
692
701
|
async playNextTrack(player, track, payload) {
|
|
693
702
|
// Shift the queue to set the next track as current
|
|
694
|
-
player.queue.
|
|
703
|
+
await player.queue.setCurrent(await player.queue.dequeue());
|
|
695
704
|
// Emit the track end event
|
|
696
705
|
this.manager.emit(Manager_1.ManagerEventTypes.TrackEnd, player, track, payload);
|
|
697
706
|
// If autoplay is enabled, play the next track
|
|
@@ -708,19 +717,19 @@ class Node {
|
|
|
708
717
|
* @returns {Promise<void>} A promise that resolves when the queue end processing is complete.
|
|
709
718
|
*/
|
|
710
719
|
async queueEnd(player, track, payload) {
|
|
711
|
-
player.queue.
|
|
720
|
+
await player.queue.setCurrent(null);
|
|
712
721
|
if (!player.isAutoplay) {
|
|
713
722
|
player.playing = false;
|
|
714
723
|
this.manager.emit(Manager_1.ManagerEventTypes.QueueEnd, player, track, payload);
|
|
715
724
|
return;
|
|
716
725
|
}
|
|
717
|
-
let
|
|
726
|
+
let attempt = 1;
|
|
718
727
|
let success = false;
|
|
719
|
-
while (
|
|
720
|
-
success = await this.handleAutoplay(player,
|
|
728
|
+
while (attempt <= player.autoplayTries) {
|
|
729
|
+
success = await this.handleAutoplay(player, attempt);
|
|
721
730
|
if (success)
|
|
722
731
|
return;
|
|
723
|
-
|
|
732
|
+
attempt++;
|
|
724
733
|
}
|
|
725
734
|
// If all attempts fail, reset the player state and emit queueEnd
|
|
726
735
|
player.playing = false;
|
|
@@ -9,6 +9,7 @@ const Queue_1 = require("./Queue");
|
|
|
9
9
|
const Utils_1 = require("./Utils");
|
|
10
10
|
const _ = tslib_1.__importStar(require("lodash"));
|
|
11
11
|
const playerCheck_1 = tslib_1.__importDefault(require("../utils/playerCheck"));
|
|
12
|
+
const RedisQueue_1 = require("./RedisQueue");
|
|
12
13
|
class Player {
|
|
13
14
|
options;
|
|
14
15
|
/** The Queue for the Player. */
|
|
@@ -50,7 +51,7 @@ class Player {
|
|
|
50
51
|
/** The autoplay state of the player. */
|
|
51
52
|
isAutoplay = false;
|
|
52
53
|
/** The number of times to try autoplay before emitting queueEnd. */
|
|
53
|
-
autoplayTries =
|
|
54
|
+
autoplayTries = 3;
|
|
54
55
|
static _manager;
|
|
55
56
|
data = {};
|
|
56
57
|
dynamicLoopInterval = null;
|
|
@@ -67,10 +68,6 @@ class Player {
|
|
|
67
68
|
this.manager = Utils_1.Structure.get("Player")._manager;
|
|
68
69
|
if (!this.manager)
|
|
69
70
|
throw new RangeError("Manager has not been initiated.");
|
|
70
|
-
// If a player with the same guild ID already exists, return it.
|
|
71
|
-
if (this.manager.players.has(options.guildId)) {
|
|
72
|
-
return this.manager.players.get(options.guildId);
|
|
73
|
-
}
|
|
74
71
|
// Check the player options for errors.
|
|
75
72
|
(0, playerCheck_1.default)(options);
|
|
76
73
|
// Set the guild ID and voice state.
|
|
@@ -91,8 +88,15 @@ class Player {
|
|
|
91
88
|
if (!this.node)
|
|
92
89
|
throw new RangeError("No available nodes.");
|
|
93
90
|
// Initialize the queue with the guild ID and manager.
|
|
94
|
-
this.
|
|
95
|
-
|
|
91
|
+
if (this.manager.options.stateStorage.type === Manager_1.StateStorageType.Redis) {
|
|
92
|
+
this.queue = new RedisQueue_1.RedisQueue(this.guildId, this.manager);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.queue = new Queue_1.Queue(this.guildId, this.manager);
|
|
96
|
+
}
|
|
97
|
+
if (this.queue instanceof Queue_1.Queue) {
|
|
98
|
+
this.queue.previous = [];
|
|
99
|
+
}
|
|
96
100
|
// Add the player to the manager's player collection.
|
|
97
101
|
this.manager.players.set(options.guildId, this);
|
|
98
102
|
// Set the initial volume.
|
|
@@ -220,20 +224,27 @@ class Player {
|
|
|
220
224
|
*/
|
|
221
225
|
async destroy(disconnect = true) {
|
|
222
226
|
const oldPlayer = this ? { ...this } : null;
|
|
227
|
+
if (this.state === Utils_1.StateTypes.Destroying || this.state === Utils_1.StateTypes.Disconnected) {
|
|
228
|
+
console.debug(`[Player#destroy] Already destroying/destroyed for ${this.guildId}`);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
223
231
|
this.state = Utils_1.StateTypes.Destroying;
|
|
224
232
|
if (disconnect) {
|
|
225
|
-
await this.disconnect()
|
|
233
|
+
await this.disconnect().catch((err) => {
|
|
234
|
+
console.warn(`[Player#destroy] Failed to disconnect player ${this.guildId}:`, err);
|
|
235
|
+
});
|
|
226
236
|
}
|
|
227
|
-
await this.node.rest.destroyPlayer(this.guildId)
|
|
228
|
-
|
|
237
|
+
await this.node.rest.destroyPlayer(this.guildId).catch((err) => {
|
|
238
|
+
console.warn(`[Player#destroy] REST failed to destroy player ${this.guildId}:`, err);
|
|
239
|
+
});
|
|
240
|
+
await this.queue.clear();
|
|
241
|
+
await this.queue.clearPrevious();
|
|
242
|
+
await this.queue.setCurrent(null);
|
|
229
243
|
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, null, {
|
|
230
244
|
changeType: Manager_1.PlayerStateEventTypes.PlayerDestroy,
|
|
231
245
|
});
|
|
232
246
|
this.manager.emit(Manager_1.ManagerEventTypes.PlayerDestroy, this);
|
|
233
247
|
const deleted = this.manager.players.delete(this.guildId);
|
|
234
|
-
if (!deleted) {
|
|
235
|
-
console.warn(`Failed to delete player with guildId: ${this.guildId}`);
|
|
236
|
-
}
|
|
237
248
|
return deleted;
|
|
238
249
|
}
|
|
239
250
|
/**
|
|
@@ -307,9 +318,9 @@ class Player {
|
|
|
307
318
|
}
|
|
308
319
|
async play(optionsOrTrack, playOptions) {
|
|
309
320
|
if (typeof optionsOrTrack !== "undefined" && Utils_1.TrackUtils.validate(optionsOrTrack)) {
|
|
310
|
-
this.queue.
|
|
321
|
+
await this.queue.setCurrent(optionsOrTrack);
|
|
311
322
|
}
|
|
312
|
-
if (!this.queue.
|
|
323
|
+
if (!(await this.queue.getCurrent()))
|
|
313
324
|
throw new RangeError("No current track.");
|
|
314
325
|
const finalOptions = playOptions
|
|
315
326
|
? playOptions
|
|
@@ -319,7 +330,7 @@ class Player {
|
|
|
319
330
|
await this.node.rest.updatePlayer({
|
|
320
331
|
guildId: this.guildId,
|
|
321
332
|
data: {
|
|
322
|
-
encodedTrack: this.queue.
|
|
333
|
+
encodedTrack: (await this.queue.getCurrent()).track,
|
|
323
334
|
...finalOptions,
|
|
324
335
|
},
|
|
325
336
|
});
|
|
@@ -375,7 +386,7 @@ class Player {
|
|
|
375
386
|
* @returns {Promise<Track[]>} - Array of recommended tracks.
|
|
376
387
|
*/
|
|
377
388
|
async getRecommendedTracks(track) {
|
|
378
|
-
const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(
|
|
389
|
+
const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(track);
|
|
379
390
|
return tracks;
|
|
380
391
|
}
|
|
381
392
|
/**
|
|
@@ -509,13 +520,13 @@ class Player {
|
|
|
509
520
|
* @throws {TypeError} If the repeat parameter is not a boolean.
|
|
510
521
|
* @throws {RangeError} If the queue size is less than or equal to 1.
|
|
511
522
|
*/
|
|
512
|
-
setDynamicRepeat(repeat, ms) {
|
|
523
|
+
async setDynamicRepeat(repeat, ms) {
|
|
513
524
|
// Validate the repeat parameter
|
|
514
525
|
if (typeof repeat !== "boolean") {
|
|
515
526
|
throw new TypeError('Repeat can only be "true" or "false".');
|
|
516
527
|
}
|
|
517
528
|
// Ensure the queue has more than one track for dynamic repeat
|
|
518
|
-
if (this.queue.size <= 1) {
|
|
529
|
+
if ((await this.queue.size()) <= 1) {
|
|
519
530
|
throw new RangeError("The queue size must be greater than 1.");
|
|
520
531
|
}
|
|
521
532
|
// Clone the current player state for comparison
|
|
@@ -526,15 +537,14 @@ class Player {
|
|
|
526
537
|
this.queueRepeat = false;
|
|
527
538
|
this.dynamicRepeat = true;
|
|
528
539
|
// Set an interval to shuffle the queue periodically
|
|
529
|
-
this.dynamicLoopInterval = setInterval(() => {
|
|
540
|
+
this.dynamicLoopInterval = setInterval(async () => {
|
|
530
541
|
if (!this.dynamicRepeat)
|
|
531
542
|
return;
|
|
532
543
|
// Shuffle the queue and replace it with the shuffled tracks
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
});
|
|
544
|
+
const tracks = await this.queue.getTracks();
|
|
545
|
+
const shuffled = _.shuffle(tracks);
|
|
546
|
+
await this.queue.clear();
|
|
547
|
+
await this.queue.add(shuffled);
|
|
538
548
|
}, ms);
|
|
539
549
|
// Store the ms value
|
|
540
550
|
this.dynamicRepeatIntervalMs = ms;
|
|
@@ -565,9 +575,9 @@ class Player {
|
|
|
565
575
|
*/
|
|
566
576
|
async restart() {
|
|
567
577
|
// Check if there is a current track in the queue
|
|
568
|
-
if (!this.queue.
|
|
578
|
+
if (!(await this.queue.getCurrent())?.track) {
|
|
569
579
|
// If the queue has tracks, play the next one
|
|
570
|
-
if (this.queue.
|
|
580
|
+
if (await this.queue.size())
|
|
571
581
|
await this.play();
|
|
572
582
|
return this;
|
|
573
583
|
}
|
|
@@ -576,7 +586,7 @@ class Player {
|
|
|
576
586
|
guildId: this.guildId,
|
|
577
587
|
data: {
|
|
578
588
|
position: 0,
|
|
579
|
-
encodedTrack: this.queue.
|
|
589
|
+
encodedTrack: (await this.queue.getCurrent())?.track,
|
|
580
590
|
},
|
|
581
591
|
});
|
|
582
592
|
return this;
|
|
@@ -591,10 +601,10 @@ class Player {
|
|
|
591
601
|
const oldPlayer = { ...this };
|
|
592
602
|
let removedTracks = [];
|
|
593
603
|
if (typeof amount === "number" && amount > 1) {
|
|
594
|
-
if (amount > this.queue.
|
|
604
|
+
if (amount > (await this.queue.size()))
|
|
595
605
|
throw new RangeError("Cannot skip more than the queue length.");
|
|
596
|
-
removedTracks = this.queue.
|
|
597
|
-
this.queue.
|
|
606
|
+
removedTracks = await this.queue.getSlice(0, amount - 1);
|
|
607
|
+
await this.queue.modifyAt(0, amount - 1);
|
|
598
608
|
}
|
|
599
609
|
this.node.rest.updatePlayer({
|
|
600
610
|
guildId: this.guildId,
|
|
@@ -653,22 +663,17 @@ class Player {
|
|
|
653
663
|
* @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
|
|
654
664
|
*/
|
|
655
665
|
async previous() {
|
|
656
|
-
//
|
|
657
|
-
|
|
666
|
+
// Get and remove the most recent previous track
|
|
667
|
+
const lastTrack = await this.queue.popPrevious();
|
|
668
|
+
if (!lastTrack) {
|
|
658
669
|
throw new Error("No previous track available.");
|
|
659
670
|
}
|
|
660
671
|
// Capture the current state of the player before making changes.
|
|
661
672
|
const oldPlayer = { ...this };
|
|
662
|
-
//
|
|
663
|
-
// let currentTrackBeforeChange: Track | null = this.queue.current ? (this.queue.current as Track) : null;
|
|
664
|
-
// Get the last played track and remove it from the history
|
|
665
|
-
const lastTrack = this.queue.previous.pop();
|
|
666
|
-
// Set the skip flag to true to prevent the onTrackEnd event from playing the next track.
|
|
673
|
+
// Set skip flag so trackEnd doesn't add current to previous
|
|
667
674
|
this.set("skipFlag", true);
|
|
668
675
|
await this.play(lastTrack);
|
|
669
|
-
//
|
|
670
|
-
// if (currentTrackBeforeChange) this.queue.push(currentTrackBeforeChange);
|
|
671
|
-
// Emit a player state update event indicating the track change to previous.
|
|
676
|
+
// Emit state update
|
|
672
677
|
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this, {
|
|
673
678
|
changeType: Manager_1.PlayerStateEventTypes.TrackChange,
|
|
674
679
|
details: {
|
|
@@ -676,7 +681,6 @@ class Player {
|
|
|
676
681
|
track: lastTrack,
|
|
677
682
|
},
|
|
678
683
|
});
|
|
679
|
-
// Reset the skip flag.
|
|
680
684
|
this.set("skipFlag", false);
|
|
681
685
|
return this;
|
|
682
686
|
}
|
|
@@ -688,7 +692,7 @@ class Player {
|
|
|
688
692
|
* @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
|
|
689
693
|
*/
|
|
690
694
|
async seek(position) {
|
|
691
|
-
if (!this.queue.
|
|
695
|
+
if (!(await this.queue.getCurrent()))
|
|
692
696
|
return undefined;
|
|
693
697
|
position = Number(position);
|
|
694
698
|
// Check if the position is valid.
|
|
@@ -698,8 +702,8 @@ class Player {
|
|
|
698
702
|
// Get the old player state.
|
|
699
703
|
const oldPlayer = this ? { ...this } : null;
|
|
700
704
|
// Clamp the position to ensure it is within the valid range.
|
|
701
|
-
if (position < 0 || position > this.queue.
|
|
702
|
-
position = Math.max(Math.min(position, this.queue.
|
|
705
|
+
if (position < 0 || position > (await this.queue.getCurrent()).duration) {
|
|
706
|
+
position = Math.max(Math.min(position, (await this.queue.getCurrent()).duration), 0);
|
|
703
707
|
}
|
|
704
708
|
// Update the player's position.
|
|
705
709
|
this.position = position;
|
|
@@ -764,7 +768,7 @@ class Player {
|
|
|
764
768
|
try {
|
|
765
769
|
const playerPosition = this.position;
|
|
766
770
|
const { sessionId, event: { token, endpoint }, } = this.voiceState;
|
|
767
|
-
const currentTrack = this.queue.
|
|
771
|
+
const currentTrack = (await this.queue.getCurrent()) ? await this.queue.getCurrent() : null;
|
|
768
772
|
await this.node.rest.destroyPlayer(this.guildId).catch(() => { });
|
|
769
773
|
this.manager.players.delete(this.guildId);
|
|
770
774
|
this.node = node;
|
|
@@ -795,7 +799,7 @@ class Player {
|
|
|
795
799
|
if (!newOptions.textChannelId)
|
|
796
800
|
throw new Error("Text channel ID is required");
|
|
797
801
|
// Check if a player already exists for the new guild
|
|
798
|
-
let newPlayer = this.manager.
|
|
802
|
+
let newPlayer = this.manager.getPlayer(newOptions.guildId);
|
|
799
803
|
// If the player already exists and force is false, return the existing player
|
|
800
804
|
if (newPlayer && !force)
|
|
801
805
|
return newPlayer;
|
|
@@ -806,9 +810,9 @@ class Player {
|
|
|
806
810
|
volume: this.volume,
|
|
807
811
|
position: this.position,
|
|
808
812
|
queue: {
|
|
809
|
-
current: this.queue.
|
|
810
|
-
tracks: [...this.queue],
|
|
811
|
-
previous: [...this.queue.
|
|
813
|
+
current: await this.queue.getCurrent(),
|
|
814
|
+
tracks: [...(await this.queue.getTracks())],
|
|
815
|
+
previous: [...(await this.queue.getPrevious())],
|
|
812
816
|
},
|
|
813
817
|
trackRepeat: this.trackRepeat,
|
|
814
818
|
queueRepeat: this.queueRepeat,
|
|
@@ -841,9 +845,9 @@ class Player {
|
|
|
841
845
|
encodedTrack: oldPlayerProperties.queue.current?.track,
|
|
842
846
|
},
|
|
843
847
|
});
|
|
844
|
-
clonedPlayer.queue.
|
|
845
|
-
clonedPlayer.queue.
|
|
846
|
-
clonedPlayer.queue.add(oldPlayerProperties.queue.tracks);
|
|
848
|
+
await clonedPlayer.queue.setCurrent(oldPlayerProperties.queue.current);
|
|
849
|
+
await clonedPlayer.queue.addPrevious(oldPlayerProperties.queue.previous);
|
|
850
|
+
await clonedPlayer.queue.add(oldPlayerProperties.queue.tracks);
|
|
847
851
|
clonedPlayer.filters = oldPlayerProperties.filters;
|
|
848
852
|
clonedPlayer.isAutoplay = oldPlayerProperties.isAutoplay;
|
|
849
853
|
clonedPlayer.nowPlayingMessage = oldPlayerProperties.nowPlayingMessage;
|
|
@@ -858,7 +862,7 @@ class Player {
|
|
|
858
862
|
// Debug information
|
|
859
863
|
const debugInfo = {
|
|
860
864
|
success: true,
|
|
861
|
-
message: `Transferred ${clonedPlayer.queue.
|
|
865
|
+
message: `Transferred ${await clonedPlayer.queue.size()} tracks successfully to <#${newOptions.voiceChannelId}> bound to <#${newOptions.textChannelId}>.`,
|
|
862
866
|
player: {
|
|
863
867
|
guildId: clonedPlayer.guildId,
|
|
864
868
|
voiceChannelId: clonedPlayer.voiceChannelId,
|
|
@@ -885,7 +889,7 @@ class Player {
|
|
|
885
889
|
throw new RangeError(`There is no lavalyrics-plugin available in the Lavalink node: ${this.node.options.identifier}`);
|
|
886
890
|
}
|
|
887
891
|
// Fetch the lyrics for the current track from the Lavalink node
|
|
888
|
-
let result = (await this.node.getLyrics(this.queue.
|
|
892
|
+
let result = (await this.node.getLyrics(await this.queue.getCurrent(), skipTrackSource));
|
|
889
893
|
// If no lyrics are found, return a default empty lyrics object
|
|
890
894
|
if (!result) {
|
|
891
895
|
result = {
|