Lunacord
The central manager. Owns nodes, players, events, plugins, cache, persistence, and the debug channel.
Construct
Builder-first (recommended):
import { Lunacord } from "@lunacord/core";
const lunacord = Lunacord.create()
.userId("bot-id")
.shards(1)
.node({ id: "main", host: "localhost", port: 2333, password: "..." })
.nodeSelection.leastLoaded()
.resume(true)
.build();userId and numShards are optional at build time — adapters (like MusicKit) call lunacord.bindIdentity({ userId, numShards }) after the Discord client is ready.
Key methods
lunacord.bindIdentity({ userId, numShards });
lunacord.lyrics(provider); // install a LyricsProvider
lunacord.persistence(adapter); // install a PersistenceAdapter
await lunacord.connect();
await lunacord.rehydrate(); // restore players from persistence
const player = lunacord
.createPlayer()
.setGuild(guildId)
.setVoiceChannel(channelId)
.setTextChannel(channelId)
.connect();
const stats = lunacord.getStats(); // aggregated across all nodes
await lunacord.movePlayer(guildId, targetNodeId);
await lunacord.destroyPlayer(guildId);
await lunacord.disconnect();Events (typed)
Every event is typed on the emitter. Listen with lunacord.on("eventName", handler). Key ones:
- Node lifecycle:
nodeCreate,nodeConnect,nodeDisconnect,nodeReconnecting,nodeReconnectFailed,nodeRemove,nodeStats,nodeError,nodeVoiceSocketClosed. - Player lifecycle:
playerCreate,playerDestroy,playerConnect,playerDisconnect,playerMigrate,playerMigrationFailed. - Queue & playback:
playerQueueAdd,playerQueueAddMany,playerQueueEmpty,playerQueueShuffle,playerPlay,playerPause,playerResume,playerStop,playerSkip,playerSeek,playerVolumeUpdate. - Track events:
trackStart,trackEnd,trackException,trackStuck. - Filters:
playerFiltersUpdate,playerFiltersClear. - Unified:
debug— a single firehose of{ scope, message, data?, nodeId? }for nodes, WS, REST, plugins, players. - Plugins:
pluginError.
Unified debug event
lunacord.on("debug", ({ scope, message, data, nodeId }) => {
console.log(`[${scope}${nodeId ? `:${nodeId}` : ""}] ${message}`, data ?? "");
});Every internal log (WS reconnects, REST requests, voice packet sync, plugin hooks, manager internals) is emitted here. You no longer need handlers for every event kind just to observe what's happening.
Node selection
Strategies:
leastLoaded— minimumplayerCount(default).roundRobinweighted— score fromplayerCount,cpu.lavalinkLoad, memory ratio.region— pick nodes whoseregionsincludeoptions.region, then fall back.failover— pick first id inorder.
Switch via the builder:
Lunacord.create()
.nodeSelection.weighted({ cpuWeight: 100, memoryWeight: 25, playerWeight: 1 })
.build();