discord-player 6.0.0-dev.5 → 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) {
@@ -540,8 +551,15 @@ var QueryType = {
540
551
  APPLE_MUSIC_SONG: "appleMusicSong",
541
552
  APPLE_MUSIC_ALBUM: "appleMusicAlbum",
542
553
  APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
554
+ APPLE_MUSIC_SEARCH: "appleMusicSearch",
543
555
  FILE: "file"
544
556
  };
557
+ var PlayerEvent = /* @__PURE__ */ ((PlayerEvent2) => {
558
+ PlayerEvent2["debug"] = "debug";
559
+ PlayerEvent2["error"] = "error";
560
+ PlayerEvent2["voiceStateUpdate"] = "voiceStateUpdate";
561
+ return PlayerEvent2;
562
+ })(PlayerEvent || {});
545
563
  var QueueRepeatMode = /* @__PURE__ */ ((QueueRepeatMode2) => {
546
564
  QueueRepeatMode2[QueueRepeatMode2["OFF"] = 0] = "OFF";
547
565
  QueueRepeatMode2[QueueRepeatMode2["TRACK"] = 1] = "TRACK";
@@ -578,10 +596,10 @@ var QueryResolver = class {
578
596
  };
579
597
  }
580
598
  static resolve(query) {
581
- query = query.trim();
582
- 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"))
583
601
  return QueryType.SOUNDCLOUD_TRACK;
584
- if (soundcloud.validateURL(query, "playlist") || query.includes("/sets/"))
602
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "playlist") || query.includes("/sets/"))
585
603
  return QueryType.SOUNDCLOUD_PLAYLIST;
586
604
  if (YouTube.isPlaylist(query))
587
605
  return QueryType.YOUTUBE_PLAYLIST;
@@ -1029,7 +1047,7 @@ function createFFmpegStream(stream, options) {
1029
1047
  args.unshift("-ss", String(options.seek));
1030
1048
  if (Array.isArray(options.encoderArgs))
1031
1049
  args.push(...options.encoderArgs);
1032
- const transcoder = new prism.FFmpeg({ shell: false, args });
1050
+ const transcoder = new (prism.FFmpeg || prism.default.FFmpeg)({ shell: false, args });
1033
1051
  transcoder.on("close", () => transcoder.destroy());
1034
1052
  if (typeof stream !== "string") {
1035
1053
  stream.on("error", () => transcoder.destroy());
@@ -1262,7 +1280,7 @@ var GuildQueueStatistics = class {
1262
1280
  memoryUsage: process.memoryUsage(),
1263
1281
  versions: {
1264
1282
  node: process.version,
1265
- player: "6.0.0-dev.5"
1283
+ player: "6.0.0"
1266
1284
  }
1267
1285
  };
1268
1286
  }
@@ -1270,6 +1288,25 @@ var GuildQueueStatistics = class {
1270
1288
  __name(GuildQueueStatistics, "GuildQueueStatistics");
1271
1289
 
1272
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 || {});
1273
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;
1274
1311
  var GuildQueue = class {
1275
1312
  constructor(player, options) {
@@ -1403,7 +1440,7 @@ var GuildQueue = class {
1403
1440
  return this.tracks.size < 1;
1404
1441
  }
1405
1442
  isPlaying() {
1406
- return this.dispatcher?.audioResource != null;
1443
+ return this.dispatcher?.audioResource != null && !this.dispatcher.audioResource.ended;
1407
1444
  }
1408
1445
  addTrack(track) {
1409
1446
  const toAdd = track instanceof Playlist ? track.tracks : track;
@@ -1505,7 +1542,14 @@ removeListeners_fn = /* @__PURE__ */ __name(function(dispatcher) {
1505
1542
  _performStart = new WeakSet();
1506
1543
  performStart_fn = /* @__PURE__ */ __name(function(resource) {
1507
1544
  const track = resource?.metadata || this.currentTrack;
1508
- 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);
1509
1553
  if (track && !this.isTransitioning())
1510
1554
  this.player.events.emit("playerStart", this, track);
1511
1555
  this.setTransitioning(false);
@@ -1514,25 +1558,38 @@ performStart_fn = /* @__PURE__ */ __name(function(resource) {
1514
1558
  _performFinish = new WeakSet();
1515
1559
  performFinish_fn = /* @__PURE__ */ __name(function(resource) {
1516
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
+ );
1517
1567
  if (track && !this.isTransitioning()) {
1568
+ this.debug("Adding track to history and emitting finish event since transition mode is disabled...");
1518
1569
  this.history.push(track);
1519
1570
  this.node.resetProgress();
1520
1571
  this.player.events.emit("playerFinish", this, track);
1521
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()");
1522
1574
  __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1523
1575
  } else {
1524
1576
  if (this.repeatMode === 1 /* TRACK */) {
1577
+ this.debug("Repeat mode is set to track, repeating last track from the history...");
1525
1578
  this.__current = this.history.tracks.dispatch() || track;
1526
1579
  return this.node.play(this.__current, { queue: false });
1527
1580
  }
1528
- 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...");
1529
1583
  this.tracks.add(this.history.tracks.dispatch() || track);
1584
+ }
1530
1585
  if (!this.tracks.size) {
1531
1586
  if (this.repeatMode === 3 /* AUTOPLAY */) {
1587
+ this.debug("Repeat mode is set to autoplay, initiating autoplay handler...");
1532
1588
  __privateMethod(this, _handleAutoplay, handleAutoplay_fn).call(this, track);
1533
1589
  return;
1534
1590
  }
1535
1591
  } else {
1592
+ this.debug("Initializing next track of the queue...");
1536
1593
  this.__current = this.tracks.dispatch();
1537
1594
  this.node.play(this.__current, {
1538
1595
  queue: false
@@ -1555,9 +1612,9 @@ emitEnd_fn = /* @__PURE__ */ __name(function() {
1555
1612
  }, "#emitEnd");
1556
1613
  _handleAutoplay = new WeakSet();
1557
1614
  handleAutoplay_fn = /* @__PURE__ */ __name(async function(track) {
1558
- 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);
1559
1616
  if (!info)
1560
- 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);
1561
1618
  if (!info) {
1562
1619
  return __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1563
1620
  }
@@ -1731,7 +1788,7 @@ var VoiceReceiverNode = class {
1731
1788
  setImmediate(async () => {
1732
1789
  if (options.mode === "pcm") {
1733
1790
  const pcm = receiveStream.pipe(
1734
- new prism2.opus.Decoder({
1791
+ new (prism2.opus || prism2.default.opus).Decoder({
1735
1792
  channels: 2,
1736
1793
  frameSize: 960,
1737
1794
  rate: 48e3
@@ -1886,10 +1943,19 @@ import {
1886
1943
  entersState,
1887
1944
  StreamType as StreamType3,
1888
1945
  VoiceConnectionStatus,
1889
- VoiceConnectionDisconnectReason
1946
+ VoiceConnectionDisconnectReason,
1947
+ version
1890
1948
  } from "@discordjs/voice";
1891
1949
  import { EventEmitter as EventEmitter2 } from "@discord-player/utils";
1892
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
+ })();
1893
1959
  var StreamDispatcher = class extends EventEmitter2 {
1894
1960
  constructor(connection, channel, queue, connectionTimeout = 2e4) {
1895
1961
  super();
@@ -1901,6 +1967,10 @@ var StreamDispatcher = class extends EventEmitter2 {
1901
1967
  this.voiceConnection = connection;
1902
1968
  this.audioPlayer = createAudioPlayer();
1903
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));
1904
1974
  this.dsp.onUpdate = () => {
1905
1975
  if (!this.dsp)
1906
1976
  return;
@@ -1916,7 +1986,18 @@ var StreamDispatcher = class extends EventEmitter2 {
1916
1986
  this.emit("sampleRate", this.dsp.resampler.targetSampleRate);
1917
1987
  };
1918
1988
  this.dsp.onError = (e) => this.emit("error", e);
1919
- 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
+ }
1920
2001
  if (newState.status === VoiceConnectionStatus.Disconnected) {
1921
2002
  if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
1922
2003
  try {
@@ -1970,10 +2051,6 @@ var StreamDispatcher = class extends EventEmitter2 {
1970
2051
  this.audioResource = null;
1971
2052
  }
1972
2053
  });
1973
- this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
1974
- this.audioPlayer.on("error", (error) => void this.emit("error", error));
1975
- this.voiceConnection.on("debug", (m) => void this.emit("debug", m));
1976
- this.voiceConnection.on("error", (error) => void this.emit("error", error));
1977
2054
  this.voiceConnection.subscribe(this.audioPlayer);
1978
2055
  }
1979
2056
  get paused() {
@@ -2130,7 +2207,8 @@ __name(StreamDispatcher, "StreamDispatcher");
2130
2207
  // src/VoiceInterface/VoiceUtils.ts
2131
2208
  import { Collection as Collection4 } from "@discord-player/utils";
2132
2209
  var VoiceUtils = class {
2133
- constructor() {
2210
+ constructor(player) {
2211
+ this.player = player;
2134
2212
  this.cache = new Collection4();
2135
2213
  }
2136
2214
  async connect(channel, options) {
@@ -2146,7 +2224,8 @@ var VoiceUtils = class {
2146
2224
  guildId: channel.guild.id,
2147
2225
  channelId: channel.id,
2148
2226
  adapterCreator: channel.guild.voiceAdapterCreator,
2149
- selfDeaf: Boolean(options?.deaf)
2227
+ selfDeaf: Boolean(options?.deaf),
2228
+ debug: this.player.events.eventNames().includes("debug")
2150
2229
  });
2151
2230
  return conn;
2152
2231
  }
@@ -2240,7 +2319,8 @@ import { SnowflakeUtil as SnowflakeUtil2, IntentsBitField, ChannelType as Channe
2240
2319
  import { generateDependencyReport } from "@discordjs/voice";
2241
2320
 
2242
2321
  // src/utils/__internal__/_container.ts
2243
- var instances = /* @__PURE__ */ new Map();
2322
+ import { Collection as Collection5 } from "@discord-player/utils";
2323
+ var instances = new Collection5();
2244
2324
 
2245
2325
  // src/utils/__internal__/addPlayer.ts
2246
2326
  function addPlayer(player) {
@@ -2259,7 +2339,7 @@ __name(clearPlayer, "clearPlayer");
2259
2339
 
2260
2340
  // src/utils/__internal__/getPlayers.ts
2261
2341
  function getPlayers() {
2262
- return [...instances.values()];
2342
+ return instances.array();
2263
2343
  }
2264
2344
  __name(getPlayers, "getPlayers");
2265
2345
 
@@ -2277,7 +2357,7 @@ var _Player = class extends PlayerEventsEmitter {
2277
2357
  __privateAdd(this, _lagMonitorInterval, void 0);
2278
2358
  this.id = SnowflakeUtil2.generate().toString();
2279
2359
  this.nodes = new GuildNodeManager(this);
2280
- this.voiceUtils = new VoiceUtils();
2360
+ this.voiceUtils = new VoiceUtils(this);
2281
2361
  this.extractors = new ExtractorExecutionContext(this);
2282
2362
  this.events = new PlayerEventsEmitter(["error", "playerError"]);
2283
2363
  this.client = client;
@@ -2484,7 +2564,8 @@ ${this.scanDeps()}`);
2484
2564
  const vc = this.client.channels.resolve(channel);
2485
2565
  if (!vc?.isVoiceBased())
2486
2566
  throw new Error("Expected a voice channel");
2487
- 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;
2488
2569
  if (result.isEmpty()) {
2489
2570
  throw new Error(`No results found for "${query}" (Extractor: ${result.extractor?.identifier || "N/A"})`);
2490
2571
  }
@@ -2496,7 +2577,7 @@ ${this.scanDeps()}`);
2496
2577
  } else {
2497
2578
  queue.addTrack(result.playlist);
2498
2579
  }
2499
- if (!queue.node.isPlaying())
2580
+ if (!queue.isPlaying())
2500
2581
  await queue.node.play();
2501
2582
  return {
2502
2583
  track: result.tracks[0],
@@ -2506,20 +2587,42 @@ ${this.scanDeps()}`);
2506
2587
  };
2507
2588
  }
2508
2589
  async search(query, options = {}) {
2590
+ if (query instanceof SearchResult)
2591
+ return query;
2509
2592
  if (options.requestedBy != null)
2510
2593
  options.requestedBy = this.client.users.resolve(options.requestedBy);
2511
2594
  options.blockExtractors ?? (options.blockExtractors = this.options.blockExtractors);
2512
2595
  if (query instanceof Track) {
2513
- this.debug(`Searching ${query.title}`);
2514
2596
  return new SearchResult(this, {
2515
2597
  playlist: query.playlist || null,
2516
2598
  tracks: [query],
2517
- query: query.toString(),
2599
+ query: query.title,
2518
2600
  extractor: null,
2519
2601
  queryType: query.queryType,
2520
2602
  requestedBy: options.requestedBy
2521
2603
  });
2522
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
+ }
2523
2626
  this.debug(`Searching ${query}`);
2524
2627
  let extractor = null;
2525
2628
  options.searchEngine ?? (options.searchEngine = QueryType.AUTO);
@@ -2629,7 +2732,7 @@ Player._singletonKey = kSingleton;
2629
2732
 
2630
2733
  // src/hooks/common.ts
2631
2734
  var getPlayer = /* @__PURE__ */ __name(() => {
2632
- return getPlayers()[0];
2735
+ return instances.first() || null;
2633
2736
  }, "getPlayer");
2634
2737
  var getQueue = /* @__PURE__ */ __name((node) => {
2635
2738
  const player = getPlayer();
@@ -2665,6 +2768,12 @@ function useQueue(node) {
2665
2768
  }
2666
2769
  __name(useQueue, "useQueue");
2667
2770
 
2771
+ // src/hooks/useMasterPlayer.ts
2772
+ function useMasterPlayer() {
2773
+ return getPlayer();
2774
+ }
2775
+ __name(useMasterPlayer, "useMasterPlayer");
2776
+
2668
2777
  // src/index.ts
2669
2778
  import {
2670
2779
  AudioFilters as AudioFilters2,
@@ -2676,9 +2785,9 @@ import {
2676
2785
  AF_VAPORWAVE_RATE,
2677
2786
  FiltersChain as FiltersChain2
2678
2787
  } from "@discord-player/equalizer";
2679
- var version = "6.0.0-dev.5";
2788
+ var version2 = "6.0.0";
2680
2789
  if (!djsVersion.startsWith("14")) {
2681
- 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`);
2682
2791
  }
2683
2792
  export {
2684
2793
  AF_NIGHTCORE_RATE,
@@ -2700,11 +2809,13 @@ export {
2700
2809
  GuildNodeManager,
2701
2810
  GuildQueue,
2702
2811
  GuildQueueAudioFilters,
2812
+ GuildQueueEvent,
2703
2813
  GuildQueueHistory,
2704
2814
  GuildQueuePlayerNode,
2705
2815
  AudioFilters2 as PCMAudioFilters,
2706
2816
  Player,
2707
2817
  PlayerError,
2818
+ PlayerEvent,
2708
2819
  PlayerEventsEmitter,
2709
2820
  Playlist,
2710
2821
  Q_BUTTERWORTH,
@@ -2721,8 +2832,9 @@ export {
2721
2832
  VolumeTransformer,
2722
2833
  createFFmpegStream,
2723
2834
  useHistory,
2835
+ useMasterPlayer,
2724
2836
  usePlayer,
2725
2837
  useQueue,
2726
- version
2838
+ version2 as version
2727
2839
  };
2728
2840
  //# sourceMappingURL=index.mjs.map