Creating Twitch Chat Bots with Node.js

December 14, 2020
Written by
Sam Agnew
Twilion

Copy of Generic Blog Header 2.png

 

From watching people play your favorite games, to seeing awesome things built with code, to cooking up a storm in the kitchen, you can find a huge variety of content being streamed live on Twitch.tv. A mainstay of many Twitch channels is having a bot to engage with viewers in chat to automate things such as tasks for moderators or sharing contextual information with newcomers. Chat bots can even control Pokemon games!

Let's walk through how to unleash the powers of Twitch chat bots on your own channel with JavaScript using Node.js.

Twitch Plays Pokemon

Taking care of dependencies

Before writing any code, you will need an up to date version of Node.js and npm installed.

Navigate to the directory where you want this code to live and run the following command in your terminal to create a package for this project:

npm init --yes

The --yes argument runs through all of the prompts that you would otherwise have to fill out or skip. Now that we have a package.json for our app, run this command in the same directory to install the tmi.js library for Twitch chat:

npm install tmi.js@1.5.0

Twitch chat can be accessed through IRC, and we can programmatically connect to Twitch IRC with tmi.js. You should now have everything you need to begin building your bot.

Connecting to a Twitch stream and reading chat messages

Let's begin by making an anonymous, read-only connection to a Twitch channel's chat. No authentication credentials are needed to read messages sent to a channel, so we can just log all incoming messages with tmi.js without overcomplicating things.

Create a file called index.js in the same directory as your package.json. Add the following code to it for logging all messages sent to a given channel as they come in:

const tmi = require('tmi.js');

const client = new tmi.Client({
  connection: {
    secure: true,
    reconnect: true
  },
  channels: [ 'channel_name' ]
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  console.log(`${tags['display-name']}: ${message}`);
});

Replace the channel_name with the Twitch username of whoever's stream you're testing with, and run the code with the command node index.js from your terminal. You should see messages being logged which looks something like this:

Testing the bot

Generating an Oauth token and sending messages to a channel

In order to send messages, from either your personal account or one you create specifically for your bot, you'll need a token to authenticate your chatbot with Twitch's servers. Go to https://twitchapps.com/tmi/ and log in with your Twitch credentials to authenticate TMI with your account.

After logging in, click "Authorize" and you should be given a token. Save this Oauth token you received in an environment variable to be used in your code later:

export TWITCH_OAUTH_TOKEN='oauth:YOUR_TOKEN_HERE'

You can use this token to connect to Twitch chat with tmi.js and send messages from whichever Twitch account you authenticated with.

As an example, let's try some code to respond to people who say hello. Replace the code in index.js with the following:

const tmi = require('tmi.js');

const client = new tmi.Client({
  options: { debug: true },
  connection: {
    secure: true,
    reconnect: true
  },
  identity: {
    username: 'your_username',
    password: process.env.TWITCH_OAUTH_TOKEN
  },
  channels: ['channel_name']
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  // Ignore echoed messages.
  if(self) return;

  if(message.toLowerCase() === '!hello') {
    client.say(channel, `@${tags.username}, Yo what's up`);
  }
});

This time you'll have to replace your_username with whatever Twitch account you're using to test this with, preferably one you created for your bot. I am just going to use my personal account for this. To avoid being rude and testing my bot in someone else's channel, I am going to connect to my own, but if you have any friends who are streaming it can be fun to connect to their streams.

Run the code with index.js again, and try saying "!hello" in the chat to get a response:

Responding to messages in the chat

Because I am using the same account for both it may appear as if I'm talking to myself but, one of those messages is automated and one is not.

Handling chat commands

Now that you can read and respond to messages sent from users in the chat, you can use your creativity to implement the logic for handling all sorts of different commands for whatever you want your bot to do. We already covered saying hello, so let's check out a few more examples.

Replace the code in index.js with the following, which includes some basic logic for handling commands, which start with "!". In this example we have our "!hello" command from before, as well as one to echo messages and one to simulate rolling a six-sided die:


const tmi = require('tmi.js');

const client = new tmi.Client({
  options: { debug: true },
  connection: {
    secure: true,
    reconnect: true
  },
  identity: {
    username: 'your_username',
    password: process.env.TWITCH_OAUTH_TOKEN
  },
  channels: ['channel_name']
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  if(self || !message.startsWith('!')) {
    return;
  }

  const args = message.slice(1).split(' ');
  const command = args.shift().toLowerCase();

  if(command === 'echo') {
    client.say(channel, `@${tags.username}, you said: "${args.join(' ')}"`);
  } else if(command === 'hello') {
    client.say(channel, `@${tags.username}, Yo what's up`);
  } else if(command === 'dice') {
    const result = Math.floor(Math.random() * 6) + 1;
    client.say(channel, `@${tags.username}, You rolled a ${result}.`);
  }
});

Run your code again and try testing out some commands.

Testing out some bot commands

From here you can have your bot do whatever you want. Let's try something slightly more involved. A common feature I've seen with IRC bots is to implement a sort of "reputation" system for frequent users of a given chat. Whenever someone provides useful insight, people can give them points by appending "++" to their username and subtract points with "--" if they are being disruptive or harmful. Add the following code to index.js to implement this rudimentary reputation system:


const tmi = require('tmi.js');

const reputation ={};
const client = new tmi.Client({
  options: { debug: true },
  connection: {
    secure: true,
    reconnect: true
  },
  identity: {
    username: 'your_username',
    password: process.env.TWITCH_OAUTH_TOKEN
  },
  channels: ['channel_name']
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  const reputationRegex = /(\+\+|--)/g;

  if(reputationRegex.test(message)) {
    const [user, operator] = message.split(reputationRegex);

    if(!(user in reputation)) {
      reputation[user] = 0;
    }

    if(operator === '++') {
      reputation[user]++;
    } else {
      reputation[user]--;
    }

    client.say(channel, `@${tags.username}, ${user} now has a reputation of ${reputation[user]}`);
    return;
  }

  if(self || !message.startsWith('!')) {
    return;
  }

  const args = message.slice(1).split(' ');
  const command = args.shift().toLowerCase();

  if(command === 'echo') {
    client.say(channel, `@${tags.username}, you said: "${args.join(' ')}"`);
  } else if(command === 'hello') {
    client.say(channel, `@${tags.username}, Yo what's up`);
  } else if(command === 'dice') {
    const result = Math.floor(Math.random() * 6) + 1;
    client.say(channel, `@${tags.username}, You rolled a ${result}.`);
  }
});

Run the code again and try it out! As you can see here, I just gave myself a terrible reputation score:

Testing out the reputation command

The Next Level

We've covered some of the basics of creating a Twitch chatbot for you and your friends' channels. You can continue working on this by interacting with other APIs such as Twilio Programmable Messaging, or adding new features that your friends think would be useful.

Feel free to reach out if you have any questions or comments, or just want to show off any cool things your Twitch bot can do.