magmastream 2.9.0-dev.42 → 2.9.0-dev.43
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/index.d.ts +205 -157
- package/dist/statestorage/JsonQueue.js +1 -1
- package/dist/structures/Filters.js +5 -5
- package/dist/structures/Manager.js +181 -269
- package/dist/structures/Node.js +1 -1
- package/dist/structures/Rest.js +1 -1
- package/dist/structures/Utils.js +111 -1
- package/package.json +1 -1
|
@@ -407,18 +407,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
407
407
|
case Enums_1.StateStorageType.JSON:
|
|
408
408
|
{
|
|
409
409
|
try {
|
|
410
|
-
const playerStateFilePath =
|
|
410
|
+
const playerStateFilePath = Utils_1.PlayerUtils.getPlayerStatePath(guildId);
|
|
411
411
|
const player = this.getPlayer(guildId);
|
|
412
412
|
if (!player || player.state === Enums_1.StateTypes.Disconnected || !player.voiceChannelId) {
|
|
413
|
-
|
|
413
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Skipping save for inactive player: ${guildId}`);
|
|
414
414
|
return;
|
|
415
415
|
}
|
|
416
|
-
const serializedPlayer = await
|
|
416
|
+
const serializedPlayer = await Utils_1.PlayerUtils.serializePlayer(player);
|
|
417
417
|
await promises_1.default.writeFile(playerStateFilePath, JSON.stringify(serializedPlayer, null, 2), "utf-8");
|
|
418
418
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Player state saved: ${guildId}`);
|
|
419
419
|
}
|
|
420
420
|
catch (error) {
|
|
421
|
-
|
|
421
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error saving player state for guild ${guildId}: ${error}`);
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
break;
|
|
@@ -430,7 +430,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
430
430
|
console.warn(`[MANAGER] Skipping save for inactive player: ${guildId}`);
|
|
431
431
|
return;
|
|
432
432
|
}
|
|
433
|
-
const serializedPlayer = await
|
|
433
|
+
const serializedPlayer = await Utils_1.PlayerUtils.serializePlayer(player);
|
|
434
434
|
const redisKey = `${this.options.stateStorage.redisConfig.prefix?.endsWith(":")
|
|
435
435
|
? this.options.stateStorage.redisConfig.prefix
|
|
436
436
|
: this.options.stateStorage.redisConfig.prefix ?? "magmastream:"}playerstore:${guildId}`;
|
|
@@ -438,7 +438,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
438
438
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Player state saved to Redis: ${guildId}`);
|
|
439
439
|
}
|
|
440
440
|
catch (error) {
|
|
441
|
-
|
|
441
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error saving player state to Redis for guild ${guildId}: ${error}`);
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
444
|
break;
|
|
@@ -468,196 +468,198 @@ class Manager extends events_1.EventEmitter {
|
|
|
468
468
|
switch (this.options.stateStorage.type) {
|
|
469
469
|
case Enums_1.StateStorageType.JSON:
|
|
470
470
|
{
|
|
471
|
-
const
|
|
471
|
+
const playersBaseDir = Utils_1.PlayerUtils.getPlayersBaseDir();
|
|
472
472
|
try {
|
|
473
|
-
//
|
|
474
|
-
await promises_1.default.access(
|
|
475
|
-
await promises_1.default.mkdir(
|
|
476
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Created directory: ${
|
|
473
|
+
// Ensure base players directory exists
|
|
474
|
+
await promises_1.default.access(playersBaseDir).catch(async () => {
|
|
475
|
+
await promises_1.default.mkdir(playersBaseDir, { recursive: true });
|
|
476
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Created directory: ${playersBaseDir}`);
|
|
477
477
|
});
|
|
478
|
-
// Read
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
478
|
+
// Read guild directories inside players base dir
|
|
479
|
+
const guildDirs = await promises_1.default.readdir(playersBaseDir, { withFileTypes: true });
|
|
480
|
+
for (const dirent of guildDirs) {
|
|
481
|
+
if (!dirent.isDirectory())
|
|
482
|
+
continue;
|
|
483
|
+
const guildId = dirent.name;
|
|
484
|
+
const stateFilePath = Utils_1.PlayerUtils.getPlayerStatePath(guildId);
|
|
483
485
|
try {
|
|
484
|
-
|
|
485
|
-
await promises_1.default.
|
|
486
|
-
const
|
|
487
|
-
const state = JSON.parse(data);
|
|
486
|
+
await promises_1.default.access(stateFilePath);
|
|
487
|
+
const rawData = await promises_1.default.readFile(stateFilePath, "utf-8");
|
|
488
|
+
const state = JSON.parse(rawData);
|
|
488
489
|
if (state.clusterId !== this.options.clusterId)
|
|
489
490
|
continue;
|
|
490
|
-
if (state
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
491
|
+
if (!state.guildId || state.node?.options?.identifier !== nodeId)
|
|
492
|
+
continue;
|
|
493
|
+
const lavaPlayer = info.find((player) => player.guildId === state.guildId);
|
|
494
|
+
if (!lavaPlayer) {
|
|
495
|
+
await this.destroy(state.guildId);
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
const playerOptions = {
|
|
499
|
+
guildId: state.options.guildId,
|
|
500
|
+
textChannelId: state.options.textChannelId,
|
|
501
|
+
voiceChannelId: state.options.voiceChannelId,
|
|
502
|
+
selfDeafen: state.options.selfDeafen,
|
|
503
|
+
volume: lavaPlayer.volume || state.options.volume,
|
|
504
|
+
nodeIdentifier: nodeId,
|
|
505
|
+
};
|
|
506
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Recreating player: ${state.guildId} from saved file: ${JSON.stringify(state.options)}`);
|
|
507
|
+
const player = this.create(playerOptions);
|
|
508
|
+
await player.node.rest.updatePlayer({
|
|
509
|
+
guildId: state.options.guildId,
|
|
510
|
+
data: {
|
|
511
|
+
voice: {
|
|
512
|
+
token: state.voiceState.event.token,
|
|
513
|
+
endpoint: state.voiceState.event.endpoint,
|
|
514
|
+
sessionId: state.voiceState.sessionId,
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
player.connect();
|
|
519
|
+
const tracks = [];
|
|
520
|
+
const currentTrack = state.queue.current;
|
|
521
|
+
const queueTracks = state.queue.tracks;
|
|
522
|
+
if (state.isAutoplay) {
|
|
523
|
+
Object.setPrototypeOf(state.data.clientUser, { constructor: { name: "User" } });
|
|
524
|
+
player.setAutoplay(true, state.data.clientUser, state.autoplayTries);
|
|
525
|
+
}
|
|
526
|
+
if (lavaPlayer?.track) {
|
|
527
|
+
tracks.push(...queueTracks);
|
|
528
|
+
if (currentTrack && currentTrack.uri === lavaPlayer.track.info.uri) {
|
|
529
|
+
await player.queue.setCurrent(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester));
|
|
494
530
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
voiceChannelId: state.options.voiceChannelId,
|
|
499
|
-
selfDeafen: state.options.selfDeafen,
|
|
500
|
-
volume: lavaPlayer.volume || state.options.volume,
|
|
501
|
-
nodeIdentifier: nodeId,
|
|
502
|
-
};
|
|
503
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Recreating player: ${state.guildId} from saved file: ${JSON.stringify(state.options)}`);
|
|
504
|
-
const player = this.create(playerOptions);
|
|
505
|
-
await player.node.rest.updatePlayer({
|
|
506
|
-
guildId: state.options.guildId,
|
|
507
|
-
data: { voice: { token: state.voiceState.event.token, endpoint: state.voiceState.event.endpoint, sessionId: state.voiceState.sessionId } },
|
|
508
|
-
});
|
|
509
|
-
player.connect();
|
|
510
|
-
const tracks = [];
|
|
511
|
-
const currentTrack = state.queue.current;
|
|
512
|
-
const queueTracks = state.queue.tracks;
|
|
513
|
-
if (state.isAutoplay) {
|
|
514
|
-
Object.setPrototypeOf(state.data.clientUser, { constructor: { name: "User" } });
|
|
515
|
-
player.setAutoplay(true, state.data.clientUser, state.autoplayTries);
|
|
531
|
+
if (tracks.length > 0) {
|
|
532
|
+
await player.queue.clear();
|
|
533
|
+
await player.queue.add(tracks);
|
|
516
534
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
await player.queue.setCurrent(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester));
|
|
523
|
-
}
|
|
524
|
-
// Add tracks to queue
|
|
525
|
-
if (tracks.length > 0) {
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
if (currentTrack) {
|
|
538
|
+
if (queueTracks.length > 0) {
|
|
539
|
+
tracks.push(...queueTracks);
|
|
526
540
|
await player.queue.clear();
|
|
527
541
|
await player.queue.add(tracks);
|
|
528
542
|
}
|
|
543
|
+
await node.trackEnd(player, currentTrack, {
|
|
544
|
+
reason: Enums_1.TrackEndReasonTypes.Finished,
|
|
545
|
+
type: "TrackEndEvent",
|
|
546
|
+
});
|
|
529
547
|
}
|
|
530
548
|
else {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
549
|
+
const previousQueue = await player.queue.getPrevious();
|
|
550
|
+
const lastTrack = previousQueue?.at(-1);
|
|
551
|
+
if (lastTrack) {
|
|
552
|
+
if (queueTracks.length === 0) {
|
|
553
|
+
await node.trackEnd(player, lastTrack, {
|
|
554
|
+
reason: Enums_1.TrackEndReasonTypes.Finished,
|
|
555
|
+
type: "TrackEndEvent",
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
534
559
|
tracks.push(...queueTracks);
|
|
560
|
+
if (tracks.length > 0) {
|
|
561
|
+
await player.queue.clear();
|
|
562
|
+
await player.queue.add(tracks);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else if (queueTracks.length > 0) {
|
|
567
|
+
tracks.push(...queueTracks);
|
|
568
|
+
if (tracks.length > 0) {
|
|
535
569
|
await player.queue.clear();
|
|
536
570
|
await player.queue.add(tracks);
|
|
537
571
|
}
|
|
538
|
-
await node.trackEnd(player,
|
|
572
|
+
await node.trackEnd(player, lastTrack, {
|
|
539
573
|
reason: Enums_1.TrackEndReasonTypes.Finished,
|
|
540
574
|
type: "TrackEndEvent",
|
|
541
575
|
});
|
|
542
576
|
}
|
|
543
|
-
else {
|
|
544
|
-
// No current track, check previous queue for last track
|
|
545
|
-
const previousQueue = await player.queue.getPrevious();
|
|
546
|
-
const lastTrack = previousQueue?.at(-1);
|
|
547
|
-
if (lastTrack) {
|
|
548
|
-
if (queueTracks.length === 0) {
|
|
549
|
-
// If no tracks in queue, end last track
|
|
550
|
-
await node.trackEnd(player, lastTrack, {
|
|
551
|
-
reason: Enums_1.TrackEndReasonTypes.Finished,
|
|
552
|
-
type: "TrackEndEvent",
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
else {
|
|
556
|
-
// If there are queued tracks, add them
|
|
557
|
-
tracks.push(...queueTracks);
|
|
558
|
-
if (tracks.length > 0) {
|
|
559
|
-
await player.queue.clear();
|
|
560
|
-
await player.queue.add(tracks);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
else {
|
|
565
|
-
if (queueTracks.length > 0) {
|
|
566
|
-
tracks.push(...queueTracks);
|
|
567
|
-
if (tracks.length > 0) {
|
|
568
|
-
await player.queue.clear();
|
|
569
|
-
await player.queue.add(tracks);
|
|
570
|
-
}
|
|
571
|
-
await node.trackEnd(player, lastTrack, {
|
|
572
|
-
reason: Enums_1.TrackEndReasonTypes.Finished,
|
|
573
|
-
type: "TrackEndEvent",
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
if (state.queue.previous.length > 0) {
|
|
580
|
-
await player.queue.addPrevious(state.queue.previous);
|
|
581
|
-
}
|
|
582
|
-
else {
|
|
583
|
-
await player.queue.clearPrevious();
|
|
584
577
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
578
|
+
}
|
|
579
|
+
if (state.queue.previous.length > 0) {
|
|
580
|
+
await player.queue.addPrevious(state.queue.previous);
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
await player.queue.clearPrevious();
|
|
584
|
+
}
|
|
585
|
+
if (state.paused) {
|
|
586
|
+
await player.pause(true);
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
player.paused = false;
|
|
590
|
+
}
|
|
591
|
+
if (state.trackRepeat)
|
|
592
|
+
player.setTrackRepeat(true);
|
|
593
|
+
if (state.queueRepeat)
|
|
594
|
+
player.setQueueRepeat(true);
|
|
595
|
+
if (state.dynamicRepeat) {
|
|
596
|
+
player.setDynamicRepeat(state.dynamicRepeat, state.dynamicLoopInterval._idleTimeout);
|
|
597
|
+
}
|
|
598
|
+
if (state.data) {
|
|
599
|
+
for (const [name, value] of Object.entries(state.data)) {
|
|
600
|
+
player.set(name, value);
|
|
602
601
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
602
|
+
}
|
|
603
|
+
const filterActions = {
|
|
604
|
+
bassboost: () => player.filters.bassBoost(state.filters.bassBoostlevel),
|
|
605
|
+
distort: (enabled) => player.filters.distort(enabled),
|
|
606
|
+
setDistortion: () => player.filters.setDistortion(state.filters.distortion),
|
|
607
|
+
eightD: (enabled) => player.filters.eightD(enabled),
|
|
608
|
+
setKaraoke: () => player.filters.setKaraoke(state.filters.karaoke),
|
|
609
|
+
nightcore: (enabled) => player.filters.nightcore(enabled),
|
|
610
|
+
slowmo: (enabled) => player.filters.slowmo(enabled),
|
|
611
|
+
soft: (enabled) => player.filters.soft(enabled),
|
|
612
|
+
trebleBass: (enabled) => player.filters.trebleBass(enabled),
|
|
613
|
+
setTimescale: () => player.filters.setTimescale(state.filters.timescale),
|
|
614
|
+
tv: (enabled) => player.filters.tv(enabled),
|
|
615
|
+
vibrato: () => player.filters.setVibrato(state.filters.vibrato),
|
|
616
|
+
vaporwave: (enabled) => player.filters.vaporwave(enabled),
|
|
617
|
+
pop: (enabled) => player.filters.pop(enabled),
|
|
618
|
+
party: (enabled) => player.filters.party(enabled),
|
|
619
|
+
earrape: (enabled) => player.filters.earrape(enabled),
|
|
620
|
+
electronic: (enabled) => player.filters.electronic(enabled),
|
|
621
|
+
radio: (enabled) => player.filters.radio(enabled),
|
|
622
|
+
setRotation: () => player.filters.setRotation(state.filters.rotation),
|
|
623
|
+
tremolo: (enabled) => player.filters.tremolo(enabled),
|
|
624
|
+
china: (enabled) => player.filters.china(enabled),
|
|
625
|
+
chipmunk: (enabled) => player.filters.chipmunk(enabled),
|
|
626
|
+
darthvader: (enabled) => player.filters.darthvader(enabled),
|
|
627
|
+
daycore: (enabled) => player.filters.daycore(enabled),
|
|
628
|
+
doubletime: (enabled) => player.filters.doubletime(enabled),
|
|
629
|
+
demon: (enabled) => player.filters.demon(enabled),
|
|
630
|
+
};
|
|
631
|
+
for (const [filter, isEnabled] of Object.entries(state.filters.filterStatus)) {
|
|
632
|
+
if (isEnabled && filterActions[filter]) {
|
|
633
|
+
filterActions[filter](true);
|
|
636
634
|
}
|
|
637
|
-
this.emit(Enums_1.ManagerEventTypes.PlayerRestored, player, node);
|
|
638
|
-
await this.sleep(1000);
|
|
639
635
|
}
|
|
636
|
+
this.emit(Enums_1.ManagerEventTypes.PlayerRestored, player, node);
|
|
637
|
+
await this.sleep(1000);
|
|
640
638
|
}
|
|
641
639
|
catch (error) {
|
|
642
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error processing
|
|
643
|
-
continue;
|
|
640
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error processing player state for guild ${guildId}: ${error}`);
|
|
641
|
+
continue;
|
|
644
642
|
}
|
|
645
643
|
}
|
|
646
|
-
//
|
|
647
|
-
for (const
|
|
648
|
-
|
|
644
|
+
// Cleanup old player state files from guild directories whose nodeId matches
|
|
645
|
+
for (const dirent of guildDirs) {
|
|
646
|
+
if (!dirent.isDirectory())
|
|
647
|
+
continue;
|
|
648
|
+
const guildId = dirent.name;
|
|
649
|
+
const stateFilePath = Utils_1.PlayerUtils.getPlayerStatePath(guildId);
|
|
649
650
|
try {
|
|
650
|
-
await promises_1.default.access(
|
|
651
|
-
const data = await promises_1.default.readFile(
|
|
651
|
+
await promises_1.default.access(stateFilePath);
|
|
652
|
+
const data = await promises_1.default.readFile(stateFilePath, "utf-8");
|
|
652
653
|
const state = JSON.parse(data);
|
|
653
|
-
if (state && typeof state === "object" && state.node
|
|
654
|
-
|
|
655
|
-
|
|
654
|
+
if (state && typeof state === "object" && state.node?.options?.identifier === nodeId) {
|
|
655
|
+
// Remove the entire guild directory or just the state file depending on your cleanup strategy
|
|
656
|
+
await promises_1.default.rm(Utils_1.PlayerUtils.getGuildDir(guildId), { recursive: true, force: true });
|
|
657
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted player state folder for guild ${guildId}`);
|
|
656
658
|
}
|
|
657
659
|
}
|
|
658
660
|
catch (error) {
|
|
659
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error deleting
|
|
660
|
-
continue;
|
|
661
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error deleting player state for guild ${guildId}: ${error}`);
|
|
662
|
+
continue;
|
|
661
663
|
}
|
|
662
664
|
}
|
|
663
665
|
}
|
|
@@ -1044,81 +1046,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
1044
1046
|
await player.pause(true);
|
|
1045
1047
|
return;
|
|
1046
1048
|
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Gets each player's JSON file
|
|
1049
|
-
* @param {string} guildId - The guild ID
|
|
1050
|
-
* @returns {string} The path to the player's JSON file
|
|
1051
|
-
*/
|
|
1052
|
-
async getPlayerFilePath(guildId) {
|
|
1053
|
-
const configDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playerStore");
|
|
1054
|
-
try {
|
|
1055
|
-
await promises_1.default.mkdir(configDir, { recursive: true });
|
|
1056
|
-
return path_1.default.join(configDir, `${guildId}.json`);
|
|
1057
|
-
}
|
|
1058
|
-
catch (err) {
|
|
1059
|
-
console.error(`[MANAGER] Error ensuring player data directory exists: ${err}`);
|
|
1060
|
-
throw new Error(`Failed to resolve player file path for guild ${guildId}`);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Serializes a Player instance to avoid circular references.
|
|
1065
|
-
* @param player The Player instance to serialize
|
|
1066
|
-
* @returns The serialized Player instance
|
|
1067
|
-
*/
|
|
1068
|
-
async serializePlayer(player) {
|
|
1069
|
-
const seen = new WeakSet();
|
|
1070
|
-
// Fetch async queue data once before serializing
|
|
1071
|
-
const current = await player.queue.getCurrent();
|
|
1072
|
-
const tracks = Array.isArray(await player.queue.getTracks()) ? await player.queue.getTracks() : [];
|
|
1073
|
-
const previous = Array.isArray(await player.queue.getPrevious()) ? await player.queue.getPrevious() : [];
|
|
1074
|
-
/**
|
|
1075
|
-
* Recursively serializes an object, avoiding circular references.
|
|
1076
|
-
* @param obj The object to serialize
|
|
1077
|
-
* @returns The serialized object
|
|
1078
|
-
*/
|
|
1079
|
-
const serialize = (obj) => {
|
|
1080
|
-
if (obj && typeof obj === "object") {
|
|
1081
|
-
if (seen.has(obj))
|
|
1082
|
-
return;
|
|
1083
|
-
seen.add(obj);
|
|
1084
|
-
}
|
|
1085
|
-
return obj;
|
|
1086
|
-
};
|
|
1087
|
-
return JSON.parse(JSON.stringify(player, (key, value) => {
|
|
1088
|
-
if (key === "manager") {
|
|
1089
|
-
return null;
|
|
1090
|
-
}
|
|
1091
|
-
if (key === "filters") {
|
|
1092
|
-
if (!value || typeof value !== "object")
|
|
1093
|
-
return null;
|
|
1094
|
-
return {
|
|
1095
|
-
distortion: value.distortion ?? null,
|
|
1096
|
-
equalizer: value.equalizer ?? [],
|
|
1097
|
-
karaoke: value.karaoke ?? null,
|
|
1098
|
-
rotation: value.rotation ?? null,
|
|
1099
|
-
timescale: value.timescale ?? null,
|
|
1100
|
-
vibrato: value.vibrato ?? null,
|
|
1101
|
-
reverb: value.reverb ?? null,
|
|
1102
|
-
volume: value.volume ?? 1.0,
|
|
1103
|
-
bassBoostlevel: value.bassBoostlevel ?? null,
|
|
1104
|
-
filterStatus: value.filtersStatus ? { ...value.filtersStatus } : {},
|
|
1105
|
-
};
|
|
1106
|
-
}
|
|
1107
|
-
if (key === "queue") {
|
|
1108
|
-
return {
|
|
1109
|
-
current,
|
|
1110
|
-
tracks,
|
|
1111
|
-
previous,
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
if (key === "data") {
|
|
1115
|
-
return {
|
|
1116
|
-
clientUser: value?.Internal_BotUser ?? null,
|
|
1117
|
-
};
|
|
1118
|
-
}
|
|
1119
|
-
return serialize(value);
|
|
1120
|
-
}));
|
|
1121
|
-
}
|
|
1122
1049
|
/**
|
|
1123
1050
|
* Cleans up inactive players by removing their state files from the file system.
|
|
1124
1051
|
* This is done to prevent stale state files from accumulating on the file system.
|
|
@@ -1127,30 +1054,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
1127
1054
|
switch (this.options.stateStorage.type) {
|
|
1128
1055
|
case Enums_1.StateStorageType.JSON:
|
|
1129
1056
|
{
|
|
1130
|
-
const
|
|
1131
|
-
const playerDataDir = this.options.stateStorage?.jsonConfig?.path ?? path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
|
|
1057
|
+
const playersBaseDir = Utils_1.PlayerUtils.getPlayersBaseDir();
|
|
1132
1058
|
try {
|
|
1133
|
-
await promises_1.default.mkdir(
|
|
1134
|
-
await promises_1.default.mkdir(playerDataDir, { recursive: true });
|
|
1059
|
+
await promises_1.default.mkdir(playersBaseDir, { recursive: true });
|
|
1135
1060
|
const activeGuildIds = new Set(this.players.keys());
|
|
1136
|
-
//
|
|
1137
|
-
const
|
|
1138
|
-
for (const file of playerStateFiles) {
|
|
1139
|
-
const guildId = path_1.default.basename(file, ".json");
|
|
1140
|
-
if (!activeGuildIds.has(guildId)) {
|
|
1141
|
-
const filePath = path_1.default.join(playerStoreDir, file);
|
|
1142
|
-
await promises_1.default.unlink(filePath);
|
|
1143
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted inactive player state: ${guildId}`);
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
// Clean up players/<guildId>/ folders
|
|
1147
|
-
const guildDirs = await promises_1.default.readdir(playerDataDir, { withFileTypes: true });
|
|
1061
|
+
// Cleanup inactive guild directories inside playersBaseDir
|
|
1062
|
+
const guildDirs = await promises_1.default.readdir(playersBaseDir, { withFileTypes: true });
|
|
1148
1063
|
for (const dirent of guildDirs) {
|
|
1149
1064
|
if (!dirent.isDirectory())
|
|
1150
1065
|
continue;
|
|
1151
1066
|
const guildId = dirent.name;
|
|
1152
1067
|
if (!activeGuildIds.has(guildId)) {
|
|
1153
|
-
const guildPath =
|
|
1068
|
+
const guildPath = Utils_1.PlayerUtils.getGuildDir(guildId);
|
|
1154
1069
|
await promises_1.default.rm(guildPath, { recursive: true, force: true });
|
|
1155
1070
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted inactive player data folder: ${guildId}`);
|
|
1156
1071
|
}
|
|
@@ -1202,13 +1117,11 @@ class Manager extends events_1.EventEmitter {
|
|
|
1202
1117
|
switch (this.options.stateStorage.type) {
|
|
1203
1118
|
case Enums_1.StateStorageType.JSON:
|
|
1204
1119
|
{
|
|
1205
|
-
const playersStoreDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playerStore");
|
|
1206
|
-
const playersDataDir = this.options.stateStorage?.jsonConfig?.path ?? path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
|
|
1207
1120
|
try {
|
|
1208
1121
|
if (!this.players.has(guildId)) {
|
|
1209
|
-
|
|
1210
|
-
await promises_1.default.rm(
|
|
1211
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER]
|
|
1122
|
+
const guildDir = Utils_1.PlayerUtils.getGuildDir(guildId);
|
|
1123
|
+
await promises_1.default.rm(guildDir, { recursive: true, force: true });
|
|
1124
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted inactive player data folder: ${guildId}`);
|
|
1212
1125
|
}
|
|
1213
1126
|
}
|
|
1214
1127
|
catch (error) {
|
|
@@ -1283,19 +1196,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
1283
1196
|
switch (this.options.stateStorage.type) {
|
|
1284
1197
|
case Enums_1.StateStorageType.Memory:
|
|
1285
1198
|
case Enums_1.StateStorageType.JSON: {
|
|
1286
|
-
const
|
|
1199
|
+
const playersBaseDir = Utils_1.PlayerUtils.getPlayersBaseDir();
|
|
1287
1200
|
try {
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Created directory: ${configDir}`);
|
|
1201
|
+
await promises_1.default.access(playersBaseDir).catch(async () => {
|
|
1202
|
+
await promises_1.default.mkdir(playersBaseDir, { recursive: true });
|
|
1203
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Created directory: ${playersBaseDir}`);
|
|
1292
1204
|
});
|
|
1293
|
-
const files = await promises_1.default.readdir(
|
|
1294
|
-
await Promise.all(files.map((file) => promises_1.default.unlink(path_1.default.join(
|
|
1295
|
-
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Cleared all player state files in ${
|
|
1205
|
+
const files = await promises_1.default.readdir(playersBaseDir);
|
|
1206
|
+
await Promise.all(files.map((file) => promises_1.default.unlink(path_1.default.join(playersBaseDir, file)).catch((err) => this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Failed to delete file ${file}: ${err}`))));
|
|
1207
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Cleared all player state files in ${playersBaseDir}`);
|
|
1296
1208
|
}
|
|
1297
1209
|
catch (err) {
|
|
1298
|
-
|
|
1210
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error clearing player state files: ${err}`);
|
|
1299
1211
|
}
|
|
1300
1212
|
break;
|
|
1301
1213
|
}
|
package/dist/structures/Node.js
CHANGED
|
@@ -91,7 +91,7 @@ class Node {
|
|
|
91
91
|
this.rest = new Rest_1.Rest(this, this.manager);
|
|
92
92
|
switch (this.manager.options.stateStorage.type) {
|
|
93
93
|
case Enums_1.StateStorageType.JSON:
|
|
94
|
-
this.sessionIdsFilePath = path_1.default.join(process.cwd(), "magmastream", "
|
|
94
|
+
this.sessionIdsFilePath = path_1.default.join(process.cwd(), "magmastream", "sessionData", "sessionIds.json");
|
|
95
95
|
const configDir = path_1.default.dirname(this.sessionIdsFilePath);
|
|
96
96
|
if (!fs_1.default.existsSync(configDir)) {
|
|
97
97
|
fs_1.default.mkdirSync(configDir, { recursive: true });
|
package/dist/structures/Rest.js
CHANGED
|
@@ -50,7 +50,7 @@ class Rest {
|
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Sends a PATCH request to update player related data.
|
|
53
|
-
* @param {
|
|
53
|
+
* @param {RestPlayOptions} options The options to update the player with.
|
|
54
54
|
* @returns {Promise<unknown>} Returns the result of the PATCH request.
|
|
55
55
|
*/
|
|
56
56
|
async updatePlayer(options) {
|