JustPaste.it
const crypto = require('crypto')
const express = require('express');
const app = express();
const port = 443;
const axios = require('axios')
   
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();
const MESSAGE_TYPE = 'Twitch-Eventsub-Message-Type'.toLowerCase();
const MESSAGE_TYPE_VERIFICATION = 'webhook_callback_verification';
const MESSAGE_TYPE_NOTIFICATION = 'notification';
const MESSAGE_TYPE_REVOCATION = 'revocation';
const HMAC_PREFIX = 'sha256=';

const clientSecret = "********";
const clientID = "********";

const options = {
    url: 'https://id.twitch.tv/oauth2/token',
    headers: {
        'Content-Type': 'application/json'
    },
    method: 'POST',
    body: JSON.stringify({
        client_id: clientID,
        client_secret: clientSecret,
        grant_type: 'client_credentials',
    })
}

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


app.post('/eventsub', (req, res) => {
    let secret = getSecret();
    let message = getHmacMessage(req);
    let hmac = HMAC_PREFIX + getHmac(secret, message);
    if (true === verifyMessage(hmac, req.headers[TWITCH_MESSAGE_SIGNATURE])) {
        console.log("signatures match");
        let notification = JSON.parse(req.body);
       
        if (MESSAGE_TYPE_NOTIFICATION === req.headers[MESSAGE_TYPE]) {
            console.log(`Event type: ${notification.subscription.type}`);
            console.log(JSON.stringify(notification.event, null, 4));
           
            res.sendStatus(204);
        }
        else if (MESSAGE_TYPE_VERIFICATION === req.headers[MESSAGE_TYPE]) {
            res.set('Content-Type', 'text/plain').status(200).send(notification.challenge);
        }
        else if (MESSAGE_TYPE_REVOCATION === req.headers[MESSAGE_TYPE]) {
            res.sendStatus(204);

            console.log(`${notification.subscription.type} notifications revoked!`);
            console.log(`reason: ${notification.subscription.status}`);
            console.log(`condition: ${JSON.stringify(notification.subscription.condition, null, 4)}`);
        }
        else {
            res.sendStatus(204);
            console.log(`Unknown message type: ${req.headers[MESSAGE_TYPE]}`);
        }
    }
    else {
        console.log('403');
        res.sendStatus(403);
    }

    fetch(options.url, options)
        .then(response => response.json())
        .then(data => {
            console.log(data)

            axios({
                method: "POST",
                url: "https://api.twitch.tv/helix/eventsub/subscriptions",
                headers: {
                    "Content-Type": "application/json",
                    'Client-Id': "********",
                    'Authorization': `Bearer ${data.access_token}`
                },
                data: {
                    "type": "stream.online",
                    "version" : "1",
                    "condition" : {
                        "broadcaster_user_id": "38746172"
                    },
                    "transport": {
                        "method": "webhook",
                        "callback": "http://localhost:443/eventsub",
                        "secret" : "clientSecret"
                    }
                }
            })
            .then((res) => {
                console.log(res.data)
            })
            .catch((error) => {
                {
            console.log(error)
                }
            });


        })
   
   
   
})
 
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
})


function getSecret() {
    return 'a02v9ped9xqd3l0lg4ktu6p5mxzt9v';
}
function getHmacMessage(request) {
    return (request.headers[TWITCH_MESSAGE_ID] +
        request.headers[TWITCH_MESSAGE_TIMESTAMP] +
        request.body);
}

function getHmac(secret, message) {
    return crypto.createHmac('sha256', secret)
    .update(message)
    .digest('hex');
}
function verifyMessage(hmac, verifySignature) {
    return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(verifySignature));
}