magmastream 2.9.3-dev.2 → 2.9.3-dev.20

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.
@@ -16,6 +16,10 @@ class MemoryQueue extends Array {
16
16
  manager;
17
17
  /** The guild ID property. */
18
18
  guildId;
19
+ /**
20
+ * Whether the queue has been destroyed.
21
+ */
22
+ destroyed = false;
19
23
  /**
20
24
  * Constructs a new Queue.
21
25
  * @param guildId The guild ID.
@@ -34,7 +38,7 @@ class MemoryQueue extends Array {
34
38
  * @param track The track or tracks to add. Can be a single `Track` or an array of `Track`s.
35
39
  * @param [offset=null] The position to add the track(s) at. If not provided, the track(s) will be added at the end of the queue.
36
40
  */
37
- async add(track, offset) {
41
+ add(track, offset) {
38
42
  try {
39
43
  const isArray = Array.isArray(track);
40
44
  const tracks = isArray ? [...track] : [track];
@@ -84,8 +88,7 @@ class MemoryQueue extends Array {
84
88
  }
85
89
  if (this.manager.players.has(this.guildId) && this.manager.players.get(this.guildId).isAutoplay) {
86
90
  if (!isArray) {
87
- const AutoplayUser = this.manager.players.get(this.guildId).get("Internal_AutoplayUser");
88
- if (AutoplayUser && AutoplayUser.id === track.requester.id) {
91
+ if (track.isAutoplay) {
89
92
  this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
90
93
  changeType: Enums_1.PlayerStateEventTypes.QueueChange,
91
94
  details: {
@@ -123,7 +126,7 @@ class MemoryQueue extends Array {
123
126
  * Adds a track to the previous tracks.
124
127
  * @param track The track or tracks to add. Can be a single `Track` or an array of `Track`s.
125
128
  */
126
- async addPrevious(track) {
129
+ addPrevious(track) {
127
130
  try {
128
131
  const max = this.manager.options.maxPreviousTracks;
129
132
  if (Array.isArray(track)) {
@@ -155,7 +158,7 @@ class MemoryQueue extends Array {
155
158
  * Clears the queue.
156
159
  * This will remove all tracks from the queue and emit a state update event.
157
160
  */
158
- async clear() {
161
+ clear() {
159
162
  try {
160
163
  // Capture the current state of the player for event emission.
161
164
  const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
@@ -187,20 +190,32 @@ class MemoryQueue extends Array {
187
190
  /**
188
191
  * Clears the previous tracks.
189
192
  */
190
- async clearPrevious() {
193
+ clearPrevious() {
191
194
  this.previous = [];
192
195
  }
193
196
  /**
194
197
  * Removes the first element from the queue.
195
198
  */
196
- async dequeue() {
199
+ dequeue() {
197
200
  return super.shift();
198
201
  }
202
+ /**
203
+ * Destroys the queue and releases all resources.
204
+ * After calling this method, the queue must not be used again.
205
+ */
206
+ destroy() {
207
+ if (this.destroyed)
208
+ return;
209
+ this.destroyed = true;
210
+ this.splice(0);
211
+ this.previous.length = 0;
212
+ this.current = null;
213
+ }
199
214
  /**
200
215
  * The total duration of the queue in milliseconds.
201
216
  * This includes the duration of the currently playing track.
202
217
  */
203
- async duration() {
218
+ duration() {
204
219
  const current = this.current?.duration ?? 0;
205
220
  return this.reduce((acc, cur) => acc + (cur.duration || 0), current);
206
221
  }
@@ -208,7 +223,7 @@ class MemoryQueue extends Array {
208
223
  * Adds the specified track or tracks to the front of the queue.
209
224
  * @param track The track or tracks to add.
210
225
  */
211
- async enqueueFront(track) {
226
+ enqueueFront(track) {
212
227
  if (Array.isArray(track)) {
213
228
  this.unshift(...track);
214
229
  }
@@ -219,49 +234,49 @@ class MemoryQueue extends Array {
219
234
  /**
220
235
  * @returns Whether all elements in the queue satisfy the provided testing function.
221
236
  */
222
- async everyAsync(callback) {
237
+ everyAsync(callback) {
223
238
  return this.every(callback);
224
239
  }
225
240
  /**
226
241
  * @returns A new array with all elements that pass the test implemented by the provided function.
227
242
  */
228
- async filterAsync(callback) {
243
+ filterAsync(callback) {
229
244
  return this.filter(callback);
230
245
  }
231
246
  /**
232
247
  * @returns The first element in the queue that satisfies the provided testing function.
233
248
  */
234
- async findAsync(callback) {
249
+ findAsync(callback) {
235
250
  return this.find(callback);
236
251
  }
237
252
  /**
238
253
  * @returns The current track.
239
254
  */
240
- async getCurrent() {
255
+ getCurrent() {
241
256
  return this.current;
242
257
  }
243
258
  /**
244
259
  * @returns The previous tracks.
245
260
  */
246
- async getPrevious() {
261
+ getPrevious() {
247
262
  return [...this.previous];
248
263
  }
249
264
  /**
250
265
  * @returns The tracks in the queue from start to end.
251
266
  */
252
- async getSlice(start, end) {
267
+ getSlice(start, end) {
253
268
  return this.slice(start, end); // Native sync method, still wrapped in a Promise
254
269
  }
255
270
  /**
256
271
  * @returns The tracks in the queue.
257
272
  */
258
- async getTracks() {
273
+ getTracks() {
259
274
  return [...this]; // clone to avoid direct mutation
260
275
  }
261
276
  /**
262
277
  * @returns A new array with the results of calling a provided function on every element in the queue.
263
278
  */
264
- async mapAsync(callback) {
279
+ mapAsync(callback) {
265
280
  return this.map(callback);
266
281
  }
267
282
  /**
@@ -271,16 +286,16 @@ class MemoryQueue extends Array {
271
286
  * @param items The elements to add to the queue.
272
287
  * @returns The modified queue.
273
288
  */
274
- async modifyAt(start, deleteCount = 0, ...items) {
289
+ modifyAt(start, deleteCount = 0, ...items) {
275
290
  return super.splice(start, deleteCount, ...items);
276
291
  }
277
292
  /**
278
293
  * @returns The newest track.
279
294
  */
280
- async popPrevious() {
295
+ popPrevious() {
281
296
  return this.previous.pop() || null; // get newest track
282
297
  }
283
- async remove(startOrPosition = 0, end) {
298
+ remove(startOrPosition = 0, end) {
284
299
  try {
285
300
  const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
286
301
  if (typeof end !== "undefined") {
@@ -332,7 +347,7 @@ class MemoryQueue extends Array {
332
347
  /**
333
348
  * Shuffles the queue to play tracks requested by each user one by one.
334
349
  */
335
- async roundRobinShuffle() {
350
+ roundRobinShuffle() {
336
351
  try {
337
352
  // Capture the current state of the player for event emission.
338
353
  const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
@@ -340,11 +355,11 @@ class MemoryQueue extends Array {
340
355
  const userTracks = new Map();
341
356
  // Group the tracks in the queue by the user that requested them.
342
357
  this.forEach((track) => {
343
- const user = track.requester.id;
344
- if (!userTracks.has(user)) {
345
- userTracks.set(user, []);
358
+ const userId = track.requester.id.toString();
359
+ if (!userTracks.has(userId)) {
360
+ userTracks.set(userId, []);
346
361
  }
347
- userTracks.get(user).push(track);
362
+ userTracks.get(userId).push(track);
348
363
  });
349
364
  // Shuffle the tracks of each user.
350
365
  userTracks.forEach((tracks) => {
@@ -395,20 +410,20 @@ class MemoryQueue extends Array {
395
410
  /**
396
411
  * @param track The track to set.
397
412
  */
398
- async setCurrent(track) {
413
+ setCurrent(track) {
399
414
  this.current = track;
400
415
  }
401
416
  /**
402
417
  * @param tracks The tracks to set.
403
418
  */
404
- async setPrevious(tracks) {
419
+ setPrevious(tracks) {
405
420
  this.previous = [...tracks];
406
421
  }
407
422
  /**
408
423
  * Shuffles the queue.
409
424
  * This will randomize the order of the tracks in the queue and emit a state update event.
410
425
  */
411
- async shuffle() {
426
+ shuffle() {
412
427
  try {
413
428
  // Capture the current state of the player for event emission.
414
429
  const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
@@ -444,13 +459,13 @@ class MemoryQueue extends Array {
444
459
  * This does not include the currently playing track.
445
460
  * @returns The size of tracks in the queue.
446
461
  */
447
- async size() {
462
+ size() {
448
463
  return this.length;
449
464
  }
450
465
  /**
451
466
  * @returns Whether at least one element in the queue satisfies the provided testing function.
452
467
  */
453
- async someAsync(callback) {
468
+ someAsync(callback) {
454
469
  return this.some(callback);
455
470
  }
456
471
  /**
@@ -458,24 +473,24 @@ class MemoryQueue extends Array {
458
473
  * This includes the current track if it is not null.
459
474
  * @returns The total size of tracks in the queue including the current track.
460
475
  */
461
- async totalSize() {
476
+ totalSize() {
462
477
  return this.length + (this.current ? 1 : 0);
463
478
  }
464
479
  /**
465
480
  * Shuffles the queue to play tracks requested by each user one block at a time.
466
481
  */
467
- async userBlockShuffle() {
482
+ userBlockShuffle() {
468
483
  try {
469
484
  // Capture the current state of the player for event emission.
470
485
  const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
471
486
  // Group the tracks in the queue by the user that requested them.
472
487
  const userTracks = new Map();
473
488
  this.forEach((track) => {
474
- const user = track.requester.id;
475
- if (!userTracks.has(user)) {
476
- userTracks.set(user, []);
489
+ const userId = track.requester.id.toString();
490
+ if (!userTracks.has(userId)) {
491
+ userTracks.set(userId, []);
477
492
  }
478
- userTracks.get(user).push(track);
493
+ userTracks.get(userId).push(track);
479
494
  });
480
495
  // Create a new array for the shuffled queue.
481
496
  const shuffledQueue = [];
@@ -18,6 +18,10 @@ class RedisQueue {
18
18
  * The Redis instance.
19
19
  */
20
20
  redis;
21
+ /**
22
+ * Whether the queue has been destroyed.
23
+ */
24
+ destroyed = false;
21
25
  /**
22
26
  * Constructs a new RedisQueue.
23
27
  * @param guildId The guild ID.
@@ -27,11 +31,7 @@ class RedisQueue {
27
31
  this.guildId = guildId;
28
32
  this.manager = manager;
29
33
  this.redis = manager.redis;
30
- const rawPrefix = manager.options.stateStorage.redisConfig.prefix;
31
- let clean = typeof rawPrefix === "string" ? rawPrefix.trim() : "";
32
- if (!clean.endsWith(":"))
33
- clean = clean || "magmastream";
34
- this.redisPrefix = `${clean}:`;
34
+ this.redisPrefix = Utils_1.PlayerUtils.getRedisKey();
35
35
  }
36
36
  // #region Public
37
37
  /**
@@ -81,8 +81,7 @@ class RedisQueue {
81
81
  // Autoplay logic
82
82
  if (this.manager.players.has(this.guildId) && this.manager.players.get(this.guildId).isAutoplay) {
83
83
  if (!Array.isArray(track)) {
84
- const AutoplayUser = (await this.manager.players.get(this.guildId).get("Internal_AutoplayUser"));
85
- if (AutoplayUser && AutoplayUser.id === track.requester.id) {
84
+ if (track.isAutoplay) {
86
85
  this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
87
86
  changeType: Enums_1.PlayerStateEventTypes.QueueChange,
88
87
  details: {
@@ -223,6 +222,28 @@ class RedisQueue {
223
222
  console.error(error);
224
223
  }
225
224
  }
225
+ /**
226
+ * Destroys the queue and releases all resources.
227
+ * After calling this method, the queue must not be used again.
228
+ */
229
+ async destroy() {
230
+ if (this.destroyed)
231
+ return;
232
+ this.destroyed = true;
233
+ try {
234
+ await this.redis.del(this.queueKey, this.previousKey, this.currentKey);
235
+ }
236
+ catch (err) {
237
+ const error = err instanceof MagmastreamError_1.MagmaStreamError
238
+ ? err
239
+ : new MagmastreamError_1.MagmaStreamError({
240
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_REDIS_ERROR,
241
+ message: `Failed to destroy RedisQueue for guild ${this.guildId}: ${err.message}`,
242
+ cause: err,
243
+ });
244
+ console.error(error);
245
+ }
246
+ }
226
247
  /**
227
248
  * @returns The total duration of the queue in milliseconds.
228
249
  * This includes the duration of the currently playing track.
@@ -488,7 +509,7 @@ class RedisQueue {
488
509
  const deserialized = rawTracks.map(this.deserialize);
489
510
  const userMap = new Map();
490
511
  for (const track of deserialized) {
491
- const userId = track.requester.id;
512
+ const userId = track.requester.id.toString();
492
513
  if (!userMap.has(userId))
493
514
  userMap.set(userId, []);
494
515
  userMap.get(userId).push(track);
@@ -659,7 +680,7 @@ class RedisQueue {
659
680
  const deserialized = rawTracks.map(this.deserialize);
660
681
  const userMap = new Map();
661
682
  for (const track of deserialized) {
662
- const userId = track.requester.id;
683
+ const userId = track.requester.id.toString();
663
684
  if (!userMap.has(userId))
664
685
  userMap.set(userId, []);
665
686
  userMap.get(userId).push(track);
@@ -163,6 +163,8 @@ var TrackPartial;
163
163
  TrackPartial["PluginInfo"] = "pluginInfo";
164
164
  /** The custom data of the track */
165
165
  TrackPartial["CustomData"] = "customData";
166
+ /** Whether the track got autoplayed */
167
+ TrackPartial["IsAutoPlay"] = "isAutoplay";
166
168
  })(TrackPartial || (exports.TrackPartial = TrackPartial = {}));
167
169
  /**
168
170
  * Manager Event Types Enum
@@ -283,6 +285,7 @@ var MagmaStreamErrorCode;
283
285
  MagmaStreamErrorCode["GENERAL_UNKNOWN"] = "MS_GENERAL_UNKNOWN";
284
286
  MagmaStreamErrorCode["GENERAL_TIMEOUT"] = "MS_GENERAL_TIMEOUT";
285
287
  MagmaStreamErrorCode["GENERAL_INVALID_MANAGER"] = "MS_GENERAL_INVALID_MANAGER";
288
+ MagmaStreamErrorCode["INTENT_MISSING"] = "MS_INTENT_MISSING";
286
289
  // MANAGER (1100)
287
290
  MagmaStreamErrorCode["MANAGER_INIT_FAILED"] = "MS_MANAGER_INIT_FAILED";
288
291
  MagmaStreamErrorCode["MANAGER_INVALID_CONFIG"] = "MS_MANAGER_INVALID_CONFIG";
@@ -326,6 +329,7 @@ var MagmaStreamErrorCode;
326
329
  MagmaStreamErrorCode["UTILS_TRACK_PARTIAL_INVALID"] = "MS_UTILS_TRACK_PARTIAL_INVALID";
327
330
  MagmaStreamErrorCode["UTILS_TRACK_BUILD_FAILED"] = "MS_UTILS_TRACK_BUILD_FAILED";
328
331
  MagmaStreamErrorCode["UTILS_AUTOPLAY_BUILD_FAILED"] = "MS_UTILS_AUTOPLAY_BUILD_FAILED";
332
+ MagmaStreamErrorCode["UTILS_PLAYER_SERIALIZE_FAILED"] = "MS_UTILS_PLAYER_SERIALIZE_FAILED";
329
333
  // PLUGIN (1800)
330
334
  MagmaStreamErrorCode["PLUGIN_LOAD_FAILED"] = "MS_PLUGIN_LOAD_FAILED";
331
335
  MagmaStreamErrorCode["PLUGIN_RUNTIME_ERROR"] = "MS_PLUGIN_RUNTIME_ERROR";
@@ -336,6 +340,7 @@ exports.MagmaStreamErrorNumbers = {
336
340
  [MagmaStreamErrorCode.GENERAL_UNKNOWN]: 1000,
337
341
  [MagmaStreamErrorCode.GENERAL_TIMEOUT]: 1001,
338
342
  [MagmaStreamErrorCode.GENERAL_INVALID_MANAGER]: 1002,
343
+ [MagmaStreamErrorCode.INTENT_MISSING]: 1003,
339
344
  // MANAGER
340
345
  [MagmaStreamErrorCode.MANAGER_INIT_FAILED]: 1100,
341
346
  [MagmaStreamErrorCode.MANAGER_INVALID_CONFIG]: 1101,
@@ -379,6 +384,7 @@ exports.MagmaStreamErrorNumbers = {
379
384
  [MagmaStreamErrorCode.UTILS_TRACK_PARTIAL_INVALID]: 1700,
380
385
  [MagmaStreamErrorCode.UTILS_TRACK_BUILD_FAILED]: 1701,
381
386
  [MagmaStreamErrorCode.UTILS_AUTOPLAY_BUILD_FAILED]: 1702,
387
+ [MagmaStreamErrorCode.UTILS_PLAYER_SERIALIZE_FAILED]: 1703,
382
388
  // PLUGIN
383
389
  [MagmaStreamErrorCode.PLUGIN_LOAD_FAILED]: 1800,
384
390
  [MagmaStreamErrorCode.PLUGIN_RUNTIME_ERROR]: 1801,
@@ -8,8 +8,6 @@ class Filters {
8
8
  distortion;
9
9
  equalizer;
10
10
  karaoke;
11
- manager;
12
- player;
13
11
  rotation;
14
12
  timescale;
15
13
  vibrato;
@@ -17,15 +15,16 @@ class Filters {
17
15
  volume;
18
16
  bassBoostlevel;
19
17
  filtersStatus;
18
+ manager;
19
+ player;
20
20
  constructor(player, manager) {
21
21
  this.distortion = null;
22
22
  this.equalizer = [];
23
23
  this.karaoke = null;
24
- this.manager = manager;
25
- this.player = player;
26
24
  this.rotation = null;
27
25
  this.timescale = null;
28
26
  this.vibrato = null;
27
+ this.reverb = null;
29
28
  this.volume = 1.0;
30
29
  this.bassBoostlevel = 0;
31
30
  // Initialize filter status
@@ -33,6 +32,8 @@ class Filters {
33
32
  acc[filter] = false;
34
33
  return acc;
35
34
  }, {});
35
+ this.manager = manager;
36
+ this.player = player;
36
37
  }
37
38
  /**
38
39
  * Updates the player's audio filters.
@@ -28,6 +28,7 @@ class Manager extends events_1.EventEmitter {
28
28
  initiated = false;
29
29
  redis;
30
30
  _send;
31
+ _getUser;
31
32
  loadedPlugins = new Set();
32
33
  /**
33
34
  * Initiates the Manager class.
@@ -61,6 +62,8 @@ class Manager extends events_1.EventEmitter {
61
62
  this.options.clusterId = options.clusterId;
62
63
  if (options.send && !this._send)
63
64
  this._send = options.send;
65
+ if (options.getUser && !this._getUser)
66
+ this._getUser = options.getUser;
64
67
  this.options = {
65
68
  ...options,
66
69
  enabledPlugins: options.enabledPlugins ?? [],
@@ -177,11 +180,15 @@ class Manager extends events_1.EventEmitter {
177
180
  db: config.db ?? 0,
178
181
  });
179
182
  }
180
- for (const node of this.nodes.values()) {
181
- try {
182
- await node.connect();
183
- }
184
- catch (err) {
183
+ const results = await Promise.allSettled([...this.nodes.values()].map(async (node) => {
184
+ await node.connect();
185
+ return node;
186
+ }));
187
+ for (let i = 0; i < results.length; i++) {
188
+ const result = results[i];
189
+ const node = [...this.nodes.values()][i];
190
+ if (result.status === "rejected") {
191
+ const err = result.reason;
185
192
  const error = err instanceof MagmastreamError_1.MagmaStreamError
186
193
  ? err
187
194
  : new MagmastreamError_1.MagmaStreamError({
@@ -277,9 +284,7 @@ class Manager extends events_1.EventEmitter {
277
284
  result.playlist.tracks = result.playlist.tracks.map(processTrack);
278
285
  }
279
286
  }
280
- const summary = "tracks" in result
281
- ? result.tracks.map((t) => Object.fromEntries(Object.entries(t).filter(([key]) => key !== "requester")))
282
- : [];
287
+ const summary = "tracks" in result ? result.tracks.map((t) => Object.fromEntries(Object.entries(t).filter(([key]) => key !== "requester"))) : [];
283
288
  this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Result search for ${_query.query}: ${Utils_1.JSONUtils.safe(summary, 2)}`);
284
289
  return result;
285
290
  }
@@ -466,9 +471,7 @@ class Manager extends events_1.EventEmitter {
466
471
  case Enums_1.StateStorageType.Redis:
467
472
  {
468
473
  try {
469
- const redisKey = `${this.options.stateStorage.redisConfig.prefix?.endsWith(":")
470
- ? this.options.stateStorage.redisConfig.prefix
471
- : this.options.stateStorage.redisConfig.prefix ?? "magmastream:"}playerstore:${guildId}`;
474
+ const redisKey = `${Utils_1.PlayerUtils.getRedisKey()}playerstore:${guildId}`;
472
475
  await this.redis.set(redisKey, JSON.stringify(serializedPlayer));
473
476
  this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Player state saved to Redis: ${guildId}`);
474
477
  }
@@ -558,6 +561,7 @@ class Manager extends events_1.EventEmitter {
558
561
  token: state.voiceState.event.token,
559
562
  endpoint: state.voiceState.event.endpoint,
560
563
  sessionId: state.voiceState.sessionId,
564
+ channelId: state.voiceState.event.channel_id,
561
565
  },
562
566
  },
563
567
  });
@@ -579,7 +583,7 @@ class Manager extends events_1.EventEmitter {
579
583
  if (lavaPlayer.track) {
580
584
  await player.queue.clear();
581
585
  if (currentTrack) {
582
- await player.queue.add(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester));
586
+ await player.queue.add(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester, currentTrack.isAutoplay));
583
587
  }
584
588
  const remainingQueue = queueTracks.filter((t) => t.uri !== lavaPlayer.track.info.uri);
585
589
  if (remainingQueue.length > 0) {
@@ -720,9 +724,7 @@ class Manager extends events_1.EventEmitter {
720
724
  {
721
725
  try {
722
726
  // Get all keys matching our pattern
723
- const redisKeyPattern = `${this.options.stateStorage.redisConfig.prefix?.endsWith(":")
724
- ? this.options.stateStorage.redisConfig.prefix
725
- : this.options.stateStorage.redisConfig.prefix ?? "magmastream:"}playerstore:*`;
727
+ const redisKeyPattern = `${Utils_1.PlayerUtils.getRedisKey()}playerstore:*`;
726
728
  const keys = await this.redis.keys(redisKeyPattern);
727
729
  for (const key of keys) {
728
730
  try {
@@ -753,7 +755,14 @@ class Manager extends events_1.EventEmitter {
753
755
  const player = this.create(playerOptions);
754
756
  await player.node.rest.updatePlayer({
755
757
  guildId: state.options.guildId,
756
- data: { voice: { token: state.voiceState.event.token, endpoint: state.voiceState.event.endpoint, sessionId: state.voiceState.sessionId } },
758
+ data: {
759
+ voice: {
760
+ token: state.voiceState.event.token,
761
+ endpoint: state.voiceState.event.endpoint,
762
+ sessionId: state.voiceState.sessionId,
763
+ channelId: state.voiceState.event.channel_id,
764
+ },
765
+ },
757
766
  });
758
767
  player.connect();
759
768
  // Rest of the player state restoration code (tracks, filters, etc.)
@@ -774,7 +783,7 @@ class Manager extends events_1.EventEmitter {
774
783
  if (lavaPlayer.track) {
775
784
  await player.queue.clear();
776
785
  if (currentTrack) {
777
- await player.queue.add(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester));
786
+ await player.queue.add(Utils_1.TrackUtils.build(lavaPlayer.track, currentTrack.requester, currentTrack.isAutoplay));
778
787
  }
779
788
  const remainingQueue = queueTracks.filter((t) => t.uri !== lavaPlayer.track.info.uri);
780
789
  if (remainingQueue.length > 0) {
@@ -916,11 +925,7 @@ class Manager extends events_1.EventEmitter {
916
925
  * @returns {Node} The node to use.
917
926
  */
918
927
  get useableNode() {
919
- return this.options.enablePriorityMode
920
- ? this.priorityNode
921
- : this.options.useNode === Enums_1.UseNodeOptions.LeastLoad
922
- ? this.leastLoadNode.first()
923
- : this.leastPlayersNode.first();
928
+ return this.options.enablePriorityMode ? this.priorityNode : this.options.useNode === Enums_1.UseNodeOptions.LeastLoad ? this.leastLoadNode.first() : this.leastPlayersNode.first();
924
929
  }
925
930
  /**
926
931
  * Handles the shutdown of the process by saving all active players' states and optionally cleaning up inactive players.
@@ -1079,13 +1084,17 @@ class Manager extends events_1.EventEmitter {
1079
1084
  */
1080
1085
  async handleVoiceServerUpdate(player, update) {
1081
1086
  player.voiceState.event = update;
1082
- const { sessionId, event: { token, endpoint }, } = player.voiceState;
1087
+ const sessionId = player.voiceState.sessionId;
1088
+ const channelId = player.voiceState.channelId;
1089
+ const token = update.token;
1090
+ const endpoint = update.endpoint;
1091
+ this.emit(Enums_1.ManagerEventTypes.Debug, `Updated voice server for player ${player.guildId} with token ${token} | endpoint ${endpoint} | sessionId ${sessionId} | channelId ${channelId}`);
1092
+ if (!sessionId || !channelId)
1093
+ return;
1083
1094
  await player.node.rest.updatePlayer({
1084
1095
  guildId: player.guildId,
1085
- data: { voice: { token, endpoint, sessionId } },
1096
+ data: { voice: { token, endpoint, sessionId, channelId } },
1086
1097
  });
1087
- this.emit(Enums_1.ManagerEventTypes.Debug, `Updated voice server for player ${player.guildId} with token ${token} and endpoint ${endpoint} and sessionId ${sessionId}`);
1088
- return;
1089
1098
  }
1090
1099
  /**
1091
1100
  * Handles a voice state update by updating the player's voice channel and session ID if provided, or by disconnecting and destroying the player if the channel ID is null.
@@ -1096,22 +1105,30 @@ class Manager extends events_1.EventEmitter {
1096
1105
  */
1097
1106
  async handleVoiceStateUpdate(player, update) {
1098
1107
  this.emit(Enums_1.ManagerEventTypes.Debug, `Updated voice state for player ${player.guildId} with channel id ${update.channel_id} and session id ${update.session_id}`);
1099
- if (update.channel_id) {
1100
- if (player.voiceChannelId !== update.channel_id) {
1101
- this.emit(Enums_1.ManagerEventTypes.PlayerMove, player, player.voiceChannelId, update.channel_id);
1102
- }
1103
- player.voiceState.sessionId = update.session_id;
1104
- player.voiceChannelId = update.channel_id;
1105
- player.options.voiceChannelId = update.channel_id;
1108
+ if (!update.channel_id) {
1109
+ this.emit(Enums_1.ManagerEventTypes.PlayerDisconnect, player, player.voiceChannelId);
1110
+ player.voiceChannelId = null;
1111
+ player.state = Enums_1.StateTypes.Disconnected;
1112
+ player.voiceState = Object.assign({});
1113
+ if (player.options.pauseOnDisconnect)
1114
+ await player.pause(true);
1106
1115
  return;
1107
1116
  }
1108
- this.emit(Enums_1.ManagerEventTypes.PlayerDisconnect, player, player.voiceChannelId);
1109
- player.voiceChannelId = null;
1110
- player.voiceState = Object.assign({});
1111
- if (player.options.pauseOnDisconnect) {
1112
- await player.pause(true);
1117
+ if (player.voiceChannelId !== update.channel_id) {
1118
+ this.emit(Enums_1.ManagerEventTypes.PlayerMove, player, player.voiceChannelId, update.channel_id);
1113
1119
  }
1114
- return;
1120
+ player.voiceState.sessionId = update.session_id;
1121
+ player.voiceState.channelId = update.channel_id;
1122
+ player.voiceChannelId = update.channel_id;
1123
+ player.options.voiceChannelId = update.channel_id;
1124
+ const token = player.voiceState.event?.token;
1125
+ const endpoint = player.voiceState.event?.endpoint;
1126
+ if (!token || !endpoint)
1127
+ return;
1128
+ await player.node.rest.updatePlayer({
1129
+ guildId: player.guildId,
1130
+ data: { voice: { token, endpoint, sessionId: update.session_id, channelId: update.channel_id } },
1131
+ });
1115
1132
  }
1116
1133
  /**
1117
1134
  * Cleans up inactive players by removing their state files from the file system.
@@ -1154,9 +1171,7 @@ class Manager extends events_1.EventEmitter {
1154
1171
  break;
1155
1172
  case Enums_1.StateStorageType.Redis:
1156
1173
  {
1157
- const prefix = this.options.stateStorage.redisConfig.prefix?.endsWith(":")
1158
- ? this.options.stateStorage.redisConfig.prefix
1159
- : this.options.stateStorage.redisConfig.prefix ?? "magmastream:";
1174
+ const prefix = Utils_1.PlayerUtils.getRedisKey();
1160
1175
  const pattern = `${prefix}queue:*:current`;
1161
1176
  try {
1162
1177
  const stream = this.redis.scanStream({
@@ -1229,9 +1244,7 @@ class Manager extends events_1.EventEmitter {
1229
1244
  {
1230
1245
  try {
1231
1246
  if (!player) {
1232
- const prefix = this.options.stateStorage.redisConfig.prefix?.endsWith(":")
1233
- ? this.options.stateStorage.redisConfig.prefix
1234
- : `${this.options.stateStorage.redisConfig.prefix ?? "magmastream"}:`;
1247
+ const prefix = Utils_1.PlayerUtils.getRedisKey();
1235
1248
  const keysToDelete = [
1236
1249
  `${prefix}playerstore:${guildId}`,
1237
1250
  `${prefix}queue:${guildId}:tracks`,
@@ -1339,9 +1352,7 @@ class Manager extends events_1.EventEmitter {
1339
1352
  break;
1340
1353
  }
1341
1354
  case Enums_1.StateStorageType.Redis: {
1342
- const prefix = this.options.stateStorage.redisConfig.prefix?.endsWith(":")
1343
- ? this.options.stateStorage.redisConfig.prefix
1344
- : this.options.stateStorage.redisConfig.prefix ?? "magmastream:";
1355
+ const prefix = Utils_1.PlayerUtils.getRedisKey();
1345
1356
  const patterns = [`${prefix}playerstore:*`, `${prefix}queue:*`];
1346
1357
  try {
1347
1358
  for (const pattern of patterns) {
@@ -1440,6 +1451,9 @@ class Manager extends events_1.EventEmitter {
1440
1451
  }
1441
1452
  return this._send(packet);
1442
1453
  }
1454
+ getUserFromCache(id) {
1455
+ return this._getUser?.(id);
1456
+ }
1443
1457
  sendPacket(packet) {
1444
1458
  return this.send(packet);
1445
1459
  }