distube 4.0.0-dev.5 → 4.0.1

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
@@ -56,7 +56,7 @@ var require_package = __commonJS({
56
56
  "package.json"(exports, module2) {
57
57
  module2.exports = {
58
58
  name: "distube",
59
- version: "4.0.0-dev.5",
59
+ version: "4.0.1",
60
60
  description: "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
61
61
  main: "./dist/index.js",
62
62
  module: "./dist/index.mjs",
@@ -122,46 +122,47 @@ var require_package = __commonJS({
122
122
  dependencies: {
123
123
  "@distube/ytdl-core": "^4.11.3",
124
124
  "@distube/ytpl": "^1.1.1",
125
- "@distube/ytsr": "^1.1.5",
125
+ "@distube/ytsr": "^1.1.8",
126
126
  "prism-media": "https://codeload.github.com/distubejs/prism-media/tar.gz/main#workaround.tar.gz",
127
127
  "tiny-typed-emitter": "^2.1.0",
128
- tslib: "^2.4.0"
128
+ tslib: "^2.4.0",
129
+ undici: "^5.8.0"
129
130
  },
130
131
  devDependencies: {
131
- "@babel/core": "^7.18.0",
132
- "@babel/plugin-proposal-class-properties": "^7.17.12",
133
- "@babel/plugin-proposal-object-rest-spread": "^7.18.0",
134
- "@babel/preset-env": "^7.18.0",
135
- "@babel/preset-typescript": "^7.17.12",
136
- "@commitlint/cli": "^17.0.0",
137
- "@commitlint/config-conventional": "^17.0.0",
138
- "@discordjs/voice": "dev",
132
+ "@babel/core": "^7.18.9",
133
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
134
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
135
+ "@babel/preset-env": "^7.18.9",
136
+ "@babel/preset-typescript": "^7.18.6",
137
+ "@commitlint/cli": "^17.0.3",
138
+ "@commitlint/config-conventional": "^17.0.3",
139
+ "@discordjs/voice": "^0.11.0",
139
140
  "@distube/docgen": "distubejs/docgen",
140
- "@types/jest": "^27.5.1",
141
- "@types/node": "^17.0.35",
142
- "@typescript-eslint/eslint-plugin": "^5.25.0",
143
- "@typescript-eslint/parser": "^5.25.0",
144
- "babel-jest": "^28.1.0",
145
- "discord.js": "dev",
146
- eslint: "^8.15.0",
141
+ "@types/jest": "^28.1.6",
142
+ "@types/node": "^18.0.6",
143
+ "@typescript-eslint/eslint-plugin": "^5.30.7",
144
+ "@typescript-eslint/parser": "^5.30.7",
145
+ "babel-jest": "^28.1.3",
146
+ "discord.js": "^14.0.2",
147
+ eslint: "^8.20.0",
147
148
  "eslint-config-distube": "^1.6.4",
148
149
  "eslint-config-prettier": "^8.5.0",
149
150
  "eslint-plugin-deprecation": "^1.3.2",
150
- "eslint-plugin-jsdoc": "^39.3.0",
151
+ "eslint-plugin-jsdoc": "^39.3.3",
151
152
  husky: "^8.0.1",
152
- jest: "^28.1.0",
153
+ jest: "^28.1.3",
153
154
  "jsdoc-babel": "^0.5.0",
154
155
  "nano-staged": "^0.8.0",
155
- "npm-check-updates": "^13.0.1",
156
+ "npm-check-updates": "^15.3.4",
156
157
  pinst: "^3.0.0",
157
- prettier: "^2.6.2",
158
- tsup: "^5.12.8",
159
- typescript: "^4.6.4"
158
+ prettier: "^2.7.1",
159
+ tsup: "^6.1.3",
160
+ typescript: "^4.7.4"
160
161
  },
161
162
  peerDependencies: {
162
163
  "@discordjs/opus": "*",
163
164
  "@discordjs/voice": "*",
164
- "discord.js": "14||^14.0.0-dev"
165
+ "discord.js": "14"
165
166
  },
166
167
  peerDependenciesMeta: {
167
168
  "@discordjs/opus": {
@@ -180,8 +181,7 @@ var require_package = __commonJS({
180
181
  engines: {
181
182
  node: ">=16.9.0"
182
183
  },
183
- packageManager: "yarn@3.2.0",
184
- stableVersion: "4.0.0-dev"
184
+ packageManager: "yarn@3.2.0"
185
185
  };
186
186
  }
187
187
  });
@@ -191,6 +191,7 @@ var src_exports = {};
191
191
  __export(src_exports, {
192
192
  BaseManager: () => BaseManager,
193
193
  CustomPlugin: () => CustomPlugin,
194
+ DirectLinkPlugin: () => DirectLinkPlugin,
194
195
  DisTube: () => DisTube,
195
196
  DisTubeBase: () => DisTubeBase,
196
197
  DisTubeError: () => DisTubeError,
@@ -201,8 +202,6 @@ __export(src_exports, {
201
202
  ExtractorPlugin: () => ExtractorPlugin,
202
203
  FilterManager: () => FilterManager,
203
204
  GuildIdManager: () => GuildIdManager,
204
- HTTPPlugin: () => HTTPPlugin,
205
- HTTPSPlugin: () => HTTPSPlugin,
206
205
  Options: () => Options,
207
206
  Playlist: () => Playlist,
208
207
  Plugin: () => Plugin,
@@ -210,8 +209,9 @@ __export(src_exports, {
210
209
  Queue: () => Queue,
211
210
  QueueManager: () => QueueManager,
212
211
  RepeatMode: () => RepeatMode,
213
- SearchResult: () => SearchResult,
212
+ SearchResultPlaylist: () => SearchResultPlaylist,
214
213
  SearchResultType: () => SearchResultType,
214
+ SearchResultVideo: () => SearchResultVideo,
215
215
  Song: () => Song,
216
216
  StreamType: () => StreamType,
217
217
  TaskQueue: () => TaskQueue,
@@ -221,10 +221,7 @@ __export(src_exports, {
221
221
  default: () => DisTube,
222
222
  defaultFilters: () => defaultFilters,
223
223
  defaultOptions: () => defaultOptions,
224
- entersState: () => entersState,
225
224
  formatDuration: () => formatDuration,
226
- getClientMember: () => getClientMember,
227
- getResponseHeaders: () => getResponseHeaders,
228
225
  isClientInstance: () => isClientInstance,
229
226
  isGuildInstance: () => isGuildInstance,
230
227
  isMemberInstance: () => isMemberInstance,
@@ -238,9 +235,7 @@ __export(src_exports, {
238
235
  isVoiceChannelEmpty: () => isVoiceChannelEmpty,
239
236
  parseNumber: () => parseNumber,
240
237
  resolveGuildId: () => resolveGuildId,
241
- resolveHttpSong: () => resolveHttpSong,
242
238
  toSecond: () => toSecond,
243
- validateAudioURL: () => validateAudioURL,
244
239
  version: () => version
245
240
  });
246
241
  module.exports = __toCommonJS(src_exports);
@@ -307,7 +302,7 @@ var defaultOptions = {
307
302
  // src/struct/DisTubeError.ts
308
303
  var import_node_util = require("util");
309
304
  var ERROR_MESSAGES = {
310
- INVALID_TYPE: (expected, got, name) => `Expected ${Array.isArray(expected) ? expected.map((e) => typeof e === "number" ? e : `'${e}'`).join(" or ") : `'${expected}'`}${name ? ` for '${name}'` : ""}, but got ${(0, import_node_util.inspect)(got)}`,
305
+ INVALID_TYPE: (expected, got, name) => `Expected ${Array.isArray(expected) ? expected.map((e) => typeof e === "number" ? e : `'${e}'`).join(" or ") : `'${expected}'`}${name ? ` for '${name}'` : ""}, but got ${(0, import_node_util.inspect)(got)} (${typeof got})`,
311
306
  NUMBER_COMPARE: (name, expected, value) => `'${name}' must be ${expected} ${value}`,
312
307
  EMPTY_ARRAY: (name) => `'${name}' is an empty array`,
313
308
  EMPTY_FILTERED_ARRAY: (name, type) => `There is no valid '${type}' in the '${name}' array`,
@@ -413,23 +408,31 @@ var Playlist = class {
413
408
  __publicField(this, "url");
414
409
  __publicField(this, "thumbnail");
415
410
  const { member, properties, metadata } = options;
416
- if (typeof playlist !== "object") {
417
- throw new DisTubeError("INVALID_TYPE", ["Array<Song>", "object"], playlist, "playlist");
411
+ if (typeof playlist !== "object" || !Array.isArray(playlist) && ["source", "songs"].some((key) => !(key in playlist))) {
412
+ throw new DisTubeError("INVALID_TYPE", ["Array<Song>", "PlaylistInfo"], playlist, "playlist");
418
413
  }
419
414
  if (typeof properties !== "undefined" && !isRecord(properties)) {
420
415
  throw new DisTubeError("INVALID_TYPE", "object", properties, "properties");
421
416
  }
422
- const info = playlist;
423
- this.source = (info.source || properties?.source || "youtube").toLowerCase();
424
- this.songs = Array.isArray(info) ? info : info.items || info.songs;
425
- if (!Array.isArray(this.songs) || !this.songs.length) {
426
- throw new DisTubeError("EMPTY_PLAYLIST");
417
+ if (Array.isArray(playlist)) {
418
+ this.source = "youtube";
419
+ if (!playlist.length)
420
+ throw new DisTubeError("EMPTY_PLAYLIST");
421
+ this.songs = playlist;
422
+ this.name = this.songs[0].name ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.` : `${this.songs.length} songs playlist`;
423
+ this.thumbnail = this.songs[0].thumbnail;
424
+ this.member = member || void 0;
425
+ } else {
426
+ this.source = (playlist.source || "youtube").toLowerCase();
427
+ if (!Array.isArray(playlist.songs) || !playlist.songs.length)
428
+ throw new DisTubeError("EMPTY_PLAYLIST");
429
+ this.songs = playlist.songs;
430
+ this.name = playlist.name || playlist.title || (this.songs[0].name ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.` : `${this.songs.length} songs playlist`);
431
+ this.url = playlist.url || playlist.webpage_url;
432
+ this.thumbnail = playlist.thumbnail || this.songs[0].thumbnail;
433
+ this.member = member || playlist.member || void 0;
427
434
  }
428
435
  this.songs.map((s) => s.constructor.name === "Song" && (s.playlist = this));
429
- this.member = member || info.member || void 0;
430
- this.name = info.name || info.title || (this.songs[0].name ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.` : `${this.songs.length} songs playlist`);
431
- this.url = info.url || info.webpage_url;
432
- this.thumbnail = info.thumbnail?.url || info.thumbnail || this.songs[0].thumbnail;
433
436
  if (properties)
434
437
  for (const [key, value] of Object.entries(properties))
435
438
  this[key] = value;
@@ -466,41 +469,64 @@ _metadata = new WeakMap();
466
469
  _member = new WeakMap();
467
470
 
468
471
  // src/struct/SearchResult.ts
469
- var SearchResult = class {
472
+ var ISearchResult = class {
470
473
  constructor(info) {
471
474
  __publicField(this, "source");
472
- __publicField(this, "type");
473
475
  __publicField(this, "id");
474
476
  __publicField(this, "name");
475
477
  __publicField(this, "url");
476
- __publicField(this, "views");
477
- __publicField(this, "isLive");
478
- __publicField(this, "duration");
479
- __publicField(this, "formattedDuration");
480
- __publicField(this, "thumbnail");
481
478
  __publicField(this, "uploader");
482
479
  this.source = "youtube";
483
- this.type = info.type === "video" ? "video" /* VIDEO */ : "playlist" /* PLAYLIST */;
484
480
  this.id = info.id;
485
481
  this.name = info.name;
486
482
  this.url = info.url;
487
- if (this.type === "video" /* VIDEO */) {
488
- info = info;
489
- this.views = info.views;
490
- this.isLive = info.isLive;
491
- this.duration = this.isLive ? 0 : toSecond(info.duration);
492
- this.formattedDuration = this.isLive ? "Live" : formatDuration(this.duration);
493
- this.thumbnail = info.thumbnail;
494
- } else if (this.type !== "playlist") {
495
- throw new DisTubeError("INVALID_TYPE", ["video", "playlist"], this.type, "SearchResult.type");
496
- }
497
483
  this.uploader = {
498
- name: (info.author || info.owner)?.name,
499
- url: (info.author || info.owner)?.url
484
+ name: void 0,
485
+ url: void 0
486
+ };
487
+ }
488
+ };
489
+ __name(ISearchResult, "ISearchResult");
490
+ var SearchResultVideo = class extends ISearchResult {
491
+ constructor(info) {
492
+ super(info);
493
+ __publicField(this, "type");
494
+ __publicField(this, "views");
495
+ __publicField(this, "isLive");
496
+ __publicField(this, "duration");
497
+ __publicField(this, "formattedDuration");
498
+ __publicField(this, "thumbnail");
499
+ if (info.type !== "video")
500
+ throw new DisTubeError("INVALID_TYPE", "video", info.type, "type");
501
+ this.type = "video" /* VIDEO */;
502
+ this.views = info.views;
503
+ this.isLive = info.isLive;
504
+ this.duration = this.isLive ? 0 : toSecond(info.duration);
505
+ this.formattedDuration = this.isLive ? "Live" : formatDuration(this.duration);
506
+ this.thumbnail = info.thumbnail;
507
+ this.uploader = {
508
+ name: info.author?.name,
509
+ url: info.author?.url
510
+ };
511
+ }
512
+ };
513
+ __name(SearchResultVideo, "SearchResultVideo");
514
+ var SearchResultPlaylist = class extends ISearchResult {
515
+ constructor(info) {
516
+ super(info);
517
+ __publicField(this, "type");
518
+ __publicField(this, "length");
519
+ if (info.type !== "playlist")
520
+ throw new DisTubeError("INVALID_TYPE", "playlist", info.type, "type");
521
+ this.type = "playlist" /* PLAYLIST */;
522
+ this.length = info.length;
523
+ this.uploader = {
524
+ name: info.owner?.name,
525
+ url: info.owner?.url
500
526
  };
501
527
  }
502
528
  };
503
- __name(SearchResult, "SearchResult");
529
+ __name(SearchResultPlaylist, "SearchResultPlaylist");
504
530
 
505
531
  // src/struct/Song.ts
506
532
  var _metadata2, _member2, _playlist;
@@ -640,114 +666,6 @@ _metadata2 = new WeakMap();
640
666
  _member2 = new WeakMap();
641
667
  _playlist = new WeakMap();
642
668
 
643
- // src/core/DisTubeOptions.ts
644
- var _validateOptions, validateOptions_fn;
645
- var Options = class {
646
- constructor(options) {
647
- __privateAdd(this, _validateOptions);
648
- __publicField(this, "plugins");
649
- __publicField(this, "emitNewSongOnly");
650
- __publicField(this, "leaveOnFinish");
651
- __publicField(this, "leaveOnStop");
652
- __publicField(this, "leaveOnEmpty");
653
- __publicField(this, "emptyCooldown");
654
- __publicField(this, "savePreviousSongs");
655
- __publicField(this, "searchSongs");
656
- __publicField(this, "searchCooldown");
657
- __publicField(this, "youtubeCookie");
658
- __publicField(this, "youtubeIdentityToken");
659
- __publicField(this, "customFilters");
660
- __publicField(this, "ytdlOptions");
661
- __publicField(this, "nsfw");
662
- __publicField(this, "emitAddSongWhenCreatingQueue");
663
- __publicField(this, "emitAddListWhenCreatingQueue");
664
- __publicField(this, "joinNewVoiceChannel");
665
- __publicField(this, "streamType");
666
- if (typeof options !== "object" || Array.isArray(options)) {
667
- throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
668
- }
669
- const opts = { ...defaultOptions, ...options };
670
- this.plugins = opts.plugins;
671
- this.emitNewSongOnly = opts.emitNewSongOnly;
672
- this.leaveOnEmpty = opts.leaveOnEmpty;
673
- this.leaveOnFinish = opts.leaveOnFinish;
674
- this.leaveOnStop = opts.leaveOnStop;
675
- this.savePreviousSongs = opts.savePreviousSongs;
676
- this.searchSongs = opts.searchSongs;
677
- this.youtubeCookie = opts.youtubeCookie;
678
- this.youtubeIdentityToken = opts.youtubeIdentityToken;
679
- this.customFilters = opts.customFilters;
680
- this.ytdlOptions = opts.ytdlOptions;
681
- this.searchCooldown = opts.searchCooldown;
682
- this.emptyCooldown = opts.emptyCooldown;
683
- this.nsfw = opts.nsfw;
684
- this.emitAddSongWhenCreatingQueue = opts.emitAddSongWhenCreatingQueue;
685
- this.emitAddListWhenCreatingQueue = opts.emitAddListWhenCreatingQueue;
686
- this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
687
- this.streamType = opts.streamType;
688
- checkInvalidKey(opts, this, "DisTubeOptions");
689
- __privateMethod(this, _validateOptions, validateOptions_fn).call(this);
690
- }
691
- };
692
- __name(Options, "Options");
693
- _validateOptions = new WeakSet();
694
- validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
695
- if (typeof options.emitNewSongOnly !== "boolean") {
696
- throw new DisTubeError("INVALID_TYPE", "boolean", options.emitNewSongOnly, "DisTubeOptions.emitNewSongOnly");
697
- }
698
- if (typeof options.leaveOnEmpty !== "boolean") {
699
- throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnEmpty, "DisTubeOptions.leaveOnEmpty");
700
- }
701
- if (typeof options.leaveOnFinish !== "boolean") {
702
- throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnFinish, "DisTubeOptions.leaveOnFinish");
703
- }
704
- if (typeof options.leaveOnStop !== "boolean") {
705
- throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnStop, "DisTubeOptions.leaveOnStop");
706
- }
707
- if (typeof options.savePreviousSongs !== "boolean") {
708
- throw new DisTubeError("INVALID_TYPE", "boolean", options.savePreviousSongs, "DisTubeOptions.savePreviousSongs");
709
- }
710
- if (typeof options.joinNewVoiceChannel !== "boolean") {
711
- throw new DisTubeError("INVALID_TYPE", "boolean", options.joinNewVoiceChannel, "DisTubeOptions.joinNewVoiceChannel");
712
- }
713
- if (typeof options.youtubeCookie !== "undefined" && typeof options.youtubeCookie !== "string") {
714
- throw new DisTubeError("INVALID_TYPE", "string", options.youtubeCookie, "DisTubeOptions.youtubeCookie");
715
- }
716
- if (typeof options.youtubeIdentityToken !== "undefined" && typeof options.youtubeIdentityToken !== "string") {
717
- throw new DisTubeError("INVALID_TYPE", "string", options.youtubeIdentityToken, "DisTubeOptions.youtubeIdentityToken");
718
- }
719
- if (typeof options.customFilters !== "undefined" && typeof options.customFilters !== "object" || Array.isArray(options.customFilters)) {
720
- throw new DisTubeError("INVALID_TYPE", "object", options.customFilters, "DisTubeOptions.customFilters");
721
- }
722
- if (typeof options.ytdlOptions !== "object" || Array.isArray(options.ytdlOptions)) {
723
- throw new DisTubeError("INVALID_TYPE", "object", options.ytdlOptions, "DisTubeOptions.ytdlOptions");
724
- }
725
- if (typeof options.searchCooldown !== "number" || isNaN(options.searchCooldown)) {
726
- throw new DisTubeError("INVALID_TYPE", "number", options.searchCooldown, "DisTubeOptions.searchCooldown");
727
- }
728
- if (typeof options.emptyCooldown !== "number" || isNaN(options.emptyCooldown)) {
729
- throw new DisTubeError("INVALID_TYPE", "number", options.emptyCooldown, "DisTubeOptions.emptyCooldown");
730
- }
731
- if (typeof options.searchSongs !== "number" || isNaN(options.searchSongs)) {
732
- throw new DisTubeError("INVALID_TYPE", "number", options.searchSongs, "DisTubeOptions.searchSongs");
733
- }
734
- if (!Array.isArray(options.plugins)) {
735
- throw new DisTubeError("INVALID_TYPE", "Array<Plugin>", options.plugins, "DisTubeOptions.plugins");
736
- }
737
- if (typeof options.nsfw !== "boolean") {
738
- throw new DisTubeError("INVALID_TYPE", "boolean", options.nsfw, "DisTubeOptions.nsfw");
739
- }
740
- if (typeof options.emitAddSongWhenCreatingQueue !== "boolean") {
741
- throw new DisTubeError("INVALID_TYPE", "boolean", options.emitAddSongWhenCreatingQueue, "DisTubeOptions.emitAddSongWhenCreatingQueue");
742
- }
743
- if (typeof options.emitAddListWhenCreatingQueue !== "boolean") {
744
- throw new DisTubeError("INVALID_TYPE", "boolean", options.emitAddListWhenCreatingQueue, "DisTubeOptions.emitAddListWhenCreatingQueue");
745
- }
746
- if (typeof options.streamType !== "number" || isNaN(options.streamType) || !StreamType[options.streamType]) {
747
- throw new DisTubeError("INVALID_TYPE", "StreamType", options.streamType, "DisTubeOptions.streamType");
748
- }
749
- }, "#validateOptions");
750
-
751
669
  // src/core/DisTubeBase.ts
752
670
  var DisTubeBase = class {
753
671
  constructor(distube) {
@@ -778,77 +696,194 @@ var DisTubeBase = class {
778
696
  };
779
697
  __name(DisTubeBase, "DisTubeBase");
780
698
 
781
- // src/core/DisTubeStream.ts
782
- var import_prism_media = require("prism-media");
699
+ // src/core/DisTubeVoice.ts
700
+ var import_tiny_typed_emitter = require("tiny-typed-emitter");
783
701
  var import_voice = require("@discordjs/voice");
784
- var chooseBestVideoFormat = /* @__PURE__ */ __name((formats, isLive = false) => {
785
- let filter = /* @__PURE__ */ __name((format) => format.hasAudio, "filter");
786
- if (isLive)
787
- filter = /* @__PURE__ */ __name((format) => format.hasAudio && format.isHLS, "filter");
788
- formats = formats.filter(filter).sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate));
789
- return formats.find((format) => !format.hasVideo) || formats.sort((a, b) => Number(a.bitrate) - Number(b.bitrate))[0];
790
- }, "chooseBestVideoFormat");
791
- var DisTubeStream = class {
792
- constructor(url, options) {
793
- __publicField(this, "type");
794
- __publicField(this, "stream");
795
- __publicField(this, "url");
796
- this.url = url;
797
- this.type = !options.type ? import_voice.StreamType.Opus : import_voice.StreamType.Raw;
798
- const args = [
799
- "-reconnect",
800
- "1",
801
- "-reconnect_streamed",
802
- "1",
803
- "-reconnect_delay_max",
804
- "5",
805
- "-i",
806
- url,
807
- "-analyzeduration",
808
- "0",
809
- "-loglevel",
810
- "0",
811
- "-ar",
812
- "48000",
813
- "-ac",
814
- "2",
815
- "-f"
816
- ];
817
- if (!options.type) {
818
- args.push("opus", "-acodec", "libopus");
819
- } else {
820
- args.push("s16le");
821
- }
822
- if (typeof options.seek === "number" && options.seek > 0) {
823
- args.unshift("-ss", options.seek.toString());
824
- }
825
- if (Array.isArray(options.ffmpegArgs)) {
826
- args.push(...options.ffmpegArgs);
827
- }
828
- this.stream = new import_prism_media.FFmpeg({ args, shell: false });
702
+ var _channel, _volume, _br, br_fn, _join, join_fn;
703
+ var DisTubeVoice = class extends import_tiny_typed_emitter.TypedEmitter {
704
+ constructor(voiceManager, channel) {
705
+ super();
706
+ __privateAdd(this, _br);
707
+ __privateAdd(this, _join);
708
+ __publicField(this, "id");
709
+ __publicField(this, "voices");
710
+ __publicField(this, "audioPlayer");
711
+ __publicField(this, "connection");
712
+ __publicField(this, "audioResource");
713
+ __publicField(this, "emittedError");
714
+ __publicField(this, "isDisconnected", false);
715
+ __privateAdd(this, _channel, void 0);
716
+ __privateAdd(this, _volume, 100);
717
+ this.voices = voiceManager;
718
+ this.id = channel.guildId;
719
+ this.channel = channel;
720
+ this.voices.add(this.id, this);
721
+ this.audioPlayer = (0, import_voice.createAudioPlayer)().on(import_voice.AudioPlayerStatus.Idle, (oldState) => {
722
+ if (oldState.status !== import_voice.AudioPlayerStatus.Idle) {
723
+ delete this.audioResource;
724
+ this.emit("finish");
725
+ }
726
+ }).on(import_voice.AudioPlayerStatus.Playing, () => __privateMethod(this, _br, br_fn).call(this)).on("error", (error) => {
727
+ if (this.emittedError)
728
+ return;
729
+ this.emittedError = true;
730
+ this.emit("error", error);
731
+ });
732
+ this.connection.on(import_voice.VoiceConnectionStatus.Disconnected, (_, newState) => {
733
+ if (newState.reason === import_voice.VoiceConnectionDisconnectReason.Manual) {
734
+ this.leave();
735
+ } else if (newState.reason === import_voice.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
736
+ (0, import_voice.entersState)(this.connection, import_voice.VoiceConnectionStatus.Connecting, 5e3).catch(() => {
737
+ if (![import_voice.VoiceConnectionStatus.Ready, import_voice.VoiceConnectionStatus.Connecting].includes(this.connection.state.status)) {
738
+ this.leave();
739
+ }
740
+ });
741
+ } else if (this.connection.rejoinAttempts < 5) {
742
+ setTimeout(() => {
743
+ this.connection.rejoin();
744
+ }, (this.connection.rejoinAttempts + 1) * 5e3).unref();
745
+ } else if (this.connection.state.status !== import_voice.VoiceConnectionStatus.Destroyed) {
746
+ this.leave(new DisTubeError("VOICE_RECONNECT_FAILED"));
747
+ }
748
+ }).on(import_voice.VoiceConnectionStatus.Destroyed, () => {
749
+ this.leave();
750
+ }).on("error", () => void 0);
751
+ this.connection.subscribe(this.audioPlayer);
829
752
  }
830
- static YouTube(formats, options = {}) {
831
- if (!formats || !formats.length)
832
- throw new DisTubeError("UNAVAILABLE_VIDEO");
833
- if (!options || typeof options !== "object" || Array.isArray(options)) {
834
- throw new DisTubeError("INVALID_TYPE", "object", options, "options");
835
- }
836
- const bestFormat = chooseBestVideoFormat(formats, options.isLive);
837
- if (!bestFormat)
838
- throw new DisTubeError("UNPLAYABLE_FORMATS");
839
- return new DisTubeStream(bestFormat.url, options);
753
+ get channel() {
754
+ return __privateGet(this, _channel);
840
755
  }
841
- static DirectLink(url, options = {}) {
842
- if (!options || typeof options !== "object" || Array.isArray(options)) {
843
- throw new DisTubeError("INVALID_TYPE", "object", options, "options");
756
+ set channel(channel) {
757
+ if (!isSupportedVoiceChannel(channel)) {
758
+ throw new DisTubeError("INVALID_TYPE", "BaseGuildVoiceChannel", channel, "DisTubeVoice#channel");
844
759
  }
845
- if (typeof url !== "string" || !isURL(url)) {
846
- throw new DisTubeError("INVALID_TYPE", "an URL", url);
760
+ if (channel.guildId !== this.id)
761
+ throw new DisTubeError("VOICE_DIFFERENT_GUILD");
762
+ if (channel.client.user?.id !== this.voices.client.user?.id)
763
+ throw new DisTubeError("VOICE_DIFFERENT_CLIENT");
764
+ if (channel.id === __privateGet(this, _channel)?.id)
765
+ return;
766
+ if (!channel.joinable) {
767
+ if (channel.full)
768
+ throw new DisTubeError("VOICE_FULL");
769
+ else
770
+ throw new DisTubeError("VOICE_MISSING_PERMS");
847
771
  }
848
- return new DisTubeStream(url, options);
849
- }
850
- };
851
- __name(DisTubeStream, "DisTubeStream");
772
+ this.connection = __privateMethod(this, _join, join_fn).call(this, channel);
773
+ __privateSet(this, _channel, channel);
774
+ __privateMethod(this, _br, br_fn).call(this);
775
+ }
776
+ async join(channel) {
777
+ const TIMEOUT = 3e4;
778
+ if (channel)
779
+ this.channel = channel;
780
+ try {
781
+ await (0, import_voice.entersState)(this.connection, import_voice.VoiceConnectionStatus.Ready, TIMEOUT);
782
+ } catch {
783
+ if (this.connection.state.status === import_voice.VoiceConnectionStatus.Ready)
784
+ return this;
785
+ if (this.connection.state.status !== import_voice.VoiceConnectionStatus.Destroyed)
786
+ this.connection.destroy();
787
+ this.voices.remove(this.id);
788
+ throw new DisTubeError("VOICE_CONNECT_FAILED", TIMEOUT / 1e3);
789
+ }
790
+ return this;
791
+ }
792
+ leave(error) {
793
+ this.stop(true);
794
+ if (!this.isDisconnected) {
795
+ this.emit("disconnect", error);
796
+ this.isDisconnected = true;
797
+ }
798
+ if (this.connection.state.status !== import_voice.VoiceConnectionStatus.Destroyed)
799
+ this.connection.destroy();
800
+ this.voices.remove(this.id);
801
+ }
802
+ stop(force = false) {
803
+ this.audioPlayer.stop(force);
804
+ }
805
+ play(stream) {
806
+ this.emittedError = false;
807
+ stream.stream.on("error", (error) => {
808
+ if (this.emittedError || error.code === "ERR_STREAM_PREMATURE_CLOSE")
809
+ return;
810
+ this.emittedError = true;
811
+ this.emit("error", error);
812
+ });
813
+ this.audioResource = (0, import_voice.createAudioResource)(stream.stream, {
814
+ inputType: stream.type,
815
+ inlineVolume: true
816
+ });
817
+ this.volume = __privateGet(this, _volume);
818
+ this.audioPlayer.play(this.audioResource);
819
+ }
820
+ set volume(volume) {
821
+ if (typeof volume !== "number" || isNaN(volume)) {
822
+ throw new DisTubeError("INVALID_TYPE", "number", volume, "volume");
823
+ }
824
+ if (volume < 0) {
825
+ throw new DisTubeError("NUMBER_COMPARE", "Volume", "bigger or equal to", 0);
826
+ }
827
+ __privateSet(this, _volume, volume);
828
+ this.audioResource?.volume?.setVolume(Math.pow(__privateGet(this, _volume) / 100, 0.5 / Math.log10(2)));
829
+ }
830
+ get volume() {
831
+ return __privateGet(this, _volume);
832
+ }
833
+ get playbackDuration() {
834
+ return (this.audioResource?.playbackDuration ?? 0) / 1e3;
835
+ }
836
+ pause() {
837
+ this.audioPlayer.pause();
838
+ }
839
+ unpause() {
840
+ this.audioPlayer.unpause();
841
+ }
842
+ get selfDeaf() {
843
+ return this.connection.joinConfig.selfDeaf;
844
+ }
845
+ get selfMute() {
846
+ return this.connection.joinConfig.selfMute;
847
+ }
848
+ setSelfDeaf(selfDeaf) {
849
+ if (typeof selfDeaf !== "boolean") {
850
+ throw new DisTubeError("INVALID_TYPE", "boolean", selfDeaf, "selfDeaf");
851
+ }
852
+ return this.connection.rejoin({
853
+ ...this.connection.joinConfig,
854
+ selfDeaf
855
+ });
856
+ }
857
+ setSelfMute(selfMute) {
858
+ if (typeof selfMute !== "boolean") {
859
+ throw new DisTubeError("INVALID_TYPE", "boolean", selfMute, "selfMute");
860
+ }
861
+ return this.connection.rejoin({
862
+ ...this.connection.joinConfig,
863
+ selfMute
864
+ });
865
+ }
866
+ get voiceState() {
867
+ return this.channel?.guild?.members?.me?.voice;
868
+ }
869
+ };
870
+ __name(DisTubeVoice, "DisTubeVoice");
871
+ _channel = new WeakMap();
872
+ _volume = new WeakMap();
873
+ _br = new WeakSet();
874
+ br_fn = /* @__PURE__ */ __name(function() {
875
+ if (this.audioResource?.encoder?.encoder)
876
+ this.audioResource.encoder.setBitrate(this.channel.bitrate);
877
+ }, "#br");
878
+ _join = new WeakSet();
879
+ join_fn = /* @__PURE__ */ __name(function(channel) {
880
+ return (0, import_voice.joinVoiceChannel)({
881
+ channelId: channel.id,
882
+ guildId: this.id,
883
+ adapterCreator: channel.guild.voiceAdapterCreator,
884
+ group: channel.client.user?.id
885
+ });
886
+ }, "#join");
852
887
 
853
888
  // src/core/manager/BaseManager.ts
854
889
  var import_discord = require("discord.js");
@@ -884,6 +919,123 @@ var GuildIdManager = class extends BaseManager {
884
919
  };
885
920
  __name(GuildIdManager, "GuildIdManager");
886
921
 
922
+ // src/core/manager/DisTubeVoiceManager.ts
923
+ var import_voice2 = require("@discordjs/voice");
924
+ var DisTubeVoiceManager = class extends GuildIdManager {
925
+ create(channel) {
926
+ const existing = this.get(channel.guildId);
927
+ if (existing) {
928
+ existing.channel = channel;
929
+ return existing;
930
+ }
931
+ return new DisTubeVoice(this, channel);
932
+ }
933
+ join(channel) {
934
+ const existing = this.get(channel.guildId);
935
+ if (existing)
936
+ return existing.join(channel);
937
+ return this.create(channel).join();
938
+ }
939
+ leave(guild) {
940
+ const voice = this.get(guild);
941
+ if (voice) {
942
+ voice.leave();
943
+ } else {
944
+ const connection = (0, import_voice2.getVoiceConnection)(resolveGuildId(guild), this.client.user?.id) ?? (0, import_voice2.getVoiceConnection)(resolveGuildId(guild));
945
+ if (connection && connection.state.status !== import_voice2.VoiceConnectionStatus.Destroyed) {
946
+ connection.destroy();
947
+ }
948
+ }
949
+ }
950
+ };
951
+ __name(DisTubeVoiceManager, "DisTubeVoiceManager");
952
+
953
+ // src/core/manager/FilterManager.ts
954
+ var _validate, validate_fn, _resolveName, resolveName_fn, _resolveValue, resolveValue_fn, _apply, apply_fn;
955
+ var FilterManager = class extends BaseManager {
956
+ constructor(queue) {
957
+ super(queue.distube);
958
+ __privateAdd(this, _validate);
959
+ __privateAdd(this, _resolveName);
960
+ __privateAdd(this, _resolveValue);
961
+ __privateAdd(this, _apply);
962
+ __publicField(this, "queue");
963
+ this.queue = queue;
964
+ }
965
+ add(filterOrFilters, override = false) {
966
+ if (Array.isArray(filterOrFilters)) {
967
+ const resolvedFilters = filterOrFilters.map((f) => __privateMethod(this, _validate, validate_fn).call(this, f));
968
+ const newFilters = resolvedFilters.reduceRight((unique, o) => {
969
+ if (!unique.some((obj) => obj === o && obj.name === o) && !unique.some((obj) => obj !== o.name && obj.name !== o.name)) {
970
+ if (!this.has(o))
971
+ unique.push(o);
972
+ if (this.has(o) && override) {
973
+ this.remove(o);
974
+ unique.push(o);
975
+ }
976
+ }
977
+ return unique;
978
+ }, []).reverse();
979
+ return this.set([...this.collection.values(), ...newFilters]);
980
+ }
981
+ return this.set([...this.collection.values(), filterOrFilters]);
982
+ }
983
+ clear() {
984
+ return this.set([]);
985
+ }
986
+ set(filters) {
987
+ this.collection.clear();
988
+ for (const filter of filters) {
989
+ const resolved = __privateMethod(this, _validate, validate_fn).call(this, filter);
990
+ this.collection.set(__privateMethod(this, _resolveName, resolveName_fn).call(this, resolved), resolved);
991
+ }
992
+ __privateMethod(this, _apply, apply_fn).call(this);
993
+ return this;
994
+ }
995
+ remove(filterOrFilters) {
996
+ const remove = /* @__PURE__ */ __name((f) => this.collection.delete(__privateMethod(this, _resolveName, resolveName_fn).call(this, __privateMethod(this, _validate, validate_fn).call(this, f))), "remove");
997
+ if (Array.isArray(filterOrFilters))
998
+ filterOrFilters.map(remove);
999
+ else
1000
+ remove(filterOrFilters);
1001
+ __privateMethod(this, _apply, apply_fn).call(this);
1002
+ return this;
1003
+ }
1004
+ has(filter) {
1005
+ return this.collection.has(__privateMethod(this, _resolveName, resolveName_fn).call(this, filter));
1006
+ }
1007
+ get names() {
1008
+ return this.collection.map((f) => __privateMethod(this, _resolveName, resolveName_fn).call(this, f));
1009
+ }
1010
+ get values() {
1011
+ return this.collection.map((f) => __privateMethod(this, _resolveValue, resolveValue_fn).call(this, f));
1012
+ }
1013
+ toString() {
1014
+ return this.names.toString();
1015
+ }
1016
+ };
1017
+ __name(FilterManager, "FilterManager");
1018
+ _validate = new WeakSet();
1019
+ validate_fn = /* @__PURE__ */ __name(function(filter) {
1020
+ if (typeof filter === "string" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter) || typeof filter === "object" && typeof filter.name === "string" && typeof filter.value === "string") {
1021
+ return filter;
1022
+ }
1023
+ throw new DisTubeError("INVALID_TYPE", "FilterResolvable", filter, "filter");
1024
+ }, "#validate");
1025
+ _resolveName = new WeakSet();
1026
+ resolveName_fn = /* @__PURE__ */ __name(function(filter) {
1027
+ return typeof filter === "string" ? filter : filter.name;
1028
+ }, "#resolveName");
1029
+ _resolveValue = new WeakSet();
1030
+ resolveValue_fn = /* @__PURE__ */ __name(function(filter) {
1031
+ return typeof filter === "string" ? this.distube.filters[filter] : filter.value;
1032
+ }, "#resolveValue");
1033
+ _apply = new WeakSet();
1034
+ apply_fn = /* @__PURE__ */ __name(function() {
1035
+ this.queue.beginTime = this.queue.currentTime;
1036
+ this.queues.playSong(this.queue);
1037
+ }, "#apply");
1038
+
887
1039
  // src/core/manager/QueueManager.ts
888
1040
  var _voiceEventHandler, voiceEventHandler_fn, _handleSongFinish, handleSongFinish_fn, _handlePlayingError, handlePlayingError_fn, _emitPlaySong, emitPlaySong_fn;
889
1041
  var QueueManager = class extends GuildIdManager {
@@ -1011,356 +1163,52 @@ handleSongFinish_fn = /* @__PURE__ */ __name(async function(queue) {
1011
1163
  const emitPlaySong = __privateMethod(this, _emitPlaySong, emitPlaySong_fn).call(this, queue);
1012
1164
  if (!queue._prev && (queue.repeatMode !== 1 /* SONG */ || queue._next)) {
1013
1165
  const prev = queue.songs.shift();
1014
- delete prev.formats;
1015
- delete prev.streamURL;
1016
- if (this.options.savePreviousSongs)
1017
- queue.previousSongs.push(prev);
1018
- else
1019
- queue.previousSongs.push({ id: prev.id });
1020
- }
1021
- queue._next = queue._prev = false;
1022
- queue.beginTime = 0;
1023
- const err = await this.playSong(queue);
1024
- if (!err && emitPlaySong)
1025
- this.emit("playSong", queue, queue.songs[0]);
1026
- } finally {
1027
- queue._taskQueue.resolve();
1028
- }
1029
- }, "#handleSongFinish");
1030
- _handlePlayingError = new WeakSet();
1031
- handlePlayingError_fn = /* @__PURE__ */ __name(function(queue, error) {
1032
- const song = queue.songs.shift();
1033
- try {
1034
- error.name = "PlayingError";
1035
- error.message = `${error.message}
1036
- Id: ${song.id}
1037
- Name: ${song.name}`;
1038
- } catch {
1039
- }
1040
- this.emitError(error, queue.textChannel);
1041
- if (queue.songs.length > 0) {
1042
- this.playSong(queue).then((e) => {
1043
- if (!e)
1044
- this.emit("playSong", queue, queue.songs[0]);
1045
- });
1046
- } else {
1047
- queue.stop();
1048
- }
1049
- }, "#handlePlayingError");
1050
- _emitPlaySong = new WeakSet();
1051
- emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
1052
- return !this.options.emitNewSongOnly || queue.repeatMode === 1 /* SONG */ && queue._next || queue.repeatMode !== 1 /* SONG */ && queue.songs[0]?.id !== queue.songs[1]?.id;
1053
- }, "#emitPlaySong");
1054
-
1055
- // src/core/manager/FilterManager.ts
1056
- var _validate, validate_fn, _resolveName, resolveName_fn, _resolveValue, resolveValue_fn, _apply, apply_fn;
1057
- var FilterManager = class extends BaseManager {
1058
- constructor(queue) {
1059
- super(queue.distube);
1060
- __privateAdd(this, _validate);
1061
- __privateAdd(this, _resolveName);
1062
- __privateAdd(this, _resolveValue);
1063
- __privateAdd(this, _apply);
1064
- __publicField(this, "queue");
1065
- this.queue = queue;
1066
- }
1067
- add(filterOrFilters, override = false) {
1068
- if (Array.isArray(filterOrFilters)) {
1069
- const resolvedFilters = filterOrFilters.map((f) => __privateMethod(this, _validate, validate_fn).call(this, f));
1070
- const newFilters = resolvedFilters.reduceRight((unique, o) => {
1071
- if (!unique.some((obj) => obj === o && obj.name === o) && !unique.some((obj) => obj !== o.name && obj.name !== o.name)) {
1072
- if (!this.has(o))
1073
- unique.push(o);
1074
- if (this.has(o) && override) {
1075
- this.remove(o);
1076
- unique.push(o);
1077
- }
1078
- }
1079
- return unique;
1080
- }, []).reverse();
1081
- return this.set([...this.collection.values(), ...newFilters]);
1082
- }
1083
- return this.set([...this.collection.values(), filterOrFilters]);
1084
- }
1085
- clear() {
1086
- return this.set([]);
1087
- }
1088
- set(filters) {
1089
- this.collection.clear();
1090
- for (const filter of filters) {
1091
- const resolved = __privateMethod(this, _validate, validate_fn).call(this, filter);
1092
- this.collection.set(__privateMethod(this, _resolveName, resolveName_fn).call(this, resolved), resolved);
1093
- }
1094
- __privateMethod(this, _apply, apply_fn).call(this);
1095
- return this;
1096
- }
1097
- remove(filterOrFilters) {
1098
- const remove = /* @__PURE__ */ __name((f) => this.collection.delete(__privateMethod(this, _resolveName, resolveName_fn).call(this, __privateMethod(this, _validate, validate_fn).call(this, f))), "remove");
1099
- if (Array.isArray(filterOrFilters))
1100
- filterOrFilters.map(remove);
1101
- else
1102
- remove(filterOrFilters);
1103
- __privateMethod(this, _apply, apply_fn).call(this);
1104
- return this;
1105
- }
1106
- has(filter) {
1107
- return this.collection.has(__privateMethod(this, _resolveName, resolveName_fn).call(this, filter));
1108
- }
1109
- get names() {
1110
- return this.collection.map((f) => __privateMethod(this, _resolveName, resolveName_fn).call(this, f));
1111
- }
1112
- get values() {
1113
- return this.collection.map((f) => __privateMethod(this, _resolveValue, resolveValue_fn).call(this, f));
1114
- }
1115
- toString() {
1116
- return this.names.toString();
1117
- }
1118
- };
1119
- __name(FilterManager, "FilterManager");
1120
- _validate = new WeakSet();
1121
- validate_fn = /* @__PURE__ */ __name(function(filter) {
1122
- if (typeof filter === "string" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter) || typeof filter === "object" && typeof filter.name === "string" && typeof filter.value === "string") {
1123
- return filter;
1124
- }
1125
- throw new DisTubeError("INVALID_TYPE", "FilterResolvable", filter, "filter");
1126
- }, "#validate");
1127
- _resolveName = new WeakSet();
1128
- resolveName_fn = /* @__PURE__ */ __name(function(filter) {
1129
- return typeof filter === "string" ? filter : filter.name;
1130
- }, "#resolveName");
1131
- _resolveValue = new WeakSet();
1132
- resolveValue_fn = /* @__PURE__ */ __name(function(filter) {
1133
- return typeof filter === "string" ? this.distube.filters[filter] : filter.value;
1134
- }, "#resolveValue");
1135
- _apply = new WeakSet();
1136
- apply_fn = /* @__PURE__ */ __name(function() {
1137
- this.queue.beginTime = this.queue.currentTime;
1138
- this.queues.playSong(this.queue);
1139
- }, "#apply");
1140
-
1141
- // src/core/voice/DisTubeVoice.ts
1142
- var import_tiny_typed_emitter = require("tiny-typed-emitter");
1143
- var import_voice2 = require("@discordjs/voice");
1144
- var _channel, _volume, _br, br_fn, _join, join_fn;
1145
- var DisTubeVoice = class extends import_tiny_typed_emitter.TypedEmitter {
1146
- constructor(voiceManager, channel) {
1147
- super();
1148
- __privateAdd(this, _br);
1149
- __privateAdd(this, _join);
1150
- __publicField(this, "id");
1151
- __publicField(this, "voices");
1152
- __publicField(this, "audioPlayer");
1153
- __publicField(this, "connection");
1154
- __publicField(this, "audioResource");
1155
- __publicField(this, "emittedError");
1156
- __publicField(this, "isDisconnected", false);
1157
- __privateAdd(this, _channel, void 0);
1158
- __privateAdd(this, _volume, 100);
1159
- this.voices = voiceManager;
1160
- this.id = channel.guildId;
1161
- this.channel = channel;
1162
- this.voices.add(this.id, this);
1163
- this.audioPlayer = (0, import_voice2.createAudioPlayer)().on(import_voice2.AudioPlayerStatus.Idle, (oldState) => {
1164
- if (oldState.status !== import_voice2.AudioPlayerStatus.Idle) {
1165
- delete this.audioResource;
1166
- this.emit("finish");
1167
- }
1168
- }).on(import_voice2.AudioPlayerStatus.Playing, () => __privateMethod(this, _br, br_fn).call(this)).on("error", (error) => {
1169
- if (this.emittedError)
1170
- return;
1171
- this.emittedError = true;
1172
- this.emit("error", error);
1173
- });
1174
- this.connection.on(import_voice2.VoiceConnectionStatus.Disconnected, (_, newState) => {
1175
- if (newState.reason === import_voice2.VoiceConnectionDisconnectReason.Manual) {
1176
- this.leave();
1177
- } else if (newState.reason === import_voice2.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
1178
- entersState(this.connection, import_voice2.VoiceConnectionStatus.Connecting, 5e3).catch(() => {
1179
- if (![import_voice2.VoiceConnectionStatus.Ready, import_voice2.VoiceConnectionStatus.Connecting].includes(this.connection.state.status)) {
1180
- this.leave();
1181
- }
1182
- });
1183
- } else if (this.connection.rejoinAttempts < 5) {
1184
- setTimeout(() => {
1185
- this.connection.rejoin();
1186
- }, (this.connection.rejoinAttempts + 1) * 5e3).unref();
1187
- } else if (this.connection.state.status !== import_voice2.VoiceConnectionStatus.Destroyed) {
1188
- this.leave(new DisTubeError("VOICE_RECONNECT_FAILED"));
1189
- }
1190
- }).on(import_voice2.VoiceConnectionStatus.Destroyed, () => {
1191
- this.leave(new DisTubeError("VOICE_RECONNECT_FAILED"));
1192
- }).on("error", () => void 0);
1193
- this.connection.subscribe(this.audioPlayer);
1194
- }
1195
- get channel() {
1196
- return __privateGet(this, _channel);
1197
- }
1198
- set channel(channel) {
1199
- if (!isSupportedVoiceChannel(channel)) {
1200
- throw new DisTubeError("INVALID_TYPE", "BaseGuildVoiceChannel", channel, "DisTubeVoice#channel");
1201
- }
1202
- if (channel.guildId !== this.id)
1203
- throw new DisTubeError("VOICE_DIFFERENT_GUILD");
1204
- if (channel.client.user?.id !== this.voices.client.user?.id)
1205
- throw new DisTubeError("VOICE_DIFFERENT_CLIENT");
1206
- if (channel.id === __privateGet(this, _channel)?.id)
1207
- return;
1208
- if (!channel.joinable) {
1209
- if (channel.full)
1210
- throw new DisTubeError("VOICE_FULL");
1211
- else
1212
- throw new DisTubeError("VOICE_MISSING_PERMS");
1213
- }
1214
- this.connection = __privateMethod(this, _join, join_fn).call(this, channel);
1215
- __privateSet(this, _channel, channel);
1216
- __privateMethod(this, _br, br_fn).call(this);
1217
- }
1218
- async join(channel) {
1219
- const TIMEOUT = 3e4;
1220
- if (channel)
1221
- this.channel = channel;
1222
- try {
1223
- await entersState(this.connection, import_voice2.VoiceConnectionStatus.Ready, TIMEOUT);
1224
- } catch {
1225
- if (this.connection.state.status === import_voice2.VoiceConnectionStatus.Ready)
1226
- return this;
1227
- if (this.connection.state.status !== import_voice2.VoiceConnectionStatus.Destroyed)
1228
- this.connection.destroy();
1229
- this.voices.remove(this.id);
1230
- throw new DisTubeError("VOICE_CONNECT_FAILED", TIMEOUT / 1e3);
1231
- }
1232
- return this;
1233
- }
1234
- leave(error) {
1235
- this.stop(true);
1236
- if (!this.isDisconnected) {
1237
- this.emit("disconnect", error);
1238
- this.isDisconnected = true;
1239
- }
1240
- if (this.connection.state.status !== import_voice2.VoiceConnectionStatus.Destroyed)
1241
- this.connection.destroy();
1242
- this.voices.remove(this.id);
1243
- }
1244
- stop(force = false) {
1245
- this.audioPlayer.stop(force);
1246
- }
1247
- play(stream) {
1248
- this.emittedError = false;
1249
- stream.stream.on("error", (error) => {
1250
- if (this.emittedError || error.code === "ERR_STREAM_PREMATURE_CLOSE")
1251
- return;
1252
- this.emittedError = true;
1253
- this.emit("error", error);
1254
- });
1255
- this.audioResource = (0, import_voice2.createAudioResource)(stream.stream, {
1256
- inputType: stream.type,
1257
- inlineVolume: true
1258
- });
1259
- this.volume = __privateGet(this, _volume);
1260
- this.audioPlayer.play(this.audioResource);
1261
- }
1262
- set volume(volume) {
1263
- if (typeof volume !== "number" || isNaN(volume)) {
1264
- throw new DisTubeError("INVALID_TYPE", "number", volume, "volume");
1265
- }
1266
- if (volume < 0) {
1267
- throw new DisTubeError("NUMBER_COMPARE", "Volume", "bigger or equal to", 0);
1268
- }
1269
- __privateSet(this, _volume, volume);
1270
- this.audioResource?.volume?.setVolume(Math.pow(__privateGet(this, _volume) / 100, 0.5 / Math.log10(2)));
1271
- }
1272
- get volume() {
1273
- return __privateGet(this, _volume);
1274
- }
1275
- get playbackDuration() {
1276
- return (this.audioResource?.playbackDuration ?? 0) / 1e3;
1277
- }
1278
- pause() {
1279
- this.audioPlayer.pause();
1280
- }
1281
- unpause() {
1282
- this.audioPlayer.unpause();
1283
- }
1284
- get selfDeaf() {
1285
- return this.connection.joinConfig.selfDeaf;
1286
- }
1287
- get selfMute() {
1288
- return this.connection.joinConfig.selfMute;
1289
- }
1290
- setSelfDeaf(selfDeaf) {
1291
- if (typeof selfDeaf !== "boolean") {
1292
- throw new DisTubeError("INVALID_TYPE", "boolean", selfDeaf, "selfDeaf");
1293
- }
1294
- return this.connection.rejoin({
1295
- ...this.connection.joinConfig,
1296
- selfDeaf
1297
- });
1298
- }
1299
- setSelfMute(selfMute) {
1300
- if (typeof selfMute !== "boolean") {
1301
- throw new DisTubeError("INVALID_TYPE", "boolean", selfMute, "selfMute");
1302
- }
1303
- return this.connection.rejoin({
1304
- ...this.connection.joinConfig,
1305
- selfMute
1306
- });
1307
- }
1308
- get voiceState() {
1309
- return getClientMember(this.channel?.guild)?.voice;
1310
- }
1311
- };
1312
- __name(DisTubeVoice, "DisTubeVoice");
1313
- _channel = new WeakMap();
1314
- _volume = new WeakMap();
1315
- _br = new WeakSet();
1316
- br_fn = /* @__PURE__ */ __name(function() {
1317
- if (this.audioResource?.encoder?.encoder)
1318
- this.audioResource.encoder.setBitrate(this.channel.bitrate);
1319
- }, "#br");
1320
- _join = new WeakSet();
1321
- join_fn = /* @__PURE__ */ __name(function(channel) {
1322
- return (0, import_voice2.joinVoiceChannel)({
1323
- channelId: channel.id,
1324
- guildId: this.id,
1325
- adapterCreator: channel.guild.voiceAdapterCreator,
1326
- group: channel.client.user?.id
1327
- });
1328
- }, "#join");
1329
-
1330
- // src/core/voice/DisTubeVoiceManager.ts
1331
- var import_voice3 = require("@discordjs/voice");
1332
- var DisTubeVoiceManager = class extends GuildIdManager {
1333
- create(channel) {
1334
- const existing = this.get(channel.guildId);
1335
- if (existing) {
1336
- existing.channel = channel;
1337
- return existing;
1166
+ delete prev.formats;
1167
+ delete prev.streamURL;
1168
+ if (this.options.savePreviousSongs)
1169
+ queue.previousSongs.push(prev);
1170
+ else
1171
+ queue.previousSongs.push({ id: prev.id });
1338
1172
  }
1339
- return new DisTubeVoice(this, channel);
1173
+ queue._next = queue._prev = false;
1174
+ queue.beginTime = 0;
1175
+ const err = await this.playSong(queue);
1176
+ if (!err && emitPlaySong)
1177
+ this.emit("playSong", queue, queue.songs[0]);
1178
+ } finally {
1179
+ queue._taskQueue.resolve();
1340
1180
  }
1341
- join(channel) {
1342
- const existing = this.get(channel.guildId);
1343
- if (existing)
1344
- return existing.join(channel);
1345
- return this.create(channel).join();
1181
+ }, "#handleSongFinish");
1182
+ _handlePlayingError = new WeakSet();
1183
+ handlePlayingError_fn = /* @__PURE__ */ __name(function(queue, error) {
1184
+ const song = queue.songs.shift();
1185
+ try {
1186
+ error.name = "PlayingError";
1187
+ error.message = `${error.message}
1188
+ Id: ${song.id}
1189
+ Name: ${song.name}`;
1190
+ } catch {
1346
1191
  }
1347
- leave(guild) {
1348
- const voice = this.get(guild);
1349
- if (voice) {
1350
- voice.leave();
1351
- } else {
1352
- const connection = (0, import_voice3.getVoiceConnection)(resolveGuildId(guild), this.client.user?.id) ?? (0, import_voice3.getVoiceConnection)(resolveGuildId(guild));
1353
- if (connection && connection.state.status !== import_voice3.VoiceConnectionStatus.Destroyed) {
1354
- connection.destroy();
1355
- }
1356
- }
1192
+ this.emitError(error, queue.textChannel);
1193
+ if (queue.songs.length > 0) {
1194
+ queue._next = queue._prev = false;
1195
+ queue.beginTime = 0;
1196
+ this.playSong(queue).then((e) => {
1197
+ if (!e)
1198
+ this.emit("playSong", queue, queue.songs[0]);
1199
+ });
1200
+ } else {
1201
+ queue.stop();
1357
1202
  }
1358
- };
1359
- __name(DisTubeVoiceManager, "DisTubeVoiceManager");
1203
+ }, "#handlePlayingError");
1204
+ _emitPlaySong = new WeakSet();
1205
+ emitPlaySong_fn = /* @__PURE__ */ __name(function(queue) {
1206
+ return !this.options.emitNewSongOnly || queue.repeatMode === 1 /* SONG */ && queue._next || queue.repeatMode !== 1 /* SONG */ && queue.songs[0]?.id !== queue.songs[1]?.id;
1207
+ }, "#emitPlaySong");
1360
1208
 
1361
1209
  // src/core/DisTubeHandler.ts
1362
- var import_ytdl_core = __toESM(require("@distube/ytdl-core"));
1363
1210
  var import_ytpl = __toESM(require("@distube/ytpl"));
1211
+ var import_ytdl_core = __toESM(require("@distube/ytdl-core"));
1364
1212
  var DisTubeHandler = class extends DisTubeBase {
1365
1213
  constructor(distube) {
1366
1214
  super(distube);
@@ -1424,13 +1272,15 @@ var DisTubeHandler = class extends DisTubeBase {
1424
1272
  song.member = options.member;
1425
1273
  return song;
1426
1274
  }
1427
- if (song instanceof SearchResult) {
1428
- if (song.type === "video" /* VIDEO */)
1429
- return new Song(song, options);
1275
+ if (song instanceof SearchResultVideo)
1276
+ return new Song(song, options);
1277
+ if (song instanceof SearchResultPlaylist)
1430
1278
  return this.resolvePlaylist(song.url, options);
1431
- }
1432
- if (isObject(song))
1279
+ if (isObject(song)) {
1280
+ if (!("url" in song) && !("id" in song))
1281
+ throw new DisTubeError("CANNOT_RESOLVE_SONG", song);
1433
1282
  return new Song(song, options);
1283
+ }
1434
1284
  if (import_ytpl.default.validateID(song))
1435
1285
  return this.resolvePlaylist(song, options);
1436
1286
  if (import_ytdl_core.default.validateURL(song))
@@ -1453,14 +1303,19 @@ var DisTubeHandler = class extends DisTubeBase {
1453
1303
  playlist.member = member;
1454
1304
  return playlist;
1455
1305
  }
1456
- let solvablePlaylist;
1457
1306
  if (typeof playlist === "string") {
1458
- solvablePlaylist = await (0, import_ytpl.default)(playlist, { limit: Infinity });
1459
- solvablePlaylist.items = solvablePlaylist.items.filter((v) => !v.thumbnail.includes("no_thumbnail")).map((v) => new Song(v, { member, metadata }));
1460
- } else {
1461
- solvablePlaylist = playlist;
1462
- }
1463
- return new Playlist(solvablePlaylist, { member, properties: { source }, metadata });
1307
+ const info = await (0, import_ytpl.default)(playlist, { limit: Infinity });
1308
+ const songs = info.items.filter((v) => !v.thumbnail.includes("no_thumbnail")).map((v) => new Song(v, { member, metadata }));
1309
+ return new Playlist({
1310
+ source,
1311
+ songs,
1312
+ member,
1313
+ name: info.title,
1314
+ url: info.url,
1315
+ thumbnail: songs[0].thumbnail
1316
+ }, { metadata });
1317
+ }
1318
+ return new Playlist(playlist, { member, properties: { source }, metadata });
1464
1319
  }
1465
1320
  async searchSong(message, query) {
1466
1321
  if (!isMessageInstance(message))
@@ -1594,6 +1449,186 @@ var DisTubeHandler = class extends DisTubeBase {
1594
1449
  };
1595
1450
  __name(DisTubeHandler, "DisTubeHandler");
1596
1451
 
1452
+ // src/core/DisTubeOptions.ts
1453
+ var _validateOptions, validateOptions_fn;
1454
+ var Options = class {
1455
+ constructor(options) {
1456
+ __privateAdd(this, _validateOptions);
1457
+ __publicField(this, "plugins");
1458
+ __publicField(this, "emitNewSongOnly");
1459
+ __publicField(this, "leaveOnFinish");
1460
+ __publicField(this, "leaveOnStop");
1461
+ __publicField(this, "leaveOnEmpty");
1462
+ __publicField(this, "emptyCooldown");
1463
+ __publicField(this, "savePreviousSongs");
1464
+ __publicField(this, "searchSongs");
1465
+ __publicField(this, "searchCooldown");
1466
+ __publicField(this, "youtubeCookie");
1467
+ __publicField(this, "youtubeIdentityToken");
1468
+ __publicField(this, "customFilters");
1469
+ __publicField(this, "ytdlOptions");
1470
+ __publicField(this, "nsfw");
1471
+ __publicField(this, "emitAddSongWhenCreatingQueue");
1472
+ __publicField(this, "emitAddListWhenCreatingQueue");
1473
+ __publicField(this, "joinNewVoiceChannel");
1474
+ __publicField(this, "streamType");
1475
+ if (typeof options !== "object" || Array.isArray(options)) {
1476
+ throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
1477
+ }
1478
+ const opts = { ...defaultOptions, ...options };
1479
+ this.plugins = opts.plugins;
1480
+ this.emitNewSongOnly = opts.emitNewSongOnly;
1481
+ this.leaveOnEmpty = opts.leaveOnEmpty;
1482
+ this.leaveOnFinish = opts.leaveOnFinish;
1483
+ this.leaveOnStop = opts.leaveOnStop;
1484
+ this.savePreviousSongs = opts.savePreviousSongs;
1485
+ this.searchSongs = opts.searchSongs;
1486
+ this.youtubeCookie = opts.youtubeCookie;
1487
+ this.youtubeIdentityToken = opts.youtubeIdentityToken;
1488
+ this.customFilters = opts.customFilters;
1489
+ this.ytdlOptions = opts.ytdlOptions;
1490
+ this.searchCooldown = opts.searchCooldown;
1491
+ this.emptyCooldown = opts.emptyCooldown;
1492
+ this.nsfw = opts.nsfw;
1493
+ this.emitAddSongWhenCreatingQueue = opts.emitAddSongWhenCreatingQueue;
1494
+ this.emitAddListWhenCreatingQueue = opts.emitAddListWhenCreatingQueue;
1495
+ this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
1496
+ this.streamType = opts.streamType;
1497
+ checkInvalidKey(opts, this, "DisTubeOptions");
1498
+ __privateMethod(this, _validateOptions, validateOptions_fn).call(this);
1499
+ }
1500
+ };
1501
+ __name(Options, "Options");
1502
+ _validateOptions = new WeakSet();
1503
+ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
1504
+ if (typeof options.emitNewSongOnly !== "boolean") {
1505
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.emitNewSongOnly, "DisTubeOptions.emitNewSongOnly");
1506
+ }
1507
+ if (typeof options.leaveOnEmpty !== "boolean") {
1508
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnEmpty, "DisTubeOptions.leaveOnEmpty");
1509
+ }
1510
+ if (typeof options.leaveOnFinish !== "boolean") {
1511
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnFinish, "DisTubeOptions.leaveOnFinish");
1512
+ }
1513
+ if (typeof options.leaveOnStop !== "boolean") {
1514
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.leaveOnStop, "DisTubeOptions.leaveOnStop");
1515
+ }
1516
+ if (typeof options.savePreviousSongs !== "boolean") {
1517
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.savePreviousSongs, "DisTubeOptions.savePreviousSongs");
1518
+ }
1519
+ if (typeof options.joinNewVoiceChannel !== "boolean") {
1520
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.joinNewVoiceChannel, "DisTubeOptions.joinNewVoiceChannel");
1521
+ }
1522
+ if (typeof options.youtubeCookie !== "undefined" && typeof options.youtubeCookie !== "string") {
1523
+ throw new DisTubeError("INVALID_TYPE", "string", options.youtubeCookie, "DisTubeOptions.youtubeCookie");
1524
+ }
1525
+ if (typeof options.youtubeIdentityToken !== "undefined" && typeof options.youtubeIdentityToken !== "string") {
1526
+ throw new DisTubeError("INVALID_TYPE", "string", options.youtubeIdentityToken, "DisTubeOptions.youtubeIdentityToken");
1527
+ }
1528
+ if (typeof options.customFilters !== "undefined" && typeof options.customFilters !== "object" || Array.isArray(options.customFilters)) {
1529
+ throw new DisTubeError("INVALID_TYPE", "object", options.customFilters, "DisTubeOptions.customFilters");
1530
+ }
1531
+ if (typeof options.ytdlOptions !== "object" || Array.isArray(options.ytdlOptions)) {
1532
+ throw new DisTubeError("INVALID_TYPE", "object", options.ytdlOptions, "DisTubeOptions.ytdlOptions");
1533
+ }
1534
+ if (typeof options.searchCooldown !== "number" || isNaN(options.searchCooldown)) {
1535
+ throw new DisTubeError("INVALID_TYPE", "number", options.searchCooldown, "DisTubeOptions.searchCooldown");
1536
+ }
1537
+ if (typeof options.emptyCooldown !== "number" || isNaN(options.emptyCooldown)) {
1538
+ throw new DisTubeError("INVALID_TYPE", "number", options.emptyCooldown, "DisTubeOptions.emptyCooldown");
1539
+ }
1540
+ if (typeof options.searchSongs !== "number" || isNaN(options.searchSongs)) {
1541
+ throw new DisTubeError("INVALID_TYPE", "number", options.searchSongs, "DisTubeOptions.searchSongs");
1542
+ }
1543
+ if (!Array.isArray(options.plugins)) {
1544
+ throw new DisTubeError("INVALID_TYPE", "Array<Plugin>", options.plugins, "DisTubeOptions.plugins");
1545
+ }
1546
+ if (typeof options.nsfw !== "boolean") {
1547
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.nsfw, "DisTubeOptions.nsfw");
1548
+ }
1549
+ if (typeof options.emitAddSongWhenCreatingQueue !== "boolean") {
1550
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.emitAddSongWhenCreatingQueue, "DisTubeOptions.emitAddSongWhenCreatingQueue");
1551
+ }
1552
+ if (typeof options.emitAddListWhenCreatingQueue !== "boolean") {
1553
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.emitAddListWhenCreatingQueue, "DisTubeOptions.emitAddListWhenCreatingQueue");
1554
+ }
1555
+ if (typeof options.streamType !== "number" || isNaN(options.streamType) || !StreamType[options.streamType]) {
1556
+ throw new DisTubeError("INVALID_TYPE", "StreamType", options.streamType, "DisTubeOptions.streamType");
1557
+ }
1558
+ }, "#validateOptions");
1559
+
1560
+ // src/core/DisTubeStream.ts
1561
+ var import_prism_media = require("prism-media");
1562
+ var import_voice3 = require("@discordjs/voice");
1563
+ var chooseBestVideoFormat = /* @__PURE__ */ __name((formats, isLive = false) => {
1564
+ let filter = /* @__PURE__ */ __name((format) => format.hasAudio, "filter");
1565
+ if (isLive)
1566
+ filter = /* @__PURE__ */ __name((format) => format.hasAudio && format.isHLS, "filter");
1567
+ formats = formats.filter(filter).sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate));
1568
+ return formats.find((format) => !format.hasVideo) || formats.sort((a, b) => Number(a.bitrate) - Number(b.bitrate))[0];
1569
+ }, "chooseBestVideoFormat");
1570
+ var DisTubeStream = class {
1571
+ constructor(url, options) {
1572
+ __publicField(this, "type");
1573
+ __publicField(this, "stream");
1574
+ __publicField(this, "url");
1575
+ this.url = url;
1576
+ this.type = !options.type ? import_voice3.StreamType.OggOpus : import_voice3.StreamType.Raw;
1577
+ const args = [
1578
+ "-reconnect",
1579
+ "1",
1580
+ "-reconnect_streamed",
1581
+ "1",
1582
+ "-reconnect_delay_max",
1583
+ "5",
1584
+ "-i",
1585
+ url,
1586
+ "-analyzeduration",
1587
+ "0",
1588
+ "-loglevel",
1589
+ "0",
1590
+ "-ar",
1591
+ "48000",
1592
+ "-ac",
1593
+ "2",
1594
+ "-f"
1595
+ ];
1596
+ if (!options.type) {
1597
+ args.push("opus", "-acodec", "libopus");
1598
+ } else {
1599
+ args.push("s16le");
1600
+ }
1601
+ if (typeof options.seek === "number" && options.seek > 0) {
1602
+ args.unshift("-ss", options.seek.toString());
1603
+ }
1604
+ if (Array.isArray(options.ffmpegArgs)) {
1605
+ args.push(...options.ffmpegArgs);
1606
+ }
1607
+ this.stream = new import_prism_media.FFmpeg({ args, shell: false });
1608
+ }
1609
+ static YouTube(formats, options = {}) {
1610
+ if (!formats || !formats.length)
1611
+ throw new DisTubeError("UNAVAILABLE_VIDEO");
1612
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
1613
+ throw new DisTubeError("INVALID_TYPE", "object", options, "options");
1614
+ }
1615
+ const bestFormat = chooseBestVideoFormat(formats, options.isLive);
1616
+ if (!bestFormat)
1617
+ throw new DisTubeError("UNPLAYABLE_FORMATS");
1618
+ return new DisTubeStream(bestFormat.url, options);
1619
+ }
1620
+ static DirectLink(url, options = {}) {
1621
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
1622
+ throw new DisTubeError("INVALID_TYPE", "object", options, "options");
1623
+ }
1624
+ if (typeof url !== "string" || !isURL(url)) {
1625
+ throw new DisTubeError("INVALID_TYPE", "an URL", url);
1626
+ }
1627
+ return new DisTubeStream(url, options);
1628
+ }
1629
+ };
1630
+ __name(DisTubeStream, "DisTubeStream");
1631
+
1597
1632
  // src/struct/Queue.ts
1598
1633
  var _filters;
1599
1634
  var Queue = class extends DisTubeBase {
@@ -1636,7 +1671,7 @@ var Queue = class extends DisTubeBase {
1636
1671
  this._listeners = void 0;
1637
1672
  }
1638
1673
  get clientMember() {
1639
- return getClientMember(this.voice.channel.guild);
1674
+ return this.voice.channel.guild.members.me ?? void 0;
1640
1675
  }
1641
1676
  get filters() {
1642
1677
  return __privateGet(this, _filters);
@@ -1980,7 +2015,7 @@ function isVoiceChannelEmpty(voiceState) {
1980
2015
  const clientId = voiceState.client.user?.id;
1981
2016
  if (!guild || !clientId)
1982
2017
  return false;
1983
- const voiceChannel = guild.members.resolve(clientId)?.voice?.channel;
2018
+ const voiceChannel = guild.members.me?.voice?.channel;
1984
2019
  if (!voiceChannel)
1985
2020
  return false;
1986
2021
  const members = voiceChannel.members.filter((m) => !m.user.bot);
@@ -2000,7 +2035,7 @@ function isMemberInstance(member) {
2000
2035
  }
2001
2036
  __name(isMemberInstance, "isMemberInstance");
2002
2037
  function isTextChannelInstance(channel) {
2003
- return !!channel && isSnowflake(channel.id) && isSnowflake(channel.guildId) && typeof channel.name === "string" && import_discord2.Constants.TextBasedChannelTypes.includes(channel.type) && typeof channel.messages?.cache === "object";
2038
+ return !!channel && isSnowflake(channel.id) && isSnowflake(channel.guildId) && typeof channel.name === "string" && import_discord2.Constants.TextBasedChannelTypes.includes(channel.type) && typeof channel.nsfw === "boolean" && "messages" in channel && typeof channel.send === "function";
2004
2039
  }
2005
2040
  __name(isTextChannelInstance, "isTextChannelInstance");
2006
2041
  function isMessageInstance(message) {
@@ -2046,34 +2081,6 @@ function checkInvalidKey(target, source, sourceName) {
2046
2081
  throw new DisTubeError("INVALID_KEY", sourceName, invalidKey);
2047
2082
  }
2048
2083
  __name(checkInvalidKey, "checkInvalidKey");
2049
- async function waitEvent(target, status, maxTime) {
2050
- let cleanup = /* @__PURE__ */ __name(() => {
2051
- }, "cleanup");
2052
- try {
2053
- await new Promise((resolve, reject) => {
2054
- const timeout = setTimeout(() => reject(new Error(`Didn't trigger ${status} within ${maxTime}ms`)), maxTime);
2055
- target.once(status, resolve);
2056
- target.once("error", reject);
2057
- cleanup = /* @__PURE__ */ __name(() => {
2058
- clearTimeout(timeout);
2059
- target.off(status, resolve);
2060
- target.off("error", reject);
2061
- }, "cleanup");
2062
- if (target?.state?.status === status)
2063
- resolve(0);
2064
- });
2065
- return target;
2066
- } finally {
2067
- cleanup();
2068
- }
2069
- }
2070
- __name(waitEvent, "waitEvent");
2071
- async function entersState(target, status, maxTime) {
2072
- if (target.state.status === status)
2073
- return target;
2074
- return waitEvent(target, status, maxTime);
2075
- }
2076
- __name(entersState, "entersState");
2077
2084
  function isObject(obj) {
2078
2085
  return typeof obj === "object" && obj !== null && !Array.isArray(obj);
2079
2086
  }
@@ -2082,63 +2089,26 @@ function isRecord(obj) {
2082
2089
  return isObject(obj);
2083
2090
  }
2084
2091
  __name(isRecord, "isRecord");
2085
- function getClientMember(guild) {
2086
- const clientUser = guild.client.user;
2087
- if (!clientUser)
2088
- return void 0;
2089
- const clientMember = guild.members.resolve(clientUser);
2090
- if (!clientMember)
2091
- return void 0;
2092
- return clientMember;
2093
- }
2094
- __name(getClientMember, "getClientMember");
2095
2092
 
2096
- // src/plugin/http.ts
2097
- var import_http = __toESM(require("http"));
2098
- var HTTPPlugin = class extends ExtractorPlugin {
2093
+ // src/plugin/DirectLink.ts
2094
+ var import_undici = require("undici");
2095
+ var DirectLinkPlugin = class extends ExtractorPlugin {
2099
2096
  async validate(url) {
2100
- return validateAudioURL(import_http.default, "http:", url);
2101
- }
2102
- async resolve(url, options = {}) {
2103
- return resolveHttpSong(url, { ...options, source: "http" });
2104
- }
2105
- };
2106
- __name(HTTPPlugin, "HTTPPlugin");
2107
-
2108
- // src/plugin/https.ts
2109
- var import_https = __toESM(require("https"));
2110
- var import_url2 = require("url");
2111
- var getResponseHeaders = /* @__PURE__ */ __name(async (httpModule, url) => new Promise((resolve, reject) => {
2112
- httpModule.get(url).on("response", (res) => {
2113
- resolve(res.headers);
2114
- }).on("error", reject);
2115
- }), "getResponseHeaders");
2116
- var validateAudioURL = /* @__PURE__ */ __name(async (httpModule, protocol, url) => {
2117
- if (new import_url2.URL(url).protocol.toLowerCase() !== protocol) {
2097
+ const headers = await (0, import_undici.request)(url, { method: "HEAD" }).then((res) => res.headers);
2098
+ const type = headers["content-type"];
2099
+ if (type?.startsWith("audio"))
2100
+ return true;
2118
2101
  return false;
2119
2102
  }
2120
- const headers = await getResponseHeaders(httpModule, url), type = headers["content-type"];
2121
- if (type?.startsWith("audio")) {
2122
- return true;
2123
- }
2124
- return false;
2125
- }, "validateAudioURL");
2126
- var resolveHttpSong = /* @__PURE__ */ __name(async (url, options) => {
2127
- url = url.replace(/\/+$/, "");
2128
- return new Song({
2129
- name: url.substring(url.lastIndexOf("/") + 1).replace(/((\?|#).*)?$/, "") || url,
2130
- url
2131
- }, options);
2132
- }, "resolveHttpSong");
2133
- var HTTPSPlugin = class extends ExtractorPlugin {
2134
- async validate(url) {
2135
- return validateAudioURL(import_https.default, "https:", url);
2136
- }
2137
2103
  async resolve(url, options = {}) {
2138
- return resolveHttpSong(url, { ...options, source: "https" });
2104
+ url = url.replace(/\/+$/, "");
2105
+ return new Song({
2106
+ name: url.substring(url.lastIndexOf("/") + 1).replace(/((\?|#).*)?$/, "") || url,
2107
+ url
2108
+ }, options);
2139
2109
  }
2140
2110
  };
2141
- __name(HTTPSPlugin, "HTTPSPlugin");
2111
+ __name(DirectLinkPlugin, "DirectLinkPlugin");
2142
2112
 
2143
2113
  // src/DisTube.ts
2144
2114
  var import_ytsr = __toESM(require("@distube/ytsr"));
@@ -2165,7 +2135,7 @@ var DisTube = class extends import_tiny_typed_emitter2.TypedEmitter {
2165
2135
  this.handler = new DisTubeHandler(this);
2166
2136
  this.queues = new QueueManager(this);
2167
2137
  this.filters = { ...defaultFilters, ...this.options.customFilters };
2168
- this.options.plugins.push(new HTTPPlugin(), new HTTPSPlugin());
2138
+ this.options.plugins.push(new DirectLinkPlugin());
2169
2139
  this.options.plugins.map((p) => p.init(this));
2170
2140
  this.extractorPlugins = this.options.plugins.filter((p) => p.type === "extractor");
2171
2141
  this.customPlugins = this.options.plugins.filter((p) => p.type === "custom");
@@ -2183,7 +2153,7 @@ var DisTube = class extends import_tiny_typed_emitter2.TypedEmitter {
2183
2153
  if (!isObject(options))
2184
2154
  throw new DisTubeError("INVALID_TYPE", "object", options, "options");
2185
2155
  const { textChannel, member, skip, message, metadata } = {
2186
- member: getClientMember(voiceChannel.guild),
2156
+ member: voiceChannel.guild.members.me ?? void 0,
2187
2157
  textChannel: options?.message?.channel,
2188
2158
  skip: false,
2189
2159
  ...options
@@ -2231,12 +2201,12 @@ var DisTube = class extends import_tiny_typed_emitter2.TypedEmitter {
2231
2201
  if (!(e instanceof DisTubeError)) {
2232
2202
  try {
2233
2203
  e.name = "PlayError";
2234
- e.message = `${song?.url || song}
2204
+ e.message = `${typeof song === "string" ? song : song.url}
2235
2205
  ${e.message}`;
2236
2206
  } catch {
2237
2207
  }
2238
2208
  }
2239
- this.emitError(e, textChannel);
2209
+ throw e;
2240
2210
  } finally {
2241
2211
  if (queuing)
2242
2212
  queue?._taskQueue.resolve();
@@ -2248,7 +2218,7 @@ ${e.message}`;
2248
2218
  throw new DisTubeError("INVALID_TYPE", "Array", songs, "songs");
2249
2219
  if (!songs.length)
2250
2220
  throw new DisTubeError("EMPTY_ARRAY", "songs");
2251
- const filteredSongs = songs.filter((song) => song instanceof Song || song instanceof SearchResult && song.type === "video" || isURL(song));
2221
+ const filteredSongs = songs.filter((song) => song instanceof Song || isURL(song) || typeof song !== "string" && song.type === "video" /* VIDEO */);
2252
2222
  if (!filteredSongs.length)
2253
2223
  throw new DisTubeError("NO_VALID_SONG");
2254
2224
  if (member && !isMemberInstance(member)) {
@@ -2270,7 +2240,7 @@ ${e.message}`;
2270
2240
  return new Playlist(resolvedSongs, { member, properties, metadata });
2271
2241
  }
2272
2242
  async search(string, options = {}) {
2273
- const opts = { type: "video", limit: 10, safeSearch: false, ...options };
2243
+ const opts = { type: "video" /* VIDEO */, limit: 10, safeSearch: false, ...options };
2274
2244
  if (typeof opts.type !== "string" || !["video", "playlist"].includes(opts.type)) {
2275
2245
  throw new DisTubeError("INVALID_TYPE", ["video", "playlist"], opts.type, "options.type");
2276
2246
  }
@@ -2283,7 +2253,11 @@ ${e.message}`;
2283
2253
  }
2284
2254
  try {
2285
2255
  const search = await (0, import_ytsr.default)(string, opts);
2286
- const results = search.items.map((i) => new SearchResult(i));
2256
+ const results = search.items.map((i) => {
2257
+ if (i.type === "video")
2258
+ return new SearchResultVideo(i);
2259
+ return new SearchResultPlaylist(i);
2260
+ });
2287
2261
  if (results.length === 0)
2288
2262
  throw new DisTubeError("NO_RESULT");
2289
2263
  return results;
@@ -2385,6 +2359,7 @@ __name(DisTube, "DisTube");
2385
2359
  0 && (module.exports = {
2386
2360
  BaseManager,
2387
2361
  CustomPlugin,
2362
+ DirectLinkPlugin,
2388
2363
  DisTube,
2389
2364
  DisTubeBase,
2390
2365
  DisTubeError,
@@ -2395,8 +2370,6 @@ __name(DisTube, "DisTube");
2395
2370
  ExtractorPlugin,
2396
2371
  FilterManager,
2397
2372
  GuildIdManager,
2398
- HTTPPlugin,
2399
- HTTPSPlugin,
2400
2373
  Options,
2401
2374
  Playlist,
2402
2375
  Plugin,
@@ -2404,8 +2377,9 @@ __name(DisTube, "DisTube");
2404
2377
  Queue,
2405
2378
  QueueManager,
2406
2379
  RepeatMode,
2407
- SearchResult,
2380
+ SearchResultPlaylist,
2408
2381
  SearchResultType,
2382
+ SearchResultVideo,
2409
2383
  Song,
2410
2384
  StreamType,
2411
2385
  TaskQueue,
@@ -2414,10 +2388,7 @@ __name(DisTube, "DisTube");
2414
2388
  chooseBestVideoFormat,
2415
2389
  defaultFilters,
2416
2390
  defaultOptions,
2417
- entersState,
2418
2391
  formatDuration,
2419
- getClientMember,
2420
- getResponseHeaders,
2421
2392
  isClientInstance,
2422
2393
  isGuildInstance,
2423
2394
  isMemberInstance,
@@ -2431,9 +2402,7 @@ __name(DisTube, "DisTube");
2431
2402
  isVoiceChannelEmpty,
2432
2403
  parseNumber,
2433
2404
  resolveGuildId,
2434
- resolveHttpSong,
2435
2405
  toSecond,
2436
- validateAudioURL,
2437
2406
  version
2438
2407
  });
2439
2408
  //# sourceMappingURL=index.js.map