UNPKG

lavalink-client

Version:

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

1,191 lines (1,184 loc) 176 kB
import { EventEmitter } from 'node:events'; import { ReadableStream } from 'node:stream/web'; /** * Debug events for more detailed logging */ 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", SocketCleanupError = "SocketCleanupError", 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", PlayerDestroyFail = "PlayerDestroyFail", PlayerChangeNodeFailNoEligibleNode = "PlayerChangeNodeFailNoEligibleNode", PlayerChangeNodeFail = "PlayerChangeNodeFail" } /** * Reasons why a player got destroyed */ 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" } /** * Reasons why a player got disconnected */ declare enum DisconnectReasons { Disconnected = "Disconnected", DisconnectAllNodes = "DisconnectAllNodes" } /** The valid SponsorBlock categories */ declare const validSponsorBlocks: string[]; /** The audio Outputs Data map declaration */ declare const audioOutputsData: Record<AudioOutputs, ChannelMixFilter>; /** Equalizer Presets */ 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[]; }; declare const RecommendationsStrings: { highCPULoad: (cpuLoad: number) => string; highSystemLoad: (systemLoad: number) => string; highMemoryUsage: (memoryUsagePercent: number) => string; frameDeficit: (frameDeficit: number) => string; highLatency: (ping: number) => string; nodeRestart: string; highPlayercount: (players: number) => string; nodeOffline: string; checkConnectivity: string; }; declare const NodeLinkExclusiveEvents: NodeLinkEventTypes[]; 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 | undefined>; /** @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 | null; /** 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; /** Whether 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; /** NodeLink Specific audioTrackId option */ audioTrackId?: string; }; } 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) & { audioTrackId?: string; }; } /** 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" | "pandora"; /** 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; /** Whether the audio is seekable */ isSeekable: boolean; /** Whether 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; /** Whether the audio is seekable */ isSeekable: boolean; /** Whether 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 TrackRequester { } 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?: TrackRequester; /** 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?: TrackRequester; } 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>" or "nodelink://<nodeId>:<nodeAuthorization(Password)>@<NodeHost>:<NodePort>" * @param connectionUrl * @returns */ declare function parseLavalinkConnUrl(connectionUrl: string): { authorization: string; nodeType: NodeType; id: string; host: string; port: number; }; declare class ManagerUtils { LavalinkManager: LavalinkManager | undefined; /** Override this with your custom sources record if you want to use custom sources for your node */ SourcesRecord: Record<SearchPlatform, LavalinkSearchPlatform | ClientCustomSearchPlatformUtils>; constructor(LavalinkManager?: LavalinkManager); /** * Builds a pluginInfo object based on the provided data, extracting relevant information from the data and clientData parameters. This function is used to construct the pluginInfo property for tracks, allowing for consistent handling of plugin-related information across different track sources and formats. * @param data * @param clientData * @returns */ buildPluginInfo(data: any, clientData?: any): any; /** * Builds a Track object from the provided data and requester information. It validates the presence of required properties in the data, transforms the requester using a custom transformer function if provided, and constructs a Track object with the appropriate properties and plugin information. The function also includes error handling to ensure that the input data is valid and provides debug information if track building fails. * @param data * @param requester * @returns */ 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; /** * Gets the transformed requester based on the LavalinkManager options. If a custom requester transformer function is provided in the player options, it applies that function to the requester; otherwise, it returns the requester as is. The function also includes error handling to catch any exceptions that may occur during the transformation process and emits a debug event if the transformation fails. * @param requester * @returns */ getTransformedRequester(requester: unknown): unknown; /** * Validate if a data is equal to node options * @param data */ isNodeOptions(data: LavalinkNodeOptions): boolean; /** * Validate tracks based on duration whether they are playble or broken tracks. * most tracks should be longer than 30s, so you can put a minDuration of 29e3 (cause preview tracks are exactly 30s) or put 0. * This check is not done automatically, you need to check it yourself by doing: * @example * ```ts * const res = await player.search("Adele"); * * // short hand: * const validTracks = res.tracks.filter(client.lavalink.utils.isNotBrokenTrack) * // or with options: * const validTracks = res.tracks.filter(t => client.lavalink.utils.isNotBrokenTrack(t, 29e3)); * * // then you can add it to the queue. * await player.queue.add(validTracks); * ``` */ isNotBrokenTrack(data: Track | UnresolvedTrack, minDuration?: number): data is Track; /** * Validate if a data is equal to a track * @param data the Track to validate * @returns */ isTrack(data: Track | UnresolvedTrack): data is Track; /** * Checks if the provided argument is a valid UnresolvedTrack. * @param track */ isUnresolvedTrack(data: UnresolvedTrack | Track): data is UnresolvedTrack; /** * Checks if the provided argument is a valid UnresolvedTrack. * @param track */ isUnresolvedTrackQuery(data: UnresolvedQuery): boolean; /** * Gets the closest track by resolving the provided UnresolvedTrack using the getClosestTrack function. It includes error handling to catch any exceptions that may occur during the resolution process and emits a debug event if the resolution fails. The function returns a Promise that resolves to a Track object if successful, or undefined if no closest track is found. * @param data * @param player * @returns */ getClosestTrack(data: UnresolvedTrack, player: Player): Promise<Track | undefined>; /** * Validates the query string against various criteria, including checking for empty strings, length limits for specific sources, blacklisted links or words, and ensuring that the Lavalink node has the necessary source managers enabled for the provided query. The function also includes debug event emissions to assist with troubleshooting and understanding the validation process. * @param node * @param queryString * @param sourceString * @returns */ validateQueryString(node: LavalinkNode, queryString: string, sourceString?: SearchPlatform): void; /** * Finds the source of a query string by checking if it starts with a valid source prefix defined in the Default Sources object. If a valid source prefix is found, it returns the corresponding SearchPlatform; otherwise, it returns null. This function is useful for determining the intended search platform for a given query string, allowing for more accurate search results when the user specifies a source (e.g., "ytsearch:Never Gonna Give You Up" would indicate that the search should be performed on YouTube). * @param queryString * @returns */ findSourceOfQuery(queryString: string): SearchPlatform; /** * Extracts the source from the query if it starts with a valid source prefix (e.g., "ytsearch:") and updates the searchQuery object accordingly. * @param searchQuery * @returns The updated searchQuery object with the extracted source and modified query string. */ extractSourceOfQuery<T extends { query: string; source?: string; }>(searchQuery: T): T; /** * Converts a string to lowercase if the input is a string, otherwise returns the input as is. This is useful for ensuring that search platform identifiers are case-insensitive while allowing other types of input to pass through unchanged. * @param input * @returns */ typedLowerCase<T extends unknown>(input: T): T; /** * Transforms a search query by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, and the determined search platform to be used for the search operation. * @param query * @returns */ transformQuery(query: SearchQuery): { query: string; extraQueryUrlParams: any; source: SearchPlatform; }; /** * Transforms a LavaSearchQuery by determining the appropriate search platform based on the query string and the default search platform specified in the LavalinkManager options. It checks if the query string starts with a valid source prefix and extracts it if present. The function returns an object containing the modified query string, any extra URL parameters, the determined search platform to be used for the search operation, and the types of search (track, playlist, artist, album, text) to be performed. * @param query * @returns */ transformLavaSearchQuery(query: LavaSearchQuery): { query: never; types: any[]; extraQueryUrlParams: any; source: SearchPlatform; } | { query: string; types: string[]; source: "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec" | "tdsearch" | "tdrec" | "qbsearch" | "qbisrc" | "qbrec" | "jssearch" | "jsrec" | "ftts" | "speak" | "phsearch" | "pornhub" | "porn" | "tts" | "amzsearch" | "admsearch" | "gnsearch" | "szsearch" | "pdsearch" | "local" | "http" | "https" | "link" | "uri" | "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk" | "vk music" | "vkmusic" | "tidal" | "tidal music" | "qobuz" | "pandora" | "pd" | "pandora music" | "pandoramusic" | "flowerytts" | "flowery" | "flowery.tts" | "bandcamp" | "bc" | "js" | "jiosaavn" | "td"; }; /** * Validates the provided source string against the capabilities of the Lavalink node. It checks if the source string is supported by the node's enabled source managers and plugins, throwing errors if any required sources or plugins are missing for the specified search platform. This ensures that search queries are only executed with compatible sources based on the node's configuration. * @param node * @param sourceString * @returns */ validateSourceString(node: LavalinkNode, sourceString: SearchPlatform): void; } /** * Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself * * @internal */ interface MiniMap<K, V> extends Map<K, V> { constructor: MiniMapConstructor; } declare class MiniMap<K, V> extends Map<K, V> { constructor(data?: [K, V][]); /** * Identical to * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), * but returns a MiniMap instead of an Array. * * @param fn The function to test with (should return boolean) * @param thisArg Value to use as `this` when executing function * * @example * miniMap.filter(user => user.username === 'Bob'); */ filter<K2 extends K>(fn: (value: V, key: K, miniMap: this) => key is K2): MiniMap<K2, V>; filter<V2 extends V>(fn: (value: V, key: K, miniMap: this) => value is V2): MiniMap<K, V2>; filter(fn: (value: V, key: K, miniMap: this) => boolean): MiniMap<K, V>; filter<This, K2 extends K>(fn: (this: This, value: V, key: K, miniMap: this) => key is K2, thisArg: This): MiniMap<K2, V>; filter<This, V2 extends V>(fn: (this: This, value: V, key: K, miniMap: this) => value is V2, thisArg: This): MiniMap<K, V2>; filter<This>(fn: (this: This, value: V, key: K, miniMap: this) => boolean, thisArg: This): MiniMap<K, V>; toJSON(): [K, V][]; /** * Maps each item to another value into an array. Identical in behavior to * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). * * @param fn Function that produces an element of the new array, taking three arguments * @param thisArg Value to use as `this` when executing function * * @example * miniMap.map(user => user.tag); */ map<T>(fn: (value: V, key: K, miniMap: this) => T): T[]; map<This, T>(fn: (this: This, value: V, key: K, miniMap: this) => T, thisArg: This): T[]; } declare function queueTrackEnd(player: Player, dontShiftQueue?: boolean): Promise<Track>; declare function safeStringify(obj: any, padding?: number): string; /** Helper for generating Opaque types. */ type Opaque<T, K> = T & { __opaque__: K; }; /** Opqaue tyep for integernumber */ type IntegerNumber = Opaque<number, "Int">; /** Opqaue tyep for floatnumber */ type FloatNumber = Opaque<number, "Float">; type LavaSrcSearchPlatformBase = "spsearch" | "sprec" | "amsearch" | "dzsearch" | "dzisrc" | "dzrec" | "ymsearch" | "ymrec" | "vksearch" | "vkrec" | "tdsearch" | "tdrec" | "qbsearch" | "qbisrc" | "qbrec" | "ytsearch" | "jssearch" | "jsrec"; type LavaSrcSearchPlatform = LavaSrcSearchPlatformBase | "ftts"; type JioSaavnSearchPlatform = "jssearch" | "jsrec"; type DuncteSearchPlatform = "speak" | "phsearch" | "pornhub" | "porn" | "tts"; type PulseLinkSearchPlatform = "spsearch" | "amzsearch" | "amsearch" | "dzsearch" | "ymsearch" | "vksearch" | "tdsearch" | "qbsearch" | "jssearch" | "admsearch" | "gnsearch" | "szsearch" | "pdsearch" | "ytsearch" | "ytmsearch"; type LavalinkClientSearchPlatform = "bcsearch"; type LavalinkClientSearchPlatformResolve = "bandcamp" | "bc"; type LavalinkSearchPlatform = "ytsearch" | "ytmsearch" | "scsearch" | "bcsearch" | LavaSrcSearchPlatform | DuncteSearchPlatform | PulseLinkSearchPlatform | JioSaavnSearchPlatform | LavalinkClientSearchPlatform; type NodeLinkSearchPlatformBase = "ytsearch" | "ytmsearch" | "scsearch" | "search" | "spsearch" | "amsearch" | "dzsearch" | "tdsearch" | "bcsearch" | "admsearch" | "audiomack" | "gaanasearch" | "jssearch" | "lfsearch" | "pdsearch" | "vksearch" | "mcsearch" | "ncsearch" | "nicovideo" | "bilibili" | "shsearch" | "szsearch" | "ebox" | "jukebox" | "slsearch" | "qbsearch" | "ymsearch" | "ausearch" | "azsearch" | "agsearch" | "bksearch" | "lmsearch" | "pipertts" | "gtts" | "speak" | "ftts" | "flowery" | "gdsearch"; type NodeLinkRecommendationPlatform = "ytrec" | "sprec" | "dzrec" | "tdrec" | "jsrec" | "vkrec"; type NodeLinkSearchPlatform = NodeLinkSearchPlatformBase | NodeLinkRecommendationPlatform; type ClientCustomSearchPlatformUtils = "local" | "http" | "https" | "link" | "uri"; type ClientSearchPlatform = ClientCustomSearchPlatformUtils | "youtube" | "yt" | "youtube music" | "youtubemusic" | "ytm" | "musicyoutube" | "music youtube" | "soundcloud" | "sc" | "am" | "apple music" | "applemusic" | "apple" | "musicapple" | "music apple" | "sp" | "spsuggestion" | "spotify" | "spotify.com" | "spotifycom" | "dz" | "deezer" | "yandex" | "yandex music" | "yandexmusic" | "vk" | "vk music" | "vkmusic" | "tidal" | "tidal music" | "qobuz" | "pandora" | "pd" | "pandora music" | "pandoramusic" | "flowerytts" | "flowery" | "flowery.tts" | LavalinkClientSearchPlatformResolve | LavalinkClientSearchPlatform | "js" | "jiosaavn" | "td" | "tidal" | "tdrec"; type SearchPlatform = LavalinkSearchPlatform | ClientSearchPlatform; type SourcesRegex = "YoutubeRegex" | "YoutubeMusicRegex" | "SoundCloudRegex" | "SoundCloudMobileRegex" | "DeezerTrackRegex" | "DeezerArtistRegex" | "DeezerEpisodeRegex" | "DeezerMixesRegex" | "DeezerPageLinkRegex" | "DeezerPlaylistRegex" | "DeezerAlbumRegex" | "AllDeezerRegex" | "AllDeezerRegexWithoutPageLink" | "SpotifySongRegex" | "SpotifyPlaylistRegex" | "SpotifyArtistRegex" | "SpotifyEpisodeRegex" | "SpotifyShowRegex" | "SpotifyAlbumRegex" | "AllSpotifyRegex" | "mp3Url" | "m3uUrl" | "m3u8Url" | "mp4Url" | "m4aUrl" | "wavUrl" | "aacpUrl" | "tiktok" | "mixcloud" | "musicYandex" | "radiohost" | "bandcamp" | "jiosaavn" | "appleMusic" | "tidal" | "PandoraTrackRegex" | "PandoraAlbumRegex" | "PandoraArtistRegex" | "PandoraPlaylistRegex" | "AllPandoraRegex" | "TwitchTv" | "vimeo"; interface PlaylistInfo { /** The playlist name */ name: string; /** The playlist title (same as name) */ title: string; /** The playlist Author */ author?: string; /** The playlist Thumbnail */ thumbnail?: string; /** A Uri to the playlist */ uri?: string; /** The playlist selected track. */ selectedTrack: Track | null; /** The duration of the entire playlist. (calcualted) */ duration: number; } interface SearchResult { loadType: LoadTypes; exception: Exception | null; pluginInfo: PluginInfo; playlist: PlaylistInfo | null; tracks: Track[]; } interface UnresolvedSearchResult { loadType: LoadTypes; exception: Exception | null; pluginInfo: PluginInfo; playlist: PlaylistInfo | null; tracks: UnresolvedTrack[]; } /** * @internal */ interface MiniMapConstructor { new (): MiniMap<unknown, unknown>; new <K, V>(entries?: ReadonlyArray<readonly [K, V]> | null): MiniMap<K, V>; new <K, V>(iterable: Iterable<readonly [K, V]>): MiniMap<K, V>; readonly prototype: MiniMap<unknown, unknown>; readonly [Symbol.species]: MiniMapConstructor; } type PlayerEvents = TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExceptionEvent | WebSocketClosedEvent | SponsorBlockSegmentEvents | LyricsEvent; type Severity = "COMMON" | "SUSPICIOUS" | "FAULT"; interface Exception { /** Severity of the error */ severity: Severity; /** Nodejs Error */ error?: Error; /** Message by lavalink */ message: string; /** Cause by lavalink */ cause: string; /** causeStackTrace by lavalink */ causeStackTrace: string; } interface PlayerEvent { op: "event"; type: PlayerEventType; guildId: string; } interface TrackStartEvent extends PlayerEvent { type: "TrackStartEvent"; track: LavalinkTrack; } interface TrackEndEvent extends PlayerEvent { type: "TrackEndEvent"; track: LavalinkTrack; reason: TrackEndReason; } interface TrackExceptionEvent extends PlayerEvent { type: "TrackExceptionEvent"; exception?: Exception; track: LavalinkTrack; error: string; } interface TrackStuckEvent extends PlayerEvent { type: "TrackStuckEvent"; thresholdMs: number; track: LavalinkTrack; } interface WebSocketClosedEvent extends PlayerEvent { type: "WebSocketClosedEvent"; code: number; byRemote: boolean; reason: string; } /** * Types & Events for Sponsorblock-plugin from Lavalink: https://github.com/topi314/Sponsorblock-Plugin#segmentsloaded */ type SponsorBlockSegmentEvents = SponsorBlockSegmentSkipped | SponsorBlockSegmentsLoaded | SponsorBlockChapterStarted | SponsorBlockChaptersLoaded; type SponsorBlockSegmentEventType = "SegmentSkipped" | "SegmentsLoaded" | "ChaptersLoaded" | "ChapterStarted"; interface SponsorBlockSegmentsLoaded extends PlayerEvent { type: "SegmentsLoaded"; segments: { category: string; start: number; end: number; }[]; } interface SponsorBlockSegmentSkipped extends PlayerEvent { type: "SegmentSkipped"; segment: { category: string; start: number; end: number; }; } interface SponsorBlockChapterStarted extends PlayerEvent { type: "ChapterStarted"; /** The Chapter which started */ chapter: { /** The Name of the Chapter */ name: string; start: number; end: number; duration: number; }; } interface SponsorBlockChaptersLoaded extends PlayerEvent { type: "ChaptersLoaded"; /** All Chapters loaded */ chapters: { /** The Name of the Chapter */ name: string; start: number; end: number; duration: number; }[]; } /** * Types & Events for Lyrics plugin from Lavalink: https://github.com/topi314/LavaLyrics */ type LyricsEvent = LyricsFoundEvent | LyricsNotFoundEvent | LyricsLineEvent; type LyricsEventType = "LyricsFoundEvent" | "LyricsNotFoundEvent" | "LyricsLineEvent"; interface LyricsFoundEvent extends PlayerEvent { /** The lyricsfound event */ type: "LyricsFoundEvent"; /** The guildId */ guildId: string; /** The lyrics */ lyrics: LyricsResult; } interface LyricsNotFoundEvent extends PlayerEvent { /**The lyricsnotfound event*/ type: "LyricsNotFoundEvent"; /**The guildId*/ guildId: string; } interface LyricsLineEvent extends PlayerEvent { /**The lyricsline event*/ type: "LyricsLineEvent"; /** The guildId */ guildId: string; /** The line number */ lineIndex: number; /** The line */ line: LyricsLine; /**skipped is true if the line was skipped */ skipped: boolean; } type LoadTypes = "track" | "playlist" | "search" | "error" | "empty"; type State = "CONNECTED" | "CONNECTING" | "DISCONNECTED" | "DISCONNECTING" | "DESTROYING"; type PlayerEventType = "TrackStartEvent" | "TrackEndEvent" | "TrackExceptionEvent" | "TrackStuckEvent" | "WebSocketClosedEvent" | SponsorBlockSegmentEventType | LyricsEventType; type TrackEndReason = "finished" | "loadFailed" | "stopped" | "replaced" | "cleanup"; interface InvalidLavalinkRestRequest { /** Rest Request Data for when it was made */ timestamp: number; /** Status of the request */ status: number; /** Specific Errro which was sent */ error: string; /** Specific Message which was created */ message?: string; /** The specific error trace from the request */ trace?: unknown; /** Path of where it's from */ path: string; } interface LavalinkPlayerVoice { /** The Voice Token */ token: string; /** The Voice Server Endpoint */ endpoint: string; /** The Voice SessionId */ sessionId: string; /** The Voice Channel Id */ channelId?: string; /** Whether or not the player is connected */ connected?: boolean; /** The Ping to the voice server */ ping?: number; } type LavalinkPlayerVoiceOptions = Omit<LavalinkPlayerVoice, "connected" | "ping">; interface FailingAddress { /** The failing address */ failingAddress: string; /** The timestamp when the address failed */ failingTimestamp: number; /** The timestamp when the address failed as a pretty string */ failingTime: string; } type RoutePlannerTypes = "RotatingIpRoutePlanner" | "NanoIpRoutePlanner" | "RotatingNanoIpRoutePlanner" | "BalancingIpRoutePlanner"; interface RoutePlanner { class?: RoutePlannerTypes; details?: { /** The ip block being used */ ipBlock: { /** The type of the ip block */ type: "Inet4Address" | "Inet6Address"; /** The size of the ip block */ size: string; }; /** The failing addresses */ failingAddresses: FailingAddress[]; /** The number of rotations */ rotateIndex?: string; /** The current offset in the block */ ipIndex?: string; /** The current address being used */ currentAddress?: string; /** The current offset in the ip block */ currentAddressIndex?: string; /** The information in which /64 block ips are chosen. This number increases on each ban. */ blockIndex?: string; }; } interface Session { /** Whether or not session is resuming or not */ resuming: boolean; /** For how long a session is lasting while not connected */ timeout: number; } interface GuildShardPayload { /** The OP code */ op: number; /** Data to send */ d: { /** Guild id to apply voice settings */ guild_id: string; /** channel to move/connect to, or null to leave it */ channel_id: string | null; /** whether or not mute yourself */ self_mute: boolean; /** whether or not deafen yourself */ self_deaf: boolean; }; } interface PlayerUpdateInfo { /** guild id of the player */ guildId: string; /** Player options to provide to lavalink */ playerOptions: LavalinkPlayOptions; /** Whether or not replace the current track with the new one (true is recommended) */ noReplace?: boolean; } interface LavalinkPlayer { /** Guild Id of the player */ guildId: string; /** IF playing a track, all of the track information */ track?: LavalinkTrack; /** Lavalink volume (mind volumedecrementer) */ volume: number; /** Whether it's paused or not */ paused: boolean; /** Voice Endpoint data */ voice: LavalinkPlayerVoice; /** All Audio Filters */ filters: Partial<LavalinkFilterData>; /** Lavalink-Voice-State Variables */ state: { /** Time since connection established */ time: number; /** Position of the track */ position: number; /** COnnected or not */ connected: boolean; /** Ping to voice server */ ping: number; }; } interface ChannelDeletePacket { /** Packet key for channel delete */ t: "CHANNEL_DELETE"; /** data which is sent and relevant */ d: { /** guild id */ guild_id: string; /** Channel id */ id: string; }; } interface VoiceState { /** OP key from lavalink */ op: "voiceUpdate"; /** GuildId provided by lavalink */ guildId: string; /** Event data */ event: VoiceServer; /** Session Id of the voice connection */ sessionId?: string; /** guild id of the voice channel */ guild_id: string; /** user id from the voice connection */ user_id: string; /** Session Id of the voice connection */ session_id: string; /** Voice Channel Id */ channel_id: string; /** Server Mute status */ mute: boolean; /** Server Deaf status */ deaf: boolean; /** Self Deaf status */ self_deaf: boolean; /** Self Mute status */ self_mute: boolean; /** Self Video (Camera) status */ self_video: boolean; /** Self Stream status */ self_stream: boolean; /** Whether the user requests to speak (stage channel) */ request_to_speak_timestamp: boolean; /** Self suppressed status (stage channel) */ suppress: boolean; } /** The Base64 decodes tring by lavalink */ type Base64 = string; interface VoiceServer { /** Voice Token */ token: string; /** Guild Id of the voice server connection */ guild_id: string; /** Server Endpoint */ endpoint: string; /** Voice Channel Id (Lavalink v4 DAVE support) */ channel_id?: string; } interface VoicePacket { /** Voice Packet Keys to send */ t?: "VOICE_SERVER_UPDATE" | "VOICE_STATE_UPDATE"; /** Voice Packets to send */ d: VoiceState | VoiceServer; } interface NodeMessage extends NodeStats { /** The type of the event */ type: PlayerEventType; /** what ops are applying to that event */ op: "stats" | "playerUpdate" | "event"; /** The specific guild id for that message */ guildId: string; } /** Specific types to filter for lavasearch, will be filtered to correct types */ type LavaSearchType = "track" | "album" | "artist" | "playlist" | "text" | "tracks" | "albums" | "artists" | "playlists" | "texts"; interface LavaSearchFilteredResponse { /** The Information of a playlist provided by lavasearch */ info: PlaylistInfo; /** additional plugin information */ pluginInfo: PluginInfo; /** List of tracks */ tracks: Track[]; } interface LavaSearchResponse { /** An array of tracks, only present if track is in types */ tracks: Track[]; /** An array of albums, only present if album is in types */ albums: LavaSearchFilteredResponse[]; /** An array of artists, only present if artist is in types */ artists: LavaSearchFilteredResponse[]; /** An array of playlists, only present if playlist is in types */ playlists: LavaSearchFilteredResponse[]; /** An array of text results, only present if text is in types */ texts: { text: string; pluginInfo: PluginInfo; }[]; /** Addition result data provided by plugins */ pluginInfo: PluginInfo; } /** SearchQuery Object for raw lavalink requests */ type SearchQuery = { /** lavalink search Query / identifier string */ query: string; /** Extra url query params to use, e.g. for flowertts */ extraQueryUrlParams?: URLSearchParams; /** Source to append to the search query string */ source?: SearchPlatform; } | /** Our just the search query / identifier string */ string; /** SearchQuery Object for Lavalink LavaSearch Plugin requests */ type LavaSearchQuery = { /** lavalink search Query / identifier string */ query: string; /** Source to append to the search query string */ source: LavaSrcSearchPlatformBase; /** The Types to filter the search to */ types?: LavaSearchType[]; }; type Awaitable<T> = Promise<T> | T; /** 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; /** if NodeLink echo filter is enabled / not */ nodeLinkEcho: boolean; /** if NodeLink chorus filter is enabled / not */ nodeLinkChorus: boolean; /** if NodeLink compressor filter is enabled / not */ nodeLinkCompressor: boolean; /** if NodeLink highpass filter is enabled / not */ nodeLinkHighPass: boolean; /** if NodeLink phaser filter is enabled / not */ nodeLinkPhaser: boolean; /** if NodeLink spatial filter is enabled / not */ nodeLinkSpatial: boolean; /** 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; } /** * Creates delay-based echo with feedback control */ interface NodeLink_EchoFilter { /** Delay time in milliseconds (0 to 5000ms) */ delay?: number; /** Amount of signal fed back into the delay (0.0 to 1.0) */ feedback?: number; /** Dry/wet mix ratio (0.0 = dry only, 1.0 = wet only) */ mix?: number; } /** * Simulates multiple voices playing together with modulated delays */ interface NodeLink_ChorusFilter { /** LFO modulation rate in Hz */ rate?: number; /** Modulation depth (0.0 to 1.0) */ depth?: number; /** Base delay time in milliseconds (1 to 45ms) */ delay?