mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat: migrate to Nuxt 4 (Nitro) and Tailwind CSS v3
This commit is contained in:
parent
f4959eebf8
commit
b139712a91
166 changed files with 19790 additions and 5539 deletions
103
server/lib/drivers/discord/rest.ts
Normal file
103
server/lib/drivers/discord/rest.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import { log } from "../../lib/log";
|
||||
import type { SendResult } from "../types";
|
||||
|
||||
const DISCORD_API = "https://discord.com/api/v10";
|
||||
|
||||
interface DiscordMessage {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
async function request(
|
||||
url: string,
|
||||
method: string,
|
||||
token: string,
|
||||
message: unknown,
|
||||
channelId: string,
|
||||
): Promise<SendResult> {
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
Authorization: `Bot ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(message),
|
||||
});
|
||||
|
||||
if (res.status === 429) {
|
||||
const rateLimit = (await res.json()) as { retry_after?: number };
|
||||
const retryAfter = (rateLimit.retry_after ?? 1) * 1000;
|
||||
log.warn({ retryAfter, attempt }, "Rate limited");
|
||||
await new Promise((r) => setTimeout(r, retryAfter));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
if (res.status >= 500) {
|
||||
log.error({ status: res.status, err, attempt, channelId }, "Discord API 5xx");
|
||||
if (attempt === 2)
|
||||
return {
|
||||
ok: false,
|
||||
error: err,
|
||||
errorCode: "DISCORD_5XX",
|
||||
status: res.status,
|
||||
attempts: attempt + 1,
|
||||
};
|
||||
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
|
||||
continue;
|
||||
}
|
||||
log.error({ status: res.status, err, channelId }, "Discord API error");
|
||||
return {
|
||||
ok: false,
|
||||
error: err,
|
||||
errorCode: "DISCORD_ERROR",
|
||||
status: res.status,
|
||||
attempts: attempt + 1,
|
||||
};
|
||||
}
|
||||
|
||||
let messageId: string | undefined;
|
||||
try {
|
||||
const data = (await res.json()) as DiscordMessage;
|
||||
messageId = data.id;
|
||||
} catch {
|
||||
// ignore malformed success body
|
||||
}
|
||||
|
||||
return { ok: true, status: res.status, messageId, attempts: attempt + 1 };
|
||||
} catch (err) {
|
||||
log.error({ err, attempt, channelId }, "Failed to send message");
|
||||
if (attempt === 2)
|
||||
return { ok: false, error: String(err), errorCode: "NETWORK", attempts: attempt + 1 };
|
||||
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
return { ok: false, error: "Max retries exceeded", errorCode: "RETRIES", attempts: 3 };
|
||||
}
|
||||
|
||||
export async function sendMessage(
|
||||
token: string,
|
||||
channelId: string,
|
||||
message: unknown,
|
||||
threadId?: string,
|
||||
): Promise<SendResult> {
|
||||
const url = threadId
|
||||
? `${DISCORD_API}/channels/${threadId}/messages`
|
||||
: `${DISCORD_API}/channels/${channelId}/messages`;
|
||||
return request(url, "POST", token, message, channelId);
|
||||
}
|
||||
|
||||
export async function editMessage(
|
||||
token: string,
|
||||
channelId: string,
|
||||
messageId: string,
|
||||
message: unknown,
|
||||
threadId?: string,
|
||||
): Promise<SendResult> {
|
||||
const base = threadId ?? channelId;
|
||||
const url = `${DISCORD_API}/channels/${base}/messages/${messageId}`;
|
||||
return request(url, "PATCH", token, message, channelId);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue