Skip to content

Webhooks ​

Der Tab Webhooks von /nay (Scope nay.admin) sendet Ereignisse der Skripte an deine URLs. Wähle die Ereignisse aus (oder alle), drücke Testen, um die Einrichtung zu prüfen, und sieh dir die letzte Antwort jedes Webhooks an.

Es gibt zwei Typen:

  • Discord: Füge die Webhook-URL eines Discord-Kanals ein (https://discord.com/api/webhooks/...). Jedes Ereignis wird zu einem Embed, mit Titel und Beschriftungen in der Serversprache und den Feldern des Ereignisses in ihrer Reihenfolge. Discord-Markdown in Werten wird maskiert, niemand wird erwähnt, und lange Nachrichten werden auf das Limit von 6000 Zeichen gekürzt.
  • Signiertes JSON: für deine eigene Website oder deinen Bot. Jeder Webhook bekommt ein Geheimnis, das beim Erstellen oder Neugenerieren angezeigt wird.

Zustellungen ​

Eine Zustellung ist ein POST mit JSON:

json
{ "id": "3f9c2a1b7d4e8f60", "event": "nay_car_wash.wash", "resource": "nay_car_wash", "time": 1791670794, "data": { "player": "John", "price": 150 } }

Header: X-Nay-Event, X-Nay-Delivery (gleich id), X-Nay-Timestamp (Unix-Sekunden) und X-Nay-Signature: sha256=<hex>.

  • Antworte mit einem beliebigen 2xx-Status. Keine Antwort innerhalb von 15 Sekunden zählt als Netzwerkfehler.
  • Netzwerkfehler sowie 5xx- und 429-Antworten werden nach 1, 10 und 60 Sekunden mit demselben X-Nay-Delivery erneut gesendet. Andere 4xx-Antworten werden nicht wiederholt.
  • Nach 20 fehlgeschlagenen Zustellungen in Folge wird der Webhook deaktiviert. Aktiviere ihn im Tab wieder oder speichere ihn mit einer neuen URL.
  • Discord-Zustellungen werden nicht signiert und halten sich bei einem Rate Limit an Discords retry_after.

Ereignisse ​

Ereignisse von nay_lib:

EreignisWannDaten
nay.settingEine Einstellung wird geändert oder zurückgesetzt.resource, key, action, actor
nay.permissionEine Berechtigungsregel wird erteilt oder entzogen.action, type, identifier, scope, actor
nay.tokenEin API-Token wird erstellt oder widerrufen.action, id, label, actor
nay.testDie Schaltfläche Testen.message

Jedes Skript listet seine eigenen Ereignisse auf seiner Seite, zum Beispiel Car Wash.

Die Signatur prüfen ​

Bevor du einer signierten Zustellung vertraust, prüfe ihre Signatur: HMAC-SHA256 von <X-Nay-Timestamp>.<raw body>, mit dem Geheimnis genau so als Schlüssel, wie es angezeigt wird (der Hex-Text selbst). Lehne alte Zeitstempel ab.

Node.js (Express):

js
import { createHmac, timingSafeEqual } from "node:crypto";
import express from "express";

const app = express();
app.post("/nayretis", express.raw({ type: "application/json" }), (req, res) => {
	const timestamp = req.get("X-Nay-Timestamp") ?? "";
	const expected = "sha256=" + createHmac("sha256", process.env.NAY_WEBHOOK_SECRET).update(`${timestamp}.${req.body}`).digest("hex");
	const given = req.get("X-Nay-Signature") ?? "";
	const valid = given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
	if (!valid || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
		return res.sendStatus(401);
	}
	const delivery = JSON.parse(req.body);
	res.sendStatus(204);
});

PHP:

php
<?php
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_NAY_TIMESTAMP'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, getenv('NAY_WEBHOOK_SECRET'));
if (!hash_equals($expected, $_SERVER['HTTP_X_NAY_SIGNATURE'] ?? '') || abs(time() - (int) $timestamp) > 300) {
	http_response_code(401);
	exit;
}
$delivery = json_decode($body, true);
http_response_code(204);