API Reference Comprehensive reference for every public export in YuKumo.
Comprehensive reference for every public export in YuKumo. Supports TypeScript and JavaScript (ESM + CommonJS).
The central orchestrator combining all subsystems.
class YuKumo {
constructor ( options : ManagerOptions );
// Lifecycle
init () : Promise < void >;
destroy () : Promise < void >;
// Search
search ( query : string | SearchOptions , source ?: string ) : Promise < SearchResult >;
lavaSearch ( query : string , types ?: LavaSearchType [], nodeName ?: string ) : Promise < LavaSearchResult >;
getLyrics ( encodedTrack : string , nodeName ?: string ) : Promise < any >;
// Player management
createPlayer ( options : YuKumoPlayerCreateOptions ) : Promise < Player >;
getPlayer ( guildId : string ) : Player | undefined ;
getPlayers () : Player [];
hasPlayer ( guildId : string ) : boolean ;
destroyPlayer ( guildId : string ) : Promise < boolean >;
// Playback
play ( guildId : string , track : TrackData ) : Promise < void >;
pause ( guildId : string ) : Promise < void >;
resume ( guildId : string ) : Promise < void >;
stop ( guildId : string ) : Promise < void >;
skip ( guildId : string ) : Promise < TrackData | null >;
setVolume ( guildId : string , volume : number ) : Promise < void >;
// Voice
handleVoiceStateUpdate ( data : VoiceStateUpdate ) : Promise < void >;
handleVoiceServerUpdate ( guildId : string , data : VoiceServerUpdate ) : Promise < void >;
// Nodes
getNode ( id : string ) : Node | undefined ;
getNodes () : Node [];
// Events
on < E extends EventName >( event : E , callback : EventCallback < E >) : this ;
// Subsystems (public for advanced use)
readonly nodes : NodeManager ;
readonly players : PlayerManager ;
readonly plugins : PluginManager ;
readonly events : EventDispatcher ;
readonly storage : StorageAdapter ;
readonly voice : VoiceStateTracker ;
}
Property Type Default Description nodesNodeConfig[]required Lavalink node configurations storageAdapterStorageAdapterMemoryStorageCustom storage backend pluginsPluginDef[][]Plugin instances to register defaultNodeSelectorNodeSelectorLeastUsedSelectorDefault node selection strategy send(guildId, payload) => void— Raw Discord gateway payload dispatcher for op: 4 voice state updates onDisconnect{ destroyPlayer?: boolean; autoReconnect?: boolean }{ destroyPlayer: true }Behavior when bot is disconnected from voice channel loggerLogger | LogLevelNoopLoggerLogger instance or minimum log level threshold ("debug" | "info" | "warn" | "error" | "silent") searchCacheSearchCache | CacheOptionsSearchCacheCustom SearchCache instance or cache configuration options (maxSize, ttl) linksAllowedbooleantrueWhen false, URL queries are rejected with an error load result linksWhitelist(string | RegExp)[][]When non-empty, URL queries must match at least one entry linksBlacklist(string | RegExp)[][]URL queries matching any entry are rejected (wins over whitelist) httpHeadersRecord<string, string>— Custom headers for every node's REST requests + WS handshake queueOptions{ persist?: boolean }{ persist: false }Auto-persist queues to the storage adapter and restore them on createPlayer() playerDefaults{ maxErrorsPerTime?, minAutoPlayMs?, queueEmptyDestroyMs? }see below Per-player protection defaults applied on create playerClassnew (options) => PlayerPlayerCustom Player subclass instantiated by the manager
playerDefaults defaults: maxErrorsPerTime: { threshold: 35000, maxAmount: 3 } (destroy after >3 track errors within 35s; null disables), minAutoPlayMs: 10000 (block autoplay after error-ends of tracks that played under 10s), queueEmptyDestroyMs: 0 (disabled).
Property Type Default Description hoststringrequired Lavalink hostname portnumberrequired Lavalink port passwordstringrequired Lavalink password namestringauto Node identifier securebooleanfalseUse https/wss resumeTimeoutnumber60Resume timeout (seconds) resumeKeystringauto Resume identifier maxRetriesnumber5Connection retry limit retryDelaynumber1000Initial retry delay (ms) retryDelayMaxnumber30000Maximum retry delay (ms) connectTimeoutnumber15000WS handshake timeout (ms) httpHeadersRecord<string, string>— Custom headers for this node (overrides manager-level httpHeaders) enableHeartbeatbooleantrueWS ping/pong dead-connection detection heartbeatIntervalMsnumber30000Interval between heartbeat pings heartbeatTimeoutMsnumber10000Pong wait before the socket is declared dead and terminated (auto-reconnects)
Property Type Description configNodeConfigConfiguration this node was created with wsWebSocketClientWebSocket client restRestClientREST client stateNodeStatedisconnected | connecting | connected | destroyedpenaltiesPenaltiesCurrent penalty scores playerCountnumberActive players on this node
Method Returns Description add(config)NodeRegister a new node remove(id)booleanRemove and destroy a node get(id)Node | undefinedGet node by name getAll()Node[]Get all registered nodes getConnected()Node[]Get only connected nodes pick(guildId)Node | nullPick best node via selector connectAll()Promise<void>Connect all nodes destroyAll()Promise<void>Destroy all nodes setSelector(selector)voidReplace selection strategy size()numberNumber of registered nodes
Selector Strategy LeastUsedSelector(Default) Fewest playersLeastPenaltySelectorLowest penalty (players + CPU + frames) CpuUsageSelectorLowest Lavalink CPU load MemoryUsageSelectorLowest memory usage LowestPingSelectorLowest WebSocket round-trip ping RegionSelectorRegion-aware with fallback selector RoundRobinSelectorRound-robin order RandomSelectorRandom connected node CustomSelectorCustom function (nodes, guildId) => Node | null
import { RoundRobinSelector, RegionSelector, CustomSelector } from "yukumo" ;
client.nodes. setSelector ( new RoundRobinSelector ());
// Region-aware with fallback
client.nodes. setSelector ( new RegionSelector ( "eu" , new LeastPenaltySelector ()));
// Custom function
client.nodes. setSelector ( new CustomSelector (( nodes , guildId ) => {
return nodes. find ( n => n.state === "connected" ) ?? null ;
}));
Property Type Description guildIdstringDiscord guild ID nodeNodeAssigned Lavalink node queueQueue<TrackData>Track queue filtersFilterChainAudio filter chain eventsEventDispatcherPlayer-local events dataMap<string, any>Custom data map statusPlayerStatusidle | playing | paused | destroyedvolumenumberVolume (0–1000) pausedbooleanWhether paused currentTrackTrackData | nullCurrent track voiceStateInternalVoiceState | nullVoice connection state positionnumberPlayback position (ms) — interpolated between server updates, clamped to track length ping{ ws: number | null; lavalink: number | null }Node WS ping + per-player Lavalink ping maxErrorsPerTime{ threshold, maxAmount } | nullSliding-window error-rate protection minAutoPlayMsnumberMin play time before error-triggered autoplay runs queueEmptyDestroyMsnumberDestroy this many ms after queue end (0 disables)
Method Returns Description play(track?, options?)Promise<void>Begin playback. options: { position?, endTime?, noReplace?, paused?, volume? } playTrack(track, options?)Promise<void>Play specific track (same PlayOptions) skip()Promise<TTrack | null>Skip — runs the same path as a natural track end (autoplay/repeat/queueEnd all fire) playPrevious()Promise<TTrack | null>Play previous track from history pause() / resume()Promise<void>Idempotent pause/resume stop()Promise<void>Stop playback setVolume(vol)Promise<void>Change volume (0-1000); remembered while the node is down seek(position)Promise<void>Seek (ms), clamped to [0, track length] waitForVoiceReady(timeoutMs?)Promise<void>Wait for Discord voice credentials to be ready before playing (default: 15s) resync()Promise<void>Re-send full player state & voice credentials to node after reconnect destroy(reason?)Promise<void>Destroy player; reason (see DestroyReasons) is emitted with playerDestroy setVoiceChannel(id)Promise<void>Move bot to channel setTextChannel(id)voidUpdate text channel search(query, source?)Promise<SearchResult>Shortcut for yukumo.search setLoop(mode)thisShortcut for queue.setRepeatMode getLyrics(track?)Promise<any>Fetch lyrics (requires Lyrics plugin) setSponsorBlock(categories?)Promise<void>Set SponsorBlock auto-skip categories (SponsorBlock plugin) getSponsorBlock() / deleteSponsorBlock()Promise<string[]> / Promise<void>Read / clear SponsorBlock categories getCurrentLyrics(skipTrackSource?)Promise<unknown>Lyrics of the current track (LavaLyrics plugin) subscribeLyrics() / unsubscribeLyrics()Promise<void>Toggle live lyricsLine events (LavaLyrics plugin) moveNode(nodeId?)Promise<Node>Move to a node — auto-picks the least-loaded connected node when omitted enableQueuePersistence()voidAuto-save the queue to the storage adapter on every change restoreQueue()Promise<boolean>Restore a persisted queue toJSON()PlayerJsonFull serializable player snapshot (queue, filters, voice, playback)
Method Returns Description create(options)Promise<Player>Create a player get(guildId)Player | undefinedGet by guild ID has(guildId)booleanCheck if exists destroy(guildId, reason?)Promise<boolean>Destroy a player getAll()Player[]All players getByNode(nodeId)Player[]Players on a node destroyAll(reason?)Promise<void>Destroy all size()numberActive player count
Property Type Default Description guildIdstringrequired Discord guild ID voiceChannelIdstringrequired Voice channel textChannelIdstring— Text channel selfDeafbooleantrueDeafen on join selfMutebooleanfalseMute on join nodeSelectorNodeSelectordefault Per-player selector override
Method Returns Description enqueue(track, index?)numberAdd track (optionally at index) dequeue()T | nullRemove and return front start()voidBegin from front next()T | nullAdvance to next previous()T | nullGo back peek()T | nullView without advancing clear()voidRemove all shuffle()voidFisher-Yates shuffle swap(indexA, indexB)booleanSwap two track positions skipTo(index)T | nullJump to queue index remove(index)T | nullRemove at index removeRange(start, end)T[]Remove range clearExceptCurrent()voidClear queue except current track setRepeatMode(mode)void"none" | "track" | "queue"sortBy(key, order?)thisSort upcoming tracks by "duration" | "title" | "author" or a comparator, "asc" | "desc" removeTrack(query)T[]Remove by track object / array / predicate (matches identity, then encoded); never removes the playing track export() / import(state)SerializedQueue / voidSerialize / restore full queue state toArray()T[]All tracks as array
Property Type Description onChanged() => voidHook invoked after every queue mutation — drives queue persistence, usable as a change watcher
Property Type Description sizenumberCurrent track count totalSizenumberIncluding history currentTrackT | nullCurrent track repeatModeRepeatModeRepeat setting
const queue = new Queue < TrackData >();
queue. enqueue (track1);
queue. enqueue (track2, 0 );
queue. setRepeatMode ( "queue" );
queue. shuffle ();
queue. start ();
let track;
while ((track = queue. next ()) !== null ) {
// process track
}
interface TrackData {
encoded : string ;
info : TrackInfo ;
pluginInfo : Record < string , unknown >;
userData ?: Record < string , unknown >;
}
interface TrackInfo {
identifier : string ;
isSeekable : boolean ;
author : string ;
length : number ;
isStream : boolean ;
position : number ;
title : string ;
uri : string | null ;
artworkUrl : string | null ;
isrc : string | null ;
sourceName : string ;
}
interface SearchResult {
loadType : "track" | "playlist" | "search" | "empty" | "error" ;
tracks : TrackData [];
playlistInfo ?: { name : string ; selectedTrack : number };
exception ?: { message : string ; severity : "common" | "suspicious" | "fault" };
}
Method Description add(filter)Add a filter remove(filter)Remove a filter clear()Remove all toPayload()Serialize to API payload has(filter)Check if exists getAll()Get all filters
Filter Key Methods VolumeFiltersetVolume(value)EqualizerFiltersetBand(index, gain)KaraokeFiltersetLevel(), setMonoloLevel(), setFilterBand(), setFilterWidth()TimescaleFiltersetSpeed(), setPitch(), setRate()TremoloFiltersetFrequency(), setDepth()VibratoFiltersetFrequency(), setDepth()RotationFiltersetRotationHz()DistortionFiltersetSinOffset(), setSinScale(), setCosOffset(), setCosScale(), setTanOffset(), setTanScale(), setOffset(), setScale()ChannelMixFiltersetLeftToLeft(), setLeftToRight(), setRightToLeft(), setRightToRight()LowPassFiltersetSmoothing()
import { FilterChain, EqualizerFilter, TimescaleFilter } from "yukumo" ;
const chain = new FilterChain ();
chain
. add ( new EqualizerFilter (). setBand ( 0 , 0.4 ))
. add ( new TimescaleFilter (). setSpeed ( 1.25 ));
player.filters. add ( new EqualizerFilter (). setBand ( 0 , 0.5 ));
One-line preset methods on FilterChain (also available on player.filters):
Preset Description setBassBoost(level)Bass boost EQ preset ("low", "medium", "high", "extreme") setNightcore(enabled?)Nightcore timescale (speed 1.25, pitch 1.25) setVaporwave(enabled?)Vaporwave timescale (speed 0.85, pitch 0.8) setSlowedReverb(enabled?)Slowed + Reverb preset (speed 0.85, pitch 0.85, lowPass filter) set8D(enabled?) / set3DAudio(enabled?)8D / 3D audio spatial rotation (0.2 Hz panning) setPitchShift(semitones)Shifts audio pitch by semitones (+/- 12 semitones) setVoiceIsolation(enabled?)Vocal frequency boost EQ curve setKaraoke(enabled?)Karaoke vocal removal filter setPop(enabled?)Pop EQ preset setSoft(enabled?)Soft EQ preset setTrebleBass(enabled?)Treble & Bass EQ preset setRock(enabled?)Rock EQ preset setClassical(enabled?)Classical EQ preset setElectronic(enabled?)Electronic EQ preset setAudioOutput(output)Channel-mix routing: "mono", "stereo" (reset), "left", "right" (presets exported as AudioOutputs) registerPreset(name, payload)Registers a custom global named preset applyPreset(name)Applies a registered custom preset
// Apply bass boost
player.filters. setBassBoost ( "high" );
// Enable nightcore
player.filters. setNightcore ();
// Disable a preset
player.filters. setNightcore ( false );
// Route audio to mono / left / right, back to stereo to reset
player.filters. setAudioOutput ( "mono" );
player.filters. setAudioOutput ( "stereo" );
Method Returns Description handleVoiceStateUpdate(data)Promise<void>Process state update handleVoiceServerUpdate(guildId, data)Promise<void>Process server update isReady(guildId)booleanConnection established? getState(guildId)VoiceState | undefinedGet connection state getVoiceState(guildId)InternalVoiceState | undefinedGet internal state getAll()Map<string, VoiceState>All tracked states remove(guildId)voidRemove state
Event Fires When voiceReadyBoth sessionId and endpoint+token received (50ms debounce) voiceDisconnectedchannelId becomes nullvoiceReconnectingSession ID changes while connected
interface VoiceStateUpdate {
guildId : string ;
sessionId : string ;
channelId : string | null ;
userId ?: string ;
}
interface VoiceServerUpdate {
token : string ;
endpoint : string | null ;
}
interface StorageAdapter {
get ( key : string ) : Promise < unknown | null >;
set ( key : string , value : unknown ) : Promise < void >;
delete ( key : string ) : Promise < boolean >;
has ( key : string ) : Promise < boolean >;
clear () : Promise < void >;
}
Adapter Description MemoryStorage(Default) In-memory Map. Zero overheadRedisStorageRedis persistence (requires redis package)
import { RedisStorage } from "yukumo" ;
const yukumo = new YuKumo ({
nodes: [ ... ],
storageAdapter: new RedisStorage ({ url: "redis://localhost:6379" }),
});
YuKumo includes a pluggable logging subsystem with level filtering.
interface Logger {
debug ( message : string , ... args : unknown []) : void ;
info ( message : string , ... args : unknown []) : void ;
warn ( message : string , ... args : unknown []) : void ;
error ( message : string , ... args : unknown []) : void ;
}
type LogLevel = "debug" | "info" | "warn" | "error" | "silent" ;
Symbol Description ConsoleLoggerBuilt-in logger outputting formatted logs to standard console NoopLoggerSilent logger that discards all log messages (default) levelFilteredLogger(inner: Logger, level: LogLevel)Helper function wrapping a logger to drop messages below the specified threshold
import { YuKumo, ConsoleLogger, levelFilteredLogger } from "yukumo" ;
const yukumo = new YuKumo ({
nodes: [ ... ],
logger: levelFilteredLogger ( new ConsoleLogger (), "info" ),
});
A high-performance in-memory LRU cache for search results with TTL support.
interface CacheOptions {
/** Maximum number of entries to keep in cache (default: 100) */
maxSize ?: number ;
/** Time to live in milliseconds (default: 3600000 / 1 hour) */
ttl ?: number ;
}
class SearchCache {
constructor ( options ?: CacheOptions );
get < T extends SearchResult | LavaSearchResult >( key : string ) : T | null ;
set ( key : string , data : SearchResult | LavaSearchResult ) : void ;
clear () : void ;
}
import { SearchCache } from "yukumo" ;
const cache = new SearchCache ({ maxSize: 500 , ttl: 1800000 }); // 30 mins
YuKumo provides first-class gateway adapters that automatically forward voice state and server updates from your Discord library.
Adapter Library DiscordJSAdapterdiscord.js v14 ErisAdapterEris SeyfertAdapterSeyfert OceanicAdapterOceanic.js DiscordenoAdapterDiscordeno RawGatewayAdapterCustom / raw gateway DaveyAdapterDavey voice connections
import { YuKumo, DiscordJSAdapter } from "yukumo" ;
import { Client } from "discord.js" ;
const discordClient = new Client ({ intents: [ ... ] });
const yukumo = new YuKumo ({ nodes: [ ... ] });
// Adapter handles voice state forwarding automatically
const adapter = new DiscordJSAdapter (discordClient, yukumo);
// Connect to voice via the adapter
adapter. sendVoiceStateUpdate (guildId, voiceChannelId);
For custom integrations, use RawGatewayAdapter:
import { RawGatewayAdapter } from "yukumo" ;
const adapter = new RawGatewayAdapter (yukumo);
// Forward raw gateway payloads manually
adapter. handleRawVoiceStateUpdate (rawPayload);
adapter. handleRawVoiceServerUpdate (rawPayload);
interface Plugin {
name : string ;
version : string ;
init ? () : void | Promise < void >;
start ? () : void | Promise < void >;
destroy ? () : void | Promise < void >;
}
Method Returns Description register(plugin)voidRegister plugin unregister(name)booleanRemove plugin get(name)Plugin | undefinedGet by name getAll()Plugin[]All plugins startAll()Promise<void>Start all destroyAll()Promise<void>Destroy all addHook(hook, handler)voidAdd lifecycle hook removeHook(hook, handler)voidRemove lifecycle hook
Hook Signature Cancelable beforeSearch(query, source?) => { query, source? } | nullYes afterSearch(result) => SearchResult | nullYes beforeConnect(guildId, channelId) => { guildId, channelId } | nullYes afterConnect(guildId, channelId) => voidNo beforePlay(guildId, track) => TrackData | nullYes afterPlay(guildId, track) => voidNo beforeDestroy(guildId) => booleanYes (return false) afterDestroy(guildId) => voidNo onNodeSelect(guildId, nodes) => string | nullYes
Error When YuKumoErrorBase error class NodeErrorNode failures NodeConnectionErrorConnection failures PlayerErrorPlayer failures PlayerNotConnectedErrorPlayer not connected RestErrorHTTP errors (includes status code) QueueErrorQueue operation errors QueueFullErrorQueue at capacity PluginErrorPlugin lifecycle errors VoiceErrorVoice state errors LoadErrorTrack loading errors
import { RestError, PlayerNotConnectedError } from "yukumo" ;
try {
await yukumo. play ( "guildId" , track);
} catch (error) {
if (error instanceof RestError ) {
console. error ( `HTTP ${ error . statusCode }: ${ error . message }` );
}
if (error instanceof PlayerNotConnectedError ) {
console. error ( "Player not connected" );
}
}
Event Payload Description trackStart(guildId, track)Track started trackEnd(guildId, track, reason)Track ended trackStuck(guildId, track, thresholdMs)Track stuck trackException(guildId, track, exception)Track error queueEnd(guildId)Queue empty playerCreate(guildId)Player created playerDestroy(guildId)Player destroyed nodeReady(nodeId)Node connected nodeDisconnected(nodeId, code, reason)Node disconnected nodeReconnected(nodeId)Node reconnected nodeError(nodeId, error)Node error stats(nodeId, stats)Node stats (~60s interval) voiceReady(guildId)Voice connected voiceDisconnected(guildId)Voice disconnected voiceReconnecting(guildId)Voice reconnecting segmentsLoaded(guildId, segments)SponsorBlock segments loaded for the current track segmentSkipped(guildId, segment)SponsorBlock segment auto-skipped chaptersLoaded(guildId, chapters)SponsorBlock chapters loaded chapterStarted(guildId, chapter)SponsorBlock chapter started lyricsFound(guildId, lyrics)LavaLyrics: lyrics found lyricsNotFound(guildId)LavaLyrics: no lyrics found lyricsLine(guildId, line)LavaLyrics: live lyrics line
playerDestroy now emits (guildId, reason?) — reasons come from the DestroyReasons export:
import { DestroyReasons } from "yukumo" ;
// QueueEmpty · NodeDestroy · NodeDeleted · LavalinkNoVoice · NodeReconnectFail
// Disconnected · PlayerReconnectFail · ChannelDeleted · DisconnectAllNodes
// TrackErrorMaxTracksErroredPerTime · TrackStuckMaxTracksErroredPerTime
// EmptyVoiceChannel · ManualDestroy
Event Payload trackStart(guildId, track)trackEnd(guildId, track, reason)trackStuck(guildId, track, thresholdMs)trackException(guildId, track, exception)queueEnd(guildId)