- Motivation
- Tools
- Getting Ready
- Workshop
- Go Forth and Make Something
- Open Source License
- Learn More About Chatbots
- Learn More About Python Concepts
- Ethics
- Ideas
- Requirements
Code Repo. Recording (note: after 1 hour stuff it’s just random student questions but not related to the workshop itself)
We all started using online chatting applications more than ever before to communicate with our families, friends, and even classes and work with the pandemic. What if we could make cool bots for these chats? Facebook bots for stores, Discord bots for your friends, or Slack bots for your clubs and jobs. The possibilities are endless.
If you’ve never done python before, here’s a start. Coming from Java or C++, this might seem almost underwhelming, but python allows you to do so many of the same things with a lot less work. This brevity does have disadvantages, but this trait of python makes it an excellent language for trying new ideas and adding to them quickly.
print("Hello Chatbots")
Hosted by: Harsh Deep
Motivation
Learn Python the Hard Way - This is advice I honestly feel everyone new to CS should read and follow.
Keeping that in mind, for this website:
How to Learn Programming the Proper Way
- Every single piece of code that I show, you will type by hand. No copy-pasting, no “I can see what it does, it’s obvious,” no “I already know this, let me move on.” I want you to do this to make sure that you process what we’re learning together. You can only copy-paste if I tell you that you can. Trust me. It may feel like a slight difference, but not following along like this will reduce your learning tenfold.
- Attention to detail: this comes from the last point, but when you type everything out yourself and look at it closely, you’re forced to concentrate on what you’re doing. For example, consider the difference between
5
and"5"
. Programming is exact, and errors like these can create bugs that can be very difficult to track down if you’re not prepared for them, especially in languages like python, every tiny detail matters.
Tools
Set this up before we start.
-
VSCode - Here’s our written guide, but the internet also has a lot of information on it if you need it.
-
git
- install it locally and enter$ git --version
into the terminal/command line to make sure that it’s installed. -
Github - create an account if you don’t have one already.
Getting Ready
You should finish this part before the workshop, but don’t worry if you’re not done since we’re recording everything. All the material is available as text on the website as well.
-
Submit the initial form, which gives us an idea of who all are here. All the forms we’re taking (initial form, final form, project forms) will be for internally tracking how we can improve our content and giving you personalized responses. We might even make some fun visualizations in the end.
-
If you’re on Windows, I highly recommend getting WSL2 (WSL1 is also acceptable, just slower). For historical reasons, the command line in Windows isn’t as good as that of Mac or Linux. Eventually, they just said, “Hey what if we had full Linux on Windows?” Thus, WSL. We will use the command line a fair amount here, so it’s an excellent idea to set it up.
- Install a recent version of python (3.7+) on your computer and make sure to enable
pip
as well.- Windows Guide (select installer and make sure to add to PATH). This guide is pretty useful too.
-
MacOS Guide or try homebrew with
brew install python
- Linux Gudide or try your distro package installer
- Do python –version to check which you got. If it says 2.x, then you will have to use
python3 scriptname.py
andpip3
; otherwise, you’ll end up using older versions of stuff.
-
Set up VSCode or a different code editor of your choice. See the page we wrote for VSCode for help.
-
Install
discord.py
.$ pip install discord.py [install output]
-
Create an account on Discord if you don’t have one already. The principles of making chatbots are the same regardless of platform, but Discord has one of the best support.
- Create a test server on Discord (sometimes called a guild) that you will add your bot to. You can add the bot to a real server once it’s working well, but this is good for debugging. Here’s a guide.
Workshop
First, we’ll create a new folder for the project by typing this into your command line. In general, if there is a $
before a code line, it means that you should run it on your command line. This $ is a convention not just for this site but for programming tutorials in general.
$ mkdir first_discord_bot
$ cd first_discord_bot
mkdir
stands for make directory (another word for folder). This command is how we create a folder in our current directory.
cd
stands for change directory. Here, we’ve already created a folder, and now we’re just entering it. The command-line prompt can only point to one folder at a time, so this is how we change where it’s pointing.
We set up git
in the folder to transform our project into a git
repository.
$ git init
You’ve probably seen git
before. It adds time travel powers to your work. git
lets you put your code on sites like Gitlab, Github and sr.ht.
Now let’s get started with the coding. Let’s open VSCode:
$ code .
Note: Don’t worry too much about the command line or git
just yet. More on that next week :)
Getting the Bot Token
Note: This tutorial also has a good section on getting the Discord bot token.
-
Go to the Discord applications page on your web browser.
-
Click on “New Application” and give it a nice name that you can recognize. Feel free to provide an icon, too, if you want.
-
Go to the Bot page on the side tab and click ‘Add Bot’. This page is for the bot that we’ll be coding that the users will see. Feel free to change its username, but the default one should be fine.
-
Scroll down to ‘TOKEN’ and click the ‘Copy’ button. This token is like your bot’s password, and it’s required for your bot to log in. Tokens are a typical pattern when dealing with APIs and external services (like Discord here). If your token is leaked, make sure to reset it.
-
The important thing is that you should never, ever share this token. One classic mistake people make is accidentally adding it on their online Git repository or storing somewhere that someone can inspect the browser state for it. This paper explains how hundreds of thousands of codebases have made this mistake. We’ll put the token in a separate file and read it from there to deal with this.
-
Now, we’ll make the file for the token. In VSCode, create a file called
BOT_TOKEN.txt
and paste the token into it. Make sure the file only has one line for the token. -
Create a file called
.gitignore
. In the first line, addBOT_TOKEN.txt
. This file tellsgit
to avoid this file and make sure that your token doesn’t end up on the public internet. Once your repo is online, make sure to doublecheck yourself that your token isn’t there just in case.
Adding the Bot to the Test Server
First, we need to generate an invite link to add our bot user to our server. To handle this, we’ll use OAuth2, a typical web standard for managing authentication and identity on the internet.
-
Go back to the Discord developers page. Go to the ‘OAuth2’ tab.
-
Under ‘OAuth2 URL Generator’, go to ‘Scopes’ and select the ‘bot’ checkbox.
-
Now, we have to figure out the list of permissions for our bot. For your actual bot, I highly suggest taking the time to understand this so you can give it the permissions you need, but for the workshop, check off “View Channels” under “General Permissions” and ‘Send Messages’ under ‘Text Permissions’.
-
Based on what you checked off, the invite URL should have updated. Hit ‘Copy’ and paste it in a new tab on your browser.
-
The page will ask you which server to add the bot, and you should pick your test server that we created earlier.
That’s all the setup done. Now let’s get to coding!
Idea bot
The whole point of this eight-week program is to learn how to make projects from start to finish. However, ideas are hard, so for now, how about we make a Discord bot that can give us ideas? We could just type !idea
, and the bot will appear and give us an excellent starting point to get moving. Let’s get started with bot.py
as shown below.
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
with open("BOT_TOKEN.txt", "r") as token_file:
TOKEN = token_file.read()
print("Token file read")
bot.run(TOKEN)
discord.py
is the library that handles many network heavy lifting, allowing us to focus on the bot logic itself. We’re using the commands
module, making it easy to create command bots (bots that respond to commands).
The command_prefix
option lets us pick how the bot’s commands will be called. So if our prefix is $
and our command is version
, then we’d type $version
into the chatbox to call the bot.
Now let’s try running it:
$ python bot.py
(Some systems might need python3
instead of based on your installation)
If this runs with the only output as Token file read
, then the login worked. If you got an error like discord.errors.LoginFailure
, there was something wrong with the token you set up, and I suggest going over the above steps again. When you’re done running it, you can hit ctrl+c to exit.
Now let’s start working on our command.
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
@bot.command(name="idea")
async def idea(ctx):
await ctx.send("Ideas are hard")
with open("BOT_TOKEN.txt", "r") as token_file:
TOKEN = token_file.read()
print("Token file read")
bot.run(TOKEN)
Don’t worry if you don’t fully understand the syntax just yet. This new function combines quite a bit of python syntax that you might have seen here or there. Still, if you try reading it, you can figure out what this code does. Let’s go over it together.
The first concept is decorators. Decorators modify the behavior of a function without changing anything from the inside. Here, the decorator says that this function called idea
is a particular function that should be called when the discord bot sees !idea
in the chat. Check out DataCamp - Decorators in Python to learn more.
async
is a keyword that indicates that this function can run asynchronously. await
tells the program that it can do other things in the meantime while waiting on this command, which is helpful if the given code might take a while or if the program will need to wait for the command to execute. The rule of thumb is that if you want to call an async
function, then you should await
before calling it. If your function uses await
in the body, you add async
to the function signature.
Async+Await combo means we can run this command and then suspend it to do other things and come back. This type of programming is a key concept in computer science called concurrency, and it’s a pretty complicated idea. Here are some links so that you can learn more about it: Python docs - asyncio and Real Python - Async IO.
ctx
is a variable that stands for context, and this abbreviation is a standard convention for context in programming. Using ctx.send()
can send messages into the chat, but you can do lots of things with the context variable to interact with the chatroom.
Anyways, let’s run the program and leave it running. When you’re done, you can hit ctrl+c to exit.
$ python bot.py
Now, if you go to your test server, the server should show your bot as online. If you type in !idea
, you will get back Ideas are hard
. If this works, that means our basic Discord bot is working so far. Now let’s flesh out the function a little.
from discord.ext import commands
import random
bot = commands.Bot(command_prefix='!')
@bot.command(name="idea")
async def idea(ctx):
await ctx.send("Ideas are hard")
await ctx.send("Worry not, I think you should...")
topics = ['chat bot', 'cli', 'game', 'web bot', 'browser extention', 'api', 'web interface']
areas = ['note taking', 'social life', 'physical fitness', 'mental health', 'pet care']
idea = f'Create a new {random.choice(topics)} that helps with {random.choice(areas)}! :slight_smile:'
await ctx.send(idea)
# make sure to create a token file (in real life use env variables)
with open("BOT_TOKEN.txt", "r") as token_file:
TOKEN = token_file.read()
print("Token file read")
bot.run(TOKEN)
So now we’re sending a couple of messages and using random.choice()
to pick elements from a list.
Now restart the bot (unfortunately, it doesn’t automatically update). Exit with ctrl+c, and then you can start it up again and leave it running.
$ python bot.py
Now, if we post !idea
on the server, we should get a response:
Ideas are hard
Worry not, I think you should...
Create a new browser extension that helps with social life! :slight_smile:
Yours might not look the same since this is randomized. If you want to learn more about random
in python, check out Real Python - Generating Random Data in Python (Guide).
Exercise
- Have the idea bot randomly pick a programming language as well. Don’t worry if the combo makes sense. This is to flesh out the program some more.
Calculator Bot
Let’s add another command, calc
, that can do the standard four-function calculator stuff. This new command will help us learn how to collect chatbot inputs and how to have branching accordingly.
@bot.command(name="calc")
async def calc(ctx, x, fn, y):
x = float(x)
y = float(y)
if fn == '+':
await ctx.send(x + y)
elif fn == '-':
await ctx.send(x - y)
elif fn == '*':
await ctx.send(x * y)
elif fn == '/':
await ctx.send(x / y)
else:
await ctx.send("We only support 4 function operations")
We have to add more parameters after ctx
, which will become the program’s inputs. So if I restart my bot:
$ python bot.py
And I ask it !calc 1 - 3
, it responds with -2.0
.
We can shorten this code a bit. Right now, every input comes in like a python string (str
), and then we convert the numbers into float
s for computation. However, python has optional type annotations (most don’t know this), which we can use to our advantage. So if we change our function heading to
async def calc(ctx, x: float, fn: str, y: float):
Then discord.py
will make sure all the conversions are done automatically. To learn more about Python type annotations, check out Using Python’s Type Annotations and mypy.
Exercise
Add **
(to the power of) as an operator onto the calc
command as well. This option will probably involve adding another level of branching. Example: !calc 5**3
should give us 125.0
.
Help Information
Using the decorators can also provide helpful information for users trying to figure out how a bot works.
@bot.command(name="idea", help="Get a side project idea")
@bot.command(name="calc", help="Perform a calculation where fn is either +,-,*, or /")
And (after restart), if we type !help
, we get:
No Category:
calc Perform a calculation where fn is either +,-,*, or /
help Shows this message
idea Get a side project idea
Type !help command for more info on a command.
You can also type !help category for more info on a category.
And if we check for a given command, for example, !help calc
:
!calc <x> <fn> <y>
Perform a calculation where fn is either +,-,*, or /
Now make sure to update everything with git
$ git add bot.py .gitignore
$ git commit -m "Create basic chatbot"
You can follow instructions on Github on how to add a remote
and then using git push
to upload it here.
Final Code
Everything put together, our final code is:
from discord.ext import commands
import random
bot = commands.Bot(command_prefix='!')
@bot.command(name="idea", help="Get a side project idea")
async def idea(ctx):
await ctx.send("Ideas are hard")
await ctx.send("Worry not, I think you should...")
topics = ['chat bot', 'cli', 'game', 'web bot', 'browser extention', 'api', 'web interface']
areas = ['note taking', 'social life', 'physical fitness', 'mental health', 'pet care']
idea = f'Create a new {random.choice(topics)} that helps with {random.choice(areas)}! :slight_smile:'
await ctx.send(idea)
@bot.command(name="calc", help="Perform a calculation where fn is either +,-,*, or /")
async def calc(ctx, x: float, fn: str, y: float):
if fn == '+':
await ctx.send(x + y)
elif fn == '-':
await ctx.send(x - y)
elif fn == '*':
await ctx.send(x * y)
elif fn == '/':
await ctx.send(x / y)
else:
await ctx.send("We only support 4 function operations")
# make sure to create a token file (in real life use env variables)
with open("BOT_TOKEN.txt", "r") as token_file:
TOKEN = token_file.read()
print("Token file read")
bot.run(TOKEN)
Go Forth and Make Something
Every week, we’re going to make one project themed on what we just did. This project workflow will have two stages.
-
Idea - come up with an idea and a set of features (MVP + sprinkles) due every Wednesday. There will be a form linked at the bottom of each article so that you can submit these.
-
Project - submit a form and create a public forum post with your project every Monday. The form for this will also be linked at the bottom of each article.
Open Source License
Many people incorrectly assume that just publicly posting a project on Github makes a project open source. However, you have to add a License to your project explicitly. For all the projects you make, a license is mandatory. Here is a guide to the more popular open-source licenses today. Adding one shouldn’t take more than a few minutes.
If you’re unsure/lazy, you can go for either MIT, ApacheV2, or GPL.
Having a proper open source license on your project makes your project an open-source project! Congrats, and welcome to creating code for all of society.
Learn More About Chatbots
-
FreeCodeCamp: How to Create a Discord Bot for Free with Python – Full Tutorial - good starter tutorial
-
Real Python: How to Make a Discord Bot in Python - this is the most comprehensive tutorial I liked
-
towards data science - How to build your own AI Chatbot on Discord? - more advanced, but this shows how you can start mixing in AI with chatbots as well
Learn More About Python Concepts
-
Decorators - datacamp - decorators in python
-
Concurrency - python docs asyncio and real python - async io.
-
Randomness - realpython - Generating Random Data in Python (Guide).
-
Types - Using Python’s Type Annotations and mypy.
Ethics
- IBM - The code of ethics for AI and chatbots that every brand should follow - taking a look at guidelines and ethical considerations for chatbots
Ideas
Feel free to come up with anything you want as long as it’s chatbot-related. Here are some ideas to help you get started, but feel free to come up with more. Don’t worry if it’s already been done or if someone else is doing it. The point is to learn and have fun. :)
-
Think of a bot you’ve seen in real life. Could you recreate a simple subset of its features?
-
Maybe a bot that could provide the user information, like recipes or sports teams?
-
Or a bot that can have a basic conversation with you. Could it help you break down tasks or provide you with a gratitude journal?
-
Maybe a bot that can automate something you find annoying? So you can use it to fire off commands to do some tasks.
-
The bot doesn’t have to be a Discord bot. You can make it on Slack, Facebook, IRC, or any chat service out there.
Requirements
These aren’t strict requirements, but you should try your best to hit all of them.
-
The chatbot connects to a real chat service, including but not limited to: Discord, Slack, Telegram, IRC, Facebook.
-
It has different responses based on various inputs.
-
Try to get your
pylint
score as good as possible. If you haven’t used it before, check our guide at /pylint. -
This has to be available on a site like Github (feel free to use alternatives like GitLab if you prefer).
-
Show your bot’s images/animations/videos in action in a
README.md
file in your repository. -
Has to use an Open Source license via a
LICENSE
file
Contributors: Harsh, Maaheen