mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-04 01:40:08 +00:00
Merge branch 'master' of https://github.com/Skillz4Killz/Discordeno
This commit is contained in:
3
module/asyncutil.ts
Normal file
3
module/asyncutil.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function sleep (timeout: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
@@ -1,19 +1,27 @@
|
||||
import Client from "../module/client.ts"
|
||||
import { RequestMethod } from "../types/fetch.ts"
|
||||
import { Ratelimiter } from './ratelimiter';
|
||||
|
||||
// type RequestBody = string | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | null | undefined
|
||||
|
||||
export default class DiscordRequestManager {
|
||||
public ratelimiter = new Ratelimiter();
|
||||
|
||||
constructor(public client: Client) {
|
||||
this.client = client
|
||||
}
|
||||
|
||||
async get(url: string, body?: unknown) {
|
||||
const response = await fetch(this.resolveURL(url), {
|
||||
headers: this.getDiscordHeaders(),
|
||||
body: body ? JSON.stringify(body) : undefined
|
||||
})
|
||||
return await response.json()
|
||||
return this.runMethod(RequestMethod.Get, url, body);
|
||||
}
|
||||
|
||||
protected async addBucket (headers: Headers) {
|
||||
this.ratelimiter.addBucket(headers.get('X-RateLimit-Bucket')!, {
|
||||
retryAfter: parseInt(headers.get('X-RateLimit-Retry-After')!),
|
||||
limit: parseInt(headers.get('X-RateLimit-Limit')!),
|
||||
remaining: parseInt(headers.get('X-RateLimit-Remaining')!),
|
||||
reset: parseInt(headers.get('X-RateLimit-Reset')!)
|
||||
});
|
||||
}
|
||||
|
||||
async post(url: string, body?: unknown) {
|
||||
@@ -32,16 +40,17 @@ export default class DiscordRequestManager {
|
||||
return this.runMethod(RequestMethod.Put, url, body)
|
||||
}
|
||||
|
||||
async runMethod(method: RequestMethod, url: string, body?: unknown) {
|
||||
const response = await fetch(this.resolveURL(url), {
|
||||
protected async baseCreateRequestForMethod (method: RequestMethod, url: string, body?: unknown) {
|
||||
return fetch(this.resolveURL(url), {
|
||||
method,
|
||||
headers: this.getDiscordHeaders(),
|
||||
body: body ? JSON.stringify(body) : undefined
|
||||
})
|
||||
}
|
||||
|
||||
const json = await response.json()
|
||||
|
||||
return json
|
||||
async runMethod(method: RequestMethod, url: string, body?: unknown) {
|
||||
const response = await this.baseCreateRequestForMethod(method, url, body);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// A hook for the RouteAwareRequestManager to override URLs.
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
import { sleep } from './asyncutil';
|
||||
|
||||
export interface Ratelimit {
|
||||
retryAfter: number;
|
||||
limit: number;
|
||||
remaining: number;
|
||||
reset: number;
|
||||
}
|
||||
|
||||
export class Ratelimiter {
|
||||
|
||||
}
|
||||
public buckets: Record<string, Ratelimit> = {};
|
||||
|
||||
awaitRatelimit (ratelimit: Ratelimit): Promise<unknown> {
|
||||
if (ratelimit.remaining === 0) {
|
||||
return sleep(ratelimit.retryAfter);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
addBucket (bucket: string, ratelimit: Ratelimit) {
|
||||
if (this.buckets[bucket]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, add this ratelimit to the registry.
|
||||
this.buckets[bucket] = ratelimit;
|
||||
}
|
||||
|
||||
async awaitBucket (bucket: string) {
|
||||
if (this.buckets[bucket]) {
|
||||
// POSSIBLE MEMORY LEAK: Some buckets might never get cleaned up.
|
||||
await this.awaitRatelimit(this.buckets[bucket]);
|
||||
|
||||
// IIRC, we avoid `delete` so v8 doesn't deoptimize this?
|
||||
this.buckets[bucket] = undefined as any;
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,13 @@ import DiscordRequestManager from "./discord-request-manager.ts"
|
||||
import Client from "./client.ts"
|
||||
import { resolveURLs } from "./url.ts"
|
||||
import { baseEndpoints } from "../constants/discord.ts"
|
||||
import { Ratelimit, Ratelimiter } from './ratelimiter';
|
||||
import { RequestMethod } from '../types/fetch';
|
||||
|
||||
export class RouteAwareDiscordRequestManager extends DiscordRequestManager {
|
||||
protected currentRatelimit?: Ratelimit;
|
||||
public ratelimiter = new Ratelimiter();
|
||||
|
||||
constructor(public client: Client, public routeName: string) {
|
||||
super(client)
|
||||
}
|
||||
@@ -11,6 +16,22 @@ export class RouteAwareDiscordRequestManager extends DiscordRequestManager {
|
||||
protected resolveURL(url: string) {
|
||||
return resolveURLs(baseEndpoints.BASE_URL, this.routeName, url)
|
||||
}
|
||||
|
||||
async runMethod (method: RequestMethod, url: string, body?: unknown) {
|
||||
if (this.currentRatelimit) {
|
||||
await this.ratelimiter.awaitRatelimit(this.currentRatelimit);
|
||||
}
|
||||
|
||||
const response = await this.baseCreateRequestForMethod(method, url, body);
|
||||
|
||||
// Capture the ratelimit from this request in our cute little store.
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
protected createRatelimitFromRequest (request: Request) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class RoutedDiscordRequestManager {
|
||||
|
||||
Reference in New Issue
Block a user