discord-player 6.0.0-dev.4 → 6.0.0

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
@@ -68,15 +68,18 @@ __export(src_exports, {
68
68
  GuildNodeManager: () => GuildNodeManager,
69
69
  GuildQueue: () => GuildQueue,
70
70
  GuildQueueAudioFilters: () => GuildQueueAudioFilters,
71
+ GuildQueueEvent: () => GuildQueueEvent,
71
72
  GuildQueueHistory: () => GuildQueueHistory,
72
73
  GuildQueuePlayerNode: () => GuildQueuePlayerNode,
73
74
  PCMAudioFilters: () => import_equalizer3.AudioFilters,
74
75
  Player: () => Player,
75
76
  PlayerError: () => PlayerError,
77
+ PlayerEvent: () => PlayerEvent,
76
78
  PlayerEventsEmitter: () => PlayerEventsEmitter,
77
79
  Playlist: () => Playlist,
78
80
  Q_BUTTERWORTH: () => import_equalizer3.Q_BUTTERWORTH,
79
81
  QueryCache: () => QueryCache,
82
+ QueryResolver: () => QueryResolver,
80
83
  QueryType: () => QueryType,
81
84
  QueueRepeatMode: () => QueueRepeatMode,
82
85
  SearchResult: () => SearchResult,
@@ -87,7 +90,11 @@ __export(src_exports, {
87
90
  VoiceUtils: () => VoiceUtils,
88
91
  VolumeTransformer: () => import_equalizer3.VolumeTransformer,
89
92
  createFFmpegStream: () => createFFmpegStream,
90
- version: () => version
93
+ useHistory: () => useHistory,
94
+ useMasterPlayer: () => useMasterPlayer,
95
+ usePlayer: () => usePlayer,
96
+ useQueue: () => useQueue,
97
+ version: () => version2
91
98
  });
92
99
  module.exports = __toCommonJS(src_exports);
93
100
  var import_discord4 = require("discord.js");
@@ -171,6 +178,9 @@ var Util = class {
171
178
  detail
172
179
  });
173
180
  }
181
+ static randomChoice(src) {
182
+ return src[Math.floor(Math.random() * src.length)];
183
+ }
174
184
  };
175
185
  __name(Util, "Util");
176
186
 
@@ -313,7 +323,15 @@ BaseExtractor.identifier = "com.discord-player.extractor";
313
323
 
314
324
  // src/extractors/ExtractorExecutionContext.ts
315
325
  var import_utils2 = require("@discord-player/utils");
316
- var knownExtractorKeys = ["YouTubeExtractor", "SoundCloudExtractor", "ReverbnationExtractor", "VimeoExtractor", "AttachmentExtractor"];
326
+ var knownExtractorKeys = [
327
+ "SoundCloudExtractor",
328
+ "AppleMusicExtractor",
329
+ "SpotifyExtractor",
330
+ "VimeoExtractor",
331
+ "YouTubeExtractor",
332
+ "ReverbnationExtractor",
333
+ "AttachmentExtractor"
334
+ ];
317
335
  var knownExtractorLib = "@discord-player/extractor";
