distube 4.0.0 → 4.0.3

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/README.md CHANGED
@@ -1,17 +1,17 @@
1
1
  <div align="center">
2
2
  <p>
3
- <a href="https://nodei.co/npm/distube/"><img src="https://nodei.co/npm/distube.png?downloads=true&downloadRank=true&stars=true"></a>
3
+ <a href="https://www.npmjs.com/package/distube" target="_blank"><img src="https://nodei.co/npm/distube.png?downloads=true&downloadRank=true&stars=true"></a>
4
4
  </p>
5
5
  <p>
6
- <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/skick1234/DisTube/Testing?label=Tests&logo=github&style=flat-square">
7
- <img alt="node-current" src="https://img.shields.io/node/v/distube?logo=node.js&logoColor=white&style=flat-square">
8
- <img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/distube/peer/discord.js?label=discord.js&logo=discord&logoColor=white&style=flat-square">
9
- <img alt="Depfu" src="https://img.shields.io/depfu/skick1234/DisTube?style=flat-square">
10
- <img alt="Codecov branch" src="https://img.shields.io/codecov/c/github/skick1234/DisTube/main?logo=codecov&logoColor=white&style=flat-square&token=WWDYRRSEQW">
6
+ <a href="https://github.com/skick1234/DisTube/actions" target="_blank"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/skick1234/DisTube/Testing?label=Tests&logo=github&style=flat-square"></a>
7
+ <a href="https://nodejs.org/" target="_blank"><img alt="node-current" src="https://img.shields.io/node/v/distube?logo=node.js&logoColor=white&style=flat-square"></a>
8
+ <a href="https://discord.js.org/" target="_blank"><img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/distube/peer/discord.js?label=discord.js&logo=discord&logoColor=white&style=flat-square"></a>
9
+ <a href="https://depfu.com/github/skick1234/DisTube?project_id=36112" target="_blank"><img alt="Depfu" src="https://img.shields.io/depfu/dependencies/github/skick1234/DisTube?style=flat-square"></a>
10
+ <a href="https://app.codecov.io/gh/skick1234/DisTube" target="_blank"><img alt="Codecov branch" src="https://img.shields.io/codecov/c/github/skick1234/DisTube/main?logo=codecov&logoColor=white&style=flat-square&token=WWDYRRSEQW"></a>
11
11
  <br>
12
- <img alt="npm" src="https://img.shields.io/npm/dt/distube?logo=npm&style=flat-square">
13
- <img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/skick1234/DisTube?logo=github&logoColor=white&style=flat-square">
14
- <img alt="Discord" src="https://img.shields.io/discord/732254550689316914?logo=discord&logoColor=white&style=flat-square">
12
+ <a href="https://www.npmjs.com/package/distube" target="_blank"><img alt="npm" src="https://img.shields.io/npm/dt/distube?logo=npm&style=flat-square"></a>
13
+ <a href="https://github.com/skick1234/DisTube/stargazers" target="_blank"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/skick1234/DisTube?logo=github&logoColor=white&style=flat-square"></a>
14
+ <a href="https://discord.gg/feaDd9h" target="_blank"><img alt="Discord" src="https://img.shields.io/discord/732254550689316914?logo=discord&logoColor=white&style=flat-square"></a>
15
15
  </p>
16
16
  </div>
17
17
 
package/dist/index.d.ts CHANGED
@@ -13,23 +13,44 @@ declare type DisTubeVoiceEvents = {
13
13
  error: (error: Error) => Awaitable;
14
14
  finish: () => Awaitable;
15
15
  };
