refactor: Implement DiscordRateLimiter for API requests to manage rate limits

This commit is contained in:
2025-10-16 13:18:25 +02:00
parent 22ed99da86
commit bbf3725acf
5 changed files with 94 additions and 38 deletions

View 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>;
}
}