From d381d585b5f6ebc3c582c2850a4c5539c12c242e Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Mon, 1 Jun 2026 15:19:23 -0400 Subject: [PATCH] First readme done. --- .gitignore | 2 +- README.md | 151 +++++++++++++++++++++++++++++++++++++++++++- config.json | 28 -------- config_example.json | 14 ++++ 4 files changed, 164 insertions(+), 31 deletions(-) delete mode 100644 config.json create mode 100644 config_example.json diff --git a/.gitignore b/.gitignore index 4c05a82..f489ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ public *.sqlite3 *.log secret.json - +config.json diff --git a/README.md b/README.md index 58196fc..e85cae4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,150 @@ -# twitch-irc-bot +# 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. \ No newline at end of file +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.__ The error message seems to be wrong, but I ran into a +situation where I couldn't add so I had to do this: + + a. Add a fake url `https://localhost:3000`. Yes, `https`, make sure that's there. + b. Then add a second one with `http://localhost:3000`. + c. Remove the first `https` one and you're done. + +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/ 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. Hot reloading would be nice. +2. Controlling the bot from the chat, which would require +3. Authenticating the owner? Or just knowing it's you. +4. Productionizing how it's run, as in making it run as a server. + +## 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. diff --git a/config.json b/config.json deleted file mode 100644 index 38fe392..0000000 --- a/config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "ClientNick": "zedashaw", - "Channel": "ZedAShaw", - "Commands": { - "keyboard": "I use https://hhkeyboard.us/hhkb/pro-classic-type-s but I don't recommend it.", - "mic": "It's a Samson se50x https://samsontech.com/products/microphones/headworn-microphones/se50x/", - "site": "https://learncodethehardway.com/", - "help": "COMMANDS: !mic !keyboard !site !ai !lsp !linux !windows !neovim !gvim !vim", - "ai": "I don't use AI, or really anything, but I don't hate AI.", - "lsp": "I use only a Terminal and Vim, no LSP, AI, or many other tools.", - "linux": "I do use Linux, and I might have to totally switch if Microsoft forces Windows 11 on me.", - "windows": "I use Windows because 95% of the world uses Windows and I want to teach them to code.", - "neovim": "NeoVIM is trying too hard to be like VSCode instead of being a better Vim.", - "gvim": "I use gvim because it works on all my computers and I'm not a troglodyte who runs...vim in a terminal? Blech.", - "vim": "I'll get my vim config on my git repo in a bit.", - "instagram": "My paintings are at https://www.instagram.com/zed.a.shaw" - }, - "Periodic": [ - { - "Seconds": 1800, - "Message": "You can use !help to get help from my Twitch IRC bot." - }, - { - "Seconds": 3300, - "Message": "I run 3 minute ads once an hour. Take a break during that time." - } - ] -} diff --git a/config_example.json b/config_example.json new file mode 100644 index 0000000..508db3c --- /dev/null +++ b/config_example.json @@ -0,0 +1,14 @@ +{ + "ClientNick": "yourusernamealllowercase", + "Channel": "YourChannel", + "Commands": { + "bangcommand": "Users type !bangcommand and then you will say this in chat.", + "help": "COMMANDS: just write your list of commands manually." + }, + "Periodic": [ + { + "Seconds": 1800, + "Message": "You can also have it periodically send a message to chat." + } + ] +}