fuga
Version:
A comprehensive, feature-rich, and modern Lavalink v4 client for Node.js
120 lines • 4.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RaftLinkManager = void 0;
const events_1 = require("events");
const RaftLinkNode_1 = require("./RaftLinkNode");
const RaftLinkPlayer_1 = require("./RaftLinkPlayer");
/**
* The main hub for RaftLink, manages all nodes and players.
*/
class RaftLinkManager extends events_1.EventEmitter {
nodes = new Map();
players = new Map();
userId = null;
nodesToAdd;
send;
constructor(options) {
super();
this.send = options.send;
if (options.userId)
this.userId = options.userId;
if (options.nodes) {
this.nodesToAdd = options.nodes;
if (this.userId)
this.addNodes(this.nodesToAdd);
}
}
init(userId) {
this.userId = userId;
if (this.nodesToAdd) {
this.addNodes(this.nodesToAdd);
this.nodesToAdd = undefined;
}
}
addNodes(nodes) {
for (const nodeOptions of nodes)
this.addNode(nodeOptions);
}
/**
* Adds a new Lavalink node to the manager.
* @param options The options for the node.
*/
addNode(options) {
const identifier = options.identifier || options.host;
console.log(`[RaftLink] [Manager] Adding node ${identifier}`);
const node = new RaftLinkNode_1.RaftLinkNode(this, { ...options, identifier });
node.on('connect', () => this.emit('nodeConnect', node));
node.on('disconnect', (code, reason) => this.emit('nodeDisconnect', node, code, reason));
node.on('error', (err) => this.emit('nodeError', node, err));
node.on('reconnecting', () => this.emit('nodeReconnecting', node));
node.on('ready', (payload) => this.emit('nodeReady', node, payload));
node.connect();
this.nodes.set(identifier, node);
return node;
}
/**
* Creates a new player or returns an existing one.
* @param options The options for creating a player.
*/
createPlayer(options) {
const existingPlayer = this.players.get(options.guildId);
if (existingPlayer)
return existingPlayer;
const node = this.getIdealNode();
if (!node) {
console.error('[RaftLink] [Manager] No available nodes to create a player.');
throw new Error('No available Lavalink nodes to create a player.');
}
console.log(`[RaftLink] [Manager] Creating player for guild ${options.guildId} on node ${node.options.identifier}`);
const player = new RaftLinkPlayer_1.RaftLinkPlayer(node, options);
this.players.set(options.guildId, player);
return player;
}
/**
* Forwards voice updates from your Discord library to the relevant player.
* @param payload The raw voice state or server update payload.
*/
handleVoiceUpdate(payload) {
console.log(`[RaftLink] [Manager] Received voice update payload:`, JSON.stringify(payload, null, 2));
const player = this.players.get(payload.guild_id);
if (player)
player.handleVoiceUpdate(payload);
}
/**
* Searches for tracks using the best available node.
* @param query The search query or URL.
*/
async search(query, requester, source) {
const node = this.getIdealNode();
if (!node)
throw new Error('No available Lavalink nodes to perform a search.');
const finalQuery = source ? `${source}:${query}` : query;
const result = await node.rest.loadTracks(finalQuery);
if (result.loadType === 'PLAYLIST_LOADED') {
result.data.tracks = result.data.tracks.map((track) => ({ ...track, requester }));
}
else if (result.data) {
result.data = result.data.map((track) => ({ ...track, requester }));
}
return result;
}
/**
* Gets the most ideal node for new players based on player count and CPU load.
* @returns The best available RaftLinkNode.
*/
getIdealNode() {
return [...this.nodes.values()]
.filter((node) => node.connected)
.sort((a, b) => {
const aStats = a.stats;
const bStats = b.stats;
if (!aStats || !aStats.cpu)
return 1;
if (!bStats || !bStats.cpu)
return -1;
return (aStats.cpu.lavalinkLoad / aStats.cpu.cores) * 100 - (bStats.cpu.lavalinkLoad / bStats.cpu.cores) * 100;
})[0];
}
}
exports.RaftLinkManager = RaftLinkManager;
//# sourceMappingURL=RaftLinkManager.js.map