Webhook
Twitchfy allows to listen events through Webhooks. By default an express server is required to handle the incoming events from Twitch. Nevertheless, an alternative will be explored in this guide.
Creating a Webhook
To create a Webhook firstly we have to initialize a server to receive incoming data. To do this we are going to use Express.
1import express from 'express';2
3const server = express();
Having created an express server we are going to use it to create a new WebhookConnection.
1import express from 'express'2import { WebhookConnection } from '@twitchfy/eventsub';3
4const server = express();5
6server.listen(3333);7
8const connection = new WebhookConnection({9 clientId: 'clientId',10 clientSecret: 'clientSecret',11 appToken: 'appToken',12 maintainSubscriptions: false,13 secret: 'myAwesomeSecret',14 baseURL: 'https://mybaseurl.com'15}, server)16
17connection.start();
As you have seen, to create a WebhookConnection we need a secret. It is important to notice that is not the same as the clientSecret, the secret is used for protecting your webhook from malicious attacks. The baseURL
field is your own url that will point at your server, it has to use a https
protocol.
To wait until the connection is fully operational you can either wait until the start
method promise is resolved or listen to ConnectionReady
event.
1import express from 'express'2import { WebhookConnection, Events } from '@twitchfy/eventsub';3
4const server = express();5
6const connection = new WebhookConnection({7 clientId: 'clientId',8 clientSecret: 'clientSecret',9 appToken: 'appToken',10 maintainSubscriptions: false,11 secret: 'myAwesomeSecret',12 baseURL: 'https://mybaseurl.com'13}, server)14
15server.listen(3333);16
17connection.start().then(() => console.log('Connection ready'));18
19connection.on(Events.ConnectionReady, () => {20 console.log('Connection ready x2')21})
Subscribing to events
Having created a functional Webhook connection it is time to subscribe to our first event.
This example will show how to subscribe to a StreamOnline
event.
1import express from 'express'2import { WebhookConnection, Events } from '@twitchfy/eventsub';3
4const server = express();5
6server.listen(3333);7
8const connection = new WebhookConnection({9 clientId: 'clientId',10 clientSecret: 'clientSecret',11 appToken: 'appToken',12 maintainSubscriptions: false,13 secret: 'myAwesomeSecret',14 baseURL: 'https://mybaseurl.com'15}, server)16
17connection.start().then(() => console.log('Connection ready'));18
19connection.on(Events.ConnectionReady, async() => {20 console.log('Connection ready x2');21
22 await connection.subscribe({ type: SubscriptionTypes.StreamOnline, options: {23 broadcaster_user_id: 'userId'24 }})25})
Listening events
Now that you have created a new subscription we will listen to it and get notified whenever it is fired.
To achive this we can either use a callback using the onMessage
function in the subscription object or using the SubscriptionMessage
event.
1import express from 'express'2import { WebhookConnection, Events } from '@twitchfy/eventsub';3
4const server = express();5
6server.listen(3333);7
8const connection = new WebhookConnection({9 clientId: 'clientId',10 clientSecret: 'clientSecret',11 appToken: 'appToken',12 maintainSubscriptions: false,13 secret: 'myAwesomeSecret',14 baseURL: 'https://mybaseurl.com'15}, server)16
17connection.start().then(() => console.log('Connection ready'));18
19connection.on(Events.ConnectionReady, async() => {20 console.log('Connection ready x2');21
22 const subscription = await connection.subscribe({ type: SubscriptionTypes.StreamOnline, options: {23 broadcaster_user_id: 'userId'24 }})25
26 subscription.onMessage((message) => {27 console.log(`${message.broadcaster.displayName} has started a stream at ${message.stream.startedAt.toLocaleDateString()}`)28 })29})
1import express from 'express'2import { WebhookConnection, Events } from '@twitchfy/eventsub';3
4const server = express();5
6server.listen(3333);7
8const connection = new WebhookConnection({9 clientId: 'clientId',10 clientSecret: 'clientSecret',11 appToken: 'appToken',12 maintainSubscriptions: false,13 secret: 'myAwesomeSecret',14 baseURL: 'https://mybaseurl.com'15}, server)16
17connection.start().then(() => console.log('Connection ready'));18
19connection.on(Events.ConnectionReady, async() => {20 console.log('Connection ready x2');21
22 await connection.subscribe({ type: SubscriptionTypes.StreamOnline, options: {23 broadcaster_user_id: 'userId'24 }})25})26
27connection.on(Events.SubscriptionMessage, (message, subscription) => {28 //checks if the subscription is the desired subscription29 if(subscription.checkSubscriptionType(SubscriptionTypes.StreamOnline)) console.log(`${message.broadcaster.displayName} has started a stream at ${message.stream.startedAt.toLocaleDateString()}`)30})
Custom Server
As mentioned at the start of this section, the package has been made to be used with an express server. Furthermore, there is a way to use another type of server which doesn’t implies it has to be created with express.
To achive this we are going to use the post
function from the connection object to send the data we have received from our server. By default the events will be sent to the base url callback +/subscriptions
route. Althrough you can customize it in the subscriptions options by setting the subscriptionRoute
option. To see the full url where the events will go you can access to WebhookConnection.url
field.
In this example we are going to use the node native module https
.
1 import { WebhookConnection, Events } from '@twitchfy/eventsub';2
3 const server = express();4
5 const connection = new WebhookConnection({6 clientId: 'clientId',7 clientSecret: 'clientSecret',8 appToken: 'appToken',9 maintainSubscriptions: false,10 secret: 'myAwesomeSecret',11 baseURL: 'https://mybaseurl.com'12 })13
14 http.createServer(async(req, res) => {15 if(req.url === connection.subscriptionRoute && req.method === 'POST'){16 let body = ''17 req.on('data', (chunk) => {18 body += chunk.toString();19 })20 req.on('end', async() => {21 return await connection.post(req.headers, JSON.parse(body), (c) => {22 res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': c.length })23 res.write(c)24 res.end();25 }, () => {26 res.writeHead(200).end();27 })28 })29 }30 }).listen(3333)
In this example the post
function is used whenever you receive a post request to the subscription route. The post function sends the package the data that has been received. The first callback which has a challenge
parameter is fired whenever the webhook callback needs to be verified. The second callback is used whenever the package has received the data and checked the secret signature.
In the challenge callback you will have to respond to the request with a 200
status code and send the challenge param. Furthermore you have to change the Content-Type
header to text/plain
and the Content-Length
header to the length of the challenge param.
In the success callback you will have to send a 200
status code to Twitch to indicate that all is ok and you have received the event.
If you fail to respond to the challenge callback no events notifications will be sent to you. Furhtermore, if you fail to respond to the success callback Twitch will try to resend the event continously and finally will revoke the subscription.