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.js CHANGED
@@ -165,6 +165,7 @@ var Events = /* @__PURE__ */ ((Events2) => {
165
165
  Events2["PlayerCreate"] = "playerCreate";
166
166
  Events2["PlayerUpdate"] = "playerUpdate";
167
167
  Events2["PlayerDestroy"] = "playerDestroy";
168
+ Events2["PlayerError"] = "playerError";
168
169
  Events2["TrackStart"] = "trackStart";
169
170
  Events2["TrackEnd"] = "trackEnd";
170
171
  Events2["TrackStuck"] = "trackStuck";
@@ -184,6 +185,8 @@ var DestroyReasons = /* @__PURE__ */ ((DestroyReasons2) => {
184
185
  DestroyReasons2["NodeDisconnected"] = "Player-NodeDisconnected";
185
186
  DestroyReasons2["NodeDestroy"] = "Player-NodeDestroy";
186
187
  DestroyReasons2["VoiceChannelDeleted"] = "Player-VoiceChannelDeleted";
188
+ DestroyReasons2["VoiceChannelLeft"] = "Player-VoiceChannelLeft";
189
+ DestroyReasons2["ReconnectFailed"] = "Player-ReconnectFailed";
187
190
  return DestroyReasons2;
188
191
  })(DestroyReasons || {});
189
192
 
@@ -371,7 +374,7 @@ var Track = class {
371
374
  pluginInfo;
372
375
  /**
373
376
  * The track user data.
374
- * @type {Record<string, unknown>}
377
+ * @type {TrackUserData}
375
378
  */
376
379
  userData;
377
380
  /**
@@ -441,7 +444,7 @@ var UnresolvedTrack = class {
441
444
  pluginInfo;
442
445
  /**
443
446
  * The track user data.
444
- * @type {Record<string, unknown> | undefined}
447
+ * @type {TrackUserData | undefined}
445
448
  */
446
449
  userData;
447
450
  /**
@@ -469,7 +472,7 @@ var UnresolvedTrack = class {
469
472
  constructor(track, requester) {
470
473
  this.info = track.info;
471
474
  this.encoded = track.encoded;
472
- this.requester = requester;
475
+ this.requester = requester ?? {};
473
476
  this.pluginInfo = track.pluginInfo;
474
477
  this.userData = track.userData ?? {};
475
478
  }
@@ -531,12 +534,20 @@ var UnresolvedTrack = class {
531
534
  // package.json
532
535
  var package_default = {
533
536
  name: "hoshimi",
534
- version: "0.3.3",
537
+ version: "0.3.5",
535
538
  description: "A lavalink@v4 client easy to use, up-to-date and all ears.",
536
539
  main: "./dist/index.js",
537
540
  module: "./dist/index.mjs",
538
541
  types: "./dist/index.d.ts",
539
- packageManager: "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501",
542
+ packageManager: "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a",
543
+ exports: {
544
+ ".": {
545
+ types: "./dist/index.d.ts",
546
+ require: "./dist/index.js",
547
+ import: "./dist/index.mjs",
548
+ default: "./dist/index.js"
549
+ }
550
+ },
540
551
  files: [
541
552
  "dist"
542
553
  ],
@@ -572,8 +583,8 @@ var package_default = {
572
583
  author: "Ganyu Studios",
573
584
  license: "MIT",
574
585
  devDependencies: {
575
- "@biomejs/biome": "^2.3.8",
576
- "@types/node": "^25.0.1",
586
+ "@biomejs/biome": "^2.3.11",
587
+ "@types/node": "^25.0.3",
577
588
  "@types/ws": "^8.18.1",
578
589
  husky: "^9.1.7",
579
590
  "lint-staged": "^16.2.7",
@@ -761,7 +772,7 @@ function validateManagerOptions(options) {
761
772
  throw new OptionError("The manager option 'options.nodes' must be a valid array of nodes and atleast one valid node.");
762
773
  if (typeof options.sendPayload !== "function")
763
774
  throw new OptionError("The manager option 'options.sendPayload' must be a vaid function.");
764
- if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.maxPreviousTracks !== "number")
775
+ if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.maxHistory !== "number")
765
776
  throw new OptionError("The manager option 'options.queueOptions.maxPreviousTracks' must be a number.");
766
777
  if (typeof options.queueOptions !== "undefined" && typeof options.queueOptions.autoplayFn !== "function")
767
778
  throw new OptionError("The manager option 'options.queueOptions.autoplayFn' must be a function.");
@@ -822,6 +833,11 @@ function validatePlayerData(data) {
822
833
  player.lastPosition = data.playerOptions.position;
823
834
  player.lastPositionUpdate = Date.now();
824
835
  }
836
+ if (typeof data.playerOptions.filters === "object") {
837
+ const timescale = Object.freeze({ ...player.filterManager.data.timescale });
838
+ Object.assign(player.filterManager.data, data.playerOptions.filters);
839
+ player.filterManager.check(timescale);
840
+ }
825
841
  }
826
842
  }
827
843
  function validateNodePlugins(node, plugins) {
@@ -846,9 +862,11 @@ function validateEngine(type) {
846
862
  }
847
863
  function validateTrack(player, track) {
848
864
  if (!track) return Promise.resolve(null);
849
- if (isTrack(track)) return Promise.resolve(new Track(track, track.requester));
865
+ const requesterFn2 = player.manager.options.playerOptions.requesterFn;
866
+ if (isTrack(track)) return Promise.resolve(new Track(track, requesterFn2(track.requester)));
850
867
  if (!isUnresolvedTrack(track)) throw new ResolveError("The track is not a valid unresolved track.");
851
- if (!track.resolve || typeof track.resolve !== "function") return new UnresolvedTrack(track, track.requester).resolve(player);
868
+ if (!track.resolve || typeof track.resolve !== "function")
869
+ return new UnresolvedTrack(track, requesterFn2(track.requester)).resolve(player);
852
870
  return track.resolve(player);
853
871
  }
854
872
  var isTrack = (track) => {
@@ -880,6 +898,9 @@ function stringify(value, space) {
880
898
  space
881
899
  );
882
900
  }
901
+ function requesterFn(requester) {
902
+ return requester;
903
+ }
883
904
  function isNode(options) {
884
905
  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");
885
906
  }
@@ -1378,8 +1399,8 @@ async function onEnd() {
1378
1399
  (x) => x.info.identifier === this.queue.current.info.identifier && x.info.title === this.queue.current.info.title
1379
1400
  )) {
1380
1401
  this.queue.history.unshift(this.queue.current);
1381
- if (this.queue.history.length > this.manager.options.queueOptions.maxPreviousTracks)
1382
- this.queue.history.splice(this.manager.options.queueOptions.maxPreviousTracks, this.queue.history.length);
1402
+ if (this.queue.history.length > this.manager.options.queueOptions.maxHistory)
1403
+ this.queue.history.splice(this.manager.options.queueOptions.maxHistory, this.queue.history.length);
1383
1404
  await this.queue.utils.save();
1384
1405
  this.manager.emit(
1385
1406
  "debug" /* Debug */,
@@ -1389,7 +1410,7 @@ async function onEnd() {
1389
1410
  }
1390
1411
  if (this.loop === 1 /* Track */ && this.queue.current) this.queue.unshift(this.queue.current);
1391
1412
  if (this.loop === 2 /* Queue */ && this.queue.current) this.queue.add(this.queue.current);
1392
- if (!this.queue.current) this.queue.current = await validateTrack(this, this.queue.shift());
1413
+ if (!this.queue.current) this.queue.current = await validateTrack(this, await this.queue.shift());
1393
1414
  await this.queue.utils.save();
1394
1415
  return;
1395
1416
  }
@@ -1536,6 +1557,43 @@ async function socketClosed(payload) {
1536
1557
  `[Player] -> [Socket] The socket has closed: ${this.guildId} | Payload: ${stringify(payload)}`
1537
1558
  );
1538
1559
  }
1560
+ async function resumeByLibrary(players) {
1561
+ this.nodeManager.manager.emit("debug" /* Debug */, 2 /* Node */, `[Socket] -> [${this.id}]: Resuming session by library...`);
1562
+ for (const player of players) {
1563
+ try {
1564
+ if (!player.playing && !player.paused && !player.queue.totalSize) {
1565
+ this.nodeManager.manager.emit(
1566
+ "debug" /* Debug */,
1567
+ 2 /* Node */,
1568
+ `[Player] -> [Resume] Destroyed player for guild ${player.guildId} due to empty queue.`
1569
+ );
1570
+ await player.destroy();
1571
+ return;
1572
+ }
1573
+ const track = player.queue.current;
1574
+ await player.node.updatePlayer({
1575
+ guildId: player.guildId,
1576
+ playerOptions: { voice: player.voice }
1577
+ });
1578
+ await player.connect();
1579
+ await player.queue.utils.sync(false, true);
1580
+ if (track)
1581
+ await player.play({
1582
+ track,
1583
+ noReplace: false,
1584
+ position: player.lastPosition,
1585
+ paused: player.paused
1586
+ });
1587
+ } catch (error) {
1588
+ this.nodeManager.manager.emit("nodeError" /* NodeError */, this, error);
1589
+ }
1590
+ this.nodeManager.manager.emit(
1591
+ "debug" /* Debug */,
1592
+ 2 /* Node */,
1593
+ `[Player] -> [Resume] Resumed player for guild ${player.guildId} using the library.`
1594
+ );
1595
+ }
1596
+ }
1539
1597
 
1540
1598
  // src/util/events/websocket.ts
1541
1599
  function onOpen(res) {
@@ -1608,34 +1666,37 @@ async function onMessage(message) {
1608
1666
  this.sessionId = payload.sessionId;
1609
1667
  this.session.resuming = payload.resumed;
1610
1668
  if (payload.resumed) {
1611
- const players = await this.rest.request({
1669
+ const players2 = await this.rest.request({
1612
1670
  endpoint: `/sessions/${payload.sessionId}/players`
1613
1671
  }) ?? [];
1614
1672
  const timeout = this.nodeManager.manager.options.nodeOptions.resumeTimeout;
1615
- this.nodeManager.manager.emit("nodeResumed" /* NodeResumed */, this, players, payload);
1673
+ this.nodeManager.manager.emit("nodeResumed" /* NodeResumed */, this, players2, payload);
1616
1674
  this.nodeManager.manager.emit(
1617
1675
  "debug" /* Debug */,
1618
1676
  2 /* Node */,
1619
- `[Socket] <- [${this.id}]: Resumed session. | Session id: ${payload.sessionId} | Players: ${players.length} | Resumed: ${payload.resumed} | Timeout: ${timeout}ms`
1677
+ `[Socket] <- [${this.id}]: Resumed session. | Session id: ${payload.sessionId} | Players: ${players2.length} | Resumed: ${payload.resumed} | Timeout: ${timeout}ms`
1620
1678
  );
1621
1679
  }
1680
+ const players = this.nodeManager.manager.players.filter((p) => p.node.id === this.id);
1681
+ const isLibrary = this.nodeManager.manager.options.nodeOptions.resumeByLibrary;
1682
+ if (!payload.resumed && isLibrary && players.length) await resumeByLibrary.call(this, players);
1622
1683
  this.info = await this.rest.request({ endpoint: "/info" });
1623
- this.nodeManager.manager.emit(
1624
- "debug" /* Debug */,
1625
- 2 /* Node */,
1626
- `[Socket] <- [${this.id}]: Received ready event. | Session id: ${payload.sessionId} | Resumed: ${payload.resumed}`
1627
- );
1628
- this.nodeManager.manager.emit("nodeReady" /* NodeReady */, this, this.retryAmount, payload);
1629
1684
  const isResumable = this.nodeManager.manager.options.nodeOptions.resumable;
1630
1685
  if (isResumable) {
1631
1686
  const timeout = this.nodeManager.manager.options.nodeOptions.resumeTimeout;
1632
1687
  this.nodeManager.manager.emit(
1633
1688
  "debug" /* Debug */,
1634
1689
  2 /* Node */,
1635
- `[Socket] -> [${this.id}]: Resuming session... | Timeout: ${timeout}ms`
1690
+ `[Socket] -> [${this.id}]: Setting timeout to resume session. | Timeout: ${timeout}ms`
1636
1691
  );
1637
1692
  await this.updateSession(isResumable, timeout);
1638
1693
  }
1694
+ this.nodeManager.manager.emit(
1695
+ "debug" /* Debug */,
1696
+ 2 /* Node */,
1697
+ `[Socket] <- [${this.id}]: Received ready event. | Session id: ${payload.sessionId} | Resumed: ${payload.resumed}`
1698
+ );
1699
+ this.nodeManager.manager.emit("nodeReady" /* NodeReady */, this, this.retryAmount, payload);
1639
1700
  }
1640
1701
  break;
1641
1702
  case "event" /* Event */: {
@@ -3362,15 +3423,7 @@ var Player = class {
3362
3423
  */
3363
3424
  async disconnect() {
3364
3425
  if (!this.voiceId) return this;
3365
- await this.manager.options.sendPayload(this.guildId, {
3366
- op: 4,
3367
- d: {
3368
- guild_id: this.guildId,
3369
- channel_id: null,
3370
- self_deaf: this.selfDeaf,
3371
- self_mute: this.selfMute
3372
- }
3373
- });
3426
+ await this.setVoice({ voiceId: null });
3374
3427
  this.manager.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Disconnect] Player disconnected for guild: ${this.guildId}`);
3375
3428
  this.connected = false;
3376
3429
  return this;
@@ -3416,7 +3469,7 @@ var Player = class {
3416
3469
  async play(options = {}) {
3417
3470
  if (typeof options !== "object") throw new PlayerError("The play options must be an object.");
3418
3471
  if (options.track) this.queue.current = await validateTrack(this, options.track);
3419
- else if (!this.queue.current) this.queue.current = await validateTrack(this, this.queue.shift());
3472
+ else if (!this.queue.current) this.queue.current = await validateTrack(this, await this.queue.shift());
3420
3473
  if (!this.queue.current) throw new PlayerError("No track to play.");
3421
3474
  if (!isTrack(this.queue.current) && !isUnresolvedTrack(this.queue.current))
3422
3475
  throw new PlayerError("The track must be a valid Track or UnresolvedTrack instance.");
@@ -3449,15 +3502,7 @@ var Player = class {
3449
3502
  */
3450
3503
  async connect() {
3451
3504
  if (!this.voiceId) return this;
3452
- await this.manager.options.sendPayload(this.guildId, {
3453
- op: 4,
3454
- d: {
3455
- guild_id: this.guildId,
3456
- channel_id: this.voiceId,
3457
- self_deaf: this.selfDeaf,
3458
- self_mute: this.selfMute
3459
- }
3460
- });
3505
+ await this.setVoice();
3461
3506
  this.manager.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Connect] Player connected for guild: ${this.guildId}`);
3462
3507
  this.connected = true;
3463
3508
  return this;
@@ -3556,7 +3601,7 @@ var Player = class {
3556
3601
  }
3557
3602
  /**
3558
3603
  * Set the voice of the player.
3559
- * @param {Partial<VoiceChannelUpdate>} voice The voice state to set.
3604
+ * @param {NullableVoiceChannelUpdate} options The voice state to set.
3560
3605
  * @returns {Promise<void>}
3561
3606
  * @example
3562
3607
  * ```ts
@@ -3564,27 +3609,17 @@ var Player = class {
3564
3609
  * player.setVoice({ voiceId: "newVoiceId" });
3565
3610
  * ```
3566
3611
  */
3567
- async setVoice(voice) {
3568
- if (voice.voiceId === this.voiceId) return;
3569
- if (voice.voiceId) {
3570
- this.voiceId = voice.voiceId;
3571
- this.options.voiceId = voice.voiceId;
3572
- }
3573
- if (voice.selfDeaf) {
3574
- this.selfDeaf = voice.selfDeaf;
3575
- this.options.selfDeaf = voice.selfDeaf;
3576
- }
3577
- if (voice.selfMute) {
3578
- this.selfMute = voice.selfMute;
3579
- this.options.selfMute = voice.selfMute;
3580
- }
3612
+ async setVoice(options = {}) {
3613
+ options.voiceId ??= this.voiceId;
3614
+ options.selfDeaf ??= this.selfDeaf;
3615
+ options.selfMute ??= this.selfMute;
3581
3616
  await this.manager.options.sendPayload(this.guildId, {
3582
3617
  op: 4,
3583
3618
  d: {
3584
3619
  guild_id: this.guildId,
3585
- self_deaf: this.selfDeaf,
3586
- self_mute: this.selfMute,
3587
- channel_id: this.voiceId ?? null
3620
+ self_deaf: options.selfDeaf,
3621
+ self_mute: options.selfMute,
3622
+ channel_id: options.voiceId ?? null
3588
3623
  }
3589
3624
  });
3590
3625
  this.manager.emit(
@@ -3801,16 +3836,15 @@ var QueueUtils = class {
3801
3836
  * ```
3802
3837
  */
3803
3838
  save() {
3804
- const max = this.options.maxPreviousTracks;
3839
+ const max = this.options.maxHistory;
3805
3840
  const length = this.queue.tracks.length;
3806
- const json = this.queue.toJSON();
3807
3841
  if (length > max) this.queue.history.splice(0, length - max);
3808
3842
  this.queue.player.manager.emit(
3809
3843
  "debug" /* Debug */,
3810
3844
  5 /* Queue */,
3811
- `[Queue] -> [Adapter] Saving queue for ${this.queue.player.guildId} | Object: ${stringify(json)}`
3845
+ `[Queue] -> [Adapter] Saving queue for ${this.queue.player.guildId} | Object: ${stringify(this.queue.toJSON())}`
3812
3846
  );
3813
- return this.store.set(this.queue.player.guildId, json);
3847
+ return this.store.set(this.queue.player.guildId, this.queue.toJSON());
3814
3848
  }
3815
3849
  /**
3816
3850
  *
@@ -3976,25 +4010,50 @@ var Queue = class {
3976
4010
  isEmpty() {
3977
4011
  return this.size === 0;
3978
4012
  }
4013
+ /**
4014
+ *
4015
+ * Build a track from a Lavalink track or unresolved Lavalink track.
4016
+ * @param {LavalinkTrack | UnresolvedLavalinkTrack} track The track to build.
4017
+ * @param {TrackRequester} requester The requester of the track.
4018
+ * @returns {Promise<Track>} The built track.
4019
+ * @example
4020
+ * ```ts
4021
+ * const queue = player.queue;
4022
+ * const lavalinkTrack = {...} // some lavalink track
4023
+ * const track = await queue.build(lavalinkTrack, author);
4024
+ *
4025
+ * console.log(track.info.title); // The title of the track
4026
+ * ```
4027
+ */
4028
+ async build(track, requester) {
4029
+ const requesterFn2 = this.player.manager.options.playerOptions.requesterFn;
4030
+ if (isUnresolvedTrack(track)) return new UnresolvedTrack(track, requesterFn2(requester)).resolve(this.player);
4031
+ if (isTrack(track)) return new Track(track, requesterFn2(requester));
4032
+ return track;
4033
+ }
3979
4034
  /**
3980
4035
  *
3981
4036
  * Get the previous track of the queue.
3982
4037
  * @param {boolean} [remove=false] Whether to remove the track from the previous queue.
3983
- * @returns {Track | null} The previous track of the queue.
4038
+ * @returns {Promise<Track | null>} The previous track of the queue.
3984
4039
  * @example
3985
4040
  * ```ts
3986
4041
  * const queue = player.queue;
3987
4042
  *
3988
- * console.log(queue.previous()); // null
4043
+ * console.log(await queue.previous()); // null
3989
4044
  * queue.add(track);
3990
4045
  * queue.add(track2);
3991
4046
  *
3992
- * console.log(queue.previous()); // track
3993
- * console.log(queue.previous(true)); // track and remove it from the previous tracks
4047
+ * console.log(await queue.previous()); // track
4048
+ * console.log(await queue.previous(true)); // track and remove it from the previous tracks
3994
4049
  * ```
3995
4050
  */
3996
- previous(remove = false) {
3997
- if (remove) return this.history.shift() ?? null;
4051
+ async previous(remove = false) {
4052
+ if (remove) {
4053
+ const track = this.history.shift() ?? null;
4054
+ if (track) await this.utils.save();
4055
+ return track;
4056
+ }
3998
4057
  return this.history[0] ?? null;
3999
4058
  }
4000
4059
  /**
@@ -4002,94 +4061,98 @@ var Queue = class {
4002
4061
  * Add a track or tracks to the queue.
4003
4062
  * @param {Track | Track[]} track The track or tracks to add.
4004
4063
  * @param {number} [position] The position to add the track or tracks.
4005
- * @returns {this} The queue instance.
4064
+ * @returns {Promise<this>} The queue instance.
4006
4065
  * @example
4007
4066
  * ```ts
4008
4067
  * const queue = player.queue;
4009
4068
  *
4010
4069
  * console.log(queue.size); // 0
4011
4070
  *
4012
- * queue.add(track);
4071
+ * await queue.add(track);
4013
4072
  * console.log(queue.size); // 1
4014
4073
  *
4015
- * queue.add([track1, track2]);
4074
+ * await queue.add([track1, track2]);
4016
4075
  * console.log(queue.size); // 3
4017
4076
  *
4018
- * queue.add(track3, 1);
4077
+ * await queue.add(track3, 1);
4019
4078
  * console.log(queue.size); // 4
4020
4079
  * console.log(queue.tracks); // [track1, track3, track2, track]
4021
4080
  * ```
4022
4081
  */
4023
- add(track, position) {
4082
+ async add(track, position) {
4024
4083
  const tracks = Array.isArray(track) ? track : [track];
4025
4084
  if (typeof position === "number" && position >= 0 && position < this.tracks.length) return this.splice(position, 0, ...tracks);
4026
4085
  this.tracks.push(...tracks);
4027
4086
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4028
4087
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Add] Added ${this.tracks.length} tracks to the queue.`);
4088
+ await this.utils.save();
4029
4089
  return this;
4030
4090
  }
4031
4091
  /**
4032
4092
  *
4033
4093
  * Get the first track of the queue.
4034
- * @returns {HoshimiTrack | null} The first track of the queue.
4094
+ * @returns {Promise<HoshimiTrack | null>} The first track of the queue.
4035
4095
  * @example
4036
4096
  * ```ts
4037
4097
  * const queue = player.queue;
4038
4098
  *
4039
- * console.log(queue.shift()); // null
4040
- * queue.add(track);
4099
+ * console.log(await queue.shift()); // null
4100
+ * await queue.add(track);
4041
4101
  *
4042
- * console.log(queue.shift()); // track
4043
- * queue.add(track2);
4102
+ * console.log(await queue.shift()); // track
4103
+ * await queue.add(track2);
4044
4104
  * ```
4045
4105
  */
4046
- shift() {
4047
- return this.tracks.shift() ?? null;
4106
+ async shift() {
4107
+ const track = this.tracks.shift() ?? null;
4108
+ if (track) await this.utils.save();
4109
+ return track;
4048
4110
  }
4049
4111
  /**
4050
4112
  *
4051
4113
  * Add tracks to the beginning of the queue.
4052
4114
  * @param {Track[]} tracks The tracks to add.
4053
- * @returns {this} The queue instance.
4115
+ * @returns {Promise<this>} The queue instance.
4054
4116
  * @example
4055
4117
  * ```ts
4056
4118
  * const queue = player.queue;
4057
4119
  *
4058
4120
  * console.log(queue.size); // 0
4059
- * queue.unshift(track);
4121
+ * await queue.unshift(track);
4060
4122
  *
4061
4123
  * console.log(queue.size); // 1
4062
- * queue.unshift([track1, track2]);
4124
+ * await queue.unshift(track1, track2);
4063
4125
  *
4064
4126
  * console.log(queue.size); // 3
4065
4127
  * console.log(queue.tracks); // [track1, track2, track]
4066
4128
  * ```
4067
4129
  */
4068
- unshift(...tracks) {
4130
+ async unshift(...tracks) {
4069
4131
  this.tracks.unshift(...tracks);
4070
4132
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Unshift] Added ${this.tracks.length} tracks to the queue.`);
4133
+ await this.utils.save();
4071
4134
  return this;
4072
4135
  }
4073
4136
  /**
4074
4137
  *
4075
4138
  * Shuffle the queue.
4076
- * @returns {this} The queue instance.
4139
+ * @returns {Promise<this>} The queue instance.
4077
4140
  * @example
4078
4141
  * ```ts
4079
4142
  * const queue = player.queue;
4080
4143
  *
4081
4144
  * console.log(queue.size); // 0
4082
- * queue.add(track);
4083
- * queue.add([track1, track2]);
4145
+ * await queue.add(track);
4146
+ * await queue.add(track1, track2);
4084
4147
  *
4085
4148
  * console.log(queue.size); // 3
4086
4149
  * console.log(queue.tracks); // [track, track1, track2]
4087
4150
  *
4088
- * queue.shuffle();
4151
+ * await queue.shuffle();
4089
4152
  * console.log(queue.tracks); // [track2, track, track1]
4090
4153
  * ```
4091
4154
  */
4092
- shuffle() {
4155
+ async shuffle() {
4093
4156
  if (this.size <= 1) return this;
4094
4157
  if (this.size === 2) [this.tracks[0], this.tracks[1]] = [this.tracks[1], this.tracks[0]];
4095
4158
  else {
@@ -4100,31 +4163,33 @@ var Queue = class {
4100
4163
  }
4101
4164
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4102
4165
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, "[Queue] -> [Shuffle] Shuffled the queue.");
4166
+ await this.utils.save();
4103
4167
  return this;
4104
4168
  }
4105
4169
  /**
4106
4170
  *
4107
4171
  * Clear the queue.
4108
- * @returns {this} The queue instance.
4172
+ * @returns {Promise<this>} The queue instance.
4109
4173
  * @example
4110
4174
  * ```ts
4111
4175
  * const queue = player.queue;
4112
4176
  *
4113
4177
  * console.log(queue.size); // 0
4114
- * queue.add(track);
4115
- * queue.add([track1, track2]);
4178
+ * await queue.add(track);
4179
+ * await queue.add(track1, track2);
4116
4180
  *
4117
4181
  * console.log(queue.size); // 3
4118
- * queue.clear();
4182
+ * await queue.clear();
4119
4183
  * console.log(queue.size); // 0
4120
4184
  * ```
4121
4185
  */
4122
- clear() {
4186
+ async clear() {
4123
4187
  this.tracks = [];
4124
4188
  this.history = [];
4125
4189
  this.current = null;
4126
4190
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4127
4191
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, "[Queue] -> [Clear] Cleared the queue.");
4192
+ await this.utils.save();
4128
4193
  return this;
4129
4194
  }
4130
4195
  /**
@@ -4132,15 +4197,16 @@ var Queue = class {
4132
4197
  * Move a track to a specific position in the queue.
4133
4198
  * @param {Track} track The track to move.
4134
4199
  * @param {number} to The position to move.
4135
- * @returns {this} The queue instance.
4200
+ * @returns {Promise<this>} The queue instance.
4136
4201
  */
4137
- move(track, to) {
4202
+ async move(track, to) {
4138
4203
  const index = this.tracks.indexOf(track);
4139
4204
  if (index === -1) return this;
4140
- this.splice(index, 1);
4141
- this.add(track, to - 1);
4205
+ await this.splice(index, 1);
4206
+ await this.add(track, to - 1);
4142
4207
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4143
4208
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Move] Moved track ${track.info.title} to position ${to}.`);
4209
+ await this.utils.save();
4144
4210
  return this;
4145
4211
  }
4146
4212
  /**
@@ -4149,14 +4215,15 @@ var Queue = class {
4149
4215
  * @param {number} start The start index.
4150
4216
  * @param {number} deleteCount The number of tracks to delete.
4151
4217
  * @param {Track | Track[]} [tracks] The tracks to add.
4152
- * @returns {this} The queue instance.
4218
+ * @returns {Promise<this>} The queue instance.
4153
4219
  */
4154
- splice(start, deleteCount, tracks) {
4155
- if (!this.size && tracks) this.add(tracks);
4220
+ async splice(start, deleteCount, tracks) {
4221
+ if (!this.size && tracks) await this.add(tracks);
4156
4222
  if (tracks) this.tracks.splice(start, deleteCount, ...Array.isArray(tracks) ? tracks : [tracks]);
4157
4223
  else this.tracks.splice(start, deleteCount);
4158
4224
  this.player.manager.emit("queueUpdate" /* QueueUpdate */, this.player, this);
4159
4225
  this.player.manager.emit("debug" /* Debug */, 5 /* Queue */, `[Queue] -> [Splice] Removed ${deleteCount} tracks from the queue.`);
4226
+ await this.utils.save();
4160
4227
  return this;
4161
4228
  }
4162
4229
  /**
@@ -4165,7 +4232,7 @@ var Queue = class {
4165
4232
  * @returns {QueueJson} The queue JSON object.
4166
4233
  */
4167
4234
  toJSON() {
4168
- const max = this.player.manager.options.queueOptions.maxPreviousTracks;
4235
+ const max = this.player.manager.options.queueOptions.maxHistory;
4169
4236
  if (this.history.length > max) this.history.splice(max, this.history.length);
4170
4237
  return {
4171
4238
  tracks: this.tracks,
@@ -4331,10 +4398,24 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4331
4398
  * resumeByLibrary: false,
4332
4399
  * },
4333
4400
  * queueOptions: {
4334
- * maxPreviousTracks: 25,
4335
- * autoplayFn: autoplayFn,
4336
- * autoPlay: false,
4401
+ * maxHistory: 25,
4402
+ * autoplayFn: autoplayFn,
4403
+ * autoPlay: false,
4404
+ * storage: new MemoryAdapter(),
4405
+ * requesterFn: defaultRequesterFn,
4337
4406
  * },
4407
+ * playerOptions: {
4408
+ * onDisconnect: {
4409
+ * autoDestroy: false,
4410
+ * autoReconnect: false,
4411
+ * autoQueue: false,
4412
+ * },
4413
+ * onError: {
4414
+ * autoDestroy: false,
4415
+ * autoSkip: false,
4416
+ * autoStop: false,
4417
+ * },
4418
+ * },
4338
4419
  * });
4339
4420
  *
4340
4421
  * console.log(manager); // The manager instance
@@ -4356,11 +4437,24 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4356
4437
  resumeTimeout: options.nodeOptions?.resumeTimeout ?? 1e4
4357
4438
  },
4358
4439
  queueOptions: {
4359
- maxPreviousTracks: options.queueOptions?.maxPreviousTracks ?? 25,
4440
+ maxHistory: options.queueOptions?.maxHistory ?? 25,
4360
4441
  autoplayFn: options.queueOptions?.autoplayFn ?? autoplayFn,
4361
4442
  autoPlay: options.queueOptions?.autoPlay ?? false,
4362
4443
  storage: options.queueOptions?.storage ?? new MemoryAdapter()
4363
4444
  },
4445
+ playerOptions: {
4446
+ requesterFn: options.playerOptions?.requesterFn ?? requesterFn,
4447
+ onDisconnect: {
4448
+ autoDestroy: options.playerOptions?.onDisconnect?.autoDestroy ?? false,
4449
+ autoReconnect: options.playerOptions?.onDisconnect?.autoReconnect ?? true,
4450
+ autoQueue: options.playerOptions?.onDisconnect?.autoQueue ?? false
4451
+ },
4452
+ onError: {
4453
+ autoDestroy: options.playerOptions?.onError?.autoDestroy ?? false,
4454
+ autoSkip: options.playerOptions?.onError?.autoSkip ?? false,
4455
+ autoStop: options.playerOptions?.onError?.autoStop ?? false
4456
+ }
4457
+ },
4364
4458
  client: {
4365
4459
  id: options.client?.id ?? "",
4366
4460
  username: options.client?.username ?? "hoshimi-client"
@@ -4497,6 +4591,56 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4497
4591
  );
4498
4592
  return;
4499
4593
  }
4594
+ if ("channel_id" in data && typeof data.channel_id === "string") {
4595
+ if (data.channel_id !== player.voiceId) {
4596
+ this.emit(
4597
+ "debug" /* Debug */,
4598
+ 3 /* Player */,
4599
+ `[Player] -> [Voice] Updating the voice channel for: ${data.guild_id} | Old: ${player.voiceId} | New: ${data.channel_id}`
4600
+ );
4601
+ player.voice.sessionId = data.session_id ?? player.voice.sessionId;
4602
+ player.voiceId = data.channel_id;
4603
+ player.options.voiceId = data.channel_id;
4604
+ if (!player.connected) await player.connect();
4605
+ return;
4606
+ }
4607
+ } else {
4608
+ this.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Voice] The channel id is missing for: ${data.guild_id}`);
4609
+ const { autoDestroy, autoReconnect, autoQueue } = this.options.playerOptions.onDisconnect;
4610
+ if (autoDestroy) {
4611
+ await player.destroy("Player-VoiceChannelLeft" /* VoiceChannelLeft */);
4612
+ return;
4613
+ }
4614
+ if (autoReconnect) {
4615
+ try {
4616
+ const position = player.position;
4617
+ const paused = player.paused;
4618
+ this.emit(
4619
+ "debug" /* Debug */,
4620
+ 3 /* Player */,
4621
+ `[Player] -> [Voice] Attempting to reconnect the player for: ${data.guild_id}`
4622
+ );
4623
+ if (autoQueue && player.queue.current && !player.queue.isEmpty()) await player.connect();
4624
+ if (player.queue.current) return player.play({ track: player.queue.current, paused, position });
4625
+ if (!player.queue.isEmpty()) return player.play({ paused });
4626
+ this.emit(
4627
+ "debug" /* Debug */,
4628
+ 3 /* Player */,
4629
+ `[Player] -> [Voice] No tracks to play after reconnect for: ${data.guild_id}`
4630
+ );
4631
+ } catch (error) {
4632
+ this.emit("playerError" /* PlayerError */, player, error);
4633
+ await player.destroy("Player-ReconnectFailed" /* ReconnectFailed */);
4634
+ }
4635
+ }
4636
+ player.voiceId = void 0;
4637
+ player.voice = {
4638
+ endpoint: null,
4639
+ sessionId: null,
4640
+ token: null
4641
+ };
4642
+ return;
4643
+ }
4500
4644
  this.emit("debug" /* Debug */, 3 /* Player */, `[Player] -> [Voice] The player voice is missing for: ${data.guild_id}`);
4501
4645
  }
4502
4646
  break;
@@ -4606,6 +4750,7 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4606
4750
  1 /* Manager */,
4607
4751
  `[Manager] -> [Search] Searching for: ${options.query} (${options.engine ?? "unknown"}) | Result: ${stringify(res)}`
4608
4752
  );
4753
+ const requesterFn2 = this.options.playerOptions.requesterFn;
4609
4754
  switch (res.loadType) {
4610
4755
  case "empty" /* Empty */: {
4611
4756
  return {
@@ -4631,7 +4776,7 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4631
4776
  exception: null,
4632
4777
  playlist: res.data,
4633
4778
  pluginInfo: res.data.pluginInfo,
4634
- tracks: res.data.tracks.map((t) => new Track(t, options.requester))
4779
+ tracks: res.data.tracks.map((t) => new Track(t, requesterFn2(options.requester)))
4635
4780
  };
4636
4781
  }
4637
4782
  case "search" /* Search */: {
@@ -4640,7 +4785,7 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4640
4785
  exception: null,
4641
4786
  playlist: null,
4642
4787
  pluginInfo: null,
4643
- tracks: res.data.map((t) => new Track(t, options.requester))
4788
+ tracks: res.data.map((t) => new Track(t, requesterFn2(options.requester)))
4644
4789
  };
4645
4790
  }
4646
4791
  case "track" /* Track */: {
@@ -4649,7 +4794,7 @@ var Hoshimi = class extends import_node_events.EventEmitter {
4649
4794
  exception: null,
4650
4795
  playlist: null,
4651
4796
  pluginInfo: res.data.pluginInfo,
4652
- tracks: [new Track(res.data, options.requester)]
4797
+ tracks: [new Track(res.data, requesterFn2(options.requester))]
4653
4798
  };
4654
4799
  }
4655
4800
  }