Skip to content

Commit 20546bd

Browse files
committed
feat(node): add generic requestREST method
This commit introduces a new public method, `requestREST`, to the `LavalinkNode` class. This utility provides a flexible and centralized way to make arbitrary REST API calls to the connected Lavalink node. It simplifies interactions with custom endpoints or those provided by Lavalink plugins by handling authentication, URL construction, and basic response parsing automatically. Key features include: - Support for modifying request options (method, headers, body). - Automatic handling of authorization headers. - Optional response parsing as text instead of JSON. - Built-in request timeout support.
1 parent 49a7dd3 commit 20546bd

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/structures/Node.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,60 @@ export class LavalinkNode {
157157

158158
return { response, options: options };
159159
}
160+
161+
/**
162+
* Request a REST endpoint on the Lavalink node.
163+
*
164+
* @param fullPath The full path of the endpoint to request (e.g. `/youtube/oauth/`)
165+
* @param modify A function to modify the request options before sending the request
166+
* @param parseAsText If true, the response will be parsed as a string instead of JSON
167+
* @returns A promise that resolves to the response data as a JSON object or string if `parseAsText` is true
168+
* @throws {Error} If the node is not connected to the Lavalink Server
169+
*/
170+
public async requestREST<T = unknown>(fullPath: string, modify?: ModifyRequest): Promise<T>;
171+
public async requestREST(fullPath: string, modify: ModifyRequest | undefined, parseAsText: true): Promise<string>;
172+
public async requestREST<T>(
173+
fullPath: string,
174+
modify?: ModifyRequest,
175+
parseAsText?: boolean
176+
): Promise<T | string> {
177+
if (!this.connected) {
178+
throw new Error("The node is not connected to the Lavalink Server!");
179+
}
180+
181+
const options: RequestInit & { path: string, extraQueryUrlParams?: URLSearchParams } = {
182+
path: fullPath.startsWith("/") ? fullPath : `/${fullPath}`,
183+
method: "GET",
184+
headers: {
185+
"Authorization": this.options.authorization
186+
},
187+
signal: this.options.requestSignalTimeoutMS && this.options.requestSignalTimeoutMS > 0
188+
? AbortSignal.timeout(this.options.requestSignalTimeoutMS)
189+
: undefined,
190+
};
191+
192+
modify?.(options);
193+
194+
const url = new URL(`${this.restAddress}${options.path}`);
195+
196+
if (options.extraQueryUrlParams?.size) {
197+
for (const [k, v] of options.extraQueryUrlParams.entries()) {
198+
url.searchParams.append(k, v);
199+
}
200+
}
201+
202+
const { ...fetchOptions } = options;
203+
const response = await fetch(url.toString(), fetchOptions);
204+
205+
this.calls++;
206+
207+
if (["DELETE", "PUT"].includes(options.method)) return undefined as any;
208+
if (response.status === 204) return undefined as any;
209+
if (response.status === 404) throw new Error(`Request failed: ${options.path}`);
210+
211+
return parseAsText ? await response.text() : await response.json();
212+
}
213+
160214
/**
161215
* Makes an API call to the Node. Should only be used for manual parsing like for not supported plugins
162216
* @param endpoint The endpoint that we will make the call to

0 commit comments

Comments
 (0)