UNPKG

discord-player

Version:

Complete framework to facilitate music commands using discord.js

1,760 lines (1,741 loc) 106 kB
import * as discord_js from 'discord.js'; import { Client, User, UserResolvable, GuildVoiceChannelResolvable, VoiceChannel, StageChannel, Guild, VoiceState, VoiceBasedChannel, GuildResolvable, Snowflake } from 'discord.js'; import Eris from 'eris'; import { ListenerSignature, DefaultListener, EventEmitter, Collection, Queue, QueueStrategy } from '@discord-player/utils'; import { Readable, Duplex } from 'stream'; import * as _discord_player_equalizer from '@discord-player/equalizer'; import { EqualizerBand, BiquadFilters, PCMFilters, FiltersChain } from '@discord-player/equalizer'; export { AF_NIGHTCORE_RATE, AF_VAPORWAVE_RATE, BASS_EQ_BANDS, FilterType as BiquadFilterType, BiquadFilters, FiltersChain, AudioFilters as PCMAudioFilters, PCMFilters, Q_BUTTERWORTH, VolumeTransformer } from '@discord-player/equalizer'; import { AudioResource, StreamType, AudioPlayerError, VoiceConnection, AudioPlayer, AudioPlayerStatus } from 'discord-voip'; export { AudioPlayer, CreateAudioPlayerOptions, JoinConfig, JoinVoiceChannelOptions, StreamType, createAudioPlayer, createAudioResource, getVoiceConnection, getVoiceConnections, joinVoiceChannel } from 'discord-voip'; import { Transform, Writable, TransformCallback } from 'node:stream'; import { RequestOptions } from 'http'; import { FFmpegLib } from '@discord-player/ffmpeg'; export * from '@discord-player/ffmpeg'; declare function isErisProxy(client: any): client is Eris.Client; /** * Allows Eris clients to be used with discord-player. When this method is called, discord-player creates a proxy object that intercepts certain methods and properties to make it compatible with discord-player. * @param client The Eris client to be used. * @returns The Eris client with discord-player compatibility. */ declare function createErisCompat(client: Eris.Client): Client; declare class PlayerEventsEmitter<L extends ListenerSignature<L> = DefaultListener> extends EventEmitter<L> { #private; requiredEvents: Array<keyof L>; constructor(requiredEvents?: Array<keyof L>); on<K extends keyof L>(name: K, listener: L[K]): this; once<K extends keyof L>(name: K, listener: L[K]): this; addListener<K extends keyof L>(name: K, listener: L[K]): this; off<K extends keyof L>(name: K, listener: L[K]): this; removeListener<K extends keyof L>(name: K, listener: L[K]): this; removeAllListeners<K extends keyof L>(name?: K): this; emit<K extends keyof L>(name: K, ...args: Parameters<L[K]>): boolean; get hasDebugger(): boolean; } type FiltersName = keyof QueueFilters; /** * Represents FFmpeg filters */ interface QueueFilters { bassboost_low?: boolean; bassboost?: boolean; bassboost_high?: boolean; '8D'?: boolean; vaporwave?: boolean; nightcore?: boolean; phaser?: boolean; tremolo?: boolean; vibrato?: boolean; reverse?: boolean; treble?: boolean; normalizer?: boolean; normalizer2?: boolean; surrounding?: boolean; pulsator?: boolean; subboost?: boolean; karaoke?: boolean; flanger?: boolean; gate?: boolean; haas?: boolean; mcompand?: boolean; mono?: boolean; mstlr?: boolean; mstrr?: boolean; compressor?: boolean; expander?: boolean; softlimiter?: boolean; chorus?: boolean; chorus2d?: boolean; chorus3d?: boolean; fadein?: boolean; dim?: boolean; earrape?: boolean; lofi?: boolean; silenceremove?: boolean; } declare class AudioFilters { constructor(); static filters: Record<FiltersName, string>; static get<K extends FiltersName>(name: K): Record<keyof QueueFilters, string>[K]; static has<K extends FiltersName>(name: K): boolean; static [Symbol.iterator](): IterableIterator<{ name: FiltersName; value: string; }>; static get names(): (keyof QueueFilters)[]; static get length(): number; static toString(): string; /** * Create ffmpeg args from the specified filters name * @param filter The filter name * @returns */ static create<K extends FiltersName>(filters?: (K | string)[]): string; /** * Defines audio filter * @param filterName The name of the filter * @param value The ffmpeg args */ static define(filterName: string, value: string): void; /** * Defines multiple audio filters * @param filtersArray Array of filters containing the filter name and ffmpeg args */ static defineBulk(filtersArray: { name: string; value: string; }[]): void; } /** * The search query type * This can be one of: * - AUTO * - YOUTUBE * - YOUTUBE_PLAYLIST * - SOUNDCLOUD_TRACK * - SOUNDCLOUD_PLAYLIST * - SOUNDCLOUD * - SPOTIFY_SONG * - SPOTIFY_ALBUM * - SPOTIFY_PLAYLIST * - SPOTIFY_SEARCH * - FACEBOOK * - VIMEO * - ARBITRARY * - REVERBNATION * - YOUTUBE_SEARCH * - YOUTUBE_VIDEO * - SOUNDCLOUD_SEARCH * - APPLE_MUSIC_SONG * - APPLE_MUSIC_ALBUM * - APPLE_MUSIC_PLAYLIST * - APPLE_MUSIC_SEARCH * - FILE * - AUTO_SEARCH * - DISCORD_PLAYER_BLOB * @typedef {string} QueryType */ declare const QueryType: { readonly AUTO: "auto"; readonly YOUTUBE: "youtube"; readonly YOUTUBE_PLAYLIST: "youtubePlaylist"; readonly SOUNDCLOUD_TRACK: "soundcloudTrack"; readonly SOUNDCLOUD_PLAYLIST: "soundcloudPlaylist"; readonly SOUNDCLOUD: "soundcloud"; readonly SPOTIFY_SONG: "spotifySong"; readonly SPOTIFY_ALBUM: "spotifyAlbum"; readonly SPOTIFY_PLAYLIST: "spotifyPlaylist"; readonly SPOTIFY_SEARCH: "spotifySearch"; readonly FACEBOOK: "facebook"; readonly VIMEO: "vimeo"; readonly ARBITRARY: "arbitrary"; readonly REVERBNATION: "reverbnation"; readonly YOUTUBE_SEARCH: "youtubeSearch"; readonly YOUTUBE_VIDEO: "youtubeVideo"; readonly SOUNDCLOUD_SEARCH: "soundcloudSearch"; readonly APPLE_MUSIC_SONG: "appleMusicSong"; readonly APPLE_MUSIC_ALBUM: "appleMusicAlbum"; readonly APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist"; readonly APPLE_MUSIC_SEARCH: "appleMusicSearch"; readonly FILE: "file"; readonly AUTO_SEARCH: "autoSearch"; readonly DISCORD_PLAYER_BLOB: "discordPlayerBlob"; }; type QueryType = (typeof QueryType)[keyof typeof QueryType]; type SearchQueryType = keyof typeof QueryType | QueryType; interface ResolvedQuery { type: (typeof QueryType)[keyof typeof QueryType]; query: string; } declare class QueryResolver { /** * Query resolver */ private constructor(); static get regex(): { spotifyAlbumRegex: RegExp; spotifyPlaylistRegex: RegExp; spotifySongRegex: RegExp; vimeoRegex: RegExp; reverbnationRegex: RegExp; attachmentRegex: RegExp; appleMusicAlbumRegex: RegExp; appleMusicPlaylistRegex: RegExp; appleMusicSongRegex: RegExp; soundcloudTrackRegex: RegExp; soundcloudPlaylistRegex: RegExp; youtubePlaylistRegex: RegExp; discordPlayerBlobRegex: RegExp; }; /** * Pre-resolve redirect urls */ static preResolve(query: string, maxDepth?: number): Promise<string>; /** * Resolves the given search query * @param {string} query The query */ static resolve(query: string, fallbackSearchEngine?: (typeof QueryType)[keyof typeof QueryType]): ResolvedQuery; /** * Parses vimeo id from url * @param {string} query The query * @returns {string} */ static getVimeoID(query: string): string | null | undefined; static validateId(q: string): boolean; static validateURL(q: string): boolean; } interface SearchResultData { query: string; queryType?: SearchQueryType | QueryExtractorSearch | null; extractor?: BaseExtractor | null; playlist?: Playlist | null; tracks?: Track[]; requestedBy?: User | null; } interface PlayOptions { /** * If this play was triggered for filters update */ filtersUpdate?: boolean; /** * FFmpeg args passed to encoder */ encoderArgs?: string[]; /** * Time to seek to before playing */ seek?: number; /** * If it should start playing the provided track immediately */ immediate?: boolean; } type QueryExtractorSearch = `ext:${string}`; interface SearchOptions { /** * The user who requested this search */ requestedBy?: UserResolvable; /** * The query search engine, can be extractor name to target specific one (custom) */ searchEngine?: SearchQueryType | QueryExtractorSearch; /** * List of the extractors to block */ blockExtractors?: string[]; /** * If it should ignore query cache lookup */ ignoreCache?: boolean; /** * Fallback search engine to use */ requestOptions?: any; /** * Fallback search engine to use */ fallbackSearchEngine?: (typeof QueryType)[keyof typeof QueryType]; } interface PlayerSearchResult { playlist: Playlist | null; tracks: Track[]; } declare class SearchResult { player: Player; private _data; constructor(player: Player, _data: SearchResultData); setQueryType(type: SearchQueryType | QueryExtractorSearch): this; setRequestedBy(user: User): this; setExtractor(extractor: BaseExtractor): this; setTracks(tracks: Track[]): this; setQuery(query: string): this; setPlaylist(playlist: Playlist): this; /** * The search query */ get query(): string; /** * The search query type */ get queryType(): SearchQueryType | `ext:${string}`; /** * The extractor */ get extractor(): BaseExtractor<object> | null; /** * Playlist result */ get playlist(): Playlist | null | undefined; /** * Tracks result */ get tracks(): Track<unknown>[]; /** * Requested by */ get requestedBy(): User | null; /** * Re-execute this search */ execute(): Promise<SearchResult>; /** * If this search result is empty */ isEmpty(): boolean; /** * If this search result has playlist */ hasPlaylist(): boolean; /** * If this search result has tracks */ hasTracks(): boolean; /** * JSON representation of this search */ toJSON(): { query: string; queryType: SearchQueryType | `ext:${string}`; playlist: PlaylistJSON | null; tracks: TrackJSON[]; extractor: string | null; requestedBy: {} | null; }; } declare enum SerializedType { Track = "track", Playlist = "playlist" } type Encodable = SerializedTrack | SerializedPlaylist; declare function serialize(data: Track | Playlist | any): any; declare function deserialize(player: Player, data: Encodable): Track<unknown> | Playlist; declare function encode(data: Encodable): string; declare function decode(data: string): any; declare function tryIntoThumbnailString(data: any): any; type TrackResolvable = Track | string | number; type WithMetadata<T extends object, M> = T & { metadata: M; requestMetadata(): Promise<M>; }; type SerializedTrack = ReturnType<Track['serialize']>; /** * The track source: * - soundcloud * - youtube * - spotify * - apple_music * - arbitrary */ type TrackSource = 'soundcloud' | 'youtube' | 'spotify' | 'apple_music' | 'arbitrary'; interface RawTrackData { /** * The title */ title: string; /** * The description */ description: string; /** * The author */ author: string; /** * The url */ url: string; /** * The thumbnail */ thumbnail: string; /** * The duration */ duration: string; /** * The duration in ms */ views: number; /** * The user who requested this track */ requestedBy?: User | null; /** * The playlist */ playlist?: Playlist; /** * The source */ source?: TrackSource; /** * The engine */ engine?: any; /** * If this track is live */ live?: boolean; /** * The raw data */ raw?: any; /** * The query type */ queryType?: SearchQueryType; /** * The serialized title */ cleanTitle?: string; } interface TrackJSON { /** * The track id */ id: string; /** * The track title */ title: string; /** * The track description */ description: string; /** * The track author */ author: string; /** * The track url */ url: string; /** * The track thumbnail */ thumbnail: string; /** * The track duration */ duration: string; /** * The track duration in ms */ durationMS: number; /** * The track views */ views: number; /** * The user id who requested this track */ requestedBy: string; /** * The playlist info (if any) */ playlist?: PlaylistJSON; } declare class Track<T = unknown> { #private; readonly player: Player; title: string; description: string; author: string; url: string; thumbnail: string; duration: string; views: number; requestedBy: User | null; playlist?: Playlist; queryType: SearchQueryType | null | undefined; raw: any; extractor: BaseExtractor | null; readonly id: string; private __metadata; private __reqMetadataFn; cleanTitle: string; live: boolean; bridgedExtractor: BaseExtractor | null; bridgedTrack: Track | null; /** * Track constructor * @param player The player that instantiated this Track * @param data Track data */ constructor(player: Player, data: Partial<WithMetadata<RawTrackData, T>>); /** * Sets audio resource for this track. This is not useful outside of the library. * @param resource Audio resource */ setResource(resource: AudioResource<Track> | null): void; /** * Gets audio resource for this track */ get resource(): AudioResource<Track<unknown>> | null; /** * Whether this track has an audio resource */ get hasResource(): boolean; /** * Request metadata for this track */ requestMetadata(): Promise<T | null>; /** * Set metadata for this track */ setMetadata(m: T | null): void; /** * Metadata of this track */ get metadata(): T | null; /** * If this track has metadata */ get hasMetadata(): boolean; /** * The queue in which this track is located */ get queue(): GuildQueue; /** * The track duration in millisecond */ get durationMS(): number; /** * Discord hyperlink representation of this track */ toHyperlink(): string; /** * Returns source of this track */ get source(): any; /** * String representation of this track */ toString(): string; /** * Raw JSON representation of this track */ toJSON(hidePlaylist?: boolean): TrackJSON; /** * Serialized track data that can be reconstructed */ serialize(): { title: string; description: string; author: string; url: string; thumbnail: any; duration: string; views: number; requested_by: {} | null; source: any; live: boolean; query_type: SearchQueryType | null | undefined; extractor: string | null; metadata: T | null; $type: SerializedType; $encoder_version: string; }; /** * Construct a track from serialized data * @param player Player instance * @param data Serialized data */ static fromSerialized(player: Player, data: ReturnType<Track['serialize']>): Track<unknown>; /** * Get belonging queues of this track */ getBelongingQueues(): Collection<string, GuildQueue<unknown>>; /** * Play this track to the given voice channel. If queue exists and another track is being played, this track will be added to the queue. * @param channel Voice channel on which this track shall be played * @param options Node initialization options */ play<T = unknown>(channel: GuildVoiceChannelResolvable, options?: PlayerNodeInitializerOptions<T>): Promise<PlayerNodeInitializationResult<T>>; } interface CreateStreamOps { type?: StreamType; data: Track; disableVolume?: boolean; disableEqualizer?: boolean; disableBiquad?: boolean; eq?: EqualizerBand[]; biquadFilter?: BiquadFilters; disableFilters?: boolean; defaultFilters?: PCMFilters[]; volume?: number; disableResampler?: boolean; sampleRate?: number; skipFFmpeg?: boolean; } interface VoiceEvents { error: (error: AudioPlayerError) => any; debug: (message: string) => any; start: (resource: AudioResource<Track>) => any; finish: (resource: AudioResource<Track>) => any; dsp: (filters: PCMFilters[]) => any; eqBands: (filters: EqualizerBand[]) => any; sampleRate: (filters: number) => any; biquad: (filters: BiquadFilters) => any; volume: (volume: number) => any; destroyed: () => any; } declare class StreamDispatcher extends EventEmitter<VoiceEvents> { #private; queue: GuildQueue; readonly connectionTimeout: number; voiceConnection: VoiceConnection; audioPlayer: AudioPlayer; channel: VoiceChannel | StageChannel; audioResource?: AudioResource<Track> | null; dsp: FiltersChain; /** * Creates new connection object * @param {VoiceConnection} connection The connection * @param {VoiceChannel|StageChannel} channel The connected channel * @private */ constructor(connection: VoiceConnection, channel: VoiceChannel | StageChannel, queue: GuildQueue, connectionTimeout?: number, audioPlayer?: AudioPlayer); /** * Check if the player has been paused manually */ get paused(): boolean; set paused(val: boolean); /** * Whether or not the player is currently paused automatically or manually. */ isPaused(): boolean; /** * Whether or not the player is currently buffering */ isBuffering(): boolean; /** * Whether or not the player is currently playing */ isPlaying(): boolean; /** * Whether or not the player is currently idle */ isIdle(): boolean; /** * Whether or not the voice connection has been destroyed */ isDestroyed(): boolean; /** * Whether or not the voice connection has been destroyed */ isDisconnected(): boolean; /** * Whether or not the voice connection is ready to play */ isReady(): boolean; /** * Whether or not the voice connection is signalling */ isSignalling(): boolean; /** * Whether or not the voice connection is connecting */ isConnecting(): boolean; /** * Creates stream * @param {Readable} src The stream source * @param {object} [ops] Options * @returns {AudioResource} */ createStream(src: Readable, ops: CreateStreamOps): Promise<AudioResource<Track<unknown>>>; get resampler(): _discord_player_equalizer.PCMResampler | null; get filters(): _discord_player_equalizer.AudioFilter | null; get biquad(): _discord_player_equalizer.BiquadStream | null; get equalizer(): _discord_player_equalizer.EqualizerStream | null; /** * The player status * @type {AudioPlayerStatus} */ get status(): AudioPlayerStatus; /** * Disconnects from voice * @returns {void} */ disconnect(): void; /** * Destroys this dispatcher */ destroy(): void; /** * Stops the player * @returns {void} */ end(): void; /** * Pauses the stream playback * @param {boolean} [interpolateSilence=false] If true, the player will play 5 packets of silence after pausing to prevent audio glitches. * @returns {boolean} */ pause(interpolateSilence?: boolean): boolean; /** * Resumes the stream playback * @returns {boolean} */ resume(): boolean; /** * Play stream * @param {AudioResource<Track>} [resource=this.audioResource] The audio resource to play * @param {boolean} [opus=false] Whether or not to use opus * @returns {Promise<StreamDispatcher>} */ playStream(resource?: AudioResource<Track>): Promise<this | undefined>; /** * Sets playback volume * @param {number} value The volume amount * @returns {boolean} */ setVolume(value: number): boolean; /** * The current volume * @type {number} */ get volume(): number; /** * The playback time * @type {number} */ get streamTime(): number; } declare class GuildQueueHistory<Meta = unknown> { queue: GuildQueue<Meta>; tracks: Queue<Track<unknown>>; constructor(queue: GuildQueue<Meta>); /** * Current track in the queue */ get currentTrack(): Track<unknown> | null; /** * Next track in the queue */ get nextTrack(): Track<unknown> | null; /** * Previous track in the queue */ get previousTrack(): Track<unknown> | null; /** * If history is disabled */ get disabled(): boolean; /** * Gets the size of the queue */ get size(): number; getSize(): number; /** * If history is empty */ isEmpty(): boolean; /** * Add track to track history * @param track The track to add */ push(track: Track | Track[]): boolean; /** * Clear history */ clear(): void; /** * Play the next track in the queue */ next(): Promise<void>; /** * Play the previous track in the queue */ previous(preserveCurrent?: boolean): Promise<void>; /** * Alias to [GuildQueueHistory].previous() */ back(preserveCurrent?: boolean): Promise<void>; /** * Resize history store */ resize(): void; } interface AsyncQueueAcquisitionOptions { /** * AbortSignal to cancel this entry */ signal?: AbortSignal; } type AsyncQueueExceptionHandler = (exception: Error) => void; declare class AsyncQueue { /** * The queued entries */ entries: Array<AsyncQueueEntry>; exceptionHandler?: AsyncQueueExceptionHandler; /** * Clear entries queue * @param consume Whether or not to consume all entries before clearing */ clear(consume?: boolean): void; /** * The total number of entries in this queue. Returns `0` if no entries are available. */ get size(): number; /** * Acquire an entry. * * @example // lock the queue * const entry = asyncQueue.acquire(); * // wait until previous task is completed * await entry.getTask(); * // do something expensive * await performSomethingExpensive(); * // make sure to release the lock once done * asyncQueue.release(); * */ acquire(options?: AsyncQueueAcquisitionOptions): AsyncQueueEntry; /** * Release the current acquisition and move to next entry. */ release(): void; /** * Cancel all entries */ cancelAll(): void; /** * Remove the given entry from the queue * @param entry The entry to remove */ removeEntry(entry: AsyncQueueEntry): boolean; } declare class AsyncQueueEntry { queue: AsyncQueue; options?: AsyncQueueAcquisitionOptions | undefined; readonly id: string; private readonly promise; signal: AbortSignal | null; onAbort: (() => void) | null; private resolve; private reject; constructor(queue: AsyncQueue, options?: AsyncQueueAcquisitionOptions | undefined); setAbortSignal(signal: AbortSignal): void; consume(): void; release(): void; cancel(): void; cleanup(): void; getTask(): Promise<void>; } declare const FFMPEG_SRATE_REGEX: RegExp; interface PlayerProgressbarOptions { /** * If it should render time codes */ timecodes?: boolean; /** * If it should create progress bar for the whole queue */ length?: number; /** * The bar length */ leftChar?: string; /** * The elapsed time track */ rightChar?: string; /** * The remaining time track */ separator?: string; /** * The separation between timestamp and line */ indicator?: string; /** * The indicator */ queue?: boolean; } interface ResourcePlayOptions { queue?: boolean; seek?: number; transitionMode?: boolean; } interface SkipOptions { reason: TrackSkipReason; description: string; } interface PlayerTimestamp { current: { label: string; value: number; }; total: { label: string; value: number; }; progress: number; } interface StreamConfig { dispatcherConfig: CreateStreamOps; playerConfig: ResourcePlayOptions; } declare class GuildQueuePlayerNode<Meta = unknown> { #private; queue: GuildQueue<Meta>; tasksQueue: AsyncQueue; constructor(queue: GuildQueue<Meta>); /** * If the player is currently in idle mode */ isIdle(): boolean; /** * If the player is currently buffering the track */ isBuffering(): boolean; /** * If the player is currently playing a track */ isPlaying(): boolean; /** * If the player is currently paused */ isPaused(): boolean; /** * Reset progress history */ resetProgress(): void; /** * Set player progress */ setProgress(progress: number): void; /** * The stream time for current session */ get streamTime(): number; /** * Current playback duration with history included */ get playbackTime(): number; /** * Get duration multiplier */ getDurationMultiplier(): number; /** * Estimated progress of the player */ get estimatedPlaybackTime(): number; /** * Estimated total duration of the player */ get estimatedDuration(): number; /** * Total duration of the current audio track */ get totalDuration(): number; /** * Get stream progress * @param ignoreFilters Ignore filters */ getTimestamp(ignoreFilters?: boolean): PlayerTimestamp | null; /** * Create progress bar for current progress * @param options Progress bar options */ createProgressBar(options?: PlayerProgressbarOptions): string | null; /** * Seek the player * @param duration The duration to seek to */ seek(duration: number): Promise<boolean>; /** * Current volume */ get volume(): number; /** * Set volume * @param vol Volume amount to set */ setVolume(vol: number): boolean; /** * Set bit rate * @param rate The bit rate to set */ setBitrate(rate: number | 'auto'): void; /** * Set paused state * @param state The state */ setPaused(state: boolean): boolean; /** * Pause the playback */ pause(): boolean; /** * Resume the playback */ resume(): boolean; /** * Skip current track */ skip(options?: SkipOptions): boolean; /** * Remove the given track from queue * @param track The track to remove * @param emitEvent Whether or not to emit the event @defaultValue true */ remove(track: TrackResolvable, emitEvent?: boolean): Track<unknown> | null; /** * Jump to specific track on the queue * @param track The track to jump to without removing other tracks */ jump(track: TrackResolvable): boolean; /** * Get track position * @param track The track */ getTrackPosition(track: TrackResolvable): number; /** * Skip to the given track, removing others on the way * @param track The track to skip to */ skipTo(track: TrackResolvable): boolean; /** * Insert a track on the given position in queue * @param track The track to insert * @param index The position to insert to, defaults to 0. */ insert(track: Track, index?: number): void; /** * Moves a track in the queue * @param from The track to move * @param to The position to move to */ move(from: TrackResolvable, to: number): void; /** * Copy a track in the queue * @param from The track to clone * @param to The position to clone at */ copy(from: TrackResolvable, to: number): void; /** * Swap two tracks in the queue * @param first The first track to swap * @param second The second track to swap */ swap(first: TrackResolvable, second: TrackResolvable): void; /** * Stop the playback * @param force Whether or not to forcefully stop the playback */ stop(force?: boolean): boolean; /** * Play the given track * @param res The track to play * @param options Options for playing the track */ play(res?: Track | null, options?: ResourcePlayOptions): Promise<void>; } interface FFmpegStreamOptions { fmt?: string; encoderArgs?: string[]; seek?: number; skip?: boolean; cookies?: string; } declare function FFMPEG_ARGS_STRING(stream: string, fmt?: string, cookies?: string): string[]; declare function FFMPEG_ARGS_PIPED(fmt?: string): string[]; /** * Creates FFmpeg stream * @param stream The source stream * @param options FFmpeg stream options */ declare function createFFmpegStream(stream: Readable | Duplex | string, options?: FFmpegStreamOptions): Readable; type Filters = keyof typeof AudioFilters.filters; type EQPreset = { Flat: EqualizerBand[]; Classical: EqualizerBand[]; Club: EqualizerBand[]; Dance: EqualizerBand[]; FullBass: EqualizerBand[]; FullBassTreble: EqualizerBand[]; FullTreble: EqualizerBand[]; Headphones: EqualizerBand[]; LargeHall: EqualizerBand[]; Live: EqualizerBand[]; Party: EqualizerBand[]; Pop: EqualizerBand[]; Reggae: EqualizerBand[]; Rock: EqualizerBand[]; Ska: EqualizerBand[]; Soft: EqualizerBand[]; SoftRock: EqualizerBand[]; Techno: EqualizerBand[]; }; declare const EqualizerConfigurationPreset: Readonly<EQPreset>; declare class FFmpegFilterer<Meta = unknown> { #private; af: GuildQueueAudioFilters<Meta>; constructor(af: GuildQueueAudioFilters<Meta>); /** * Indicates whether ffmpeg may be skipped */ get skippable(): boolean; /** * Set input args for FFmpeg */ setInputArgs(args: string[]): void; /** * Get input args */ get inputArgs(): string[]; /** * Get encoder args */ get encoderArgs(): string[]; /** * Get final ffmpeg args */ get args(): string[]; /** * Create ffmpeg stream * @param source The stream source * @param options The stream options */ createStream(source: string | Readable, options: FFmpegStreamOptions): Readable; /** * Set ffmpeg filters * @param filters The filters */ setFilters(filters: Filters[] | Record<Filters, boolean> | string[] | boolean): Promise<boolean>; /** * Currently active ffmpeg filters */ get filters(): Filters[]; set filters(filters: Filters[]); /** * Toggle given ffmpeg filter(s) * @param filters The filter(s) */ toggle(filters: Filters[] | Filters): Promise<boolean>; /** * Set default filters * @param ff Filters list */ setDefaults(ff: Filters[]): void; /** * Get list of enabled filters */ getFiltersEnabled(): (keyof QueueFilters)[]; /** * Get list of disabled filters */ getFiltersDisabled(): (keyof QueueFilters)[]; /** * Check if the given filter is enabled * @param filter The filter */ isEnabled<T extends Filters>(filter: T): boolean; /** * Check if the given filter is disabled * @param filter The filter */ isDisabled<T extends Filters>(filter: T): boolean; /** * Check if the given filter is a valid filter * @param filter The filter to test */ isValidFilter(filter: string): filter is FiltersName; /** * Convert current filters to array */ toArray(): string[]; /** * Convert current filters to JSON object */ toJSON(): Record<keyof QueueFilters, string>; /** * String representation of current filters */ toString(): string; } interface GuildQueueAFiltersCache { equalizer: EqualizerBand[]; biquad: BiquadFilters | null; filters: PCMFilters[]; volume: number; sampleRate: number; } declare class GuildQueueAudioFilters<Meta = unknown> { queue: GuildQueue<Meta>; graph: AFilterGraph<Meta>; ffmpeg: FFmpegFilterer<Meta>; equalizerPresets: Readonly<EQPreset>; _lastFiltersCache: GuildQueueAFiltersCache; constructor(queue: GuildQueue<Meta>); /** * Volume transformer */ get volume(): _discord_player_equalizer.VolumeTransformer | null; /** * 15 Band Equalizer */ get equalizer(): _discord_player_equalizer.EqualizerStream | null; /** * Digital biquad filters */ get biquad(): _discord_player_equalizer.BiquadStream | null; /** * DSP filters */ get filters(): _discord_player_equalizer.AudioFilter | null; /** * Audio resampler */ get resampler(): _discord_player_equalizer.PCMResampler | null; /** * Replay current track in transition mode * @param seek The duration to seek to */ triggerReplay(seek?: number): Promise<boolean>; } declare class AFilterGraph<Meta = unknown> { af: GuildQueueAudioFilters<Meta>; constructor(af: GuildQueueAudioFilters<Meta>); get ffmpeg(): (keyof QueueFilters)[]; get equalizer(): EqualizerBand[]; get biquad(): "SinglePoleLowPassApprox" | "SinglePoleLowPass" | "LowPass" | "HighPass" | "BandPass" | "Notch" | "AllPass" | "LowShelf" | "HighShelf" | "PeakingEQ" | null; get filters(): ("8D" | "Tremolo" | "Vibrato")[]; get volume(): _discord_player_equalizer.VolumeTransformer | null; get resampler(): _discord_player_equalizer.PCMResampler | null; dump(): FilterGraph; } interface FilterGraph { ffmpeg: Filters[]; equalizer: EqualizerBand[]; biquad: Exclude<BiquadFilters, number> | null; filters: PCMFilters[]; volume: number; sampleRate: number; } interface GuildQueueStatisticsMetadata { latency: { eventLoop: number; voiceConnection: number; }; status: { buffering: boolean; playing: boolean; paused: boolean; idle: boolean; }; tracksCount: number; historySize: number; extractors: number; listeners: number; memoryUsage: NodeJS.MemoryUsage; versions: { node: string; player: string; }; } declare class GuildQueueStatistics<Meta = unknown> { queue: GuildQueue<Meta>; constructor(queue: GuildQueue<Meta>); /** * Generate statistics of this queue */ generate(): GuildQueueStatisticsMetadata; } type RequestEntity = () => Promise<Response>; declare class SequentialBucket { limit: number; remaining: number; resetAfter: number; queue: AsyncQueue; MAX_RETRIES: number; /** * Checks if the bucket is rate limited. */ isRateLimited(): boolean; /** * Enqueues a request. * @param req The request function to enqueue */ enqueue(req: RequestEntity): Promise<Response>; private _request; private _patchHeaders; } interface LrcSearchParams { /** * The query to search for. Either this or trackName is required. */ q?: string; /** * The track name to search for. Either this or query is required. */ trackName?: string; /** * The artist name */ artistName?: string; /** * The album name */ albumName?: string; } interface LrcGetParams extends Required<Omit<LrcSearchParams, 'query'>> { /** * The duration of the track */ duration: number; } interface LrcSearchResult { /** * The track id */ id: number; /** * The track name */ name: string; /** * The artist name */ trackName: string; /** * The album name */ artistName: string; /** * The album name */ albumName: string; /** * The duration of the track */ duration: number; /** * The release date of the track */ instrumental: boolean; /** * The release date of the track */ plainLyrics: string; /** * The release date of the track */ syncedLyrics?: string; } type LrcGetResult = Omit<LrcSearchResult, 'name'>; declare class LrcLib { readonly player: Player; /** * The API URL */ api: string; /** * The request timeout. Default is 15 seconds. */ timeout: number; /** * The request bucket */ bucket: SequentialBucket; /** * Creates a new LrcLib instance * @param {Player} player The player instance */ constructor(player: Player); /** * Sets the request timeout * @param {number} timeout The timeout in milliseconds */ setRequestTimeout(timeout: number): void; /** * Sets the retry limit. Default is 5. * @param {number} limit The retry limit */ setRetryLimit(limit: number): void; /** * Gets lyrics * @param params The get params */ get(params: LrcGetParams): Promise<LrcSearchResult>; /** * Gets lyrics by ID * @param id The lyrics ID */ getById(id: `${number}` | number): Promise<LrcSearchResult>; /** * Gets cached lyrics * @param params The get params */ getCached(params: LrcGetParams): Promise<LrcSearchResult>; /** * Searches for lyrics * @param params The search params */ search(params: LrcSearchParams): Promise<LrcSearchResult[]>; /** * Requests the API * @param path The path * @param options The request options */ request<T>(path: string, options?: RequestInit): Promise<T>; } type LyricsData = Map<number, string>; type Unsubscribe = () => void; type LyricsCallback = (lyrics: string, timestamp: number) => unknown; type LyricsAt = { timestamp: number; line: string; }; declare class SyncedLyricsProvider { #private; readonly queue: GuildQueue; readonly raw?: LrcSearchResult | LrcGetResult | undefined; interval: number; readonly lyrics: LyricsData; constructor(queue: GuildQueue, raw?: LrcSearchResult | LrcGetResult | undefined); isSubscribed(): boolean; load(lyrics: string): void; /** * Returns the lyrics at a specific time or at the closest time (±2 seconds) * @param time The time in milliseconds */ at(time: number): LyricsAt | null; /** * Callback for the lyrics change. * @param callback The callback function */ onChange(callback: LyricsCallback): void; /** * Callback to detect when the provider is unsubscribed. * @param callback The callback function */ onUnsubscribe(callback: Unsubscribe): void; /** * Unsubscribes from the queue. */ unsubscribe(): void; /** * Subscribes to the queue to monitor the current time. * @returns The unsubscribe function */ subscribe(): Unsubscribe; /** * Pauses the lyrics provider. */ pause(): boolean; /** * Resumes the lyrics provider. */ resume(): boolean; } interface GuildNodeInit<Meta = unknown> { guild: Guild; queueStrategy: QueueStrategy; equalizer: EqualizerBand[] | boolean; volume: number | boolean; biquad: BiquadFilters | boolean | undefined; resampler: number | boolean; filterer: PCMFilters[] | boolean; ffmpegFilters: FiltersName[]; disableHistory: boolean; onBeforeCreateStream?: OnBeforeCreateStreamHandler; onAfterCreateStream?: OnAfterCreateStreamHandler; repeatMode?: QueueRepeatMode; leaveOnEmpty: boolean; leaveOnEmptyCooldown: number; leaveOnEnd: boolean; leaveOnEndCooldown: number; leaveOnStop: boolean; leaveOnStopCooldown: number; connectionTimeout: number; selfDeaf?: boolean; metadata?: Meta | null; bufferingTimeout: number; noEmitInsert: boolean; maxSize?: number; maxHistorySize?: number; preferBridgedMetadata: boolean; pauseOnEmpty?: boolean; disableVolume: boolean; disableEqualizer: boolean; disableFilterer: boolean; disableBiquad: boolean; disableResampler: boolean; disableFallbackStream: boolean; enableStreamInterceptor: boolean; } interface VoiceConnectConfig { deaf?: boolean; timeout?: number; group?: string; audioPlayer?: AudioPlayer; } interface PostProcessedResult { stream: Readable; type: StreamType; } type OnBeforeCreateStreamHandler = (track: Track, queryType: SearchQueryType, queue: GuildQueue) => Promise<Readable | null>; type OnAfterCreateStreamHandler<T = unknown> = (stream: Readable, queue: GuildQueue, track: Track<T>) => Promise<PostProcessedResult | null>; type PlayerTriggeredReason = 'filters' | 'normal'; declare const GuildQueueEvent: { /** * Emitted when audio track is added to the queue */ readonly AudioTrackAdd: "audioTrackAdd"; /** * Emitted when audio tracks were added to the queue */ readonly AudioTracksAdd: "audioTracksAdd"; /** * Emitted when audio track is removed from the queue */ readonly AudioTrackRemove: "audioTrackRemove"; /** * Emitted when audio tracks are removed from the queue */ readonly AudioTracksRemove: "audioTracksRemove"; /** * Emitted when a connection is created */ readonly Connection: "connection"; /** * Emitted when a voice connection is destroyed */ readonly ConnectionDestroyed: "connectionDestroyed"; /** * Emitted when the bot is disconnected from the channel */ readonly Disconnect: "disconnect"; /** * Emitted when the queue sends a debug info */ readonly Debug: "debug"; /** * Emitted when the queue encounters error */ readonly Error: "error"; /** * Emitted when the voice channel is empty */ readonly EmptyChannel: "emptyChannel"; /** * Emitted when the queue is empty */ readonly EmptyQueue: "emptyQueue"; /** * Emitted when the audio player starts streaming audio track */ readonly PlayerStart: "playerStart"; /** * Emitted when the audio player errors while streaming audio track */ readonly PlayerError: "playerError"; /** * Emitted when the audio player finishes streaming audio track */ readonly PlayerFinish: "playerFinish"; /** * Emitted when the audio player skips current track */ readonly PlayerSkip: "playerSkip"; /** * Emitted when the audio player is triggered */ readonly PlayerTrigger: "playerTrigger"; /** * Emitted when the voice state is updated. Consuming this event may disable default voice state update handler if `Player.isVoiceStateHandlerLocked()` returns `false`. */ readonly VoiceStateUpdate: "voiceStateUpdate"; /** * Emitted when volume is updated */ readonly VolumeChange: "volumeChange"; /** * Emitted when player is paused */ readonly PlayerPause: "playerPause"; /** * Emitted when player is resumed */ readonly PlayerResume: "playerResume"; /** * Biquad Filters Update */ readonly BiquadFiltersUpdate: "biquadFiltersUpdate"; /** * Equalizer Update */ readonly EqualizerUpdate: "equalizerUpdate"; /** * DSP update */ readonly DSPUpdate: "dspUpdate"; /** * Audio Filters Update */ readonly AudioFiltersUpdate: "audioFiltersUpdate"; /** * Audio player will play next track */ readonly WillPlayTrack: "willPlayTrack"; /** * Emitted when a voice channel is repopulated */ readonly ChannelPopulate: "channelPopulate"; /** * Emitted when a queue is successfully created */ readonly QueueCreate: "queueCreate"; /** * Emitted when a queue is deleted */ readonly QueueDelete: "queueDelete"; /** * Emitted when a queue is trying to add similar track for autoplay */ readonly WillAutoPlay: "willAutoPlay"; }; type GuildQueueEvent = (typeof GuildQueueEvent)[keyof typeof GuildQueueEvent]; declare enum TrackSkipReason { NoStream = "ERR_NO_STREAM", Manual = "MANUAL", SEEK_OVER_THRESHOLD = "SEEK_OVER_THRESHOLD", Jump = "JUMPED_TO_ANOTHER_TRACK", SkipTo = "SKIP_TO_ANOTHER_TRACK", HistoryNext = "HISTORY_NEXT_TRACK" } interface GuildQueueEvents<Meta = any> { /** * Emitted when audio track is added to the queue * @param queue The queue where this event occurred * @param track The track */ [GuildQueueEvent.AudioTrackAdd]: (queue: GuildQueue<Meta>, track: Track) => unknown; /** * Emitted when audio tracks were added to the queue * @param queue The queue where this event occurred * @param tracks The tracks array */ [GuildQueueEvent.AudioTracksAdd]: (queue: GuildQueue<Meta>, track: Track[]) => unknown; /** * Emitted when audio track is removed from the queue * @param queue The queue where this event occurred * @param track The track */ [GuildQueueEvent.AudioTrackRemove]: (queue: GuildQueue<Meta>, track: Track) => unknown; /** * Emitted when audio tracks are removed from the queue * @param queue The queue where this event occurred * @param track The track */ [GuildQueueEvent.AudioTracksRemove]: (queue: GuildQueue<Meta>, track: Track[]) => unknown; /** * Emitted when a connection is created * @param queue The queue where this event occurred */ [GuildQueueEvent.Connection]: (queue: GuildQueue<Meta>) => unknown; /** * Emitted when a connection is destroyed * @param queue The queue where this event occurred */ [GuildQueueEvent.ConnectionDestroyed]: (queue: GuildQueue<Meta>) => unknown; /** * Emitted when the bot is disconnected from the channel * @param queue The queue where this event occurred */ [GuildQueueEvent.Disconnect]: (queue: GuildQueue<Meta>) => unknown; /** * Emitted when the queue sends a debug info * @param queue The queue where this event occurred * @param message The debug message */ [GuildQueueEvent.Debug]: (queue: GuildQueue<Meta>, message: string) => unknown; /** * Emitted when the queue encounters error * @param queue The queue where this event occurred * @param error The error */ [GuildQueueEvent.Error]: (queue: GuildQueue<Meta>, error: Error) => unknown; /** * Emitted when the voice channel is empty * @param queue The queue where this event occurred */ [GuildQueueEvent.EmptyChannel]: (queue: GuildQueue<Meta>) => unknown; /** * Emitted when the queue is empty * @param queue The queue where this event occurred */ [GuildQueueEvent.EmptyQueue]: (queue: GuildQueue<Meta>) => unknown; /** * Emitted when the audio player starts streaming audio track * @param queue The queue where this event occurred * @param track The track that is being streamed */ [GuildQueueEvent.PlayerStart]: (queue: GuildQueue<Meta>, track: Track) => unknown; /** * Emitted when the audio player errors while streaming audio track * @param queue The queue where this event occurred * @param error The error * @param track The track that is being streamed */ [GuildQueueEvent.PlayerError]: (queue: GuildQueue<Meta>, error: Error, track: Track) => unknown; /** * Emitted when the audio player finishes streaming audio track * @param queue The queue where this event occurred * @param track The track that was being streamed */ [GuildQueueEvent.PlayerFinish]: (queue: GuildQueue<Meta>, track: Track) => unknown; /** * Emitted when the audio player skips current track * @param queue The queue where this event occurred * @param track The track that was skipped * @param reason The reason for skipping * @param description The description for skipping */ [GuildQueueEvent.PlayerSkip]: (queue: GuildQueue<Meta>, track: Track, reason: TrackSkipReason, description: string) => unknown; /** * Emitted when the audio player is triggered * @param queue The queue where this event occurred * @param track The track which was played in this event */ [GuildQueueEvent.PlayerTrigger]: (queue: GuildQueue<Meta>, track: Track, reason: PlayerTriggeredReason) => unknown; /** * Emitted when the voice state is updated. Consuming this event may disable default voice state update handler if `Player.isVoiceStateHandlerLocked()` returns `false`. * @param queue The queue where this event occurred * @param oldState The old voice state * @param newState The new voice state */ [GuildQueueEvent.VoiceStateUpdate]: (queue: GuildQueue<Meta>, oldState: VoiceState, newState: VoiceState) => unknown; /** * Emitted when audio player is paused * @param queue The queue where this event occurred */ [GuildQueueEvent.PlayerPause]: (queue: GuildQueue<Meta>) => unknown; /**