import { createHmac, timingSafeEqual } from "node:crypto"; import type { RequestHandler } from "@sveltejs/kit"; import { HASH_SECRET } from "$env/static/private"; import { twitchFollowEvent } from "$lib/twitch"; import { client } from "$lib"; const getHmacMessage = (request: Request, body: string): string => { return ( request.headers.get(TWITCH_MESSAGE_ID)! + request.headers.get(TWITCH_MESSAGE_TIMESTAMP)! + body ); }; const getHmac = (secret: string, message: string): string => { return createHmac("sha256", secret).update(message).digest("hex"); }; const verifyMessage = (hmac: string, verifySignature: string): boolean => { return timingSafeEqual(Buffer.from(hmac), Buffer.from(verifySignature)); }; const HMAC_PREFIX = "sha256="; const TWITCH_MESSAGE_ID = "Twitch-Eventsub-Message-Id".toLowerCase(); const TWITCH_MESSAGE_TIMESTAMP = "Twitch-Eventsub-Message-Timestamp".toLowerCase(); const TWITCH_MESSAGE_SIGNATURE = "Twitch-Eventsub-Message-Signature".toLowerCase(); export const fallback: RequestHandler = async ({ request }) => { const body = await request.text(); const message = getHmacMessage(request, body); const hmac = HMAC_PREFIX + getHmac(HASH_SECRET, message); if (!verifyMessage(hmac, request.headers.get(TWITCH_MESSAGE_SIGNATURE)!)) { console.log("Invalid request"); throw new Error("go away"); } else { // Get JSON object from body, so you can process the message. const jsonBody = JSON.parse(body); console.log(jsonBody); const event = twitchFollowEvent.safeParse(jsonBody); if (!event.success) { console.log("Not a follow event"); console.log(event.error); return new Response(); } const { user_name } = event.data.event; client.setRave(5_000); console.log(`${user_name} has just subscribed`); return new Response(); } };