DEV Community

Cover image for Let's make a Twitch bot with Python!

Let's make a Twitch bot with Python!

💾 bun9000 on October 18, 2019

This tutorial gets you up and running with a simple chat bot for Twitch channel. Who's this tutorial for? Beginners to coding and exper...
Collapse
 
mrbackbreaker_ profile image
Angry Bob

I have a problem at the point where i have to wake the bot up with "pipenv run python bot.py". It keeps saying "Loading .env environment variables…" but nothing more. Its just stuck at this point and doesnt even give me an error.
I would really appreciate an answer since im stuck here for several hours and its driving me nuts. Thank you in advance

Collapse
 
seanlodhammar profile image
Sean Lodhammar

The reason "Loading .env environment variables..." will stay, is because there is nothing to print to the console afterwards. In the "event_ready" function, if you print something, then there will be output.

Collapse
 
holphana profile image
Holly Pennington • Edited

I'm so sorry that it took someone more than a year to find this but this is a super easy fix that was not very clear in the guide.

(the following example has a couple extra spaces to avoid formatting)

the:
if __ name __ == "__ main __":
bot.run()

must go at the bottom of your bot.py file

if there are functions after it, it will not load.

Collapse
 
pesteaux profile image
pesteaux

Hi I am having the same problem and can't get around it. I am stuck on this error. Did anyone get a fix? The name/channel seems to be key but I can't get a working combination. I don't understand the user who said the nick is the channel.

Collapse
 
erosika profile image
erosika • Edited

Not sure if its actually an issue to be stuck on "Loading .env environment variables…" because I can continue with the rest of the code, and my bot does go online.

This happens when my Bot_Nick and Channel are the same. Before making my Bot_Nick the same as my channel name, I was having the "channel does not exist" error. If I make my Bot_Nick my channel name, it doesn't seem to matter what the Channel input is, because the bot still goes online as my channel name.

Would love to see this fixed because it's very easy to get running otherwise!

Collapse
 
lukasdim27 profile image
Lukas Dimitroff

Bot_Nick is not a nickname, it is the name of the channel.

Collapse
 
zakdugie profile image
Dugie

Same problem, eventually when trying to abort it prints this error:
C:\Users\User.virtualenvs\Chatbot_work--fd3mIVH\lib\site-packages\twitchio\websocket.py:618: RuntimeWarning: coroutine 'WebSocketCommonProtocol.close' was never awaited
self._websocket.close()

Collapse
 
xninjarose profile image
Ninja | Rose [A+,Net+]

If it says nothing more and your still at beginning of tutorial, then you did it right, it's in the channel, do the next step and it should put a message in chat like it says in tutorial

Collapse
 
phyrexxii profile image
Sam

i get this error

Traceback (most recent call last):
File "B:\ChatLoyalty\ChatLoyalty.py", line 7, in
irc_token=os.environ['TMI_TOKEN'],
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\os.py", line 675, in getitem
raise KeyError(key) from None
KeyError: 'TMI_TOKEN'

what am i doing wrong?

Collapse
 
spiringosu profile image
Spiring

I figured this out. What you want to do is put in what is in these quotations for each of the environments into bot.py instead of .env.
"os.environ['TMI_TOKEN']=
os.environ['CLIENT_ID']=
os.environ['BOT_NICK']=
os.environ['BOT_PREFIX']=
os.environ['CHANNEL']=
"
For some reason, the OP didn't specify how to call the .env file before it tries to run the rest of bot.py, but doing that eliminates the need for .env

Collapse
 
sunnybirdboi profile image
sunnybirdboi

I'm getting the same issue and cannot figure out where to put your solution. I've tried putting the .env info directly into bot.py as variables to eliminate the need for the .env, and I still get the KeyError despite any changes I make. Where am I putting this info to fix this problem? Thank you!

Collapse
 
space__cdt profile image
Space Cadet

Hey y'all! Like most of you I ended up here and had trouble getting the channel to connect.

What you want to do is lead the channel name with a "#" in your env file.

For instance:

CHANNEL="#space_cdt"

After this I was able to connect!

Collapse
 
spiringosu profile image
Spiring

Could you be a little more specific? Doing this still leads to having it not set the correct channel name,

Collapse
 
cgusb profile image
Gus Becker

This is more likely an error with you TMI token or Client ID. Make sure both are generated using your bot's Twitch account and not your personal Twitch account.

Collapse
 
xdnuggets profile image
Nuggets • Edited

It keeps saying "Make sure channel exists. I have tried the url type, twitch.tv/channelname, and just the channel name. I have made a new oauth, and tried everything I can. EDIT: Just looked at the other comments, and figured out that bot_nick needs to be the channel name, so what do I put at CHANNEL=?

