First readme done.

master
Zed A. Shaw 3 hours ago
parent f8fc1a5bee
commit d381d585b5
  1. 2
      .gitignore
  2. 149
      README.md
  3. 28
      config.json
  4. 14
      config_example.json

2
.gitignore vendored

@ -33,4 +33,4 @@ public
*.sqlite3
*.log
secret.json
config.json

@ -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.
## 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.

@ -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."
}
]
}

@ -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."
}
]
}
Loading…
Cancel
Save