Creating a Twitch Chat Bot

Pedro Lourenco
CodeX
Published in
11 min readJan 3, 2022
Photo by Caspar Camille Rubin on Unsplash

Let’s say you like going on Twitch, to watch gaming streams and check out new games, to watch music streams from great unknown artists or to watch some ASMR content because you are freaky like that.

Then you decide to start streaming, just for fun. You like to do things right, as such, you’d like to have layers of interaction with your viewers like the pros do.

The chat sounds like a good place to go for that, right ?

You’ve heard of Chat Bots, but you don’t want to use one of those paid ones! Oh no-no-no, you are just starting out! It is not smart to start spending your hard earned money on something you don’t even know if you actually like to do or want to pursue! If only there was a free option available…

Look no further

In this article I will guide you through the technical implementation of a Twitch Chat Bot and, after that, I will also provide guidance on how to set it up and use it on your (surely) epic streams!

If you just want to know how to use it, jump to the “Setup and Use the Bot” section. But I would recommend to at least read the part where the behavior of the bot is defined.

The code for this Chat Bot is also available for free on GitHub.

Let’s Start

The first step to implement a Twitch Chat Bot is determining what it will require to run! In other words, what config values do we have to provide the bot for it to successfully connect to twitch, to the intended channel and, finally, to the chat. So, let’s define the config file structure we need!

This is the config file structure we will be using:

Let’s dissect it a little bit:

  • token_endpoint — As our chat bot includes the logic to fetch its own access token for Twitch, we need to pass the endpoint which Twitch makes available to get OAuth Tokens from. It is always the same url, and is already pre-populated in the snippet above.
  • username — The username we want the bot to use on twitch, even though I believe this gets overriden we should still pass it to the bot.
  • client_id — Id attributed by Twitch for the Chat Bot application, after we registered it on the platform (we will look into this later).
  • client_secret — Secret generated by Twitch for the Chat Bot application, after we registered it on the platform (we will look into this later).
  • authorization_code — Code which tells Twitch that the Chat Bot is authorized to use a certain account on the platform (we will look into this later).

So, basically, a bunch of stuff that is needed to connect to Twitch, and for most of which you will only know more details later in this article. Hope this is being helpful so far 🤣.

In all seriousness this brief description on each config is all you need for now to understand what comes next in this guide, so let’s move on.

Configuration Ingestion

Okay, now that we know what has to be in the config, we should talk about how to integrate those values into the application.

Configuration ingestion is a subject for an article of its own, but here we will touch a bit on the implementation I did for this Chat Bot, in order to read the config file and validate that whatever is being provided in it is compliant to what the application expects.

Configuration Ingestion can be separated into two parts:

  • The definition of the model that, once instantiated, will contain the config values.
  • The validation of the values provided for the config.

Starting with the model, as you can see in the snippet bellow, it is basically a value class, with the added sugar of using annotations from the class-validator package, which is a great help for cleanly setting up constraints for the values accepted on a variable.

Here we only use two annotations because that is all we need, but it is already stripping our code from at least two discrete validation functions, which is great!

Now, onto the config validation part. The validation of the config is embedded in the readConfig function, which reads the file in the path passed as parameter and returns a Promise for a valid ChatBotConfig.

For the validation, as we have the model already annotated with the constraints per configuration value, we can just call the “validate” function from class-validator.

The way it works is pretty simple: You instantiate the annotated class, then you call validate with that instance as a parameter. If it returns an empty list, you have no issues on your config, otherwise, something is not compliant to the requirements and in that non-empty list you can find all the issues.

Pretty simple and clean, right? When I found this package I was very happy 🤩.

Also, you’ll notice that I defined a specific error type for configuration ingestion, instead of just using generic error types. I tend to do this most of the times because it makes so much easier to analyze any stack trace that comes my way when using the applications I create.

If I see an “InvalidTwitchConfigError” in my log, I know immediately where that comes from.

Into the actual Chat Bot

All of this text and we are not into the Chat Bot itself, right? I am very sorry, but I wanted to give you a good idea of how I did the things that “float around” the logic for the bot itself!

Now into the meaty part: How does the bot work?

Let’s start by the main section and then we dive into the details. Below, is the constructor and the “brain” function for the Chat Bot.

Basically, it needs a config object on instatiation and then the launch function goes like this:

  1. Get an OAuth access token to be able to authenticate with Twitch
  2. Create an instance of Twitch Client with a connection config built in the format supported by the Client.
  3. Setup the behaviors we want our bot to have (commands it is supposed to answer, messages it should ignore, etc.)
  4. Connect to Twitch and be happy!

Let’s dive into each of these steps.

Fetching the Access Token

Below is the code that fetches the access token for the bot to be able to connect to Twitch.

Diving a bit into what is actually going on in the code, you can see it translates into basically two steps:

  • Making a request to twitch’s token endpoint.
  • Handling whatever happens with that request.

The request obviously has to comply with the expected parameters by Twitch, but we are safe from “big issues” on that front because all “configurable” values are coming from our config object, which was already validated. Worst case scenario, we can have wrong values in the config, but that is managed on the response handling section.

On the response handling section (lines 17–32), we put the endpoint’s answer through a validator that we created, which will either:

  • Return a validated token response (hence the return type for fetchAccessToken being a promise of TwitchTokenDetails)
  • Throw one of the error types that we created to have easier debugging and root-cause analysis if something fails.

Bottom-line, a very similar logic to what was being done on the Config Validation.

