distube 4.2.2 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,33 +1,39 @@
1
- import * as ytdl from '@distube/ytdl-core';
2
- import ytdl__default, { Cookie } from '@distube/ytdl-core';
3
1
  import * as discord_js from 'discord.js';
4
- import { GuildTextBasedChannel, Message, Snowflake, VoiceBasedChannel, VoiceState, Guild, GuildMember, Interaction, Client, Collection, ClientOptions } from 'discord.js';
5
- import ytpl from '@distube/ytpl';
6
- import { Video, Playlist as Playlist$1 } from '@distube/ytsr';
2
+ import { Snowflake, Message, GuildTextBasedChannel, VoiceBasedChannel, VoiceState, Guild, GuildMember, Interaction, Client, Collection, ClientOptions } from 'discord.js';
7
3
  import { TypedEmitter } from 'tiny-typed-emitter';
8
- import { AudioPlayer, VoiceConnection, AudioResource, StreamType as StreamType$1 } from '@discordjs/voice';
9
- import { PassThrough } from 'node:stream';
4
+ import { AudioPlayer, VoiceConnection, AudioResource } from '@discordjs/voice';
5
+ import { Transform, TransformCallback } from 'stream';
10
6
  import { ChildProcess } from 'child_process';
11
7
 
12
8
  type Awaitable<T = any> = T | PromiseLike<T>;
9
+ declare enum Events {
10
+ ERROR = "error",
11
+ ADD_LIST = "addList",
12
+ ADD_SONG = "addSong",
13
+ PLAY_SONG = "playSong",
14
+ FINISH_SONG = "finishSong",
15
+ EMPTY = "empty",
16
+ FINISH = "finish",
17
+ INIT_QUEUE = "initQueue",
18
+ NO_RELATED = "noRelated",
19
+ DISCONNECT = "disconnect",
20
+ DELETE_QUEUE = "deleteQueue",
21
+ FFMPEG_DEBUG = "ffmpegDebug",
22
+ DEBUG = "debug"
23
+ }
13
24
  type DisTubeEvents = {
14
- addList: [queue: Queue, playlist: Playlist];
15
- addSong: [queue: Queue, song: Song];
16
- deleteQueue: [queue: Queue];
17
- disconnect: [queue: Queue];
18
- empty: [queue: Queue];
19
- error: [channel: GuildTextBasedChannel | undefined, error: Error];
20
- ffmpegDebug: [debug: string];
21
- finish: [queue: Queue];
22
- finishSong: [queue: Queue, song: Song];
23
- initQueue: [queue: Queue];
24
- noRelated: [queue: Queue];
25
- playSong: [queue: Queue, song: Song];
26
- searchCancel: [message: Message<true>, query: string];
27
- searchDone: [message: Message<true>, answer: Message<true>, query: string];
28
- searchInvalidAnswer: [message: Message<true>, answer: Message<true>, query: string];
29
- searchNoResult: [message: Message<true>, query: string];
30
- searchResult: [message: Message<true>, results: SearchResult[], query: string];
25
+ [Events.ADD_LIST]: [queue: Queue, playlist: Playlist];
26
+ [Events.ADD_SONG]: [queue: Queue, song: Song];
27
+ [Events.DELETE_QUEUE]: [queue: Queue];
28
+ [Events.DISCONNECT]: [queue: Queue];
29
+ [Events.ERROR]: [error: Error, queue: Queue, song: Song | undefined];
30
+ [Events.FFMPEG_DEBUG]: [debug: string];
31
+ [Events.DEBUG]: [debug: string];
32
+ [Events.FINISH]: [queue: Queue];
33
+ [Events.FINISH_SONG]: [queue: Queue, song: Song];
34
+ [Events.INIT_QUEUE]: [queue: Queue];
35
+ [Events.NO_RELATED]: [queue: Queue, error: DisTubeError];
36
+ [Events.PLAY_SONG]: [queue: Queue, song: Song];
31
37
  };
