UNPKG

lavalink-client

Version:

Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.

1,405 lines (1,395 loc) 117 kB
import { EventEmitter } from 'events'; import internal from 'stream'; /** The Audio Outputs type */ type AudioOutputs = "mono" | "stereo" | "left" | "right"; /** The "active" / "disabled" Player Filters */ interface PlayerFilters { /** Sets nightcore to false, and vaporwave to false */ custom: boolean; /** Sets custom to false, and vaporwave to false */ nightcore: boolean; /** Sets custom to false, and nightcore to false */ vaporwave: boolean; /** If rotation filter is enabled / not */ rotation: boolean; /** if karaoke filter is enabled / not */ karaoke: boolean; /** if tremolo filter is enabled / not */ tremolo: boolean; /** if vibrato filter is enabled / not */ vibrato: boolean; lowPass: boolean; /** audio Output (default stereo, mono sounds the fullest and best for not-stereo tracks) */ audioOutput: AudioOutputs; /** Lavalink Volume FILTER (not player Volume, think of it as a gain booster) */ volume: boolean; /** Filters for the Lavalink Filter Plugin */ lavalinkFilterPlugin: { /** if echo filter is enabled / not */ echo: boolean; /** if reverb filter is enabled / not */ reverb: boolean; }; lavalinkLavaDspxPlugin: { /** if lowPass filter is enabled / not */ lowPass: boolean; /** if highPass filter is enabled / not */ highPass: boolean; /** if normalization filter is enabled / not */ normalization: boolean; /** if echo filter is enabled / not */ echo: boolean; }; } /** * There are 15 bands (0-14) that can be changed. * "gain" is the multiplier for the given band. * The default value is 0. * Valid values range from -0.25 to 1.0, where -0.25 means the given band is completely muted, and 0.25 means it is doubled. * Modifying the gain could also change the volume of the output. */ interface EQBand { /** On what band position (0-14) it should work */ band: IntegerNumber | number; /** The gain (-0.25 to 1.0) */ gain: FloatNumber | number; } /** * Uses equalization to eliminate part of a band, usually targeting vocals. */ interface KaraokeFilter { /** The level (0 to 1.0 where 0.0 is no effect and 1.0 is full effect) */ level?: number; /** The mono level (0 to 1.0 where 0.0 is no effect and 1.0 is full effect) */ monoLevel?: number; /** The filter band (in Hz) */ filterBand?: number; /** The filter width */ filterWidth?: number; } /** * Changes the speed, pitch, and rate */ interface TimescaleFilter { /** The playback speed 0.0 ≤ x */ speed?: number; /** The pitch 0.0 ≤ x */ pitch?: number; /** The rate 0.0 ≤ x */ rate?: number; } /** * Uses amplification to create a shuddering effect, where the volume quickly oscillates. * Demo: https://en.wikipedia.org/wiki/File:Fuse_Electronics_Tremolo_MK-III_Quick_Demo.ogv */ interface TremoloFilter { /** The frequency 0.0 < x */ frequency?: number; /** The tremolo depth 0.0 < x ≤ 1.0 */ depth?: number; } /** * Similar to tremolo. While tremolo oscillates the volume, vibrato oscillates the pitch. */ interface VibratoFilter { /** The frequency 0.0 < x ≤ 14.0 */ frequency?: number; /** The vibrato depth 0.0 < x ≤ 1.0 */ depth?: number; } /** * Rotates the sound around the stereo channels/user headphones (aka Audio Panning). * It can produce an effect similar to https://youtu.be/QB9EB8mTKcc (without the reverb). */ interface RotationFilter { /** The frequency of the audio rotating around the listener in Hz. 0.2 is similar to the example video above */ rotationHz?: number; } /** * Distortion effect. It can generate some pretty unique audio effects. */ interface DistortionFilter { sinOffset?: number; sinScale?: number; cosOffset?: number; cosScale?: number; tanOffset?: number; tanScale?: number; offset?: number; scale?: number; } /** * Mixes both channels (left and right), with a configurable factor on how much each channel affects the other. * With the defaults, both channels are kept independent of each other. * Setting all factors to 0.5 means both channels get the same audio. */ interface ChannelMixFilter { /** The left to left channel mix factor (0.0 ≤ x ≤ 1.0) */ leftToLeft?: number; /** The left to right channel mix factor (0.0 ≤ x ≤ 1.0) */ leftToRight?: number; /** The right to left channel mix factor (0.0 ≤ x ≤ 1.0) */ rightToLeft?: number; /** The right to right channel mix factor (0.0 ≤ x ≤ 1.0) */ rightToRight?: number; } /** * Higher frequencies get suppressed, while lower frequencies pass through this filter, thus the name low pass. * Any smoothing values equal to or less than 1.0 will disable the filter. */ interface LowPassFilter { /** The smoothing factor (1.0 < x) */ smoothing?: number; } /** * Filter Data stored in the Client and partially sent to Lavalink */ interface FilterData { volume?: number; karaoke?: KaraokeFilter; timescale?: TimescaleFilter; tremolo?: TremoloFilter; vibrato?: VibratoFilter; rotation?: RotationFilter; distortion?: DistortionFilter; channelMix?: ChannelMixFilter; lowPass?: LowPassFilter; pluginFilters?: { "lavalink-filter-plugin"?: { "echo"?: { delay?: number; decay?: number; }; "reverb"?: { delays?: number[]; gains?: number[]; }; }; "high-pass"?: { cutoffFrequency?: number; boostFactor?: number; }; "low-pass"?: { cutoffFrequency?: number; boostFactor?: number; }; normalization?: { maxAmplitude?: number; adaptive?: boolean; }; echo?: { echoLength?: number; decay?: number; }; }; } /** * Actual Filter Data sent to Lavalink */ interface LavalinkFilterData extends FilterData { equalizer?: EQBand[]; } declare enum DebugEvents { SetSponsorBlock = "SetSponsorBlock", DeleteSponsorBlock = "DeleteSponsorBlock", TrackEndReplaced = "TrackEndReplaced", AutoplayExecution = "AutoplayExecution", AutoplayNoSongsAdded = "AutoplayNoSongsAdded", AutoplayThresholdSpamLimiter = "AutoplayThresholdSpamLimiter", TriggerQueueEmptyInterval = "TriggerQueueEmptyInterval", QueueEnded = "QueueEnded", TrackStartNewSongsOnly = "TrackStartNewSongsOnly", TrackStartNoTrack = "TrackStartNoTrack", ResumingFetchingError = "ResumingFetchingError", PlayerUpdateNoPlayer = "PlayerUpdateNoPlayer", PlayerUpdateFilterFixApply = "PlayerUpdateFilterFixApply", PlayerUpdateSuccess = "PlayerUpdateSuccess", HeartBeatTriggered = "HeartBeatTriggered", NoSocketOnDestroy = "NoSocketOnDestroy", SocketTerminateHeartBeatTimeout = "SocketTerminateHeartBeatTimeout", TryingConnectWhileConnected = "TryingConnectWhileConnected", LavaSearchNothingFound = "LavaSearchNothingFound", SearchNothingFound = "SearchNothingFound", ValidatingBlacklistLinks = "ValidatingBlacklistLinks", ValidatingWhitelistLinks = "ValidatingWhitelistLinks", TrackErrorMaxTracksErroredPerTime = "TrackErrorMaxTracksErroredPerTime", TrackStuckMaxTracksErroredPerTime = "TrackStuckMaxTracksErroredPerTime", PlayerDestroyingSomewhereElse = "PlayerDestroyingSomewhereElse", PlayerCreateNodeNotFound = "PlayerCreateNodeNotFound", PlayerPlayQueueEmptyTimeoutClear = "PlayerPlayQueueEmptyTimeoutClear", PlayerPlayWithTrackReplace = "PlayerPlayWithTrackReplace", PlayerPlayUnresolvedTrack = "PlayerPlayUnresolvedTrack", PlayerPlayUnresolvedTrackFailed = "PlayerPlayUnresolvedTrackFailed", PlayerVolumeAsFilter = "PlayerVolumeAsFilter", BandcampSearchLokalEngine = "BandcampSearchLokalEngine", PlayerChangeNode = "PlayerChangeNode", BuildTrackError = "BuildTrackError", TransformRequesterFunctionFailed = "TransformRequesterFunctionFailed", GetClosestTrackFailed = "GetClosestTrackFailed", PlayerDeleteInsteadOfDestroy = "PlayerDeleteInsteadOfDestroy", FailedToConnectToNodes = "FailedToConnectToNodes", NoAudioDebug = "NoAudioDebug", PlayerAutoReconnect = "PlayerAutoReconnect" } declare enum DestroyReasons { QueueEmpty = "QueueEmpty", NodeDestroy = "NodeDestroy", NodeDeleted = "NodeDeleted", LavalinkNoVoice = "LavalinkNoVoice", NodeReconnectFail = "NodeReconnectFail", Disconnected = "Disconnected", PlayerReconnectFail = "PlayerReconnectFail", PlayerChangeNodeFail = "PlayerChangeNodeFail", PlayerChangeNodeFailNoEligibleNode = "PlayerChangeNodeFailNoEligibleNode", ChannelDeleted = "ChannelDeleted", DisconnectAllNodes = "DisconnectAllNodes", ReconnectAllNodes = "ReconnectAllNodes", TrackErrorMaxTracksErroredPerTime = "TrackErrorMaxTracksErroredPerTime", TrackStuckMaxTracksErroredPerTime = "TrackStuckMaxTracksErroredPerTime" } declare enum DisconnectReasons { Disconnected = "Disconnected", DisconnectAllNodes = "DisconnectAllNodes" } declare const validSponsorBlocks: string[]; /** The audio Outputs Data map declaration */ declare const audioOutputsData: Record<AudioOutputs, ChannelMixFilter>; declare const EQList: { /** A Bassboost Equalizer, so high it distorts the audio */ BassboostEarrape: EQBand[]; /** A High and decent Bassboost Equalizer */ BassboostHigh: EQBand[]; /** A decent Bassboost Equalizer */ BassboostMedium: EQBand[]; /** A slight Bassboost Equalizer */ BassboostLow: EQBand[]; /** Makes the Music slightly "better" */ BetterMusic: EQBand[]; /** Makes the Music sound like rock music / sound rock music better */ Rock: EQBand[]; /** Makes the Music sound like Classic music / sound Classic music better */ Classic: EQBand[]; /** Makes the Music sound like Pop music / sound Pop music better */ Pop: EQBand[]; /** Makes the Music sound like Electronic music / sound Electronic music better */ Electronic: EQBand[]; /** Boosts all Bands slightly for louder and fuller sound */ FullSound: EQBand[]; /** Boosts basses + lower highs for a pro gaming sound */ Gaming: EQBand[]; }; /** * The FilterManager for each player */ declare class FilterManager { /** The Equalizer bands currently applied to the Lavalink Server */ equalizerBands: EQBand[]; /** Private Util for the instaFix Filters option */ filterUpdatedState: boolean; /** All "Active" / "disabled" Player Filters */ filters: PlayerFilters; /** The Filter Data sent to Lavalink, only if the filter is enabled (ofc.) */ data: FilterData; /** The Player assigned to this Filter Manager */ player: Player; /** The Constructor for the FilterManager */ constructor(player: Player); /** * Apply Player filters for lavalink filter sending data, if the filter is enabled / not */ applyPlayerFilters(): Promise<void>; /** * Checks if the filters are correctly stated (active / not-active) * @param oldFilterTimescale * @returns */ checkFiltersState(oldFilterTimescale?: Partial<TimescaleFilter>): boolean; /** * Reset all Filters */ resetFilters(): Promise<PlayerFilters>; /** * Set the Filter Volume * @param volume * @returns */ setVolume(volume: number): Promise<boolean>; /** * Set the AudioOutput Filter * @param type * @returns */ setAudioOutput(type: AudioOutputs): Promise<AudioOutputs>; /** * Set custom filter.timescale#speed . This method disabled both: nightcore & vaporwave. use 1 to reset it to normal * @param speed * @returns */ setSpeed(speed?: number): Promise<boolean>; /** * Set custom filter.timescale#pitch . This method disabled both: nightcore & vaporwave. use 1 to reset it to normal * @param speed * @returns */ setPitch(pitch?: number): Promise<boolean>; /** * Set custom filter.timescale#rate . This method disabled both: nightcore & vaporwave. use 1 to reset it to normal * @param speed * @returns */ setRate(rate?: number): Promise<boolean>; /** * Enables / Disables the rotation effect, (Optional: provide your Own Data) * @param rotationHz * @returns */ toggleRotation(rotationHz?: number): Promise<boolean>; /** * Enables / Disables the Vibrato effect, (Optional: provide your Own Data) * @param frequency * @param depth * @returns */ toggleVibrato(frequency?: number, depth?: number): Promise<boolean>; /** * Enables / Disables the Tremolo effect, (Optional: provide your Own Data) * @param frequency * @param depth * @returns */ toggleTremolo(frequency?: number, depth?: number): Promise<boolean>; /** * Enables / Disables the LowPass effect, (Optional: provide your Own Data) * @param smoothing * @returns */ toggleLowPass(smoothing?: number): Promise<boolean>; lavalinkLavaDspxPlugin: { /** * Enables / Disables the LowPass effect, (Optional: provide your Own Data) * @param boostFactor * @param cutoffFrequency * @returns */ toggleLowPass: (boostFactor?: number, cutoffFrequency?: number) => Promise<boolean>; /** * Enables / Disables the HighPass effect, (Optional: provide your Own Data) * @param boostFactor * @param cutoffFrequency * @returns */ toggleHighPass: (boostFactor?: number, cutoffFrequency?: number) => Promise<boolean>; /** * Enables / Disables the Normalization effect. * @param {number} [maxAmplitude=0.75] - The maximum amplitude of the audio. * @param {boolean} [adaptive=true] - Whether to use adaptive normalization or not. * @returns {Promise<boolean>} - The state of the filter after execution. */ toggleNormalization: (maxAmplitude?: number, adaptive?: boolean) => Promise<boolean>; /** * Enables / Disables the Echo effect, IMPORTANT! Only works with the correct Lavalink Plugin installed. (Optional: provide your Own Data) * @param {number} [decay=0.5] - The decay of the echo effect. * @param {number} [echoLength=0.5] - The length of the echo effect. * @returns {Promise<boolean>} - The state of the filter after execution. */ toggleEcho: (decay?: number, echoLength?: number) => Promise<boolean>; }; lavalinkFilterPlugin: { /** * Enables / Disables the Echo effect, IMPORTANT! Only works with the correct Lavalink Plugin installed. (Optional: provide your Own Data) * @param delay * @param decay * @returns */ toggleEcho: (delay?: number, decay?: number) => Promise<boolean>; /** * Enables / Disables the Echo effect, IMPORTANT! Only works with the correct Lavalink Plugin installed. (Optional: provide your Own Data) * @param delays * @param gains * @returns */ toggleReverb: (delays?: number[], gains?: number[]) => Promise<boolean>; }; /** * Enables / Disables a Nightcore-like filter Effect. Disables/Overrides both: custom and Vaporwave Filter * @param speed * @param pitch * @param rate * @returns */ toggleNightcore(speed?: number, pitch?: number, rate?: number): Promise<boolean>; /** * Enables / Disables a Vaporwave-like filter Effect. Disables/Overrides both: custom and nightcore Filter * @param speed * @param pitch * @param rate * @returns */ toggleVaporwave(speed?: number, pitch?: number, rate?: number): Promise<boolean>; /** * Enable / Disables a Karaoke like Filter Effect * @param level * @param monoLevel * @param filterBand * @param filterWidth * @returns */ toggleKaraoke(level?: number, monoLevel?: number, filterBand?: number, filterWidth?: number): Promise<boolean>; /** Function to find out if currently there is a custom timescamle etc. filter applied */ isCustomFilterActive(): boolean; /** * Sets the players equalizer band on-top of the existing ones. * @param bands */ setEQ(bands: EQBand | EQBand[]): Promise<this>; /** Clears the equalizer bands. */ clearEQ(): Promise<this>; } declare class QueueSaver { /** * The queue store manager */ private _; /** * The options for the queue saver */ options: { maxPreviousTracks: number; }; constructor(options: ManagerQueueOptions); /** * Get the queue for a guild * @param guildId The guild ID * @returns The queue for the guild */ get(guildId: string): Promise<Partial<StoredQueue>>; /** * Delete the queue for a guild * @param guildId The guild ID * @returns The queue for the guild */ delete(guildId: string): Promise<boolean | void>; /** * Set the queue for a guild * @param guildId The guild ID * @param valueToStringify The queue to set * @returns The queue for the guild */ set(guildId: string, valueToStringify: StoredQueue): Promise<boolean | void>; /** * Sync the queue for a guild * @param guildId The guild ID * @returns The queue for the guild */ sync(guildId: string): Promise<Partial<StoredQueue>>; } declare class DefaultQueueStore implements QueueStoreManager { private data; constructor(); /** * Get the queue for a guild * @param guildId The guild ID * @returns The queue for the guild */ get(guildId: string): StoredQueue; /** * Set the queue for a guild * @param guildId The guild ID * @param valueToStringify The queue to set * @returns The queue for the guild */ set(guildId: string, valueToStringify: any): boolean; /** * Delete the queue for a guild * @param guildId The guild ID * @returns The queue for the guild */ delete(guildId: string): boolean; /** * Stringify the queue for a guild * @param value The queue to stringify * @returns The stringified queue */ stringify(value: StoredQueue | string): StoredQueue | string; /** * Parse the queue for a guild * @param value The queue to parse * @returns The parsed queue */ parse(value: StoredQueue | string): Partial<StoredQueue>; } declare class Queue { readonly tracks: (Track | UnresolvedTrack)[]; readonly previous: Track[]; current: Track | null; options: { maxPreviousTracks: number; }; private readonly guildId; private readonly QueueSaver; private managerUtils; private queueChanges; /** * Create a new Queue * @param guildId The guild ID * @param data The data to initialize the queue with * @param QueueSaver The queue saver to use * @param queueOptions */ constructor(guildId: string, data?: Partial<StoredQueue>, QueueSaver?: QueueSaver, queueOptions?: ManagerQueueOptions); /** * Utils for a Queue */ utils: { /** * Save the current cached Queue on the database/server (overides the server) */ save: () => Promise<boolean | void>; /** * Sync the current queue database/server with the cached one * @returns {void} */ sync: (override?: boolean, dontSyncCurrent?: boolean) => Promise<void>; destroy: () => Promise<boolean | void>; /** * @returns {{current:Track|null, previous:Track[], tracks:Track[]}}The Queue, but in a raw State, which allows easier handling for the QueueStoreManager */ toJSON: () => StoredQueue; /** * Get the Total Duration of the Queue-Songs summed up * @returns {number} */ totalDuration: () => number; }; /** * Shuffles the current Queue, then saves it * @returns Amount of Tracks in the Queue */ shuffle(): Promise<number>; /** * Add a Track to the Queue, and after saved in the "db" it returns the amount of the Tracks * @param {Track | Track[]} TrackOrTracks * @param {number} index At what position to add the Track * @returns {number} Queue-Size (for the next Tracks) */ add(TrackOrTracks: Track | UnresolvedTrack | (Track | UnresolvedTrack)[], index?: number): any; /** * Splice the tracks in the Queue * @param {number} index Where to remove the Track * @param {number} amount How many Tracks to remove? * @param {Track | Track[]} TrackOrTracks Want to Add more Tracks? * @returns {Track} Spliced Track */ splice(index: number, amount: number, TrackOrTracks?: Track | UnresolvedTrack | (Track | UnresolvedTrack)[]): any; /** * Remove stuff from the queue.tracks array * - single Track | UnresolvedTrack * - multiple Track | UnresovedTrack * - at the index or multiple indexes * @param removeQueryTrack * @returns null (if nothing was removed) / { removed } where removed is an array with all removed elements * * @example * ```js * // remove single track * * const track = player.queue.tracks[4]; * await player.queue.remove(track); * * // if you already have the index you can straight up pass it too * await player.queue.remove(4); * * * // if you want to remove multiple tracks, e.g. from position 4 to position 10 you can do smt like this * await player.queue.remove(player.queue.tracks.slice(4, 10)) // get's the tracks from 4 - 10, which then get's found in the remove function to be removed * * // I still highly suggest to use .splice! * * await player.queue.splice(4, 10); // removes at index 4, 10 tracks * * await player.queue.splice(1, 1); // removes at index 1, 1 track * * await player.queue.splice(4, 0, ...tracks) // removes 0 tracks at position 4, and then inserts all tracks after position 4. * ``` */ remove<T extends Track | UnresolvedTrack | number | Track[] | UnresolvedTrack[] | number[] | (number | Track | UnresolvedTrack)[]>(removeQueryTrack: T): Promise<{ removed: (Track | UnresolvedTrack)[]; } | null>; /** * Shifts the previous array, to return the last previous track & thus remove it from the previous queue * @returns * * @example * ```js * // example on how to play the previous track again * const previous = await player.queue.shiftPrevious(); // get the previous track and remove it from the previous queue array!! * if(!previous) return console.error("No previous track found"); * await player.play({ clientTrack: previous }); // play it again * ``` */ shiftPrevious(): Promise<Track>; } declare class Player { /** Filter Manager per player */ filterManager: FilterManager; /** circular reference to the lavalink Manager from the Player for easier use */ LavalinkManager: LavalinkManager; /** Player options currently used, mutation doesn't affect player's state */ options: PlayerOptions; /** The lavalink node assigned the the player, don't change it manually */ node: LavalinkNode; /** The queue from the player */ queue: Queue; /** The Guild Id of the Player */ guildId: string; /** The Voice Channel Id of the Player */ voiceChannelId: string | null; /** The Text Channel Id of the Player */ textChannelId: string | null; /** States if the Bot is supposed to be outputting audio */ playing: boolean; /** States if the Bot is paused or not */ paused: boolean; /** Repeat Mode of the Player */ repeatMode: RepeatMode; /** Player's ping */ ping: { lavalink: number; ws: number; }; /** The Display Volume */ volume: number; /** The Volume Lavalink actually is outputting */ lavalinkVolume: number; /** The current Positin of the player (Calculated) */ get position(): number; /** The timestamp when the last position change update happened */ lastPositionChange: number; /** The current Positin of the player (from Lavalink) */ lastPosition: number; lastSavedPosition: number; /** When the player was created [Timestamp in Ms] (from lavalink) */ createdTimeStamp: number; /** The Player Connection's State (from Lavalink) */ connected: boolean | undefined; /** Voice Server Data (from Lavalink) */ voice: LavalinkPlayerVoiceOptions; voiceState: { selfDeaf: boolean; selfMute: boolean; serverDeaf: boolean; serverMute: boolean; suppress: boolean; }; /** Custom data for the player */ private readonly data; /** * Create a new Player * @param options * @param LavalinkManager */ constructor(options: PlayerOptions, LavalinkManager: LavalinkManager, dontEmitPlayerCreateEvent?: boolean); /** * Set custom data. * @param key * @param value */ set(key: string, value: unknown): this; /** * Get custom data. * @param key */ get<T>(key: string): T; /** * CLears all the custom data. */ clearData(): this; /** * Get all custom Data */ getAllData(): Record<string, unknown>; /** * Play the next track from the queue / a specific track, with playoptions for Lavalink * @param options */ play(options?: Partial<PlayOptions>): any; /** * Set the Volume for the Player * @param volume The Volume in percent * @param ignoreVolumeDecrementer If it should ignore the volumedecrementer option */ setVolume(volume: number, ignoreVolumeDecrementer?: boolean): Promise<this>; /** * Search for a track * @param query The query to search for * @param requestUser The user that requested the track * @param throwOnEmpty If an error should be thrown if no track is found * @returns The search result */ lavaSearch(query: LavaSearchQuery, requestUser: unknown, throwOnEmpty?: boolean): Promise<LavaSearchResponse | SearchResult>; /** * Set the SponsorBlock * @param segments The segments to set */ setSponsorBlock(segments?: SponsorBlockSegment[]): Promise<void>; /** * Get the SponsorBlock */ getSponsorBlock(): Promise<SponsorBlockSegment[]>; /** * Delete the SponsorBlock */ deleteSponsorBlock(): Promise<void>; /** * * @param query Query for your data * @param requestUser */ search(query: SearchQuery, requestUser: unknown, throwOnEmpty?: boolean): Promise<UnresolvedSearchResult | SearchResult>; /** * Pause the player */ pause(): Promise<this>; /** * Resume the Player */ resume(): Promise<this>; /** * Seek to a specific Position * @param position */ seek(position: number): Promise<this>; /** * Set the Repeatmode of the Player * @param repeatMode */ setRepeatMode(repeatMode: RepeatMode): Promise<this>; /** * Skip the current song, or a specific amount of songs * @param amount provide the index of the next track to skip to */ skip(skipTo?: number, throwError?: boolean): Promise<this>; /** * Clears the queue and stops playing. Does not destroy the Player and not leave the channel * @returns */ stopPlaying(clearQueue?: boolean, executeAutoplay?: boolean): Promise<this>; /** * Connects the Player to the Voice Channel * @returns */ connect(): Promise<this>; changeVoiceState(data: { voiceChannelId?: string; selfDeaf?: boolean; selfMute?: boolean; }): Promise<this>; /** * Disconnects the Player from the Voice Channel, but keeps the player in the cache * @param force If false it throws an error, if player thinks it's already disconnected * @returns */ disconnect(force?: boolean): Promise<this>; /** * Destroy the player and disconnect from the voice channel */ destroy(reason?: DestroyReasons | string, disconnect?: boolean): Promise<this>; /** * Get the current lyrics of the track currently playing on the guild * @param guildId The guild id to get the current lyrics for * @param skipTrackSource If true, it will not try to get the lyrics from the track source * @returns The current lyrics * @example * ```ts * const lyrics = await player.getCurrentLyrics(); * ``` */ getCurrentLyrics(skipTrackSource?: boolean): Promise<LyricsResult>; /** * Get the lyrics of a specific track * @param track The track to get the lyrics for * @param skipTrackSource If true, it will not try to get the lyrics from the track source * @returns The lyrics of the track * @example * ```ts * const lyrics = await player.getLyrics(player.queue.tracks[0], true); * ``` */ getLyrics(track: Track, skipTrackSource?: boolean): Promise<LyricsResult>; /** * Subscribe to the lyrics event on a specific guild to active live lyrics events * @returns The unsubscribe function * @example * ```ts * const lyrics = await player.subscribeLyrics(); * ``` */ subscribeLyrics(): Promise<unknown>; /** * Unsubscribe from the lyrics event on a specific guild to disable live lyrics events * @returns The unsubscribe function * @example * ```ts * const lyrics = await player.unsubscribeLyrics(); * ``` */ unsubscribeLyrics(): Promise<void>; /** * Move the player on a different Audio-Node * @param newNode New Node / New Node Id * @param checkSources If it should check if the sources are supported by the new node @default true * @return The new Node Id * @example * ```ts * const changeNode = await player.changeNode(newNode, true); * ``` */ changeNode(newNode: LavalinkNode | string, checkSources?: boolean): Promise<string>; /** * Move the player to a different node. If no node is provided, it will find the least used node that is not the same as the current node. * @param node the id of the node to move to * @returns the player * @throws RangeError if there is no available nodes. * @throws Error if the node to move to is the same as the current node. */ moveNode(node?: string): Promise<string | this>; /** Converts the Player including Queue to a Json state */ toJSON(): PlayerJson; } /** Sourcenames provided by lavalink server */ type LavalinkSourceNames = "youtube" | "youtubemusic" | "soundcloud" | "bandcamp" | "twitch"; /** Source Names provided by lava src plugin */ type LavalinkPlugin_LavaSrc_SourceNames = "deezer" | "spotify" | "applemusic" | "yandexmusic" | "flowery-tts" | "vkmusic" | "tidal" | "qobuz"; /** Source Names provided by jiosaavan plugin */ type LavalinkPlugin_JioSaavn_SourceNames = "jiosaavn"; /** The SourceNames provided by lavalink */ type SourceNames = LavalinkSourceNames | LavalinkPlugin_LavaSrc_SourceNames | LavalinkPlugin_JioSaavn_SourceNames; interface LavalinkTrackInfo { /** The Identifier of the Track */ identifier: string; /** The Track Title / Name */ title: string; /** The Name of the Author */ author: string; /** The duration of the Track */ length: number; /** The URL of the artwork if available */ artworkUrl: string | null; /** The URL (aka Link) of the Track called URI */ uri: string; /** The Source name of the Track, e.g. soundcloud, youtube, spotify */ sourceName: SourceNames; /** Wether the audio is seekable */ isSeekable: boolean; /** Wether the audio is of a live stream */ isStream: boolean; /** If isrc code is available, it's provided */ isrc: string | null; } interface TrackInfo { /** The Identifier of the Track */ identifier: string; /** The Track Title / Name */ title: string; /** The Name of the Author */ author: string; /** The duration of the Track */ duration: number; /** The URL of the artwork if available */ artworkUrl: string | null; /** The URL (aka Link) of the Track called URI */ uri: string; /** The Source name of the Track, e.g. soundcloud, youtube, spotify */ sourceName: SourceNames; /** Wether the audio is seekable */ isSeekable: boolean; /** Wether the audio is of a live stream */ isStream: boolean; /** If isrc code is available, it's provided */ isrc: string | null; } interface PluginInfo { /** The Type provided by a plugin */ type?: "album" | "playlist" | "artist" | "recommendations" | string; /** The Identifier provided by a plugin */ albumName?: string; /** The url of the album */ albumUrl?: string; /** The url of the album art */ albumArtUrl?: string; /** The url of the artist */ artistUrl?: string; /** The url of the artist artwork */ artistArtworkUrl?: string; /** The url of the preview */ previewUrl?: string; /** Whether the track is a preview */ isPreview?: boolean; /** The total number of tracks in the playlist */ totalTracks?: number; /** The Identifier provided by a plugin */ identifier?: string; /** The ArtworkUrl provided by a plugin */ artworkUrl?: string; /** The Author Information provided by a plugin */ author?: string; /** The Url provided by a Plugin */ url?: string; /** The Url provided by a Plugin */ uri?: string; /** You can put specific track information here, to transform the tracks... */ clientData?: { previousTrack?: boolean; [key: string]: any; }; } interface LavalinkTrack { /** The Base 64 encoded String */ encoded?: Base64; /** Track Information */ info: LavalinkTrackInfo; /** Plugin Information from Lavalink */ pluginInfo: Partial<PluginInfo>; /** The userData Object from when you provide to the lavalink request */ userData?: anyObject; } interface Track { /** The Base 64 encoded String */ encoded?: Base64; /** Track Information */ info: TrackInfo; /** Plugin Information from Lavalink */ pluginInfo: Partial<PluginInfo>; /** The Track's Requester */ requester?: unknown; /** The userData Object from when you provide to the lavalink request */ userData?: anyObject; } interface UnresolvedTrackInfo extends Partial<TrackInfo> { /** Required */ title: string; } interface UnresolvedQuery extends UnresolvedTrackInfo { /** The base64 of the unresolved track to "encode" */ encoded?: Base64; } interface UnresolvedTrack { /** Required */ resolve: (player: Player) => Promise<void>; /** The Base 64 encoded String */ encoded?: Base64; /** Track Information */ info: UnresolvedTrackInfo; /** Plugin Information from Lavalink */ pluginInfo: Partial<PluginInfo>; /** The userData Object from when you provide to the lavalink request */ userData?: anyObject; /** The Track's Requester */ requester?: unknown; } interface StoredQueue { current: Track | null; previous: Track[]; tracks: (Track | UnresolvedTrack)[]; } interface QueueStoreManager { /** @async get a Value (MUST RETURN UNPARSED!) */ get: (guildId: string) => Awaitable<StoredQueue | string>; /** @async Set a value inside a guildId (MUST BE UNPARSED) */ set: (guildId: string, value: StoredQueue | string) => Awaitable<void | boolean>; /** @async Delete a Database Value based of it's guildId */ delete: (guildId: string) => Awaitable<void | boolean>; /** @async Transform the value(s) inside of the QueueStoreManager (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */ stringify: (value: StoredQueue | string) => Awaitable<StoredQueue | string>; /** @async Parse the saved value back to the Queue (IF YOU DON'T NEED PARSING/STRINGIFY, then just return the value) */ parse: (value: StoredQueue | string) => Awaitable<Partial<StoredQueue>>; } interface ManagerQueueOptions { /** Maximum Amount of tracks for the queue.previous array. Set to 0 to not save previous songs. Defaults to 25 Tracks */ maxPreviousTracks?: number; /** Custom Queue Store option */ queueStore?: QueueStoreManager; /** Custom Queue Watcher class */ queueChangesWatcher?: QueueChangesWatcher; } interface QueueChangesWatcher { /** get a Value (MUST RETURN UNPARSED!) */ tracksAdd: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void; /** Set a value inside a guildId (MUST BE UNPARSED) */ tracksRemoved: (guildId: string, tracks: (Track | UnresolvedTrack)[], position: number | number[], oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void; /** Set a value inside a guildId (MUST BE UNPARSED) */ shuffled: (guildId: string, oldStoredQueue: StoredQueue, newStoredQueue: StoredQueue) => void; } type DestroyReasonsType = keyof typeof DestroyReasons | string; type DisconnectReasonsType = keyof typeof DisconnectReasons | string; interface PlayerJson { /** Guild Id where the player was playing in */ guildId: string; /** Options provided to the player */ options: PlayerOptions; /** Voice Channel Id the player was playing in */ voiceChannelId: string; /** Text Channel Id the player was synced to */ textChannelId?: string; /** Position the player was at */ position: number; /** Lavalink's position the player was at */ lastPosition: number; /** Last time the position was sent from lavalink */ lastPositionChange: number; /** Volume in % from the player (without volumeDecrementer) */ volume: number; /** Real Volume used in lavalink (with the volumeDecrementer) */ lavalinkVolume: number; /** The repeatmode from the player */ repeatMode: RepeatMode; /** Pause state */ paused: boolean; /** Wether the player was playing or not */ playing: boolean; /** When the player was created */ createdTimeStamp?: number; /** All current used fitlers Data */ filters: FilterData; /** The player's ping object */ ping: { /** Ping to the voice websocket server */ ws: number; /** Avg. calc. Ping to the lavalink server */ lavalink: number; }; /** Equalizer Bands used in lavalink */ equalizer: EQBand[]; /** The Id of the last used node */ nodeId?: string; /** The SessionId of the node */ nodeSessionId?: string; /** The stored queue */ queue?: StoredQueue; } type RepeatMode = "queue" | "track" | "off"; interface PlayerOptions { /** Guild id of the player */ guildId: string; /** The Voice Channel Id */ voiceChannelId: string; /** The Text Channel Id of the Player */ textChannelId?: string; /** instantly change volume with the one play request */ volume?: number; /** VC Region for node selections */ vcRegion?: string; /** if it should join deafened */ selfDeaf?: boolean; /** If it should join muted */ selfMute?: boolean; /** If it should use a specific lavalink node */ node?: LavalinkNode | string; /** If when applying filters, it should use the insta apply filters fix */ instaUpdateFiltersFix?: boolean; /** If a volume should be applied via filters instead of lavalink-volume */ applyVolumeAsFilter?: boolean; /** Custom Data for the player get/set datastorage */ customData?: anyObject; } type anyObject = { [key: string | number]: string | number | null | anyObject; }; interface BasePlayOptions { /** The position to start the track. */ position?: number; /** The position to end the track. */ endTime?: number; /** If to start "paused" */ paused?: boolean; /** The Volume to start with */ volume?: number; /** The Lavalink Filters to use | only with the new REST API */ filters?: Partial<LavalinkFilterData>; /** Voice Update for Lavalink */ voice?: LavalinkPlayerVoiceOptions; } interface LavalinkPlayOptions extends BasePlayOptions { /** Which Track to play | don't provide, if it should pick from the Queue */ track?: { /** The track encoded base64 string to use instead of the one from the queue system */ encoded?: Base64 | null; /** The identifier of the track to use */ identifier?: string; /** Custom User Data for the track to provide, will then be on the userData object from the track */ userData?: anyObject; /** The Track requester for when u provide encodedTrack / identifer */ requester?: unknown; }; } interface PlayOptions extends LavalinkPlayOptions { /** Whether to not replace the track if a play payload is sent. */ noReplace?: boolean; /** Adds track on queue and skips to it */ clientTrack?: Track | UnresolvedTrack; } /** Ability to manipulate fetch requests */ type ModifyRequest = (options: RequestInit & { path: string; extraQueryUrlParams?: URLSearchParams; }) => void; type SponsorBlockSegment = "sponsor" | "selfpromo" | "interaction" | "intro" | "outro" | "preview" | "music_offtopic" | "filler"; /** * Node Options for creating a lavalink node */ interface LavalinkNodeOptions { /** The Lavalink Server-Ip / Domain-URL */ host: string; /** The Lavalink Connection Port */ port: number; /** The Lavalink Password / Authorization-Key */ authorization: string; /** Does the Server use ssl (https) */ secure?: boolean; /** RESUME THE PLAYER? by providing a sessionid on the node-creation */ sessionId?: string; /** Add a Custom ID to the node, for later use */ id?: string; /** Voice Regions of this Node */ regions?: string[]; /** The retryAmount for the node. */ retryAmount?: number; /** The retryDelay for the node. */ retryDelay?: number; /** signal for cancelling requests - default: AbortSignal.timeout(options.requestSignalTimeoutMS || 10000) - put <= 0 to disable */ requestSignalTimeoutMS?: number; /** Close on error */ closeOnError?: boolean; /** Heartbeat interval , set to <= 0 to disable heartbeat system */ heartBeatInterval?: 30000; /** Recommended, to check wether the client is still connected or not on the stats endpoint */ enablePingOnStatsCheck?: boolean; } /** * Memory Stats object from lavalink */ interface MemoryStats { /** The free memory of the allocated amount. */ free: number; /** The used memory of the allocated amount. */ used: number; /** The total allocated memory. */ allocated: number; /** The reservable memory. */ reservable: number; } /** * CPU Stats object from lavalink */ interface CPUStats { /** The core amount the host machine has. */ cores: number; /** The system load. */ systemLoad: number; /** The lavalink load. */ lavalinkLoad: number; } /** * FrameStats Object from lavalink */ interface FrameStats { /** The amount of sent frames. */ sent?: number; /** The amount of nulled frames. */ nulled?: number; /** The amount of deficit frames. */ deficit?: number; } /** * BaseNodeStats object from Lavalink */ interface BaseNodeStats { /** The amount of players on the node. */ players: number; /** The amount of playing players on the node. */ playingPlayers: number; /** The uptime for the node. */ uptime: number; /** The memory stats for the node. */ memory: MemoryStats; /** The cpu stats for the node. */ cpu: CPUStats; /** The frame stats for the node. */ frameStats: FrameStats; } /** * Interface for nodeStats from lavalink */ interface NodeStats extends BaseNodeStats { /** The frame stats for the node. */ frameStats: FrameStats; } /** * Entire lavalink information object from lavalink */ interface LavalinkInfo { /** The version of this Lavalink server */ version: VersionObject; /** The millisecond unix timestamp when this Lavalink jar was built */ buildTime: number; /** The git information of this Lavalink server */ git: GitObject; /** The JVM version this Lavalink server runs on */ jvm: string; /** The Lavaplayer version being used by this server */ lavaplayer: string; /** The enabled source managers for this server */ sourceManagers: string[]; /** The enabled filters for this server */ filters: string[]; /** The enabled plugins for this server */ plugins: PluginObject[]; } /** * Lavalink's version object from lavalink */ interface VersionObject { /** The full version string of this Lavalink server */ semver: string; /** The major version of this Lavalink server */ major: number; /** The minor version of this Lavalink server */ minor: number; /** The patch version of this Lavalink server */ patch: internal; /** The pre-release version according to semver as a . separated list of identifiers */ preRelease?: string; /** The build metadata according to semver as a . separated list of identifiers */ build?: string; } /** * Git information object from lavalink */ interface GitObject { /** The branch this Lavalink server was built on */ branch: string; /** The commit this Lavalink server was built on */ commit: string; /** The millisecond unix timestamp for when the commit was created */ commitTime: string; } /** * Lavalink's plugins object from lavalink's plugin */ interface PluginObject { /** The name of the plugin */ name: string; /** The version of the plugin */ version: string; } interface LyricsResult { /**The name of the source */ sourceName: string; /**The name of the provider */ provider: string; /**The result text */ text: string | null; /**The lyrics lines */ lines: LyricsLine[]; /**Information about the plugin */ plugin: PluginInfo; } interface LyricsLine { /**The millisecond timestamp */ timestamp: number; /**The line duration in milliseconds */ duration: number | null; /**The line text */ line: string; /**Information about the plugin */ plugin: PluginInfo; } type LavalinkNodeIdentifier = string; interface NodeManagerEvents { /** * Emitted when a Node is created. * @event Manager.nodeManager#create */ "create": (node: LavalinkNode) => void; /** * Emitted when a Node is destroyed. * @event Manager.nodeManager#destroy */ "destroy": (node: LavalinkNode, destroyReason?: DestroyReasonsType) => void; /** * Emitted when a Node is connected. * @event Manager.nodeManager#connect */ "connect": (node: LavalinkNode) => void; /** * Emitted when a Node is reconnecting. * @event Manager.nodeManager#reconnecting */ "reconnecting": (node: LavalinkNode) => void; /** * Emitted When a node starts to reconnect (if you have a reconnection delay, the reconnecting event will be emitted after the retryDelay.) * Useful to check wether the internal node reconnect system works or not * @event Manager.nodeManager#reconnectinprogress */ "reconnectinprogress": (node: LavalinkNode) => void; /** * Emitted when a Node is disconnects. * @event Manager.nodeManager#disconnect */ "disconnect": (node: LavalinkNode, reason: { code?: number; reason?: string; }) => void; /** * Emitted when a Node is error. * @event Manager.nodeManager#error */ "error": (node: LavalinkNode, error: Error, payload?: unknown) => void; /** * Emits every single Node event. * @event Manager.nodeManager#raw */ "raw": (node: LavalinkNode, payload: unknown) => void; /** * Emits when the node connects resumed. You then need to create all players within this event for your usecase. * Aka for that you need to be able to save player data like vc channel + text channel in a db and then sync it again * @event Manager.nodeManager#nodeResumed */ "resumed": (node: LavalinkNode, payload: { resumed: true; sessionId: string; op: "ready"; }, players: LavalinkPlayer[] | InvalidLavalinkRestRequest) => void; } declare const TrackSymbol: unique symbol; declare const UnresolvedTrackSymbol: unique symbol; declare const QueueSymbol: unique symbol; declare const NodeSymbol: unique symbol; /** * Parses Node Connection Url: "lavalink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>" * @param connectionUrl * @returns */ declare function parseLavalinkConnUrl(connectionUrl: string): { authorization: string; id: string; host: string; port: number; }; declare class ManagerUtils { LavalinkManager: LavalinkManager | undefined; constructor(LavalinkManager?: LavalinkManager); buildPluginInfo(data: any, clientData?: any): any; buildTrack(data: LavalinkTrack | Track, requester: unknown): Track; /** * Builds a UnresolvedTrack to be resolved before being played . * @param query * @param requester */ buildUnresolvedTrack(query: UnresolvedQuery | UnresolvedTrack, requester: unknown): UnresolvedTrack; /** * Validate if a data is equal to a node * @param data */ isNode(data: LavalinkNode): boolean; g