16
+ declare enum Events {
17
+ ERROR = "error",
18
+ ADD_LIST = "addList",
19
+ ADD_SONG = "addSong",
20
+ PLAY_SONG = "playSong",
21
+ FINISH_SONG = "finishSong",
22
+ EMPTY = "empty",
23
+ FINISH = "finish",
24
+ INIT_QUEUE = "initQueue",
25
+ NO_RELATED = "noRelated",
26
+ DISCONNECT = "disconnect",
27
+ DELETE_QUEUE = "deleteQueue",
28
+ SEARCH_CANCEL = "searchCancel",
29
+ SEARCH_NO_RESULT = "searchNoResult",
30
+ SEARCH_DONE = "searchDone",
31
+ SEARCH_INVALID_ANSWER = "searchInvalidAnswer",
32
+ SEARCH_RESULT = "searchResult"
33
+ }
16
34
  declare type DisTubeEvents = {
17
- error: (channel: GuildTextBasedChannel | undefined, error: Error) => Awaitable;
18
- addList: (queue: Queue, playlist: Playlist) => Awaitable;
19
- addSong: (queue: Queue, song: Song) => Awaitable;
20
- playSong: (queue: Queue, song: Song) => Awaitable;
21
- finishSong: (queue: Queue, song: Song) => Awaitable;
22
- empty: (queue: Queue) => Awaitable;
23
- finish: (queue: Queue) => Awaitable;
24
- initQueue: (queue: Queue) => Awaitable;
25
- noRelated: (queue: Queue) => Awaitable;
26
- disconnect: (queue: Queue) => Awaitable;
27
- deleteQueue: (queue: Queue) => Awaitable;
28
- searchCancel: (message: Message<true>, query: string) => Awaitable;
29
- searchNoResult: (message: Message<true>, query: string) => Awaitable;
30
- searchDone: (message: Message<true>, answer: Message<true>, query: string) => Awaitable;
31
- searchInvalidAnswer: (message: Message<true>, answer: Message<true>, query: string) => Awaitable;
32
- searchResult: (message: Message<true>, results: SearchResult[], query: string) => Awaitable;
35
+ error: [channel: GuildTextBasedChannel | undefined, error: Error];
36
+ addList: [queue: Queue, playlist: Playlist];
37
+ addSong: [queue: Queue, song: Song];
38
+ playSong: [queue: Queue, song: Song];
39
+ finishSong: [queue: Queue, song: Song];
40
+ empty: [queue: Queue];
41
+ finish: [queue: Queue];
42
+ initQueue: [queue: Queue];
43
+ noRelated: [queue: Queue];
44
+ disconnect: [queue: Queue];
45
+ deleteQueue: [queue: Queue];
46
+ searchCancel: [message: Message<true>, query: string];
47
+ searchNoResult: [message: Message<true>, query: string];
48
+ searchDone: [message: Message<true>, answer: Message<true>, query: string];
49
+ searchInvalidAnswer: [message: Message<true>, answer: Message<true>, query: string];
50
+ searchResult: [message: Message<true>, results: SearchResult[], query: string];
51
+ };
52
+ declare type TypedDisTubeEvents = {
53
+ [K in keyof DisTubeEvents]: (...args: DisTubeEvents[K]) => Awaitable;
33
54
  };
