🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

distube

Package Overview
Dependencies
Maintainers
1
Versions
201
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

distube - npm Package Compare versions

Comparing version

to
5.0.0

1451

dist/index.d.ts

@@ -1,31 +0,37 @@

import * as ytdl from '@distube/ytdl-core';
import ytdl__default, { Cookie } from '@distube/ytdl-core';
import * as discord_js from 'discord.js';
import { GuildTextBasedChannel, Message, Snowflake, VoiceBasedChannel, VoiceState, Guild, GuildMember, Interaction, Client, Collection, ClientOptions } from 'discord.js';
import ytpl from '@distube/ytpl';
import { Video, Playlist as Playlist$1 } from '@distube/ytsr';
import { Snowflake, Message, GuildTextBasedChannel, VoiceBasedChannel, VoiceState, Guild, GuildMember, Interaction, Client, Collection, ClientOptions } from 'discord.js';
import { TypedEmitter } from 'tiny-typed-emitter';
import { AudioPlayer, VoiceConnection, AudioResource, StreamType as StreamType$1 } from '@discordjs/voice';
import { PassThrough } from 'node:stream';
import { AudioPlayer, VoiceConnection, AudioResource } from '@discordjs/voice';
import { Transform, TransformCallback } from 'stream';
import { ChildProcess } from 'child_process';
type Awaitable<T = any> = T | PromiseLike<T>;
declare enum Events {
ERROR = "error",
ADD_LIST = "addList",
ADD_SONG = "addSong",
PLAY_SONG = "playSong",
FINISH_SONG = "finishSong",
EMPTY = "empty",
FINISH = "finish",
INIT_QUEUE = "initQueue",
NO_RELATED = "noRelated",
DISCONNECT = "disconnect",
DELETE_QUEUE = "deleteQueue",
FFMPEG_DEBUG = "ffmpegDebug",
DEBUG = "debug"
}
type DisTubeEvents = {
addList: [queue: Queue, playlist: Playlist];
addSong: [queue: Queue, song: Song];
deleteQueue: [queue: Queue];
disconnect: [queue: Queue];
empty: [queue: Queue];
error: [channel: GuildTextBasedChannel | undefined, error: Error];
ffmpegDebug: [debug: string];
finish: [queue: Queue];
finishSong: [queue: Queue, song: Song];
initQueue: [queue: Queue];
noRelated: [queue: Queue];
playSong: [queue: Queue, song: Song];
searchCancel: [message: Message<true>, query: string];
searchDone: [message: Message<true>, answer: Message<true>, query: string];
searchInvalidAnswer: [message: Message<true>, answer: Message<true>, query: string];
searchNoResult: [message: Message<true>, query: string];
searchResult: [message: Message<true>, results: SearchResult[], query: string];
[Events.ADD_LIST]: [queue: Queue, playlist: Playlist];
[Events.ADD_SONG]: [queue: Queue, song: Song];
[Events.DELETE_QUEUE]: [queue: Queue];
[Events.DISCONNECT]: [queue: Queue];
[Events.ERROR]: [error: Error, queue: Queue, song: Song | undefined];
[Events.FFMPEG_DEBUG]: [debug: string];
[Events.DEBUG]: [debug: string];
[Events.FINISH]: [queue: Queue];
[Events.FINISH_SONG]: [queue: Queue, song: Song];
[Events.INIT_QUEUE]: [queue: Queue];
[Events.NO_RELATED]: [queue: Queue, error: DisTubeError];
[Events.PLAY_SONG]: [queue: Queue, song: Song];
};

@@ -42,3 +48,2 @@ type TypedDisTubeEvents = {

* An FFmpeg audio filter object
*
* ```ts

@@ -63,6 +68,4 @@ * {

* Data that resolves to give an FFmpeg audio filter. This can be:
*
* - A name of a default filters or custom filters (`string`)
* - A {@link Filter} object
*
* @see {@link defaultFilters}

@@ -74,3 +77,2 @@ * @see {@link DisTubeOptions|DisTubeOptions.customFilters}

* FFmpeg Filters
*
* ```ts

@@ -81,4 +83,3 @@ * {

* }
* ```ts
*
* ```
* @see {@link defaultFilters}

@@ -92,7 +93,8 @@ */

/**
* DisTube plugins
* DisTube plugins.
* The order of this effects the priority of the plugins when verifying the input.
*/
plugins?: (CustomPlugin | ExtractorPlugin)[];
plugins?: DisTubePlugin[];
/**
* Whether or not emitting {@link DisTube#playSong} event when looping a song
* Whether or not emitting {@link Events.PLAY_SONG} event when looping a song
* or next song is the same as the previous one

@@ -102,39 +104,7 @@ */

/**
* Whether or not leaving voice channel if the voice channel is empty after {@link
* DisTubeOptions}.emptyCooldown seconds
*/
leaveOnEmpty?: boolean;
/**
* Whether or not leaving voice channel when the queue ends
*/
leaveOnFinish?: boolean;
/**
* Whether or not leaving voice channel after using {@link DisTube#stop} function
*/
leaveOnStop?: boolean;
/**
* Built-in leave on empty cooldown in seconds (When leaveOnEmpty is true)
*/
emptyCooldown?: number;
/**
* Whether or not saving the previous songs of the queue and enable {@link
* DisTube#previous} method
* DisTube#previous} method. Disable it may help to reduce the memory usage
*/
savePreviousSongs?: boolean;
/**
* Limit of search results emits in {@link DisTube#searchResult} event when
* {@link DisTube#play} method executed. If `searchSongs <= 1`, play the first
* result
*/
searchSongs?: number;
/**
* Built-in search cooldown in seconds (When searchSongs is bigger than 0)
*/
searchCooldown?: number;
/**
* YouTube cookies. Guide: {@link
* https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
*/
youtubeCookie?: Cookie[] | string;
/**
* Override {@link defaultFilters} or add more ffmpeg filters

@@ -144,6 +114,2 @@ */

/**
* `ytdl-core` get info options
*/
ytdlOptions?: ytdl__default.downloadOptions;
/**
* Whether or not playing age-restricted content and disabling safe search in

@@ -167,21 +133,2 @@ * non-NSFW channel

/**
* Decide the {@link DisTubeStream#type} will be used (Not the same as {@link
* DisTubeStream#type})
*/
streamType?: StreamType;
/**
* Whether or not playing a song with direct link
*/
directLink?: boolean;
/**
* FFmpeg path
* @deprecated
*/
ffmpegPath?: string;
/**
* FFmpeg default arguments
* @deprecated
*/
ffmpegDefaultArgs?: FFmpegArgs;
/**
* FFmpeg options

@@ -197,7 +144,3 @@ */

*/
args?: {
global?: FFmpegArgs;
input?: FFmpegArgs;
output?: FFmpegArgs;
};
args?: Partial<FFmpegArgs>;
};

@@ -207,3 +150,2 @@ };

