distube 4.0.0-dev.4 → 4.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
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -56,7 +57,7 @@ var require_package = __commonJS({
56
57
  "package.json"(exports, module2) {
57
58
  module2.exports = {
58
59
  name: "distube",
59
- version: "4.0.0-dev.4",
60
+ version: "4.0.0",
60
61
  description: "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
61
62
  main: "./dist/index.js",
62
63
  module: "./dist/index.mjs",
@@ -122,46 +123,47 @@ var require_package = __commonJS({
122
123
  dependencies: {
123
124
  "@distube/ytdl-core": "^4.11.3",
124
125
  "@distube/ytpl": "^1.1.1",
125
- "@distube/ytsr": "^1.1.5",
126
+ "@distube/ytsr": "^1.1.8",
126
127
  "prism-media": "https://codeload.github.com/distubejs/prism-media/tar.gz/main#workaround.tar.gz",
127
128
  "tiny-typed-emitter": "^2.1.0",
128
- tslib: "^2.4.0"
129
+ tslib: "^2.4.0",
130
+ undici: "^5.8.0"
129
131
  },
130
132
  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",
133
+ "@babel/core": "^7.18.6",
134
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
135
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.6",
136
+ "@babel/preset-env": "^7.18.6",
137
+ "@babel/preset-typescript": "^7.18.6",
138
+ "@commitlint/cli": "^17.0.3",
139
+ "@commitlint/config-conventional": "^17.0.3",
140
+ "@discordjs/voice": "latest",
139
141
  "@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",
142
+ "@types/jest": "^28.1.6",
143
+ "@types/node": "^18.0.6",
144
+ "@typescript-eslint/eslint-plugin": "^5.30.6",
145
+ "@typescript-eslint/parser": "^5.30.6",
146
+ "babel-jest": "^28.1.3",
147
+ "discord.js": "latest",
148
+ eslint: "^8.20.0",
147
149
  "eslint-config-distube": "^1.6.4",
148
150
  "eslint-config-prettier": "^8.5.0",
149
151
  "eslint-plugin-deprecation": "^1.3.2",
150
- "eslint-plugin-jsdoc": "^39.3.0",
152
+ "eslint-plugin-jsdoc": "^39.3.3",
151
153
  husky: "^8.0.1",
152
- jest: "^28.1.0",
154
+ jest: "^28.1.3",
153
155
  "jsdoc-babel": "^0.5.0",
154
156
  "nano-staged": "^0.8.0",
155
- "npm-check-updates": "^13.0.1",
157
+ "npm-check-updates": "^15.3.4",
156
158
  pinst: "^3.0.0",
157
- prettier: "^2.6.2",
158
- tsup: "^5.12.8",
159
- typescript: "^4.6.4"
159
+ prettier: "^2.7.1",
160
+ tsup: "^6.1.3",
161
+ typescript: "^4.7.4"
160
162
  },
161
163
  peerDependencies: {
162
164
  "@discordjs/opus": "*",
163
165
  "@discordjs/voice": "*",
164
- "discord.js": "14||^14.0.0-dev"
166
+ "discord.js": "14"
165
167
  },
166
168
  peerDependenciesMeta: {
167
169
  "@discordjs/opus": {
@@ -180,8 +182,7 @@ var require_package = __commonJS({
180
182
  engines: {
181
183
  node: ">=16.9.0"
182
184
  },
183
- packageManager: "yarn@3.2.0",
184
- stableVersion: "4.0.0-dev"
185
+ packageManager: "yarn@3.2.0"
185
186
  };
186
187
  }
187
188
  });
@@ -191,6 +192,7 @@ var src_exports = {};
191
192
  __export(src_exports, {
192
193
  BaseManager: () => BaseManager,
193
194
  CustomPlugin: () => CustomPlugin,
195
+ DirectLinkPlugin: () => DirectLinkPlugin,
194
196
  DisTube: () => DisTube,
195
197
  DisTubeBase: () => DisTubeBase,
196
198
  DisTubeError: () => DisTubeError,
@@ -201,8 +203,6 @@ __export(src_exports, {
201
203
  ExtractorPlugin: () => ExtractorPlugin,
202
204
  FilterManager: () => FilterManager,
203
205
  GuildIdManager: () => GuildIdManager,
204
- HTTPPlugin: () => HTTPPlugin,
205
- HTTPSPlugin: () => HTTPSPlugin,
206
206
  Options: () => Options,
207
207
  Playlist: () => Playlist,
208
208
  Plugin: () => Plugin,
@@ -210,8 +210,9 @@ __export(src_exports, {
210
210
  Queue: () => Queue,
211
211
  QueueManager: () => QueueManager,
212
212
  RepeatMode: () => RepeatMode,
213
- SearchResult: () => SearchResult,
213
+ SearchResultPlaylist: () => SearchResultPlaylist,
214
214
  SearchResultType: () => SearchResultType,
215
+ SearchResultVideo: () => SearchResultVideo,
215
216
  Song: () => Song,
216
217
  StreamType: () => StreamType,
217
218
  TaskQueue: () => TaskQueue,
@@ -221,10 +222,7 @@ __export(src_exports, {
221
222
  default: () => DisTube,
222
223
  defaultFilters: () => defaultFilters,
223
224
  defaultOptions: () => defaultOptions,
224
- entersState: () => entersState,
225
225
  formatDuration: () => formatDuration,
226
- getClientMember: () => getClientMember,
227
- getResponseHeaders: () => getResponseHeaders,
228
226
  isClientInstance: () => isClientInstance,
229
227
  isGuildInstance: () => isGuildInstance,
230
228
  isMemberInstance: () => isMemberInstance,
@@ -238,9 +236,7 @@ __export(src_exports, {
238
236
  isVoiceChannelEmpty: () => isVoiceChannelEmpty,
239
237
  parseNumber: () => parseNumber,
240
238
  resolveGuildId: () => resolveGuildId,
241
- resolveHttpSong: () => resolveHttpSong,
242
239
  toSecond: () => toSecond,
243
- validateAudioURL: () => validateAudioURL,
244
240
  version: () => version
245
241
  });
246
242
  module.exports = __toCommonJS(src_exports);
@@ -307,7 +303,7 @@ var defaultOptions = {
307
303
  // src/struct/DisTubeError.ts
308
304
  var import_node_util = require("util");
309
305
  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)}`,
306
+ 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
307
  NUMBER_COMPARE: (name, expected, value) => `'${name}' must be ${expected} ${value}`,
312
308
  EMPTY_ARRAY: (name) => `'${name}' is an empty array`,
313
309
  EMPTY_FILTERED_ARRAY: (name, type) => `There is no valid '${type}' in the '${name}' array`,
@@ -413,26 +409,33 @@ var Playlist = class {
413
409
  __publicField(this, "url");
414
410
  __publicField(this, "thumbnail");
415
411
  const { member, properties, metadata } = options;
416
- if (typeof playlist !== "object") {
417
- throw new DisTubeError("INVALID_TYPE", ["Array<Song>", "object"], playlist, "playlist");
412
+ if (typeof playlist !== "object" || !Array.isArray(playlist) && ["source", "songs"].some((key) => !(key in playlist))) {
413
+ throw new DisTubeError("INVALID_TYPE", ["Array<Song>", "PlaylistInfo"], playlist, "playlist");
418
414
  }
419
415
  if (typeof properties !== "undefined" && !isRecord(properties)) {
420
416
  throw new DisTubeError("INVALID_TYPE", "object", properties, "properties");
421
417
  }
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");
418
+ if (Array.isArray(playlist)) {
419
+ this.source = "youtube";
420
+ if (!playlist.length)
421
+ throw new DisTubeError("EMPTY_PLAYLIST");
422
+ this.songs = playlist;
423
+ this.name = this.songs[0].name ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.` : `${this.songs.length} songs playlist`;
424
+ this.thumbnail = this.songs[0].thumbnail;
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;
427
433
  }
428
434
  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
435
  if (properties)
434
436
  for (const [key, value] of Object.entries(properties))
435
437
  this[key] = value;
438
+ this.member = member;
436
439
  this.metadata = metadata;
437
440
  }
438
441
  get duration() {
@@ -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
500
510
  };
501
511
  }
502
512
  };
503
- __name(SearchResult, "SearchResult");
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
526
+ };
527
+ }
528
+ };
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);
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;
849
868
  }
850
869
  };
851
- __name(DisTubeStream, "DisTubeStream");
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.nsfw === "boolean";
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