Created
May 21, 2020 17:01
-
-
Save kevinswiber/9b7c601b64f025a20e55968901b09cc0 to your computer and use it in GitHub Desktop.
Twitch Webhook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const crypto = require('crypto'); | |
const http = require('http'); | |
const server = http.createServer(async (req, res) => { | |
if (req.method === 'GET') { | |
return handleSubscriptionVerification(req, res); | |
} else if (req.method === 'POST') { | |
return await handleEventNotification(req, res); | |
} | |
res.statusCode = 400; | |
res.end(); | |
}) | |
server.on('listening', () => { | |
log(`=> Twitch Webhook Server running on ${JSON.stringify(server.address())}`); | |
}); | |
server.listen(process.env.PORT || 3000); | |
const handleSubscriptionVerification = (req, res) => { | |
const parsed = new URL(req.url, `http://${req.headers.host}`); | |
const mode = parsed.searchParams.get('hub.mode'); | |
const challenge = parsed.searchParams.get('hub.challenge'); | |
log(`=> Receiving subscription verification, { mode: "${mode}", challenge: "${challenge}" }`); | |
res.statusCode = 200; | |
res.setHeader('Content-Type', 'text/plain'); | |
res.end(challenge); | |
} | |
const handleEventNotification = async (req, res) => { | |
console.log(req.url); | |
console.log(req.headers); | |
req.setEncoding('utf8'); | |
let input = ''; | |
for await (const chunk of req) { | |
input += chunk | |
} | |
const secret = '<secret>'; | |
const signatureHeader = req.headers['x-hub-signature'] || ''; | |
const [algorithm, signature] = signatureHeader.split('='); | |
if (algorithm !== 'sha256' || !signature) { | |
log(`=> Event notification, invalid hub signature!`); | |
res.statusCode = 400; | |
res.end(); | |
return; | |
} | |
const digest = crypto.createHmac('sha256', secret) | |
.update(input) | |
.digest('hex'); | |
if (signature !== digest) { | |
log(`=> Event notification, invalid hub signature or secret!`); | |
res.statusCode = 400; | |
res.end(); | |
return; | |
} | |
inputJSON = JSON.parse(input); | |
console.log(inputJSON); | |
if (inputJSON && inputJSON.data && inputJSON.data.length) { | |
log(`Stream is live, { title: "${inputJSON.data[0].title}" }`); | |
} else { | |
log('Stream has ended.'); | |
} | |
res.statusCode = 204; | |
res.end(); | |
}; | |
const log = (msg) => { | |
console.log(new Date(), `=> ${msg}`); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment