import { sleepSeconds } from './sleep.ts'; import { WEBHOOK_ENDPOINT } from 'astro:env/server'; import { logger } from '@util/log.ts'; export enum WebhookAction { Signup = 'signup', Report = 'report', Strike = 'strike' } export type WebhookActionType = { [WebhookAction.Signup]: { firstname: string; lastname: string; birthday: string; telephone: string | null; username: string; edition: 'java' | 'bedrock'; uuid: string | null; }; [WebhookAction.Report]: { reporter: string | null; reported: string | null; reason: string; }; [WebhookAction.Strike]: { uuid: string; }; }[T]; export async function sendWebhook(action: T, data: WebhookActionType) { if (!WEBHOOK_ENDPOINT) return; else if (!/^(https?:\/\/[^\s,]+)(?:,(https?:\/\/[^\s,]+))*$/.test(WEBHOOK_ENDPOINT)) { logger.warn('webhook endpoint is invalid'); return; } const webhookFutures = []; for (const webhook of WEBHOOK_ENDPOINT.split(',')) { webhookFutures.push( (async () => { let retries = 0; while (retries < 3) { try { const response = await fetch(webhook, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-webhook-action': action }, body: JSON.stringify(data) }); if (response.status === 200) break; } catch (e) { logger.warn( { retry: retries + 1, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore error: e.message }, 'error while sending webhook' ); } retries++; await sleepSeconds(60); } })() ); } await Promise.all(webhookFutures); }