Collapse
 
cgusb profile image
Gus Becker

BOT_NICK is the channel name of the bot account, CHANNEL is the channel name of the channel whose chat you'd like the bot to join. Just the usernames, don't use the "twitch.tv/" prefix.

Collapse
 
space__cdt profile image
Space Cadet

you need to define CHANNEL in your .env file like this:

CHANNEL="#channel_name"

Collapse
 
kicksent profile image
Nick Trierweiler

To everyone with the error:
self._websocket.close()
If you scroll up there should be an earlier error saying:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1097)

To resolve this I used this: gist.github.com/marschhuynh/31c937...

Simply copy this into another python file called install_ssl_certs.py and run it with
pipenv run python install_ssl_certs.py

After doing this I was able to connect and got the message: Ready | frenchtoastbot_

Collapse
 
chreaus profile image
Chreaus • Edited

this wound up working great! ty for the start :) what section of the api docs did you find these?

EDIT:nvm... i just figured it out... you need to use the Account name as the NICK not the botname... might help if you make that a bit more clear in the instructions.

I'm having the same issue as Jordan and Cai...

I think its safe to assume it is connecting to twitch API but something about the channel name variable is not working.

I created a new twitch account just for the bot and registered the application on that account.

I have tried with a different channel (a friends) to no avail.

I have checked and double checked my oAuth and Client-ID and they're both correct.
My (4) files are all in the same directory. (changing the channel name changes name in the error so pipenv is definitely working from the correct .env and other files...)

could you maybe post a "throw away" screen cap of what its supposed to look like all filled out? maybe its a simple syntax derp that i'm missing... i'm currently not using " marks or anything else after the = in the .env file.

-error return below-

PS C:\Users\thato\Documents\Python Files> pipenv run python bot.py
Loading .env environment variables…
Task exception was never retrieved
future: exception=KeyError('chreaus')>
Traceback (most recent call last):
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 558, in join_action
cache = self._channel_cache[channel]['channel']._users
KeyError: 'chreaus'
Task exception was never retrieved
future: exception=KeyError('chreaus')>
Traceback (most recent call last):
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 558, in join_action
cache = self._channel_cache[channel]['channel']._users
KeyError: 'chreaus'
Task exception was never retrieved
future: exception=TimeoutError('Request to join the "chreaus" channel has timed out. Make sure the channel exists.')>
Traceback (most recent call last):
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 280, in _join_channel
await asyncio.wait_for(fut, timeout=10)
File "c:\users\thato\appdata\local\programs\python\python37\lib\asyncio\tasks.py", line 449, in wait_for
raise futures.TimeoutError()
concurrent.futures._base.TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 228, in auth_seq
await self.join_channels(channels)
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 271, in join_channels
await asyncio.gather(
[self._join_channel(x) for x in channels])
File "C:\Users\thato.virtualenvs\Python_Files-vA_Pk7W6\lib\site-packages\twitchio\websocket.py", line 285, in _join_channel
f'Request to join the "{channel}" channel has timed out. Make sure the channel exists.')
concurrent.futures._base.TimeoutError: Request to join the "chreaus" channel has timed out. Make sure the channel exists.

Collapse
 
jordoosu profile image
Jordan • Edited

I keep trying to run the bot but get the error: KeyError: 'jordo1'.

asyncio.exceptions.TimeoutError: Request to join the "jordo1" channel has timed out. Make sure the channel exists.

My channel certainly exists. I tried it with both Python 3.7 and 3.8. My code is basically the same, but I made my own class inheriting Bot instead.

I regenerated my oauth and reconfirmed my client ID.

Please help. Driving me nuts for hours.

Edit: Just realized the bot is working but this error still appears despite joining the channel. Strange. The nick isn't working though, it's just using my twitch username.

Collapse
 
dunkelweizen profile image
Cai Nowicki

I'm getting the same error and resolution. And I can't get any of the bot.command functions to work, even with copy/pasting the code given here. If I fold it inside the event_message function it works, but not as its own thing.

Collapse
 
cgusb profile image
Gus Becker

