Twitch IRC bot (C# console application)

By
Kenton Standard

Background

Video game streaming has been an important part of the gaming community since Twitch took in its first breath of life in 2011. Gamers like to watch other people play games for information and entertainment. However, live streams take this concept one step further. These streams allow the audience or viewers to ask questions about the game being streamed and to interact with the streamer or broadcaster in real-time.

There are many different aspects to streaming, ranging from foreground content (game and broadcaster input) to background content (music and chat bots). Chat bots, in particular, help not only the broadcaster interact with the audience, but also entertain them when the broadcaster is too busy to respond. Coming from personal experience as a broadcaster, many of my viewers come to my streams not for the foreground content, but for my custom chat bot and myself. My personal advice is that anyone can watch gameplay videos, but personality and uniqueness bring your audience back.

This communication between the audience and the broadcaster is driven by an Internet Relay Chat (IRC) client/server relationship that allows users to communicate together via text. This post goes over the general structure of Twitch chat bots without a graphical user interface (GUI).

Bot requirements

Before working with this IRC Console Application, you need 3 things:

  • A broadcaster’s username
  • Your bot’s name from your second Twitch account
  • An OAuth password to allow the bot to enter the broadcaster’s channel
  • Under your main account, you need to have a Client ID for this application
  • This can be obtained by registering your application under the “Connections” tab within the “Settings” menu of Twitch and grabbing it there
  • Go to Twitch Chat OAuth Password Generator as your bot account to generate this password
  • If you need additional info, please check out the official authentication documentation

Getting started

Make a new console application solution. My namespace is TwitchBotDemo if you want to follow exactly what I have written. You need three classes: Program.cs, IrcClient.cs, and PingSender.cs. Replace the generated code inside these class files with the code below.

For demo purposes, I have implemented the bot settings inside Program.cs as private static string variables. Please replace the values within these variables with the appropriate info you’ve gathered from the requirements explained above.

And that’s it! You should be able to build and run this application in one fell swoop.

Code

C# - Program.cs


using System;

namespace TwitchBotDemo
{
    class Program
    {
        // Bot settings
        private static string _botName = "bot_name";
        private static string _broadcasterName = "channel_name";
        private static string _twitchOAuth = "oauth:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // get chat bot's oauth from www.twitchapps.com/tmi/

        static void Main(string[] args)
        {
            // Initialize and connect to Twitch chat
            IrcClient irc = new IrcClient("irc.twitch.tv", 6667,
                _botName, _twitchOAuth, _broadcasterName);

            // Ping to the server to make sure this bot stays connected to the chat
            // Server will respond back to this bot with a PONG (without quotes):
            // Example: ":tmi.twitch.tv PONG tmi.twitch.tv :irc.twitch.tv"
            PingSender ping = new PingSender(irc);
            ping.Start();
            
            // Listen to the chat until program exits
            while (true)
            {
                // Read any message from the chat room
                string message = irc.ReadMessage();
                Console.WriteLine(message); // Print raw irc messages

                if (message.Contains("PRIVMSG"))
                {
                    // Messages from the users will look something like this (without quotes):
                    // Format: ":[user]![user]@[user].tmi.twitch.tv PRIVMSG #[channel] :[message]"

                    // Modify message to only retrieve user and message
                    int intIndexParseSign = message.IndexOf('!');
                    string userName = message.Substring(1, intIndexParseSign - 1); // parse username from specific section (without quotes)
                                                                                   // Format: ":[user]!"
                    // Get user's message
                    intIndexParseSign = message.IndexOf(" :");
                    message = message.Substring(intIndexParseSign + 2);

                    //Console.WriteLine(message); // Print parsed irc message (debugging only)

                    // Broadcaster commands
                    if (userName.Equals(_broadcasterName))
                    {
                        if (message.Equals("!exitbot"))
                        {
                            irc.SendPublicChatMessage("Bye! Have a beautiful time!");
                            Environment.Exit(0); // Stop the program
                        }
                    }

                    // General commands anyone can use
                    if (message.Equals("!hello"))
                    {
                        irc.SendPublicChatMessage("Hello World!");
                    }
                }
            }
        }
    }
}

C# - ircclient.cs


using System;
using System.Net.Sockets;
using System.IO;

namespace TwitchBotDemo
{
    // Reference: https://www.youtube.com/watch?v=Ss-OzV9aUZg
    public class IrcClient
    {
        public string userName;
        private string channel;

        private TcpClient _tcpClient;
        private StreamReader _inputStream;
        private StreamWriter _outputStream;

        public IrcClient(string ip, int port, string userName, string password, string channel)
        {
            try
            {
                this.userName = userName;
                this.channel = channel;

                _tcpClient = new TcpClient(ip, port);
                _inputStream = new StreamReader(_tcpClient.GetStream());
                _outputStream = new StreamWriter(_tcpClient.GetStream());

                // Try to join the room
                _outputStream.WriteLine("PASS " + password);
                _outputStream.WriteLine("NICK " + userName);
                _outputStream.WriteLine("USER " + userName + " 8 * :" + userName);
                _outputStream.WriteLine("JOIN #" + channel);
                _outputStream.Flush();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void SendIrcMessage(string message)
        {
            try
            {
                _outputStream.WriteLine(message);
                _outputStream.Flush();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void SendPublicChatMessage(string message)
        {
            try
            {
                SendIrcMessage(":" + userName + "!" + userName + "@" + userName +
                ".tmi.twitch.tv PRIVMSG #" + channel + " :" + message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public string ReadMessage()
        {
            try
            {
                string message = _inputStream.ReadLine();
                return message;
            }
            catch (Exception ex)
            {
                return "Error receiving message: " + ex.Message;
            }
        }
    }
}

C# - pingsender.cs


using System.Threading;

namespace TwitchBotDemo
{
    /*
    * Class that sends PING to irc server every 5 minutes
    */
    public class PingSender
    {
        private IrcClient _irc;
        private Thread pingSender;

        // Empty constructor makes instance of Thread
        public PingSender(IrcClient irc)
        {
            _irc = irc;
            pingSender = new Thread(new ThreadStart(this.Run));
        }

        // Starts the thread
        public void Start()
        {
            pingSender.IsBackground = true;
            pingSender.Start();
        }

        // Send PING to irc server every 5 minutes
        public void Run()
        {
            while (true)
            {
                _irc.SendIrcMessage("PING irc.twitch.tv");
                Thread.Sleep(300000); // 5 minutes
            }
        }
    }
}

Notes

I’ve used Visual Studio 2015 Community with .NET Framework 4.6.1 to make this demonstration. I have also used a YouTube chat bot tutorial for the IrcClient code (referenced inside the IrcClient.cs) because it is short, sweet and straight to the point. I followed this tutorial for my first Twitch bot until I needed more commands and a way to keep my bot’s connection alive.

Closing

I hope you have a basic understanding of how Twitch IRC bots work and a foundation to expand this logic. If you enjoyed this article and want to get in contact with me with more questions about this bot or would be interested in my Twitch streams, please check out my GitHub or Twitch channel.