Connecting to Twitch API with NodeJS and socket io

I am using NodeJS and I would like to create a connection to the Twitch API, so I can catch all the different things happening on my channel. So far I got my client ID, client secret and token. But the Twitch Dev Docs are quite overwhelming and the examples are in Curl, which I have no knowledge about. Because I am already able to connect to Streamlabs with socket.io, I thought I could do the same thing with the Twitch API. With Streamlabs, it looks like this:

const io = require('socket.io-client');
const streamlabs = io(`https://sockets.streamlabs.com?token=XXX`, {transports: ['websocket']});
streamlabs.on('connect', () => console.log('Connected with Streamlabs.'));

So with Twitch I tried it like this:

const io = require('socket.io-client');
const twitch = io(`https://sockets.twitch.com?token=XXX`, {transports: ['websocket']});
twitch.on('connect', () => console.log('Connected with Twitch.'));

Because this doesn’t work, I am not sure how to solve this. Did I write it wrong? Is this even possible with socket.io?

Thank you.

Twitch doesn’t provide a socket.io compatible endpoint. Nor is there any hint of socket.io in the docs.

Socket wise Twitch offers the following:

  • Twitch does provide a PubSub (regular sockets) endpoint.
  • Twitch will provide EventSub over sockets at some point
  • Twitch Chat is available over WebSocket as well.

All three of these will be “regular” sockets rather than socket.io, socket.io is sockets but uses a messaging encapsulation method.

Here are some node examples that do PubSub and Chat in nodeJS

So it depends on what data you are intending to obtain which then detemines what thing you will need to use.

The API is only available via HTTP interface, So cURL is used as cURL will translate to any language. Teach a developer to translate cURL into their language of choice and then you can use any API and they only need to write one version of docs!

Hey,

thanks for the answer. So I was able to connect with the chat. Now I would like to know, what information I am actually able to get? So for example:

twitch.on('message', (message) => {
    console.log(message);
});

’message’ seems to be the filter for “Just react, when something was written in the chat” and (message) is for pointing at this key to get its value, in this case the actuall written message.
But beside ‘message’, what other filters can I use? Or is there even a word for “Tell me always, no matter what”?
Same with (message): Is there a word for giving me the complete content and not just certain keys?

Depends what is twitch?

Are you using my chat exmaple, or a library?

It’s unclear what you are doing or using from this snippet.

Oh yeah, sry, here is the full thing:

const tmi = require('tmi.js');
const twitch = new tmi.client({
    identity: {
        username: 'xxx',
        password: 'oauth:xxx'
    },
    channels: ['xxx']
});

twitch.connect(console.log('Connected with Twitch.'));

twitch.on('message', (message) => {
    console.log(message);
});

You will need to refer to the tmi.js documentation

Which I can’t help with as I don’t use tmi.js I use the chat example I linked

Hey, so the last days I looked into the tmi.js dev docs and found answers. Unfortunately tmi.js can’t handle things like Channel Points. Because of that I am kinda back at point 1 and now I am trying to connect with the Pubsub system. You and the dev docs are so nice and link to JS examples. Problem is:

My knowledge is really low. As I mentioned in the start post: I get really fast overwhelmed. Imaging I am from China, Russia or any counrty, that doesn’t use the latin alphabet. I am trying to learn french and would like to start by saying “Hello, my name is…”. Your linked github examples have the translation in it, but for me they are like a 10 pager example-story with hundreds of french sentences that I have to read through now, just to see where in that story a character says “Hello, my name is…”. And the twitch dev docs are like a GIANT book with thousands of pages. I just can’t handle this. I am an idiot. When I mention things like “Unfortunately the examples in the dev docs are in cURL” and you say “cURL will translate to ANY language”, that is like me saying “The examples are in english, not french” and you answering “Well english is a global used language. So english can be translated to ANY language.” You are absoltuly right when you say that, but that doesn’t help me.
So yeah, thank you very much for trying to help me, but unfortunately you have to do it way easier for me. I am really sorry.

Looking through your example code, all I can do is guess. To make the first step, It seems like instead of writing something like…
const io = require('socket.io-client');
…I have to write…
const ws = new WebSocket('wss://pubsub-edge.twitch.tv');
…,right?

Chat libraries generally won’t.
As they handle chat rather than API or EventSub operations, which is where CP’s reside.

cURL is more like the alphabet than a different langauge but sure.
Since use seem to be using node/JS

You’ll need to pick a library to make HTTP requests with and then something like

Where the token is a user token

curl -X GET 'https://api.twitch.tv/helix/users' \
-H 'Authorization: Bearer cfabdegwdoklmawdzdo98xt2fo512y' \
-H 'Client-Id: uo6dggojyb8d6soh92zknwmi5ej1q2'

becomes, when using the HTTP Lib got

got({
    url: 'https://api.twitch.tv/helix/users',
    headers: {
        'Client-ID': 'uo6dggojyb8d6soh92zknwmi5ej1q2',
        'Authorization': 'Bearer cfabdegwdoklmawdzdo98xt2fo512y'
    },
    responseType: 'json'
})
.then(resp => {
    // process resp.body
})
.catch(err => {
    // do error processing
})

Once you know how to make HTTP calls in your language of choice then you can read any docs in cURL.

Not really no.

