Configure webhooks to handle run completion events in real time.

import express, { Request, Response } from 'express';
import bodyParser from 'body-parser';
import crypto from 'crypto';
import dotenv from 'dotenv';
import autotab, { RunSession, RunSessionState } from 'autotab';

dotenv.config();

const WEBHOOK_SECRET = process.env.AUTOTAB_WEBHOOK_SECRET;
const app = express();

app.use(bodyParser.raw({ type: 'application/json' }));

app.post("/webhook/autotab", async (req: Request, res: Response) => {
    const signature = req.headers['autotab-signature'] as string | undefined;
    
    if (!verifySignature(req.body, signature)) {
        return res.status(401).json({ error: "Invalid signature" });
    }

    try {
        const runSession: RunSession = JSON.parse(req.body.toString());

        switch (runSession.state) {
            case RunSessionState.FINISH:
                await handleSessionCompleted(runSession);
                break;
            case RunSessionState.CANCEL:
                await handleSessionFailed(runSession);
                break;
            case RunSessionState.TIMEOUT:
                await handleSessionTimedOut(runSession);
                break;
            default:
                console.warn(`Unhandled event type: ${runSession.event}`);
        }

        res.json({ status: "success" });
    } catch (e) {
        console.error("Error processing webhook:", e);
        res.status(500).json({ error: e.message });
    }
});

function verifySignature(requestBody: Buffer, signature: string | undefined): boolean {
    if (!signature || !WEBHOOK_SECRET) {
        return false;
    }

    const expectedSignature = crypto.createHmac('sha256', WEBHOOK_SECRET)
                                     .update(requestBody)
                                     .digest('hex');

    return crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature));
}

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});