diff --git a/README.md b/README.md index bcaaf09..e75e566 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/src/pages/index.astro b/src/pages/index.astro index 1dd67ab..631a2e7 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -91,8 +91,8 @@ const information = [

Über uns

- Wir sind ein kleines Team 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 Team 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.

diff --git a/src/util/webhook.ts b/src/util/webhook.ts index e0af808..a56ed47 100644 --- a/src/util/webhook.ts +++ b/src/util/webhook.ts @@ -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]; export async function sendWebhook(action: T, data: WebhookActionType) { - 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); }