# Twitch IRC Bot A simple answer bot written in Go that uses Twitch's IRC service to do most of the work. This project is meant to explain to anyone else trying to make a similar client all the weird setup crap Twitch makes you do with OAUTH2. ## How to Actually Write a Twitch Bot Twitch's documentation on this is _extremely_ confusing. It's the classic, "We've explained every single thing exactly but didn't explain how they all work together." In this document I'm going to explain how you _actually_ get a Twitch bot setup. I'm using IRC but this initial setup should apply to the WebAPI...I think. ## Overview of the Problem Twitch uses [Oauth2](https://oauth.net/2/) to confirm that a user wants to give your bot access to their account. This is a good thing. Imagine you have a bot that pays people channel points or some similar thing and any user that wants to play with your bot must give them access. Then the flow is something like this: 1. User says, "Hey, this bot is cool I want to use it." 2. User goes to a web page explaining the bot. 3. Use clicks the, "Give Access" button which is _your button on your site, not twitch.tv_. 4. This then sends the user to twitch.tv's Oauth2 receiver and Twitch confirms they actually do want to give the bot access. This will also list the things your bot wants access to in their account. 5. Once they click the confirmation on _twitch's Oauth2_ end point, twitch bounces them back to your site's "oauth2 is done" URL. 6. Your bot now has access to the information you requested in their account. That's all reasonable, and should be the same process for other features like extensions. ## Anyone Using Oauth2 for Servers Deserves to Rot in Hell Twitch, in their infinite wisdom decided that _you_--the bot author--would use this same workflow to __give a bot you created in their own UI access to your own bot you created in your own account__. If that sounds dumb it is, and I have a theory about why they're doing this at the end. To make things worse, Twitch does not explain this weird "use Oauth2 to get a key for my bot" flow and they have errors in their UI. Here's the flow: 1. You would like to create a simple bot using Twitch's IRC. 2. You register your bot at https://dev.twitch.tv/console/apps/ 3. Your bot has a __Client ID__ and __Client Secret__. 4. You also...register an Oauth2 end point. Why does a bot that you run on a server need Oauth2? This also has to be `https` in the UI. 5. Because, to get the _actual_ key you use you have to get an Oauth2 URL at twitch. 6. When you go to this URL--that's exactly like the one for a user using your bot--it will ask you to...give yourself access to your own bot...that you just __fucking created in their fucking UI and got a two fucking keys for__. You have KEYS ALREADY! 7. You click the "Give Myself Access to Myself" button on the Oauth2 page, and it bounces you back to your...Oauth2 receiver that you definitely don't have because the _fucking bot is running on your computer at localhost and their stupid UI only allows `https` endpoints!_ 8. That means _you_ have to run an _entire Oauth2 stack on a computer on the internet_ just to get _yet another key_ from their Oauth2 system that's using the key they already gave you from their application registration. 9. Finally, when you get this key, it's not permanent. No, you have to refresh it using a _refresh key_ so we're now up to 4 different keys just to create a bot. Yes, it is as absolutely stupid as it sounds, but I'm going to tell you how to get this to work. ## Just Use the `twitch-cli` Thankfully, someone at Twitch rebelled against the middle manager in charge of this raging pile of bullshit and created the lovely [twitch-cli](https://dev.twitch.tv/docs/cli/). The `twich-cli` command will handle the Oauth2 bullshit for you, even setting up a local server and also handling the token management. It's also written in Go so you can study how they do it and you can even install it on Windows with `winget install Twitch.TwitchCLI`. 2. Log into your account and go to https://dev.twitch.tv/console/apps/ 3. Click "Register Application" 4. Give it a unique name, _but you will not use this name in the IRC login later_. Yes, you heard me right. 5. On the __OAuth Redirect URLs__ you'll see this error `Redirect URIs must use HTTPS protocol`. The problem is `twich-cli` creates a Oauth2 receiver at `http://localhost:3000` so it can't be https. __Just add http://localhost:3000/ anyway.__ If you still get an error then you should just refresh and immediately add the _not SSL localhost__ URL. If you added the `https` then the UI gets into a weird loop and won't let you add regular localhost. 6. For the category you must select `Chat Bot` as the category. 7. You also select `Confidential` as the type of bot. This is because you aren't in a web page but instead running as a server. ## The Oauth2 Dance After you create your application it's time to dance with Twitch's entirely useless Oauth2 key provisioning thing: 1. Install [twitch-cli](https://dev.twitch.tv/docs/cli/). 2. Run `twitch configure` and give it your Client ID and Client Secret. This will configure the `twitch` command for later operations. 3. Run `twitch token --user-token --scopes "chat:read chat:edit"` to get your keys. It's important you do `--user-token` here since you need the Oauth2 authentication even though you said in [the console](https://dev.twitch.tv/docs/cli/) that your application is Confidential. 4. The `twitch` command will then open a browser for you to approve your bot using Oauth2. 5. After you approve it your browser will redirect back to http://localhost:3000 (NO TRAILING SLASH!) and the `twitch` command will handle the Oauth2 result. 6. It will then output your `ClientSecret` and `RefreshToken` for the `secret.json` file used in this bot's configuration. __DO NOT COMMIT THIS TO GIT__. ## Refreshing Your Keys Currently my bot doesn't auto-refresh the keys, but you should only need to send a POST to `/oauth2/token` with your `RefreshToken` to renew it. Until then I do this manually: 1. Copy `secret_example.json` to `secret.json`. 1. Run `twitch token --refresh RefreshToken` where I replace "RefreshToken" with my `secret.json`'s `RefreshToken` setting. 2. This outputs a __totally new key that you have to record again__. So update your `secret.json` file and it should keep working. Once again, this is incredibly stupid and does not add security to their system. Companies like Paypal and Stripe only use secret keys given out by their UI and those companies deal with trillions of real dollars. Adding this bullshit key rotation layer on top of Oauth2 does nothing but make things complicated and inject a [notoriously](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/05-Testing_for_OAuth_Weaknesses) [insecure](https://nvd.nist.gov/vuln/detail/CVE-2026-34457) [system](https://portswigger.net/web-security/oauth) into the mix. ## Running This Bot Once you have your `secret.json` configured you can then edit the `config.json` to configure your bot. Run `cp config_example.json config.json` to get your version of the file. Here's they key configurations: `ClientNick` : This is _your username_, not the bot's, although the bot's will work too. `Channel` : Your channel to join. Not sure if it will work with any channel, but you might be able to use the `chat:read` scope. `Commands` : This is a list of `{"command": "Message"}` combinations. The "command" is used by the user with !command in the chat. `Periodic` : This is a list of messages the bot will post into chat periodically. Just say how many seconds to wait and it will wait then say that. ## TODO 1. Automated key refresh. 2. Hot reloading would be nice. 3. Controlling the bot from the chat, which would require 4. Authenticating the owner? Or just knowing it's you. 5. Productionizing how it's run, as in making it run as a server. 6. Chat log recording for later playback. 7. Maybe a separate tool for rendering out the chat messages for use in videos. ## Conspiracy Theory There's a middle manager at Amazon in charge of the Oauth2 system and they will receive a bonus for the number of users that utilize Oauth2. To get their bonus this idiot required everyone across the company to use Oauth2 in everything even if it didn't make sense like in a server.