* Data that can be resolved to give a guild id string. This can be:
*
* - A guild id string | a guild {@link https://discord.js.org/#/docs/main/stable/class/Snowflake|Snowflake}

@@ -226,51 +168,30 @@ * - A {@link https://discord.js.org/#/docs/main/stable/class/Guild | Guild}

type GuildIdResolvable = Queue | DisTubeVoice | Snowflake | Message | GuildTextBasedChannel | VoiceBasedChannel | VoiceState | Guild | GuildMember | Interaction | string;
interface OtherSongInfo {
src: string;
interface SongInfo {
plugin: DisTubePlugin | null;
source: string;
playFromSource: boolean;
streamURL?: string;
id?: string;
title?: string;
name?: string;
is_live?: boolean;
isLive?: boolean;
_duration_raw?: string | number;
duration?: string | number;
webpage_url?: string;
url: string;
duration?: number;
url?: string;
thumbnail?: string;
related?: RelatedSong[];
view_count?: string | number;
views?: string | number;
like_count?: string | number;
likes?: string | number;
dislike_count?: string | number;
dislikes?: string | number;
repost_count?: string | number;
reposts?: string | number;
uploader?: string | {
name: string;
url: string;
views?: number;
likes?: number;
dislikes?: number;
reposts?: number;
uploader?: {
name?: string;
url?: string;
};
uploader_url?: string;
age_limit?: string | number;
chapters?: Chapter[];
age_restricted?: boolean;
ageRestricted?: boolean;
}
interface Chapter {
title: string;
start_time: number;
}
interface PlaylistInfo {
source: string;
member?: GuildMember;
songs: Song[];
id?: string;
name?: string;
url?: string;
thumbnail?: string;
/**
* @deprecated Use {@link PlaylistInfo#name}
*/
title?: string;
/**
* @deprecated Use {@link PlaylistInfo#url}
*/
webpage_url?: string;
}

@@ -294,3 +215,3 @@ type RelatedSong = Omit<Song, "related">;

};
interface PlayOptions extends PlayHandlerOptions, ResolveOptions<any> {
interface PlayOptions<T = unknown> extends PlayHandlerOptions, ResolveOptions<T> {
/**

@@ -325,6 +246,2 @@ * Called message (For built-in search events. If this is a {@link

/**
* Additional properties such as `name`
*/
properties?: Record<string, any>;
/**
* Whether or not fetch the songs in parallel

@@ -337,6 +254,21 @@ */

metadata?: any;
/**
* Playlist name
*/
name?: string;
/**
* Playlist source
*/
source?: string;
/**
* Playlist url
*/
url?: string;
/**
* Playlist thumbnail
*/
thumbnail?: string;
}
/**
* The repeat mode of a {@link Queue}
*
* - `DISABLED` = 0

@@ -353,57 +285,33 @@ * - `SONG` = 1

* All available plugin types:
*
* - `CUSTOM` = `"custom"`: {@link CustomPlugin}
* - `EXTRACTOR` = `"extractor"`: {@link ExtractorPlugin}
* - `INFO_EXTRACTOR` = `"info-extractor"`: {@link InfoExtractorPlugin}
* - `PLAYABLE_EXTRACTOR` = `"playable-extractor"`: {@link PlayableExtractorPlugin}
*/
declare enum PluginType {
CUSTOM = "custom",
EXTRACTOR = "extractor"
EXTRACTOR = "extractor",
INFO_EXTRACTOR = "info-extractor",
PLAYABLE_EXTRACTOR = "playable-extractor"
}
type DisTubePlugin = ExtractorPlugin | InfoExtractorPlugin | PlayableExtractorPlugin;
type FFmpegArg = Record<string, string | number | boolean | Array<string | null | undefined> | null | undefined>;
/**
* Search result types:
*
* - `VIDEO` = `"video"`
* - `PLAYLIST` = `"playlist"`
* FFmpeg arguments for different use cases
*/
declare enum SearchResultType {
VIDEO = "video",
PLAYLIST = "playlist"
}
type FFmpegArgs = {
global: FFmpegArg;
input: FFmpegArg;
output: FFmpegArg;
};
/**
* Stream types:
*
* - `OPUS` = `0` (Better quality, use more resources - **Recommended**)
* - `RAW` = `1` (Better performance, use less resources)
* FFmpeg options
*/
declare enum StreamType {
OPUS = 0,
RAW = 1
}
declare enum Events {
ERROR = "error",
ADD_LIST = "addList",
ADD_SONG = "addSong",
PLAY_SONG = "playSong",
FINISH_SONG = "finishSong",
EMPTY = "empty",
FINISH = "finish",
INIT_QUEUE = "initQueue",
NO_RELATED = "noRelated",
DISCONNECT = "disconnect",
DELETE_QUEUE = "deleteQueue",
SEARCH_CANCEL = "searchCancel",
SEARCH_NO_RESULT = "searchNoResult",
SEARCH_DONE = "searchDone",
SEARCH_INVALID_ANSWER = "searchInvalidAnswer",
SEARCH_RESULT = "searchResult",
FFMPEG_DEBUG = "ffmpegDebug"
}
type FFmpegArgs = Record<string, string | number | boolean | Array<string | null | undefined> | null | undefined>;
type FFmpegOptions = {
/**
* Path to the ffmpeg executable
*/
path: string;
args: {
global: FFmpegArgs;
input: FFmpegArgs;
output: FFmpegArgs;
};
/**
* Arguments
*/
args: FFmpegArgs;
};

@@ -418,10 +326,3 @@

emitNewSongOnly: false;
leaveOnEmpty: true;
leaveOnFinish: false;
leaveOnStop: true;
savePreviousSongs: true;
searchSongs: number;
ytdlOptions: {};
searchCooldown: number;
emptyCooldown: number;
nsfw: false;

@@ -431,4 +332,2 @@ emitAddSongWhenCreatingQueue: true;

joinNewVoiceChannel: true;
streamType: StreamType.OPUS;
directLink: true;
};

@@ -450,2 +349,3 @@

VOICE_FULL: string;
VOICE_ALREADY_CREATED: string;
VOICE_CONNECT_FAILED: (s: number) => string;

@@ -460,2 +360,3 @@ VOICE_MISSING_PERMS: string;

QUEUE_EXIST: string;
QUEUE_STOPPED: string;
PAUSED: string;

@@ -466,4 +367,3 @@ RESUMED: string;

NO_SONG_POSITION: string;
NO_PLAYING: string;
NO_RESULT: string;
NO_PLAYING_SONG: string;
NO_RELATED: string;

@@ -475,4 +375,9 @@ CANNOT_PLAY_RELATED: string;

NOT_SUPPORTED_URL: string;
NOT_SUPPORTED_SONG: (song: string) => string;
NO_VALID_SONG: string;
CANNOT_RESOLVE_SONG: (t: any) => string;
NO_VALID_SONG: string;
CANNOT_GET_STREAM_URL: (song: string) => string;
CANNOT_GET_SEARCH_QUERY: (song: string) => string;
NO_RESULT: (query: string) => string;
NO_STREAM_URL: (song: string) => string;
EMPTY_FILTERED_PLAYLIST: string;

@@ -487,8 +392,8 @@ EMPTY_PLAYLIST: string;

type TemplateErrorCode = Exclude<keyof typeof ERROR_MESSAGES, StaticErrorCode>;
declare class DisTubeError<T extends string> extends Error {
declare class DisTubeError<T extends string = any> extends Error {
errorCode: string;
constructor(code: StaticErrorCode);
constructor(code: T extends StaticErrorCode ? T : never);
constructor(code: T extends TemplateErrorCode ? T : never, ...args: Parameters<ErrorMessage[typeof code]>);
constructor(code: TemplateErrorCode, _: never);
constructor(code: T extends ErrorCode ? "This is built-in error code" : T, message: string);
constructor(code: T extends ErrorCode ? never : T, message: string);
get name(): string;

@@ -505,6 +410,4 @@ get code(): string;

* Waits for last task finished and queues a new task
*
* @param resolveInfo - Whether the task is a resolving info task
*/
queuing(resolveInfo?: boolean): Promise<void>;
queuing(): Promise<void>;
/**

@@ -518,6 +421,2 @@ * Removes the finished task and processes the next task

get remaining(): number;
/**
* Whether or not having a resolving info task
*/
get hasResolveTask(): boolean;
}

@@ -530,19 +429,32 @@

#private;
/**
* Playlist source.
*/
source: string;
/**
* Songs in the playlist.
*/
songs: Song[];
name: string;
/**
* Playlist ID.
*/
id?: string;
/**
* Playlist name.
*/
name?: string;
/**
* Playlist URL.
*/
url?: string;
/**
* Playlist thumbnail.
*/
thumbnail?: string;
[x: string]: any;
/**
* Create a playlist
*
* @param playlist - Playlist
* @param options - Optional options
* Create a Playlist
* @param playlist - Raw playlist info
* @param options - Optional data
*/
constructor(playlist: Song[] | PlaylistInfo, options?: {
member?: GuildMember;
properties?: Record<string, any>;
metadata?: T;
});
constructor(playlist: PlaylistInfo, { member, metadata }?: ResolveOptions<T>);
/**

@@ -565,2 +477,5 @@ * Playlist duration in second.

get user(): discord_js.User | undefined;
/**
* Optional metadata that can be used to identify the playlist.
*/
get metadata(): T;

@@ -571,74 +486,57 @@ set metadata(metadata: T);

/**
* A abstract class representing a search result.
*
* @virtual
*/
declare abstract class ISearchResult {
source: "youtube";
abstract type: SearchResultType;
id: string;
name: string;
url: string;
uploader: {
name?: string;
url?: string;
};
/**
* Create a search result
*
* @param info - ytsr result
*/
constructor(info: Video | Playlist$1);
}
/**
* A class representing a video search result.
*/
declare class SearchResultVideo extends ISearchResult {
type: SearchResultType.VIDEO;
views: number;
isLive: boolean;
duration: number;
formattedDuration: string;
thumbnail: string;
constructor(info: Video);
}
/**
* A video or playlist search result
*/
type SearchResult = SearchResultVideo | SearchResultPlaylist;
/**
* A class representing a playlist search result.
*/
declare class SearchResultPlaylist extends ISearchResult {
type: SearchResultType.PLAYLIST;
length: number;
constructor(info: Playlist$1);
}
/**
* Class representing a song.
*
* <info>If {@link Song} is added from a YouTube {@link SearchResult} or {@link
* Playlist}, some info will be missing to save your resources. It will be filled
* when emitting {@link DisTube#playSong} event.
*
* Missing info: {@link Song#likes}, {@link Song#dislikes}, {@link Song#streamURL},
* {@link Song#related}, {@link Song#chapters}, {@link Song#age_restricted}</info>
*/
declare class Song<T = unknown> {
#private;
/**
* The source of this song info
*/
source: string;
formats?: ytdl__default.videoFormat[];
/**
* Song ID.
*/
id?: string;
/**
* Song name.
*/
name?: string;
isLive: boolean;
/**
* Indicates if the song is an active live.
*/
isLive?: boolean;
/**
* Song duration.
*/
duration: number;
formattedDuration?: string;
url: string;
streamURL?: string;
/**
* Formatted duration string (`hh:mm:ss`, `mm:ss` or `Live`).
*/
formattedDuration: string;
/**
* Song URL.
*/
url?: string;
/**
* Song thumbnail.
*/
thumbnail?: string;
related: RelatedSong[];
views: number;
likes: number;
dislikes: number;
/**
* Song view count
*/
views?: number;
/**
* Song like count
*/
likes?: number;
/**
* Song dislike count
*/
dislikes?: number;
/**
* Song repost (share) count
*/
reposts?: number;
/**
* Song uploader
*/
uploader: {

@@ -648,25 +546,41 @@ name?: string;

};
age_restricted: boolean;
chapters: Chapter[];
reposts: number;
/**
* Create a Song
*
* @param info - Raw info
* @param options - Optional options
* Whether or not an age-restricted content
*/
constructor(info: ytdl__default.videoInfo | SearchResult | OtherSongInfo | ytdl__default.relatedVideo | RelatedSong | ytpl.result["items"][number], options?: {
member?: GuildMember;
source?: string;
metadata?: T;
});
_patchYouTube(i: ytdl__default.videoInfo | SearchResult): void;
ageRestricted?: boolean;
/**
* Patch data from other source
* Stream info
*/
stream: {
/**
* The stream of this song will be played from source
*/
playFromSource: true;
/**
* Stream URL of this song
*/
url?: string;
} | {
/**
* The stream of this song will be played from another song
*/
playFromSource: false;
/**
* The song that this song will be played from
*/
song?: Song<T>;
};
/**
* The plugin that created this song
*/
plugin: DisTubePlugin | null;
/**
* Create a Song
*
* @param info - Video info
* @param info - Raw song info
* @param options - Optional data
*/
_patchOther(info: OtherSongInfo): void;
constructor(info: SongInfo, { member, metadata }?: ResolveOptions<T>);
/**
* The playlist added this song
* The playlist this song belongs to
*/

@@ -676,3 +590,3 @@ get playlist(): Playlist | undefined;

/**
* User requested.
* User requested to play this song.
*/

@@ -682,12 +596,14 @@ get member(): GuildMember | undefined;

/**
* User requested.
* User requested to play this song.
*/
get user(): discord_js.User | undefined;
/**
* Optional metadata that can be used to identify the song. This is attached by the
* {@link DisTube#play} method.
*/
get metadata(): T;
set metadata(metadata: T);
toString(): string;
}
/**
* @virtual
*/
declare abstract class DisTubeBase {

@@ -698,3 +614,2 @@ distube: DisTube;

* Emit the {@link DisTube} of this base
*
* @param eventName - Event name

@@ -706,8 +621,13 @@ * @param args - arguments

* Emit error event
*
* @param error - error
* @param channel - Text channel where the error is encountered.
* @param queue - The queue encountered the error
* @param song - The playing song when encountered the error
*/
emitError(error: Error, channel?: GuildTextBasedChannel): void;
emitError(error: Error, queue: Queue, song?: Song): void;
/**
* Emit debug event
* @param message - debug message
*/
debug(message: string): void;
/**
* The queue manager

@@ -732,2 +652,6 @@ */

get handler(): DisTubeHandler;
/**
* DisTube plugins
*/
get plugins(): DisTubePlugin[];
}

@@ -744,3 +668,2 @@

connection: VoiceConnection;
audioResource?: AudioResource;
emittedError: boolean;

@@ -758,3 +681,2 @@ isDisconnected: boolean;

* Join a voice channel with this connection
*
* @param channel - A voice channel

@@ -765,3 +687,2 @@ */

* Leave the voice channel of this connection
*
* @param error - Optional, an error to emit with 'error' event.

@@ -772,5 +693,4 @@ */

* Stop the playing stream
*
* @param force - If true, will force the {@link DisTubeVoice#audioPlayer} to enter the Idle state even
* if the {@link DisTubeVoice#audioResource} has silence padding frames.
* if the {@link DisTubeStream#audioResource} has silence padding frames.
*/

@@ -780,3 +700,2 @@ stop(force?: boolean): void;

* Play a {@link DisTubeStream}
*
* @param dtStream - DisTubeStream

@@ -786,2 +705,5 @@ */

set volume(volume: number);
/**
* Get or set the volume percentage
*/
get volume(): number;

@@ -804,5 +726,3 @@ /**

* Self-deafens/undeafens the bot.
*
* @param selfDeaf - Whether or not the bot should be self-deafened
*
* @returns true if the voice state was successfully updated, otherwise false

@@ -813,5 +733,3 @@ */

* Self-mutes/unmutes the bot.
*
* @param selfMute - Whether or not the bot should be self-muted
*
* @returns true if the voice state was successfully updated, otherwise false

@@ -826,8 +744,16 @@ */

/**
* Options for {@link DisTubeStream}
*/
interface StreamOptions {
/**
* FFmpeg options
*/
ffmpeg: FFmpegOptions;
/**
* Seek time (in seconds).
* @default 0
*/
seek?: number;
type?: StreamType;
}
declare const chooseBestVideoFormat: ({ duration, formats, isLive }: Song) => ytdl.videoFormat | undefined;
declare const checkFFmpeg: (distube: DisTube) => void;

@@ -841,31 +767,23 @@ /**

}> {
private killed;
process: ChildProcess;
stream: PassThrough;
type: StreamType$1;
url: string;
#private;
process?: ChildProcess;
stream: VolumeTransformer;
audioResource: AudioResource;
/**
* Create a DisTubeStream to play with {@link DisTubeVoice}
*
* @param url - Stream URL
* @param options - Stream options
*/
constructor(url: string, { ffmpeg, seek, type }: StreamOptions);
constructor(url: string, options: StreamOptions);
spawn(): void;
private debug;
setVolume(volume: number): void;
kill(): void;
/**
* Create a stream from a YouTube {@link Song}
*
* @param song - A YouTube Song
* @param options - options
*/
static YouTube(song: Song, options: StreamOptions): DisTubeStream;
/**
* Create a stream from a stream url
*
* @param url - stream url
* @param options - options
*/
static DirectLink(url: string, options: StreamOptions): DisTubeStream;
}
declare class VolumeTransformer extends Transform {
private buffer;
private readonly extrema;
vol: number;
_transform(newChunk: Buffer, _encoding: BufferEncoding, done: TransformCallback): void;
}

@@ -877,71 +795,19 @@ /**

#private;
constructor(distube: DisTube);
get ytdlOptions(): ytdl__default.getInfoOptions;
get ytCookie(): string;
/**
* @param url - url
* @param basic - getBasicInfo?
*/
getYouTubeInfo(url: string, basic?: boolean): Promise<ytdl__default.videoInfo>;
resolve<T = unknown>(song: Song<T>, options?: Omit<ResolveOptions, "metadata">): Promise<Song<T>>;
resolve<T = unknown>(song: Playlist<T>, options?: Omit<ResolveOptions, "metadata">): Promise<Playlist<T>>;
resolve<T = unknown>(song: string | SearchResult, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;
resolve<T = unknown>(song: ytdl__default.videoInfo | OtherSongInfo | ytdl__default.relatedVideo, options?: ResolveOptions<T>): Promise<Song<T>>;
resolve<T = unknown>(song: string, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;
resolve<T = unknown>(song: Song, options: ResolveOptions<T>): Promise<Song<T>>;
resolve<T = unknown>(song: Playlist, options: ResolveOptions<T>): Promise<Playlist<T>>;
resolve(song: string | ytdl__default.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl__default.relatedVideo, options?: ResolveOptions): Promise<Song | Playlist>;
resolvePlaylist<T = unknown>(playlist: Playlist<T> | Song<T>[] | string, options?: Omit<ResolvePlaylistOptions, "metadata">): Promise<Playlist<T>>;
resolvePlaylist<T = undefined>(playlist: Playlist | Song[] | string, options: ResolvePlaylistOptions<T>): Promise<Playlist<T>>;
resolvePlaylist(playlist: Playlist | Song[] | string, options?: ResolvePlaylistOptions): Promise<Playlist>;
resolve(song: string | Song | Playlist, options?: ResolveOptions): Promise<Song | Playlist>;
_getPluginFromURL(url: string): Promise<DisTubePlugin | null>;
_getPluginFromSong(song: Song): Promise<DisTubePlugin | null>;
_getPluginFromSong<T extends PluginType>(song: Song, types: T[], validate?: boolean): Promise<(DisTubePlugin & {
type: T;
}) | null>;
/**
* Search for a song, fire {@link DisTube#error} if not found.
*
* @throws {@link DisTubeError}
*
* @param message - The original message from an user
* @param query - The query string
*
* @returns Song info
*/
searchSong(message: Message<true>, query: string): Promise<SearchResult | null>;
/**
* Create a message collector for selecting search results.
*
* Needed events: {@link DisTube#searchResult}, {@link DisTube#searchCancel},
* {@link DisTube#searchInvalidAnswer}, {@link DisTube#searchDone}.
*
* @throws {@link DisTubeError}
*
* @param message - The original message from an user
* @param results - The search results
* @param query - The query string
*
* @returns Selected result
*/
createSearchMessageCollector<R extends SearchResult | Song | Playlist>(message: Message<true>, results: Array<R>, query?: string): Promise<R | null>;
/**
* Play or add a {@link Playlist} to the queue.
*
* @throws {@link DisTubeError}
*
* @param voiceChannel - A voice channel
* @param playlist - A YouTube playlist url | a Playlist
* @param options - Optional options
*/
playPlaylist(voiceChannel: VoiceBasedChannel, playlist: Playlist, options?: PlayHandlerOptions): Promise<void>;
/**
* Play or add a {@link Song} to the queue.
*
* @throws {@link DisTubeError}
*
* @param voiceChannel - A voice channel
* @param song - A YouTube playlist url | a Playlist
* @param options - Optional options
*/
playSong(voiceChannel: VoiceBasedChannel, song: Song, options?: PlayHandlerOptions): Promise<void>;
/**
* Get {@link Song}'s stream info and attach it to the song.
*
* @param song - A Song
*/
attachStreamInfo(song: Song): Promise<void>;
followRedirectLink(url: string, maxRedirect?: number): Promise<string>;
}

@@ -951,14 +817,6 @@

#private;
plugins: (CustomPlugin | ExtractorPlugin)[];
plugins: DisTubePlugin[];
emitNewSongOnly: boolean;
leaveOnFinish: boolean;
leaveOnStop: boolean;
leaveOnEmpty: boolean;
emptyCooldown: number;
savePreviousSongs: boolean;
searchSongs: number;
searchCooldown: number;
youtubeCookie?: Cookie[] | string;
customFilters?: Filters;
ytdlOptions: ytdl__default.getInfoOptions;
nsfw: boolean;

@@ -968,8 +826,2 @@ emitAddSongWhenCreatingQueue: boolean;

joinNewVoiceChannel: boolean;
streamType: StreamType;
directLink: boolean;
/** @deprecated */
ffmpegPath: undefined;
/** @deprecated */
ffmpegDefaultArgs: undefined;
ffmpeg: FFmpegOptions;

@@ -981,4 +833,2 @@ constructor(options: DisTubeOptions);

* Manages the collection of a data model.
*
* @virtual
*/

@@ -998,4 +848,2 @@ declare abstract class BaseManager<V> extends DisTubeBase {

* Manages the collection of a data model paired with a guild id.
*
* @virtual
*/

@@ -1010,16 +858,7 @@ declare abstract class GuildIdManager<V> extends BaseManager<V> {

/**
* Manages voice connections for {@link DisTube}
* Manages voice connections
*/
declare class DisTubeVoiceManager extends GuildIdManager<DisTubeVoice> {
/**
* Get a {@link DisTubeVoice}.
*
* @param guild - The queue resolvable to resolve
*/
/**
* Collection of {@link DisTubeVoice}.
*/
/**
* Create a {@link DisTubeVoice}
*
* Create a {@link DisTubeVoice} instance
* @param channel - A voice channel to join

@@ -1029,4 +868,3 @@ */

/**
* Join a voice channel
*
* Join a voice channel and wait until the connection is ready
* @param channel - A voice channel to join

@@ -1037,3 +875,2 @@ */

* Leave the connected voice channel in a guild
*
* @param guild - Queue Resolvable

@@ -1050,3 +887,3 @@ */

/**
* Collection of {@link Filter}.
* The queue to manage
*/

@@ -1057,3 +894,2 @@ queue: Queue;

* Enable a filter or multiple filters to the manager
*
* @param filterOrFilters - The filter or filters to enable

@@ -1069,3 +905,2 @@ * @param override - Wether or not override the applied filter with new filter value

* Set the filters applied to the manager
*
* @param filters - The filters to apply

@@ -1076,3 +911,2 @@ */

* Disable a filter or multiple filters
*
* @param filterOrFilters - The filter or filters to disable

@@ -1083,3 +917,2 @@ */

* Check whether a filter enabled or not
*
* @param filter - The filter to check

@@ -1096,3 +929,3 @@ */

get values(): Filter[];
get ffmpegArgs(): FFmpegArgs;
get ffmpegArgs(): FFmpegArg;
toString(): string;

@@ -1107,28 +940,14 @@ }

/**
* Collection of {@link Queue}.
*/
/**
* Create a {@link Queue}
*
* @param channel - A voice channel
* @param song - First song
* @param textChannel - Default text channel
*
* @returns Returns `true` if encounter an error
*/
create(channel: VoiceBasedChannel, song: Song[] | Song, textChannel?: GuildTextBasedChannel): Promise<Queue | true>;
create(channel: VoiceBasedChannel, textChannel?: GuildTextBasedChannel): Promise<Queue>;
/**
* Create a ytdl stream
*
* @param queue - Queue
* Play a song on voice connection with queue properties
* @param queue - The guild queue to play
* @param emitPlaySong - Whether or not emit {@link Events.PLAY_SONG} event
*/
createStream(queue: Queue): DisTubeStream;
/**
* Play a song on voice connection
*
* @param queue - The guild queue
*
* @returns error?
*/
playSong(queue: Queue): Promise<boolean>;
playSong(queue: Queue, emitPlaySong?: boolean): Promise<void>;
}

@@ -1141,27 +960,75 @@

#private;
/**
* Queue id (Guild id)
*/
readonly id: Snowflake;
/**
* Voice connection of this queue.
*/
voice: DisTubeVoice;
/**
* List of songs in the queue (The first one is the playing song)
*/
songs: Song[];
/**
* List of the previous songs.
*/
previousSongs: Song[];
/**
* Whether stream is currently stopped.
*/
stopped: boolean;
_next: boolean;
_prev: boolean;
/**
* Whether or not the stream is currently playing.
*/
playing: boolean;
/**
* Whether or not the stream is currently paused.
*/
paused: boolean;
/**
* Type of repeat mode (`0` is disabled, `1` is repeating a song, `2` is repeating
* all the queue). Default value: `0` (disabled)
*/
repeatMode: RepeatMode;
/**
* Whether or not the autoplay mode is enabled. Default value: `false`
*/
autoplay: boolean;
beginTime: number;
/**
* FFmpeg arguments for the current queue. Default value is defined with {@link DisTubeOptions}.ffmpeg.args.
* `af` output argument will be replaced with {@link Queue#filters} manager
*/
ffmpegArgs: FFmpegArgs;
/**
* The text channel of the Queue. (Default: where the first command is called).
*/
textChannel?: GuildTextBasedChannel;
_emptyTimeout?: NodeJS.Timeout;
/**
* What time in the song to begin (in seconds).
*/
_beginTime: number;
/**
* Whether or not the last song was skipped to next song.
*/
_next: boolean;
/**
* Whether or not the last song was skipped to previous song.
*/
_prev: boolean;
/**
* Task queuing system
*/
_taskQueue: TaskQueue;
/**
* {@link DisTubeVoice} listener
*/
_listeners?: DisTubeVoiceEvents;
/**
* Create a queue for the guild
*
* @param distube - DisTube
* @param voice - Voice connection
* @param song - First song(s)
* @param textChannel - Default text channel
*/
constructor(distube: DisTube, voice: DisTubeVoice, song: Song | Song[], textChannel?: GuildTextBasedChannel);
constructor(distube: DisTube, voice: DisTubeVoice, textChannel?: GuildTextBasedChannel);
/**

@@ -1195,2 +1062,5 @@ * The client user as a `GuildMember` of this queue's guild

get voiceChannel(): discord_js.VoiceBasedChannel | null;
/**
* Get or set the stream volume. Default value: `50`.
*/
get volume(): number;

@@ -1200,6 +1070,4 @@ set volume(value: number);

* @throws {DisTubeError}
*
* @param song - Song to add
* @param position - Position to add, \<= 0 to add to the end of the queue
*
* @returns The guild queue

@@ -1210,3 +1078,2 @@ */

* Pause the guild stream
*
* @returns The guild queue

@@ -1217,3 +1084,2 @@ */

* Resume the guild stream
*
* @returns The guild queue

@@ -1224,5 +1090,3 @@ */

* Set the guild stream's volume
*
* @param percent - The percentage of volume you want to set
*
* @returns The guild queue

@@ -1235,3 +1099,2 @@ */

* play a related song.</info>
*
* @returns The song will skip to

@@ -1242,3 +1105,2 @@ */

* Play the previous song if exists
*
* @returns The guild queue

@@ -1249,3 +1111,2 @@ */

* Shuffle the queue's songs
*
* @returns The guild queue

@@ -1258,5 +1119,3 @@ */

* if `num` is invalid number
*
* @param position - The song position to play
*
* @returns The new Song will be played

@@ -1268,5 +1127,3 @@ */

* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
*
* @param mode - The repeat modes (toggle if `undefined`)
*
* @returns The new repeat mode

@@ -1277,5 +1134,3 @@ */

* Set the playing time to another position
*
* @param time - Time in seconds
*
* @returns The guild queue

@@ -1286,3 +1141,2 @@ */

* Add a related song of the playing song to the queue
*
* @returns The added song

@@ -1296,4 +1150,3 @@ */

/**
* Remove the queue from the manager (This does not leave the voice channel even if
* {@link DisTubeOptions | DisTubeOptions.leaveOnStop} is enabled)
* Remove the queue from the manager
*/

@@ -1303,6 +1156,10 @@ remove(): void;

* Toggle autoplay mode
*
* @returns Autoplay mode state
*/
toggleAutoplay(): boolean;
/**
* Play the queue
* @param emitPlaySong - Whether or not emit {@link Events.PLAY_SONG} event
*/
play(emitPlaySong?: boolean): Promise<void>;
}

@@ -1312,114 +1169,105 @@

* DisTube Plugin
*
* @virtual
*/
declare abstract class Plugin {
abstract type: PluginType;
distube: DisTube;
init(distube: DisTube): void;
/**
* Type of the plugin
*/
abstract readonly type: PluginType;
/**
* Emit an event to the {@link DisTube} class
*
* @param eventName - Event name
* @param args - arguments
* DisTube
*/
emit(eventName: keyof DisTubeEvents, ...args: any): boolean;
distube: DisTube;
init(distube: DisTube): void;
/**
* Emit error event to the {@link DisTube} class
*
* @param error - error
* @param channel - Text channel where the error is encountered.
* Get related songs from a supported url.
* @param song - Input song
*/
emitError(error: Error, channel?: GuildTextBasedChannel): void;
abstract getRelatedSongs(song: Song): Awaitable<Song[]>;
}
/**
* This plugin can extract the info, search, and play a song directly from its source
*/
declare abstract class ExtractorPlugin extends Plugin {
readonly type = PluginType.EXTRACTOR;
/**
* The queue manager
* Check if the url is working with this plugin
* @param url - Input url
*/
get queues(): QueueManager;
abstract validate(url: string): Awaitable<boolean>;
/**
* The voice manager
* Resolve the validated url to a {@link Song} or a {@link Playlist}.
* @param url - URL
* @param options - Optional options
*/
get voices(): DisTubeVoiceManager;
abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
/**
* Discord.js client
* Search for a Song which playable from this plugin's source
* @param query - Search query
* @param options - Optional options
*/
get client(): Client;
abstract searchSong<T>(query: string, options: ResolveOptions<T>): Awaitable<Song<T> | null>;
/**
* DisTube options
* Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
* Not needed if the plugin plays song from YouTube.
* @param song - Input song
*/
get options(): Options;
abstract getStreamURL<T>(song: Song<T>): Awaitable<string>;
}
/**
* This plugin only can extract the info from supported links, but not play song directly from its source
*/
declare abstract class InfoExtractorPlugin extends Plugin {
readonly type = PluginType.INFO_EXTRACTOR;
/**
* DisTube handler
* Check if the url is working with this plugin
* @param url - Input url
*/
get handler(): DisTubeHandler;
abstract validate(url: string): Awaitable<boolean>;
/**
* Check if the string is working with this plugin
*
* @param _string - Input string
* Resolve the validated url to a {@link Song} or a {@link Playlist}.
* @param url - URL
* @param options - Optional options
*/
validate(_string: string): Awaitable<boolean>;
abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
/**
* Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
* Not needed if the plugin plays song from YouTube.
*
* @param url - Input url
* Create a search query to be used in {@link ExtractorPlugin#searchSong}
* @param song - Input song
*/
getStreamURL(url: string): Awaitable<string>;
/**
* Get related songs from a supported url. {@link Song#member} should be
* `undefined`. Not needed to add {@link Song#related} because it will be added
* with this function later.
*
* @param _url - Input url
*/
getRelatedSongs(_url: string): Awaitable<RelatedSong[]>;
abstract createSearchQuery<T>(song: Song<T>): Awaitable<string>;
}
/**
* Custom Plugin
*
* @virtual
* This plugin can extract and play song from supported links, but cannot search for songs from its source
*/
declare abstract class CustomPlugin extends Plugin {
readonly type = PluginType.CUSTOM;
abstract play(voiceChannel: VoiceBasedChannel, song: string, options: PlayOptions): Awaitable<void>;
declare abstract class PlayableExtractorPlugin extends Plugin {
readonly type = PluginType.PLAYABLE_EXTRACTOR;
/**
* Check if the url is working with this plugin
* @param url - Input url
*/
abstract validate(url: string): Awaitable<boolean>;
/**
* Resolve the validated url to a {@link Song} or a {@link Playlist}.
* @param url - URL
* @param options - Optional options
*/
abstract resolve<T>(url: string, options: ResolveOptions<T>): Awaitable<Song<T> | Playlist<T>>;
/**
* Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.
* Not needed if the plugin plays song from YouTube.
* @param song - Input song
*/
abstract getStreamURL<T>(song: Song<T>): Awaitable<string>;
}
/**
* Extractor Plugin
*
* @virtual
*/
declare abstract class ExtractorPlugin extends Plugin {
readonly type = PluginType.EXTRACTOR;
abstract resolve<T = unknown>(url: string, options: {
member?: GuildMember;
metadata?: T;
}): Awaitable<Song<T> | Playlist<T>>;
}
/**
* Format duration to string
*
* @param sec - Duration in seconds
*/
declare function formatDuration(sec: number): string;
/**
* Convert formatted duration to seconds
*
* @param input - Formatted duration string
*/
declare function toSecond(input: any): number;
/**
* Parse number from input
*
* @param input - Any
*/
declare function parseNumber(input: any): number;
declare const SUPPORTED_PROTOCOL: readonly ["https:", "http:", "file:"];
/**
* Check if the string is an URL
*
* @param input - input

@@ -1430,3 +1278,2 @@ */

* Check if the Client has enough intents to using DisTube
*
* @param options - options

@@ -1437,3 +1284,2 @@ */

* Check if the voice channel is empty
*
* @param voiceState - voiceState

@@ -1452,3 +1298,2 @@ */

declare function isObject(obj: any): obj is object;
declare function isRecord<T = unknown>(obj: any): obj is Record<string, T>;
type KeyOf<T> = T extends object ? (keyof T)[] : [];

@@ -1460,137 +1305,75 @@ declare function objectKeys<T>(obj: T): KeyOf<T>;

declare class DirectLinkPlugin extends ExtractorPlugin {
validate(url: string): Promise<boolean>;
resolve(url: string, options?: {
member?: GuildMember;
metadata?: any;
}): Song<any>;
}
declare const version: string;
interface DisTube extends TypedEmitter<TypedDisTubeEvents> {
/**
* DisTube class
*/
declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
#private;
/**
* @event
* Emitted after DisTube add a new playlist to the playing {@link Queue}.
*
* @example
* ```ts
* distube.on("addList", (queue, playlist) => queue.textChannel.send(
* `Added \`${playlist.name}\` playlist (${playlist.songs.length} songs) to the queue!`
* ));
* ```
*
* @param queue - The guild queue
* @param playlist - Playlist info
*/
[Events.ADD_LIST]: (queue: Queue, playlist: Playlist) => Awaitable;
static readonly [Events.ADD_LIST]: (queue: Queue, playlist: Playlist) => Awaitable;
/**
* @event
* Emitted after DisTube add a new song to the playing {@link Queue}.
*
* @example
* ```ts
* distube.on("addSong", (queue, song) => queue.textChannel.send(
* `Added ${song.name} - \`${song.formattedDuration}\` to the queue by ${song.user}.`
* ));
* ```
*
* @param queue - The guild queue
* @param song - Added song
*/
[Events.ADD_SONG]: (queue: Queue, song: Song) => Awaitable;
static readonly [Events.ADD_SONG]: (queue: Queue, song: Song) => Awaitable;
/**
* @event
* Emitted when a {@link Queue} is deleted with any reasons.
*
* @param queue - The guild queue
*/
[Events.DELETE_QUEUE]: (queue: Queue) => Awaitable;
static readonly [Events.DELETE_QUEUE]: (queue: Queue) => Awaitable;
/**
* @event
* Emitted when the bot is disconnected to a voice channel.
*
* @param queue - The guild queue
*/
[Events.DISCONNECT]: (queue: Queue) => Awaitable;
static readonly [Events.DISCONNECT]: (queue: Queue) => Awaitable;
/**
* @event
* Emitted when there is no user in the voice channel, {@link DisTubeOptions}.leaveOnEmpty
* is `true` and there is a playing queue.
*
* If there is no playing queue (stopped and {@link DisTubeOptions}.leaveOnStop is
* `false`), it will leave the channel without emitting this event.
*
* @example
* ```ts
* distube.on("empty", queue => queue.textChannel.send("Channel is empty. Leaving the channel"))
* ```
*
* @param queue - The guild queue
* Emitted when DisTube encounters an error while playing songs.
* @param error - error
* @param queue - The queue encountered the error
* @param song - The playing song when encountered the error
*/
[Events.EMPTY]: (queue: Queue) => Awaitable;
static readonly [Events.ERROR]: (error: Error, queue: Queue, song?: Song) => Awaitable;
/**
* @event
* Emitted when DisTube encounters an error while playing songs.
*
* @example
* ```ts
* distube.on('error', (channel, e) => {
* if (channel) channel.send(`An error encountered: ${e}`)
* else console.error(e)
* })
* ```
*
* @param channel - Text channel where the error is encountered.
* @param error - The error encountered
* Emitted for logging FFmpeg debug information.
* @param debug - Debug message string.
*/
[Events.ERROR]: (channel: GuildTextBasedChannel | undefined, error: Error) => Awaitable;
static readonly [Events.FFMPEG_DEBUG]: (debug: string) => Awaitable;
/**
* @event
* Emitted for FFmpeg debugging information.
* Emitted to provide debug information from DisTube's operation.
* Useful for troubleshooting or logging purposes.
*
* @param debug - The debug information
* @param debug - Debug message string.
*/
[Events.FFMPEG_DEBUG]: (debug: string) => Awaitable;
static readonly [Events.DEBUG]: (debug: string) => Awaitable;
/**
* @event
* Emitted when there is no more song in the queue and {@link Queue#autoplay} is
* `false`. DisTube will leave voice channel if {@link
* DisTubeOptions}.leaveOnFinish is `true`.
*
* @example
* ```ts
* distube.on("finish", queue => queue.textChannel.send("No more song in queue"));
* ```
*
* Emitted when there is no more song in the queue and {@link Queue#autoplay} is `false`.
* @param queue - The guild queue
*/
[Events.FINISH]: (queue: Queue) => Awaitable;
static readonly [Events.FINISH]: (queue: Queue) => Awaitable;
/**
* @event
* Emitted when DisTube finished a song.
*
* @example
* ```ts
* distube.on("finishSong", (queue, song) => queue.textChannel.send(`${song.name} has finished!`));
* ```
*
* @param queue - The guild queue
* @param song - Finished song
*/
[Events.FINISH_SONG]: (queue: Queue, song: Song) => Awaitable;
static readonly [Events.FINISH_SONG]: (queue: Queue, song: Song) => Awaitable;
/**
* @event
* Emitted when DisTube initialize a queue to change queue default properties.
*
* @example
* ```ts
* distube.on("initQueue", queue => {
* queue.autoplay = false;
* queue.volume = 100;
* });
* ```ts
*
* @param queue - The guild queue
*/
[Events.INIT_QUEUE]: (queue: Queue) => Awaitable;
static readonly [Events.INIT_QUEUE]: (queue: Queue) => Awaitable;
/**

@@ -1600,146 +1383,45 @@ * @event

* DisTube cannot find related songs to play.
*
* @example
* ```ts
* distube.on("noRelated", queue => queue.textChannel.send("Can't find related video to play."));
* ```ts
*
* @param queue - The guild queue
*/
[Events.NO_RELATED]: (queue: Queue) => Awaitable;
static readonly [Events.NO_RELATED]: (queue: Queue) => Awaitable;
/**
* @event
* Emitted when DisTube play a song.
*
* If {@link DisTubeOptions}.emitNewSongOnly is `true`, this event is not emitted
* when looping a song or next song is the previous one.
*
* @example
* ```ts
* distube.on("playSong", (queue, song) => queue.textChannel.send(
* `Playing \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${song.user}`
* ));
* ```ts
*
* @param queue - The guild queue
* @param song - Playing song
*/
[Events.PLAY_SONG]: (queue: Queue, song: Song) => Awaitable;
static readonly [Events.PLAY_SONG]: (queue: Queue, song: Song) => Awaitable;
/**
* @event
* Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
* and the search canceled due to {@link DisTubeOptions |
* DisTubeOptions.searchTimeout}.
*
* @example
* ```ts
* // DisTubeOptions.searchSongs > 0
* distube.on("searchCancel", (message) => message.channel.send(`Searching canceled`));
* ```ts
*
* @param message - The user message called play method
* @param query - The search query
* DisTube internal handler
*/
[Events.SEARCH_CANCEL]: (message: Message, query: string) => Awaitable;
readonly handler: DisTubeHandler;
/**
* @event
* Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
* and after the user chose a search result to play.
*
* @param message - The user message called play method
* @param answer - The answered message of user
* @param query - The search query
* DisTube options
*/
[Events.SEARCH_DONE]: (message: Message, answer: string, query: string) => Awaitable;
readonly options: Options;
/**
* @event
* Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
* and the search canceled due to user's next message is not a number or out of
* results range.
*
* @example
* ```ts
* // DisTubeOptions.searchSongs > 0
* distube.on("searchInvalidAnswer", (message) => message.channel.send(`You answered an invalid number!`));
* ```ts
*
* @param message - The user message called play method
* @param answer - The answered message of user
* @param query - The search query
* Discord.js v14 client
*/
[Events.SEARCH_INVALID_ANSWER]: (message: Message, answer: string, query: string) => Awaitable;
readonly client: Client;
/**
* @event
* Emitted when DisTube cannot find any results for the query.
*
* @example
* ```ts
* distube.on("searchNoResult", (message, query) => message.channel.send(`No result found for ${query}!`));
* ```ts
*
* @param message - The user message called play method
* @param query - The search query
* Queues manager
*/
[Events.SEARCH_NO_RESULT]: (message: Message, query: string) => Awaitable;
readonly queues: QueueManager;
/**
* @event
* Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,
* and song param of {@link DisTube#play} is invalid url. DisTube will wait for
* user's next message to choose a song manually. <info>{@link
* https://support.google.com/youtube/answer/7354993 | Safe search} is enabled if
* {@link DisTubeOptions}.nsfw is disabled and the message's channel is not a nsfw
* channel.</info>
*
* @example
* ```ts
* // DisTubeOptions.searchSongs > 0
* distube.on("searchResult", (message, results) => {
* message.channel.send(`**Choose an option from below**\n${
* results.map((song, i) => `**${i + 1}**. ${song.name} - \`${song.formattedDuration}\``).join("\n")
* }\n*Enter anything else or wait 60 seconds to cancel*`);
* });
* ```ts
*
* @param message - The user message called play method
* @param results - Searched results
* @param query - The search query
* DisTube voice connections manager
*/
[Events.SEARCH_RESULT]: (message: Message, results: SearchResult[], query: string) => Awaitable;
}
/**
* DisTube class
*/
declare class DisTube extends TypedEmitter<TypedDisTubeEvents> {
#private;
readonly handler: DisTubeHandler;
readonly options: Options;
readonly client: Client;
readonly queues: QueueManager;
readonly voices: DisTubeVoiceManager;
readonly extractorPlugins: ExtractorPlugin[];
readonly customPlugins: CustomPlugin[];
readonly filters: Filters;
/**
* @deprecated Use `youtubeCookie: Cookie[]` instead. Guide: {@link
* https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}
* DisTube plugins
*/
constructor(client: Client, opts: DisTubeOptions & {
youtubeCookie: string;
});
readonly plugins: DisTubePlugin[];
/**
* DisTube ffmpeg audio filters
*/
readonly filters: Filters;
/**
* Create a new DisTube class.
*
* @example
* ```ts
* const Discord = require('discord.js'),
* DisTube = require('distube'),
* client = new Discord.Client();
* // Create a new DisTube
* const distube = new DisTube.default(client, { searchSongs: 10 });
* // client.DisTube = distube // make it access easily
* client.login("Your Discord Bot Token")
* ```ts
*
* @throws {@link DisTubeError}
*
* @param client - Discord.JS client

@@ -1755,82 +1437,19 @@ * @param opts - Custom DisTube options

/**
* Play / add a song or playlist from url. Search and play a song if it is not a
* valid url.
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "play")
* distube.play(message.member.voice.channel, args.join(" "), {
* member: message.member,
* textChannel: message.channel,
* message
* });
* });
* ```ts
*
* Play / add a song or playlist from url.
* Search and play a song (with {@link ExtractorPlugin}) if it is not a valid url.
* @throws {@link DisTubeError}
*
* @param voiceChannel - The channel will be joined if the bot isn't in any channels, the bot will be
* moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`
* @param song - URL | Search string | {@link Song} | {@link SearchResult} | {@link Playlist}
* @param song - URL | Search string | {@link Song} | {@link Playlist}
* @param options - Optional options
*/
play(voiceChannel: VoiceBasedChannel, song: string | Song | SearchResult | Playlist, options?: PlayOptions): Promise<void>;
play<T = unknown>(voiceChannel: VoiceBasedChannel, song: string | Song | Playlist, options?: PlayOptions<T>): Promise<void>;
/**
* Create a custom playlist
*
* @example
* ```ts
* const songs = ["https://www.youtube.com/watch?v=xxx", "https://www.youtube.com/watch?v=yyy"];
* const playlist = await distube.createCustomPlaylist(songs, {
* member: message.member,
* properties: { name: "My playlist name", source: "custom" },
* parallel: true
* });
* distube.play(voiceChannel, playlist, { ... });
* ```ts
*
* @param songs - Array of url, Song or SearchResult
* @param songs - Array of url or Song
* @param options - Optional options
*/
createCustomPlaylist(songs: (string | Song | SearchResult)[], options?: CustomPlaylistOptions): Promise<Playlist>;
search(string: string, options?: {
type?: SearchResultType.VIDEO;
limit?: number;
safeSearch?: boolean;
retried?: boolean;
}): Promise<Array<SearchResultVideo>>;
search(string: string, options: {
type: SearchResultType.PLAYLIST;
limit?: number;
safeSearch?: boolean;
retried?: boolean;
}): Promise<Array<SearchResultPlaylist>>;
search(string: string, options?: {
type?: SearchResultType;
limit?: number;
safeSearch?: boolean;
retried?: boolean;
}): Promise<Array<SearchResult>>;
createCustomPlaylist(songs: (string | Song)[], { member, parallel, metadata, name, source, url, thumbnail }?: CustomPlaylistOptions): Promise<Playlist>;
/**
* Get the guild queue
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "queue") {
* const queue = distube.getQueue(message);
* message.channel.send('Current queue:\n' + queue.songs.map((song, id) =>
* `**${id+1}**. [${song.name}](${song.url}) - \`${song.formattedDuration}\``
* ).join("\n"));
* }
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}

@@ -1841,5 +1460,3 @@ */

* Pause the guild stream
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The guild queue

@@ -1850,5 +1467,3 @@ */

* Resume the guild stream
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The guild queue

@@ -1859,16 +1474,2 @@ */

* Stop the guild stream
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "stop") {
* distube.stop(message);
* message.channel.send("Stopped the queue!");
* }
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}

@@ -1879,17 +1480,4 @@ */

* Set the guild stream's volume
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "volume")
* distube.setVolume(message, Number(args[0]));
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
* @param percent - The percentage of volume you want to set
*
* @returns The guild queue

@@ -1902,16 +1490,3 @@ */

* play a related song.</info>
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "skip")
* distube.skip(message);
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The new Song will be played

@@ -1922,16 +1497,3 @@ */

* Play the previous song
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "previous")
* distube.previous(message);
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The new Song will be played

@@ -1942,16 +1504,3 @@ */

* Shuffle the guild queue songs
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "shuffle")
* distube.shuffle(message);
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The guild queue

@@ -1963,18 +1512,4 @@ */

* is -1, -2,...
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "jump")
* distube.jump(message, parseInt(args[0]))
* .catch(err => message.channel.send("Invalid song number."));
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
* @param num - The song number to play
*
* @returns The new Song will be played

@@ -1986,58 +1521,10 @@ */

* Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "repeat") {
* let mode = distube.setRepeatMode(message, parseInt(args[0]));
* mode = mode ? mode == 2 ? "Repeat queue" : "Repeat song" : "Off";
* message.channel.send("Set repeat mode to `" + mode + "`");
* }
* });
* ```ts
* @example
* ```ts
* const { RepeatMode } = require("distube");
* let mode;
* switch(distube.setRepeatMode(message, parseInt(args[0]))) {
* case RepeatMode.DISABLED:
* mode = "Off";
* break;
* case RepeatMode.SONG:
* mode = "Repeat a song";
* break;
* case RepeatMode.QUEUE:
* mode = "Repeat all queue";
* break;
* }
* message.channel.send("Set repeat mode to `" + mode + "`");
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
* @param mode - The repeat modes (toggle if `undefined`)
*
* @returns The new repeat mode
*/
setRepeatMode(guild: GuildIdResolvable, mode?: number): number;
setRepeatMode(guild: GuildIdResolvable, mode?: RepeatMode): RepeatMode;
/**
* Toggle autoplay mode
*
* @example
* ```ts
* client.on('message', (message) => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command == "autoplay") {
* const mode = distube.toggleAutoplay(message);
* message.channel.send("Set autoplay mode to `" + (mode ? "On" : "Off") + "`");
* }
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns Autoplay mode state

@@ -2048,5 +1535,3 @@ */