Hi all! After some headaches with this yesterday, I wanted to make some clarifications that would have helped me when I started trying to make my bot!
1) The TMI token and Client ID should both be generated using the Twitch account you set up for your bot. If you are having the "channel does not exist" error, try re-registering your app with Twitch dev and make sure you save the changes and get the updated Client ID! If you are using a personal computer as opposed to a web server, make sure for the entry box "OAuth Redirect URLs" you are entering "localhost" (no quotes).
2) The .env file is a way to keep your TMI token and Client ID secret even if you use version control software like Git to store your code somewhere like GitHub. You need to have a Python package called dotenv to load these variables into your bot.py file. To download this package, you can do it using pip with the command pip install python-dotenv. You then need to import the function load_dotenv() from the package at the top of your file. This can be done by including from dotenv import load_dotenv with all your other package imports at the top of the file. Then you need to call the load_dotenv() function at the top of your bot.py file (below the imports but above the os.environ calls. This allows os to properly import those variable from the .env file. If you don't want to download dotenv, you can list these variables directly in bot.commands(), but realize that if you do this, you shouldn't share this code publicly because someone else getting their hands on the TMI token and Client ID would allow them to control your bot.
3) The variables in the .env file should be as follows:
TMI_TOKEN=oauth:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
BOT_NICK=BotChannelName
BOT_PREFIX=!
CHANNEL=ChannelNameOfChatToEnter
Important note: BOT_PREFIX refers to the prefix of the commands that the bot will respond to. Most Twitch bots use "! " (e.g. !discord), so it's probably a good idea to keep it as a single exclamation mark. A lot of comments say to use you bot's channel name, but this will make it so that your bot doesn't respond to commands!
4) When testing your bot, you may want to edit the code in your bot.py file. To do this, you must stop the code from executing and re-execute the code to update the bot with the new info in the saved bot.py file. To do this, go to the command line that your prompts are run from and hit Crtl + C. This will stop the execution and allow you to re-execute.

I hope this helps anybody that might be confused in ways similar to how I was!

Collapse
 
robbieb212 profile image
RobbieB212

Still says channel not found for me, do I put my channel name in the "channel" variable?

Collapse
 
cgusb profile image
Gus Becker

Make sure you are using the TMI token and Client ID for your bot channel and not your personal Twitch account. BOT_NICK is the channel name of your bot and CHANNEL is the channel name of the account whose chat you'd like the bot to join.

Collapse
 
space__cdt profile image
Space Cadet

you need to define CHANNEL in your .env file like this:

CHANNEL="#channel_name"

Collapse
 
runneypo profile image
runneypo

I'm having trouble registering an app on the dev.twitch.tv/console/apps/create, using localhost gives me Cartman.GetAuthorizationToken: 401: {"code":401,"status":"invalid oauth token"}, any idea what I'm supposed to do to get it to work?

Collapse
 
ericeberhart profile image
Eric_Eberhart

Creating a Twitch Bot with Python

To create a Twitch bot using Python, we'll utilize the twitchio library, which provides easy-to-use functionality for interacting with the Twitch API. Follow these steps to get started:

Install Required Packages:
First, install the twitchio library using pip:

Copy code
pip install twitchio
Create a Twitch Account:
If you haven't already, create a Twitch account that you'll use for your bot.

Generate OAuth Token:
Generate an OAuth token for your bot by visiting the Twitch Chat OAuth Password Generator (twitchapps.com/tmi/). Log in with your bot's Twitch account and copy the OAuth token generated.

Write the Bot Code:
Now, let's write the Python code for our Twitch bot:

python
Copy code
import twitchio
import os

Twitch Bot Configuration

BOT_NICK = 'your_bot_username'
CHANNEL = 'channel_to_join'
TOKEN = 'your_oauth_token'

Bot Class

class Bot(twitchio.Client):
async def event_ready(self):
print(f'Bot is ready! Joining channel {CHANNEL}')
await self.join_channels(CHANNEL)

async def event_message(self, message):
print(f'Received message in {message.channel.name}: {message.content}')
Enter fullscreen mode Exit fullscreen mode




Run the Bot

bot = Bot(
irc_token=TOKEN,
nick=BOT_NICK,
prefix='!',
initial_channels=[CHANNEL]
)
bot.run()
Replace 'your_bot_username', 'channel_to_join', and 'your_oauth_token' with your bot's Twitch username, the channel you want the bot to join, and the OAuth token you generated, respectively.

Run the Bot:
Save the Python code to a file (e.g., twitch_bot.py) and run it using Python:

Copy code
python twitch_bot.py
Test Your Bot:
Your Twitch bot should now be running and connected to the specified channel. Test it out by sending messages in the Twitch chat and observing the bot's responses in the console.

Extend Functionality:
You can extend your bot's functionality by adding event handlers for specific Twitch events, such as new messages, subscriptions, or channel raids. Refer to the twitchio documentation for more information on available events and methods.

By following these steps, you can create a simple Twitch bot using Python and start experimenting with custom commands and interactions in your Twitch channel.

