{"version":3,"sources":["../../../src/lib/Manager.ts"],"names":["EventEmitter","Player","LavalinkNode"],"mappings":"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","file":"Manager.cjs","sourcesContent":["import { EventEmitter } from \"events\";\nimport { LavalinkNode } from \"./LavalinkNode\";\nimport { Player } from \"./Player\";\nimport type { JoinData, ManagerOptions, JoinOptions, LavalinkNodeOptions, ManagerEvents } from \"./Types\";\nimport { GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdate, GatewayVoiceStateUpdateDispatchData } from \"discord-api-types/v10\";\n\n/**\n * Main class that handles Lavalink node connections and player management.\n *\n * @remarks\n * The Manager acts as the central hub for Lavacord, managing connections to Lavalink nodes,\n * handling voice state updates, and providing a unified interface for player operations.\n */\nexport class Manager extends EventEmitter<ManagerEvents> {\n\t/**\n\t * A Map of Lavalink Nodes indexed by their IDs.\n\t */\n\tpublic nodes = new Map<string, LavalinkNode>();\n\n\t/**\n\t * A Map of all active players indexed by guild ID.\n\t */\n\tpublic players = new Map<string, Player>();\n\n\t/**\n\t * A Map of voice server update states indexed by guild ID.\n\t */\n\tpublic voiceServers = new Map<string, GatewayVoiceServerUpdateDispatchData>();\n\n\t/**\n\t * A Map of voice state update states indexed by guild ID.\n\t */\n\tpublic voiceStates = new Map<string, GatewayVoiceStateUpdateDispatchData>();\n\n\t/**\n\t * The user ID of the bot this Manager is managing.\n\t */\n\tpublic userId: string | null = null;\n\n\t/**\n\t * Function to send voice state update packets to Discord.\n\t *\n\t * @remarks\n\t * This can be implemented by the user in two ways:\n\t * 1. Via constructor options: `new Manager(nodes, { send: fn })`\n\t * 2. Via class extension: `class MyManager extends Manager { send(packet) { ... } }`\n\t */\n\tprivate _send?: (packet: GatewayVoiceStateUpdate) => unknown;\n\n\t/**\n\t * The Player class constructor used when creating new players.\n\t *\n\t * @remarks\n\t * Can be overridden in the manager options to use a custom Player implementation.\n\t */\n\tprivate readonly Player: typeof Player = Player;\n\n\t/**\n\t * A Set of guild IDs that are waiting for a connection.\n\t *\n\t * @internal\n\t */\n\tprivate readonly expecting = new Set<string>();\n\n\t/**\n\t * Creates a new Manager instance.\n\t *\n\t * @param nodes - An array of Lavalink node options to connect to.\n\t * @param options - Configuration options for the Manager.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Method 1: Define send function via options\n\t * const manager = new Manager([\n\t *   {\n\t *     id: \"main\",\n\t *     host: \"localhost\",\n\t *     port: 2333,\n\t *     password: \"youshallnotpass\"\n\t *   }\n\t * ], {\n\t *   userId: \"bot_user_id\",\n\t *   send: (packet) => {\n\t *     const guild = client.guilds.cache.get(packet.d.guild_id);\n\t *     if (guild) guild.shard.send(packet);\n\t *   }\n\t * });\n\t *\n\t * // Method 2: Extend Manager class\n\t * class MyManager extends Manager {\n\t *   send(packet) {\n\t *     const guild = this.client.guilds.cache.get(packet.d.guild_id);\n\t *     if (guild) guild.shard.send(packet);\n\t *   }\n\t * }\n\t * const manager = new MyManager(nodes, { userId: \"bot_user_id\" });\n\t * ```\n\t */\n\tpublic constructor(nodes: LavalinkNodeOptions[], options?: ManagerOptions) {\n\t\tsuper();\n\t\toptions ??= {};\n\n\t\tif (options.userId) this.userId = options.userId;\n\t\tif (options.player) this.Player = options.player;\n\t\tif (options.send && !this._send) this._send = options.send;\n\n\t\tfor (const node of nodes) this.createNode(node);\n\t}\n\n\t/**\n\t * Connects all Lavalink nodes to their respective Lavalink servers.\n\t *\n\t * @returns A promise that resolves when all connections are established.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Connect all nodes\n\t * manager.connect()\n\t *   .then(() => console.log('All nodes connected!'))\n\t *   .catch(error => console.error('Failed to connect nodes:', error));\n\t * ```\n\t */\n\tpublic async connect(): Promise<LavalinkNode[]> {\n\t\tif (!this.userId)\n\t\t\tthrow new Error(\n\t\t\t\t\"Lavacord requires a client user ID before connecting. \\n\" +\n\t\t\t\t\t\"Set the user ID when constructing the Manager or after your Discord client is ready.\"\n\t\t\t);\n\t\treturn Promise.all(this.nodes.values().map((node) => node.connect().then(() => node)));\n\t}\n\n\t/**\n\t * Disconnects all players and nodes, effectively cleaning up all resources.\n\t *\n\t * @returns A promise that resolves when all disconnections are complete.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Disconnect everything\n\t * manager.disconnect()\n\t *   .then(() => console.log('All players and nodes cleaned up'))\n\t *   .catch(error => console.error('Error during disconnection:', error));\n\t * ```\n\t */\n\tpublic async disconnect(): Promise<void> {\n\t\tfor await (const player of this.players.keys()) await this.leave(player);\n\t\tfor (const node of this.nodes.values()) node.destroy();\n\t}\n\n\t/**\n\t * Creates a new Lavalink node and adds it to the nodes map.\n\t *\n\t * @param options - Configuration options for the node.\n\t * @returns The newly created LavalinkNode instance.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Add a new node\n\t * const newNode = manager.createNode({\n\t *   id: \"node2\",\n\t *   host: \"example.com\",\n\t *   port: 2333,\n\t *   password: \"securepassword\",\n\t *   resuming: true\n\t * });\n\t * ```\n\t */\n\tpublic createNode(options: LavalinkNodeOptions): LavalinkNode {\n\t\tconst node = new LavalinkNode(this, options);\n\t\tthis.nodes.set(options.id, node);\n\t\treturn node;\n\t}\n\n\t/**\n\t * Disconnects and removes a node from the manager.\n\t *\n\t * @param id - The ID of the node to remove.\n\t * @returns Whether the node was successfully removed.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Remove a node\n\t * const removed = manager.removeNode(\"node1\");\n\t * if (removed) {\n\t *   console.log(\"Node successfully removed\");\n\t * } else {\n\t *   console.log(\"Node not found\");\n\t * }\n\t * ```\n\t */\n\tpublic removeNode(id: string): boolean {\n\t\tconst node = this.nodes.get(id);\n\t\tif (!node) return false;\n\t\tnode.destroy();\n\t\treturn this.nodes.delete(id);\n\t}\n\n\t/**\n\t * Joins a voice channel and creates a player for the guild.\n\t *\n\t * @param data - The data needed to join a voice channel.\n\t * @param joinOptions - Options for joining the channel (selfmute, selfdeaf).\n\t * @returns A promise resolving to the Player instance.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Join a voice channel\n\t * const player = await manager.join({\n\t *   guild: \"123456789012345678\", // Guild ID\n\t *   channel: \"123456789012345679\", // Voice Channel ID\n\t *   node: \"main\" // Node ID\n\t * }, {\n\t *   selfdeaf: true // Join deafened\n\t * });\n\t *\n\t * // Now you can use the player to play music\n\t * const result = await Rest.load(player.node, \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\");\n\t * await player.play(result.tracks[0].track);\n\t * ```\n\t */\n\tpublic async join(data: JoinData, joinOptions: JoinOptions = {}): Promise<Player> {\n\t\tconst player = this.players.get(data.guild);\n\t\tif (player) return player;\n\t\tawait this.sendWS(data.guild, data.channel, joinOptions);\n\t\treturn this.spawnPlayer(data);\n\t}\n\n\t/**\n\t * Leaves a voice channel and cleans up the player.\n\t *\n\t * @param guild - The ID of the guild to leave.\n\t * @returns A promise resolving to whether the operation was successful.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Leave a voice channel\n\t * const success = await manager.leave(\"123456789012345678\");\n\t * if (success) {\n\t *   console.log(\"Successfully left the voice channel\");\n\t * } else {\n\t *   console.log(\"Not in a voice channel in this guild\");\n\t * }\n\t * ```\n\t */\n\tpublic async leave(guild: string): Promise<boolean> {\n\t\tawait this.sendWS(guild, null);\n\t\tconst player = this.players.get(guild);\n\t\tif (!player) return false;\n\n\t\tawait player.destroy();\n\t\treturn this.players.delete(guild);\n\t}\n\n\t/**\n\t * Switches a player from one node to another, implementing fallback capability.\n\t *\n\t * @param player - The player to move to another node.\n\t * @param node - The destination node.\n\t * @returns A promise resolving to the updated player.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Switch a player to another node (e.g. if current node is failing)\n\t * const player = manager.players.get(\"123456789012345678\");\n\t * const newNode = manager.nodes.get(\"backup-node\");\n\t *\n\t * if (player && newNode) {\n\t *   await manager.switch(player, newNode);\n\t *   console.log(\"Player switched to backup node\");\n\t * }\n\t * ```\n\t */\n\tpublic async switch(player: Player, node: LavalinkNode): Promise<Player> {\n\t\tplayer.node = node;\n\n\t\tif (!player.voice?.channelId) return player;\n\t\tawait player.destroy();\n\t\tif (!player.track) return player;\n\n\t\tawait player.play(player.track.encoded, {\n\t\t\tposition: player.state.position,\n\t\t\tvolume: player.volume,\n\t\t\tfilters: player.filters,\n\t\t\t// @ts-expect-error The type narrow for if no channelId didn't work\n\t\t\tvoice: player.voice,\n\t\t\tpaused: player.paused,\n\t\t\tuserData: player.track.userData\n\t\t});\n\n\t\treturn player;\n\t}\n\n\t/**\n\t * Processes voice server update events from Discord.\n\t *\n\t * @param data - The voice server update data from Discord.\n\t * @returns A promise resolving to whether a connection was established.\n\t *\n\t * @example\n\t * ```typescript\n\t * // In your Discord.js client events\n\t * client.ws.on(GatewayDispatchEvents.VoiceServerUpdate, (data) => {\n\t *   manager.voiceServerUpdate(data);\n\t * });\n\t * ```\n\t */\n\tpublic voiceServerUpdate(data: GatewayVoiceServerUpdateDispatchData): Promise<boolean> {\n\t\tthis.voiceServers.set(data.guild_id, data);\n\t\tthis.expecting.add(data.guild_id);\n\t\treturn this._attemptConnection(data.guild_id);\n\t}\n\n\t/**\n\t * Processes voice state update events from Discord.\n\t *\n\t * @param data - The voice state update data from Discord.\n\t * @returns A promise resolving to whether a connection was established.\n\t *\n\t * @example\n\t * ```typescript\n\t * // In your Discord.js client events\n\t * client.ws.on(GatewayDispatchEvents.VoiceStateUpdate, (data) => {\n\t *   manager.voiceStateUpdate(data);\n\t * });\n\t * ```\n\t */\n\tpublic async voiceStateUpdate(data: GatewayVoiceStateUpdateDispatchData): Promise<boolean> {\n\t\tif (data.user_id !== this.userId) return false;\n\t\tif (!data.guild_id) return false;\n\n\t\tif (data.channel_id) {\n\t\t\tthis.voiceStates.set(data.guild_id, data);\n\t\t\treturn this._attemptConnection(data.guild_id);\n\t\t}\n\n\t\tthis.voiceServers.delete(data.guild_id);\n\t\tthis.voiceStates.delete(data.guild_id);\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sends a voice state update packet to Discord.\n\t *\n\t * @param guild - The ID of the guild.\n\t * @param channel - The ID of the voice channel to join, or null to leave.\n\t * @param options - Options for joining (selfmute, selfdeaf).\n\t * @returns The result from the send function.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Join a voice channel\n\t * manager.sendWS(\"123456789012345678\", \"123456789012345679\", { selfdeaf: true });\n\t *\n\t * // Leave a voice channel\n\t * manager.sendWS(\"123456789012345678\", null);\n\t * ```\n\t */\n\tpublic sendWS(guild: string, channel: string | null, { selfmute = false, selfdeaf = false }: JoinOptions = {}): unknown {\n\t\treturn this.send({\n\t\t\top: 4,\n\t\t\td: {\n\t\t\t\tguild_id: guild,\n\t\t\t\tchannel_id: channel,\n\t\t\t\tself_mute: selfmute,\n\t\t\t\tself_deaf: selfdeaf\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Gets all connected nodes, sorted by CPU load.\n\t *\n\t * @returns An array of connected nodes sorted by CPU load (least to most).\n\t *\n\t * @example\n\t * ```typescript\n\t * // Get the node with the least CPU load\n\t * const bestNode = manager.idealNodes[0];\n\t * if (bestNode) {\n\t *   console.log(`Best node for new connections: ${bestNode.id}`);\n\t * }\n\t * ```\n\t */\n\tpublic get idealNodes(): LavalinkNode[] {\n\t\treturn Array.from(this.nodes.values())\n\t\t\t.filter((node) => node.connected)\n\t\t\t.sort((a, b) => {\n\t\t\t\tconst aload = a.stats.cpu ? (a.stats.cpu.systemLoad / a.stats.cpu.cores) * 100 : 0;\n\t\t\t\tconst bload = b.stats.cpu ? (b.stats.cpu.systemLoad / b.stats.cpu.cores) * 100 : 0;\n\t\t\t\treturn aload - bload;\n\t\t\t});\n\t}\n\n\t/**\n\t * Attempts to establish a connection for a guild using available voice data.\n\t *\n\t * @internal\n\t * @param guildID - The ID of the guild to attempt connecting.\n\t * @returns A promise resolving to whether a connection was established.\n\t */\n\tprivate async _attemptConnection(guildID: string): Promise<boolean> {\n\t\tconst server = this.voiceServers.get(guildID);\n\t\tconst state = this.voiceStates.get(guildID);\n\n\t\tif (!server || !state || !this.expecting.has(guildID)) return false;\n\n\t\tconst player = this.players.get(guildID);\n\t\tif (!player) return false;\n\n\t\tawait player.connect({ sessionId: state.session_id, event: server, channelId: state.channel_id! });\n\t\tthis.expecting.delete(guildID);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Creates a new player instance.\n\t *\n\t * @internal\n\t * @param data - The data needed to create a player.\n\t * @returns The created Player instance.\n\t */\n\tprivate spawnPlayer(data: JoinData): Player {\n\t\tconst exists = this.players.get(data.guild);\n\t\tif (exists) return exists;\n\t\tconst node = this.nodes.get(data.node);\n\t\tif (!node) throw new Error(`INVALID_HOST: No available node with ${data.node}`);\n\t\tconst player = new this.Player(node, data.guild);\n\t\tthis.players.set(data.guild, player);\n\t\treturn player;\n\t}\n\n\tprotected send(packet: GatewayVoiceStateUpdate): unknown {\n\t\tif (typeof this._send !== \"function\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"Lavacord requires a send function to be defined in the Manager options.\\\n\t\t\t\tThis function should send voice state updates to Discord.\"\n\t\t\t);\n\t\t}\n\t\treturn this._send(packet);\n\t}\n}\n"]}