58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
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();
|
|
}
|
|
};
|