Collapse
 
beardfacefacebeard profile image
beardfacefacebeard • Edited

when i run the bot.py my terminal prompt replies:
Loading .env environment variables...

and thats it. never says anything else. it DOES join the channel, it DOES respond to the !test command (and i made a couple dopey simple commands to test out as well). it feels like if i try to run !test back to back, it wont issue the command the second time but if i use a second command then !test again, it will show up. same thing with another command. the bot never says it has landed in the chatroom, it doesnt display any chat text within the terminal window. the article is slightly older at this point so my python version is 3.10 but im not sure how much that would have an effect.. i even added to the imports asyncio just in case to no avail.

any help would be marvelous.. if there is anything anyone would like to see that may be helpful let me know but im not seeing any errors or anything else to really have something to show other than the inital 'loading .env etc..'

thanks everyone

Collapse
 
wilverengame profile image
Wilveren

I'm at the "Greet the chat room!" step in the tutorial, and I'm not getting anything out of it. The terminal says "loading .env environment variables..." and that's all. Nothing is printed in either the terminal, or my chat. My .env file looks like this, with the token and ID masked, of course:

TMI_TOKEN=oauth:***************
CLIENT_ID=**************
BOT_NICK=SapphireHerald
BOT_PREFIX=!
CHANNEL=Wilveren

My bot.py looks almost exactly the same, with the exception that, per the comments below, "irc_token" has been replaced with "token"

I also don't have a redirect URL, just localhost
I was told I have to build a website, but does that not apply with this method?

Collapse
 
jarelef profile image
Jarelef • Edited

Greetings
Cool bot.
The question is how to receive commands in private messages?
example "/w @botname !command"
There is an idea to create a mafia game for twitch chat, but there some players have to write commands to the bot in private messages so that their roles are not easily revealed

Collapse
 
jarelef profile image
Jarelef

Nobody knows?

Collapse
 
restingbeardface profile image
RestingBeardFace

Hey there, I just found this now and am trying to get it to work. I am getting an error: TypeError: Bot.init() missing 1 required positional argument: 'token'

I have seen a couple of the posts / people experiencing it and have tried some of the comments associated on the chain but been unable to fix, please help!

Collapse
 
doctorpizzamd profile image
DoctorPizzaMD • Edited

Inside your bot = commands.Bot() function the "tmi_token" variable needs to be changed to "token". My guess is that twitchio probably changed something since this post was made, seeing as it's a couple years old at this point. But this is just a guess.

The commands.Bot() function call is expecting the "token" argument to be present, and since it's not, due to the instructions saying "tmi_token" the call is failing.

Edit: I'm trying to upload an image, but it's not letting me.

It should look like this: imgur.com/oaAMC1t

Collapse
 
nisha550png profile image
nisha550-png

Traceback (most recent call last):
File "bot.py", line 11, in
initial_channels=[os.environ['CHANNEL']]
TypeError: init() missing 1 required positional argument: 'token'

Facing pipenv run python bot.py

Collapse
 
xtimemaster profile image
Carlos Castro

It was working properly an then got this error
Traceback (most recent call last):
File "bot.py", line 11, in
initial_channels=[os.environ['CHANNEL']]
TypeError: init() missing 1 required positional argument: 'token'

Collapse
 
jacouby profile image
EkoDoesntDev

Keep getting this error, have looked at the comments and everything people say seems to be correct. Please help cause this is confusing me very much.

