refactor: Implement DiscordRateLimiter for API requests to manage rate limits
This commit is contained in:
46
src/lib/discordRateLimiter.ts
Normal file
46
src/lib/discordRateLimiter.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
export class DiscordRateLimiter {
|
||||
private readonly baseUrl: string;
|
||||
private readonly botToken: string;
|
||||
|
||||
constructor(baseUrl: string, botToken: string) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.botToken = botToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a request to the Discord API, handling rate limits automatically.
|
||||
* @param path The API endpoint path (e.g., '/channels/123/messages').
|
||||
* @param options Fetch options (method, headers, body, etc.).
|
||||
* @returns The JSON response from the Discord API.
|
||||
*/
|
||||
public async request<T>(path: string, options: RequestInit = {}): Promise<T> {
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
|
||||
const headers = {
|
||||
'Authorization': `Bot ${this.botToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
const response = await fetch(url, { ...options, headers });
|
||||
|
||||
if (response.status === 429) {
|
||||
const retryAfter = response.headers.get('Retry-After');
|
||||
const delay = retryAfter ? parseInt(retryAfter, 10) * 1000 : 1000; // Default to 1 second if header is missing
|
||||
|
||||
console.warn(`Discord API rate limit hit. Retrying after ${delay / 1000} seconds.`);
|
||||
await sleep(delay);
|
||||
return this.request<T>(path, options); // Retry the request
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ message: response.statusText }));
|
||||
throw new Error(`Discord API error: ${response.status} - ${errorData.message || JSON.stringify(errorData)}`);
|
||||
}
|
||||
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user