77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
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<T extends WebhookAction> = {
|
|
[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<T extends WebhookAction>(action: T, data: WebhookActionType<T>) {
|
|
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);
|
|
}
|