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.js CHANGED
@@ -68,11 +68,13 @@ __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,
@@ -89,9 +91,10 @@ __export(src_exports, {
89
91
  VolumeTransformer: () => import_equalizer3.VolumeTransformer,
90
92
  createFFmpegStream: () => createFFmpegStream,
91
93
  useHistory: () => useHistory,
94
+ useMasterPlayer: () => useMasterPlayer,
92
95
  usePlayer: () => usePlayer,
93
96
  useQueue: () => useQueue,
94
- version: () => version
97
+ version: () => version2
95
98
  });
96
99
  module.exports = __toCommonJS(src_exports);
97
100
  var import_discord4 = require("discord.js");
@@ -175,6 +178,9 @@ var Util = class {
175
178
  detail
176
179
  });
177
180
  }
181
+ static randomChoice(src) {
182
+ return src[Math.floor(Math.random() * src.length)];
183
+ }
178
184
  };
179
185
  __name(Util, "Util");
180
186
 
@@ -317,7 +323,15 @@ BaseExtractor.identifier = "com.discord-player.extractor";
317
323
 
318
324
  // src/extractors/ExtractorExecutionContext.ts
319
325
  var import_utils2 = require("@discord-player/utils");
320
- 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
+ ];
321
335
  var knownExtractorLib = "@discord-player/extractor";