SocketIO is WS but encapsulated.

So socketIO you do io.on('eventDefinedByTheProvider

Where is WebSocket it’s all .on('message

It doesn’t split them into events for you it’s all one event.

So a “full” pubsub example is linked

This

  • sets up the pubsub socket connection.
  • The Ping/Pong loop functions
  • Asking for topics (fake/bad topics in the runAuth)
  • Message console.log-ing (no processing)

So

That line is the actual messge recieverm, the process msg (line 93) to see what topic it is and action/do your own stuff as needed when this triggers.

Hey,
thank you very much for you detailed explanation. In combination with your HTTP-Lib-got example and a little https-lib-post code I used in the past to get my app access token, I was able to turn your linked Get Users Refrerence into this:

Summary
const https = require('https');
const options = {
    host: 'api.twitch.tv',
    path: '/helix/users?login=<myLogin>',
    headers: {
        'Client-ID': '<myClientId>',
        'Authorization': 'Bearer <myAppAccessToken>'
    },
    method: 'GET'
};
callback = function(response) {
    let str = '';
    response.on('data', function (chunk) {
        str += chunk;
        });
    response.on('end', function () {
        console.log(str);
        });
};
https.request(options, callback).end();

And it worked. So now I have a template I can work with, in case I see another cURL code. That’s cool!

About the Pubsub connection:
I installed WebSocket and looked into the WebSockets Dev Docs to get a little overview about it. It helped me to understand your pubsub example a little bit more. So far I can connect to Pubsub WS. I saw in your example, that you solved the disconnect/reconnect-problem by puting it in a function, making it a loop. My version looks like this:

Summary
const WebSocket = require('ws');

connect = function() {
    const twitch = new WebSocket('wss://pubsub-edge.twitch.tv');
    
    twitch.on('open', () => {
        console.log('Connected with Twitch.')
    })
    
    twitch.on('close', () => {
        console.log('Disconnected from Twitch.')
        connect();
    })
}

connect();

So THIS is now, what I was basicly looking for in my start post. Again, that’s cool!
Unfortunately, unlike in streamlabs/socket.oi, there is still this ping/pong-problem I have to solve, so I don’t get disconnected after 5 miuntes. Btw, to my suprise I don’t get disconnected after 5 minutes (like it’s mentioned in the dev docs), but already after 1. Not sure if that means something.
Anyway, my thought is now:

If I already have a reconnection-loop, how necessary is the ping-pong-thing then? Or does a solution without ping/pong create a too big disadventage? And if the ping/pong is still really needed, how does it look like?

Because the ping doesn’t have do be send every second, I thought about a ping function I could call (in my case every minute). And you actually have some kind of function like that. But again, because it looks like you have tangled multiple functions into each other, it’s a bit hard for me to untangle your example.

You should ping/pong rather that disconnect/reconnect

As during the disconnect/reconnect you could miss a message/event.

To keep the server from closing the connection, clients must send a PING command at least once every 5 minutes. If a client does not receive a PONG message within 10 seconds of issuing a PING command, it should reconnect to the server. See details in Handling Connection Failures.

You need multiple timers.

One to handle sending ping and one to handle recieving a pong and doing stuff if a Pong isn’t receieved in time.

Thats why I have some things split out. So it’s less tangled and the seperate timer controller is held away from the main pubsub loop.

Hey,
because your point about the missing events while reconneting makes sense, I put in PING and PONG now. The new code looks now like this:

Summary
const WebSocket = require('ws');

function connect() {
    const twitch = new WebSocket('wss://pubsub-edge.twitch.tv');
    
    twitch.on('open', () => {
        console.log('Connected with Twitch.');

        twitch.ping(JSON.stringify({type: "PING"}), true, function() {console.log('Send PING.')});
        
        setInterval(function() {
            setTimeout(function() {
                twitch.ping(JSON.stringify({type: "PING"}), true, function() {console.log('Send PING.')});
        }, Math.floor((Math.random() * 1000) + 1));
        }, 50000)

        var noPongRestart = setTimeout(function() {
            console.log('Got no PONG.');
            twitch.close();
        }, 10000);

        twitch.on('pong', () => {
            console.log('Got PONG.');
            clearTimeout(noPongRestart);
        })
    });

    twitch.on('close', () => {
        console.log('Disconnected from Twitch.');
        connect();
    });
};

connect();

The weird thing is: After 60 seconds I still get disconnected. But a PING gets send every 50 seconds. My guess is, that even tho the console tells me I am sending PINGs and getting PONGs, I am actually not really sending a PING. But I seem to have written it right, when I look into the dev doc für a PING. But in case I also tried:

twitch.ping(console.log('Send PING.'));

Same problem.

twitch.ping();
twitch.on('ping', () => {console.log('Send PING.')});

Again, same problem. Also the console doesn’t say Send PING, but a Got PONG. Makes it even weirder.

What did I do wrong?

twitch.ping isn’t the right way to ping/pong

From my example

        pubsub.send(JSON.stringify({
            type: 'PING'
        }));

Which for you equates to

twitch.send(JSON.stringify({type: "PING"}));

This is also wrong

        twitch.on('pong', () => {
            console.log('Got PONG.');
            clearTimeout(noPongRestart);
        })

See line 78

Twitch sends as a message (not as a “pong”)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.