magmastream 2.10.3-alpha.0 → 2.10.3-alpha.3
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/statestorage/JsonQueue.js +6 -6
- package/dist/statestorage/MemoryQueue.js +6 -6
- package/dist/statestorage/RedisQueue.js +4 -4
- package/dist/structures/Manager.js +40 -38
- package/dist/structures/Node.d.ts +1 -1
- package/dist/structures/Node.js +24 -18
- package/dist/structures/Player.js +8 -8
- package/dist/structures/Utils.js +14 -14
- package/dist/wrappers/cloudstorm.js +3 -3
- package/dist/wrappers/discord.js.js +4 -4
- package/dist/wrappers/discordeno.js +3 -3
- package/dist/wrappers/eris.js +3 -3
- package/dist/wrappers/oceanic.js +3 -3
- package/dist/wrappers/seyfert.js +4 -4
- package/package.json +1 -1
|
@@ -102,11 +102,11 @@ class JsonQueue {
|
|
|
102
102
|
const tracks = Array.isArray(track) ? track : [track];
|
|
103
103
|
if (!tracks.length)
|
|
104
104
|
return;
|
|
105
|
-
const current = (await this.getPrevious()).filter((
|
|
106
|
-
const validTracks = tracks.filter((
|
|
105
|
+
const current = (await this.getPrevious()).filter((previousTrack) => previousTrack !== null);
|
|
106
|
+
const validTracks = tracks.filter((track) => track !== null && typeof track.uri === "string");
|
|
107
107
|
if (!validTracks.length)
|
|
108
108
|
return;
|
|
109
|
-
const newTracks = validTracks.filter((
|
|
109
|
+
const newTracks = validTracks.filter((track) => !current.some((previousTrack) => previousTrack.uri === track.uri));
|
|
110
110
|
if (!newTracks.length)
|
|
111
111
|
return;
|
|
112
112
|
const updated = [...current, ...newTracks];
|
|
@@ -391,9 +391,9 @@ class JsonQueue {
|
|
|
391
391
|
const users = [...userMap.keys()];
|
|
392
392
|
const queues = users.map((id) => userMap.get(id));
|
|
393
393
|
const shuffledQueue = [];
|
|
394
|
-
while (queues.some((
|
|
395
|
-
for (const
|
|
396
|
-
const track =
|
|
394
|
+
while (queues.some((queue) => queue.length > 0)) {
|
|
395
|
+
for (const queue of queues) {
|
|
396
|
+
const track = queue.shift();
|
|
397
397
|
if (track)
|
|
398
398
|
shuffledQueue.push(track);
|
|
399
399
|
}
|
|
@@ -43,7 +43,7 @@ class MemoryQueue extends Array {
|
|
|
43
43
|
const isArray = Array.isArray(track);
|
|
44
44
|
const tracks = isArray ? [...track] : [track];
|
|
45
45
|
// Get the track info as a string
|
|
46
|
-
const trackInfo = isArray ? tracks.map((
|
|
46
|
+
const trackInfo = isArray ? tracks.map((track) => Utils_1.JSONUtils.safe(track, 2)).join(", ") : Utils_1.JSONUtils.safe(track, 2);
|
|
47
47
|
// Emit a debug message
|
|
48
48
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[MEMORYQUEUE] Added ${tracks.length} track(s) to queue: ${trackInfo}`);
|
|
49
49
|
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
@@ -129,13 +129,13 @@ class MemoryQueue extends Array {
|
|
|
129
129
|
addPrevious(track) {
|
|
130
130
|
try {
|
|
131
131
|
const max = this.manager.options.maxPreviousTracks;
|
|
132
|
-
this.previous = this.previous.filter((
|
|
132
|
+
this.previous = this.previous.filter((previousTrack) => previousTrack !== null);
|
|
133
133
|
if (Array.isArray(track)) {
|
|
134
|
-
const newTracks = track.filter((
|
|
134
|
+
const newTracks = track.filter((track) => !this.previous.some((previousTrack) => previousTrack?.identifier === track.identifier));
|
|
135
135
|
this.previous.push(...newTracks);
|
|
136
136
|
}
|
|
137
137
|
else {
|
|
138
|
-
const exists = this.previous.some((
|
|
138
|
+
const exists = this.previous.some((previousTrack) => previousTrack?.identifier === track.identifier);
|
|
139
139
|
if (!exists) {
|
|
140
140
|
this.previous.push(track);
|
|
141
141
|
}
|
|
@@ -261,7 +261,7 @@ class MemoryQueue extends Array {
|
|
|
261
261
|
* @returns The previous tracks.
|
|
262
262
|
*/
|
|
263
263
|
getPrevious() {
|
|
264
|
-
this.previous = this.previous.map((
|
|
264
|
+
this.previous = this.previous.map((track) => Utils_1.TrackUtils.revive(track));
|
|
265
265
|
return [...this.previous];
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
@@ -274,7 +274,7 @@ class MemoryQueue extends Array {
|
|
|
274
274
|
* @returns The tracks in the queue.
|
|
275
275
|
*/
|
|
276
276
|
getTracks() {
|
|
277
|
-
this.forEach((
|
|
277
|
+
this.forEach((track) => Utils_1.TrackUtils.revive(track));
|
|
278
278
|
return [...this]; // clone to avoid direct mutation
|
|
279
279
|
}
|
|
280
280
|
/**
|
|
@@ -44,7 +44,7 @@ class RedisQueue {
|
|
|
44
44
|
const isArray = Array.isArray(track);
|
|
45
45
|
const tracks = isArray ? track : [track];
|
|
46
46
|
// Serialize tracks
|
|
47
|
-
const serialized = tracks.map((
|
|
47
|
+
const serialized = tracks.map((track) => this.serialize(track));
|
|
48
48
|
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
49
49
|
// Set current track if none exists
|
|
50
50
|
if (!(await this.getCurrent())) {
|
|
@@ -524,9 +524,9 @@ class RedisQueue {
|
|
|
524
524
|
const users = [...userMap.keys()];
|
|
525
525
|
const queues = users.map((id) => userMap.get(id));
|
|
526
526
|
const shuffledQueue = [];
|
|
527
|
-
while (queues.some((
|
|
528
|
-
for (const
|
|
529
|
-
const track =
|
|
527
|
+
while (queues.some((queue) => queue.length > 0)) {
|
|
528
|
+
for (const queue of queues) {
|
|
529
|
+
const track = queue.shift();
|
|
530
530
|
if (track)
|
|
531
531
|
shuffledQueue.push(track);
|
|
532
532
|
}
|
|
@@ -216,8 +216,8 @@ class Manager extends events_1.EventEmitter {
|
|
|
216
216
|
const search = isUrl ? _query.query : `${_source}:${_query.query}`;
|
|
217
217
|
this.emit(Enums_1.ManagerEventTypes.Debug, isUrl ? `[MANAGER] Performing search for: ${_query.query}` : `[MANAGER] Performing ${_source} search for: ${_query.query}`);
|
|
218
218
|
try {
|
|
219
|
-
const
|
|
220
|
-
if (!
|
|
219
|
+
const lavalinkResponse = (await node.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(search)}`));
|
|
220
|
+
if (!lavalinkResponse) {
|
|
221
221
|
throw new MagmastreamError_1.MagmaStreamError({
|
|
222
222
|
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
223
223
|
message: `No results returned from Lavalink for query "${search}".`,
|
|
@@ -225,16 +225,16 @@ class Manager extends events_1.EventEmitter {
|
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
let result;
|
|
228
|
-
switch (
|
|
228
|
+
switch (lavalinkResponse.loadType) {
|
|
229
229
|
case Enums_1.LoadTypes.Search: {
|
|
230
|
-
const tracks =
|
|
231
|
-
result = { loadType:
|
|
230
|
+
const tracks = lavalinkResponse.data.map((track) => Utils_1.TrackUtils.build(track, requester));
|
|
231
|
+
result = { loadType: lavalinkResponse.loadType, tracks };
|
|
232
232
|
break;
|
|
233
233
|
}
|
|
234
234
|
case Enums_1.LoadTypes.Short:
|
|
235
235
|
case Enums_1.LoadTypes.Track: {
|
|
236
|
-
const track = Utils_1.TrackUtils.build(
|
|
237
|
-
result = { loadType:
|
|
236
|
+
const track = Utils_1.TrackUtils.build(lavalinkResponse.data, requester);
|
|
237
|
+
result = { loadType: lavalinkResponse.loadType, tracks: [track] };
|
|
238
238
|
break;
|
|
239
239
|
}
|
|
240
240
|
case Enums_1.LoadTypes.Album:
|
|
@@ -243,10 +243,10 @@ class Manager extends events_1.EventEmitter {
|
|
|
243
243
|
case Enums_1.LoadTypes.Podcast:
|
|
244
244
|
case Enums_1.LoadTypes.Show:
|
|
245
245
|
case Enums_1.LoadTypes.Playlist: {
|
|
246
|
-
const playlistData =
|
|
247
|
-
const tracks = playlistData.tracks.map((
|
|
246
|
+
const playlistData = lavalinkResponse.data;
|
|
247
|
+
const tracks = playlistData.tracks.map((track) => Utils_1.TrackUtils.build(track, requester));
|
|
248
248
|
result = {
|
|
249
|
-
loadType:
|
|
249
|
+
loadType: lavalinkResponse.loadType,
|
|
250
250
|
tracks,
|
|
251
251
|
playlist: {
|
|
252
252
|
name: playlistData.info.name,
|
|
@@ -259,7 +259,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
259
259
|
break;
|
|
260
260
|
}
|
|
261
261
|
default:
|
|
262
|
-
result = { loadType:
|
|
262
|
+
result = { loadType: lavalinkResponse.loadType };
|
|
263
263
|
}
|
|
264
264
|
if (this.options.normalizeYouTubeTitles && "tracks" in result) {
|
|
265
265
|
const processTrack = (track) => {
|
|
@@ -275,7 +275,9 @@ class Manager extends events_1.EventEmitter {
|
|
|
275
275
|
result.playlist.tracks = result.tracks;
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
|
-
const summary = "tracks" in result
|
|
278
|
+
const summary = "tracks" in result
|
|
279
|
+
? result.tracks.map((track) => Object.fromEntries(Object.entries(track).filter(([key]) => key !== "requester")))
|
|
280
|
+
: [];
|
|
279
281
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Result search for ${_query.query}: ${Utils_1.JSONUtils.safe(summary, 2)}`);
|
|
280
282
|
return result;
|
|
281
283
|
}
|
|
@@ -412,14 +414,14 @@ class Manager extends events_1.EventEmitter {
|
|
|
412
414
|
message: "No available nodes to decode tracks.",
|
|
413
415
|
});
|
|
414
416
|
}
|
|
415
|
-
const
|
|
416
|
-
if (!
|
|
417
|
+
const decodedTrackData = (await node.rest.post("/v4/decodetracks", Utils_1.JSONUtils.safe(tracks, 2)).catch((err) => reject(err)));
|
|
418
|
+
if (!decodedTrackData) {
|
|
417
419
|
throw new MagmastreamError_1.MagmaStreamError({
|
|
418
420
|
code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
|
|
419
421
|
message: "No decoded tracks returned from node.",
|
|
420
422
|
});
|
|
421
423
|
}
|
|
422
|
-
return resolve(
|
|
424
|
+
return resolve(decodedTrackData);
|
|
423
425
|
});
|
|
424
426
|
}
|
|
425
427
|
/**
|
|
@@ -429,9 +431,9 @@ class Manager extends events_1.EventEmitter {
|
|
|
429
431
|
* @throws Will throw an error if no nodes are available or if the API request fails.
|
|
430
432
|
*/
|
|
431
433
|
async decodeTrack(track) {
|
|
432
|
-
const
|
|
434
|
+
const decodedTracks = await this.decodeTracks([track]);
|
|
433
435
|
// Since we're only decoding one track, we can just return the first element of the array
|
|
434
|
-
return
|
|
436
|
+
return decodedTracks[0];
|
|
435
437
|
}
|
|
436
438
|
/**
|
|
437
439
|
* Saves player states.
|
|
@@ -577,7 +579,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
577
579
|
}
|
|
578
580
|
async restorePreviousQueue(player, state) {
|
|
579
581
|
if (state.queue.previous.length > 0) {
|
|
580
|
-
const validPrevious = state.queue.previous.filter((
|
|
582
|
+
const validPrevious = state.queue.previous.filter((track) => track !== null && typeof track.identifier === "string");
|
|
581
583
|
if (validPrevious.length > 0)
|
|
582
584
|
await player.queue.addPrevious(validPrevious);
|
|
583
585
|
}
|
|
@@ -604,31 +606,31 @@ class Manager extends events_1.EventEmitter {
|
|
|
604
606
|
restoreFilters(player, state) {
|
|
605
607
|
const filterActions = {
|
|
606
608
|
bassboost: () => player.filters.bassBoost(state.filters.bassBoostlevel),
|
|
607
|
-
distort: (
|
|
609
|
+
distort: (isEnabled) => player.filters.distort(isEnabled),
|
|
608
610
|
setDistortion: () => player.filters.setDistortion(state.filters.distortion),
|
|
609
|
-
eightD: (
|
|
611
|
+
eightD: (isEnabled) => player.filters.eightD(isEnabled),
|
|
610
612
|
setKaraoke: () => player.filters.setKaraoke(state.filters.karaoke),
|
|
611
|
-
nightcore: (
|
|
612
|
-
slowmo: (
|
|
613
|
-
soft: (
|
|
614
|
-
trebleBass: (
|
|
613
|
+
nightcore: (isEnabled) => player.filters.nightcore(isEnabled),
|
|
614
|
+
slowmo: (isEnabled) => player.filters.slowmo(isEnabled),
|
|
615
|
+
soft: (isEnabled) => player.filters.soft(isEnabled),
|
|
616
|
+
trebleBass: (isEnabled) => player.filters.trebleBass(isEnabled),
|
|
615
617
|
setTimescale: () => player.filters.setTimescale(state.filters.timescale),
|
|
616
|
-
tv: (
|
|
618
|
+
tv: (isEnabled) => player.filters.tv(isEnabled),
|
|
617
619
|
vibrato: () => player.filters.setVibrato(state.filters.vibrato),
|
|
618
|
-
vaporwave: (
|
|
619
|
-
pop: (
|
|
620
|
-
party: (
|
|
621
|
-
earrape: (
|
|
622
|
-
electronic: (
|
|
623
|
-
radio: (
|
|
620
|
+
vaporwave: (isEnabled) => player.filters.vaporwave(isEnabled),
|
|
621
|
+
pop: (isEnabled) => player.filters.pop(isEnabled),
|
|
622
|
+
party: (isEnabled) => player.filters.party(isEnabled),
|
|
623
|
+
earrape: (isEnabled) => player.filters.earrape(isEnabled),
|
|
624
|
+
electronic: (isEnabled) => player.filters.electronic(isEnabled),
|
|
625
|
+
radio: (isEnabled) => player.filters.radio(isEnabled),
|
|
624
626
|
setRotation: () => player.filters.setRotation(state.filters.rotation),
|
|
625
|
-
tremolo: (
|
|
626
|
-
china: (
|
|
627
|
-
chipmunk: (
|
|
628
|
-
darthvader: (
|
|
629
|
-
daycore: (
|
|
630
|
-
doubletime: (
|
|
631
|
-
demon: (
|
|
627
|
+
tremolo: (isEnabled) => player.filters.tremolo(isEnabled),
|
|
628
|
+
china: (isEnabled) => player.filters.china(isEnabled),
|
|
629
|
+
chipmunk: (isEnabled) => player.filters.chipmunk(isEnabled),
|
|
630
|
+
darthvader: (isEnabled) => player.filters.darthvader(isEnabled),
|
|
631
|
+
daycore: (isEnabled) => player.filters.daycore(isEnabled),
|
|
632
|
+
doubletime: (isEnabled) => player.filters.doubletime(isEnabled),
|
|
633
|
+
demon: (isEnabled) => player.filters.demon(isEnabled),
|
|
632
634
|
};
|
|
633
635
|
for (const [filter, isEnabled] of Object.entries(state.filters.filterStatus)) {
|
|
634
636
|
if (isEnabled && filterActions[filter])
|
|
@@ -150,7 +150,7 @@ export declare class Node {
|
|
|
150
150
|
* @emits {nodeRaw} - Emits a nodeRaw event with the raw message received from the WebSocket connection.
|
|
151
151
|
* @private
|
|
152
152
|
*/
|
|
153
|
-
protected message(
|
|
153
|
+
protected message(messagePayload: Buffer | string): Promise<void>;
|
|
154
154
|
/**
|
|
155
155
|
* Handles an event emitted from the Lavalink node.
|
|
156
156
|
* @param {PlayerEvent & PlayerEvents} payload The event emitted from the node.
|
package/dist/structures/Node.js
CHANGED
|
@@ -10,7 +10,7 @@ const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
|
10
10
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
11
|
const Enums_1 = require("./Enums");
|
|
12
12
|
const MagmastreamError_1 = require("./MagmastreamError");
|
|
13
|
-
const validSponsorBlocks = Object.values(Enums_1.SponsorBlockSegment).map((
|
|
13
|
+
const validSponsorBlocks = Object.values(Enums_1.SponsorBlockSegment).map((segment) => segment.toLowerCase());
|
|
14
14
|
class Node {
|
|
15
15
|
manager;
|
|
16
16
|
options;
|
|
@@ -29,7 +29,7 @@ class Node {
|
|
|
29
29
|
/** Whether the node is a NodeLink. */
|
|
30
30
|
isNodeLink = false;
|
|
31
31
|
reconnectTimeout;
|
|
32
|
-
reconnectAttempts =
|
|
32
|
+
reconnectAttempts = 0;
|
|
33
33
|
redisPrefix;
|
|
34
34
|
/** Session ID sent in the reconnect header for resumption — cleared once the ready op is received. */
|
|
35
35
|
pendingResumeSessionId = null;
|
|
@@ -302,18 +302,18 @@ class Node {
|
|
|
302
302
|
identifier: this.options.identifier,
|
|
303
303
|
address: this.address,
|
|
304
304
|
sessionId: this.sessionId,
|
|
305
|
-
playerCount: this.manager.players.filter((
|
|
305
|
+
playerCount: this.manager.players.filter((player) => player.node == this).size,
|
|
306
306
|
};
|
|
307
307
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Destroying node: ${Utils_1.JSONUtils.safe(debugInfo, 2)}`);
|
|
308
308
|
// Automove all players connected to that node
|
|
309
|
-
const players = this.manager.players.filter((
|
|
309
|
+
const players = this.manager.players.filter((player) => player.node == this);
|
|
310
310
|
if (players.size) {
|
|
311
311
|
await Promise.all(Array.from(players.values(), (player) => player.autoMoveNode()));
|
|
312
312
|
}
|
|
313
313
|
// Always clear reconnect state regardless of connection status
|
|
314
314
|
clearTimeout(this.reconnectTimeout);
|
|
315
315
|
this.reconnectTimeout = undefined;
|
|
316
|
-
this.reconnectAttempts =
|
|
316
|
+
this.reconnectAttempts = 0;
|
|
317
317
|
// Only close the socket if it is actually open
|
|
318
318
|
if (this.connected) {
|
|
319
319
|
this.socket.close(1000, "destroy");
|
|
@@ -349,7 +349,8 @@ class Node {
|
|
|
349
349
|
};
|
|
350
350
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Reconnecting node: ${Utils_1.JSONUtils.safe(debugInfo, 2)}`);
|
|
351
351
|
this.reconnectTimeout = setTimeout(async () => {
|
|
352
|
-
|
|
352
|
+
this.reconnectAttempts++;
|
|
353
|
+
if (this.reconnectAttempts > this.options.maxRetryAttempts) {
|
|
353
354
|
const error = new MagmastreamError_1.MagmaStreamError({
|
|
354
355
|
code: Enums_1.MagmaStreamErrorCode.NODE_RECONNECT_FAILED,
|
|
355
356
|
message: `Unable to reconnect after ${this.options.maxRetryAttempts} attempts.`,
|
|
@@ -362,7 +363,6 @@ class Node {
|
|
|
362
363
|
this.socket = null;
|
|
363
364
|
this.manager.emit(Enums_1.ManagerEventTypes.NodeReconnect, this);
|
|
364
365
|
await this.connect();
|
|
365
|
-
this.reconnectAttempts++;
|
|
366
366
|
}, this.options.retryDelayMs);
|
|
367
367
|
}
|
|
368
368
|
/**
|
|
@@ -384,13 +384,15 @@ class Node {
|
|
|
384
384
|
open() {
|
|
385
385
|
if (this.reconnectTimeout)
|
|
386
386
|
clearTimeout(this.reconnectTimeout);
|
|
387
|
+
this.reconnectTimeout = undefined;
|
|
388
|
+
this.reconnectAttempts = 0;
|
|
387
389
|
const debugInfo = {
|
|
388
390
|
identifier: this.options.identifier,
|
|
389
391
|
connected: this.connected,
|
|
390
392
|
};
|
|
391
393
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Connected node: ${Utils_1.JSONUtils.safe(debugInfo, 2)}`);
|
|
392
394
|
this.manager.emit(Enums_1.ManagerEventTypes.NodeConnect, this);
|
|
393
|
-
const playersOnBackupNode = this.manager.players.filter((
|
|
395
|
+
const playersOnBackupNode = this.manager.players.filter((player) => player.node.options.isBackup);
|
|
394
396
|
if (playersOnBackupNode.size) {
|
|
395
397
|
Promise.all(Array.from(playersOnBackupNode.values(), (player) => player.moveNode(this.options.identifier)));
|
|
396
398
|
}
|
|
@@ -416,8 +418,12 @@ class Node {
|
|
|
416
418
|
};
|
|
417
419
|
this.manager.emit(Enums_1.ManagerEventTypes.NodeDisconnect, this, { code, reason });
|
|
418
420
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Disconnected node: ${Utils_1.JSONUtils.safe(debugInfo, 2)}`);
|
|
421
|
+
// Null the session ID immediately so REST calls during the reconnect delay
|
|
422
|
+
// window don't fire with a stale session. connect() reloads it from storage
|
|
423
|
+
// into pendingResumeSessionId for the WS Session-Id header.
|
|
424
|
+
this.sessionId = null;
|
|
419
425
|
if (this.manager.useableNode) {
|
|
420
|
-
const players = this.manager.players.filter((
|
|
426
|
+
const players = this.manager.players.filter((player) => player.node.options.identifier == this.options.identifier);
|
|
421
427
|
if (players.size) {
|
|
422
428
|
await Promise.all(Array.from(players.values(), (player) => player.autoMoveNode()));
|
|
423
429
|
}
|
|
@@ -459,12 +465,12 @@ class Node {
|
|
|
459
465
|
* @emits {nodeRaw} - Emits a nodeRaw event with the raw message received from the WebSocket connection.
|
|
460
466
|
* @private
|
|
461
467
|
*/
|
|
462
|
-
async message(
|
|
463
|
-
if (Array.isArray(
|
|
464
|
-
|
|
465
|
-
else if (
|
|
466
|
-
|
|
467
|
-
const payload = JSON.parse(
|
|
468
|
+
async message(messagePayload) {
|
|
469
|
+
if (Array.isArray(messagePayload))
|
|
470
|
+
messagePayload = Buffer.concat(messagePayload);
|
|
471
|
+
else if (messagePayload instanceof ArrayBuffer)
|
|
472
|
+
messagePayload = Buffer.from(messagePayload);
|
|
473
|
+
const payload = JSON.parse(messagePayload.toString());
|
|
468
474
|
if (!payload.op)
|
|
469
475
|
return;
|
|
470
476
|
this.manager.emit(Enums_1.ManagerEventTypes.NodeRaw, payload);
|
|
@@ -1132,15 +1138,15 @@ class Node {
|
|
|
1132
1138
|
context: { identifier: this.options.identifier, guildId: player.guildId },
|
|
1133
1139
|
});
|
|
1134
1140
|
}
|
|
1135
|
-
if (segments.some((
|
|
1141
|
+
if (segments.some((segment) => !validSponsorBlocks.includes(segment.toLowerCase()))) {
|
|
1136
1142
|
throw new MagmastreamError_1.MagmaStreamError({
|
|
1137
1143
|
code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
|
|
1138
|
-
message: `Invalid SponsorBlock segments provided. Valid ones are: ${validSponsorBlocks.map((
|
|
1144
|
+
message: `Invalid SponsorBlock segments provided. Valid ones are: ${validSponsorBlocks.map((segment) => `'${segment}'`).join(", ")}`,
|
|
1139
1145
|
context: { identifier: this.options.identifier, guildId: player.guildId, invalidSegments: segments },
|
|
1140
1146
|
});
|
|
1141
1147
|
}
|
|
1142
1148
|
try {
|
|
1143
|
-
await this.rest.put(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, segments.map((
|
|
1149
|
+
await this.rest.put(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, segments.map((segment) => segment.toLowerCase()));
|
|
1144
1150
|
}
|
|
1145
1151
|
catch (err) {
|
|
1146
1152
|
throw err instanceof MagmastreamError_1.MagmaStreamError
|
|
@@ -1043,7 +1043,7 @@ class Player {
|
|
|
1043
1043
|
this.voiceReceiverWsClient = new ws_1.WebSocket(`${useSSL ? "wss" : "ws"}://${host}:${port}/connection/data`, { headers });
|
|
1044
1044
|
this.voiceReceiverWsClient.on("open", () => this.openVoiceReceiver());
|
|
1045
1045
|
this.voiceReceiverWsClient.on("error", (err) => this.onVoiceReceiverError(err));
|
|
1046
|
-
this.voiceReceiverWsClient.on("message", (
|
|
1046
|
+
this.voiceReceiverWsClient.on("message", (rawMessage) => this.onVoiceReceiverMessage(rawMessage.toString()));
|
|
1047
1047
|
this.voiceReceiverWsClient.on("close", (code, reason) => this.closeVoiceReceiver(code, reason.toString()));
|
|
1048
1048
|
}
|
|
1049
1049
|
/**
|
|
@@ -1166,18 +1166,18 @@ class Player {
|
|
|
1166
1166
|
* @returns {Promise<void>} - A promise that resolves when the voice state is updated.
|
|
1167
1167
|
*/
|
|
1168
1168
|
async updateVoice() {
|
|
1169
|
-
const
|
|
1170
|
-
const
|
|
1171
|
-
if (!
|
|
1169
|
+
const voiceState = this.voiceState;
|
|
1170
|
+
const voiceEvent = voiceState?.event;
|
|
1171
|
+
if (!voiceState?.channelId || !voiceState?.sessionId || !voiceEvent?.token || !voiceEvent?.endpoint)
|
|
1172
1172
|
return;
|
|
1173
1173
|
await this.node.rest.updatePlayer({
|
|
1174
1174
|
guildId: this.options.guildId,
|
|
1175
1175
|
data: {
|
|
1176
1176
|
voice: {
|
|
1177
|
-
token:
|
|
1178
|
-
endpoint:
|
|
1179
|
-
sessionId:
|
|
1180
|
-
channelId:
|
|
1177
|
+
token: voiceEvent.token,
|
|
1178
|
+
endpoint: voiceEvent.endpoint,
|
|
1179
|
+
sessionId: voiceState.sessionId,
|
|
1180
|
+
channelId: voiceState.channelId,
|
|
1181
1181
|
},
|
|
1182
1182
|
},
|
|
1183
1183
|
});
|
package/dist/structures/Utils.js
CHANGED
|
@@ -62,8 +62,8 @@ class TrackUtils {
|
|
|
62
62
|
static isTrack(track) {
|
|
63
63
|
if (typeof track !== "object" || track === null)
|
|
64
64
|
return false;
|
|
65
|
-
const
|
|
66
|
-
return REQUIRED_TRACK_KEYS.every((key) => typeof
|
|
65
|
+
const trackRecord = track;
|
|
66
|
+
return REQUIRED_TRACK_KEYS.every((key) => typeof trackRecord[key] === "string");
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Checks if the provided argument is a valid Track array.
|
|
@@ -295,7 +295,7 @@ class AutoPlayUtils {
|
|
|
295
295
|
const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
|
|
296
296
|
if (!resolvedTracks.length)
|
|
297
297
|
return [];
|
|
298
|
-
const filteredTracks = resolvedTracks.filter((
|
|
298
|
+
const filteredTracks = resolvedTracks.filter((resolvedTrack) => resolvedTrack.uri !== track.uri);
|
|
299
299
|
if (!filteredTracks.length) {
|
|
300
300
|
return [];
|
|
301
301
|
}
|
|
@@ -392,10 +392,10 @@ class AutoPlayUtils {
|
|
|
392
392
|
const h2 = element.querySelector('h2[itemprop="name"]');
|
|
393
393
|
if (!h2)
|
|
394
394
|
return null;
|
|
395
|
-
const
|
|
396
|
-
if (!
|
|
395
|
+
const anchorElement = h2.querySelector('a[itemprop="url"]');
|
|
396
|
+
if (!anchorElement)
|
|
397
397
|
return null;
|
|
398
|
-
const href =
|
|
398
|
+
const href = anchorElement.getAttribute("href");
|
|
399
399
|
return href ? `https://soundcloud.com${href}` : null;
|
|
400
400
|
})
|
|
401
401
|
.filter(Boolean);
|
|
@@ -433,7 +433,7 @@ class AutoPlayUtils {
|
|
|
433
433
|
searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
|
|
434
434
|
} while (track.uri.includes(searchURI));
|
|
435
435
|
const resolvedTracks = await this.resolveTracksFromQuery(searchURI, Enums_1.SearchPlatform.YouTube, requester);
|
|
436
|
-
const filteredTracks = resolvedTracks.filter((
|
|
436
|
+
const filteredTracks = resolvedTracks.filter((resolvedTrack) => resolvedTrack.uri !== track.uri);
|
|
437
437
|
return filteredTracks;
|
|
438
438
|
}
|
|
439
439
|
case Enums_1.AutoPlayPlatform.Tidal: {
|
|
@@ -596,7 +596,7 @@ class AutoPlayUtils {
|
|
|
596
596
|
context: { recommendedResult },
|
|
597
597
|
});
|
|
598
598
|
}
|
|
599
|
-
return data.map((
|
|
599
|
+
return data.map((trackData) => TrackUtils.build(trackData, requester, true));
|
|
600
600
|
}
|
|
601
601
|
case Enums_1.LoadTypes.Album:
|
|
602
602
|
case Enums_1.LoadTypes.Artist:
|
|
@@ -606,7 +606,7 @@ class AutoPlayUtils {
|
|
|
606
606
|
case Enums_1.LoadTypes.Playlist: {
|
|
607
607
|
const data = recommendedResult.data;
|
|
608
608
|
if (this.isPlaylistRawData(data)) {
|
|
609
|
-
return data.tracks.map((
|
|
609
|
+
return data.tracks.map((trackData) => TrackUtils.build(trackData, requester, true));
|
|
610
610
|
}
|
|
611
611
|
throw new MagmastreamError_1.MagmaStreamError({
|
|
612
612
|
code: Enums_1.MagmaStreamErrorCode.UTILS_AUTOPLAY_BUILD_FAILED,
|
|
@@ -666,9 +666,9 @@ class PlayerUtils {
|
|
|
666
666
|
if (!obj || typeof obj !== "object")
|
|
667
667
|
return obj;
|
|
668
668
|
const result = {};
|
|
669
|
-
for (const [k,
|
|
670
|
-
if (!isNonSerializable(
|
|
671
|
-
result[k] =
|
|
669
|
+
for (const [k, entryValue] of Object.entries(obj)) {
|
|
670
|
+
if (!isNonSerializable(entryValue)) {
|
|
671
|
+
result[k] = entryValue;
|
|
672
672
|
}
|
|
673
673
|
}
|
|
674
674
|
return result;
|
|
@@ -690,8 +690,8 @@ class PlayerUtils {
|
|
|
690
690
|
}
|
|
691
691
|
};
|
|
692
692
|
const safeCurrent = current ? serializeTrack(current) : null;
|
|
693
|
-
const safeTracks = tracks.map(serializeTrack).filter((
|
|
694
|
-
const safePrevious = previous.map(serializeTrack).filter((
|
|
693
|
+
const safeTracks = tracks.map(serializeTrack).filter((serializedTrack) => serializedTrack !== null);
|
|
694
|
+
const safePrevious = previous.map(serializeTrack).filter((serializedTrack) => serializedTrack !== null);
|
|
695
695
|
let safeNode = null;
|
|
696
696
|
if (player.node) {
|
|
697
697
|
try {
|
|
@@ -63,12 +63,12 @@ class CloudstormManager extends Manager_1.Manager {
|
|
|
63
63
|
}
|
|
64
64
|
// CloudStorm has no user/guild cache — return minimal portable info only.
|
|
65
65
|
async resolveUser(user) {
|
|
66
|
-
const
|
|
67
|
-
const cached = this.getUserFromCache(
|
|
66
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
67
|
+
const cached = this.getUserFromCache(userId);
|
|
68
68
|
if (cached)
|
|
69
69
|
return cached;
|
|
70
70
|
return {
|
|
71
|
-
id,
|
|
71
|
+
id: userId,
|
|
72
72
|
username: typeof user === "string" ? undefined : user.username,
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -50,16 +50,16 @@ class DiscordJSManager extends Manager_1.Manager {
|
|
|
50
50
|
guild.shard.send(packet);
|
|
51
51
|
}
|
|
52
52
|
async resolveUser(user) {
|
|
53
|
-
const
|
|
54
|
-
const cached = this.client.users.cache.get(
|
|
53
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
54
|
+
const cached = this.client.users.cache.get(userId);
|
|
55
55
|
if (cached)
|
|
56
56
|
return cached;
|
|
57
57
|
try {
|
|
58
|
-
const fetched = await this.client.users.fetch(
|
|
58
|
+
const fetched = await this.client.users.fetch(userId);
|
|
59
59
|
return fetched;
|
|
60
60
|
}
|
|
61
61
|
catch {
|
|
62
|
-
return { id, username: typeof user === "string" ? undefined : user.username };
|
|
62
|
+
return { id: userId, username: typeof user === "string" ? undefined : user.username };
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
resolveGuild(guildId) {
|
|
@@ -57,14 +57,14 @@ class DiscordenoManager extends Manager_1.Manager {
|
|
|
57
57
|
* Uses user-provided cache getter if available, otherwise falls back to minimal info.
|
|
58
58
|
*/
|
|
59
59
|
async resolveUser(user) {
|
|
60
|
-
const
|
|
60
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
61
61
|
// Try user-provided cache getter
|
|
62
|
-
const cached = this.getUserFromCache(
|
|
62
|
+
const cached = this.getUserFromCache(userId);
|
|
63
63
|
if (cached)
|
|
64
64
|
return cached;
|
|
65
65
|
// Fallback: return minimal info
|
|
66
66
|
return {
|
|
67
|
-
id,
|
|
67
|
+
id: userId,
|
|
68
68
|
username: typeof user === "string" ? undefined : user.username,
|
|
69
69
|
};
|
|
70
70
|
}
|
package/dist/wrappers/eris.js
CHANGED
|
@@ -35,12 +35,12 @@ class ErisManager extends Manager_1.Manager {
|
|
|
35
35
|
guild.shard.sendWS(packet.op, packet.d);
|
|
36
36
|
}
|
|
37
37
|
async resolveUser(user) {
|
|
38
|
-
const
|
|
39
|
-
const cached = this.client.users.get(
|
|
38
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
39
|
+
const cached = this.client.users.get(userId);
|
|
40
40
|
if (cached)
|
|
41
41
|
return cached;
|
|
42
42
|
return {
|
|
43
|
-
id,
|
|
43
|
+
id: userId,
|
|
44
44
|
username: typeof user === "string" ? undefined : user.username,
|
|
45
45
|
};
|
|
46
46
|
}
|
package/dist/wrappers/oceanic.js
CHANGED
|
@@ -35,12 +35,12 @@ class OceanicManager extends Manager_1.Manager {
|
|
|
35
35
|
guild.shard.send(packet.op, packet.d);
|
|
36
36
|
}
|
|
37
37
|
async resolveUser(user) {
|
|
38
|
-
const
|
|
39
|
-
const cached = this.client.users.get(
|
|
38
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
39
|
+
const cached = this.client.users.get(userId);
|
|
40
40
|
if (cached)
|
|
41
41
|
return cached;
|
|
42
42
|
return {
|
|
43
|
-
id,
|
|
43
|
+
id: userId,
|
|
44
44
|
username: typeof user === "string" ? undefined : user.username,
|
|
45
45
|
};
|
|
46
46
|
}
|
package/dist/wrappers/seyfert.js
CHANGED
|
@@ -63,15 +63,15 @@ class SeyfertManager extends Manager_1.Manager {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
async resolveUser(user) {
|
|
66
|
-
const
|
|
67
|
-
const cached = this.client.cache.users?.get(
|
|
66
|
+
const userId = typeof user === "string" ? user : String(user.id);
|
|
67
|
+
const cached = this.client.cache.users?.get(userId);
|
|
68
68
|
if (cached)
|
|
69
69
|
return cached;
|
|
70
70
|
try {
|
|
71
|
-
return await this.client.users.fetch(
|
|
71
|
+
return await this.client.users.fetch(userId);
|
|
72
72
|
}
|
|
73
73
|
catch {
|
|
74
|
-
return { id, username: typeof user === "string" ? undefined : user.username };
|
|
74
|
+
return { id: userId, username: typeof user === "string" ? undefined : user.username };
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
resolveGuild(guildId) {
|