add support for multiple webhook endpoints
All checks were successful
deploy / build-and-deploy (push) Successful in 17s
All checks were successful
deploy / build-and-deploy (push) Successful in 17s
This commit is contained in:
@@ -152,6 +152,7 @@
|
||||
## Webhook
|
||||
|
||||
> Die env variable `WEBHOOK_ENDPOINT` muss gesetzt und eine valide HTTP URL sein.
|
||||
> Es können auch mehrere Endpoints gesetzt sein, dafür müssen die URLs mit einem komma getrennt sein.
|
||||
|
||||
Bei bestimmten Aktionen wird an den Webhook Endpoint ein Webhook gesendet.
|
||||
Die Art des Webhooks wird dabei durch den `x-webhook-action` HTTP Header angegeben und hat einen festgelegten JSON Body.
|
||||
|
||||
@@ -91,8 +91,8 @@ const information = [
|
||||
<div>
|
||||
<h2 class="text-3xl text-black dark:text-white mb-8">Über uns</h2>
|
||||
<p>
|
||||
Wir sind ein kleines <a class="link" href="admins">Team</a> von Minecraft-Enthusiasten, das bereits im 8. Jahr in
|
||||
Folge Minecraft CraftAttack organisiert. Jahr für Jahr arbeiten wir daran, das Spielerlebnis zu verbessern und
|
||||
Wir sind ein kleines <a class="link" href="admins">Team</a> von Minecraft-Enthusiasten, das bereits im 8. Jahr
|
||||
in Folge Minecraft CraftAttack organisiert. Jahr für Jahr arbeiten wir daran, das Spielerlebnis zu verbessern und
|
||||
steigeren die Teilnehmerzahl.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { sleepSeconds } from './sleep.ts';
|
||||
import { WEBHOOK_ENDPOINT } from 'astro:env/server';
|
||||
import { logger } from '@util/log.ts';
|
||||
|
||||
export enum WebhookAction {
|
||||
Signup = 'signup',
|
||||
@@ -27,22 +28,46 @@ export type WebhookActionType<T extends WebhookAction> = {
|
||||
}[T];
|
||||
|
||||
export async function sendWebhook<T extends WebhookAction>(action: T, data: WebhookActionType<T>) {
|
||||
if (!WEBHOOK_ENDPOINT || !/^https?:\/\/.+$/.test(WEBHOOK_ENDPOINT)) return;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const response = await fetch(WEBHOOK_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-webhook-action': action
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.status === 200) return;
|
||||
} catch (_) {}
|
||||
|
||||
await sleepSeconds(60);
|
||||
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 in 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) return;
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
{
|
||||
retry: retries + 1,
|
||||
error: e
|
||||
},
|
||||
'error while sending webhook'
|
||||
);
|
||||
}
|
||||
|
||||
retries++;
|
||||
await sleepSeconds(60);
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(webhookFutures);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user