* Add related song to the queue
*
* @param guild - The type can be resolved to give a {@link Queue}
*
* @returns The guild queue

@@ -2057,17 +1542,4 @@ */

* Set the playing time to another position
*
* @example
* ```ts
* client.on('message', message => {
* if (!message.content.startsWith(config.prefix)) return;
* const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
* const command = args.shift();
* if (command = 'seek')
* distube.seek(message, Number(args[0]));
* });
* ```ts
*
* @param guild - The type can be resolved to give a {@link Queue}
* @param time - Time in seconds
*
* @returns Seeked queue

@@ -2078,9 +1550,14 @@ */

* Emit error event
*
* @param error - error
* @param channel - Text channel where the error is encountered.
* @param queue - The queue encountered the error
* @param song - The playing song when encountered the error
*/
emitError(error: Error, channel?: GuildTextBasedChannel): void;
emitError(error: Error, queue: Queue, song?: Song): void;
/**
* Emit debug event
* @param message - debug message
*/
debug(message: string): void;
}
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 };
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 };
{
"name": "distube",
"version": "4.2.2",
"description": "A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.",
"version": "5.0.0",
"description": "A powerful Discord.js module for simplifying music commands and effortless playback of various sources with integrated audio filters.",
"main": "./dist/index.js",

@@ -37,30 +37,25 @@ "types": "./dist/index.d.ts",

},
"funding": "https://github.com/skick1234/DisTube?sponsor=1",
"funding": "https://github.com/skick1234/DisTube?sponsor",
"homepage": "https://distube.js.org/",
"dependencies": {
"@distube/ytdl-core": "^4.13.3",
"@distube/ytpl": "^1.2.1",
"@distube/ytsr": "^2.0.0",
"tiny-typed-emitter": "^2.1.0",
"tough-cookie": "^4.1.3",
"tslib": "^2.6.2",
"undici": "^6.13.0"
"undici": "^6.18.2"
},
"devDependencies": {
"@babel/core": "^7.24.4",
"@babel/plugin-transform-class-properties": "^7.24.1",
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@babel/preset-env": "^7.24.4",
"@babel/preset-typescript": "^7.24.1",
"@commitlint/cli": "^19.2.2",
"@babel/core": "^7.24.6",
"@babel/plugin-transform-class-properties": "^7.24.6",
"@babel/plugin-transform-object-rest-spread": "^7.24.6",
"@babel/plugin-transform-private-methods": "^7.24.6",
"@babel/preset-env": "^7.24.6",
"@babel/preset-typescript": "^7.24.6",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@discordjs/voice": "^0.16.1",
"@discordjs/voice": "^0.17.0",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.7",
"@types/node": "^20.14.1",
"@types/tough-cookie": "^4.0.5",
"@typescript-eslint/eslint-plugin": "^7.7.0",
"@typescript-eslint/parser": "^7.7.0",
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
"babel-jest": "^29.7.0",
"discord.js": "^14.14.1",
"discord.js": "^14.15.3",
"eslint": "^8.57.0",

@@ -71,5 +66,6 @@ "eslint-config-distube": "^1.7.0",

"nano-staged": "^0.8.0",
"pinst": "^3.0.0",
"prettier": "^3.2.5",
"tsup": "^8.0.2",
"prettier": "^3.3.0",
"sodium-native": "^4.1.1",
"ts-node": "^10.9.2",
"tsup": "^8.1.0",
"typedoc": "^0.25.13",

@@ -103,6 +99,5 @@ "typedoc-material-theme": "^1.0.2",

"build:check": "tsc --noEmit",
"update": "pnpm up -L",
"_postinstall": "husky",
"update": "pnpm up -L \"!eslint\"",
"dev:add-docs-to-worktree": "git worktree add --track -b docs docs origin/docs"
}
}

