magmastream 2.10.5 → 2.10.6-alpha.1
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.
|
@@ -117,12 +117,6 @@ export declare class Manager extends EventEmitter {
|
|
|
117
117
|
* @param {string} guildId - The guild ID of the player to save
|
|
118
118
|
*/
|
|
119
119
|
savePlayerState(guildId: string): Promise<void>;
|
|
120
|
-
/**
|
|
121
|
-
* Sleeps for a specified amount of time.
|
|
122
|
-
* @param ms The amount of time to sleep in milliseconds.
|
|
123
|
-
* @returns A promise that resolves after the specified amount of time.
|
|
124
|
-
*/
|
|
125
|
-
private sleep;
|
|
126
120
|
private restorePlayerFromState;
|
|
127
121
|
private restoreQueue;
|
|
128
122
|
private restorePreviousQueue;
|
|
@@ -529,14 +529,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
529
529
|
await player.queue.clearPrevious();
|
|
530
530
|
await player.queue.setCurrent(null);
|
|
531
531
|
}
|
|
532
|
-
/**
|
|
533
|
-
* Sleeps for a specified amount of time.
|
|
534
|
-
* @param ms The amount of time to sleep in milliseconds.
|
|
535
|
-
* @returns A promise that resolves after the specified amount of time.
|
|
536
|
-
*/
|
|
537
|
-
async sleep(ms) {
|
|
538
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
539
|
-
}
|
|
540
532
|
async restorePlayerFromState(node, nodeId, guildId, state, cleanup) {
|
|
541
533
|
if (!state.guildId || state.node?.options?.identifier !== nodeId)
|
|
542
534
|
return;
|
|
@@ -584,7 +576,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
584
576
|
await player.pause(true);
|
|
585
577
|
await cleanup();
|
|
586
578
|
this.emit(Enums_1.ManagerEventTypes.PlayerRestored, player, node);
|
|
587
|
-
await this.sleep(1000);
|
|
588
579
|
}
|
|
589
580
|
async restoreQueue(node, player, state, lavaPlayer) {
|
|
590
581
|
const currentTrack = state.queue.current;
|
|
@@ -724,10 +715,9 @@ class Manager extends events_1.EventEmitter {
|
|
|
724
715
|
await promises_1.default.mkdir(playersBaseDir, { recursive: true });
|
|
725
716
|
});
|
|
726
717
|
const guildDirs = await promises_1.default.readdir(playersBaseDir, { withFileTypes: true });
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
const guildId = file.name;
|
|
718
|
+
await Promise.all(guildDirs
|
|
719
|
+
.filter((file) => file.isDirectory())
|
|
720
|
+
.map(async ({ name: guildId }) => {
|
|
731
721
|
const stateFilePath = Utils_1.PlayerUtils.getPlayerStatePath(guildId);
|
|
732
722
|
try {
|
|
733
723
|
await promises_1.default.access(stateFilePath);
|
|
@@ -740,7 +730,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
740
730
|
catch (error) {
|
|
741
731
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error processing guild ${guildId}: ${error}`);
|
|
742
732
|
}
|
|
743
|
-
}
|
|
733
|
+
}));
|
|
744
734
|
}
|
|
745
735
|
catch (error) {
|
|
746
736
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error loading player states: ${error}`);
|
|
@@ -750,17 +740,17 @@ class Manager extends events_1.EventEmitter {
|
|
|
750
740
|
case Enums_1.StateStorageType.Redis: {
|
|
751
741
|
try {
|
|
752
742
|
const keys = await this.redis.keys(`${Utils_1.PlayerUtils.getRedisKey()}playerstore:*`);
|
|
753
|
-
|
|
743
|
+
await Promise.all(keys.map(async (key) => {
|
|
754
744
|
try {
|
|
755
745
|
const data = await this.redis.get(key);
|
|
756
746
|
if (!data)
|
|
757
|
-
|
|
747
|
+
return;
|
|
758
748
|
const state = JSON.parse(data);
|
|
759
749
|
if (!state || typeof state !== "object")
|
|
760
|
-
|
|
750
|
+
return;
|
|
761
751
|
const guildId = key.split(":").pop();
|
|
762
752
|
if (!guildId)
|
|
763
|
-
|
|
753
|
+
return;
|
|
764
754
|
await this.restorePlayerFromState(node, nodeId, guildId, state, async () => {
|
|
765
755
|
await this.redis.del(key);
|
|
766
756
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted Redis state: ${key}`);
|
|
@@ -769,7 +759,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
769
759
|
catch (error) {
|
|
770
760
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error processing Redis key ${key}: ${error}`);
|
|
771
761
|
}
|
|
772
|
-
}
|
|
762
|
+
}));
|
|
773
763
|
}
|
|
774
764
|
catch (error) {
|
|
775
765
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error loading player states from Redis: ${error}`);
|
package/dist/structures/Node.js
CHANGED
|
@@ -11,6 +11,7 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
11
11
|
const Enums_1 = require("./Enums");
|
|
12
12
|
const MagmastreamError_1 = require("./MagmastreamError");
|
|
13
13
|
const validSponsorBlocks = Object.values(Enums_1.SponsorBlockSegment).map((segment) => segment.toLowerCase());
|
|
14
|
+
const TRACK_REQUIRED_EVENTS = new Set(["TrackStartEvent", "TrackEndEvent", "TrackStuckEvent", "TrackExceptionEvent"]);
|
|
14
15
|
class Node {
|
|
15
16
|
manager;
|
|
16
17
|
options;
|
|
@@ -484,7 +485,9 @@ class Node {
|
|
|
484
485
|
this.handlePlayerUpdate(payload);
|
|
485
486
|
break;
|
|
486
487
|
case "event":
|
|
487
|
-
this.manager.
|
|
488
|
+
if (this.manager.listenerCount(Enums_1.ManagerEventTypes.Debug)) {
|
|
489
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Node message: ${Utils_1.JSONUtils.safe(payload, 2)}`);
|
|
490
|
+
}
|
|
488
491
|
await this.handleEvent(payload);
|
|
489
492
|
break;
|
|
490
493
|
case "ready":
|
|
@@ -567,8 +570,7 @@ class Node {
|
|
|
567
570
|
return;
|
|
568
571
|
const track = await this.resolveEventTrack(player, payload);
|
|
569
572
|
const type = payload.type;
|
|
570
|
-
|
|
571
|
-
if (!track && trackRequiredEvents.includes(type)) {
|
|
573
|
+
if (!track && TRACK_REQUIRED_EVENTS.has(type)) {
|
|
572
574
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Received ${type} for guild ${payload.guildId}, but neither the payload nor local queue contains a usable track.`);
|
|
573
575
|
return;
|
|
574
576
|
}
|
|
@@ -1227,7 +1229,9 @@ class Node {
|
|
|
1227
1229
|
socketClosed(player, payload) {
|
|
1228
1230
|
// A move can close the old socket after the new connection is ready.
|
|
1229
1231
|
this.manager.emit(Enums_1.ManagerEventTypes.SocketClosed, player, payload);
|
|
1230
|
-
this.manager.
|
|
1232
|
+
if (this.manager.listenerCount(Enums_1.ManagerEventTypes.Debug)) {
|
|
1233
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Websocket closed for player: ${player.guildId} with payload: ${Utils_1.JSONUtils.safe(payload, 2)}`);
|
|
1234
|
+
}
|
|
1231
1235
|
}
|
|
1232
1236
|
/**
|
|
1233
1237
|
* Emitted when the segments for a track are loaded.
|
|
@@ -101,6 +101,7 @@ export declare class Player {
|
|
|
101
101
|
* @returns {this} The player instance.
|
|
102
102
|
*/
|
|
103
103
|
disconnect(): Promise<this>;
|
|
104
|
+
private emitConnectionChange;
|
|
104
105
|
/**
|
|
105
106
|
* Destroys the player and clears the queue.
|
|
106
107
|
* @param {boolean} disconnect - Whether to disconnect the player from the voice channel.
|
|
@@ -187,7 +187,7 @@ class Player {
|
|
|
187
187
|
// Set the player state to connecting.
|
|
188
188
|
this.state = Enums_1.StateTypes.Connecting;
|
|
189
189
|
// Clone the current player state for comparison.
|
|
190
|
-
const oldPlayer =
|
|
190
|
+
const oldPlayer = { ...this };
|
|
191
191
|
this.manager.sendPacket({
|
|
192
192
|
op: 4,
|
|
193
193
|
d: {
|
|
@@ -200,15 +200,7 @@ class Player {
|
|
|
200
200
|
// Set the player state to connected.
|
|
201
201
|
this.state = Enums_1.StateTypes.Connected;
|
|
202
202
|
// Emit the player state update event.
|
|
203
|
-
this.
|
|
204
|
-
changeType: Enums_1.PlayerStateEventTypes.ConnectionChange,
|
|
205
|
-
details: {
|
|
206
|
-
type: "connection",
|
|
207
|
-
action: "connect",
|
|
208
|
-
previousConnection: oldPlayer?.state === Enums_1.StateTypes.Connected,
|
|
209
|
-
currentConnection: true,
|
|
210
|
-
},
|
|
211
|
-
});
|
|
203
|
+
this.emitConnectionChange(oldPlayer, "connect");
|
|
212
204
|
}
|
|
213
205
|
/**
|
|
214
206
|
* Disconnects the player from the voice channel.
|
|
@@ -218,7 +210,7 @@ class Player {
|
|
|
218
210
|
// Set the player state to disconnecting.
|
|
219
211
|
this.state = Enums_1.StateTypes.Disconnecting;
|
|
220
212
|
// Clone the current player state for comparison.
|
|
221
|
-
const oldPlayer =
|
|
213
|
+
const oldPlayer = { ...this };
|
|
222
214
|
// Pause the player.
|
|
223
215
|
if (this.options.pauseOnDisconnect) {
|
|
224
216
|
await this.pause(true);
|
|
@@ -238,16 +230,19 @@ class Player {
|
|
|
238
230
|
// Set the player state to disconnected.
|
|
239
231
|
this.state = Enums_1.StateTypes.Disconnected;
|
|
240
232
|
// Emit the player state update event.
|
|
233
|
+
this.emitConnectionChange(oldPlayer, "disconnect");
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
236
|
+
emitConnectionChange(oldPlayer, action) {
|
|
241
237
|
this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this, {
|
|
242
238
|
changeType: Enums_1.PlayerStateEventTypes.ConnectionChange,
|
|
243
239
|
details: {
|
|
244
240
|
type: "connection",
|
|
245
|
-
action
|
|
241
|
+
action,
|
|
246
242
|
previousConnection: oldPlayer.state === Enums_1.StateTypes.Connected,
|
|
247
|
-
currentConnection:
|
|
243
|
+
currentConnection: action === "connect",
|
|
248
244
|
},
|
|
249
245
|
});
|
|
250
|
-
return this;
|
|
251
246
|
}
|
|
252
247
|
/**
|
|
253
248
|
* Destroys the player and clears the queue.
|
|
@@ -1340,7 +1335,9 @@ class Player {
|
|
|
1340
1335
|
}
|
|
1341
1336
|
if (!packet?.op)
|
|
1342
1337
|
return;
|
|
1343
|
-
this.manager.
|
|
1338
|
+
if (this.manager.listenerCount(Enums_1.ManagerEventTypes.Debug)) {
|
|
1339
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `VoiceReceiver recieved a payload: ${Utils_1.JSONUtils.safe(textPayload, 2)}`);
|
|
1340
|
+
}
|
|
1344
1341
|
switch (packet.type) {
|
|
1345
1342
|
case "startSpeakingEvent": {
|
|
1346
1343
|
this.manager.emit(Enums_1.ManagerEventTypes.VoiceReceiverStartSpeaking, this, packet.data);
|
|
@@ -1355,7 +1352,9 @@ class Player {
|
|
|
1355
1352
|
break;
|
|
1356
1353
|
}
|
|
1357
1354
|
default: {
|
|
1358
|
-
this.manager.
|
|
1355
|
+
if (this.manager.listenerCount(Enums_1.ManagerEventTypes.Debug)) {
|
|
1356
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `VoiceReceiver recieved an unknown payload: ${Utils_1.JSONUtils.safe(textPayload, 2)}`);
|
|
1357
|
+
}
|
|
1359
1358
|
break;
|
|
1360
1359
|
}
|
|
1361
1360
|
}
|
|
@@ -1408,9 +1407,12 @@ class Player {
|
|
|
1408
1407
|
return;
|
|
1409
1408
|
}
|
|
1410
1409
|
if (frame.op === 3) {
|
|
1411
|
-
|
|
1410
|
+
let stream = this.voiceReceiverStreams.get(key);
|
|
1411
|
+
if (!stream) {
|
|
1412
|
+
stream = { guildId: frame.guildId, userId: frame.userId, type: frame.type, chunks: [] };
|
|
1413
|
+
this.voiceReceiverStreams.set(key, stream);
|
|
1414
|
+
}
|
|
1412
1415
|
stream.chunks.push(frame.data);
|
|
1413
|
-
this.voiceReceiverStreams.set(key, stream);
|
|
1414
1416
|
this.manager.emit(Enums_1.ManagerEventTypes.VoiceReceiverData, this, {
|
|
1415
1417
|
userId: frame.userId,
|
|
1416
1418
|
guildId: frame.guildId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magmastream",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.6-alpha.1",
|
|
4
4
|
"description": "A user-friendly Lavalink client designed for NodeJS.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"prepare": "npm run build",
|
|
12
12
|
"build": "tsc",
|
|
13
13
|
"types": "rtb --dist dist",
|
|
14
|
-
"test": "npm run build && node --test tests/player-state.test.cjs",
|
|
14
|
+
"test": "npm run build && node --test tests/player-state.test.cjs tests/hot-paths.test.cjs tests/restore-performance.test.cjs",
|
|
15
15
|
"format": "prettier --write .",
|
|
16
16
|
"format:check": "prettier --check .",
|
|
17
17
|
"lint": "eslint \"src/**/*.{ts,js}\"",
|