318
336
  var ExtractorExecutionContext = class {
319
337
  constructor(player) {
@@ -487,6 +505,12 @@ var Playlist = class {
487
505
  *[Symbol.iterator]() {
488
506
  yield* this.tracks;
489
507
  }
508
+ get estimatedDuration() {
509
+ return this.tracks.reduce((p, c) => p + c.durationMS, 0);
510
+ }
511
+ get durationFormatted() {
512
+ return Util.buildTimeCode(Util.parseMS(this.estimatedDuration));
513
+ }
490
514
  toJSON(withTracks = true) {
491
515
  const payload = {
492
516
  id: this.id,
@@ -525,6 +549,12 @@ var GuildQueueHistory = class {
525
549
  get disabled() {
526
550
  return this.queue.options.disableHistory;
527
551
  }
552
+ get size() {
553
+ return this.tracks.size;
554
+ }
555
+ getSize() {
556
+ return this.size;
557
+ }
528
558
  isEmpty() {
529
559
  return this.tracks.size < 1;
530
560
  }
@@ -544,14 +574,14 @@ var GuildQueueHistory = class {
544
574
  }
545
575
  this.queue.node.skip();
546
576
  }
547
- async previous() {
577
+ async previous(preserveCurrent = true) {
548
578
  const track = this.tracks.dispatch();
549
579
  if (!track) {
550
580
  throw new Error("No previous track in the queue");
551
581
  }
552
582
  const current = this.currentTrack;
553
583
  await this.queue.node.play(track, { queue: false });
554
- if (current)
584
+ if (current && preserveCurrent)
555
585
  this.queue.node.insert(current, 0);
556
586
  }
557
587
  back() {
@@ -587,8 +617,15 @@ var QueryType = {
587
617
  APPLE_MUSIC_SONG: "appleMusicSong",
588
618
  APPLE_MUSIC_ALBUM: "appleMusicAlbum",
589
619
  APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
620
+ APPLE_MUSIC_SEARCH: "appleMusicSearch",
590
621
  FILE: "file"
591
622
  };
623
+ var PlayerEvent = /* @__PURE__ */ ((PlayerEvent2) => {
624
+ PlayerEvent2["debug"] = "debug";
625
+ PlayerEvent2["error"] = "error";
626
+ PlayerEvent2["voiceStateUpdate"] = "voiceStateUpdate";
627
+ return PlayerEvent2;
628
+ })(PlayerEvent || {});
592
629
  var QueueRepeatMode = /* @__PURE__ */ ((QueueRepeatMode2) => {
593
630
  QueueRepeatMode2[QueueRepeatMode2["OFF"] = 0] = "OFF";
594
631
  QueueRepeatMode2[QueueRepeatMode2["TRACK"] = 1] = "TRACK";
@@ -625,10 +662,10 @@ var QueryResolver = class {
625
662
  };
626
663
  }
627
664
  static resolve(query) {
628
- query = query.trim();
629
- if (soundcloud.validateURL(query, "track"))
665
+ query = !query.includes("youtube.com") ? query.trim() : query.replace(/(m(usic)?|gaming)\./, "").trim();
666
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "track"))
630
667
  return QueryType.SOUNDCLOUD_TRACK;
631
- if (soundcloud.validateURL(query, "playlist") || query.includes("/sets/"))
668
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "playlist") || query.includes("/sets/"))
632
669
  return QueryType.SOUNDCLOUD_PLAYLIST;
633
670
  if (import_youtube_sr.YouTube.isPlaylist(query))
634
671
  return QueryType.YOUTUBE_PLAYLIST;
@@ -809,6 +846,7 @@ var GuildQueuePlayerNode = class {
809
846
  if (!foundTrack)
810
847
  return null;
811
848
  this.queue.tracks.removeOne((t) => t.id === foundTrack.id);
849
+ this.queue.player.events.emit("audioTrackRemove", this.queue, foundTrack);
812
850
  return foundTrack;
813
851
  }
814
852
  jump(track) {
@@ -835,15 +873,20 @@ var GuildQueuePlayerNode = class {
835
873
  const removed = this.remove(idx);
836
874
  if (!removed)
837
875
  return false;
876
+ const toRemove = this.queue.tracks.store.filter((_, i) => i <= idx);
838
877
  this.queue.tracks.store.splice(0, idx, removed);
878
+ this.queue.player.events.emit("audioTracksRemove", this.queue, toRemove);
839
879
  return this.skip();
840
880
  }
841
881
  insert(track, index = 0) {
842
882
  if (!(track instanceof Track))
843
883
  throw new Error("invalid track");
844
884
  this.queue.tracks.store.splice(index, 0, track);
885
+ this.queue.player.events.emit("audioTrackAdd", this.queue, track);
845
886
  }
846
887
  stop(force = false) {
888
+ this.queue.tracks.clear();
889
+ this.queue.history.clear();
847
890
  if (!this.queue.dispatcher)
848
891
  return false;
849
892
  this.queue.dispatcher.end();
@@ -879,7 +922,7 @@ var GuildQueuePlayerNode = class {
879
922
  );
880
923
  if (res && options.queue) {
881
924
  this.queue.debug("Requested option requires to queue the track, adding the given track to queue instead...");
882
- return this.queue.tracks.add(res);
925
+ return this.queue.addTrack(res);
883
926
  }
884
927
  const track = res || this.queue.tracks.dispatch();
885
928
  if (!track) {
@@ -908,7 +951,7 @@ var GuildQueuePlayerNode = class {
908
951
  this.queue.player.events.emit("playerSkip", this.queue, track);
909
952
  this.queue.player.events.emit("playerError", this.queue, error, track);
910
953
  this.queue.initializing = false;
911
- this.play(this.queue.tracks.dispatch());
954
+ this.play(this.queue.tracks.dispatch(), { queue: false });
912
955
  return;
913
956
  }
914
957
  throw error;
@@ -1070,7 +1113,7 @@ function createFFmpegStream(stream, options) {
1070
1113
  args.unshift("-ss", String(options.seek));
1071
1114
  if (Array.isArray(options.encoderArgs))
1072
1115
  args.push(...options.encoderArgs);
1073
- const transcoder = new prism.FFmpeg({ shell: false, args });
1116
+ const transcoder = new (prism.FFmpeg || prism.default.FFmpeg)({ shell: false, args });
1074
1117
  transcoder.on("close", () => transcoder.destroy());
1075
1118
  if (typeof stream !== "string") {
1076
1119
  stream.on("error", () => transcoder.destroy());
@@ -1303,7 +1346,7 @@ var GuildQueueStatistics = class {
1303
1346
  memoryUsage: process.memoryUsage(),
1304
1347
  versions: {
1305
1348
  node: process.version,
1306
- player: "6.0.0-dev.4"
1349
+ player: "6.0.0"
1307
1350
  }
1308
1351
  };
1309
1352
  }
@@ -1311,6 +1354,25 @@ var GuildQueueStatistics = class {
1311
1354
  __name(GuildQueueStatistics, "GuildQueueStatistics");
1312
1355
 
1313
1356
  // src/Structures/GuildQueue.ts
1357
+ var GuildQueueEvent = /* @__PURE__ */ ((GuildQueueEvent2) => {
1358
+ GuildQueueEvent2["audioTrackAdd"] = "audioTrackadd";
1359
+ GuildQueueEvent2["audioTracksAdd"] = "audioTracksAdd";
1360
+ GuildQueueEvent2["audioTrackRemove"] = "audioTrackRemove";
1361
+ GuildQueueEvent2["audioTracksRemove"] = "audioTracksRemove";
1362
+ GuildQueueEvent2["connection"] = "connection";
1363
+ GuildQueueEvent2["disconnect"] = "disconnect";
1364
+ GuildQueueEvent2["debug"] = "debug";
1365
+ GuildQueueEvent2["error"] = "error";
1366
+ GuildQueueEvent2["emptyChannel"] = "emptyChannel";
1367
+ GuildQueueEvent2["emptyQueue"] = "emptyQueue";
1368
+ GuildQueueEvent2["playerStart"] = "playerStart";
1369
+ GuildQueueEvent2["playerError"] = "playerError";
1370
+ GuildQueueEvent2["playerFinish"] = "playerFinish";
1371
+ GuildQueueEvent2["playerSkip"] = "playerSkip";
1372
+ GuildQueueEvent2["playerTrigger"] = "playerTrigger";
1373
+ GuildQueueEvent2["voiceStateUpdate"] = "voiceStateUpdate";
1374
+ return GuildQueueEvent2;
1375
+ })(GuildQueueEvent || {});
1314
1376
  var _transitioning, _initializing, _deleted, _initializingPromises, _attachListeners, attachListeners_fn, _removeListeners, removeListeners_fn, _performStart, performStart_fn, _performFinish, performFinish_fn, _emitEnd, emitEnd_fn, _handleAutoplay, handleAutoplay_fn, _resolveInitializerAwaiters, resolveInitializerAwaiters_fn;
1315
1377
  var GuildQueue = class {
1316
1378
  constructor(player, options) {
@@ -1365,6 +1427,12 @@ var GuildQueue = class {
1365
1427
  }
1366
1428
  this.debug(`GuildQueue initialized for guild ${this.options.guild.name} (ID: ${this.options.guild.id})`);
1367
1429
  }
1430
+ get estimatedDuration() {
1431
+ return this.tracks.store.reduce((a, c) => a + c.durationMS, 0);
1432
+ }
1433
+ get durationFormatted() {
1434
+ return Util.buildTimeCode(Util.parseMS(this.estimatedDuration));
1435
+ }
1368
1436
  get voiceReceiver() {
1369
1437
  return this.dispatcher?.receiver ?? null;
1370
1438
  }
@@ -1424,18 +1492,27 @@ var GuildQueue = class {
1424
1492
  setRepeatMode(mode) {
1425
1493
  this.repeatMode = mode;
1426
1494
  }
1495
+ get size() {
1496
+ return this.tracks.size;
1497
+ }
1498
+ getSize() {
1499
+ return this.size;
1500
+ }
1501
+ clear() {
1502
+ this.tracks.clear();
1503
+ this.history.clear();
1504
+ }
1427
1505
  isEmpty() {
1428
1506
  return this.tracks.size < 1;
1429
1507
  }
1430
1508
  isPlaying() {
1431
- return this.dispatcher?.audioResource != null;
1509
+ return this.dispatcher?.audioResource != null && !this.dispatcher.audioResource.ended;
1432
1510
  }
1433
1511
  addTrack(track) {
1434
1512
  const toAdd = track instanceof Playlist ? track.tracks : track;
1435
1513
  this.tracks.add(toAdd);
1436
1514
  const isMulti = Array.isArray(toAdd);
1437
1515
  if (isMulti) {
1438
- this.player.events.emit("audioTrackAdd", this, toAdd[0]);
1439
1516
  this.player.events.emit("audioTracksAdd", this, toAdd);
1440
1517
  } else {
1441
1518
  this.player.events.emit("audioTrackAdd", this, toAdd);
@@ -1531,7 +1608,14 @@ removeListeners_fn = /* @__PURE__ */ __name(function(dispatcher) {
1531
1608
  _performStart = new WeakSet();
1532
1609
  performStart_fn = /* @__PURE__ */ __name(function(resource) {
1533
1610
  const track = resource?.metadata || this.currentTrack;
1534
- this.player.events.emit("playerTrigger", this, track, this.isTransitioning() ? "filters" : "normal");
1611
+ const reason = this.isTransitioning() ? "filters" : "normal";
1612
+ this.debug(
1613
+ `Player triggered for Track ${JSON.stringify({
1614
+ title: track?.title,
1615
+ reason
1616
+ })}`
1617
+ );
1618
+ this.player.events.emit("playerTrigger", this, track, reason);
1535
1619
  if (track && !this.isTransitioning())
1536
1620
  this.player.events.emit("playerStart", this, track);
1537
1621
  this.setTransitioning(false);
@@ -1540,25 +1624,38 @@ performStart_fn = /* @__PURE__ */ __name(function(resource) {
1540
1624
  _performFinish = new WeakSet();
1541
1625
  performFinish_fn = /* @__PURE__ */ __name(function(resource) {
1542
1626
  const track = resource?.metadata || this.currentTrack;
1627
+ this.debug(
1628
+ `Track ${JSON.stringify({
1629
+ title: track?.title,
1630
+ isTransitionMode: this.isTransitioning()
1631
+ })} was marked as finished`
1632
+ );
1543
1633
  if (track && !this.isTransitioning()) {
1634
+ this.debug("Adding track to history and emitting finish event since transition mode is disabled...");
1544
1635
  this.history.push(track);
1545
1636
  this.node.resetProgress();
1546
1637
  this.player.events.emit("playerFinish", this, track);
1547
1638
  if (this.tracks.size < 1 && this.repeatMode === 0 /* OFF */) {
1639
+ this.debug("No more tracks left in the queue to play and repeat mode is off, initiating #emitEnd()");
1548
1640
  __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1549
1641
  } else {
1550
1642
  if (this.repeatMode === 1 /* TRACK */) {
1643
+ this.debug("Repeat mode is set to track, repeating last track from the history...");
1551
1644
  this.__current = this.history.tracks.dispatch() || track;
1552
1645
  return this.node.play(this.__current, { queue: false });
1553
1646
  }
1554
- if (this.repeatMode === 2 /* QUEUE */)
1647
+ if (this.repeatMode === 2 /* QUEUE */) {
1648
+ this.debug("Repeat mode is set to queue, moving last track from the history to current queue...");
1555
1649
  this.tracks.add(this.history.tracks.dispatch() || track);
1650
+ }
1556
1651
  if (!this.tracks.size) {
1557
1652
  if (this.repeatMode === 3 /* AUTOPLAY */) {
1653
+ this.debug("Repeat mode is set to autoplay, initiating autoplay handler...");
1558
1654
  __privateMethod(this, _handleAutoplay, handleAutoplay_fn).call(this, track);
1559
1655
  return;
1560
1656
  }
1561
1657
  } else {
1658
+ this.debug("Initializing next track of the queue...");
1562
1659
  this.__current = this.tracks.dispatch();
1563
1660
  this.node.play(this.__current, {
1564
1661
  queue: false
@@ -1581,9 +1678,9 @@ emitEnd_fn = /* @__PURE__ */ __name(function() {
1581
1678
  }, "#emitEnd");
1582
1679
  _handleAutoplay = new WeakSet();
1583
1680
  handleAutoplay_fn = /* @__PURE__ */ __name(async function(track) {
1584
- let info = await import_youtube_sr2.YouTube.getVideo(track.url).then((x) => x.videos[0]).catch(Util.noop);
1681
+ let info = await import_youtube_sr2.YouTube.getVideo(track.url).then((x) => Util.randomChoice(x.videos.slice(0, 5))).catch(Util.noop);
1585
1682
  if (!info)
1586
- info = await import_youtube_sr2.YouTube.search(track.author).then((x) => x[0]).catch(Util.noop);
1683
+ info = await import_youtube_sr2.YouTube.search(track.author, { limit: 5, type: "video" }).then((x) => Util.randomChoice(x)).catch(Util.noop);
1587
1684
  if (!info) {
1588
1685
  return __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1589
1686
  }
@@ -1757,7 +1854,7 @@ var VoiceReceiverNode = class {
1757
1854
  setImmediate(async () => {
1758
1855
  if (options.mode === "pcm") {
1759
1856
  const pcm = receiveStream.pipe(
1760
- new prism2.opus.Decoder({
1857
+ new (prism2.opus || prism2.default.opus).Decoder({
1761
1858
  channels: 2,
1762
1859
  frameSize: 960,
1763
1860
  rate: 48e3
@@ -1784,6 +1881,30 @@ var SearchResult = class {
1784
1881
  track.extractor = this._data.extractor || null;
1785
1882
  });
1786
1883
  }
1884
+ setQueryType(type) {
1885
+ this._data.queryType = type;
1886
+ return this;
1887
+ }
1888
+ setRequestedBy(user) {
1889
+ this._data.requestedBy = user;
1890
+ return this;
1891
+ }
1892
+ setExtractor(extractor) {
1893
+ this._data.extractor = extractor;
1894
+ return this;
1895
+ }
1896
+ setTracks(tracks) {
1897
+ this._data.tracks = tracks;
1898
+ return this;
1899
+ }
1900
+ setQuery(query) {
1901
+ this._data.query = query;
1902
+ return this;
1903
+ }
1904
+ setPlaylist(playlist) {
1905
+ this._data.playlist = playlist;
1906
+ return this;
1907
+ }
1787
1908
  get query() {
1788
1909
  return this._data.query;
1789
1910
  }
@@ -1884,6 +2005,14 @@ var import_voice5 = require("@discordjs/voice");
1884
2005
  var import_voice4 = require("@discordjs/voice");
1885
2006
  var import_utils6 = require("@discord-player/utils");
1886
2007
  var import_equalizer2 = require("@discord-player/equalizer");
2008
+ var needsKeepAlivePatch = (() => {
2009
+ if ("DP_NO_KEEPALIVE_PATCH" in process.env)
2010
+ return false;
2011
+ if (import_voice4.version.includes("-dev") || import_voice4.version.startsWith("1"))
2012
+ return false;
2013
+ const [_major, minor, patch] = import_voice4.version.split(".").map((n) => parseInt(n));
2014
+ return minor > 14 ? false : minor < 15 && patch < 1;
2015
+ })();
1887
2016
  var StreamDispatcher = class extends import_utils6.EventEmitter {
1888
2017
  constructor(connection, channel, queue, connectionTimeout = 2e4) {
1889
2018
  super();
@@ -1895,6 +2024,10 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1895
2024
  this.voiceConnection = connection;
1896
2025
  this.audioPlayer = (0, import_voice4.createAudioPlayer)();
1897
2026
  this.channel = channel;
2027
+ this.voiceConnection.on("debug", (m) => void this.emit("debug", m));
2028
+ this.voiceConnection.on("error", (error) => void this.emit("error", error));
2029
+ this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
2030
+ this.audioPlayer.on("error", (error) => void this.emit("error", error));
1898
2031
  this.dsp.onUpdate = () => {
1899
2032
  if (!this.dsp)
1900
2033
  return;
@@ -1910,14 +2043,26 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1910
2043
  this.emit("sampleRate", this.dsp.resampler.targetSampleRate);
1911
2044
  };
1912
2045
  this.dsp.onError = (e) => this.emit("error", e);
1913
- this.voiceConnection.on("stateChange", async (_, newState) => {
2046
+ this.voiceConnection.on("stateChange", async (oldState, newState) => {
2047
+ if (needsKeepAlivePatch) {
2048
+ this.queue.debug(`Detected @discordjs/voice version ${import_voice4.version} which needs keepAlive patch, applying patch...`);
2049
+ const oldNetworking = Reflect.get(oldState, "networking");
2050
+ const newNetworking = Reflect.get(newState, "networking");
2051
+ const networkStateChangeHandler = /* @__PURE__ */ __name((_, newNetworkState) => {
2052
+ const newUdp = Reflect.get(newNetworkState, "udp");
2053
+ clearInterval(newUdp?.keepAliveInterval);
2054
+ }, "networkStateChangeHandler");
2055
+ oldNetworking?.off("stateChange", networkStateChangeHandler);
2056
+ newNetworking?.on("stateChange", networkStateChangeHandler);
2057
+ }
1914
2058
  if (newState.status === import_voice4.VoiceConnectionStatus.Disconnected) {
1915
2059
  if (newState.reason === import_voice4.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
1916
2060
  try {
1917
2061
  await (0, import_voice4.entersState)(this.voiceConnection, import_voice4.VoiceConnectionStatus.Connecting, this.connectionTimeout);
1918
2062
  } catch {
1919
2063
  try {
1920
- this.voiceConnection.destroy();
2064
+ if (this.voiceConnection.state.status !== import_voice4.VoiceConnectionStatus.Destroyed)
2065
+ this.voiceConnection.destroy();
1921
2066
  } catch (err) {
1922
2067
  this.emit("error", err);
1923
2068
  }
@@ -1927,7 +2072,8 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1927
2072
  this.voiceConnection.rejoin();
1928
2073
  } else {
1929
2074
  try {
1930
- this.voiceConnection.destroy();
2075
+ if (this.voiceConnection.state.status !== import_voice4.VoiceConnectionStatus.Destroyed)
2076
+ this.voiceConnection.destroy();
1931
2077
  } catch (err) {
1932
2078
  this.emit("error", err);
1933
2079
  }
@@ -1962,8 +2108,6 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1962
2108
  this.audioResource = null;
1963
2109
  }
1964
2110
  });
1965
- this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
1966
- this.audioPlayer.on("error", (error) => void this.emit("error", error));
1967
2111
  this.voiceConnection.subscribe(this.audioPlayer);
1968
2112
  }
1969
2113
  get paused() {
@@ -1984,6 +2128,21 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1984
2128
  isIdle() {
1985
2129
  return this.audioPlayer.state.status === import_voice4.AudioPlayerStatus.Idle;
1986
2130
  }
2131
+ isDestroyed() {
2132
+ return this.voiceConnection.state.status === import_voice4.VoiceConnectionStatus.Destroyed;
2133
+ }
2134
+ isDisconnected() {
2135
+ return this.voiceConnection.state.status === import_voice4.VoiceConnectionStatus.Disconnected;
2136
+ }
2137
+ isReady() {
2138
+ return this.voiceConnection.state.status === import_voice4.VoiceConnectionStatus.Ready;
2139
+ }
2140
+ isSignalling() {
2141
+ return this.voiceConnection.state.status === import_voice4.VoiceConnectionStatus.Signalling;
2142
+ }
2143
+ isConnecting() {
2144
+ return this.voiceConnection.state.status === import_voice4.VoiceConnectionStatus.Connecting;
2145
+ }
1987
2146
  async createStream(src, ops) {
1988
2147
  if (!ops?.disableFilters)
1989
2148
  this.queue.debug("Initiating DSP filters pipeline...");
@@ -2043,12 +2202,16 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
2043
2202
  try {
2044
2203
  if (this.audioPlayer)
2045
2204
  this.audioPlayer.stop(true);
2046
- this.voiceConnection.destroy();
2205
+ if (this.voiceConnection.state.status !== import_voice4.VoiceConnectionStatus.Destroyed)
2206
+ this.voiceConnection.destroy();
2047
2207
  } catch {
2048
2208
  }
2049
2209
  }
2050
2210
  end() {
2051
- this.audioPlayer.stop();
2211
+ try {
2212
+ this.audioPlayer.stop();
2213
+ } catch {
2214
+ }
2052
2215
  }
2053
2216
  pause(interpolateSilence) {
2054
2217
  const success = this.audioPlayer.pause(interpolateSilence);
@@ -2101,7 +2264,8 @@ __name(StreamDispatcher, "StreamDispatcher");
2101
2264
  // src/VoiceInterface/VoiceUtils.ts
2102
2265
  var import_utils7 = require("@discord-player/utils");
2103
2266
  var VoiceUtils = class {
2104
- constructor() {
2267
+ constructor(player) {
2268
+ this.player = player;
2105
2269
  this.cache = new import_utils7.Collection();
2106
2270
  }
2107
2271
  async connect(channel, options) {
@@ -2117,14 +2281,19 @@ var VoiceUtils = class {
2117
2281
  guildId: channel.guild.id,
2118
2282
  channelId: channel.id,
2119
2283
  adapterCreator: channel.guild.voiceAdapterCreator,
2120
- selfDeaf: Boolean(options?.deaf)
2284
+ selfDeaf: Boolean(options?.deaf),
2285
+ debug: this.player.events.eventNames().includes("debug")
2121
2286
  });
2122
2287
  return conn;
2123
2288
  }
2124
2289
  disconnect(connection) {
2125
2290
  if (connection instanceof StreamDispatcher)
2126
- return connection.voiceConnection.destroy();
2127
- return connection.destroy();
2291
+ connection = connection.voiceConnection;
2292
+ try {
2293
+ if (connection.state.status !== import_voice5.VoiceConnectionStatus.Destroyed)
2294
+ return connection.destroy();
2295
+ } catch {
2296
+ }
2128
2297
  }
2129
2298
  getConnection(guild) {
2130
2299
  return this.cache.get(guild) || (0, import_voice5.getVoiceConnection)(guild);
@@ -2133,7 +2302,6 @@ var VoiceUtils = class {
2133
2302
  __name(VoiceUtils, "VoiceUtils");
2134
2303
 
2135
2304
  // src/utils/QueryCache.ts
2136
- var import_fuse = __toESM(require("fuse.js"));
2137
2305
  var DEFAULT_EXPIRY_TIMEOUT = 18e6;
2138
2306
  var _defaultCache;
2139
2307
  var QueryCache = class {
@@ -2143,11 +2311,6 @@ var QueryCache = class {
2143
2311
  this.player = player;
2144
2312
  this.options = options;
2145
2313
  __privateAdd(this, _defaultCache, /* @__PURE__ */ new Map());
2146
- this.fuse = new import_fuse.default([], {
2147
- keys: [
2148
- "url"
2149
- ]
2150
- });
2151
2314
  this.timer = setInterval(this.cleanup.bind(this), this.checkInterval).unref();
2152
2315
  }
2153
2316
  get checkInterval() {
@@ -2174,10 +2337,8 @@ var QueryCache = class {
2174
2337
  });
2175
2338
  }
2176
2339
  async resolve(context) {
2177
- const cacheData = await this.getData();
2178
- this.fuse.setCollection(cacheData.map((m) => m.data));
2179
- const result = this.fuse.search(context.query);
2180
- if (!result.length)
2340
+ const result = __privateGet(this, _defaultCache).get(context.query);
2341
+ if (!result)
2181
2342
  return new SearchResult(this.player, {
2182
2343
  query: context.query,
2183
2344
  requestedBy: context.requestedBy,
@@ -2185,7 +2346,7 @@ var QueryCache = class {
2185
2346
  });
2186
2347
  return new SearchResult(this.player, {
2187
2348
  query: context.query,
2188
- tracks: result.map((m) => m.item),
2349
+ tracks: [result.data],
2189
2350
  playlist: null,
2190
2351
  queryType: context.queryType,
2191
2352
  requestedBy: context.requestedBy
@@ -2215,7 +2376,8 @@ var import_discord3 = require("discord.js");
2215
2376
  var import_voice6 = require("@discordjs/voice");
2216
2377
 
2217
2378
  // src/utils/__internal__/_container.ts
2218
- var instances = /* @__PURE__ */ new Map();
2379
+ var import_utils8 = require("@discord-player/utils");
2380
+ var instances = new import_utils8.Collection();
2219
2381
 
2220
2382
  // src/utils/__internal__/addPlayer.ts
2221
2383
  function addPlayer(player) {
@@ -2234,7 +2396,7 @@ __name(clearPlayer, "clearPlayer");
2234
2396
 
2235
2397
  // src/utils/__internal__/getPlayers.ts
2236
2398
  function getPlayers() {
2237
- return [...instances.values()];
2399
+ return instances.array();
2238
2400
  }
2239
2401
  __name(getPlayers, "getPlayers");
2240
2402
 
@@ -2243,6 +2405,8 @@ var kSingleton = Symbol("InstanceDiscordPlayerSingleton");
2243
2405
  var _lastLatency, _voiceStateUpdateListener, _lagMonitorTimeout, _lagMonitorInterval;
2244
2406
  var _Player = class extends PlayerEventsEmitter {
2245
2407
  constructor(client, options = {}) {
2408
+ if (!options.ignoreInstance && kSingleton in _Player)
2409
+ return _Player[kSingleton];
2246
2410
  super(["error"]);
2247
2411
  __privateAdd(this, _lastLatency, -1);
2248
2412
  __privateAdd(this, _voiceStateUpdateListener, this.handleVoiceState.bind(this));
@@ -2250,7 +2414,7 @@ var _Player = class extends PlayerEventsEmitter {
2250
2414
  __privateAdd(this, _lagMonitorInterval, void 0);
2251
2415
  this.id = import_discord3.SnowflakeUtil.generate().toString();
2252
2416
  this.nodes = new GuildNodeManager(this);
2253
- this.voiceUtils = new VoiceUtils();
2417
+ this.voiceUtils = new VoiceUtils(this);
2254
2418
  this.extractors = new ExtractorExecutionContext(this);
2255
2419
  this.events = new PlayerEventsEmitter(["error", "playerError"]);
2256
2420
  this.client = client;
@@ -2294,20 +2458,23 @@ ${this.scanDeps()}`);
2294
2458
  }, this.options.lagMonitor).unref());
2295
2459
  }
2296
2460
  addPlayer(this);
2297
- }
2298
- debug(m) {
2299
- return this.emit("debug", m);
2300
- }
2301
- static singleton(client, options = {}) {
2302
2461
  if (!(kSingleton in _Player)) {
2303
2462
  Object.defineProperty(_Player, kSingleton, {
2304
- value: new _Player(client, options),
2463
+ value: this,
2305
2464
  writable: true,
2306
2465
  configurable: true,
2307
2466
  enumerable: false
2308
2467
  });
2309
2468
  }
2310
- return _Player[kSingleton];
2469
+ }
2470
+ debug(m) {
2471
+ return this.emit("debug", m);
2472
+ }
2473
+ static singleton(client, options = {}) {
2474
+ return new _Player(client, {
2475
+ ...options,
2476
+ ignoreInstance: false
2477
+ });
2311
2478
  }
2312
2479
  static getAllPlayers() {
2313
2480
  return getPlayers();
@@ -2351,20 +2518,20 @@ ${this.scanDeps()}`);
2351
2518
  const wasHandled = this.events.emit("voiceStateUpdate", queue, oldState, newState);
2352
2519
  if (wasHandled && !this.options.lockVoiceStateHandler)
2353
2520
  return;
2354
- if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) {
2521
+ if (oldState.channelId && !newState.channelId && newState.member?.id === newState.guild.members.me?.id) {
2355
2522
  try {
2356
2523
  queue.delete();
2357
2524
  } catch {
2358
2525
  }
2359
2526
  return void this.events.emit("disconnect", queue);
2360
2527
  }
2361
- if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) {
2528
+ if (!oldState.channelId && newState.channelId && newState.member?.id === newState.guild.members.me?.id) {
2362
2529
  if (newState.serverMute != null && oldState.serverMute !== newState.serverMute) {
2363
2530
  queue.node.setPaused(newState.serverMute);
2364
2531
  } else if (newState.channel?.type === import_discord3.ChannelType.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) {
2365
2532
  queue.node.setPaused(newState.suppress);
2366
2533
  if (newState.suppress) {
2367
- newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop);
2534
+ newState.guild.members.me?.voice.setRequestToSpeak(true).catch(Util.noop);
2368
2535
  }
2369
2536
  }
2370
2537
  }
@@ -2391,8 +2558,8 @@ ${this.scanDeps()}`);
2391
2558
  }
2392
2559
  }
2393
2560
  if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
2394
- if (newState.member.id === newState.guild.members.me.id) {
2395
- if (queue.connection && newState.member.id === newState.guild.members.me.id)
2561
+ if (newState.member?.id === newState.guild.members.me?.id) {
2562
+ if (queue.connection && newState.member?.id === newState.guild.members.me?.id)
2396
2563
  queue.channel = newState.channel;
2397
2564
  const emptyTimeout = queue.timeouts.get(`empty_${oldState.guild.id}`);
2398
2565
  const channelEmpty = Util.isVoiceEmpty(queue.channel);
@@ -2454,19 +2621,21 @@ ${this.scanDeps()}`);
2454
2621
  const vc = this.client.channels.resolve(channel);
2455
2622
  if (!vc?.isVoiceBased())
2456
2623
  throw new Error("Expected a voice channel");
2457
- const result = query instanceof SearchResult ? query : await this.search(query, options);
2624
+ const originalResult = query instanceof SearchResult ? query : await this.search(query, options);
2625
+ const result = await options.afterSearch?.(originalResult) || originalResult;
2458
2626
  if (result.isEmpty()) {
2459
2627
  throw new Error(`No results found for "${query}" (Extractor: ${result.extractor?.identifier || "N/A"})`);
2460
2628
  }
2461
2629
  const queue = this.nodes.create(vc.guild, options.nodeOptions);
2462
2630
  if (!queue.channel)
2463
2631
  await queue.connect(vc, options.connectionOptions);
2464
- if (!result.hasPlaylist()) {
2465
- await queue.node.play(result.tracks[0]);
2632
+ if (!result.playlist) {
2633
+ queue.addTrack(result.tracks[0]);
2466
2634
  } else {
2467
2635
  queue.addTrack(result.playlist);
2468
- await queue.node.play();
2469
2636
  }
2637
+ if (!queue.isPlaying())
2638
+ await queue.node.play();
2470
2639
  return {
2471
2640
  track: result.tracks[0],
2472
2641
  extractor: result.extractor,
@@ -2475,20 +2644,42 @@ ${this.scanDeps()}`);
2475
2644
  };
2476
2645
  }
2477
2646
  async search(query, options = {}) {
2647
+ if (query instanceof SearchResult)
2648
+ return query;
2478
2649
  if (options.requestedBy != null)
2479
2650
  options.requestedBy = this.client.users.resolve(options.requestedBy);
2480
2651
  options.blockExtractors ?? (options.blockExtractors = this.options.blockExtractors);
2481
2652
  if (query instanceof Track) {
2482
- this.debug(`Searching ${query.title}`);
2483
2653
  return new SearchResult(this, {
2484
2654
  playlist: query.playlist || null,
2485
2655
  tracks: [query],
2486
- query: query.toString(),
2656
+ query: query.title,
2487
2657
  extractor: null,
2488
2658
  queryType: query.queryType,
2489
2659
  requestedBy: options.requestedBy
2490
2660
  });
2491
2661
  }
2662
+ if (query instanceof Playlist) {
2663
+ return new SearchResult(this, {
2664
+ playlist: query,
2665
+ tracks: query.tracks,
2666
+ query: query.title,
2667
+ extractor: null,
2668
+ queryType: QueryType.AUTO,
2669
+ requestedBy: options.requestedBy
2670
+ });
2671
+ }
2672
+ if (Array.isArray(query)) {
2673
+ const tracks = query.filter((t) => t instanceof Track);
2674
+ return new SearchResult(this, {
2675
+ playlist: null,
2676
+ tracks,
2677
+ query: "@@#%{{UserLoadedContent}}%#@@",
2678
+ extractor: null,
2679
+ queryType: QueryType.AUTO,
2680
+ requestedBy: options.requestedBy
2681
+ });
2682
+ }
2492
2683
  this.debug(`Searching ${query}`);
2493
2684
  let extractor = null;
2494
2685
  options.searchEngine ?? (options.searchEngine = QueryType.AUTO);
@@ -2596,11 +2787,55 @@ _lagMonitorTimeout = new WeakMap();
2596
2787
  _lagMonitorInterval = new WeakMap();
2597
2788
  Player._singletonKey = kSingleton;
2598
2789
 
2790
+ // src/hooks/common.ts
2791
+ var getPlayer = /* @__PURE__ */ __name(() => {
2792
+ return instances.first() || null;
2793
+ }, "getPlayer");
2794
+ var getQueue = /* @__PURE__ */ __name((node) => {
2795
+ const player = getPlayer();
2796
+ if (!player)
2797
+ return null;
2798
+ return player.nodes.resolve(node) || null;
2799
+ }, "getQueue");
2800
+
2801
+ // src/hooks/useHistory.ts
2802
+ function useHistory(node) {
2803
+ const queue = getQueue(node);
2804
+ if (!queue)
2805
+ return null;
2806
+ return queue.history;
2807
+ }
2808
+ __name(useHistory, "useHistory");
2809
+
2810
+ // src/hooks/usePlayer.ts
2811
+ function usePlayer(node) {
2812
+ const queue = getQueue(node);
2813
+ if (!queue)
2814
+ return null;
2815
+ return queue.node;
2816
+ }
2817
+ __name(usePlayer, "usePlayer");
2818
+
2819
+ // src/hooks/useQueue.ts
2820
+ function useQueue(node) {
2821
+ const queue = getQueue(node);
2822
+ if (!queue)
2823
+ return null;
2824
+ return queue;
2825
+ }
2826
+ __name(useQueue, "useQueue");
2827
+
2828
+ // src/hooks/useMasterPlayer.ts
2829
+ function useMasterPlayer() {
2830
+ return getPlayer();
2831
+ }
2832
+ __name(useMasterPlayer, "useMasterPlayer");
2833
+
2599
2834
  // src/index.ts
2600
2835
  var import_equalizer3 = require("@discord-player/equalizer");
2601
- var version = "6.0.0-dev.4";
2836
+ var version2 = "6.0.0";
2602
2837
  if (!import_discord4.version.startsWith("14")) {
2603
- process.emitWarning(`Discord.js v${import_discord4.version} is incompatible with Discord Player v${version}! Please use >=v14.x of Discord.js`);
2838
+ process.emitWarning(`Discord.js v${import_discord4.version} is incompatible with Discord Player v${version2}! Please use >=v14.x of Discord.js`);
2604
2839
  }
2605
2840
  // Annotate the CommonJS export names for ESM import in node:
2606
2841
  0 && (module.exports = {
@@ -2623,15 +2858,18 @@ if (!import_discord4.version.startsWith("14")) {
2623
2858
  GuildNodeManager,
2624
2859
  GuildQueue,
2625
2860
  GuildQueueAudioFilters,
2861
+ GuildQueueEvent,
2626
2862
  GuildQueueHistory,
2627
2863
  GuildQueuePlayerNode,
2628
2864
  PCMAudioFilters,
2629
2865
  Player,
2630
2866
  PlayerError,
2867
+ PlayerEvent,
2631
2868
  PlayerEventsEmitter,
2632
2869
  Playlist,
2633
2870
  Q_BUTTERWORTH,
2634
2871
  QueryCache,
2872
+ QueryResolver,
2635
2873
  QueryType,
2636
2874
  QueueRepeatMode,
2637
2875
  SearchResult,
@@ -2642,6 +2880,10 @@ if (!import_discord4.version.startsWith("14")) {
2642
2880
  VoiceUtils,
2643
2881
  VolumeTransformer,
2644
2882
  createFFmpegStream,
2883
+ useHistory,
2884
+ useMasterPlayer,
2885
+ usePlayer,
2886
+ useQueue,
2645
2887
  version
2646
2888
  });
2647
2889
  //# sourceMappingURL=index.js.map