From 37cc5f16def3a804ad973162166ec578bc715383 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 3 Sep 2022 18:03:51 +0200 Subject: [PATCH] feat: handle ratelimits (kinda) --- lib/config.ts | 2 ++ lib/handler.ts | 38 +++++++++++++++++++++++++++++++------- lib/util.ts | 4 ++++ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/config.ts b/lib/config.ts index d8e4e48..9249e33 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -13,4 +13,6 @@ export default { hostname: get("HOSTNAME", "127.0.0.1"), port: parseInt(get("PORT", "8080")), signKey: get("SIGN_KEY"), + maxWebhookRetries: parseInt(get("MAX_RETRIES", "3")), + maxWebhookRetryMs: parseInt(get("MAX_RETRY_MS", "30000")), }; diff --git a/lib/handler.ts b/lib/handler.ts index 783308f..9850601 100644 --- a/lib/handler.ts +++ b/lib/handler.ts @@ -1,4 +1,5 @@ import { http, log } from "../deps.ts"; +import config from "./config.ts"; import { verify } from "./crypto.ts"; import filterWebhook from "./filter.ts"; import { UrlConfig } from "./types.d.ts"; @@ -65,11 +66,34 @@ async function sendWebhook( body: string, ): Promise { const url = `https://discord.com/api/webhooks/${id}/${token}/github?wait=1`; - log.info(`Sending webhook request to ${url}`); - const req = new Request(url, { - method: "POST", - headers: headers, - body: body, - }); - return await fetch(req); + + let res: Response; + let retries = 0; + do { + const req = new Request(url, { + method: "POST", + headers: headers, + body: body, + }); + + log.info(`sending webhook request to ${url}`); + res = await fetch(req); + + // return response if everything's fine + if (res.status !== 429) break; + + const reset = res.headers.get("retry-after"); + // should always exist, even for cf bans, but checking anyway + if (reset === null) break; + + const resetms = parseFloat(reset); + // if we'd wait longer than the configured limit, just return the 429 + if (resetms > config.maxWebhookRetryMs) break; + + // wait and try again + log.warning(`retrying after ${resetms}ms`); + await util.sleep(resetms); + retries++; + } while (retries <= config.maxWebhookRetries); + return res; } diff --git a/lib/util.ts b/lib/util.ts index 7fc7393..d33510a 100644 --- a/lib/util.ts +++ b/lib/util.ts @@ -1,3 +1,7 @@ export function parseBool(s: string): boolean { return ["1", "true", "on", "y", "yes"].includes(s.toLowerCase()); } + +export function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +}