parent
f8fc1a5bee
commit
d381d585b5
@ -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. |
||||
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…
Reference in new issue