You can check below the code for the TwitchTokenDetails value class and TwitchTokenResponseValidator.

You may have noticed that I don’t really have a catch anywhere for the InvalidTwitchResponseError. That is because, there is no case of the endpoint answering correctly (Status Code 200) but the contents of the response being wrong.

What could eventually trigger this error to be thrown by the validator is if the contract from Twitch’s API changed but we were unaware of it and, as such, not prepared to interpret the response body. But that couldn’t really be considered to be a error from the response could it?

So that is why, I have these error falling into the else-branch from the response handling section in fetchAccessToken(). Basically converting these cases into MalformedTwitchRequestError instances, for fairness.

Right now InvalidTwitchResponseError is only being used to signal failures in the token’s validation, but I still decided to maintain this type as it is not causing any harm right now and can become useful in the future — if Twitch responses start to be buggy at any point in time, for instance.

Instantiation of Twitch Client

Twitch Client is the one piece actually doing what we want: Connect to a Twitch Channel’s chat.

The Twitch Client comes from tmi.js which is a javascript library for the Twitch Messaging Interface. It is quite easy to use and setup: Only need to pass a config in the format it expects.

As you can see above, not too much going on. There is a function which builds the config as it needs to be provided to the client (and lets us visualize the structure of it in the process), I pass it the values from the Bot config and from the token that was just fetched, and then I use its return to create our client using tmi.js.

Setup the behaviors we want our bot to have

Before I launch the bot and connect to Twitch, I need to define how it will behave. This is done via a callback function.

The callback function defines the behavior the bot will have on each message that is pushed to the chat.

In the sample callback in the code, I define that the bot will ignore messages from itself, I also define that messages starting with ‘!’ are commands, and I provide one command for the Bot to support.

The interaction here defined is pretty simple: On receiving “!hello” from the chat the bot should answer with “Hello, <username>! Welcome to the channel.”.

This is obviously a starting point, you can have much more complex behaviors, but this is already a good start. It is always good to be polite, even if you are a Chat Bot.

This is all there is to it, regarding the implementation of a chat bot! Now we move into the “How to I setup and use the thing” part. Which I guess is the most interesting for the non-coders among you.

Setup and Use the Bot

I am sorry if you had to scroll this far to find what you actually wanted. But be happy, you survived!

In this section we will detail on how to get the values required for the config file, and how to use the Bot.

Before all else, you need to have npm and node.js installed. If you don’t, go do it (try from here), and then come back.

To get the code to your side, you can go to the GitHub Repository and download it as a zip file. After unzipping it, you have the bot on your side.

Download ZIP button to get the code

How to get the values for the Bot Configuration

For the Bot to run, you need to provide it with the configuration file already mentioned above in this article. That file contains the values for:

  • token_endpoint
  • username
  • client_id
  • client_secret
  • authorization_code

From these, token_endpoint is a constant value (shown in the configuration file snippet in this article and on the GitHub Repository), and username is pretty much up to you. This leaves us with 3 values to go and get!

Client_id and client_secret are both obtained from the same place, the Twitch portal for application registration. This is a portal in which you register your application as an entity that will connect to Twitch.

Registering Application on Twitch

After you register the application, click on the manage button to access the client_id and the button to generate a client_secret (which you should store somewhere safe as it is not possible to ever see it again from this page — but you can always generate a new one).

Manage Application Screen

Client_id✔️, client_secret✔️. Two down, one to go, and that one is the authorization_code.

The authorization code tells Twitch that whoever has it (in this case, the Bot), was authorized to log into twitch with the account of the authorizer.

Do you know that screen that shows up when you try to log into some website with Facebook, or Apple ID or whatever? When you click “allow”, you authorize the website to connect to those parties on your behalf to get some info. For this case it is pretty much the same overall procedure.

That authorization comes in the shape of an alphanumeric code, that you need to provide to the Bot so that it can log into Twitch using the account you used to authorize it, without knowing the actual credentials for the account!

This means that the bot does not have its own identity on Twitch. It uses the identity from the account used in the authorization procedure.

Usually, for those paid chat bot applications, to access the authorization screen there would be a website with a pretty “authorize on twitch” button or something.

But here in DIY land, we don’t need that because we can get there via this url structure:

https://id.twitch.tv/oauth2/authorize?client_id=<client_id>&redirect_uri=http://localhost&response_type=code&scope=chat:read chat:edit

You can copy the above url to your browser and replace <client_id> by the application’s client_id you got on the prior step.

You should be presented with a screen like the one below

Authorization Page for Twitch App

Once you click authorize, you will be able to see on your browser’s address bar your authorization code.

Address bar containing the authorization code.

Run the Chat Bot!

It’sssss TIMEEEEE! 👊

Now is the time when it all comes together: We get to run the bot in our channel’s chat while we stream! 🙌

So, pre-requisites: You should obviously be streaming when you run the bot, otherwise there is no chat to connect to. 😅

Apart from that, just follow these steps:

  1. Go to the folder containing the unzipped files you downloaded from GitHub
  2. Populate your config.ts file with the values for the Bot Config and your channel’s name
config.ts file structure

3. Type, in the command prompt, “npm install” and press enter — this will download everything that the Bot needs to run.

4. Still from the command prompt, type “npm start” and press enter to run the Bot! The initial output should be something like this:

If that was the case, congratulations, you are running a Chat Bot for free!!!

To see it working, just write one of the your supported commands to the chat, using an account different to the one the bot was authorized with, and have fun!

Working Chat Bot 🙌

--

--