@@ -28,7 +28,7 @@ <div align="center">

- Easy to use and customize
- Support YouTube and audio link
- Audio filters (bassboost, nightcore, vaporwave,...)
- Auto-play related songs
- Plugin system to support more sites ([Plugin List](https://github.com/skick1234/DisTube/wiki/Projects-Hub#plugins))
- Easy Integration: Built on top of [discord.js](https://discord.js.org) v14 and [@discordjs/voice](https://discord.js.org).
- Voice and Queue Management: Handles voice channel connections, disconnections, and manages music queues efficiently.
- Audio Filters: Offers built-in audio filters (bassboost, echo, karaoke, etc.) and allows for custom filter implementations.
- Plugin System: Supports extensibility through plugins
> DisTube does not have built-in support for music sources. You need to use plugins to add support for them.

@@ -40,4 +40,4 @@ ## Requirement

- [@discordjs/voice](https://github.com/discordjs/voice)
- [@discordjs/opus](https://github.com/discordjs/opus)
- [FFmpeg](https://www.ffmpeg.org/download.html)
- [@discordjs/opus](https://github.com/discordjs/opus)
- [sodium-native](https://www.npmjs.com/package/sodium-native)

@@ -50,1 +50,3 @@

Learn how to build a music bot from scratch with [DisTube Guide](https://github.com/skick1234/DisTube/wiki)
[List of plugins](https://github.com/skick1234/DisTube/wiki/Projects-Hub#plugins) for supporting various sites

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet