Files
discord-storage/src/lib/discordRateLimiter.ts
b3ni15 968a843120
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 7s
Vercel Production Deployment / Deploy-Production (push) Successful in 1m32s
refactor: Add type annotations for response objects in API request handling
2025-10-16 13:21:01 +02:00

51 lines
1.8 KiB
TypeScript

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: Record<string, string> = {
'Authorization': `Bot ${this.botToken}`,
...(options.headers as Record<string, string>),
};
// Only set Content-Type to application/json if body is a string and not explicitly set
if (typeof options.body === 'string' && !('Content-Type' in headers)) {
headers['Content-Type'] = 'application/json';
}
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>;
}
}