lavalink-client
Version:
Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.
1,405 lines (1,395 loc) • 117 kB
TypeScript
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