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.mjs CHANGED
@@ -112,6 +112,9 @@ var Util = class {
112
112
  detail
113
113
  });
114
114
  }
115
+ static randomChoice(src) {
116
+ return src[Math.floor(Math.random() * src.length)];
117
+ }
115
118
  };
116
119
  __name(Util, "Util");
117
120
 
@@ -254,7 +257,15 @@ BaseExtractor.identifier = "com.discord-player.extractor";
254
257
 
255
258
  // src/extractors/ExtractorExecutionContext.ts
256
259
  import { Collection } from "@discord-player/utils";
257
- var knownExtractorKeys = ["YouTubeExtractor", "SoundCloudExtractor", "ReverbnationExtractor", "VimeoExtractor", "AttachmentExtractor"];
260
+ var knownExtractorKeys = [
261
+ "SoundCloudExtractor",
262
+ "AppleMusicExtractor",
263
+ "SpotifyExtractor",
264
+ "VimeoExtractor",
265
+ "YouTubeExtractor",
266
+ "ReverbnationExtractor",
267
+ "AttachmentExtractor"
268
+ ];
258
269
  var knownExtractorLib = "@discord-player/extractor";
259
270
  var ExtractorExecutionContext = class {
260
271
  constructor(player) {
@@ -428,6 +439,12 @@ var Playlist = class {
428
439
  *[Symbol.iterator]() {
429
440
  yield* this.tracks;
430
441
  }
442
+ get estimatedDuration() {
443
+ return this.tracks.reduce((p, c) => p + c.durationMS, 0);
444
+ }
445
+ get durationFormatted() {
446
+ return Util.buildTimeCode(Util.parseMS(this.estimatedDuration));
447
+ }
431
448
  toJSON(withTracks = true) {
432
449
  const payload = {
433
450
  id: this.id,
@@ -466,6 +483,12 @@ var GuildQueueHistory = class {
466
483
  get disabled() {
467
484
  return this.queue.options.disableHistory;
468
485
  }
486
+ get size() {
487
+ return this.tracks.size;
488
+ }
489
+ getSize() {
490
+ return this.size;
491
+ }
469
492
  isEmpty() {
470
493
  return this.tracks.size < 1;
471
494
  }
@@ -485,14 +508,14 @@ var GuildQueueHistory = class {
485
508
  }
486
509
  this.queue.node.skip();
487
510
  }
488
- async previous() {
511
+ async previous(preserveCurrent = true) {
489
512
  const track = this.tracks.dispatch();
490
513
  if (!track) {
491
514
  throw new Error("No previous track in the queue");
492
515
  }
493
516
  const current = this.currentTrack;
494
517
  await this.queue.node.play(track, { queue: false });
495
- if (current)
518
+ if (current && preserveCurrent)
496
519
  this.queue.node.insert(current, 0);
497
520
  }
498
521
  back() {
@@ -528,8 +551,15 @@ var QueryType = {
528
551
  APPLE_MUSIC_SONG: "appleMusicSong",
529
552
  APPLE_MUSIC_ALBUM: "appleMusicAlbum",
530
553
  APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
554
+ APPLE_MUSIC_SEARCH: "appleMusicSearch",
531
555
  FILE: "file"
532
556
  };
557
+ var PlayerEvent = /* @__PURE__ */ ((PlayerEvent2) => {
558
+ PlayerEvent2["debug"] = "debug";
559
+ PlayerEvent2["error"] = "error";
560
+ PlayerEvent2["voiceStateUpdate"] = "voiceStateUpdate";
561
+ return PlayerEvent2;
562
+ })(PlayerEvent || {});
533
563
  var QueueRepeatMode = /* @__PURE__ */ ((QueueRepeatMode2) => {
534
564
  QueueRepeatMode2[QueueRepeatMode2["OFF"] = 0] = "OFF";
535
565
  QueueRepeatMode2[QueueRepeatMode2["TRACK"] = 1] = "TRACK";
@@ -566,10 +596,10 @@ var QueryResolver = class {
566
596
  };
567
597
  }
568
598
  static resolve(query) {
569
- query = query.trim();
570
- if (soundcloud.validateURL(query, "track"))
599
+ query = !query.includes("youtube.com") ? query.trim() : query.replace(/(m(usic)?|gaming)\./, "").trim();
600
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "track"))
571
601
  return QueryType.SOUNDCLOUD_TRACK;
572
- if (soundcloud.validateURL(query, "playlist") || query.includes("/sets/"))
602
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "playlist") || query.includes("/sets/"))
573
603
  return QueryType.SOUNDCLOUD_PLAYLIST;
574
604
  if (YouTube.isPlaylist(query))
575
605
  return QueryType.YOUTUBE_PLAYLIST;
@@ -750,6 +780,7 @@ var GuildQueuePlayerNode = class {
750
780
  if (!foundTrack)
751
781
  return null;
752
782
  this.queue.tracks.removeOne((t) => t.id === foundTrack.id);
783
+ this.queue.player.events.emit("audioTrackRemove", this.queue, foundTrack);
753
784
  return foundTrack;
754
785
  }
755
786
  jump(track) {
@@ -776,15 +807,20 @@ var GuildQueuePlayerNode = class {
776
807
  const removed = this.remove(idx);
777
808
  if (!removed)
778
809
  return false;
810
+ const toRemove = this.queue.tracks.store.filter((_, i) => i <= idx);
779
811
  this.queue.tracks.store.splice(0, idx, removed);
812
+ this.queue.player.events.emit("audioTracksRemove", this.queue, toRemove);
780
813
  return this.skip();
781
814
  }
782
815
  insert(track, index = 0) {
783
816
  if (!(track instanceof Track))
784
817
  throw new Error("invalid track");
785
818
  this.queue.tracks.store.splice(index, 0, track);
819
+ this.queue.player.events.emit("audioTrackAdd", this.queue, track);
786
820
  }
787
821
  stop(force = false) {
822
+ this.queue.tracks.clear();
823
+ this.queue.history.clear();
788
824
  if (!this.queue.dispatcher)
789
825
  return false;
790
826
  this.queue.dispatcher.end();
@@ -820,7 +856,7 @@ var GuildQueuePlayerNode = class {
820
856
  );
821
857
  if (res && options.queue) {
822
858
  this.queue.debug("Requested option requires to queue the track, adding the given track to queue instead...");
823
- return this.queue.tracks.add(res);
859
+ return this.queue.addTrack(res);
824
860
  }
825
861
  const track = res || this.queue.tracks.dispatch();
826
862
  if (!track) {
@@ -849,7 +885,7 @@ var GuildQueuePlayerNode = class {
849
885
  this.queue.player.events.emit("playerSkip", this.queue, track);
850
886
  this.queue.player.events.emit("playerError", this.queue, error, track);
851
887
  this.queue.initializing = false;
852
- this.play(this.queue.tracks.dispatch());
888
+ this.play(this.queue.tracks.dispatch(), { queue: false });
853
889
  return;
854
890
  }
855
891
  throw error;
@@ -1011,7 +1047,7 @@ function createFFmpegStream(stream, options) {
1011
1047
  args.unshift("-ss", String(options.seek));
1012
1048
  if (Array.isArray(options.encoderArgs))
1013
1049
  args.push(...options.encoderArgs);
1014
- const transcoder = new prism.FFmpeg({ shell: false, args });
1050
+ const transcoder = new (prism.FFmpeg || prism.default.FFmpeg)({ shell: false, args });
1015
1051
  transcoder.on("close", () => transcoder.destroy());
1016
1052
  if (typeof stream !== "string") {
1017
1053
  stream.on("error", () => transcoder.destroy());
@@ -1244,7 +1280,7 @@ var GuildQueueStatistics = class {
1244
1280
  memoryUsage: process.memoryUsage(),
1245
1281
  versions: {
1246
1282
  node: process.version,
1247
- player: "6.0.0-dev.4"
1283
+ player: "6.0.0"
1248
1284
  }
1249
1285
  };
1250
1286
  }
@@ -1252,6 +1288,25 @@ var GuildQueueStatistics = class {
1252
1288
  __name(GuildQueueStatistics, "GuildQueueStatistics");
1253
1289
 
1254
1290
  // src/Structures/GuildQueue.ts
1291
+ var GuildQueueEvent = /* @__PURE__ */ ((GuildQueueEvent2) => {
1292
+ GuildQueueEvent2["audioTrackAdd"] = "audioTrackadd";
1293
+ GuildQueueEvent2["audioTracksAdd"] = "audioTracksAdd";
1294
+ GuildQueueEvent2["audioTrackRemove"] = "audioTrackRemove";
1295
+ GuildQueueEvent2["audioTracksRemove"] = "audioTracksRemove";
1296
+ GuildQueueEvent2["connection"] = "connection";
1297
+ GuildQueueEvent2["disconnect"] = "disconnect";
1298
+ GuildQueueEvent2["debug"] = "debug";
1299
+ GuildQueueEvent2["error"] = "error";
1300
+ GuildQueueEvent2["emptyChannel"] = "emptyChannel";
1301
+ GuildQueueEvent2["emptyQueue"] = "emptyQueue";
1302
+ GuildQueueEvent2["playerStart"] = "playerStart";
1303
+ GuildQueueEvent2["playerError"] = "playerError";
1304
+ GuildQueueEvent2["playerFinish"] = "playerFinish";
1305
+ GuildQueueEvent2["playerSkip"] = "playerSkip";
1306
+ GuildQueueEvent2["playerTrigger"] = "playerTrigger";
1307
+ GuildQueueEvent2["voiceStateUpdate"] = "voiceStateUpdate";
1308
+ return GuildQueueEvent2;
1309
+ })(GuildQueueEvent || {});
1255
1310
  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;
1256
1311
  var GuildQueue = class {
1257
1312
  constructor(player, options) {
@@ -1306,6 +1361,12 @@ var GuildQueue = class {
1306
1361
  }
1307
1362
  this.debug(`GuildQueue initialized for guild ${this.options.guild.name} (ID: ${this.options.guild.id})`);
1308
1363
  }
1364
+ get estimatedDuration() {
1365
+ return this.tracks.store.reduce((a, c) => a + c.durationMS, 0);
1366
+ }
1367
+ get durationFormatted() {
1368
+ return Util.buildTimeCode(Util.parseMS(this.estimatedDuration));
1369
+ }
1309
1370
  get voiceReceiver() {
1310
1371
  return this.dispatcher?.receiver ?? null;
1311
1372
  }
@@ -1365,18 +1426,27 @@ var GuildQueue = class {
1365
1426
  setRepeatMode(mode) {
1366
1427
  this.repeatMode = mode;
1367
1428
  }
1429
+ get size() {
1430
+ return this.tracks.size;
1431
+ }
1432
+ getSize() {
1433
+ return this.size;
1434
+ }
1435
+ clear() {
1436
+ this.tracks.clear();
1437
+ this.history.clear();
1438
+ }
1368
1439
  isEmpty() {
1369
1440
  return this.tracks.size < 1;
1370
1441
  }
1371
1442
  isPlaying() {
1372
- return this.dispatcher?.audioResource != null;
1443
+ return this.dispatcher?.audioResource != null && !this.dispatcher.audioResource.ended;
1373
1444
  }
1374
1445
  addTrack(track) {
1375
1446
  const toAdd = track instanceof Playlist ? track.tracks : track;
1376
1447
  this.tracks.add(toAdd);
1377
1448
  const isMulti = Array.isArray(toAdd);
1378
1449
  if (isMulti) {
1379
- this.player.events.emit("audioTrackAdd", this, toAdd[0]);
1380
1450
  this.player.events.emit("audioTracksAdd", this, toAdd);
1381
1451
  } else {
1382
1452
  this.player.events.emit("audioTrackAdd", this, toAdd);
@@ -1472,7 +1542,14 @@ removeListeners_fn = /* @__PURE__ */ __name(function(dispatcher) {
1472
1542
  _performStart = new WeakSet();
1473
1543
  performStart_fn = /* @__PURE__ */ __name(function(resource) {
1474
1544
  const track = resource?.metadata || this.currentTrack;
1475
- this.player.events.emit("playerTrigger", this, track, this.isTransitioning() ? "filters" : "normal");
1545
+ const reason = this.isTransitioning() ? "filters" : "normal";
1546
+ this.debug(
1547
+ `Player triggered for Track ${JSON.stringify({
1548
+ title: track?.title,
1549
+ reason
1550
+ })}`
1551
+ );
1552
+ this.player.events.emit("playerTrigger", this, track, reason);
1476
1553
  if (track && !this.isTransitioning())
1477
1554
  this.player.events.emit("playerStart", this, track);
1478
1555
  this.setTransitioning(false);
@@ -1481,25 +1558,38 @@ performStart_fn = /* @__PURE__ */ __name(function(resource) {
1481
1558
  _performFinish = new WeakSet();
1482
1559
  performFinish_fn = /* @__PURE__ */ __name(function(resource) {
1483
1560
  const track = resource?.metadata || this.currentTrack;
1561
+ this.debug(
1562
+ `Track ${JSON.stringify({
1563
+ title: track?.title,
1564
+ isTransitionMode: this.isTransitioning()
1565
+ })} was marked as finished`
1566
+ );
1484
1567
  if (track && !this.isTransitioning()) {
1568
+ this.debug("Adding track to history and emitting finish event since transition mode is disabled...");
1485
1569
  this.history.push(track);
1486
1570
  this.node.resetProgress();
1487
1571
  this.player.events.emit("playerFinish", this, track);
1488
1572
  if (this.tracks.size < 1 && this.repeatMode === 0 /* OFF */) {
1573
+ this.debug("No more tracks left in the queue to play and repeat mode is off, initiating #emitEnd()");
1489
1574
  __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1490
1575
  } else {
1491
1576
  if (this.repeatMode === 1 /* TRACK */) {
1577
+ this.debug("Repeat mode is set to track, repeating last track from the history...");
1492
1578
  this.__current = this.history.tracks.dispatch() || track;
1493
1579
  return this.node.play(this.__current, { queue: false });
1494
1580
  }
1495
- if (this.repeatMode === 2 /* QUEUE */)
1581
+ if (this.repeatMode === 2 /* QUEUE */) {
1582
+ this.debug("Repeat mode is set to queue, moving last track from the history to current queue...");
1496
1583
  this.tracks.add(this.history.tracks.dispatch() || track);
1584
+ }
1497
1585
  if (!this.tracks.size) {
1498
1586
  if (this.repeatMode === 3 /* AUTOPLAY */) {
1587
+ this.debug("Repeat mode is set to autoplay, initiating autoplay handler...");
1499
1588
  __privateMethod(this, _handleAutoplay, handleAutoplay_fn).call(this, track);
1500
1589
  return;
1501
1590
  }
1502
1591
  } else {
1592
+ this.debug("Initializing next track of the queue...");
1503
1593
  this.__current = this.tracks.dispatch();
1504
1594
  this.node.play(this.__current, {
1505
1595
  queue: false
@@ -1522,9 +1612,9 @@ emitEnd_fn = /* @__PURE__ */ __name(function() {
1522
1612
  }, "#emitEnd");
1523
1613
  _handleAutoplay = new WeakSet();
1524
1614
  handleAutoplay_fn = /* @__PURE__ */ __name(async function(track) {
1525
- let info = await YouTube2.getVideo(track.url).then((x) => x.videos[0]).catch(Util.noop);
1615
+ let info = await YouTube2.getVideo(track.url).then((x) => Util.randomChoice(x.videos.slice(0, 5))).catch(Util.noop);
1526
1616
  if (!info)
1527
- info = await YouTube2.search(track.author).then((x) => x[0]).catch(Util.noop);
1617
+ info = await YouTube2.search(track.author, { limit: 5, type: "video" }).then((x) => Util.randomChoice(x)).catch(Util.noop);
1528
1618
  if (!info) {
1529
1619
  return __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1530
1620
  }
@@ -1698,7 +1788,7 @@ var VoiceReceiverNode = class {
1698
1788
  setImmediate(async () => {
1699
1789
  if (options.mode === "pcm") {
1700
1790
  const pcm = receiveStream.pipe(
1701
- new prism2.opus.Decoder({
1791
+ new (prism2.opus || prism2.default.opus).Decoder({
1702
1792
  channels: 2,
1703
1793
  frameSize: 960,
1704
1794
  rate: 48e3
@@ -1725,6 +1815,30 @@ var SearchResult = class {
1725
1815
  track.extractor = this._data.extractor || null;
1726
1816
  });
1727
1817
  }
1818
+ setQueryType(type) {
1819
+ this._data.queryType = type;
1820
+ return this;
1821
+ }
1822
+ setRequestedBy(user) {
1823
+ this._data.requestedBy = user;
1824
+ return this;
1825
+ }
1826
+ setExtractor(extractor) {
1827
+ this._data.extractor = extractor;
1828
+ return this;
1829
+ }
1830
+ setTracks(tracks) {
1831
+ this._data.tracks = tracks;
1832
+ return this;
1833
+ }
1834
+ setQuery(query) {
1835
+ this._data.query = query;
1836
+ return this;
1837
+ }
1838
+ setPlaylist(playlist) {
1839
+ this._data.playlist = playlist;
1840
+ return this;
1841
+ }
1728
1842
  get query() {
1729
1843
  return this._data.query;
1730
1844
  }
@@ -1819,7 +1933,7 @@ var PlayerError = class extends Error {
1819
1933
  __name(PlayerError, "PlayerError");
1820
1934
 
1821
1935
  // src/VoiceInterface/VoiceUtils.ts
1822
- import { joinVoiceChannel, getVoiceConnection } from "@discordjs/voice";
1936
+ import { joinVoiceChannel, getVoiceConnection, VoiceConnectionStatus as VoiceConnectionStatus2 } from "@discordjs/voice";
1823
1937
 
1824
1938
  // src/VoiceInterface/StreamDispatcher.ts
1825
1939
  import {
@@ -1829,10 +1943,19 @@ import {
1829
1943
  entersState,
1830
1944
  StreamType as StreamType3,
1831
1945
  VoiceConnectionStatus,
1832
- VoiceConnectionDisconnectReason
1946
+ VoiceConnectionDisconnectReason,
1947
+ version
1833
1948
  } from "@discordjs/voice";
1834
1949
  import { EventEmitter as EventEmitter2 } from "@discord-player/utils";
1835
1950
  import { FiltersChain } from "@discord-player/equalizer";
1951
+ var needsKeepAlivePatch = (() => {
1952
+ if ("DP_NO_KEEPALIVE_PATCH" in process.env)
1953
+ return false;
1954
+ if (version.includes("-dev") || version.startsWith("1"))
1955
+ return false;
1956
+ const [_major, minor, patch] = version.split(".").map((n) => parseInt(n));
1957
+ return minor > 14 ? false : minor < 15 && patch < 1;
1958
+ })();
1836
1959
  var StreamDispatcher = class extends EventEmitter2 {
1837
1960
  constructor(connection, channel, queue, connectionTimeout = 2e4) {
1838
1961
  super();
@@ -1844,6 +1967,10 @@ var StreamDispatcher = class extends EventEmitter2 {
1844
1967
  this.voiceConnection = connection;
1845
1968
  this.audioPlayer = createAudioPlayer();
1846
1969
  this.channel = channel;
1970
+ this.voiceConnection.on("debug", (m) => void this.emit("debug", m));
1971
+ this.voiceConnection.on("error", (error) => void this.emit("error", error));
1972
+ this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
1973
+ this.audioPlayer.on("error", (error) => void this.emit("error", error));
1847
1974
  this.dsp.onUpdate = () => {
1848
1975
  if (!this.dsp)
1849
1976
  return;
@@ -1859,14 +1986,26 @@ var StreamDispatcher = class extends EventEmitter2 {
1859
1986
  this.emit("sampleRate", this.dsp.resampler.targetSampleRate);
1860
1987
  };
1861
1988
  this.dsp.onError = (e) => this.emit("error", e);
1862
- this.voiceConnection.on("stateChange", async (_, newState) => {
1989
+ this.voiceConnection.on("stateChange", async (oldState, newState) => {
1990
+ if (needsKeepAlivePatch) {
1991
+ this.queue.debug(`Detected @discordjs/voice version ${version} which needs keepAlive patch, applying patch...`);
1992
+ const oldNetworking = Reflect.get(oldState, "networking");
1993
+ const newNetworking = Reflect.get(newState, "networking");
1994
+ const networkStateChangeHandler = /* @__PURE__ */ __name((_, newNetworkState) => {
1995
+ const newUdp = Reflect.get(newNetworkState, "udp");
1996
+ clearInterval(newUdp?.keepAliveInterval);
1997
+ }, "networkStateChangeHandler");
1998
+ oldNetworking?.off("stateChange", networkStateChangeHandler);
1999
+ newNetworking?.on("stateChange", networkStateChangeHandler);
2000
+ }
1863
2001
  if (newState.status === VoiceConnectionStatus.Disconnected) {
1864
2002
  if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
1865
2003
  try {
1866
2004
  await entersState(this.voiceConnection, VoiceConnectionStatus.Connecting, this.connectionTimeout);
1867
2005
  } catch {
1868
2006
  try {
1869
- this.voiceConnection.destroy();
2007
+ if (this.voiceConnection.state.status !== VoiceConnectionStatus.Destroyed)
2008
+ this.voiceConnection.destroy();
1870
2009
  } catch (err) {
1871
2010
  this.emit("error", err);
1872
2011
  }
@@ -1876,7 +2015,8 @@ var StreamDispatcher = class extends EventEmitter2 {
1876
2015
  this.voiceConnection.rejoin();
1877
2016
  } else {
1878
2017
  try {
1879
- this.voiceConnection.destroy();
2018
+ if (this.voiceConnection.state.status !== VoiceConnectionStatus.Destroyed)
2019
+ this.voiceConnection.destroy();
1880
2020
  } catch (err) {
1881
2021
  this.emit("error", err);
1882
2022
  }
@@ -1911,8 +2051,6 @@ var StreamDispatcher = class extends EventEmitter2 {
1911
2051
  this.audioResource = null;
1912
2052
  }
1913
2053
  });
1914
- this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
1915
- this.audioPlayer.on("error", (error) => void this.emit("error", error));
1916
2054
  this.voiceConnection.subscribe(this.audioPlayer);
1917
2055
  }
1918
2056
  get paused() {
@@ -1933,6 +2071,21 @@ var StreamDispatcher = class extends EventEmitter2 {
1933
2071
  isIdle() {
1934
2072
  return this.audioPlayer.state.status === AudioPlayerStatus.Idle;
1935
2073
  }
2074
+ isDestroyed() {
2075
+ return this.voiceConnection.state.status === VoiceConnectionStatus.Destroyed;
2076
+ }
2077
+ isDisconnected() {
2078
+ return this.voiceConnection.state.status === VoiceConnectionStatus.Disconnected;
2079
+ }
2080
+ isReady() {
2081
+ return this.voiceConnection.state.status === VoiceConnectionStatus.Ready;
2082
+ }
2083
+ isSignalling() {
2084
+ return this.voiceConnection.state.status === VoiceConnectionStatus.Signalling;
2085
+ }
2086
+ isConnecting() {
2087
+ return this.voiceConnection.state.status === VoiceConnectionStatus.Connecting;
2088
+ }
1936
2089
  async createStream(src, ops) {
1937
2090
  if (!ops?.disableFilters)
1938
2091
  this.queue.debug("Initiating DSP filters pipeline...");
@@ -1992,12 +2145,16 @@ var StreamDispatcher = class extends EventEmitter2 {
1992
2145
  try {
1993
2146
  if (this.audioPlayer)
1994
2147
  this.audioPlayer.stop(true);
1995
- this.voiceConnection.destroy();
2148
+ if (this.voiceConnection.state.status !== VoiceConnectionStatus.Destroyed)
2149
+ this.voiceConnection.destroy();
1996
2150
  } catch {
1997
2151
  }
1998
2152
  }
1999
2153
  end() {
2000
- this.audioPlayer.stop();
2154
+ try {
2155
+ this.audioPlayer.stop();
2156
+ } catch {
2157
+ }
2001
2158
  }
2002
2159
  pause(interpolateSilence) {
2003
2160
  const success = this.audioPlayer.pause(interpolateSilence);
@@ -2050,7 +2207,8 @@ __name(StreamDispatcher, "StreamDispatcher");
2050
2207
  // src/VoiceInterface/VoiceUtils.ts
2051
2208
  import { Collection as Collection4 } from "@discord-player/utils";
2052
2209
  var VoiceUtils = class {
2053
- constructor() {
2210
+ constructor(player) {
2211
+ this.player = player;
2054
2212
  this.cache = new Collection4();
2055
2213
  }
2056
2214
  async connect(channel, options) {
@@ -2066,14 +2224,19 @@ var VoiceUtils = class {
2066
2224
  guildId: channel.guild.id,
2067
2225
  channelId: channel.id,
2068
2226
  adapterCreator: channel.guild.voiceAdapterCreator,
2069
- selfDeaf: Boolean(options?.deaf)
2227
+ selfDeaf: Boolean(options?.deaf),
2228
+ debug: this.player.events.eventNames().includes("debug")
2070
2229
  });
2071
2230
  return conn;
2072
2231
  }
2073
2232
  disconnect(connection) {
2074
2233
  if (connection instanceof StreamDispatcher)
2075
- return connection.voiceConnection.destroy();
2076
- return connection.destroy();
2234
+ connection = connection.voiceConnection;
2235
+ try {
2236
+ if (connection.state.status !== VoiceConnectionStatus2.Destroyed)
2237
+ return connection.destroy();
2238
+ } catch {
2239
+ }
2077
2240
  }
2078
2241
  getConnection(guild) {
2079
2242
  return this.cache.get(guild) || getVoiceConnection(guild);
@@ -2082,7 +2245,6 @@ var VoiceUtils = class {
2082
2245
  __name(VoiceUtils, "VoiceUtils");
2083
2246
 
2084
2247
  // src/utils/QueryCache.ts
2085
- import Fuse from "fuse.js";
2086
2248
  var DEFAULT_EXPIRY_TIMEOUT = 18e6;
2087
2249
  var _defaultCache;
2088
2250
  var QueryCache = class {
@@ -2092,11 +2254,6 @@ var QueryCache = class {
2092
2254
  this.player = player;
2093
2255
  this.options = options;
2094
2256
  __privateAdd(this, _defaultCache, /* @__PURE__ */ new Map());
2095
- this.fuse = new Fuse([], {
2096
- keys: [
2097
- "url"
2098
- ]
2099
- });
2100
2257
  this.timer = setInterval(this.cleanup.bind(this), this.checkInterval).unref();
2101
2258
  }
2102
2259
  get checkInterval() {
@@ -2123,10 +2280,8 @@ var QueryCache = class {
2123
2280
  });
2124
2281
  }
2125
2282
  async resolve(context) {
2126
- const cacheData = await this.getData();
2127
- this.fuse.setCollection(cacheData.map((m) => m.data));
2128
- const result = this.fuse.search(context.query);
2129
- if (!result.length)
2283
+ const result = __privateGet(this, _defaultCache).get(context.query);
2284
+ if (!result)
2130
2285
  return new SearchResult(this.player, {
2131
2286
  query: context.query,
2132
2287
  requestedBy: context.requestedBy,
@@ -2134,7 +2289,7 @@ var QueryCache = class {
2134
2289
  });
2135
2290
  return new SearchResult(this.player, {
2136
2291
  query: context.query,
2137
- tracks: result.map((m) => m.item),
2292
+ tracks: [result.data],
2138
2293
  playlist: null,
2139
2294
  queryType: context.queryType,
2140
2295
  requestedBy: context.requestedBy
@@ -2164,7 +2319,8 @@ import { SnowflakeUtil as SnowflakeUtil2, IntentsBitField, ChannelType as Channe
2164
2319
  import { generateDependencyReport } from "@discordjs/voice";
2165
2320
 
2166
2321
  // src/utils/__internal__/_container.ts
2167
- var instances = /* @__PURE__ */ new Map();
2322
+ import { Collection as Collection5 } from "@discord-player/utils";
2323
+ var instances = new Collection5();
2168
2324
 
2169
2325
  // src/utils/__internal__/addPlayer.ts
2170
2326
  function addPlayer(player) {
@@ -2183,7 +2339,7 @@ __name(clearPlayer, "clearPlayer");
2183
2339
 
2184
2340
  // src/utils/__internal__/getPlayers.ts
2185
2341
  function getPlayers() {
2186
- return [...instances.values()];
2342
+ return instances.array();
2187
2343
  }
2188
2344
  __name(getPlayers, "getPlayers");
2189
2345
 
@@ -2192,6 +2348,8 @@ var kSingleton = Symbol("InstanceDiscordPlayerSingleton");
2192
2348
  var _lastLatency, _voiceStateUpdateListener, _lagMonitorTimeout, _lagMonitorInterval;
2193
2349
  var _Player = class extends PlayerEventsEmitter {
2194
2350
  constructor(client, options = {}) {
2351
+ if (!options.ignoreInstance && kSingleton in _Player)
2352
+ return _Player[kSingleton];
2195
2353
  super(["error"]);
2196
2354
  __privateAdd(this, _lastLatency, -1);
2197
2355
  __privateAdd(this, _voiceStateUpdateListener, this.handleVoiceState.bind(this));
@@ -2199,7 +2357,7 @@ var _Player = class extends PlayerEventsEmitter {
2199
2357
  __privateAdd(this, _lagMonitorInterval, void 0);
2200
2358
  this.id = SnowflakeUtil2.generate().toString();
2201
2359
  this.nodes = new GuildNodeManager(this);
2202
- this.voiceUtils = new VoiceUtils();
2360
+ this.voiceUtils = new VoiceUtils(this);
2203
2361
  this.extractors = new ExtractorExecutionContext(this);
2204
2362
  this.events = new PlayerEventsEmitter(["error", "playerError"]);
2205
2363
  this.client = client;
@@ -2243,20 +2401,23 @@ ${this.scanDeps()}`);
2243
2401
  }, this.options.lagMonitor).unref());
2244
2402
  }
2245
2403
  addPlayer(this);
2246
- }
2247
- debug(m) {
2248
- return this.emit("debug", m);
2249
- }
2250
- static singleton(client, options = {}) {
2251
2404
  if (!(kSingleton in _Player)) {
2252
2405
  Object.defineProperty(_Player, kSingleton, {
2253
- value: new _Player(client, options),
2406
+ value: this,
2254
2407
  writable: true,
2255
2408
  configurable: true,
2256
2409
  enumerable: false
2257
2410
  });
2258
2411
  }
2259
- return _Player[kSingleton];
2412
+ }
2413
+ debug(m) {
2414
+ return this.emit("debug", m);
2415
+ }
2416
+ static singleton(client, options = {}) {
2417
+ return new _Player(client, {
2418
+ ...options,
2419
+ ignoreInstance: false
2420
+ });
2260
2421
  }
2261
2422
  static getAllPlayers() {
2262
2423
  return getPlayers();
@@ -2300,20 +2461,20 @@ ${this.scanDeps()}`);
2300
2461
  const wasHandled = this.events.emit("voiceStateUpdate", queue, oldState, newState);
2301
2462
  if (wasHandled && !this.options.lockVoiceStateHandler)
2302
2463
  return;
2303
- if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) {
2464
+ if (oldState.channelId && !newState.channelId && newState.member?.id === newState.guild.members.me?.id) {
2304
2465
  try {
2305
2466
  queue.delete();
2306
2467
  } catch {
2307
2468
  }
2308
2469
  return void this.events.emit("disconnect", queue);
2309
2470
  }
2310
- if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) {
2471
+ if (!oldState.channelId && newState.channelId && newState.member?.id === newState.guild.members.me?.id) {
2311
2472
  if (newState.serverMute != null && oldState.serverMute !== newState.serverMute) {
2312
2473
  queue.node.setPaused(newState.serverMute);
2313
2474
  } else if (newState.channel?.type === ChannelType2.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) {
2314
2475
  queue.node.setPaused(newState.suppress);
2315
2476
  if (newState.suppress) {
2316
- newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop);
2477
+ newState.guild.members.me?.voice.setRequestToSpeak(true).catch(Util.noop);
2317
2478
  }
2318
2479
  }
2319
2480
  }
@@ -2340,8 +2501,8 @@ ${this.scanDeps()}`);
2340
2501
  }
2341
2502
  }
2342
2503
  if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
2343
- if (newState.member.id === newState.guild.members.me.id) {
2344
- if (queue.connection && newState.member.id === newState.guild.members.me.id)
2504
+ if (newState.member?.id === newState.guild.members.me?.id) {
2505
+ if (queue.connection && newState.member?.id === newState.guild.members.me?.id)
2345
2506
  queue.channel = newState.channel;
2346
2507
  const emptyTimeout = queue.timeouts.get(`empty_${oldState.guild.id}`);
2347
2508
  const channelEmpty = Util.isVoiceEmpty(queue.channel);
@@ -2403,19 +2564,21 @@ ${this.scanDeps()}`);
2403
2564
  const vc = this.client.channels.resolve(channel);
2404
2565
  if (!vc?.isVoiceBased())
2405
2566
  throw new Error("Expected a voice channel");
2406
- const result = query instanceof SearchResult ? query : await this.search(query, options);
2567
+ const originalResult = query instanceof SearchResult ? query : await this.search(query, options);
2568
+ const result = await options.afterSearch?.(originalResult) || originalResult;
2407
2569
  if (result.isEmpty()) {
2408
2570
  throw new Error(`No results found for "${query}" (Extractor: ${result.extractor?.identifier || "N/A"})`);
2409
2571
  }
2410
2572
  const queue = this.nodes.create(vc.guild, options.nodeOptions);
2411
2573
  if (!queue.channel)
2412
2574
  await queue.connect(vc, options.connectionOptions);
2413
- if (!result.hasPlaylist()) {
2414
- await queue.node.play(result.tracks[0]);
2575
+ if (!result.playlist) {
2576
+ queue.addTrack(result.tracks[0]);
2415
2577
  } else {
2416
2578
  queue.addTrack(result.playlist);
2417
- await queue.node.play();
2418
2579
  }
2580
+ if (!queue.isPlaying())
2581
+ await queue.node.play();
2419
2582
  return {
2420
2583
  track: result.tracks[0],
2421
2584
  extractor: result.extractor,
@@ -2424,20 +2587,42 @@ ${this.scanDeps()}`);
2424
2587
  };
2425
2588
  }
2426
2589
  async search(query, options = {}) {
2590
+ if (query instanceof SearchResult)
2591
+ return query;
2427
2592
  if (options.requestedBy != null)
2428
2593
  options.requestedBy = this.client.users.resolve(options.requestedBy);
2429
2594
  options.blockExtractors ?? (options.blockExtractors = this.options.blockExtractors);
2430
2595
  if (query instanceof Track) {
2431
- this.debug(`Searching ${query.title}`);
2432
2596
  return new SearchResult(this, {
2433
2597
  playlist: query.playlist || null,
2434
2598
  tracks: [query],
2435
- query: query.toString(),
2599
+ query: query.title,
2436
2600
  extractor: null,
2437
2601
  queryType: query.queryType,
2438
2602
  requestedBy: options.requestedBy
2439
2603
  });
2440
2604
  }
2605
+ if (query instanceof Playlist) {
2606
+ return new SearchResult(this, {
2607
+ playlist: query,
2608
+ tracks: query.tracks,
2609
+ query: query.title,
2610
+ extractor: null,
2611
+ queryType: QueryType.AUTO,
2612
+ requestedBy: options.requestedBy
2613
+ });
2614
+ }
2615
+ if (Array.isArray(query)) {
2616
+ const tracks = query.filter((t) => t instanceof Track);
2617
+ return new SearchResult(this, {
2618
+ playlist: null,
2619
+ tracks,
2620
+ query: "@@#%{{UserLoadedContent}}%#@@",
2621
+ extractor: null,
2622
+ queryType: QueryType.AUTO,
2623
+ requestedBy: options.requestedBy
2624
+ });
2625
+ }
2441
2626
  this.debug(`Searching ${query}`);
2442
2627
  let extractor = null;
2443
2628
  options.searchEngine ?? (options.searchEngine = QueryType.AUTO);
@@ -2545,6 +2730,50 @@ _lagMonitorTimeout = new WeakMap();
2545
2730
  _lagMonitorInterval = new WeakMap();
2546
2731
  Player._singletonKey = kSingleton;
2547
2732
 
2733
+ // src/hooks/common.ts
2734
+ var getPlayer = /* @__PURE__ */ __name(() => {
2735
+ return instances.first() || null;
2736
+ }, "getPlayer");
2737
+ var getQueue = /* @__PURE__ */ __name((node) => {
2738
+ const player = getPlayer();
2739
+ if (!player)
2740
+ return null;
2741
+ return player.nodes.resolve(node) || null;
2742
+ }, "getQueue");
2743
+
2744
+ // src/hooks/useHistory.ts
2745
+ function useHistory(node) {
2746
+ const queue = getQueue(node);
2747
+ if (!queue)
2748
+ return null;
2749
+ return queue.history;
2750
+ }
2751
+ __name(useHistory, "useHistory");
2752
+
2753
+ // src/hooks/usePlayer.ts
2754
+ function usePlayer(node) {
2755
+ const queue = getQueue(node);
2756
+ if (!queue)
2757
+ return null;
2758
+ return queue.node;
2759
+ }
2760
+ __name(usePlayer, "usePlayer");
2761
+
2762
+ // src/hooks/useQueue.ts
2763
+ function useQueue(node) {
2764
+ const queue = getQueue(node);
2765
+ if (!queue)
2766
+ return null;
2767
+ return queue;
2768
+ }
2769
+ __name(useQueue, "useQueue");
2770
+
2771
+ // src/hooks/useMasterPlayer.ts
2772
+ function useMasterPlayer() {
2773
+ return getPlayer();
2774
+ }
2775
+ __name(useMasterPlayer, "useMasterPlayer");
2776
+
2548
2777
  // src/index.ts
2549
2778
  import {
2550
2779
  AudioFilters as AudioFilters2,
@@ -2556,9 +2785,9 @@ import {
2556
2785
  AF_VAPORWAVE_RATE,
2557
2786
  FiltersChain as FiltersChain2
2558
2787
  } from "@discord-player/equalizer";
2559
- var version = "6.0.0-dev.4";
2788
+ var version2 = "6.0.0";
2560
2789
  if (!djsVersion.startsWith("14")) {
2561
- process.emitWarning(`Discord.js v${djsVersion} is incompatible with Discord Player v${version}! Please use >=v14.x of Discord.js`);
2790
+ process.emitWarning(`Discord.js v${djsVersion} is incompatible with Discord Player v${version2}! Please use >=v14.x of Discord.js`);
2562
2791
  }
2563
2792
  export {
2564
2793
  AF_NIGHTCORE_RATE,
@@ -2580,15 +2809,18 @@ export {
2580
2809
  GuildNodeManager,
2581
2810
  GuildQueue,
2582
2811
  GuildQueueAudioFilters,
2812
+ GuildQueueEvent,
2583
2813
  GuildQueueHistory,
2584
2814
  GuildQueuePlayerNode,
2585
2815
  AudioFilters2 as PCMAudioFilters,
2586
2816
  Player,
2587
2817
  PlayerError,
2818
+ PlayerEvent,
2588
2819
  PlayerEventsEmitter,
2589
2820
  Playlist,
2590
2821
  Q_BUTTERWORTH,
2591
2822
  QueryCache,
2823
+ QueryResolver,
2592
2824
  QueryType,
2593
2825
  QueueRepeatMode,
2594
2826
  SearchResult,
@@ -2599,6 +2831,10 @@ export {
2599
2831
  VoiceUtils,
2600
2832
  VolumeTransformer,
2601
2833
  createFFmpegStream,
2602
- version
2834
+ useHistory,
2835
+ useMasterPlayer,
2836
+ usePlayer,
2837
+ useQueue,
2838
+ version2 as version
2603
2839
  };
2604
2840
  //# sourceMappingURL=index.mjs.map