hoshimi 0.3.3 → 0.3.5

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.mjs CHANGED
@@ -98,6 +98,7 @@ var Events = /* @__PURE__ */ ((Events2) => {
98
98
  Events2["PlayerCreate"] = "playerCreate";
99
99
  Events2["PlayerUpdate"] = "playerUpdate";
100
100
  Events2["PlayerDestroy"] = "playerDestroy";
101
+ Events2["PlayerError"] = "playerError";
101
102
  Events2["TrackStart"] = "trackStart";
102
103
  Events2["TrackEnd"] = "trackEnd";
103
104
  Events2["TrackStuck"] = "trackStuck";
@@ -117,6 +118,8 @@ var DestroyReasons = /* @__PURE__ */ ((DestroyReasons2) => {
117
118
  DestroyReasons2["NodeDisconnected"] = "Player-NodeDisconnected";
118
119
  DestroyReasons2["NodeDestroy"] = "Player-NodeDestroy";
119
120
  DestroyReasons2["VoiceChannelDeleted"] = "Player-VoiceChannelDeleted";
121
+ DestroyReasons2["VoiceChannelLeft"] = "Player-VoiceChannelLeft";
122
+ DestroyReasons2["ReconnectFailed"] = "Player-ReconnectFailed";
120
123
  return DestroyReasons2;
121
124
  })(DestroyReasons || {});
122
125
 
@@ -304,7 +307,7 @@ var Track = class {
304
307
  pluginInfo;
305
308
  /**
306
309
  * The track user data.
307
- * @type {Record<string, unknown>}
310
+ * @type {TrackUserData}
308
311
  */
309
312
  userData;
310
313
  /**
@@ -374,7 +377,7 @@ var UnresolvedTrack = class {
374
377
  pluginInfo;
375
378
  /**
376
379
  * The track user data.
377
- * @type {Record<string, unknown> | undefined}
380
+ * @type {TrackUserData | undefined}
378
381
  */
379
382
  userData;
380
383
  /**
@@ -402,7 +405,7 @@ var UnresolvedTrack = class {
402
405
  constructor(track, requester) {
403
406
  this.info = track.info;
404
407
  this.encoded = track.encoded;
405
- this.requester = requester;
408
+ this.requester = requester ?? {};
406
409
  this.pluginInfo = track.pluginInfo;
407
410
  this.userData = track.userData ?? {};
408
411
  }
@@ -464,12 +467,20 @@ var UnresolvedTrack = class {
464
467
  // package.json
465
468
  var package_default = {
466
469
  name: "hoshimi",
467
- version: "0.3.3",
470
+ version: "0.3.5",
468
471
  description: "A lavalink@v4 client easy to use, up-to-date and all ears.",
469
472
  main: "./dist/index.js",
470
473
  module: "./dist/index.mjs",
471
474
  types: "./dist/index.d.ts",
472
- packageManager: "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501",
475
+ packageManager: "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a",
476
+ exports: {
477
+ ".": {
478
+ types: "./dist/index.d.ts",
479
+ require: "./dist/index.js",
480
+ import: "./dist/index.mjs",
481
+ default: "./dist/index.js"
482
+ }
483
+ },
473
484
  files: [
474
485
  "dist"
475
486
  ],
@@ -505,8 +516,8 @@ var package_default = {
505
516
  author: "Ganyu Studios",
506
517
  license: "MIT",
507
518
  devDependencies: {
508
- "@biomejs/biome": "^2.3.8",
509
- "@types/node": "^25.0.1",
519
+ "@biomejs/biome": "^2.3.11",
520
+ "@types/node": "^25.0.3",
510
521
  "@types/ws": "^8.18.1",
511
522
  husky: "^9.1.7",
512
523
  "lint-staged": "^16.2.7",
@@ -694,7 +705,7 @@ function validateManagerOptions(options) {
694
705
  throw new OptionError("The manager option 'options.nodes' must be a valid array of nodes and atleast one valid node.");
695
706
  if (typeof options.sendPayload !== "function")
696
707
  throw new OptionError("The manager option 'options.sendPayload' must be a vaid function.");
697
- if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.maxPreviousTracks !== "number")
708
+ if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.maxHistory !== "number")
698
709
  throw new OptionError("The manager option 'options.queueOptions.maxPreviousTracks' must be a number.");
699
710
  if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.autoplayFn !== "function")
700
711
  throw new OptionError("The manager option 'options.queueOptions.autoplayFn' must be a function.");
@@ -755,6 +766,11 @@ function validatePlayerData(data) {
755
766
  player.lastPosition = data.playerOptions.position;
756
767
  player.lastPositionUpdate = Date.now();
757
768
  }
769
+ if (typeof data.playerOptions.filters === "object") {
770
+ const timescale = Object.freeze({ ...player.filterManager.data.timescale });
771
+ Object.assign(player.filterManager.data, data.playerOptions.filters);
772
+ player.filterManager.check(timescale);
773
+ }
758
774
  }
759
775
  }
760
776
  function validateNodePlugins(node, plugins) {
@@ -779,9 +795,11 @@ function validateEngine(type) {
779
795
  }
780
796
  function validateTrack(player, track) {
781
797
  if (!track) return Promise.resolve(null);
782
- if (isTrack(track)) return Promise.resolve(new Track(track, track.requester));
798
+ const requesterFn2 = player.manager.options.playerOptions.requesterFn;
799
+ if (isTrack(track)) return Promise.resolve(new Track(track, requesterFn2(track.requester)));
783
800
  if (!isUnresolvedTrack(track)) throw new ResolveError("The track is not a valid unresolved track.");
784
- if (!track.resolve || typeof track.resolve !== "function") return new UnresolvedTrack(track, track.requester).resolve(player);
801
+ if (!track.resolve || typeof track.resolve !== "function")
802
+ return new UnresolvedTrack(track, requesterFn2(track.requester)).resolve(player);
785
803
  return track.resolve(player);
786
804
  }
787
805
  var isTrack = (track) => {
@@ -813,6 +831,9 @@ function stringify(value, space) {
813
831
  space
814
832
  );
815
833
  }
834
+ function requesterFn(requester) {
835
+ return requester;
836
+ }
816
837
  function isNode(options) {
817
838
  return typeof options.host === "string" && typeof options.port === "number" && typeof options.password === "string" && (typeof options.id === "string" || typeof options.id === "undefined") && (typeof options.secure === "boolean" || typeof options.secure === "undefined") && (typeof options.sessionId === "string" || typeof options.sessionId === "undefined") && (typeof options.retryAmount === "number" || typeof options.retryAmount === "undefined") && (typeof options.retryDelay === "number" || typeof options.retryDelay === "undefined");
818
839
  }
@@ -1311,8 +1332,8 @@ async function onEnd() {
1311
1332
  (x) => x.info.identifier === this.queue.current.info.identifier && x.info.title === this.queue.current.info.title
1312
1333
  )) {
1313
1334
  this.queue.history.unshift(this.queue.current);
1314
- if (this.queue.history.length > this.manager.options.queueOptions.maxPreviousTracks)
1315
- this.queue.history.splice(this.manager.options.queueOptions.maxPreviousTracks, this.queue.history.length);
1335
+ if (this.queue.history.length > this.manager.options.queueOptions.maxHistory)
1336
+ this.queue.history.splice(this.manager.options.queueOptions.maxHistory, this.queue.history.length);
1316
1337
  await this.queue.utils.save();
1317
1338
  this.manager.emit(
1318
1339
  "debug" /* Debug */,
@@ -1322,7 +1343,7 @@ async function onEnd() {
1322
1343
  }
1323
1344
  if (this.loop === 1 /* Track */ && this.queue.current) this.queue.unshift(this.queue.current);
1324
1345
  if (this.loop === 2 /* Queue */ && this.queue.current) this.queue.add(this.queue.current);
1325
- if (!this.queue.current) this.queue.current = await validateTrack(this, this.queue.shift());
1346
+ if (!this.queue.current) this.queue.current = await validateTrack(this, await this.queue.shift());
1326
1347
  await this.queue.utils.save();
1327
1348
  return;
1328
1349
  }
@@ -1469,6 +1490,43 @@ async function socketClosed(payload) {
1469
1490
  `[Player] -> [Socket] The socket has closed: ${this.guildId} | Payload: ${stringify(payload)}`
1470
1491
  );
1471
1492
  }
1493
+ async function resumeByLibrary(players) {
1494
+ this.nodeManager.manager.emit("debug" /* Debug */, 2 /* Node */, `[Socket] -> [${this.id}]: Resuming session by library...`);
1495
+ for (const player of players) {
1496
+ try {
1497
+ if (!player.playing && !player.paused && !player.queue.totalSize) {
1498
+ this.nodeManager.manager.emit(
1499
+ "debug" /* Debug */,
1500
+ 2 /* Node */,
1501
+ `[Player] -> [Resume] Destroyed player for guild ${player.guildId} due to empty queue.`
1502
+ );
1503
+ await player.destroy();
1504
+ return;
1505
+ }
1506
+ const track = player.queue.current;
1507
+ await player.node.updatePlayer({
1508
+ guildId: player.guildId,
1509
+ playerOptions: { voice: player.voice }
1510
+ });
1511
+ await player.connect();
1512
+ await player.queue.utils.sync(false, true);
1513
+ if (track)
1514
+ await player.play({
1515
+ track,
1516
+ noReplace: false,
1517
+ position: player.lastPosition,
1518
+ paused: player.paused
1519
+ });
1520
+ } catch (error) {
1521
+ this.nodeManager.manager.emit("nodeError" /* NodeError */, this, error);
1522
+ }
1523
+ this.nodeManager.manager.emit(
1524
+ "debug" /* Debug */,
1525
+ 2 /* Node */,
1526
+ `[Player] -> [Resume] Resumed player for guild ${player.guildId} using the library.`
1527
+ );
1528
+ }
1529
+ }
1472
1530
 
1473
1531
  // src/util/events/websocket.ts
1474
1532
  function onOpen(res) {
@@ -1541,34 +1599,37 @@ async function onMessage(message) {
1541
1599
  this.sessionId = payload.sessionId;
1542
1600
  this.session.resuming = payload.resumed;
1543
1601
  if (payload.resumed) {
1544
- const players = await this.rest.request({
1602
+ const players2 = await this.rest.request({
1545
1603
  endpoint: `/sessions/${payload.sessionId}/players`
1546
1604
  }) ?? [];
1547
1605
  const timeout = this.nodeManager.manager.options.nodeOptions.resumeTimeout;
1548
- this.nodeManager.manager.emit("nodeResumed" /* NodeResumed */, this, players, payload);
1606
+ this.nodeManager.manager.emit("nodeResumed" /* NodeResumed */, this, players2, payload);
1549
1607
  this.nodeManager.manager.emit(
1550
1608
  "debug" /* Debug */,
1551
1609
  2 /* Node */,
1552
- `[Socket] <- [${this.id}]: Resumed session. | Session id: ${payload.sessionId} | Players: ${players.length} | Resumed: ${payload.resumed} | Timeout: ${timeout}ms`
1610
+ `[Socket] <- [${this.id}]: Resumed session. | Session id: ${payload.sessionId} | Players: ${players2.length} | Resumed: ${payload.resumed} | Timeout: ${timeout}ms`
1553
1611
  );
1554
1612
  }
1613
+ const players = this.nodeManager.manager.players.filter((p) => p.node.id === this.id);
1614
+ const isLibrary = this.nodeManager.manager.options.nodeOptions.resumeByLibrary;
1615
+ if (!payload.resumed && isLibrary && players.length) await resumeByLibrary.call(this, players);
1555
1616
  this.info = await this.rest.request({ endpoint: "/info" });
1556
- this.nodeManager.manager.emit(
1557
- "debug" /* Debug */,
1558
- 2 /* Node */,
1559
- `[Socket] <- [${this.id}]: Received ready event. | Session id: ${payload.sessionId} | Resumed: ${payload.resumed}`
1560
- );
1561
- this.nodeManager.manager.emit("nodeReady" /* NodeReady */, this, this.retryAmount, payload);
1562
1617
  const isResumable = this.nodeManager.manager.options.nodeOptions.resumable;
1563
1618
  if (isResumable) {
1564
1619
  const timeout = this.nodeManager.manager.options.nodeOptions.resumeTimeout;
1565
1620
  this.nodeManager.manager.emit(
1566
1621
  "debug" /* Debug */,
1567
1622
  2 /* Node */,
1568
- `[Socket] -> [${this.id}]: Resuming session... | Timeout: ${timeout}ms`
1623
+ `[Socket] -> [${this.id}]: Setting timeout to resume session. | Timeout: ${timeout}ms`
1569
1624
  );
1570
1625
  await this.updateSession(isResumable, timeout);
1571
1626
  }
1627
+ this.nodeManager.manager.emit(
1628
+ "debug" /* Debug */,
1629
+ 2 /* Node */,
1630
+ `[Socket] <- [${this.id}]: Received ready event. | Session id: ${payload.sessionId} | Resumed: ${payload.resumed}`
1631
+ );
1632
+ this.nodeManager.manager.emit("nodeReady" /* NodeReady */, this, this.retryAmount, payload);
1572
1633
  }
1573
1634
  break;
1574
1635
  case "event" /* Event */: {
@@ -3295,15 +3356,7 @@ var Player = class {
3295
3356
  */
3296
3357
  async disconnect() {
3297
3358
  if (!this.voiceId) return this;
3298
- await this.manager.options.sendPayload(this.guildId, {
3299
- op: 4,
3300
- d: {
3301
- guild_id: this.guildId,
3302
- channel_id: null,
3303
- self_deaf: this.selfDeaf,
3304
- self_mute: this.selfMute
3305
- }
3306
- });
3359
+ await this.setVoice({ voiceId: null });
3307
3360
  this.manager.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Disconnect] Player disconnected for guild: ${this.guildId}`);
3308
3361
  this.connected = false;
3309
3362
  return this;
@@ -3349,7 +3402,7 @@ var Player = class {
3349
3402
  async play(options = {}) {
3350
3403
  if (typeof options !== "object") throw new PlayerError("The play options must be an object.");
3351
3404
  if (options.track) this.queue.current = await validateTrack(this, options.track);
3352
- else if (!this.queue.current) this.queue.current = await validateTrack(this, this.queue.shift());
3405
+ else if (!this.queue.current) this.queue.current = await validateTrack(this, await this.queue.shift());
3353
3406
  if (!this.queue.current) throw new PlayerError("No track to play.");
3354
3407
  if (!isTrack(this.queue.current) && !isUnresolvedTrack(this.queue.current))
3355
3408
  throw new PlayerError("The track must be a valid Track or UnresolvedTrack instance.");
@@ -3382,15 +3435,7 @@ var Player = class {
3382
3435
  */
3383
3436
  async connect() {
3384
3437
  if (!this.voiceId) return this;
3385
- await this.manager.options.sendPayload(this.guildId, {
3386
- op: 4,
3387
- d: {
3388
- guild_id: this.guildId,
3389
- channel_id: this.voiceId,
3390
- self_deaf: this.selfDeaf,
3391
- self_mute: this.selfMute
3392
- }
3393
- });
3438
+ await this.setVoice();
3394
3439
  this.manager.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Connect] Player connected for guild: ${this.guildId}`);
3395
3440
  this.connected = true;
3396
3441
  return this;
@@ -3489,7 +3534,7 @@ var Player = class {
3489
3534
  }
3490
3535
  /**
3491
3536
  * Set the voice of the player.
3492
- * @param {Partial<VoiceChannelUpdate>} voice The voice state to set.
3537
+ * @param {NullableVoiceChannelUpdate} options The voice state to set.
3493
3538
  * @returns {Promise<void>}
3494
3539
  * @example
3495
3540
  * ```ts
@@ -3497,27 +3542,17 @@ var Player = class {
3497
3542
  * player.setVoice({ voiceId: "newVoiceId" });
3498
3543
  * ```
3499
3544
  */
3500
- async setVoice(voice) {
3501
- if (voice.voiceId === this.voiceId) return;
3502
- if (voice.voiceId) {
3503
- this.voiceId = voice.voiceId;
3504
- this.options.voiceId = voice.voiceId;
3505
- }
3506
- if (voice.selfDeaf) {
3507
- this.selfDeaf = voice.selfDeaf;
3508
- this.options.selfDeaf = voice.selfDeaf;
3509
- }
3510
- if (voice.selfMute) {
3511
- this.selfMute = voice.selfMute;
3512
- this.options.selfMute = voice.selfMute;
3513
- }
3545
+ async setVoice(options = {}) {
3546
+ options.voiceId ??= this.voiceId;
3547
+ options.selfDeaf ??= this.selfDeaf;
3548
+ options.selfMute ??= this.selfMute;
3514
3549
  await this.manager.options.sendPayload(this.guildId, {
3515
3550
  op: 4,
3516
3551
  d: {
3517
3552
  guild_id: this.guildId,
3518
- self_deaf: this.selfDeaf,
3519
- self_mute: this.selfMute,
3520
- channel_id: this.voiceId ?? null
3553
+ self_deaf: options.selfDeaf,
3554
+ self_mute: options.selfMute,
3555
+ channel_id: options.voiceId ?? null
3521
3556
  }
3522
3557
  });
3523
3558
  this.manager.emit(
@@ -3734,16 +3769,15 @@ var QueueUtils = class {
3734
3769
  * ```
3735
3770
  */
3736
3771
  save() {
3737
- const max = this.options.maxPreviousTracks;
3772
+ const max = this.options.maxHistory;
3738
3773
  const length = this.queue.tracks.length;
3739
- const json = this.queue.toJSON();
3740
3774
  if (length > max) this.queue.history.splice(0, length - max);
3741
3775
  this.queue.player.manager.emit(
3742
3776
  "debug" /* Debug */,
3743
3777
  5 /* Queue */,
3744
- `[Queue] -> [Adapter] Saving queue for ${this.queue.player.guildId} | Object: ${stringify(json)}`
3778
+ `[Queue] -> [Adapter] Saving queue for ${this.queue.player.guildId} | Object: ${stringify(this.queue.toJSON())}`
3745
3779
  );
3746
- return this.store.set(this.queue.player.guildId, json);
3780
+ return this.store.set(this.queue.player.guildId, this.queue.toJSON());
3747
3781
  }
3748
3782
  /**
3749
3783
  *
@@ -3909,25 +3943,50 @@ var Queue = class {
3909
3943
  isEmpty() {
3910
3944
  return this.size === 0;
3911
3945
  }
3946
+ /**
3947
+ *
3948
+ * Build a track from a Lavalink track or unresolved Lavalink track.
3949
+ * @param {LavalinkTrack | UnresolvedLavalinkTrack} track The track to build.
3950
+ * @param {TrackRequester} requester The requester of the track.
3951
+ * @returns {Promise<Track>} The built track.
3952
+ * @example
3953
+ * ```ts
3954
+ * const queue = player.queue;
3955
+ * const lavalinkTrack = {...} // some lavalink track
3956
+ * const track = await queue.build(lavalinkTrack, author);
3957
+ *
3958
+ * console.log(track.info.title); // The title of the track
3959
+ * ```
3960
+ */
3961
+ async build(track, requester) {
3962
+ const requesterFn2 = this.player.manager.options.playerOptions.requesterFn;
3963
+ if (isUnresolvedTrack(track)) return new UnresolvedTrack(track, requesterFn2(requester)).resolve(this.player);
3964
+ if (isTrack(track)) return new Track(track, requesterFn2(requester));
3965
+ return track;
3966
+ }
3912
3967
  /**
3913
3968
  *
3914
3969
  * Get the previous track of the queue.
3915
3970
  * @param {boolean} [remove=false] Whether to remove the track from the previous queue.
3916
- * @returns {Track | null} The previous track of the queue.
3971
+ * @returns {Promise<Track | null>} The previous track of the queue.
3917
3972
  * @example
3918
3973
  * ```ts
3919
3974
  * const queue = player.queue;
3920
3975
  *
3921
- * console.log(queue.previous()); // null
3976
+ * console.log(await queue.previous()); // null
3922
3977
  * queue.add(track);
3923
3978
  * queue.add(track2);
3924
3979
  *
3925
- * console.log(queue.previous()); // track
3926
- * console.log(queue.previous(true)); // track and remove it from the previous tracks
3980
+ * console.log(await queue.previous()); // track
3981
+ * console.log(await queue.previous(true)); // track and remove it from the previous tracks
3927
3982
  * ```
3928
3983
  */
3929
- previous(remove = false) {
3930
- if (remove) return this.history.shift() ?? null;
3984
+ async previous(remove = false) {
3985
+ if (remove) {
3986
+ const track = this.history.shift() ?? null;
3987
+ if (track) await this.utils.save();
3988
+ return track;
3989
+ }
3931
3990
  return this.history[0] ?? null;
3932
3991
  }
3933
3992
  /**
@@ -3935,94 +3994,98 @@ var Queue = class {
3935
3994
  * Add a track or tracks to the queue.
3936
3995
  * @param {Track | Track[]} track The track or tracks to add.
3937
3996
  * @param {number} [position] The position to add the track or tracks.
3938
- * @returns {this} The queue instance.
3997
+ * @returns {Promise<this>} The queue instance.
3939
3998
  * @example
3940
3999
  * ```ts
3941
4000
  * const queue = player.queue;
3942
4001
  *
3943
4002
  * console.log(queue.size); // 0
3944
4003
  *
3945
- * queue.add(track);
4004
+ * await queue.add(track);
3946
4005
  * console.log(queue.size); // 1
3947
4006
  *
3948
- * queue.add([track1, track2]);
4007
+ * await queue.add([track1, track2]);
3949
4008
  * console.log(queue.size); // 3
3950
4009
  *
3951
- * queue.add(track3, 1);
4010
+ * await queue.add(track3, 1);
3952
4011
  * console.log(queue.size); // 4
3953
4012
  * console.log(queue.tracks); // [track1, track3, track2, track]
3954
4013
  * ```
3955
4014
  */
3956
- add(track, position) {
4015
+ async add(track, position) {
3957
4016
  const tracks = Array.isArray(track) ? track : [track];
3958
4017
  if (typeof position === "number" && position >= 0 && position < this.tracks.length) return this.splice(position, 0, ...tracks);
3959
4018
  this.tracks.push(...tracks);
3960
4019
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
3961
4020
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Add] Added ${this.tracks.length} tracks to the queue.`);
4021
+ await this.utils.save();
3962
4022
  return this;
3963
4023
  }
3964
4024
  /**
3965
4025
  *
3966
4026
  * Get the first track of the queue.
3967
- * @returns {HoshimiTrack | null} The first track of the queue.
4027
+ * @returns {Promise<HoshimiTrack | null>} The first track of the queue.
3968
4028
  * @example
3969
4029
  * ```ts
3970
4030
  * const queue = player.queue;
3971
4031
  *
3972
- * console.log(queue.shift()); // null
3973
- * queue.add(track);
4032
+ * console.log(await queue.shift()); // null
4033
+ * await queue.add(track);
3974
4034
  *
3975
- * console.log(queue.shift()); // track
3976
- * queue.add(track2);
4035
+ * console.log(await queue.shift()); // track
4036
+ * await queue.add(track2);
3977
4037
  * ```
3978
4038
  */
3979
- shift() {
3980
- return this.tracks.shift() ?? null;
4039
+ async shift() {
4040
+ const track = this.tracks.shift() ?? null;
4041
+ if (track) await this.utils.save();
4042
+ return track;
3981
4043
  }
3982
4044
  /**
3983
4045
  *
3984
4046
  * Add tracks to the beginning of the queue.
3985
4047
  * @param {Track[]} tracks The tracks to add.
3986
- * @returns {this} The queue instance.
4048
+ * @returns {Promise<this>} The queue instance.
3987
4049
  * @example
3988
4050
  * ```ts
3989
4051
  * const queue = player.queue;
3990
4052
  *
3991
4053
  * console.log(queue.size); // 0
3992
- * queue.unshift(track);
4054
+ * await queue.unshift(track);
3993
4055
  *
3994
4056
  * console.log(queue.size); // 1
3995
- * queue.unshift([track1, track2]);
4057
+ * await queue.unshift(track1, track2);
3996
4058
  *
3997
4059
  * console.log(queue.size); // 3
3998
4060
  * console.log(queue.tracks); // [track1, track2, track]
3999
4061
  * ```
4000
4062
  */
4001
- unshift(...tracks) {
4063
+ async unshift(...tracks) {
4002
4064
  this.tracks.unshift(...tracks);
4003
4065
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Unshift] Added ${this.tracks.length} tracks to the queue.`);
4066
+ await this.utils.save();
4004
4067
  return this;
4005
4068
  }
4006
4069
  /**
4007
4070
  *
4008
4071
  * Shuffle the queue.
4009
- * @returns {this} The queue instance.
4072
+ * @returns {Promise<this>} The queue instance.
4010
4073
  * @example
4011
4074
  * ```ts
4012
4075
  * const queue = player.queue;
4013
4076
  *
4014
4077
  * console.log(queue.size); // 0
4015
- * queue.add(track);
4016
- * queue.add([track1, track2]);
4078
+ * await queue.add(track);
4079
+ * await queue.add(track1, track2);
4017
4080
  *
4018
4081
  * console.log(queue.size); // 3
4019
4082
  * console.log(queue.tracks); // [track, track1, track2]
4020
4083
  *
4021
- * queue.shuffle();
4084
+ * await queue.shuffle();
4022
4085
  * console.log(queue.tracks); // [track2, track, track1]
4023
4086
  * ```
4024
4087
  */
4025
- shuffle() {
4088
+ async shuffle() {
4026
4089
  if (this.size <= 1) return this;
4027
4090
  if (this.size === 2) [this.tracks[0], this.tracks[1]] = [this.tracks[1], this.tracks[0]];
4028
4091
  else {
@@ -4033,31 +4096,33 @@ var Queue = class {
4033
4096
  }
4034
4097
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4035
4098
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, "[Queue] -> [Shuffle] Shuffled the queue.");
4099
+ await this.utils.save();
4036
4100
  return this;
4037
4101
  }
4038
4102
  /**
4039
4103
  *
4040
4104
  * Clear the queue.
4041
- * @returns {this} The queue instance.
4105
+ * @returns {Promise<this>} The queue instance.
4042
4106
  * @example
4043
4107
  * ```ts
4044
4108
  * const queue = player.queue;
4045
4109
  *
4046
4110
  * console.log(queue.size); // 0
4047
- * queue.add(track);
4048
- * queue.add([track1, track2]);
4111
+ * await queue.add(track);
4112
+ * await queue.add(track1, track2);
4049
4113
  *
4050
4114
  * console.log(queue.size); // 3
4051
- * queue.clear();
4115
+ * await queue.clear();
4052
4116
  * console.log(queue.size); // 0
4053
4117
  * ```
4054
4118
  */
4055
- clear() {
4119
+ async clear() {
4056
4120
  this.tracks = [];
4057
4121
  this.history = [];
4058
4122
  this.current = null;
4059
4123
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4060
4124
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, "[Queue] -> [Clear] Cleared the queue.");
4125
+ await this.utils.save();
4061
4126
  return this;
4062
4127
  }
4063
4128
  /**
@@ -4065,15 +4130,16 @@ var Queue = class {
4065
4130
  * Move a track to a specific position in the queue.
4066
4131
  * @param {Track} track The track to move.
4067
4132
  * @param {number} to The position to move.
4068
- * @returns {this} The queue instance.
4133
+ * @returns {Promise<this>} The queue instance.
4069
4134
  */
4070
- move(track, to) {
4135
+ async move(track, to) {
4071
4136
  const index = this.tracks.indexOf(track);
4072
4137
  if (index === -1) return this;
4073
- this.splice(index, 1);
4074
- this.add(track, to - 1);
4138
+ await this.splice(index, 1);
4139
+ await this.add(track, to - 1);
4075
4140
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4076
4141
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Move] Moved track ${track.info.title} to position ${to}.`);
4142
+ await this.utils.save();
4077
4143
  return this;
4078
4144
  }
4079
4145
  /**
@@ -4082,14 +4148,15 @@ var Queue = class {
4082
4148
  * @param {number} start The start index.
4083
4149
  * @param {number} deleteCount The number of tracks to delete.
4084
4150
  * @param {Track | Track[]} [tracks] The tracks to add.
4085
- * @returns {this} The queue instance.
4151
+ * @returns {Promise<this>} The queue instance.
4086
4152
  */
4087
- splice(start, deleteCount, tracks) {
4088
- if (!this.size && tracks) this.add(tracks);
4153
+ async splice(start, deleteCount, tracks) {
4154
+ if (!this.size && tracks) await this.add(tracks);
4089
4155
  if (tracks) this.tracks.splice(start, deleteCount, ...Array.isArray(tracks) ? tracks : [tracks]);
4090
4156
  else this.tracks.splice(start, deleteCount);
4091
4157
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4092
4158
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Splice] Removed ${deleteCount} tracks from the queue.`);
4159
+ await this.utils.save();
4093
4160
  return this;
4094
4161
  }
4095
4162
  /**
@@ -4098,7 +4165,7 @@ var Queue = class {
4098
4165
  * @returns {QueueJson} The queue JSON object.
4099
4166
  */
4100
4167
  toJSON() {
4101
- const max = this.player.manager.options.queueOptions.maxPreviousTracks;
4168
+ const max = this.player.manager.options.queueOptions.maxHistory;
4102
4169
  if (this.history.length > max) this.history.splice(max, this.history.length);
4103
4170
  return {
4104
4171
  tracks: this.tracks,
@@ -4264,10 +4331,24 @@ var Hoshimi = class extends EventEmitter {
4264
4331
  * resumeByLibrary: false,
4265
4332
  * },
4266
4333
  * queueOptions: {
4267
- * maxPreviousTracks: 25,
4268
- * autoplayFn: autoplayFn,
4269
- * autoPlay: false,
4334
+ * maxHistory: 25,
4335
+ * autoplayFn: autoplayFn,
4336
+ * autoPlay: false,
4337
+ * storage: new MemoryAdapter(),
4338
+ * requesterFn: defaultRequesterFn,
4270
4339
  * },
4340
+ * playerOptions: {
4341
+ * onDisconnect: {
4342
+ * autoDestroy: false,
4343
+ * autoReconnect: false,
4344
+ * autoQueue: false,
4345
+ * },
4346
+ * onError: {
4347
+ * autoDestroy: false,
4348
+ * autoSkip: false,
4349
+ * autoStop: false,
4350
+ * },
4351
+ * },
4271
4352
  * });
4272
4353
  *
4273
4354
  * console.log(manager); // The manager instance
@@ -4289,11 +4370,24 @@ var Hoshimi = class extends EventEmitter {
4289
4370
  resumeTimeout: options.nodeOptions?.resumeTimeout ?? 1e4
4290
4371
  },
4291
4372
  queueOptions: {
4292
- maxPreviousTracks: options.queueOptions?.maxPreviousTracks ?? 25,
4373
+ maxHistory: options.queueOptions?.maxHistory ?? 25,
4293
4374
  autoplayFn: options.queueOptions?.autoplayFn ?? autoplayFn,
4294
4375
  autoPlay: options.queueOptions?.autoPlay ?? false,
4295
4376
  storage: options.queueOptions?.storage ?? new MemoryAdapter()
4296
4377
  },
4378
+ playerOptions: {
4379
+ requesterFn: options.playerOptions?.requesterFn ?? requesterFn,
4380
+ onDisconnect: {
4381
+ autoDestroy: options.playerOptions?.onDisconnect?.autoDestroy ?? false,
4382
+ autoReconnect: options.playerOptions?.onDisconnect?.autoReconnect ?? true,
4383
+ autoQueue: options.playerOptions?.onDisconnect?.autoQueue ?? false
4384
+ },
4385
+ onError: {
4386
+ autoDestroy: options.playerOptions?.onError?.autoDestroy ?? false,
4387
+ autoSkip: options.playerOptions?.onError?.autoSkip ?? false,
4388
+ autoStop: options.playerOptions?.onError?.autoStop ?? false
4389
+ }
4390
+ },
4297
4391
  client: {
4298
4392
  id: options.client?.id ?? "",
4299
4393
  username: options.client?.username ?? "hoshimi-client"
@@ -4430,6 +4524,56 @@ var Hoshimi = class extends EventEmitter {
4430
4524
  );
4431
4525
  return;
4432
4526
  }
4527
+ if ("channel_id" in data && typeof data.channel_id === "string") {
4528
+ if (data.channel_id !== player.voiceId) {
4529
+ this.emit(
4530
+ "debug" /* Debug */,
4531
+ 3 /* Player */,
4532
+ `[Player] -> [Voice] Updating the voice channel for: ${data.guild_id} | Old: ${player.voiceId} | New: ${data.channel_id}`
4533
+ );
4534
+ player.voice.sessionId = data.session_id ?? player.voice.sessionId;
4535
+ player.voiceId = data.channel_id;
4536
+ player.options.voiceId = data.channel_id;
4537
+ if (!player.connected) await player.connect();
4538
+ return;
4539
+ }
4540
+ } else {
4541
+ this.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Voice] The channel id is missing for: ${data.guild_id}`);
4542
+ const { autoDestroy, autoReconnect, autoQueue } = this.options.playerOptions.onDisconnect;
4543
+ if (autoDestroy) {
4544
+ await player.destroy("Player-VoiceChannelLeft" /* VoiceChannelLeft */);
4545
+ return;
4546
+ }
4547
+ if (autoReconnect) {
4548
+ try {
4549
+ const position = player.position;
4550
+ const paused = player.paused;
4551
+ this.emit(
4552
+ "debug" /* Debug */,
4553
+ 3 /* Player */,
4554
+ `[Player] -> [Voice] Attempting to reconnect the player for: ${data.guild_id}`
4555
+ );
4556
+ if (autoQueue && player.queue.current && !player.queue.isEmpty()) await player.connect();
4557
+ if (player.queue.current) return player.play({ track: player.queue.current, paused, position });
4558
+ if (!player.queue.isEmpty()) return player.play({ paused });
4559
+ this.emit(
4560
+ "debug" /* Debug */,
4561
+ 3 /* Player */,
4562
+ `[Player] -> [Voice] No tracks to play after reconnect for: ${data.guild_id}`
4563
+ );
4564
+ } catch (error) {
4565
+ this.emit("playerError" /* PlayerError */, player, error);
4566
+ await player.destroy("Player-ReconnectFailed" /* ReconnectFailed */);
4567
+ }
4568
+ }
4569
+ player.voiceId = void 0;
4570
+ player.voice = {
4571
+ endpoint: null,
4572
+ sessionId: null,
4573
+ token: null
4574
+ };
4575
+ return;
4576
+ }
4433
4577
  this.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Voice] The player voice is missing for: ${data.guild_id}`);
4434
4578
  }
4435
4579
  break;
@@ -4539,6 +4683,7 @@ var Hoshimi = class extends EventEmitter {
4539
4683
  1 /* Manager */,
4540
4684
  `[Manager] -> [Search] Searching for: ${options.query} (${options.engine ?? "unknown"}) | Result: ${stringify(res)}`
4541
4685
  );
4686
+ const requesterFn2 = this.options.playerOptions.requesterFn;
4542
4687
  switch (res.loadType) {
4543
4688
  case "empty" /* Empty */: {
4544
4689
  return {
@@ -4564,7 +4709,7 @@ var Hoshimi = class extends EventEmitter {
4564
4709
  exception: null,
4565
4710
  playlist: res.data,
4566
4711
  pluginInfo: res.data.pluginInfo,
4567
- tracks: res.data.tracks.map((t) => new Track(t, options.requester))
4712
+ tracks: res.data.tracks.map((t) => new Track(t, requesterFn2(options.requester)))
4568
4713
  };
4569
4714
  }
4570
4715
  case "search" /* Search */: {
@@ -4573,7 +4718,7 @@ var Hoshimi = class extends EventEmitter {
4573
4718
  exception: null,
4574
4719
  playlist: null,
4575
4720
  pluginInfo: null,
4576
- tracks: res.data.map((t) => new Track(t, options.requester))
4721
+ tracks: res.data.map((t) => new Track(t, requesterFn2(options.requester)))
4577
4722
  };
4578
4723
  }
4579
4724
  case "track" /* Track */: {
@@ -4582,7 +4727,7 @@ var Hoshimi = class extends EventEmitter {
4582
4727
  exception: null,
4583
4728
  playlist: null,
4584
4729
  pluginInfo: res.data.pluginInfo,
4585
- tracks: [new Track(res.data, options.requester)]
4730
+ tracks: [new Track(res.data, requesterFn2(options.requester))]
4586
4731
  };
4587
4732
  }
4588
4733
  }