34
55
  interface Filter {
35
56
  name: string;
@@ -56,6 +77,7 @@ interface DisTubeOptions {
56
77
  emitAddListWhenCreatingQueue?: boolean;
57
78
  joinNewVoiceChannel?: boolean;
58
79
  streamType?: StreamType;
80
+ directLink?: boolean;
59
81
  }
60
82
  declare type GuildIdResolvable = Queue | DisTubeVoice | Snowflake | Message | GuildTextBasedChannel | VoiceBasedChannel | VoiceState | Guild | GuildMember | Interaction | string;
61
83
  interface OtherSongInfo {
@@ -159,6 +181,7 @@ declare const defaultOptions: {
159
181
  emitAddListWhenCreatingQueue: boolean;
160
182
  joinNewVoiceChannel: boolean;
161
183
  streamType: StreamType;
184
+ directLink: boolean;
162
185
  };
163
186
 
164
187
  declare const ERROR_MESSAGES: {
@@ -267,12 +290,12 @@ declare class SearchResultVideo extends ISearchResult {
267
290
  thumbnail: string;
268
291
  constructor(info: Video);
269
292
  }
293
+ declare type SearchResult = SearchResultVideo | SearchResultPlaylist;
270
294
  declare class SearchResultPlaylist extends ISearchResult {
271
295
  type: SearchResultType.PLAYLIST;
272
296
  length: number;
273
297
  constructor(info: Playlist$1);
274
298
  }
275
- declare type SearchResult = SearchResultVideo | SearchResultPlaylist;
276
299
 
277
300
  declare class Song<T = unknown> {
278
301
  #private;
@@ -335,6 +358,7 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
335
358
  emittedError: boolean;
336
359
  isDisconnected: boolean;
337
360
  constructor(voiceManager: DisTubeVoiceManager, channel: VoiceBasedChannel);
361
+ get channelId(): string | undefined;
338
362
  get channel(): VoiceBasedChannel;
339
363
  set channel(channel: VoiceBasedChannel);
340
364
  join(channel?: VoiceBasedChannel): Promise<DisTubeVoice>;
@@ -431,6 +455,7 @@ declare class Options {
431
455
  emitAddListWhenCreatingQueue: boolean;
432
456
  joinNewVoiceChannel: boolean;
433
457
  streamType: StreamType;
458
+ directLink: boolean;
434
459
  constructor(options: DisTubeOptions);
435
460
  }
436
461
 
@@ -540,6 +565,8 @@ declare function isClientInstance(client: any): client is Client;
540
565
  declare function checkInvalidKey(target: Record<string, any>, source: Record<string, any> | string[], sourceName: string): void;
541
566
  declare function isObject(obj: any): obj is object;
542
567
  declare function isRecord<T = unknown>(obj: any): obj is Record<string, T>;
568
+ declare type KeyOf<T> = T extends object ? (keyof T)[] : [];
569
+ declare function objectKeys<T>(obj: T): KeyOf<T>;
543
570
 
544
571
  declare class DirectLinkPlugin extends ExtractorPlugin {
545
572
  validate(url: string): Promise<boolean>;
@@ -550,7 +577,7 @@ declare class DirectLinkPlugin extends ExtractorPlugin {
550
577
  }
551
578
 
552
579
  declare const version: string;
553
- declare class DisTube extends TypedEmitter<DisTubeEvents> {
580
+ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
554
581
  readonly handler: DisTubeHandler;
555
582
  readonly options: Options;
556
583
  readonly client: Client;
@@ -598,4 +625,4 @@ declare class DisTube extends TypedEmitter<DisTubeEvents> {
598
625
  emitError(error: Error, channel?: GuildTextBasedChannel): void;
599
626
  }
600
627
 
601
- export { Awaitable, BaseManager, Chapter, CustomPlaylistOptions, CustomPlugin, DirectLinkPlugin, DisTube, DisTubeBase, DisTubeError, DisTubeEvents, DisTubeHandler, DisTubeOptions, DisTubeStream, DisTubeVoice, DisTubeVoiceEvents, DisTubeVoiceManager, ExtractorPlugin, Filter, FilterManager, FilterResolvable, Filters, GuildIdManager, GuildIdResolvable, Options, OtherSongInfo, PlayHandlerOptions, PlayOptions, Playlist, PlaylistInfo, Plugin, PluginType, Queue, QueueManager, RelatedSong, RepeatMode, ResolveOptions, ResolvePlaylistOptions, SearchResult, SearchResultPlaylist, SearchResultType, SearchResultVideo, Song, StreamType, TaskQueue, checkIntents, checkInvalidKey, chooseBestVideoFormat, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isObject, isRecord, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isURL, isVoiceChannelEmpty, parseNumber, resolveGuildId, toSecond, version };
628
+ export { Awaitable, BaseManager, Chapter, CustomPlaylistOptions, CustomPlugin, DirectLinkPlugin, DisTube, DisTubeBase, DisTubeError, DisTubeEvents, DisTubeHandler, DisTubeOptions, DisTubeStream, DisTubeVoice, DisTubeVoiceEvents, DisTubeVoiceManager, Events, ExtractorPlugin, Filter, FilterManager, FilterResolvable, Filters, GuildIdManager, GuildIdResolvable, Options, OtherSongInfo, PlayHandlerOptions, PlayOptions, Playlist, PlaylistInfo, Plugin, PluginType, Queue, QueueManager, RelatedSong, RepeatMode, ResolveOptions, ResolvePlaylistOptions, SearchResult, SearchResultPlaylist, SearchResultType, SearchResultVideo, Song, StreamType, TaskQueue, TypedDisTubeEvents, checkIntents, checkInvalidKey, chooseBestVideoFormat, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isObject, isRecord, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isURL, isVoiceChannelEmpty, objectKeys, parseNumber, resolveGuildId, toSecond, version };
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- "use strict";
3
2
  var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
5
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -57,15 +56,11 @@ var require_package = __commonJS({
57
56
  "package.json"(exports, module2) {
58
57
  module2.exports = {
59
58
  name: "distube",
60
- version: "4.0.0",
59
+ version: "4.0.3",
61
60
  description: "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
62
61
  main: "./dist/index.js",
63
- module: "./dist/index.mjs",
64
62
  types: "./dist/index.d.ts",
65
- exports: {
66
- import: "./dist/index.mjs",
67
- require: "./dist/index.js"
68
- },
63
+ exports: "./dist/index.js",
69
64
  directories: {
70
65
  lib: "src",
71
66
  test: "tests"
@@ -81,7 +76,7 @@ var require_package = __commonJS({
81
76
  prettier: 'prettier --write "**/*.{ts,json,yml,yaml,md}"',
82
77
  build: "tsup",
83
78
  "build:check": "tsc --noEmit",
84
- update: "ncu -u --dep dev,prod && yarn up '**' -R",
79
+ update: "ncu -u && yarn up '**' -R",
85
80
  postinstall: "husky install",
86
81
  prepublishOnly: "yarn lint && yarn test",
87
82
  prepack: "yarn build && pinst --disable",
@@ -130,21 +125,21 @@ var require_package = __commonJS({
130
125
  undici: "^5.8.0"
131
126
  },
132
127
  devDependencies: {
133
- "@babel/core": "^7.18.6",
128
+ "@babel/core": "^7.18.9",
134
129
  "@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",
130
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
131
+ "@babel/preset-env": "^7.18.9",
137
132
  "@babel/preset-typescript": "^7.18.6",
138
133
  "@commitlint/cli": "^17.0.3",
139
134
  "@commitlint/config-conventional": "^17.0.3",
140
- "@discordjs/voice": "latest",
135
+ "@discordjs/voice": "^0.11.0",
141
136
  "@distube/docgen": "distubejs/docgen",
142
137
  "@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",
138
+ "@types/node": "^18.6.0",
139
+ "@typescript-eslint/eslint-plugin": "^5.30.7",
140
+ "@typescript-eslint/parser": "^5.30.7",
146
141
  "babel-jest": "^28.1.3",
147
- "discord.js": "latest",
142
+ "discord.js": "^14.0.3",
148
143
  eslint: "^8.20.0",
149
144
  "eslint-config-distube": "^1.6.4",
150
145
  "eslint-config-prettier": "^8.5.0",
@@ -154,7 +149,7 @@ var require_package = __commonJS({
154
149
  jest: "^28.1.3",
155
150
  "jsdoc-babel": "^0.5.0",
156
151
  "nano-staged": "^0.8.0",
157
- "npm-check-updates": "^15.3.4",
152
+ "npm-check-updates": "^16.0.0",
158
153
  pinst: "^3.0.0",
159
154
  prettier: "^2.7.1",
160
155
  tsup: "^6.1.3",
@@ -200,6 +195,7 @@ __export(src_exports, {
200
195
  DisTubeStream: () => DisTubeStream,
201
196
  DisTubeVoice: () => DisTubeVoice,
202
197
  DisTubeVoiceManager: () => DisTubeVoiceManager,
198
+ Events: () => Events,
203
199
  ExtractorPlugin: () => ExtractorPlugin,
204
200
  FilterManager: () => FilterManager,
205
201
  GuildIdManager: () => GuildIdManager,
@@ -234,6 +230,7 @@ __export(src_exports, {
234
230
  isTextChannelInstance: () => isTextChannelInstance,
235
231
  isURL: () => isURL,
236
232
  isVoiceChannelEmpty: () => isVoiceChannelEmpty,
233
+ objectKeys: () => objectKeys,
237
234
  parseNumber: () => parseNumber,
238
235
  resolveGuildId: () => resolveGuildId,
239
236
  toSecond: () => toSecond,
@@ -242,6 +239,25 @@ __export(src_exports, {
242
239
  module.exports = __toCommonJS(src_exports);
243
240
 
244
241
  // src/type.ts
242
+ var Events = /* @__PURE__ */ ((Events2) => {
243
+ Events2["ERROR"] = "error";
244
+ Events2["ADD_LIST"] = "addList";
245
+ Events2["ADD_SONG"] = "addSong";
246
+ Events2["PLAY_SONG"] = "playSong";
247
+ Events2["FINISH_SONG"] = "finishSong";
248
+ Events2["EMPTY"] = "empty";
249
+ Events2["FINISH"] = "finish";
250
+ Events2["INIT_QUEUE"] = "initQueue";
251
+ Events2["NO_RELATED"] = "noRelated";
252
+ Events2["DISCONNECT"] = "disconnect";
253
+ Events2["DELETE_QUEUE"] = "deleteQueue";
254
+ Events2["SEARCH_CANCEL"] = "searchCancel";
255
+ Events2["SEARCH_NO_RESULT"] = "searchNoResult";
256
+ Events2["SEARCH_DONE"] = "searchDone";
257
+ Events2["SEARCH_INVALID_ANSWER"] = "searchInvalidAnswer";
258
+ Events2["SEARCH_RESULT"] = "searchResult";
259
+ return Events2;
260
+ })(Events || {});
245
261
  var RepeatMode = /* @__PURE__ */ ((RepeatMode2) => {
246
262
  RepeatMode2[RepeatMode2["DISABLED"] = 0] = "DISABLED";
247
263
  RepeatMode2[RepeatMode2["SONG"] = 1] = "SONG";
@@ -297,7 +313,8 @@ var defaultOptions = {
297
313
  emitAddSongWhenCreatingQueue: true,
298
314
  emitAddListWhenCreatingQueue: true,
299
315
  joinNewVoiceChannel: true,
300
- streamType: 0 /* OPUS */
316
+ streamType: 0 /* OPUS */,
317
+ directLink: true
301
318
  };
302
319
 
303
320
  // src/struct/DisTubeError.ts
@@ -422,6 +439,7 @@ var Playlist = class {
422
439
  this.songs = playlist;
423
440
  this.name = this.songs[0].name ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.` : `${this.songs.length} songs playlist`;
424
441
  this.thumbnail = this.songs[0].thumbnail;
442
+ this.member = member || void 0;
425
443
  } else {
426
444
  this.source = (playlist.source || "youtube").toLowerCase();
427
445
  if (!Array.isArray(playlist.songs) || !playlist.songs.length)
@@ -430,12 +448,12 @@ var Playlist = class {
430
448
  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
449
  this.url = playlist.url || playlist.webpage_url;
432
450
  this.thumbnail = playlist.thumbnail || this.songs[0].thumbnail;
451
+ this.member = member || playlist.member || void 0;
433
452
  }
434
453
  this.songs.map((s) => s.constructor.name === "Song" && (s.playlist = this));
435
454
  if (properties)
436
455
  for (const [key, value] of Object.entries(properties))
437
456
  this[key] = value;
438
- this.member = member;
439
457
  this.metadata = metadata;
440
458
  }
441
459
  get duration() {
@@ -697,6 +715,7 @@ var DisTubeBase = class {
697
715
  __name(DisTubeBase, "DisTubeBase");
698
716
 
699
717
  // src/core/DisTubeVoice.ts
718
+ var import_discord = require("discord.js");
700
719
  var import_tiny_typed_emitter = require("tiny-typed-emitter");
701
720
  var import_voice = require("@discordjs/voice");
702
721
  var _channel, _volume, _br, br_fn, _join, join_fn;
@@ -750,7 +769,23 @@ var DisTubeVoice = class extends import_tiny_typed_emitter.TypedEmitter {
750
769
  }).on("error", () => void 0);
751
770
  this.connection.subscribe(this.audioPlayer);
752
771
  }
772
+ get channelId() {
773
+ return this.connection?.joinConfig?.channelId ?? void 0;
774
+ }
753
775
  get channel() {
776
+ if (!this.channelId)
777
+ return __privateGet(this, _channel);
778
+ if (__privateGet(this, _channel)?.id === this.channelId)
779
+ return __privateGet(this, _channel);
780
+ const channel = this.voices.client.channels.cache.get(this.channelId);
781
+ if (!channel)
782
+ return __privateGet(this, _channel);
783
+ for (const type of import_discord.Constants.VoiceBasedChannelTypes) {
784
+ if (channel.type === type) {
785
+ __privateSet(this, _channel, channel);
786
+ return channel;
787
+ }
788
+ }
754
789
  return __privateGet(this, _channel);
755
790
  }
756
791
  set channel(channel) {
@@ -761,7 +796,7 @@ var DisTubeVoice = class extends import_tiny_typed_emitter.TypedEmitter {
761
796
  throw new DisTubeError("VOICE_DIFFERENT_GUILD");
762
797
  if (channel.client.user?.id !== this.voices.client.user?.id)
763
798
  throw new DisTubeError("VOICE_DIFFERENT_CLIENT");
764
- if (channel.id === __privateGet(this, _channel)?.id)
799
+ if (channel.id === this.channelId)
765
800
  return;
766
801
  if (!channel.joinable) {
767
802
  if (channel.full)
@@ -886,11 +921,11 @@ join_fn = /* @__PURE__ */ __name(function(channel) {
886
921
  }, "#join");
887
922
 
888
923
  // src/core/manager/BaseManager.ts
889
- var import_discord = require("discord.js");
924
+ var import_discord2 = require("discord.js");
890
925
  var BaseManager = class extends DisTubeBase {
891
926
  constructor() {
892
927
  super(...arguments);
893
- __publicField(this, "collection", new import_discord.Collection());
928
+ __publicField(this, "collection", new import_discord2.Collection());
894
929
  }
895
930
  get size() {
896
931
  return this.collection.size;
@@ -1124,7 +1159,7 @@ voiceEventHandler_fn = /* @__PURE__ */ __name(function(queue) {
1124
1159
  error: (error) => __privateMethod(this, _handlePlayingError, handlePlayingError_fn).call(this, queue, error),
1125
1160
  finish: () => __privateMethod(this, _handleSongFinish, handleSongFinish_fn).call(this, queue)
1126
1161
  };
1127
- for (const event of Object.keys(queue._listeners)) {
1162
+ for (const event of objectKeys(queue._listeners)) {
1128
1163
  queue.voice.on(event, queue._listeners[event]);
1129
1164
  }
1130
1165
  }, "#voiceEventHandler");
@@ -1472,6 +1507,7 @@ var Options = class {
1472
1507
  __publicField(this, "emitAddListWhenCreatingQueue");
1473
1508
  __publicField(this, "joinNewVoiceChannel");
1474
1509
  __publicField(this, "streamType");
1510
+ __publicField(this, "directLink");
1475
1511
  if (typeof options !== "object" || Array.isArray(options)) {
1476
1512
  throw new DisTubeError("INVALID_TYPE", "object", options, "DisTubeOptions");
1477
1513
  }
@@ -1494,6 +1530,7 @@ var Options = class {
1494
1530
  this.emitAddListWhenCreatingQueue = opts.emitAddListWhenCreatingQueue;
1495
1531
  this.joinNewVoiceChannel = opts.joinNewVoiceChannel;
1496
1532
  this.streamType = opts.streamType;
1533
+ this.directLink = opts.directLink;
1497
1534
  checkInvalidKey(opts, this, "DisTubeOptions");
1498
1535
  __privateMethod(this, _validateOptions, validateOptions_fn).call(this);
1499
1536
  }
@@ -1555,6 +1592,9 @@ validateOptions_fn = /* @__PURE__ */ __name(function(options = this) {
1555
1592
  if (typeof options.streamType !== "number" || isNaN(options.streamType) || !StreamType[options.streamType]) {
1556
1593
  throw new DisTubeError("INVALID_TYPE", "StreamType", options.streamType, "DisTubeOptions.streamType");
1557
1594
  }
1595
+ if (typeof options.directLink !== "boolean") {
1596
+ throw new DisTubeError("INVALID_TYPE", "boolean", options.directLink, "DisTubeOptions.directLink");
1597
+ }
1558
1598
  }, "#validateOptions");
1559
1599
 
1560
1600
  // src/core/DisTubeStream.ts
@@ -1875,7 +1915,7 @@ var Queue = class extends DisTubeBase {
1875
1915
  this.songs = [];
1876
1916
  this.previousSongs = [];
1877
1917
  if (this._listeners) {
1878
- for (const event of Object.keys(this._listeners)) {
1918
+ for (const event of objectKeys(this._listeners)) {
1879
1919
  this.voice.removeListener(event, this._listeners[event]);
1880
1920
  }
1881
1921
  }
@@ -1951,7 +1991,7 @@ __name(ExtractorPlugin, "ExtractorPlugin");
1951
1991
 
1952
1992
  // src/util.ts
1953
1993
  var import_url = require("url");
1954
- var import_discord2 = require("discord.js");
1994
+ var import_discord3 = require("discord.js");
1955
1995
  var formatInt = /* @__PURE__ */ __name((int) => int < 10 ? `0${int}` : int, "formatInt");
1956
1996
  function formatDuration(sec) {
1957
1997
  if (!sec || !Number(sec))
@@ -2005,8 +2045,8 @@ function isURL(input) {
2005
2045
  }
2006
2046
  __name(isURL, "isURL");
2007
2047
  function checkIntents(options) {
2008
- const intents = new import_discord2.IntentsBitField(options.intents);
2009
- if (!intents.has(import_discord2.GatewayIntentBits.GuildVoiceStates))
2048
+ const intents = new import_discord3.IntentsBitField(options.intents);
2049
+ if (!intents.has(import_discord3.GatewayIntentBits.GuildVoiceStates))
2010
2050
  throw new DisTubeError("MISSING_INTENTS", "GuildVoiceStates");
2011
2051
  }
2012
2052
  __name(checkIntents, "checkIntents");
@@ -2024,7 +2064,7 @@ function isVoiceChannelEmpty(voiceState) {
2024
2064
  __name(isVoiceChannelEmpty, "isVoiceChannelEmpty");
2025
2065
  function isSnowflake(id) {
2026
2066
  try {
2027
- return import_discord2.SnowflakeUtil.deconstruct(id).timestamp > import_discord2.SnowflakeUtil.epoch;
2067
+ return import_discord3.SnowflakeUtil.deconstruct(id).timestamp > import_discord3.SnowflakeUtil.epoch;
2028
2068
  } catch {
2029
2069
  return false;
2030
2070
  }
@@ -2035,15 +2075,15 @@ function isMemberInstance(member) {
2035
2075
  }
2036
2076
  __name(isMemberInstance, "isMemberInstance");
2037
2077
  function isTextChannelInstance(channel) {
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";
2078
+ return !!channel && isSnowflake(channel.id) && isSnowflake(channel.guildId) && typeof channel.name === "string" && import_discord3.Constants.TextBasedChannelTypes.includes(channel.type) && typeof channel.nsfw === "boolean" && "messages" in channel && typeof channel.send === "function";
2039
2079
  }
2040
2080
  __name(isTextChannelInstance, "isTextChannelInstance");
2041
2081
  function isMessageInstance(message) {
2042
- return !!message && isSnowflake(message.id) && isSnowflake(message.guildId) && isMemberInstance(message.member) && isTextChannelInstance(message.channel) && import_discord2.Constants.NonSystemMessageTypes.includes(message.type) && message.member.id === message.author?.id;
2082
+ return !!message && isSnowflake(message.id) && isSnowflake(message.guildId) && isMemberInstance(message.member) && isTextChannelInstance(message.channel) && import_discord3.Constants.NonSystemMessageTypes.includes(message.type) && message.member.id === message.author?.id;
2043
2083
  }
2044
2084
  __name(isMessageInstance, "isMessageInstance");
2045
2085
  function isSupportedVoiceChannel(channel) {
2046
- return !!channel && isSnowflake(channel.id) && isSnowflake(channel.guildId) && import_discord2.Constants.VoiceBasedChannelTypes.includes(channel.type);
2086
+ return !!channel && isSnowflake(channel.id) && isSnowflake(channel.guildId) && import_discord3.Constants.VoiceBasedChannelTypes.includes(channel.type);
2047
2087
  }
2048
2088
  __name(isSupportedVoiceChannel, "isSupportedVoiceChannel");
2049
2089
  function isGuildInstance(guild) {
@@ -2075,8 +2115,8 @@ __name(isClientInstance, "isClientInstance");
2075
2115
  function checkInvalidKey(target, source, sourceName) {
2076
2116
  if (!isObject(target))
2077
2117
  throw new DisTubeError("INVALID_TYPE", "object", target, sourceName);
2078
- const sourceKeys = Array.isArray(source) ? source : Object.keys(source);
2079
- const invalidKey = Object.keys(target).find((key) => !sourceKeys.includes(key));
2118
+ const sourceKeys = Array.isArray(source) ? source : objectKeys(source);
2119
+ const invalidKey = objectKeys(target).find((key) => !sourceKeys.includes(key));
2080
2120
  if (invalidKey)
2081
2121
  throw new DisTubeError("INVALID_KEY", sourceName, invalidKey);
2082
2122
  }
@@ -2089,15 +2129,24 @@ function isRecord(obj) {
2089
2129
  return isObject(obj);
2090
2130
  }
2091
2131
  __name(isRecord, "isRecord");
2132
+ function objectKeys(obj) {
2133
+ if (!isObject(obj))
2134
+ return [];
2135
+ return Object.keys(obj);
2136
+ }
2137
+ __name(objectKeys, "objectKeys");
2092
2138
 
2093
2139
  // src/plugin/DirectLink.ts
2094
2140
  var import_undici = require("undici");
2095
2141
  var DirectLinkPlugin = class extends ExtractorPlugin {
2096
2142
  async validate(url) {
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;
2143
+ try {
2144
+ const headers = await (0, import_undici.request)(url, { method: "HEAD" }).then((res) => res.headers);
2145
+ const type = headers["content-type"];
2146
+ if (type?.startsWith("audio"))
2147
+ return true;
2148
+ } catch {
2149
+ }
2101
2150
  return false;
2102
2151
  }
2103
2152
  async resolve(url, options = {}) {
@@ -2135,7 +2184,8 @@ var DisTube = class extends import_tiny_typed_emitter2.TypedEmitter {
2135
2184
  this.handler = new DisTubeHandler(this);
2136
2185
  this.queues = new QueueManager(this);
2137
2186
  this.filters = { ...defaultFilters, ...this.options.customFilters };
2138
- this.options.plugins.push(new DirectLinkPlugin());
2187
+ if (this.options.directLink)
2188
+ this.options.plugins.push(new DirectLinkPlugin());
2139
2189
  this.options.plugins.map((p) => p.init(this));
2140
2190
  this.extractorPlugins = this.options.plugins.filter((p) => p.type === "extractor");
2141
2191
  this.customPlugins = this.options.plugins.filter((p) => p.type === "custom");
@@ -2367,6 +2417,7 @@ __name(DisTube, "DisTube");
2367
2417
  DisTubeStream,
2368
2418
  DisTubeVoice,
2369
2419
  DisTubeVoiceManager,
2420
+ Events,
2370
2421
  ExtractorPlugin,
2371
2422
  FilterManager,
2372
2423
  GuildIdManager,
@@ -2400,6 +2451,7 @@ __name(DisTube, "DisTube");
2400
2451
  isTextChannelInstance,
2401
2452
  isURL,
2402
2453
  isVoiceChannelEmpty,
2454
+ objectKeys,
2403
2455
  parseNumber,
2404
2456
  resolveGuildId,
2405
2457
  toSecond,