synthra-client
Version:
A user-friendly Lavalink client designed for NodeJS.
468 lines (467 loc) • 20.7 kB
TypeScript
import { PlayerEvent, PlayerEvents, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, WebSocketClosedEvent } from "./Utils";
import { Synthra, SearchPlatform } from "./Manager";
import { Player, Track } from "./Player";
import { Rest } from "./Rest";
import WebSocket from "ws";
export declare enum SponsorBlockSegment {
Sponsor = "sponsor",
SelfPromo = "selfpromo",
Interaction = "interaction",
Intro = "intro",
Outro = "outro",
Preview = "preview",
MusicOfftopic = "music_offtopic",
Filler = "filler"
}
export declare class Node {
options: NodeOptions;
/** The socket for the node. */
socket: WebSocket | null;
/** The stats for the node. */
stats: NodeStats;
/** The manager for the node */
manager: Synthra;
/** The node's session ID. */
sessionId: string | null;
/** The REST instance. */
readonly rest: Rest;
/** Actual Lavalink information of the node. */
info: LavalinkInfo | null;
private static _manager;
private reconnectTimeout?;
private reconnectAttempts;
/**
* Creates an instance of Node.
* @param options
*/
constructor(options: NodeOptions);
/** Returns if connected to the Node. */
get connected(): boolean;
/** Returns the address for this node. */
get address(): string;
/** @hidden */
static init(manager: Synthra): void;
/**
* Creates the sessionIds.json file if it doesn't exist. This file is used to
* store the session IDs for each node. The session IDs are used to identify
* the node when resuming a session.
*/
createSessionIdsFile(): void;
/**
* Loads session IDs from the sessionIds.json file if it exists.
* The session IDs are used to resume sessions for each node.
*
* The session IDs are stored in the sessionIds.json file as a composite key
* of the node identifier and cluster ID. This allows multiple clusters to
* be used with the same node identifier.
*/
loadSessionIds(): void;
/**
* Updates the session ID in the sessionIds.json file.
*
* This method is called after the session ID has been updated, and it
* writes the new session ID to the sessionIds.json file.
*
* @remarks
* The session ID is stored in the sessionIds.json file as a composite key
* of the node identifier and cluster ID. This allows multiple clusters to
* be used with the same node identifier.
*/
updateSessionId(): void;
/**
* Connects to the Node.
*
* @remarks
* If the node is already connected, this method will do nothing.
* If the node has a session ID, it will be sent in the headers of the WebSocket connection.
* If the node has no session ID but the `resumeStatus` option is true, it will use the session ID
* stored in the sessionIds.json file if it exists.
*/
connect(): void;
/**
* Destroys the node and cleans up associated resources.
*
* This method emits a debug event indicating that the node is being destroyed and attempts
* to automatically move all players connected to the node to a usable one. It then closes
* the WebSocket connection, removes all event listeners, and clears the reconnect timeout.
* Finally, it emits a "nodeDestroy" event and removes the node from the manager.
*
* @returns {Promise<void>} A promise that resolves when the node and its resources have been destroyed.
*/
destroy(): Promise<void>;
/**
* Attempts to reconnect to the node if the connection is lost.
*
* This method is called when the WebSocket connection is closed
* unexpectedly. It will attempt to reconnect to the node after a
* specified delay, and will continue to do so until the maximum
* number of retry attempts is reached or the node is manually destroyed.
* If the maximum number of retry attempts is reached, an error event
* will be emitted and the node will be destroyed.
*
* @returns {Promise<void>} - Resolves when the reconnection attempt is scheduled.
* @emits {debug} - Emits a debug event indicating the node is attempting to reconnect.
* @emits {nodeReconnect} - Emits a nodeReconnect event when the node is attempting to reconnect.
* @emits {nodeError} - Emits an error event if the maximum number of retry attempts is reached.
* @emits {nodeDestroy} - Emits a nodeDestroy event if the maximum number of retry attempts is reached.
*/
private reconnect;
/**
* Handles the "open" event emitted by the WebSocket connection.
*
* This method is called when the WebSocket connection is established.
* It clears any existing reconnect timeouts, emits a debug event
* indicating the node is connected, and emits a "nodeConnect" event
* with the node as the argument.
*/
protected open(): void;
/**
* Handles the "close" event emitted by the WebSocket connection.
*
* This method is called when the WebSocket connection is closed.
* It emits a "nodeDisconnect" event with the node and the close event as arguments,
* and a debug event indicating the node is disconnected.
* It then attempts to move all players connected to that node to a useable one.
* If the close event was not initiated by the user, it will also attempt to reconnect.
*
* @param {number} code The close code of the WebSocket connection.
* @param {string} reason The reason for the close event.
* @returns {Promise<void>} A promise that resolves when the disconnection is handled.
*/
protected close(code: number, reason: string): Promise<void>;
/**
* Handles the "error" event emitted by the WebSocket connection.
*
* This method is called when an error occurs on the WebSocket connection.
* It emits a "nodeError" event with the node and the error as arguments and
* a debug event indicating the error on the node.
* @param {Error} error The error that occurred.
*/
protected error(error: Error): void;
/**
* Handles incoming messages from the Lavalink WebSocket connection.
* @param {Buffer | string} d The message received from the WebSocket connection.
* @returns {Promise<void>} A promise that resolves when the message is handled.
* @emits {debug} - Emits a debug event with the message received from the WebSocket connection.
* @emits {nodeError} - Emits a nodeError event if an unexpected op is received.
* @emits {nodeRaw} - Emits a nodeRaw event with the raw message received from the WebSocket connection.
* @private
*/
protected message(d: Buffer | string): Promise<void>;
/**
* Handles an event emitted from the Lavalink node.
* @param {PlayerEvent & PlayerEvents} payload The event emitted from the node.
* @returns {Promise<void>} A promise that resolves when the event has been handled.
* @private
*/
protected handleEvent(payload: PlayerEvent & PlayerEvents): Promise<void>;
/**
* Emitted when a new track starts playing.
* @param {Player} player The player that started playing the track.
* @param {Track} track The track that started playing.
* @param {TrackStartEvent} payload The payload of the event emitted by the node.
* @private
*/
protected trackStart(player: Player, track: Track, payload: TrackStartEvent): void;
/**
* Emitted when a track ends playing.
* @param {Player} player - The player that the track ended on.
* @param {Track} track - The track that ended.
* @param {TrackEndEvent} payload - The payload of the event emitted by the node.
* @private
*/
protected trackEnd(player: Player, track: Track, payload: TrackEndEvent): Promise<void>;
/**
* Handles autoplay logic for a player.
* This method is responsible for selecting an appropriate method of autoplay
* and executing it. If autoplay is not enabled or all attempts have failed,
* it will return false.
* @param {Player} player - The player to handle autoplay for.
* @param {number} attempt - The current attempt number of the autoplay.
* @returns {Promise<boolean>} A promise that resolves to a boolean indicating if autoplay was successful.
* @private
*/
private handleAutoplay;
/**
* Selects a platform from the given enabled sources.
* @param {string[]} enabledSources - The enabled sources to select from.
* @returns {SearchPlatform | null} - The selected platform or null if none was found.
*/
selectPlatform(enabledSources: string[]): SearchPlatform | null;
/**
* Handles Last.fm-based autoplay.
* @param {Player} player - The player instance.
* @param {Track} previousTrack - The previous track.
* @param {SearchPlatform} platform - The selected platform.
* @param {string} apiKey - The Last.fm API key.
* @returns {Promise<boolean>} - Whether the autoplay was successful.
*/
private handlePlatformAutoplay;
/**
* Handles YouTube-based autoplay.
* @param {Player} player - The player instance.
* @param {Track} previousTrack - The previous track.
* @returns {Promise<boolean>} - Whether the autoplay was successful.
*/
private handleYouTubeAutoplay;
/**
* Handles the scenario when a track fails to play or load.
* Shifts the queue to the next track and emits a track end event.
* If there is no next track, handles the queue end scenario.
* If autoplay is enabled, plays the next track.
*
* @param {Player} player - The player instance associated with the track.
* @param {Track} track - The track that failed.
* @param {TrackEndEvent} payload - The event payload containing details about the track end.
* @returns {Promise<void>} A promise that resolves when the track failure has been processed.
* @private
*/
private handleFailedTrack;
/**
* Handles the scenario when a track is repeated.
* Shifts the queue to the next track and emits a track end event.
* If there is no next track, handles the queue end scenario.
* If autoplay is enabled, plays the next track.
*
* @param {Player} player - The player instance associated with the track.
* @param {Track} track - The track that is repeated.
* @param {TrackEndEvent} payload - The event payload containing details about the track end.
* @returns {Promise<void>} A promise that resolves when the repeated track has been processed.
* @private
*/
private handleRepeatedTrack;
/**
* Plays the next track in the queue.
* Updates the queue by shifting the current track to the previous track
* and plays the next track if autoplay is enabled.
*
* @param {Player} player - The player associated with the track.
* @param {Track} track - The track that has ended.
* @param {TrackEndEvent} payload - The event payload containing additional data about the track end event.
* @returns {void}
* @private
*/
private playNextTrack;
/**
* Handles the event when a queue ends.
* If autoplay is enabled, attempts to play the next track in the queue using the autoplay logic.
* If all attempts fail, resets the player state and emits the `queueEnd` event.
* @param {Player} player - The player associated with the track.
* @param {Track} track - The track that has ended.
* @param {TrackEndEvent} payload - The event payload containing additional data about the track end event.
* @returns {Promise<void>} A promise that resolves when the queue end processing is complete.
*/
queueEnd(player: Player, track: Track, payload: TrackEndEvent): Promise<void>;
/**
* Fetches the lyrics of a track from the Lavalink node.
* This method uses the `lavalyrics-plugin` to fetch the lyrics.
* If the plugin is not available, it will throw a RangeError.
*
* @param {Track} track - The track to fetch the lyrics for.
* @param {boolean} [skipTrackSource=false] - Whether to skip using the track's source URL.
* @returns {Promise<Lyrics>} A promise that resolves with the lyrics data.
*/
getLyrics(track: Track, skipTrackSource?: boolean): Promise<Lyrics>;
/**
* Handles the event when a track becomes stuck during playback.
* Stops the current track and emits a `trackStuck` event.
*
* @param {Player} player - The player associated with the track that became stuck.
* @param {Track} track - The track that became stuck.
* @param {TrackStuckEvent} payload - The event payload containing additional data about the track stuck event.
* @returns {void}
* @protected
*/
protected trackStuck(player: Player, track: Track, payload: TrackStuckEvent): Promise<void>;
/**
* Handles the event when a track has an error during playback.
* Stops the current track and emits a `trackError` event.
*
* @param {Player} player - The player associated with the track that had an error.
* @param {Track} track - The track that had an error.
* @param {TrackExceptionEvent} payload - The event payload containing additional data about the track error event.
* @returns {void}
* @protected
*/
protected trackError(player: Player, track: Track, payload: TrackExceptionEvent): Promise<void>;
/**
* Emitted when the WebSocket connection for a player closes.
* The payload of the event will contain the close code and reason if provided.
* @param {Player} player - The player associated with the WebSocket connection.
* @param {WebSocketClosedEvent} payload - The event payload containing additional data about the WebSocket close event.
*/
protected socketClosed(player: Player, payload: WebSocketClosedEvent): void;
/**
* Emitted when the segments for a track are loaded.
* The payload of the event will contain the segments.
* @param {Player} player - The player associated with the segments.
* @param {Track} track - The track associated with the segments.
* @param {SponsorBlockSegmentsLoaded} payload - The event payload containing additional data about the segments loaded event.
*/
private sponsorBlockSegmentLoaded;
/**
* Emitted when a segment of a track is skipped using the sponsorblock plugin.
* The payload of the event will contain the skipped segment.
* @param {Player} player - The player associated with the skipped segment.
* @param {Track} track - The track associated with the skipped segment.
* @param {SponsorBlockSegmentSkipped} payload - The event payload containing additional data about the segment skipped event.
*/
private sponsorBlockSegmentSkipped;
/**
* Emitted when chapters for a track are loaded using the sponsorblock plugin.
* The payload of the event will contain the chapters.
* @param {Player} player - The player associated with the chapters.
* @param {Track} track - The track associated with the chapters.
* @param {SponsorBlockChaptersLoaded} payload - The event payload containing additional data about the chapters loaded event.
*/
private sponsorBlockChaptersLoaded;
/**
* Emitted when a chapter of a track is started using the sponsorblock plugin.
* The payload of the event will contain the started chapter.
* @param {Player} player - The player associated with the started chapter.
* @param {Track} track - The track associated with the started chapter.
* @param {SponsorBlockChapterStarted} payload - The event payload containing additional data about the chapter started event.
*/
private sponsorBlockChapterStarted;
/**
* Fetches Lavalink node information.
* @returns {Promise<LavalinkInfo>} A promise that resolves to the Lavalink node information.
*/
fetchInfo(): Promise<LavalinkInfo>;
/**
* Gets the current sponsorblock segments for a player.
* @param {Player} player - The player to get the sponsorblocks for.
* @returns {Promise<SponsorBlockSegment[]>} A promise that resolves to the sponsorblock segments.
* @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
*/
getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
/**
* Sets the sponsorblock segments for a player.
* @param {Player} player - The player to set the sponsor blocks for.
* @param {SponsorBlockSegment[]} segments - The sponsorblock segments to set. Defaults to `[SponsorBlockSegment.Sponsor, SponsorBlockSegment.SelfPromo]` if not provided.
* @returns {Promise<void>} The promise is resolved when the operation is complete.
* @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
* @throws {RangeError} If no segments are provided.
* @throws {SyntaxError} If an invalid sponsorblock is provided.
* @example
* ```ts
* // use it on the player via player.setSponsorBlock();
* player.setSponsorBlock([SponsorBlockSegment.Sponsor, SponsorBlockSegment.SelfPromo]);
* ```
*/
setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
/**
* Deletes the sponsorblock segments for a player.
* @param {Player} player - The player to delete the sponsorblocks for.
* @returns {Promise<void>} The promise is resolved when the operation is complete.
* @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
*/
deleteSponsorBlock(player: Player): Promise<void>;
/**
* Creates a README.md or README.txt file in the magmastream directory
* if it doesn't already exist. This file is used to store player data
* for autoresume and other features.
* @private
*/
private createReadmeFile;
}
export interface NodeOptions {
/** The host for the node. */
host: string;
/** The port for the node. */
port?: number;
/** The password for the node. */
password?: string;
/** Whether the host uses SSL. */
secure?: boolean;
/** The identifier for the node. */
identifier?: string;
/** The retryAmount for the node. */
retryAmount?: number;
/** The retryDelay for the node. */
retryDelay?: number;
/** Whether to resume the previous session. */
resumeStatus?: boolean;
/** The time the lavalink server will wait before it removes the player. */
resumeTimeout?: number;
/** The timeout used for api calls. */
requestTimeout?: number;
/** Priority of the node. */
priority?: number;
}
export interface NodeStats {
/** 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;
}
export 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;
}
export interface CPUStats {
/** The core amount the host machine has. */
cores: number;
/** The system load. */
systemLoad: number;
/** The lavalink load. */
lavalinkLoad: number;
}
export interface FrameStats {
/** The amount of sent frames. */
sent?: number;
/** The amount of nulled frames. */
nulled?: number;
/** The amount of deficit frames. */
deficit?: number;
}
export interface LavalinkInfo {
version: {
semver: string;
major: number;
minor: number;
patch: number;
preRelease: string;
};
buildTime: number;
git: {
branch: string;
commit: string;
commitTime: number;
};
jvm: string;
lavaplayer: string;
sourceManagers: string[];
filters: string[];
plugins: {
name: string;
version: string;
}[];
}
export interface LyricsLine {
timestamp: number;
duration: number;
line: string;
plugin: object;
}
export interface Lyrics {
source: string;
provider: string;
text?: string;
lines: LyricsLine[];
plugin: object[];
}