322
336
  var ExtractorExecutionContext = class {
323
337
  constructor(player) {
@@ -603,8 +617,15 @@ var QueryType = {
603
617
  APPLE_MUSIC_SONG: "appleMusicSong",
604
618
  APPLE_MUSIC_ALBUM: "appleMusicAlbum",
605
619
  APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist",
620
+ APPLE_MUSIC_SEARCH: "appleMusicSearch",
606
621
  FILE: "file"
607
622
  };
623
+ var PlayerEvent = /* @__PURE__ */ ((PlayerEvent2) => {
624
+ PlayerEvent2["debug"] = "debug";
625
+ PlayerEvent2["error"] = "error";
626
+ PlayerEvent2["voiceStateUpdate"] = "voiceStateUpdate";
627
+ return PlayerEvent2;
628
+ })(PlayerEvent || {});
608
629
  var QueueRepeatMode = /* @__PURE__ */ ((QueueRepeatMode2) => {
609
630
  QueueRepeatMode2[QueueRepeatMode2["OFF"] = 0] = "OFF";
610
631
  QueueRepeatMode2[QueueRepeatMode2["TRACK"] = 1] = "TRACK";
@@ -641,10 +662,10 @@ var QueryResolver = class {
641
662
  };
642
663
  }
643
664
  static resolve(query) {
644
- query = query.trim();
645
- 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"))
646
667
  return QueryType.SOUNDCLOUD_TRACK;
647
- if (soundcloud.validateURL(query, "playlist") || query.includes("/sets/"))
668
+ if ((soundcloud.validateURL || soundcloud.default.validateURL)(query, "playlist") || query.includes("/sets/"))
648
669
  return QueryType.SOUNDCLOUD_PLAYLIST;
649
670
  if (import_youtube_sr.YouTube.isPlaylist(query))
650
671
  return QueryType.YOUTUBE_PLAYLIST;
@@ -1092,7 +1113,7 @@ function createFFmpegStream(stream, options) {
1092
1113
  args.unshift("-ss", String(options.seek));
1093
1114
  if (Array.isArray(options.encoderArgs))
1094
1115
  args.push(...options.encoderArgs);
1095
- const transcoder = new prism.FFmpeg({ shell: false, args });
1116
+ const transcoder = new (prism.FFmpeg || prism.default.FFmpeg)({ shell: false, args });
1096
1117
  transcoder.on("close", () => transcoder.destroy());
1097
1118
  if (typeof stream !== "string") {
1098
1119
  stream.on("error", () => transcoder.destroy());
@@ -1325,7 +1346,7 @@ var GuildQueueStatistics = class {
1325
1346
  memoryUsage: process.memoryUsage(),
1326
1347
  versions: {
1327
1348
  node: process.version,
1328
- player: "6.0.0-dev.5"
1349
+ player: "6.0.0"
1329
1350
  }
1330
1351
  };
1331
1352
  }
@@ -1333,6 +1354,25 @@ var GuildQueueStatistics = class {
1333
1354
  __name(GuildQueueStatistics, "GuildQueueStatistics");
1334
1355
 
1335
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 || {});
1336
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;
1337
1377
  var GuildQueue = class {
1338
1378
  constructor(player, options) {
@@ -1466,7 +1506,7 @@ var GuildQueue = class {
1466
1506
  return this.tracks.size < 1;
1467
1507
  }
1468
1508
  isPlaying() {
1469
- return this.dispatcher?.audioResource != null;
1509
+ return this.dispatcher?.audioResource != null && !this.dispatcher.audioResource.ended;
1470
1510
  }
1471
1511
  addTrack(track) {
1472
1512
  const toAdd = track instanceof Playlist ? track.tracks : track;
@@ -1568,7 +1608,14 @@ removeListeners_fn = /* @__PURE__ */ __name(function(dispatcher) {
1568
1608
  _performStart = new WeakSet();
1569
1609
  performStart_fn = /* @__PURE__ */ __name(function(resource) {
1570
1610
  const track = resource?.metadata || this.currentTrack;
1571
- 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);
1572
1619
  if (track && !this.isTransitioning())
1573
1620
  this.player.events.emit("playerStart", this, track);
1574
1621
  this.setTransitioning(false);
@@ -1577,25 +1624,38 @@ performStart_fn = /* @__PURE__ */ __name(function(resource) {
1577
1624
  _performFinish = new WeakSet();
1578
1625
  performFinish_fn = /* @__PURE__ */ __name(function(resource) {
1579
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
+ );
1580
1633
  if (track && !this.isTransitioning()) {
1634
+ this.debug("Adding track to history and emitting finish event since transition mode is disabled...");
1581
1635
  this.history.push(track);
1582
1636
  this.node.resetProgress();
1583
1637
  this.player.events.emit("playerFinish", this, track);
1584
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()");
1585
1640
  __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1586
1641
  } else {
1587
1642
  if (this.repeatMode === 1 /* TRACK */) {
1643
+ this.debug("Repeat mode is set to track, repeating last track from the history...");
1588
1644
  this.__current = this.history.tracks.dispatch() || track;
1589
1645
  return this.node.play(this.__current, { queue: false });
1590
1646
  }
1591
- 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...");
1592
1649
  this.tracks.add(this.history.tracks.dispatch() || track);
1650
+ }
1593
1651
  if (!this.tracks.size) {
1594
1652
  if (this.repeatMode === 3 /* AUTOPLAY */) {
1653
+ this.debug("Repeat mode is set to autoplay, initiating autoplay handler...");
1595
1654
  __privateMethod(this, _handleAutoplay, handleAutoplay_fn).call(this, track);
1596
1655
  return;
1597
1656
  }
1598
1657
  } else {
1658
+ this.debug("Initializing next track of the queue...");
1599
1659
  this.__current = this.tracks.dispatch();
1600
1660
  this.node.play(this.__current, {
1601
1661
  queue: false
@@ -1618,9 +1678,9 @@ emitEnd_fn = /* @__PURE__ */ __name(function() {
1618
1678
  }, "#emitEnd");
1619
1679
  _handleAutoplay = new WeakSet();
1620
1680
  handleAutoplay_fn = /* @__PURE__ */ __name(async function(track) {
1621
- 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);
1622
1682
  if (!info)
1623
- 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);
1624
1684
  if (!info) {
1625
1685
  return __privateMethod(this, _emitEnd, emitEnd_fn).call(this);
1626
1686
  }
@@ -1794,7 +1854,7 @@ var VoiceReceiverNode = class {
1794
1854
  setImmediate(async () => {
1795
1855
  if (options.mode === "pcm") {
1796
1856
  const pcm = receiveStream.pipe(
1797
- new prism2.opus.Decoder({
1857
+ new (prism2.opus || prism2.default.opus).Decoder({
1798
1858
  channels: 2,
1799
1859
  frameSize: 960,
1800
1860
  rate: 48e3
@@ -1945,6 +2005,14 @@ var import_voice5 = require("@discordjs/voice");
1945
2005
  var import_voice4 = require("@discordjs/voice");
1946
2006
  var import_utils6 = require("@discord-player/utils");
1947
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
+ })();
1948
2016
  var StreamDispatcher = class extends import_utils6.EventEmitter {
1949
2017
  constructor(connection, channel, queue, connectionTimeout = 2e4) {
1950
2018
  super();
@@ -1956,6 +2024,10 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1956
2024
  this.voiceConnection = connection;
1957
2025
  this.audioPlayer = (0, import_voice4.createAudioPlayer)();
1958
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));
1959
2031
  this.dsp.onUpdate = () => {
1960
2032
  if (!this.dsp)
1961
2033
  return;
@@ -1971,7 +2043,18 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
1971
2043
  this.emit("sampleRate", this.dsp.resampler.targetSampleRate);
1972
2044
  };
1973
2045
  this.dsp.onError = (e) => this.emit("error", e);
1974
- 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
+ }
1975
2058
  if (newState.status === import_voice4.VoiceConnectionStatus.Disconnected) {
1976
2059
  if (newState.reason === import_voice4.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
1977
2060
  try {
@@ -2025,10 +2108,6 @@ var StreamDispatcher = class extends import_utils6.EventEmitter {
2025
2108
  this.audioResource = null;
2026
2109
  }
2027
2110
  });
2028
- this.audioPlayer.on("debug", (m) => void this.emit("debug", m));
2029
- this.audioPlayer.on("error", (error) => void this.emit("error", error));
2030
- this.voiceConnection.on("debug", (m) => void this.emit("debug", m));
2031
- this.voiceConnection.on("error", (error) => void this.emit("error", error));
2032
2111
  this.voiceConnection.subscribe(this.audioPlayer);
2033
2112
  }
2034
2113
  get paused() {
@@ -2185,7 +2264,8 @@ __name(StreamDispatcher, "StreamDispatcher");
2185
2264
  // src/VoiceInterface/VoiceUtils.ts
2186
2265
  var import_utils7 = require("@discord-player/utils");
2187
2266
  var VoiceUtils = class {
2188
- constructor() {
2267
+ constructor(player) {
2268
+ this.player = player;
2189
2269
  this.cache = new import_utils7.Collection();
2190
2270
  }
2191
2271
  async connect(channel, options) {
@@ -2201,7 +2281,8 @@ var VoiceUtils = class {
2201
2281
  guildId: channel.guild.id,
2202
2282
  channelId: channel.id,
2203
2283
  adapterCreator: channel.guild.voiceAdapterCreator,
2204
- selfDeaf: Boolean(options?.deaf)
2284
+ selfDeaf: Boolean(options?.deaf),
2285
+ debug: this.player.events.eventNames().includes("debug")
2205
2286
  });
2206
2287
  return conn;
2207
2288
  }
@@ -2295,7 +2376,8 @@ var import_discord3 = require("discord.js");
2295
2376
  var import_voice6 = require("@discordjs/voice");
2296
2377
 
2297
2378
  // src/utils/__internal__/_container.ts
2298
- var instances = /* @__PURE__ */ new Map();
2379
+ var import_utils8 = require("@discord-player/utils");
2380
+ var instances = new import_utils8.Collection();
2299
2381
 
2300
2382
  // src/utils/__internal__/addPlayer.ts
2301
2383
  function addPlayer(player) {
@@ -2314,7 +2396,7 @@ __name(clearPlayer, "clearPlayer");
2314
2396
 
2315
2397
  // src/utils/__internal__/getPlayers.ts
2316
2398
  function getPlayers() {
2317
- return [...instances.values()];
2399
+ return instances.array();
2318
2400
  }
2319
2401
  __name(getPlayers, "getPlayers");
2320
2402
 
@@ -2332,7 +2414,7 @@ var _Player = class extends PlayerEventsEmitter {
2332
2414
  __privateAdd(this, _lagMonitorInterval, void 0);
2333
2415
  this.id = import_discord3.SnowflakeUtil.generate().toString();
2334
2416
  this.nodes = new GuildNodeManager(this);
2335
- this.voiceUtils = new VoiceUtils();
2417
+ this.voiceUtils = new VoiceUtils(this);
2336
2418
  this.extractors = new ExtractorExecutionContext(this);
2337
2419
  this.events = new PlayerEventsEmitter(["error", "playerError"]);
2338
2420
  this.client = client;
@@ -2539,7 +2621,8 @@ ${this.scanDeps()}`);
2539
2621
  const vc = this.client.channels.resolve(channel);
2540
2622
  if (!vc?.isVoiceBased())
2541
2623
  throw new Error("Expected a voice channel");
2542
- 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;
2543
2626
  if (result.isEmpty()) {
2544
2627
  throw new Error(`No results found for "${query}" (Extractor: ${result.extractor?.identifier || "N/A"})`);
2545
2628
  }
@@ -2551,7 +2634,7 @@ ${this.scanDeps()}`);
2551
2634
  } else {
2552
2635
  queue.addTrack(result.playlist);
2553
2636
  }
2554
- if (!queue.node.isPlaying())
2637
+ if (!queue.isPlaying())
2555
2638
  await queue.node.play();
2556
2639
  return {
2557
2640
  track: result.tracks[0],
@@ -2561,20 +2644,42 @@ ${this.scanDeps()}`);
2561
2644
  };
2562
2645
  }
2563
2646
  async search(query, options = {}) {
2647
+ if (query instanceof SearchResult)
2648
+ return query;
2564
2649
  if (options.requestedBy != null)
2565
2650
  options.requestedBy = this.client.users.resolve(options.requestedBy);
2566
2651
  options.blockExtractors ?? (options.blockExtractors = this.options.blockExtractors);
2567
2652
  if (query instanceof Track) {
2568
- this.debug(`Searching ${query.title}`);
2569
2653
  return new SearchResult(this, {
2570
2654
  playlist: query.playlist || null,
2571
2655
  tracks: [query],
2572
- query: query.toString(),
2656
+ query: query.title,
2573
2657
  extractor: null,
2574
2658
  queryType: query.queryType,
2575
2659
  requestedBy: options.requestedBy
2576
2660
  });
2577
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
+ }
2578
2683
  this.debug(`Searching ${query}`);
2579
2684
  let extractor = null;
2580
2685
  options.searchEngine ?? (options.searchEngine = QueryType.AUTO);
@@ -2684,7 +2789,7 @@ Player._singletonKey = kSingleton;
2684
2789
 
2685
2790
  // src/hooks/common.ts
2686
2791
  var getPlayer = /* @__PURE__ */ __name(() => {
2687
- return getPlayers()[0];
2792
+ return instances.first() || null;
2688
2793
  }, "getPlayer");
2689
2794
  var getQueue = /* @__PURE__ */ __name((node) => {
2690
2795
  const player = getPlayer();
@@ -2720,11 +2825,17 @@ function useQueue(node) {
2720
2825
  }
2721
2826
  __name(useQueue, "useQueue");
2722
2827
 
2828
+ // src/hooks/useMasterPlayer.ts
2829
+ function useMasterPlayer() {
2830
+ return getPlayer();
2831
+ }
2832
+ __name(useMasterPlayer, "useMasterPlayer");
2833
+
2723
2834
  // src/index.ts
2724
2835
  var import_equalizer3 = require("@discord-player/equalizer");
2725
- var version = "6.0.0-dev.5";
2836
+ var version2 = "6.0.0";
2726
2837
  if (!import_discord4.version.startsWith("14")) {
2727
- 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`);
2728
2839
  }
2729
2840
  // Annotate the CommonJS export names for ESM import in node:
2730
2841
  0 && (module.exports = {
@@ -2747,11 +2858,13 @@ if (!import_discord4.version.startsWith("14")) {
2747
2858
  GuildNodeManager,
2748
2859
  GuildQueue,
2749
2860
  GuildQueueAudioFilters,
2861
+ GuildQueueEvent,
2750
2862
  GuildQueueHistory,
2751
2863
  GuildQueuePlayerNode,
2752
2864
  PCMAudioFilters,
2753
2865
  Player,
2754
2866
  PlayerError,
2867
+ PlayerEvent,
2755
2868
  PlayerEventsEmitter,
2756
2869
  Playlist,
2757
2870
  Q_BUTTERWORTH,
@@ -2768,6 +2881,7 @@ if (!import_discord4.version.startsWith("14")) {
2768
2881
  VolumeTransformer,
2769
2882
  createFFmpegStream,
2770
2883
  useHistory,
2884
+ useMasterPlayer,
2771
2885
  usePlayer,
2772
2886
  useQueue,
2773
2887
  version