Task exception was never retrieved
future: exception=TimeoutError('Request to join the "josh_liv3" channel has timed out. Make sure the channel exists.')>
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/twitchio/websocket.py", line 280, in _join_channel
await asyncio.wait_for(fut, timeout=10)
File "/usr/lib/python3.8/asyncio/tasks.py", line 501, in wait_for
raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/twitchio/websocket.py", line 228, in auth_seq
await self.join_channels(channels)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/twitchio/websocket.py", line 271, in join_channels
await asyncio.gather(
[self._join_channel(x) for x in channels])
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/twitchio/websocket.py", line 284, in _join_channel
raise asyncio.TimeoutError(
asyncio.exceptions.TimeoutError: Request to join the "josh_liv3" channel has timed out. Make sure the channel exists.

Collapse
 
ryanma1 profile image
RyanMa1

FOR THOSE HAVING "Make sure channel exists." make sure your "BOT_NICK" is the name of your bot account. Also make sure the "CHANNEL" is the name of the channel you're trying to join. For "BOT_PREFIX" I just put the same name as my bot_NICK. If this works let me know! I had spent some time on this issue because of the confusion on this discussion post.

Collapse
 
cgusb profile image
Gus Becker

For anybody reading, BOT_PREFIX should be the prefix used for your bot commands. Most often on Twitch, bot commands start with "!" which I believe is why the original author has the line BOT_PREFIX=!

Collapse
 
fsncryo profile image
Cameron Phillips

hey, my bot runs and displays the arrival message (in twitch chat)
but it doesn't execute any commands I've tried printing ctx.author.name.lower() before the check to see if the message was from the bot and it only prints out a name when the bot types the arrival command.

Collapse
 
cgusb profile image
Gus Becker

I had this issue too! My problem was that I was replacing the line BOT_PREFIX=! in the file .env with an incorrect value. This line tells the bot to look for commands that start with the value passed, so if you are trying to execute a command that starts with an exclamation mark (e.g. !discord), don't change this line!

Collapse
 
stevoisiak profile image
Stevoisiak • Edited

Why does event_ready() use send_privmsg() instead of channel.send()?

The method documentation says privmsg "should only be used directly in rare circumstances where a twitchio.abcs.Messageable is not available."

Collapse
 
aaronfranchi profile image
Aaron Franchi

I apologize in advance for maybe not being as clear as someone more advanced, I do not have advanced programming knowledge. I would like to add pygame functionality to this bot. Where I'm caught up is in basically having to do with the main loop. Either my pygame stuff works one time then everything is limited to the bot or my pygame stuff is looped without the bot loading. Anyone able to provide any guidance on this matter?

Collapse
 
cgusb profile image
Gus Becker

Did you solve your problem? Sounds like a cool use for a bot! Since the loops are getting you caught up, maybe it would be better to take an OOP approach similar to the example used in the official docs: twitchio.readthedocs.io/en/latest/...

Collapse
 
bigmancallum profile image
Callum

What do I put in the "channel" section in the .env?

If I put my channel name it says.
asyncio.exceptions.TimeoutError: Request to join the "[my channel]" channel has timed out. Make sure the channel exists.

Help?

Collapse
 
realfollowersau profile image
harry

The videos a user has viewed on TikTok are those they've marked as "loved." These favored videos are stored in a dedicated "likes" section on the user's profile, which can be set as either public or private. buy tiktok likes real

Collapse
 
mimmz86 profile image
Mimmz86 • Edited

So, I've had to make a few minor edits to my code to make it work and it feels appropriately held together with duct tape and bubblegum, but I'm recieving an "AttributeError: 'funtion' object has no attribute 'run'" when I go to run my code. I take it as a good sign its running into an error so far into the code, but I'm unsure how to proceed. Currently my run code reads

def bot():
@bot.event
async def event_ready():
print(f"{os.environ['BOT_NICK']} is online!")
ws = bot._ws
await ws.send_privmsg(os.environ['CHANNEL'], f'/me has landed!')

if __ name __ == "__ main __":
bot.run()

(Spaces where needed for clarity)

If anyone can help, I'd be sincerely appreciative.

Collapse
 
sethminecraft profile image
SethMinecraft

It says that the twitchio module isn't found. I also looked in the directory I ran the commands in, and there's no pipfile.lock

Collapse
 
cgusb profile image
Gus Becker

Install the TwitchIO module using pip on Windows with the command py -m pip install twitchio. To install on Mac/Linux, I believe simply pip install twitchio should do the trick.

Collapse
 
airplanegobrr profile image
AirplaneGoBrr

How do you add more then 1 channel?

Collapse
 
seanlodhammar profile image
Sean Lodhammar

Just wanted to ask, what do you fill in for the 'CHANNEL' variable in the .env file?

Collapse
 
xdnuggets profile image
Nuggets

Can I change the name of the bot? My friend doesent want it to be called after me!

Collapse
 
nolagnarwhal profile image
Anton Overby

I had to make a new Twitch account for my bot in order to change the name per the advice I found here: discuss.dev.twitch.tv/t/twitch-cha...

The bot will use the name that the OAuth token is assigned to.

Collapse
 
divitotommaso profile image
DiVitoTommaso

how to send whispers?

Collapse
 
insannee profile image
1nsannee

how do I add this bot to multiple channels ??

Collapse
 
sive profile image
Sive

Got this working today, wow. This is beautiful. Thank you!

Collapse
 
teslamax profile image
Ryan Rasmussen

How would I daemonize this script. I'd like to run a few at a time to manage different channels.

Currently I have each run detached using screen.

Collapse
 
newbiesaurus profile image
Newbiesaurus

So I'm able to connect to twitch and see the bot in chat but when it comes to the @bot.event nothing happens. It doesn't print in the terminal or in the twitch chat.