UNPKG

magmastream

Version:

A user-friendly Lavalink client designed for NodeJS.

204 lines (203 loc) 9.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rest = void 0; const undici_1 = require("undici"); const Enums_1 = require("./Enums"); const Utils_1 = require("./Utils"); const MagmastreamError_1 = require("./MagmastreamError"); /** Handles the requests sent to the Lavalink REST API. */ class Rest { /** The Node that this Rest instance is connected to. */ node; /** The password for the Node. */ password; /** The URL of the Node. */ url; /** The Manager instance. */ manager; /** Whether the node is a NodeLink. */ isNodeLink = false; constructor(node, manager) { this.node = node; this.url = `http${node.options.useSSL ? "s" : ""}://${node.options.host}:${node.options.port}`; this.password = node.options.password; this.manager = manager; this.isNodeLink = node.isNodeLink; } /** * Gets the session ID. * @returns {string} Returns the session ID. */ get sessionId() { return this.node.sessionId; } /** * Sets the session ID. * This method is used to set the session ID after a resume operation is done. * @param {string} sessionId The session ID to set. * @returns {string} Returns the set session ID. */ setSessionId(sessionId) { this.node.sessionId = sessionId; return this.node.sessionId; } /** * Retrieves the player that is currently running on the node. * @param {string} guildId The guild ID of the player to retrieve. * @returns {Promise<LavaPlayer>} Returns the player. */ async getPlayer(guildId) { if (!this.sessionId) { this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Skipping getPlayer for ${guildId} - no session ID on node ${this.node.options.identifier}`); return null; } const result = await this.get(`/v4/sessions/${this.sessionId}/players/${guildId}`); this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Getting player on node: ${this.node.options.identifier} : ${Utils_1.JSONUtils.safe(result, 2)}`); return result; } /** * Sends a PATCH request to update player related data. * @param {RestPlayOptions} options The options to update the player with. * @returns {Promise<LavaPlayer>} Returns the updated player. */ async updatePlayer(options) { if (!this.sessionId) { this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Skipping updatePlayer for guildId: ${options.guildId} - no session ID on node ${this.node.options.identifier}`); return null; } this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Updating player: ${options.guildId}: ${Utils_1.JSONUtils.safe(options, 2)}`); return await this.patch(`/v4/sessions/${this.sessionId}/players/${options.guildId}?noReplace=${options.noReplace ?? false}`, options.data); } /** * Sends a DELETE request to the server to destroy the player. * @param {string} guildId The guild ID of the player to destroy. * @returns {Promise<void>} Returns void (204 No Content). */ async destroyPlayer(guildId) { if (!this.sessionId) { this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Skipping destroyPlayer for guildId: ${guildId} - no session ID on node ${this.node.options.identifier}`); return; } this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Destroying player: ${guildId}`); return await this.delete(`/v4/sessions/${this.sessionId}/players/${guildId}`); } /** * Updates the session status for resuming. * @param {boolean} resuming - Indicates whether the session should be set to resuming. * @param {number} timeout - The timeout duration for the session resume. * @returns {Promise<LavalinkSession>} The updated session. */ async updateSession(resuming, timeout) { if (!this.sessionId) { this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Skipping updateSession for resuming: ${resuming} timeout: ${timeout} - no session ID on node ${this.node.options.identifier}`); return null; } this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Updating session: ${this.sessionId}`); return await this.patch(`/v4/sessions/${this.sessionId}`, { resuming, timeout }); } /** * Sends a request to the specified endpoint and returns the response data. * @param {string} method The HTTP method to use for the request. * @param {string} endpoint The endpoint to send the request to. * @param {unknown} [body] The data to send in the request body. * @returns {Promise<unknown>} The response data of the request. */ async request(method, endpoint, body) { this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] ${method} request to ${endpoint} with body: ${Utils_1.JSONUtils.safe(body, 2)}`); let response = null; try { response = await (0, undici_1.fetch)(this.url + endpoint, { method, headers: { "Content-Type": "application/json", Authorization: this.password, }, body: body !== undefined ? JSON.stringify(body) : undefined, signal: AbortSignal.timeout(this.node.options.apiRequestTimeoutMs), }); } catch (e) { const isTimeout = e instanceof Error && (e.name === "AbortError" || e.name === "TimeoutError"); const message = e instanceof Error ? e.message : "Unknown error"; const error = new MagmastreamError_1.MagmaStreamError({ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED, message: `${isTimeout ? "Timeout" : "Network error"} on ${method} ${endpoint}: ${message}`, }); this.manager.emit(Enums_1.ManagerEventTypes.NodeError, this.node, error); return null; } const { status } = response; const data = status !== 204 ? await response.json() : null; if (status >= 200 && status < 300) { return data; } if (status === 404) { if (data?.message === "Guild not found") { return []; } if (data?.message === "Session not found") { this.manager.emit(Enums_1.ManagerEventTypes.NodeError, this.node, new MagmastreamError_1.MagmaStreamError({ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED, message: "Session not found" })); return []; } } const message = typeof data === "string" ? data : typeof data === "object" && data !== null && "message" in data && typeof data.message === "string" ? data.message : Utils_1.JSONUtils.safe(data, 2); if (status === 401) { throw new MagmastreamError_1.MagmaStreamError({ code: Enums_1.MagmaStreamErrorCode.REST_UNAUTHORIZED, message: `Unauthorized access to node ${this.node.options.identifier}`, }); } throw new MagmastreamError_1.MagmaStreamError({ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED, message: `Request to node ${this.node.options.identifier} failed (${status}): ${message}`, }); } /** * Sends a GET request to the specified endpoint and returns the response data. * @param {string} endpoint The endpoint to send the GET request to. * @returns {Promise<T>} The response data of the GET request. */ async get(endpoint) { return (await this.request("GET", endpoint)); } /** * Sends a PATCH request to the specified endpoint and returns the response data. * @param {string} endpoint The endpoint to send the PATCH request to. * @param {unknown} body The data to send in the request body. * @returns {Promise<T>} The response data of the PATCH request. */ async patch(endpoint, body) { return (await this.request("PATCH", endpoint, body)); } /** * Sends a POST request to the specified endpoint and returns the response data. * @param {string} endpoint The endpoint to send the POST request to. * @param {unknown} body The data to send in the request body. * @returns {Promise<T>} The response data of the POST request. */ async post(endpoint, body) { return (await this.request("POST", endpoint, body)); } /** * Sends a PUT request to the specified endpoint and returns the response data. * @param {string} endpoint The endpoint to send the PUT request to. * @param {unknown} body The data to send in the request body. * @returns {Promise<T>} The response data of the PUT request. */ async put(endpoint, body) { return (await this.request("PUT", endpoint, body)); } /** * Sends a DELETE request to the specified endpoint. * @param {string} endpoint - The endpoint to send the DELETE request to. * @returns {Promise<void>} Void. */ async delete(endpoint) { await this.request("DELETE", endpoint); } } exports.Rest = Rest;