32
38
  type TypedDisTubeEvents = {
33
39
  [K in keyof DisTubeEvents]: (...args: DisTubeEvents[K]) => Awaitable;
@@ -39,7 +45,6 @@ type DisTubeVoiceEvents = {
39
45
  };
40
46
  /**
41
47
  * An FFmpeg audio filter object
42
- *
43
48
  * ```ts
44
49
  * {
45
50
  * name: "bassboost",
@@ -59,24 +64,20 @@ interface Filter {
59
64
  }
60
65
  /**
61
66
  * Data that resolves to give an FFmpeg audio filter. This can be:
62
- *
63
67
  * - A name of a default filters or custom filters (`string`)
64
68
  * - A {@link Filter} object
65
- *
66
69
  * @see {@link defaultFilters}
67
70
  * @see {@link DisTubeOptions|DisTubeOptions.customFilters}
68
71
  */
69
72
  type FilterResolvable = string | Filter;
70
73
  /**
71
74
  * FFmpeg Filters
72
- *
73
75
  * ```ts
74
76
  * {
75
77
  * "Filter Name": "Filter Value",
76
78
  * "bassboost": "bass=g=10"
77
79
  * }
78
- * ```ts
79
- *
80
+ * ```
80
81
  * @see {@link defaultFilters}
81
82
  */
82
83
  type Filters = Record<string, string>;
@@ -85,59 +86,24 @@ type Filters = Record<string, string>;
85
86
  */
86
87
  type DisTubeOptions = {
87
88
  /**
88
- * DisTube plugins
89
+ * DisTube plugins.
90
+ * The order of this effects the priority of the plugins when verifying the input.
89
91
  */
90
- plugins?: (CustomPlugin | ExtractorPlugin)[];
92
+ plugins?: DisTubePlugin[];
91
93
  /**
92
- * Whether or not emitting {@link DisTube#playSong} event when looping a song
94
+ * Whether or not emitting {@link Events.PLAY_SONG} event when looping a song
93
95
  * or next song is the same as the previous one
94
96
  */
95
97
  emitNewSongOnly?: boolean;
96
- /**
97
- * Whether or not leaving voice channel if the voice channel is empty after {@link
98
- * DisTubeOptions}.emptyCooldown seconds
99
- */
100
- leaveOnEmpty?: boolean;
101
- /**
102
- * Whether or not leaving voice channel when the queue ends
103
- */
104
- leaveOnFinish?: boolean;
105
- /**
106
- * Whether or not leaving voice channel after using {@link DisTube#stop} function
107
- */
108
- leaveOnStop?: boolean;
109
- /**
110
- * Built-in leave on empty cooldown in seconds (When leaveOnEmpty is true)
111
- */
112
- emptyCooldown?: number;
113
98
  /**
114
99
  * Whether or not saving the previous songs of the queue and enable {@link
115
- * DisTube#previous} method
100
+ * DisTube#previous} method. Disable it may help to reduce the memory usage
116
101
  */
117
102
  savePreviousSongs?: boolean;
118
- /**
119
- * Limit of search results emits in {@link DisTube#searchResult} event when
120
- * {@link DisTube#play} method executed. If `searchSongs <= 1`, play the first
121
- * result
122
- */
123
- searchSongs?: number;
124
- /**
125
- * Built-in search cooldown in seconds (When searchSongs is bigger than 0)
126
- */
127
- searchCooldown?: number;
128
- /**
129
- * YouTube cookies. Guide: {@link
130
- * https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
131
- */
132
- youtubeCookie?: Cookie[] | string;
133
103
  /**
134
104
  * Override {@link defaultFilters} or add more ffmpeg filters
135
105
  */
136
106
  customFilters?: Filters;
137
- /**
138
- * `ytdl-core` get info options
139
- */
140
- ytdlOptions?: ytdl__default.downloadOptions;
141
107
  /**
142
108
  * Whether or not playing age-restricted content and disabling safe search in
143
109
  * non-NSFW channel
@@ -156,25 +122,6 @@ type DisTubeOptions = {
156
122
  * method
157
123
  */
158
124
  joinNewVoiceChannel?: boolean;
159
- /**
160
- * Decide the {@link DisTubeStream#type} will be used (Not the same as {@link
161
- * DisTubeStream#type})
162
- */
163
- streamType?: StreamType;
164
- /**
165
- * Whether or not playing a song with direct link
166
- */
167
- directLink?: boolean;
168
- /**
169
- * FFmpeg path
170
- * @deprecated
171
- */
172
- ffmpegPath?: string;
173
- /**
174
- * FFmpeg default arguments
175
- * @deprecated
176
- */
177
- ffmpegDefaultArgs?: FFmpegArgs;
178
125
  /**
179
126
  * FFmpeg options
180
127
  */
@@ -186,16 +133,11 @@ type DisTubeOptions = {
186
133
  /**
187
134
  * FFmpeg default arguments
188
135
  */
189
- args?: {
190
- global?: FFmpegArgs;
191
- input?: FFmpegArgs;
192
- output?: FFmpegArgs;
193
- };
136
+ args?: Partial<FFmpegArgs>;
194
137
  };
195
138
  };
196
139
  /**
197
140
  * Data that can be resolved to give a guild id string. This can be:
198
- *
199
141
  * - A guild id string | a guild {@link https://discord.js.org/#/docs/main/stable/class/Snowflake|Snowflake}
200
142
  * - A {@link https://discord.js.org/#/docs/main/stable/class/Guild | Guild}
201
143
  * - A {@link https://discord.js.org/#/docs/main/stable/class/Message | Message}
@@ -213,55 +155,34 @@ type DisTubeOptions = {
213
155
  * - A {@link Queue}
214
156
  */
215
157
  type GuildIdResolvable = Queue | DisTubeVoice | Snowflake | Message | GuildTextBasedChannel | VoiceBasedChannel | VoiceState | Guild | GuildMember | Interaction | string;
216
- interface OtherSongInfo {
217
- src: string;
158
+ interface SongInfo {
159
+ plugin: DisTubePlugin | null;
160
+ source: string;
161
+ playFromSource: boolean;
162
+ streamURL?: string;
218
163
  id?: string;
219
- title?: string;
220
164
  name?: string;
221
- is_live?: boolean;
222
165
  isLive?: boolean;
223
- _duration_raw?: string | number;
224
- duration?: string | number;
225
- webpage_url?: string;
226
- url: string;
166
+ duration?: number;
167
+ url?: string;
227
168
  thumbnail?: string;
228
- related?: RelatedSong[];
229
- view_count?: string | number;
230
- views?: string | number;
231
- like_count?: string | number;
232
- likes?: string | number;
233
- dislike_count?: string | number;
234
- dislikes?: string | number;
235
- repost_count?: string | number;
236
- reposts?: string | number;
237
- uploader?: string | {
238
- name: string;
239
- url: string;
169
+ views?: number;
170
+ likes?: number;
171
+ dislikes?: number;
172
+ reposts?: number;
173
+ uploader?: {
174
+ name?: string;
175
+ url?: string;
240
176
  };
241
- uploader_url?: string;
242
- age_limit?: string | number;
243
- chapters?: Chapter[];
244
- age_restricted?: boolean;
245
- }
246
- interface Chapter {
247
- title: string;
248
- start_time: number;
177
+ ageRestricted?: boolean;
249
178
  }
250
179
  interface PlaylistInfo {
251
180
  source: string;
252
- member?: GuildMember;
253
181
  songs: Song[];
182
+ id?: string;
254
183
  name?: string;
255
184
  url?: string;
256
185
  thumbnail?: string;
257
- /**
258
- * @deprecated Use {@link PlaylistInfo#name}
259
- */
260
- title?: string;
261
- /**
262
- * @deprecated Use {@link PlaylistInfo#url}
263
- */
264
- webpage_url?: string;
265
186
  }
266
187
  type RelatedSong = Omit<Song, "related">;
267
188
  type PlayHandlerOptions = {
@@ -280,7 +201,7 @@ type PlayHandlerOptions = {
280
201
  */
281
202
  textChannel?: GuildTextBasedChannel;
282
203
  };
283
- interface PlayOptions extends PlayHandlerOptions, ResolveOptions<any> {
204
+ interface PlayOptions<T = unknown> extends PlayHandlerOptions, ResolveOptions<T> {
284
205
  /**
285
206
  * Called message (For built-in search events. If this is a {@link
286
207
  * https://developer.mozilla.org/en-US/docs/Glossary/Falsy | falsy value}, it will
@@ -309,10 +230,6 @@ interface CustomPlaylistOptions {
309
230
  * A guild member creating the playlist
310
231
  */
311
232
  member?: GuildMember;
312
- /**
313
- * Additional properties such as `name`
314
- */
315
- properties?: Record<string, any>;
316
233
  /**
317
234
  * Whether or not fetch the songs in parallel
318
235
  */
@@ -321,10 +238,25 @@ interface CustomPlaylistOptions {
321
238
  * Metadata
322
239
  */
323
240
  metadata?: any;
241
+ /**
242
+ * Playlist name
243
+ */
244
+ name?: string;
245
+ /**
246
+ * Playlist source
247
+ */
248
+ source?: string;
249
+ /**
250
+ * Playlist url
251
+ */
252
+ url?: string;
253
+ /**
254
+ * Playlist thumbnail
255
+ */
256
+ thumbnail?: string;
324
257
  }
325
258
  /**
326
259
  * The repeat mode of a {@link Queue}
327
- *
328
260
  * - `DISABLED` = 0
329
261
  * - `SONG` = 1
330
262
  * - `QUEUE` = 2
@@ -336,61 +268,37 @@ declare enum RepeatMode {
336
268
  }
337
269
  /**
338
270
  * All available plugin types:
339
- *
340
- * - `CUSTOM` = `"custom"`: {@link CustomPlugin}
341
271
  * - `EXTRACTOR` = `"extractor"`: {@link ExtractorPlugin}
272
+ * - `INFO_EXTRACTOR` = `"info-extractor"`: {@link InfoExtractorPlugin}
273
+ * - `PLAYABLE_EXTRACTOR` = `"playable-extractor"`: {@link PlayableExtractorPlugin}
342
274
  */
343
275
  declare enum PluginType {
344
- CUSTOM = "custom",
345
- EXTRACTOR = "extractor"
276
+ EXTRACTOR = "extractor",
277
+ INFO_EXTRACTOR = "info-extractor",
278
+ PLAYABLE_EXTRACTOR = "playable-extractor"
346
279
  }
280
+ type DisTubePlugin = ExtractorPlugin | InfoExtractorPlugin | PlayableExtractorPlugin;
281
+ type FFmpegArg = Record<string, string | number | boolean | Array<string | null | undefined> | null | undefined>;
347
282
  /**
348
- * Search result types:
349
- *
350
- * - `VIDEO` = `"video"`
351
- * - `PLAYLIST` = `"playlist"`
283
+ * FFmpeg arguments for different use cases
352
284
  */
353
- declare enum SearchResultType {
354
- VIDEO = "video",
355
- PLAYLIST = "playlist"
356
- }
285
+ type FFmpegArgs = {
286
+ global: FFmpegArg;
287
+ input: FFmpegArg;
288
+ output: FFmpegArg;
289
+ };
357
290
  /**
358
- * Stream types:
359
- *
360
- * - `OPUS` = `0` (Better quality, use more resources - **Recommended**)
361
- * - `RAW` = `1` (Better performance, use less resources)
291
+ * FFmpeg options
362
292
  */
363
- declare enum StreamType {
364
- OPUS = 0,
365
- RAW = 1
366
- }
367
- declare enum Events {
368
- ERROR = "error",
369
- ADD_LIST = "addList",
370
- ADD_SONG = "addSong",
371
- PLAY_SONG = "playSong",
372
- FINISH_SONG = "finishSong",
373
- EMPTY = "empty",
374
- FINISH = "finish",
375
- INIT_QUEUE = "initQueue",
376
- NO_RELATED = "noRelated",
377
- DISCONNECT = "disconnect",
378
- DELETE_QUEUE = "deleteQueue",
379
- SEARCH_CANCEL = "searchCancel",
380
- SEARCH_NO_RESULT = "searchNoResult",
381
- SEARCH_DONE = "searchDone",
382
- SEARCH_INVALID_ANSWER = "searchInvalidAnswer",
383
- SEARCH_RESULT = "searchResult",
384
- FFMPEG_DEBUG = "ffmpegDebug"
385
- }
386
- type FFmpegArgs = Record<string, string | number | boolean | Array<string | null | undefined> | null | undefined>;
387
293
  type FFmpegOptions = {
294
+ /**
295
+ * Path to the ffmpeg executable
296
+ */
388
297
  path: string;
389
- args: {
390
- global: FFmpegArgs;
391
- input: FFmpegArgs;
392
- output: FFmpegArgs;
393
- };
298
+ /**
299
+ * Arguments
300
+ */
301
+ args: FFmpegArgs;
394
302
  };
395
303
 
396
304
  /**
@@ -400,20 +308,11 @@ declare const defaultFilters: Filters;
400
308
  declare const defaultOptions: {
401
309
  plugins: never[];
402
310
  emitNewSongOnly: false;
403
- leaveOnEmpty: true;
404
- leaveOnFinish: false;
405
- leaveOnStop: true;
406
311
  savePreviousSongs: true;
407
- searchSongs: number;
408
- ytdlOptions: {};
409
- searchCooldown: number;
410
- emptyCooldown: number;
411
312
  nsfw: false;
412
313
  emitAddSongWhenCreatingQueue: true;
413
314
  emitAddListWhenCreatingQueue: true;
414
315
  joinNewVoiceChannel: true;
415
- streamType: StreamType.OPUS;
416
- directLink: true;
417
316
  };
418
317
 
419
318
  declare const ERROR_MESSAGES: {
@@ -430,6 +329,7 @@ declare const ERROR_MESSAGES: {
430
329
  ENABLED_OPTION: (o: string) => string;
431
330
  NOT_IN_VOICE: string;
432
331
  VOICE_FULL: string;
332
+ VOICE_ALREADY_CREATED: string;
433
333
  VOICE_CONNECT_FAILED: (s: number) => string;
434
334
  VOICE_MISSING_PERMS: string;
435
335
  VOICE_RECONNECT_FAILED: string;
@@ -439,21 +339,26 @@ declare const ERROR_MESSAGES: {
439
339
  FFMPEG_NOT_INSTALLED: (path: string) => string;
440
340
  NO_QUEUE: string;
441
341
  QUEUE_EXIST: string;
342
+ QUEUE_STOPPED: string;
442
343
  PAUSED: string;
443
344
  RESUMED: string;
444
345
  NO_PREVIOUS: string;
445
346
  NO_UP_NEXT: string;
446
347
  NO_SONG_POSITION: string;
447
- NO_PLAYING: string;
448
- NO_RESULT: string;
348
+ NO_PLAYING_SONG: string;
449
349
  NO_RELATED: string;
450
350
  CANNOT_PLAY_RELATED: string;
451
351
  UNAVAILABLE_VIDEO: string;
452
352
  UNPLAYABLE_FORMATS: string;
453
353
  NON_NSFW: string;
454
354
  NOT_SUPPORTED_URL: string;
455
- CANNOT_RESOLVE_SONG: (t: any) => string;
355
+ NOT_SUPPORTED_SONG: (song: string) => string;
456
356
  NO_VALID_SONG: string;
357
+ CANNOT_RESOLVE_SONG: (t: any) => string;
358
+ CANNOT_GET_STREAM_URL: (song: string) => string;
359
+ CANNOT_GET_SEARCH_QUERY: (song: string) => string;
360
+ NO_RESULT: (query: string) => string;
361
+ NO_STREAM_URL: (song: string) => string;
457
362
  EMPTY_FILTERED_PLAYLIST: string;
458
363
  EMPTY_PLAYLIST: string;
459
364
  };
@@ -463,12 +368,12 @@ type StaticErrorCode = {
463
368
  [K in ErrorCode]-?: ErrorMessage[K] extends string ? K : never;
464
369
  }[ErrorCode];
465
370
  type TemplateErrorCode = Exclude<keyof typeof ERROR_MESSAGES, StaticErrorCode>;
466
- declare class DisTubeError<T extends string> extends Error {
371
+ declare class DisTubeError<T extends string = any> extends Error {
467
372
  errorCode: string;
468
- constructor(code: StaticErrorCode);
373
+ constructor(code: T extends StaticErrorCode ? T : never);
469
374
  constructor(code: T extends TemplateErrorCode ? T : never, ...args: Parameters<ErrorMessage[typeof code]>);
470
375
  constructor(code: TemplateErrorCode, _: never);
471
- constructor(code: T extends ErrorCode ? "This is built-in error code" : T, message: string);
376
+ constructor(code: T extends ErrorCode ? never : T, message: string);
472
377
  get name(): string;
473
378
  get code(): string;
474
379
  }
@@ -480,10 +385,8 @@ declare class TaskQueue {
480
385
  #private;
481
386
  /**
482
387
  * Waits for last task finished and queues a new task
483
- *
484
- * @param resolveInfo - Whether the task is a resolving info task
485
388
  */
486
- queuing(resolveInfo?: boolean): Promise<void>;
389
+ queuing(): Promise<void>;
487
390
  /**
488
391
  * Removes the finished task and processes the next task
489
392
  */
@@ -492,10 +395,6 @@ declare class TaskQueue {
492
395
  * The remaining number of tasks
493
396
  */
494
397
  get remaining(): number;
495
- /**
496
- * Whether or not having a resolving info task
497
- */
498
- get hasResolveTask(): boolean;
499
398
  }
500
399
 
501
400
  /**
@@ -503,23 +402,36 @@ declare class TaskQueue {
503
402
  */
504
403
  declare class Playlist<T = unknown> implements PlaylistInfo {
505
404
  #private;
405
+ /**
406
+ * Playlist source.
407
+ */
506
408
  source: string;
409
+ /**
410
+ * Songs in the playlist.
411
+ */
507
412
  songs: Song[];
508
- name: string;
413
+ /**
414
+ * Playlist ID.
415
+ */
416
+ id?: string;
417
+ /**
418
+ * Playlist name.
419
+ */
420
+ name?: string;
421
+ /**
422
+ * Playlist URL.
423
+ */
509
424
  url?: string;
425
+ /**
426
+ * Playlist thumbnail.
427
+ */
510
428
  thumbnail?: string;
511
- [x: string]: any;
512
429
  /**
513
- * Create a playlist
514
- *
515
- * @param playlist - Playlist
516
- * @param options - Optional options
430
+ * Create a Playlist
431
+ * @param playlist - Raw playlist info
432
+ * @param options - Optional data
517
433
  */
518
- constructor(playlist: Song[] | PlaylistInfo, options?: {
519
- member?: GuildMember;
520
- properties?: Record<string, any>;
521
- metadata?: T;
522
- });
434
+ constructor(playlist: PlaylistInfo, { member, metadata }?: ResolveOptions<T>);
523
435
  /**
524
436
  * Playlist duration in second.
525
437
  */
@@ -537,146 +449,155 @@ declare class Playlist<T = unknown> implements PlaylistInfo {
537
449
  * User requested.
538
450
  */
539
451
  get user(): discord_js.User | undefined;
540
- get metadata(): T;
541
- set metadata(metadata: T);
542
- }
543
-
544
- /**
545
- * A abstract class representing a search result.
546
- *
547
- * @virtual
548
- */
549
- declare abstract class ISearchResult {
550
- source: "youtube";
551
- abstract type: SearchResultType;
552
- id: string;
553
- name: string;
554
- url: string;
555
- uploader: {
556
- name?: string;
557
- url?: string;
558
- };
559
452
  /**
560
- * Create a search result
561
- *
562
- * @param info - ytsr result
453
+ * Optional metadata that can be used to identify the playlist.
563
454
  */
564
- constructor(info: Video | Playlist$1);
565
- }
566
- /**
567
- * A class representing a video search result.
568
- */
569
- declare class SearchResultVideo extends ISearchResult {
570
- type: SearchResultType.VIDEO;
571
- views: number;
572
- isLive: boolean;
573
- duration: number;
574
- formattedDuration: string;
575
- thumbnail: string;
576
- constructor(info: Video);
577
- }
578
- /**
579
- * A video or playlist search result
580
- */
581
- type SearchResult = SearchResultVideo | SearchResultPlaylist;
582
- /**
583
- * A class representing a playlist search result.
584
- */
585
- declare class SearchResultPlaylist extends ISearchResult {
586
- type: SearchResultType.PLAYLIST;
587
- length: number;
588
- constructor(info: Playlist$1);
455
+ get metadata(): T;
456
+ set metadata(metadata: T);
457
+ toString(): string;
589
458
  }
590
459
 
591
460
  /**
592
461
  * Class representing a song.
593
- *
594
- * <info>If {@link Song} is added from a YouTube {@link SearchResult} or {@link
595
- * Playlist}, some info will be missing to save your resources. It will be filled
596
- * when emitting {@link DisTube#playSong} event.
597
- *
598
- * Missing info: {@link Song#likes}, {@link Song#dislikes}, {@link Song#streamURL},
599
- * {@link Song#related}, {@link Song#chapters}, {@link Song#age_restricted}</info>
600
462
  */
601
463
  declare class Song<T = unknown> {
602
464
  #private;
465
+ /**
466
+ * The source of this song info
467
+ */
603
468
  source: string;
604
- formats?: ytdl__default.videoFormat[];
469
+ /**
470
+ * Song ID.
471
+ */
605
472
  id?: string;
473
+ /**
474
+ * Song name.
475
+ */
606
476
  name?: string;
607
- isLive: boolean;
477
+ /**
478
+ * Indicates if the song is an active live.
479
+ */
480
+ isLive?: boolean;
481
+ /**
482
+ * Song duration.
483
+ */
608
484
  duration: number;
609
- formattedDuration?: string;
610
- url: string;
611
- streamURL?: string;
485
+ /**
486
+ * Formatted duration string (`hh:mm:ss`, `mm:ss` or `Live`).
487
+ */
488
+ formattedDuration: string;
489
+ /**
490
+ * Song URL.
491
+ */
492
+ url?: string;
493
+ /**
494
+ * Song thumbnail.
495
+ */
612
496
  thumbnail?: string;
613
- related: RelatedSong[];
614
- views: number;
615
- likes: number;
616
- dislikes: number;
497
+ /**
498
+ * Song view count
499
+ */
500
+ views?: number;
501
+ /**
502
+ * Song like count
503
+ */
504
+ likes?: number;
505
+ /**
506
+ * Song dislike count
507
+ */
508
+ dislikes?: number;
509
+ /**
510
+ * Song repost (share) count
511
+ */
512
+ reposts?: number;
513
+ /**
514
+ * Song uploader
515
+ */
617
516
  uploader: {
618
517
  name?: string;
619
518
  url?: string;
620
519
  };
621
- age_restricted: boolean;
622
- chapters: Chapter[];
623
- reposts: number;
624
520
  /**
625
- * Create a Song
626
- *
627
- * @param info - Raw info
628
- * @param options - Optional options
521
+ * Whether or not an age-restricted content
629
522
  */
630
- constructor(info: ytdl__default.videoInfo | SearchResult | OtherSongInfo | ytdl__default.relatedVideo | RelatedSong | ytpl.result["items"][number], options?: {
631
- member?: GuildMember;
632
- source?: string;
633
- metadata?: T;
634
- });
635
- _patchYouTube(i: ytdl__default.videoInfo | SearchResult): void;
523
+ ageRestricted?: boolean;
636
524
  /**
637
- * Patch data from other source
525
+ * Stream info
526
+ */
527
+ stream: {
528
+ /**
529
+ * The stream of this song will be played from source
530
+ */
531
+ playFromSource: true;
532
+ /**
533
+ * Stream URL of this song
534
+ */
535
+ url?: string;
536
+ } | {
537
+ /**
538
+ * The stream of this song will be played from another song
539
+ */
540
+ playFromSource: false;
541
+ /**
542
+ * The song that this song will be played from
543
+ */
544
+ song?: Song<T>;
545
+ };
546
+ /**
547
+ * The plugin that created this song
548
+ */
549
+ plugin: DisTubePlugin | null;
550
+ /**
551
+ * Create a Song
638
552
  *
639
- * @param info - Video info
553
+ * @param info - Raw song info
554
+ * @param options - Optional data
640
555
  */
641
- _patchOther(info: OtherSongInfo): void;
556
+ constructor(info: SongInfo, { member, metadata }?: ResolveOptions<T>);
642
557
  /**
643
- * The playlist added this song
558
+ * The playlist this song belongs to
644
559
  */
645
560
  get playlist(): Playlist | undefined;
646
561
  set playlist(playlist: Playlist | undefined);
647
562
  /**
648
- * User requested.
563
+ * User requested to play this song.
649
564
  */
650
565
  get member(): GuildMember | undefined;
651
566
  set member(member: GuildMember | undefined);
652
567
  /**
653
- * User requested.
568
+ * User requested to play this song.
654
569
  */
655
570
  get user(): discord_js.User | undefined;
571
+ /**
572
+ * Optional metadata that can be used to identify the song. This is attached by the
573
+ * {@link DisTube#play} method.
574
+ */
656
575
  get metadata(): T;
657
576
  set metadata(metadata: T);
577
+ toString(): string;
658
578
  }
659
579
 
660
- /**
661
- * @virtual
662
- */
663
580
  declare abstract class DisTubeBase {
664
581
  distube: DisTube;
665
582
  constructor(distube: DisTube);
666
583
  /**
667
584
  * Emit the {@link DisTube} of this base
668
- *
669
585
  * @param eventName - Event name
670
586
  * @param args - arguments
671
587
  */
672
588
  emit(eventName: keyof DisTubeEvents, ...args: any): boolean;
673
589
  /**
674
590
  * Emit error event
675
- *
676
591
  * @param error - error
677
- * @param channel - Text channel where the error is encountered.
592
+ * @param queue - The queue encountered the error
593
+ * @param song - The playing song when encountered the error
594
+ */
595
+ emitError(error: Error, queue: Queue, song?: Song): void;
596
+ /**
597
+ * Emit debug event
598
+ * @param message - debug message
678
599
  */
679
- emitError(error: Error, channel?: GuildTextBasedChannel): void;
600
+ debug(message: string): void;
680
601
  /**
681
602
  * The queue manager
682
603
  */
@@ -697,6 +618,10 @@ declare abstract class DisTubeBase {
697
618
  * DisTube handler
698
619
  */
699
620
  get handler(): DisTubeHandler;
621
+ /**
622
+ * DisTube plugins
623
+ */
624
+ get plugins(): DisTubePlugin[];
700
625
  }
701
626
 
702
627
  /**
@@ -708,7 +633,6 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
708
633
  readonly voices: DisTubeVoiceManager;
709
634
  readonly audioPlayer: AudioPlayer;
710
635
  connection: VoiceConnection;
711
- audioResource?: AudioResource;
712
636
  emittedError: boolean;
713
637
  isDisconnected: boolean;
714
638
  stream?: DisTubeStream;
@@ -721,30 +645,29 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
721
645
  set channel(channel: VoiceBasedChannel);
722
646
  /**
723
647
  * Join a voice channel with this connection
724
- *
725
648
  * @param channel - A voice channel
726
649
  */
727
650
  join(channel?: VoiceBasedChannel): Promise<DisTubeVoice>;
728
651
  /**
729
652
  * Leave the voice channel of this connection
730
- *
731
653
  * @param error - Optional, an error to emit with 'error' event.
732
654
  */
733
655
  leave(error?: Error): void;
734
656
  /**
735
657
  * Stop the playing stream
736
- *
737
658
  * @param force - If true, will force the {@link DisTubeVoice#audioPlayer} to enter the Idle state even
738
- * if the {@link DisTubeVoice#audioResource} has silence padding frames.
659
+ * if the {@link DisTubeStream#audioResource} has silence padding frames.
739
660
  */
740
661
  stop(force?: boolean): void;
741
662
  /**
742
663
  * Play a {@link DisTubeStream}
743
- *
744
664
  * @param dtStream - DisTubeStream
745
665
  */
746
666
  play(dtStream: DisTubeStream): void;
747
667
  set volume(volume: number);
668
+ /**
669
+ * Get or set the volume percentage
670
+ */
748
671
  get volume(): number;
749
672
  /**
750
673
  * Playback duration of the audio resource in seconds
@@ -762,17 +685,13 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
762
685
  get selfMute(): boolean;
763
686
  /**
764
687
  * Self-deafens/undeafens the bot.
765
- *
766
688
  * @param selfDeaf - Whether or not the bot should be self-deafened
767
- *
768
689
  * @returns true if the voice state was successfully updated, otherwise false
769
690
  */
770
691
  setSelfDeaf(selfDeaf: boolean): boolean;
771
692
  /**
772
693
  * Self-mutes/unmutes the bot.
773
- *
774
694
  * @param selfMute - Whether or not the bot should be self-muted
775
- *
776
695
  * @returns true if the voice state was successfully updated, otherwise false
777
696
  */
778
697
  setSelfMute(selfMute: boolean): boolean;
@@ -782,12 +701,20 @@ declare class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {
782
701
  get voiceState(): VoiceState | undefined;
783
702
  }
784
703
 
704
+ /**
705
+ * Options for {@link DisTubeStream}
706
+ */
785
707
  interface StreamOptions {
708
+ /**
709
+ * FFmpeg options
710
+ */
786
711
  ffmpeg: FFmpegOptions;
712
+ /**
713
+ * Seek time (in seconds).
714
+ * @default 0
715
+ */
787
716
  seek?: number;
788
- type?: StreamType;
789
717
  }
790
- declare const chooseBestVideoFormat: ({ duration, formats, isLive }: Song) => ytdl.videoFormat | undefined;
791
718
  declare const checkFFmpeg: (distube: DisTube) => void;
792
719
  /**
793
720
  * Create a stream to play with {@link DisTubeVoice}
@@ -796,34 +723,26 @@ declare class DisTubeStream extends TypedEmitter<{
796
723
  debug: (debug: string) => Awaitable;
797
724
  error: (error: Error) => Awaitable;
798
725
  }> {
799
- private killed;
800
- process: ChildProcess;
801
- stream: PassThrough;
802
- type: StreamType$1;
803
- url: string;
726
+ #private;
727
+ process?: ChildProcess;
728
+ stream: VolumeTransformer;
729
+ audioResource: AudioResource;
804
730
  /**
805
731
  * Create a DisTubeStream to play with {@link DisTubeVoice}
806
- *
807
732
  * @param url - Stream URL
808
733
  * @param options - Stream options
809
734
  */
810
- constructor(url: string, { ffmpeg, seek, type }: StreamOptions);
735
+ constructor(url: string, options: StreamOptions);
736
+ spawn(): void;
811
737
  private debug;
738
+ setVolume(volume: number): void;
812
739
  kill(): void;
813
- /**
814
- * Create a stream from a YouTube {@link Song}
815
- *
816
- * @param song - A YouTube Song
817
- * @param options - options
818
- */
819
- static YouTube(song: Song, options: StreamOptions): DisTubeStream;
820
- /**
821
- * Create a stream from a stream url
822
- *
823
- * @param url - stream url
824
- * @param options - options
825
- */
826
- static DirectLink(url: string, options: StreamOptions): DisTubeStream;
740
+ }
741
+ declare class VolumeTransformer extends Transform {
742
+ private buffer;
743
+ private readonly extrema;
744
+ vol: number;
745
+ _transform(newChunk: Buffer, _encoding: BufferEncoding, done: TransformCallback): void;
827
746
  }
828
747
 
829
748
  /**
@@ -831,109 +750,41 @@ declare class DisTubeStream extends TypedEmitter<{
831
750
  */
832
751
  declare class DisTubeHandler extends DisTubeBase {
833
752
  #private;
834
- constructor(distube: DisTube);
835
- get ytdlOptions(): ytdl__default.getInfoOptions;
836
- get ytCookie(): string;
837
- /**
838
- * @param url - url
839
- * @param basic - getBasicInfo?
840
- */
841
- getYouTubeInfo(url: string, basic?: boolean): Promise<ytdl__default.videoInfo>;
842
753
  resolve<T = unknown>(song: Song<T>, options?: Omit<ResolveOptions, "metadata">): Promise<Song<T>>;
843
754
  resolve<T = unknown>(song: Playlist<T>, options?: Omit<ResolveOptions, "metadata">): Promise<Playlist<T>>;
844
- resolve<T = unknown>(song: string | SearchResult, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;
845
- resolve<T = unknown>(song: ytdl__default.videoInfo | OtherSongInfo | ytdl__default.relatedVideo, options?: ResolveOptions<T>): Promise<Song<T>>;
755
+ resolve<T = unknown>(song: string, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;
756
+ resolve<T = unknown>(song: Song, options: ResolveOptions<T>): Promise<Song<T>>;
846
757
  resolve<T = unknown>(song: Playlist, options: ResolveOptions<T>): Promise<Playlist<T>>;
847
- resolve(song: string | ytdl__default.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl__default.relatedVideo, options?: ResolveOptions): Promise<Song | Playlist>;
848
- resolvePlaylist<T = unknown>(playlist: Playlist<T> | Song<T>[] | string, options?: Omit<ResolvePlaylistOptions, "metadata">): Promise<Playlist<T>>;
849
- resolvePlaylist<T = undefined>(playlist: Playlist | Song[] | string, options: ResolvePlaylistOptions<T>): Promise<Playlist<T>>;
850
- resolvePlaylist(playlist: Playlist | Song[] | string, options?: ResolvePlaylistOptions): Promise<Playlist>;
851
- /**
852
- * Search for a song, fire {@link DisTube#error} if not found.
853
- *
854
- * @throws {@link DisTubeError}
855
- *
856
- * @param message - The original message from an user
857
- * @param query - The query string
858
- *
859
- * @returns Song info
860
- */
861
- searchSong(message: Message<true>, query: string): Promise<SearchResult | null>;
862
- /**
863
- * Create a message collector for selecting search results.
864
- *
865
- * Needed events: {@link DisTube#searchResult}, {@link DisTube#searchCancel},
866
- * {@link DisTube#searchInvalidAnswer}, {@link DisTube#searchDone}.
867
- *
868
- * @throws {@link DisTubeError}
869
- *
870
- * @param message - The original message from an user
871
- * @param results - The search results
872
- * @param query - The query string
873
- *
874
- * @returns Selected result
875
- */
876
- createSearchMessageCollector<R extends SearchResult | Song | Playlist>(message: Message<true>, results: Array<R>, query?: string): Promise<R | null>;
877
- /**
878
- * Play or add a {@link Playlist} to the queue.
879
- *
880
- * @throws {@link DisTubeError}
881
- *
882
- * @param voiceChannel - A voice channel
883
- * @param playlist - A YouTube playlist url | a Playlist
884
- * @param options - Optional options
885
- */
886
- playPlaylist(voiceChannel: VoiceBasedChannel, playlist: Playlist, options?: PlayHandlerOptions): Promise<void>;
887
- /**
888
- * Play or add a {@link Song} to the queue.
889
- *
890
- * @throws {@link DisTubeError}
891
- *
892
- * @param voiceChannel - A voice channel
893
- * @param song - A YouTube playlist url | a Playlist
894
- * @param options - Optional options
895
- */
896
- playSong(voiceChannel: VoiceBasedChannel, song: Song, options?: PlayHandlerOptions): Promise<void>;
758
+ resolve(song: string | Song | Playlist, options?: ResolveOptions): Promise<Song | Playlist>;
759
+ _getPluginFromURL(url: string): Promise<DisTubePlugin | null>;
760
+ _getPluginFromSong(song: Song): Promise<DisTubePlugin | null>;
761
+ _getPluginFromSong<T extends PluginType>(song: Song, types: T[], validate?: boolean): Promise<(DisTubePlugin & {
762
+ type: T;
763
+ }) | null>;
897
764
  /**
898
765
  * Get {@link Song}'s stream info and attach it to the song.
899
- *
900
766
  * @param song - A Song
901
767
  */
902
768
  attachStreamInfo(song: Song): Promise<void>;
769
+ followRedirectLink(url: string, maxRedirect?: number): Promise<string>;
903
770
  }
904
771
 
905
772
  declare class Options {
906
773
  #private;
907
- plugins: (CustomPlugin | ExtractorPlugin)[];
774
+ plugins: DisTubePlugin[];
908
775
  emitNewSongOnly: boolean;
909
- leaveOnFinish: boolean;
910
- leaveOnStop: boolean;
911
- leaveOnEmpty: boolean;
912
- emptyCooldown: number;
913
776
  savePreviousSongs: boolean;
914
- searchSongs: number;
915
- searchCooldown: number;
916
- youtubeCookie?: Cookie[] | string;
917
777
  customFilters?: Filters;
918
- ytdlOptions: ytdl__default.getInfoOptions;
919
778
  nsfw: boolean;
920
779
  emitAddSongWhenCreatingQueue: boolean;
921
780
  emitAddListWhenCreatingQueue: boolean;
922
781
  joinNewVoiceChannel: boolean;
923
- streamType: StreamType;
924
- directLink: boolean;
925
- /** @deprecated */
926
- ffmpegPath: undefined;
927
- /** @deprecated */
928
- ffmpegDefaultArgs: undefined;
929
782
  ffmpeg: FFmpegOptions;
930
783
  constructor(options: DisTubeOptions);
931
784
  }
932
785
 
933
786
  /**
934
787
  * Manages the collection of a data model.
935
- *
936
- * @virtual
937
788
  */
938
789
  declare abstract class BaseManager<V> extends DisTubeBase {
939
790
  /**
@@ -948,8 +799,6 @@ declare abstract class BaseManager<V> extends DisTubeBase {
948
799
 
949
800
  /**
950
801
  * Manages the collection of a data model paired with a guild id.
951
- *
952
- * @virtual
953
802
  */
954
803
  declare abstract class GuildIdManager<V> extends BaseManager<V> {
955
804
  add(idOrInstance: GuildIdResolvable, data: V): this;
@@ -959,32 +808,21 @@ declare abstract class GuildIdManager<V> extends BaseManager<V> {
959
808
  }
960
809
 
961
810
  /**
962
- * Manages voice connections for {@link DisTube}
811
+ * Manages voice connections
963
812
  */
964
813
  declare class DisTubeVoiceManager extends GuildIdManager<DisTubeVoice> {
965
814
  /**
966
- * Get a {@link DisTubeVoice}.
967
- *
968
- * @param guild - The queue resolvable to resolve
969
- */
970
- /**
971
- * Collection of {@link DisTubeVoice}.
972
- */
973
- /**
974
- * Create a {@link DisTubeVoice}
975
- *
815
+ * Create a {@link DisTubeVoice} instance
976
816
  * @param channel - A voice channel to join
977
817
  */
978
818
  create(channel: VoiceBasedChannel): DisTubeVoice;
979
819
  /**
980
- * Join a voice channel
981
- *
820
+ * Join a voice channel and wait until the connection is ready
982
821
  * @param channel - A voice channel to join
983
822
  */
984
823
  join(channel: VoiceBasedChannel): Promise<DisTubeVoice>;
985
824
  /**
986
825
  * Leave the connected voice channel in a guild
987
- *
988
826
  * @param guild - Queue Resolvable
989
827
  */
990
828
  leave(guild: GuildIdResolvable): void;
@@ -996,13 +834,12 @@ declare class DisTubeVoiceManager extends GuildIdManager<DisTubeVoice> {
996
834
  declare class FilterManager extends BaseManager<Filter> {
997
835
  #private;
998
836
  /**
999
- * Collection of {@link Filter}.
837
+ * The queue to manage
1000
838
  */
1001
839
  queue: Queue;
1002
840
  constructor(queue: Queue);
1003
841
  /**
1004
842
  * Enable a filter or multiple filters to the manager
1005
- *
1006
843
  * @param filterOrFilters - The filter or filters to enable
1007
844
  * @param override - Wether or not override the applied filter with new filter value
1008
845
  */
@@ -1013,19 +850,16 @@ declare class FilterManager extends BaseManager<Filter> {
1013
850
  clear(): this;
1014
851
  /**
1015
852
  * Set the filters applied to the manager
1016
- *
1017
853
  * @param filters - The filters to apply
1018
854
  */
1019
855
  set(filters: FilterResolvable[]): this;
1020
856
  /**
1021
857
  * Disable a filter or multiple filters
1022
- *
1023
858
  * @param filterOrFilters - The filter or filters to disable
1024
859
  */
1025
860
  remove(filterOrFilters: FilterResolvable | FilterResolvable[]): this;
1026
861
  /**
1027
862
  * Check whether a filter enabled or not
1028
- *
1029
863
  * @param filter - The filter to check
1030
864
  */
1031
865
  has(filter: FilterResolvable): boolean;
@@ -1037,7 +871,7 @@ declare class FilterManager extends BaseManager<Filter> {
1037
871
  * Array of enabled filters
1038
872
  */
1039
873
  get values(): Filter[];
1040
- get ffmpegArgs(): FFmpegArgs;
874
+ get ffmpegArgs(): FFmpegArg;
1041
875
  toString(): string;
1042
876
  }
1043
877
 
@@ -1046,33 +880,19 @@ declare class FilterManager extends BaseManager<Filter> {
1046
880
  */
1047
881
  declare class QueueManager extends GuildIdManager<Queue> {
1048
882
  #private;
1049
- /**
1050
- * Collection of {@link Queue}.
1051
- */
1052
883
  /**
1053
884
  * Create a {@link Queue}
1054
- *
1055
885
  * @param channel - A voice channel
1056
- * @param song - First song
1057
886
  * @param textChannel - Default text channel
1058
- *
1059
887
  * @returns Returns `true` if encounter an error
1060
888
  */
1061
- create(channel: VoiceBasedChannel, song: Song[] | Song, textChannel?: GuildTextBasedChannel): Promise<Queue | true>;
1062
- /**
1063
- * Create a ytdl stream
1064
- *
1065
- * @param queue - Queue
1066
- */
1067
- createStream(queue: Queue): DisTubeStream;
889
+ create(channel: VoiceBasedChannel, textChannel?: GuildTextBasedChannel): Promise<Queue>;
1068
890
  /**
1069
- * Play a song on voice connection
1070
- *
1071
- * @param queue - The guild queue
1072
- *
1073
- * @returns error?
891
+ * Play a song on voice connection with queue properties
892
+ * @param queue - The guild queue to play
893
+ * @param emitPlaySong - Whether or not emit {@link Events.PLAY_SONG} event
1074
894
  */
1075
- playSong(queue: Queue): Promise<boolean>;
895
+ playSong(queue: Queue, emitPlaySong?: boolean): Promise<void>;
1076
896
  }
1077
897
 
1078
898
  /**
@@ -1080,31 +900,79 @@ declare class QueueManager extends GuildIdManager<Queue> {
1080
900
  */
1081
901
  declare class Queue extends DisTubeBase {
1082
902
  #private;
903
+ /**
904
+ * Queue id (Guild id)
905
+ */
1083
906
  readonly id: Snowflake;
907
+ /**
908
+ * Voice connection of this queue.
909
+ */
1084
910
  voice: DisTubeVoice;
911
+ /**
912
+ * List of songs in the queue (The first one is the playing song)
913
+ */
1085
914
  songs: Song[];
915
+ /**
916
+ * List of the previous songs.
917
+ */
1086
918
  previousSongs: Song[];
919
+ /**
920
+ * Whether stream is currently stopped.
921
+ */
1087
922
  stopped: boolean;
1088
- _next: boolean;
1089
- _prev: boolean;
923
+ /**
924
+ * Whether or not the stream is currently playing.
925
+ */
1090
926
  playing: boolean;
927
+ /**
928
+ * Whether or not the stream is currently paused.
929
+ */
1091
930
  paused: boolean;
931
+ /**
932
+ * Type of repeat mode (`0` is disabled, `1` is repeating a song, `2` is repeating
933
+ * all the queue). Default value: `0` (disabled)
934
+ */
1092
935
  repeatMode: RepeatMode;
936
+ /**
937
+ * Whether or not the autoplay mode is enabled. Default value: `false`
938
+ */
1093
939
  autoplay: boolean;
1094
- beginTime: number;
940
+ /**
941
+ * FFmpeg arguments for the current queue. Default value is defined with {@link DisTubeOptions}.ffmpeg.args.
942
+ * `af` output argument will be replaced with {@link Queue#filters} manager
943
+ */
944
+ ffmpegArgs: FFmpegArgs;
945
+ /**
946
+ * The text channel of the Queue. (Default: where the first command is called).
947
+ */
1095
948
  textChannel?: GuildTextBasedChannel;
1096
- _emptyTimeout?: NodeJS.Timeout;
949
+ /**
950
+ * What time in the song to begin (in seconds).
951
+ */
952
+ _beginTime: number;
953
+ /**
954
+ * Whether or not the last song was skipped to next song.
955
+ */
956
+ _next: boolean;
957
+ /**
958
+ * Whether or not the last song was skipped to previous song.
959
+ */
960
+ _prev: boolean;
961
+ /**
962
+ * Task queuing system
963
+ */
1097
964
  _taskQueue: TaskQueue;
965
+ /**
966
+ * {@link DisTubeVoice} listener
967
+ */
1098
968
  _listeners?: DisTubeVoiceEvents;
1099
969
  /**
1100
970
  * Create a queue for the guild
1101
- *
1102
971
  * @param distube - DisTube
1103
972
  * @param voice - Voice connection
1104
- * @param song - First song(s)
1105
973
  * @param textChannel - Default text channel
1106
974
  */
1107
- constructor(distube: DisTube, voice: DisTubeVoice, song: Song | Song[], textChannel?: GuildTextBasedChannel);
975
+ constructor(distube: DisTube, voice: DisTubeVoice, textChannel?: GuildTextBasedChannel);
1108
976
  /**
1109
977
  * The client user as a `GuildMember` of this queue's guild
1110
978
  */
@@ -1133,34 +1001,31 @@ declare class Queue extends DisTubeBase {
1133
1001
  * The voice channel playing in.
1134
1002
  */
1135
1003
  get voiceChannel(): discord_js.VoiceBasedChannel | null;
1004
+ /**
1005
+ * Get or set the stream volume. Default value: `50`.
1006
+ */
1136
1007
  get volume(): number;
1137
1008
  set volume(value: number);
1138
1009
  /**
1139
1010
  * @throws {DisTubeError}
1140
- *
1141
1011
  * @param song - Song to add
1142
1012
  * @param position - Position to add, \<= 0 to add to the end of the queue
1143
- *
1144
1013
  * @returns The guild queue
1145
1014
  */
1146
1015
  addToQueue(song: Song | Song[], position?: number): Queue;
1147
1016
  /**
1148
1017
  * Pause the guild stream
1149
- *
1150
1018
  * @returns The guild queue
1151
1019
  */
1152
1020
  pause(): Queue;
1153
1021
  /**
1154
1022
  * Resume the guild stream
1155
- *
1156
1023
  * @returns The guild queue
1157
1024
  */
1158
1025
  resume(): Queue;
1159
1026
  /**
1160
1027
  * Set the guild stream's volume
1161
- *
1162
1028
  * @param percent - The percentage of volume you want to set
1163
- *
1164
1029
  * @returns The guild queue
1165
1030
  */
1166
1031
  setVolume(percent: number): Queue;
@@ -1168,19 +1033,16 @@ declare class Queue extends DisTubeBase {
1168
1033
  * Skip the playing song if there is a next song in the queue. <info>If {@link
1169
1034
  * Queue#autoplay} is `true` and there is no up next song, DisTube will add and
1170
1035
  * play a related song.</info>
1171
- *
1172
1036
  * @returns The song will skip to
1173
1037
  */
1174
1038
  skip(): Promise<Song>;
1175
1039
  /**
1176
1040
  * Play the previous song if exists
1177
- *
1178
1041
  * @returns The guild queue
1179
1042
  */
1180
1043
  previous(): Promise<Song>;
1181
1044
  /**
1182
1045
  * Shuffle the queue's songs
1183
- *
1184
1046
  * @returns The guild queue
1185
1047
  */
1186
1048
  shuffle(): Promise<Queue>;
@@ -1188,32 +1050,25 @@ declare class Queue extends DisTubeBase {
1188
1050
  * Jump to the song position in the queue. The next one is 1, 2,... The previous
1189
1051
  * one is -1, -2,...
1190
1052
  * if `num` is invalid number
1191
- *
1192
1053
  * @param position - The song position to play
1193
- *
1194
1054
  * @returns The new Song will be played
1195
1055
  */
1196
1056
  jump(position: number): Promise<Song>;
1197
1057
  /**
1198
1058
  * Set the repeat mode of the guild queue.
1199
1059
  * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
1200
- *
1201
1060
  * @param mode - The repeat modes (toggle if `undefined`)
1202
- *
1203
1061
  * @returns The new repeat mode
1204
1062
  */
1205
1063
  setRepeatMode(mode?: RepeatMode): RepeatMode;
1206
1064
  /**
1207
1065
  * Set the playing time to another position
1208
- *
1209
1066
  * @param time - Time in seconds
1210
- *
1211
1067
  * @returns The guild queue
1212
1068
  */
1213
1069
  seek(time: number): Queue;
1214
1070
  /**
1215
1071
  * Add a related song of the playing song to the queue
1216
- *
1217
1072
  * @returns The added song
1218
1073
  */
1219
1074
  addRelatedSong(): Promise<Song>;
@@ -1222,144 +1077,136 @@ declare class Queue extends DisTubeBase {
1222
1077
  */
1223
1078
  stop(): Promise<void>;
1224
1079
  /**
1225
- * Remove the queue from the manager (This does not leave the voice channel even if
1226
- * {@link DisTubeOptions | DisTubeOptions.leaveOnStop} is enabled)
1080
+ * Remove the queue from the manager
1227
1081
  */
1228
1082
  remove(): void;
1229
1083
  /**
1230
1084
  * Toggle autoplay mode
1231
- *
1232
1085
  * @returns Autoplay mode state
1233
1086
  */
1234
1087
  toggleAutoplay(): boolean;
1088
+ /**
1089
+ * Play the queue
1090
+ * @param emitPlaySong - Whether or not emit {@link Events.PLAY_SONG} event
1091
+ */
1092
+ play(emitPlaySong?: boolean): Promise<void>;
1235
1093
  }
1236
1094
 
1237
1095
  /**
1238
1096
  * DisTube Plugin
1239
- *
1240
- * @virtual
1241
1097
  */
1242
1098
  declare abstract class Plugin {
1243
- abstract type: PluginType;
1244
- distube: DisTube;
1245
- init(distube: DisTube): void;
1246
1099
  /**
1247
1100
  * Type of the plugin
1248
1101
  */
1102
+ abstract readonly type: PluginType;
1249
1103
  /**
1250
- * Emit an event to the {@link DisTube} class
1251
- *
1252
- * @param eventName - Event name
1253
- * @param args - arguments
1254
- */
1255
- emit(eventName: keyof DisTubeEvents, ...args: any): boolean;
1256
- /**
1257
- * Emit error event to the {@link DisTube} class
1258
- *
1259
- * @param error - error
1260
- * @param channel - Text channel where the error is encountered.
1261
- */
1262
- emitError(error: Error, channel?: GuildTextBasedChannel): void;
1263
- /**
1264
- * The queue manager
1104
+ * DisTube
1265
1105
  */
1266
- get queues(): QueueManager;
1106
+ distube: DisTube;
1107
+ init(distube: DisTube): void;
1267
1108
  /**
1268
- * The voice manager
1109
+ * Get related songs from a supported url.
1110
+ * @param song - Input song
1269
1111
  */
1270
- get voices(): DisTubeVoiceManager;
1271
- /**
1272
- * Discord.js client
1273
- */
1274
- get client(): Client;
1112
+ abstract getRelatedSongs(song: Song): Awaitable<Song[]>;
1113
+ }
1114
+
1115
+ /**
1116
+ * This plugin can extract the info, search, and play a song directly from its source
1117
+ */
1118
+ declare abstract class ExtractorPlugin extends Plugin {
1119
+ readonly type = PluginType.EXTRACTOR;
1275
1120
  /**
1276
- * DisTube options
1121
+ * Check if the url is working with this plugin
1122
+ * @param url - Input url
1277
1123
  */
1278
- get options(): Options;
1124
+ abstract validate(url: string): Awaitable<boolean>;
1279
1125
  /**
1280
- * DisTube handler
1126
+ * Resolve the validated url to a {@link Song} or a {@link Playlist}.
1127
+ * @param url - URL
1128
+ * @param options - Optional options
1281
1129
  */
1282
- get handler(): DisTubeHandler;
1130
+ abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
1283
1131
  /**
1284
- * Check if the string is working with this plugin
1285
- *
1286
- * @param _string - Input string
1132
+ * Search for a Song which playable from this plugin's source
1133
+ * @param query - Search query
1134
+ * @param options - Optional options
1287
1135
  */
1288
- validate(_string: string): Awaitable<boolean>;
1136
+ abstract searchSong<T>(query: string, options: ResolveOptions<T>): Awaitable<Song<T> | null>;
1289
1137
  /**
1290
1138
  * Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
1291
1139
  * Not needed if the plugin plays song from YouTube.
1292
- *
1293
- * @param url - Input url
1294
- */
1295
- getStreamURL(url: string): Awaitable<string>;
1296
- /**
1297
- * Get related songs from a supported url. {@link Song#member} should be
1298
- * `undefined`. Not needed to add {@link Song#related} because it will be added
1299
- * with this function later.
1300
- *
1301
- * @param _url - Input url
1140
+ * @param song - Input song
1302
1141
  */
1303
- getRelatedSongs(_url: string): Awaitable<RelatedSong[]>;
1142
+ abstract getStreamURL<T>(song: Song<T>): Awaitable<string>;
1304
1143
  }
1305
1144
 
1306
1145
  /**
1307
- * Custom Plugin
1308
- *
1309
- * @virtual
1146
+ * This plugin only can extract the info from supported links, but not play song directly from its source
1310
1147
  */
1311
- declare abstract class CustomPlugin extends Plugin {
1312
- readonly type = PluginType.CUSTOM;
1313
- abstract play(voiceChannel: VoiceBasedChannel, song: string, options: PlayOptions): Awaitable<void>;
1148
+ declare abstract class InfoExtractorPlugin extends Plugin {
1149
+ readonly type = PluginType.INFO_EXTRACTOR;
1150
+ /**
1151
+ * Check if the url is working with this plugin
1152
+ * @param url - Input url
1153
+ */
1154
+ abstract validate(url: string): Awaitable<boolean>;
1155
+ /**
1156
+ * Resolve the validated url to a {@link Song} or a {@link Playlist}.
1157
+ * @param url - URL
1158
+ * @param options - Optional options
1159
+ */
1160
+ abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
1161
+ /**
1162
+ * Create a search query to be used in {@link ExtractorPlugin#searchSong}
1163
+ * @param song - Input song
1164
+ */
1165
+ abstract createSearchQuery<T>(song: Song<T>): Awaitable<string>;
1314
1166
  }
1315
1167
 
1316
1168
  /**
1317
- * Extractor Plugin
1318
- *
1319
- * @virtual
1169
+ * This plugin can extract and play song from supported links, but cannot search for songs from its source
1320
1170
  */
1321
- declare abstract class ExtractorPlugin extends Plugin {
1322
- readonly type = PluginType.EXTRACTOR;
1323
- abstract resolve<T = unknown>(url: string, options: {
1324
- member?: GuildMember;
1325
- metadata?: T;
1326
- }): Awaitable<Song<T> | Playlist<T>>;
1171
+ declare abstract class PlayableExtractorPlugin extends Plugin {
1172
+ readonly type = PluginType.PLAYABLE_EXTRACTOR;
1173
+ /**
1174
+ * Check if the url is working with this plugin
1175
+ * @param url - Input url
1176
+ */
1177
+ abstract validate(url: string): Awaitable<boolean>;
1178
+ /**
1179
+ * Resolve the validated url to a {@link Song} or a {@link Playlist}.
1180
+ * @param url - URL
1181
+ * @param options - Optional options
1182
+ */
1183
+ abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
1184
+ /**
1185
+ * Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
1186
+ * Not needed if the plugin plays song from YouTube.
1187
+ * @param song - Input song
1188
+ */
1189
+ abstract getStreamURL<T>(song: Song<T>): Awaitable<string>;
1327
1190
  }
1328
1191
 
1329
1192
  /**
1330
1193
  * Format duration to string
1331
- *
1332
1194
  * @param sec - Duration in seconds
1333
1195
  */
1334
1196
  declare function formatDuration(sec: number): string;
1335
- /**
1336
- * Convert formatted duration to seconds
1337
- *
1338
- * @param input - Formatted duration string
1339
- */
1340
- declare function toSecond(input: any): number;
1341
- /**
1342
- * Parse number from input
1343
- *
1344
- * @param input - Any
1345
- */
1346
- declare function parseNumber(input: any): number;
1347
1197
  declare const SUPPORTED_PROTOCOL: readonly ["https:", "http:", "file:"];
1348
1198
  /**
1349
1199
  * Check if the string is an URL
1350
- *
1351
1200
  * @param input - input
1352
1201
  */
1353
1202
  declare function isURL(input: any): input is `${(typeof SUPPORTED_PROTOCOL)[number]}//${string}`;
1354
1203
  /**
1355
1204
  * Check if the Client has enough intents to using DisTube
1356
- *
1357
1205
  * @param options - options
1358
1206
  */
1359
1207
  declare function checkIntents(options: ClientOptions): void;
1360
1208
  /**
1361
1209
  * Check if the voice channel is empty
1362
- *
1363
1210
  * @param voiceState - voiceState
1364
1211
  */
1365
1212
  declare function isVoiceChannelEmpty(voiceState: VoiceState): boolean;
@@ -1373,296 +1220,132 @@ declare function resolveGuildId(resolvable: GuildIdResolvable): Snowflake;
1373
1220
  declare function isClientInstance(client: any): client is Client;
1374
1221
  declare function checkInvalidKey(target: Record<string, any>, source: Record<string, any> | string[], sourceName: string): void;
1375
1222
  declare function isObject(obj: any): obj is object;
1376
- declare function isRecord<T = unknown>(obj: any): obj is Record<string, T>;
1377
1223
  type KeyOf<T> = T extends object ? (keyof T)[] : [];
1378
1224
  declare function objectKeys<T>(obj: T): KeyOf<T>;
1379
1225
  declare function isNsfwChannel(channel?: GuildTextBasedChannel): boolean;
1380
1226
  type Falsy = undefined | null | false | 0 | "";
1381
1227
  declare const isTruthy: <T>(x: T | Falsy) => x is T;
1382
1228
 
1383
- declare class DirectLinkPlugin extends ExtractorPlugin {
1384
- validate(url: string): Promise<boolean>;
1385
- resolve(url: string, options?: {
1386
- member?: GuildMember;
1387
- metadata?: any;
1388
- }): Song<any>;
1389
- }
1390
-
1391
1229
  declare const version: string;
1392
- interface DisTube extends TypedEmitter<TypedDisTubeEvents> {
1230
+ /**
1231
+ * DisTube class
1232
+ */
1233
+ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
1234
+ #private;
1393
1235
  /**
1394
1236
  * @event
1395
1237
  * Emitted after DisTube add a new playlist to the playing {@link Queue}.
1396
- *
1397
- * @example
1398
- * ```ts
1399
- * distube.on("addList", (queue, playlist) => queue.textChannel.send(
1400
- * `Added \`${playlist.name}\` playlist (${playlist.songs.length} songs) to the queue!`
1401
- * ));
1402
- * ```
1403
- *
1404
1238
  * @param queue - The guild queue
1405
1239
  * @param playlist - Playlist info
1406
1240
  */
1407
- [Events.ADD_LIST]: (queue: Queue, playlist: Playlist) => Awaitable;
1241
+ static readonly [Events.ADD_LIST]: (queue: Queue, playlist: Playlist) => Awaitable;
1408
1242
  /**
1409
1243
  * @event
1410
1244
  * Emitted after DisTube add a new song to the playing {@link Queue}.
1411
- *
1412
- * @example
1413
- * ```ts
1414
- * distube.on("addSong", (queue, song) => queue.textChannel.send(
1415
- * `Added ${song.name} - \`${song.formattedDuration}\` to the queue by ${song.user}.`
1416
- * ));
1417
- * ```
1418
- *
1419
1245
  * @param queue - The guild queue
1420
1246
  * @param song - Added song
1421
1247
  */
1422
- [Events.ADD_SONG]: (queue: Queue, song: Song) => Awaitable;
1248
+ static readonly [Events.ADD_SONG]: (queue: Queue, song: Song) => Awaitable;
1423
1249
  /**
1424
1250
  * @event
1425
1251
  * Emitted when a {@link Queue} is deleted with any reasons.
1426
- *
1427
1252
  * @param queue - The guild queue
1428
1253
  */
1429
- [Events.DELETE_QUEUE]: (queue: Queue) => Awaitable;
1254
+ static readonly [Events.DELETE_QUEUE]: (queue: Queue) => Awaitable;
1430
1255
  /**
1431
1256
  * @event
1432
1257
  * Emitted when the bot is disconnected to a voice channel.
1433
- *
1434
1258
  * @param queue - The guild queue
1435
1259
  */
1436
- [Events.DISCONNECT]: (queue: Queue) => Awaitable;
1260
+ static readonly [Events.DISCONNECT]: (queue: Queue) => Awaitable;
1437
1261
  /**
1438
1262
  * @event
1439
- * Emitted when there is no user in the voice channel, {@link DisTubeOptions}.leaveOnEmpty
1440
- * is `true` and there is a playing queue.
1441
- *
1442
- * If there is no playing queue (stopped and {@link DisTubeOptions}.leaveOnStop is
1443
- * `false`), it will leave the channel without emitting this event.
1444
- *
1445
- * @example
1446
- * ```ts
1447
- * distube.on("empty", queue => queue.textChannel.send("Channel is empty. Leaving the channel"))
1448
- * ```
1449
- *
1450
- * @param queue - The guild queue
1263
+ * Emitted when DisTube encounters an error while playing songs.
1264
+ * @param error - error
1265
+ * @param queue - The queue encountered the error
1266
+ * @param song - The playing song when encountered the error
1451
1267
  */
1452
- [Events.EMPTY]: (queue: Queue) => Awaitable;
1268
+ static readonly [Events.ERROR]: (error: Error, queue: Queue, song?: Song) => Awaitable;
1453
1269
  /**
1454
1270
  * @event
1455
- * Emitted when DisTube encounters an error while playing songs.
1456
- *
1457
- * @example
1458
- * ```ts
1459
- * distube.on('error', (channel, e) => {
1460
- * if (channel) channel.send(`An error encountered: ${e}`)
1461
- * else console.error(e)
1462
- * })
1463
- * ```
1464
- *
1465
- * @param channel - Text channel where the error is encountered.
1466
- * @param error - The error encountered
1271
+ * Emitted for logging FFmpeg debug information.
1272
+ * @param debug - Debug message string.
1467
1273
  */
1468
- [Events.ERROR]: (channel: GuildTextBasedChannel | undefined, error: Error) => Awaitable;
1274
+ static readonly [Events.FFMPEG_DEBUG]: (debug: string) => Awaitable;
1469
1275
  /**
1470
1276
  * @event
1471
- * Emitted for FFmpeg debugging information.
1277
+ * Emitted to provide debug information from DisTube's operation.
1278
+ * Useful for troubleshooting or logging purposes.
1472
1279
  *
1473
- * @param debug - The debug information
1280
+ * @param debug - Debug message string.
1474
1281
  */
1475
- [Events.FFMPEG_DEBUG]: (debug: string) => Awaitable;
1282
+ static readonly [Events.DEBUG]: (debug: string) => Awaitable;
1476
1283
  /**
1477
1284
  * @event
1478
- * Emitted when there is no more song in the queue and {@link Queue#autoplay} is
1479
- * `false`. DisTube will leave voice channel if {@link
1480
- * DisTubeOptions}.leaveOnFinish is `true`.
1481
- *
1482
- * @example
1483
- * ```ts
1484
- * distube.on("finish", queue => queue.textChannel.send("No more song in queue"));
1485
- * ```
1486
- *
1285
+ * Emitted when there is no more song in the queue and {@link Queue#autoplay} is `false`.
1487
1286
  * @param queue - The guild queue
1488
1287
  */
1489
- [Events.FINISH]: (queue: Queue) => Awaitable;
1288
+ static readonly [Events.FINISH]: (queue: Queue) => Awaitable;
1490
1289
  /**
1491
1290
  * @event
1492
1291
  * Emitted when DisTube finished a song.
1493
- *
1494
- * @example
1495
- * ```ts
1496
- * distube.on("finishSong", (queue, song) => queue.textChannel.send(`${song.name} has finished!`));
1497
- * ```
1498
- *
1499
1292
  * @param queue - The guild queue
1500
1293
  * @param song - Finished song
1501
1294
  */
1502
- [Events.FINISH_SONG]: (queue: Queue, song: Song) => Awaitable;
1295
+ static readonly [Events.FINISH_SONG]: (queue: Queue, song: Song) => Awaitable;
1503
1296
  /**
1504
1297
  * @event
1505
1298
  * Emitted when DisTube initialize a queue to change queue default properties.
1506
- *
1507
- * @example
1508
- * ```ts
1509
- * distube.on("initQueue", queue => {
1510
- * queue.autoplay = false;
1511
- * queue.volume = 100;
1512
- * });
1513
- * ```ts
1514
- *
1515
1299
  * @param queue - The guild queue
1516
1300
  */
1517
- [Events.INIT_QUEUE]: (queue: Queue) => Awaitable;
1301
+ static readonly [Events.INIT_QUEUE]: (queue: Queue) => Awaitable;
1518
1302
  /**
1519
1303
  * @event
1520
1304
  * Emitted when {@link Queue#autoplay} is `true`, {@link Queue#songs} is empty, and
1521
1305
  * DisTube cannot find related songs to play.
1522
- *
1523
- * @example
1524
- * ```ts
1525
- * distube.on("noRelated", queue => queue.textChannel.send("Can't find related video to play."));
1526
- * ```ts
1527
- *
1528
1306
  * @param queue - The guild queue
1529
1307
  */
1530
- [Events.NO_RELATED]: (queue: Queue) => Awaitable;
1308
+ static readonly [Events.NO_RELATED]: (queue: Queue) => Awaitable;
1531
1309
  /**
1532
1310
  * @event
1533
1311
  * Emitted when DisTube play a song.
1534
- *
1535
1312
  * If {@link DisTubeOptions}.emitNewSongOnly is `true`, this event is not emitted
1536
1313
  * when looping a song or next song is the previous one.
1537
- *
1538
- * @example
1539
- * ```ts
1540
- * distube.on("playSong", (queue, song) => queue.textChannel.send(
1541
- * `Playing \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${song.user}`
1542
- * ));
1543
- * ```ts
1544
- *
1545
1314
  * @param queue - The guild queue
1546
1315
  * @param song - Playing song
1547
1316
  */
1548
- [Events.PLAY_SONG]: (queue: Queue, song: Song) => Awaitable;
1317
+ static readonly [Events.PLAY_SONG]: (queue: Queue, song: Song) => Awaitable;
1549
1318
  /**
1550
- * @event
1551
- * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
1552
- * and the search canceled due to {@link DisTubeOptions |
1553
- * DisTubeOptions.searchTimeout}.
1554
- *
1555
- * @example
1556
- * ```ts
1557
- * // DisTubeOptions.searchSongs > 0
1558
- * distube.on("searchCancel", (message) => message.channel.send(`Searching canceled`));
1559
- * ```ts
1560
- *
1561
- * @param message - The user message called play method
1562
- * @param query - The search query
1319
+ * DisTube internal handler
1563
1320
  */
1564
- [Events.SEARCH_CANCEL]: (message: Message, query: string) => Awaitable;
1321
+ readonly handler: DisTubeHandler;
1565
1322
  /**
1566
- * @event
1567
- * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
1568
- * and after the user chose a search result to play.
1569
- *
1570
- * @param message - The user message called play method
1571
- * @param answer - The answered message of user
1572
- * @param query - The search query
1323
+ * DisTube options
1573
1324
  */
1574
- [Events.SEARCH_DONE]: (message: Message, answer: string, query: string) => Awaitable;
1325
+ readonly options: Options;
1575
1326
  /**
1576
- * @event
1577
- * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
1578
- * and the search canceled due to user's next message is not a number or out of
1579
- * results range.
1580
- *
1581
- * @example
1582
- * ```ts
1583
- * // DisTubeOptions.searchSongs > 0
1584
- * distube.on("searchInvalidAnswer", (message) => message.channel.send(`You answered an invalid number!`));
1585
- * ```ts
1586
- *
1587
- * @param message - The user message called play method
1588
- * @param answer - The answered message of user
1589
- * @param query - The search query
1327
+ * Discord.js v14 client
1590
1328
  */
1591
- [Events.SEARCH_INVALID_ANSWER]: (message: Message, answer: string, query: string) => Awaitable;
1329
+ readonly client: Client;
1592
1330
  /**
1593
- * @event
1594
- * Emitted when DisTube cannot find any results for the query.
1595
- *
1596
- * @example
1597
- * ```ts
1598
- * distube.on("searchNoResult", (message, query) => message.channel.send(`No result found for ${query}!`));
1599
- * ```ts
1600
- *
1601
- * @param message - The user message called play method
1602
- * @param query - The search query
1331
+ * Queues manager
1603
1332
  */
1604
- [Events.SEARCH_NO_RESULT]: (message: Message, query: string) => Awaitable;
1333
+ readonly queues: QueueManager;
1605
1334
  /**
1606
- * @event
1607
- * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
1608
- * and song param of {@link DisTube#play} is invalid url. DisTube will wait for
1609
- * user's next message to choose a song manually. <info>{@link
1610
- * https://support.google.com/youtube/answer/7354993 | Safe search} is enabled if
1611
- * {@link DisTubeOptions}.nsfw is disabled and the message's channel is not a nsfw
1612
- * channel.</info>
1613
- *
1614
- * @example
1615
- * ```ts
1616
- * // DisTubeOptions.searchSongs > 0
1617
- * distube.on("searchResult", (message, results) => {
1618
- * message.channel.send(`**Choose an option from below**\n${
1619
- * results.map((song, i) => `**${i + 1}**. ${song.name} - \`${song.formattedDuration}\``).join("\n")
1620
- * }\n*Enter anything else or wait 60 seconds to cancel*`);
1621
- * });
1622
- * ```ts
1623
- *
1624
- * @param message - The user message called play method
1625
- * @param results - Searched results
1626
- * @param query - The search query
1335
+ * DisTube voice connections manager
1627
1336
  */
1628
- [Events.SEARCH_RESULT]: (message: Message, results: SearchResult[], query: string) => Awaitable;
1629
- }
1630
- /**
1631
- * DisTube class
1632
- */
1633
- declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
1634
- #private;
1635
- readonly handler: DisTubeHandler;
1636
- readonly options: Options;
1637
- readonly client: Client;
1638
- readonly queues: QueueManager;
1639
1337
  readonly voices: DisTubeVoiceManager;
1640
- readonly extractorPlugins: ExtractorPlugin[];
1641
- readonly customPlugins: CustomPlugin[];
1642
- readonly filters: Filters;
1643
1338
  /**
1644
- * @deprecated Use `youtubeCookie: Cookie[]` instead. Guide: {@link
1645
- * https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
1339
+ * DisTube plugins
1340
+ */
1341
+ readonly plugins: DisTubePlugin[];
1342
+ /**
1343
+ * DisTube ffmpeg audio filters
1646
1344
  */
1647
- constructor(client: Client, opts: DisTubeOptions & {
1648
- youtubeCookie: string;
1649
- });
1345
+ readonly filters: Filters;
1650
1346
  /**
1651
1347
  * Create a new DisTube class.
1652
- *
1653
- * @example
1654
- * ```ts
1655
- * const Discord = require('discord.js'),
1656
- * DisTube = require('distube'),
1657
- * client = new Discord.Client();
1658
- * // Create a new DisTube
1659
- * const distube = new DisTube.default(client, { searchSongs: 10 });
1660
- * // client.DisTube = distube // make it access easily
1661
- * client.login("Your Discord Bot Token")
1662
- * ```ts
1663
- *
1664
1348
  * @throws {@link DisTubeError}
1665
- *
1666
1349
  * @param client - Discord.JS client
1667
1350
  * @param opts - Custom DisTube options
1668
1351
  */
@@ -1673,141 +1356,47 @@ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
1673
1356
  */
1674
1357
  get version(): string;
1675
1358
  /**
1676
- * Play / add a song or playlist from url. Search and play a song if it is not a
1677
- * valid url.
1678
- *
1679
- * @example
1680
- * ```ts
1681
- * client.on('message', (message) => {
1682
- * if (!message.content.startsWith(config.prefix)) return;
1683
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1684
- * const command = args.shift();
1685
- * if (command == "play")
1686
- * distube.play(message.member.voice.channel, args.join(" "), {
1687
- * member: message.member,
1688
- * textChannel: message.channel,
1689
- * message
1690
- * });
1691
- * });
1692
- * ```ts
1693
- *
1359
+ * Play / add a song or playlist from url.
1360
+ * Search and play a song (with {@link ExtractorPlugin}) if it is not a valid url.
1694
1361
  * @throws {@link DisTubeError}
1695
- *
1696
1362
  * @param voiceChannel - The channel will be joined if the bot isn't in any channels, the bot will be
1697
1363
  * moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`
1698
- * @param song - URL | Search string | {@link Song} | {@link SearchResult} | {@link Playlist}
1364
+ * @param song - URL | Search string | {@link Song} | {@link Playlist}
1699
1365
  * @param options - Optional options
1700
1366
  */
1701
- play(voiceChannel: VoiceBasedChannel, song: string | Song | SearchResult | Playlist, options?: PlayOptions): Promise<void>;
1367
+ play<T = unknown>(voiceChannel: VoiceBasedChannel, song: string | Song | Playlist, options?: PlayOptions<T>): Promise<void>;
1702
1368
  /**
1703
1369
  * Create a custom playlist
1704
- *
1705
- * @example
1706
- * ```ts
1707
- * const songs = ["https://www.youtube.com/watch?v=xxx", "https://www.youtube.com/watch?v=yyy"];
1708
- * const playlist = await distube.createCustomPlaylist(songs, {
1709
- * member: message.member,
1710
- * properties: { name: "My playlist name", source: "custom" },
1711
- * parallel: true
1712
- * });
1713
- * distube.play(voiceChannel, playlist, { ... });
1714
- * ```ts
1715
- *
1716
- * @param songs - Array of url, Song or SearchResult
1370
+ * @param songs - Array of url or Song
1717
1371
  * @param options - Optional options
1718
1372
  */
1719
- createCustomPlaylist(songs: (string | Song | SearchResult)[], options?: CustomPlaylistOptions): Promise<Playlist>;
1720
- search(string: string, options?: {
1721
- type?: SearchResultType.VIDEO;
1722
- limit?: number;
1723
- safeSearch?: boolean;
1724
- retried?: boolean;
1725
- }): Promise<Array<SearchResultVideo>>;
1726
- search(string: string, options: {
1727
- type: SearchResultType.PLAYLIST;
1728
- limit?: number;
1729
- safeSearch?: boolean;
1730
- retried?: boolean;
1731
- }): Promise<Array<SearchResultPlaylist>>;
1732
- search(string: string, options?: {
1733
- type?: SearchResultType;
1734
- limit?: number;
1735
- safeSearch?: boolean;
1736
- retried?: boolean;
1737
- }): Promise<Array<SearchResult>>;
1373
+ createCustomPlaylist(songs: (string | Song)[], { member, parallel, metadata, name, source, url, thumbnail }?: CustomPlaylistOptions): Promise<Playlist>;
1738
1374
  /**
1739
1375
  * Get the guild queue
1740
- *
1741
- * @example
1742
- * ```ts
1743
- * client.on('message', (message) => {
1744
- * if (!message.content.startsWith(config.prefix)) return;
1745
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1746
- * const command = args.shift();
1747
- * if (command == "queue") {
1748
- * const queue = distube.getQueue(message);
1749
- * message.channel.send('Current queue:\n' + queue.songs.map((song, id) =>
1750
- * `**${id+1}**. [${song.name}](${song.url}) - \`${song.formattedDuration}\``
1751
- * ).join("\n"));
1752
- * }
1753
- * });
1754
- * ```ts
1755
- *
1756
1376
  * @param guild - The type can be resolved to give a {@link Queue}
1757
1377
  */
1758
1378
  getQueue(guild: GuildIdResolvable): Queue | undefined;
1759
1379
  /**
1760
1380
  * Pause the guild stream
1761
- *
1762
1381
  * @param guild - The type can be resolved to give a {@link Queue}
1763
- *
1764
1382
  * @returns The guild queue
1765
1383
  */
1766
1384
  pause(guild: GuildIdResolvable): Queue;
1767
1385
  /**
1768
1386
  * Resume the guild stream
1769
- *
1770
1387
  * @param guild - The type can be resolved to give a {@link Queue}
1771
- *
1772
1388
  * @returns The guild queue
1773
1389
  */
1774
1390
  resume(guild: GuildIdResolvable): Queue;
1775
1391
  /**
1776
1392
  * Stop the guild stream
1777
- *
1778
- * @example
1779
- * ```ts
1780
- * client.on('message', (message) => {
1781
- * if (!message.content.startsWith(config.prefix)) return;
1782
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1783
- * const command = args.shift();
1784
- * if (command == "stop") {
1785
- * distube.stop(message);
1786
- * message.channel.send("Stopped the queue!");
1787
- * }
1788
- * });
1789
- * ```ts
1790
- *
1791
1393
  * @param guild - The type can be resolved to give a {@link Queue}
1792
1394
  */
1793
1395
  stop(guild: GuildIdResolvable): Promise<void>;
1794
1396
  /**
1795
1397
  * Set the guild stream's volume
1796
- *
1797
- * @example
1798
- * ```ts
1799
- * client.on('message', (message) => {
1800
- * if (!message.content.startsWith(config.prefix)) return;
1801
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1802
- * const command = args.shift();
1803
- * if (command == "volume")
1804
- * distube.setVolume(message, Number(args[0]));
1805
- * });
1806
- * ```ts
1807
- *
1808
1398
  * @param guild - The type can be resolved to give a {@link Queue}
1809
1399
  * @param percent - The percentage of volume you want to set
1810
- *
1811
1400
  * @returns The guild queue
1812
1401
  */
1813
1402
  setVolume(guild: GuildIdResolvable, percent: number): Queue;
@@ -1815,180 +1404,69 @@ declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
1815
1404
  * Skip the playing song if there is a next song in the queue. <info>If {@link
1816
1405
  * Queue#autoplay} is `true` and there is no up next song, DisTube will add and
1817
1406
  * play a related song.</info>
1818
- *
1819
- * @example
1820
- * ```ts
1821
- * client.on('message', (message) => {
1822
- * if (!message.content.startsWith(config.prefix)) return;
1823
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1824
- * const command = args.shift();
1825
- * if (command == "skip")
1826
- * distube.skip(message);
1827
- * });
1828
- * ```ts
1829
- *
1830
1407
  * @param guild - The type can be resolved to give a {@link Queue}
1831
- *
1832
1408
  * @returns The new Song will be played
1833
1409
  */
1834
1410
  skip(guild: GuildIdResolvable): Promise<Song>;
1835
1411
  /**
1836
1412
  * Play the previous song
1837
- *
1838
- * @example
1839
- * ```ts
1840
- * client.on('message', (message) => {
1841
- * if (!message.content.startsWith(config.prefix)) return;
1842
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1843
- * const command = args.shift();
1844
- * if (command == "previous")
1845
- * distube.previous(message);
1846
- * });
1847
- * ```ts
1848
- *
1849
1413
  * @param guild - The type can be resolved to give a {@link Queue}
1850
- *
1851
1414
  * @returns The new Song will be played
1852
1415
  */
1853
1416
  previous(guild: GuildIdResolvable): Promise<Song>;
1854
1417
  /**
1855
1418
  * Shuffle the guild queue songs
1856
- *
1857
- * @example
1858
- * ```ts
1859
- * client.on('message', (message) => {
1860
- * if (!message.content.startsWith(config.prefix)) return;
1861
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1862
- * const command = args.shift();
1863
- * if (command == "shuffle")
1864
- * distube.shuffle(message);
1865
- * });
1866
- * ```ts
1867
- *
1868
1419
  * @param guild - The type can be resolved to give a {@link Queue}
1869
- *
1870
1420
  * @returns The guild queue
1871
1421
  */
1872
1422
  shuffle(guild: GuildIdResolvable): Promise<Queue>;
1873
1423
  /**
1874
1424
  * Jump to the song number in the queue. The next one is 1, 2,... The previous one
1875
1425
  * is -1, -2,...
1876
- *
1877
- * @example
1878
- * ```ts
1879
- * client.on('message', (message) => {
1880
- * if (!message.content.startsWith(config.prefix)) return;
1881
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1882
- * const command = args.shift();
1883
- * if (command == "jump")
1884
- * distube.jump(message, parseInt(args[0]))
1885
- * .catch(err => message.channel.send("Invalid song number."));
1886
- * });
1887
- * ```ts
1888
- *
1889
1426
  * @param guild - The type can be resolved to give a {@link Queue}
1890
1427
  * @param num - The song number to play
1891
- *
1892
1428
  * @returns The new Song will be played
1893
1429
  */
1894
1430
  jump(guild: GuildIdResolvable, num: number): Promise<Song>;
1895
1431
  /**
1896
1432
  * Set the repeat mode of the guild queue.
1897
1433
  * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
1898
- *
1899
- * @example
1900
- * ```ts
1901
- * client.on('message', (message) => {
1902
- * if (!message.content.startsWith(config.prefix)) return;
1903
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1904
- * const command = args.shift();
1905
- * if (command == "repeat") {
1906
- * let mode = distube.setRepeatMode(message, parseInt(args[0]));
1907
- * mode = mode ? mode == 2 ? "Repeat queue" : "Repeat song" : "Off";
1908
- * message.channel.send("Set repeat mode to `" + mode + "`");
1909
- * }
1910
- * });
1911
- * ```ts
1912
- * @example
1913
- * ```ts
1914
- * const { RepeatMode } = require("distube");
1915
- * let mode;
1916
- * switch(distube.setRepeatMode(message, parseInt(args[0]))) {
1917
- * case RepeatMode.DISABLED:
1918
- * mode = "Off";
1919
- * break;
1920
- * case RepeatMode.SONG:
1921
- * mode = "Repeat a song";
1922
- * break;
1923
- * case RepeatMode.QUEUE:
1924
- * mode = "Repeat all queue";
1925
- * break;
1926
- * }
1927
- * message.channel.send("Set repeat mode to `" + mode + "`");
1928
- * ```ts
1929
- *
1930
1434
  * @param guild - The type can be resolved to give a {@link Queue}
1931
1435
  * @param mode - The repeat modes (toggle if `undefined`)
1932
- *
1933
1436
  * @returns The new repeat mode
1934
1437
  */
1935
- setRepeatMode(guild: GuildIdResolvable, mode?: number): number;
1438
+ setRepeatMode(guild: GuildIdResolvable, mode?: RepeatMode): RepeatMode;
1936
1439
  /**
1937
1440
  * Toggle autoplay mode
1938
- *
1939
- * @example
1940
- * ```ts
1941
- * client.on('message', (message) => {
1942
- * if (!message.content.startsWith(config.prefix)) return;
1943
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1944
- * const command = args.shift();
1945
- * if (command == "autoplay") {
1946
- * const mode = distube.toggleAutoplay(message);
1947
- * message.channel.send("Set autoplay mode to `" + (mode ? "On" : "Off") + "`");
1948
- * }
1949
- * });
1950
- * ```ts
1951
- *
1952
1441
  * @param guild - The type can be resolved to give a {@link Queue}
1953
- *
1954
1442
  * @returns Autoplay mode state
1955
1443
  */
1956
1444
  toggleAutoplay(guild: GuildIdResolvable): boolean;
1957
1445
  /**
1958
1446
  * Add related song to the queue
1959
- *
1960
1447
  * @param guild - The type can be resolved to give a {@link Queue}
1961
- *
1962
1448
  * @returns The guild queue
1963
1449
  */
1964
1450
  addRelatedSong(guild: GuildIdResolvable): Promise<Song>;
1965
1451
  /**
1966
1452
  * Set the playing time to another position
1967
- *
1968
- * @example
1969
- * ```ts
1970
- * client.on('message', message => {
1971
- * if (!message.content.startsWith(config.prefix)) return;
1972
- * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
1973
- * const command = args.shift();
1974
- * if (command = 'seek')
1975
- * distube.seek(message, Number(args[0]));
1976
- * });
1977
- * ```ts
1978
- *
1979
1453
  * @param guild - The type can be resolved to give a {@link Queue}
1980
1454
  * @param time - Time in seconds
1981
- *
1982
1455
  * @returns Seeked queue
1983
1456
  */
1984
1457
  seek(guild: GuildIdResolvable, time: number): Queue;
1985
1458
  /**
1986
1459
  * Emit error event
1987
- *
1988
1460
  * @param error - error
1989
- * @param channel - Text channel where the error is encountered.
1461
+ * @param queue - The queue encountered the error
1462
+ * @param song - The playing song when encountered the error
1463
+ */
1464
+ emitError(error: Error, queue: Queue, song?: Song): void;
1465
+ /**
1466
+ * Emit debug event
1467
+ * @param message - debug message
1990
1468
  */
1991
- emitError(error: Error, channel?: GuildTextBasedChannel): void;
1469
+ debug(message: string): void;
1992
1470
  }
1993
1471
 
1994
- export { type Awaitable, BaseManager, type Chapter, type CustomPlaylistOptions, CustomPlugin, DirectLinkPlugin, DisTube, DisTubeBase, DisTubeError, type DisTubeEvents, DisTubeHandler, type DisTubeOptions, DisTubeStream, DisTubeVoice, type DisTubeVoiceEvents, DisTubeVoiceManager, Events, ExtractorPlugin, type FFmpegArgs, type FFmpegOptions, type Filter, FilterManager, type FilterResolvable, type Filters, GuildIdManager, type GuildIdResolvable, Options, type OtherSongInfo, type PlayHandlerOptions, type PlayOptions, Playlist, type PlaylistInfo, Plugin, PluginType, Queue, QueueManager, type RelatedSong, RepeatMode, type ResolveOptions, type ResolvePlaylistOptions, type SearchResult, SearchResultPlaylist, SearchResultType, SearchResultVideo, Song, StreamType, TaskQueue, type TypedDisTubeEvents, checkFFmpeg, checkIntents, checkInvalidKey, chooseBestVideoFormat, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isNsfwChannel, isObject, isRecord, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isTruthy, isURL, isVoiceChannelEmpty, objectKeys, parseNumber, resolveGuildId, toSecond, version };
1472
+ export { type Awaitable, BaseManager, type CustomPlaylistOptions, DisTube, DisTubeBase, DisTubeError, type DisTubeEvents, DisTubeHandler, type DisTubeOptions, type DisTubePlugin, DisTubeStream, DisTubeVoice, type DisTubeVoiceEvents, DisTubeVoiceManager, Events, ExtractorPlugin, type FFmpegArg, type FFmpegArgs, type FFmpegOptions, type Falsy, type Filter, FilterManager, type FilterResolvable, type Filters, GuildIdManager, type GuildIdResolvable, InfoExtractorPlugin, type KeyOf, Options, type PlayHandlerOptions, type PlayOptions, PlayableExtractorPlugin, Playlist, type PlaylistInfo, Plugin, PluginType, Queue, QueueManager, type RelatedSong, RepeatMode, type ResolveOptions, type ResolvePlaylistOptions, Song, type SongInfo, type StreamOptions, TaskQueue, type TypedDisTubeEvents, checkFFmpeg, checkIntents, checkInvalidKey, DisTube as default, defaultFilters, defaultOptions, formatDuration, isClientInstance, isGuildInstance, isMemberInstance, isMessageInstance, isNsfwChannel, isObject, isSnowflake, isSupportedVoiceChannel, isTextChannelInstance, isTruthy, isURL, isVoiceChannelEmpty, objectKeys, resolveGuildId, version };