Motivation

On the Subject of Talent - this is originally for artists, but I believe it applies to programmers really well too.

Recording

Workshop Recording

Tools

  • https://replit.com Account - This is where we will be hosting the bot and programming it.
  • Discord Test Server - To test our bot and its various commands.

Setup

Replit.com Setup

We’ll be using https://replit.com to code our discord bot. This is an IDE that is built into the browser, so it will allow us to create our bot without having to host it on our PC.

To start, make an account and create a new Python project on https://replit.com. Next, open main.py and type the following on the first line:

from discord.ext import commands

This command will allow us to utilize the discord.py library and create our bot.

Grabbing the Token

If you don’t have an account on Discord, make one first. Then, once you have an account we need to make a test server. This is where we will invite the bot and test out its commands.

To begin setting up your bot, go to this page: Discord Developer Page and click on “new application” Then, follow these steps:

  • Name and create your bot.
  • Go to bot page on the sidebar and click ‘Add Bot’.
  • Scroll down to ‘TOKEN’ and click on copy. This is the bot’s password we use to login into it.
  • Be careful to NEVER share the token, or your bot could be stolen.
  • Head back to replit.com and go to the secrets panel (lock icon on the left side).
  • Create a key called “password” and paste your token there. Make sure to never make it public - or else your token might get stolen.
  • In main.py, add the following:
import os
bot = commands.Bot(command_prefix='!')
password = os.environ['password']
bot.run(password)

This will allow your bot to access the token so that it can run. NOTE : If at any point your code returns an error despite having the same exact code as the tutorial, you can try typing ‘kill 1’ in the client and pressing enter. This will clear the container and will fix any discord rate limit related problems.

Bot Permissions

Now we will give our bot permissions so that it can carry out the commands we create for it.

  • Go back to the Discord Developers page
  • 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 ‘Read messages/View Channels’ and ‘Send Messages’.

Adding Bot to Server

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. Be careful where you’re adding it!

Workshop

First Task : Hello World

Let’s start off with a simple !hello command that will say hello to the user calling it! Our function will accept a parameter ctx that is taken when the user calls the command on Discord, and we’ll use ctx to get the name of the user. This will also familiarize you with with the basic structure of a command and string manipulation.

First we will have our bot send a message with the traditional programming greeting of ‘hello world!’.

Add this snippet of code under the line that says bot = commands.Bot(command_prefix=’!')

@bot.command()
async def hello(ctx):
    await ctx.send("hello world!")

Now run your bot and test it out in your discord test server. Isn’t that cool? The “async” before the function header lets our program deal with stuff that may take a while to run. It lets other commands run while it is running, so we can wait more efficiently.

Now we will make this command a bit more in depth by making it greet the user that called the command!

In the definition of hello() that we just wrote, change it so that it matches this snippet of code:

@bot.command()
async def hello(ctx):
    await ctx.send("hello " + ctx.author.display_name)

Now run your bot and test the command out in your Discord test server. It should now display your username after the ‘hello’!

Second Task : Cat Videos

Next we will make a command to give us a randomly chosen cat video out of a list we will be making.

Add this line of code under the line bot = commands.Bot(command_prefix=’!’)

bot.videos = ['https://www.youtube.com/watch?v=XmoKM4RunZQ', 'https://www.youtube.com/watch?v=qTmjKpl2Jk0', 'https://www.youtube.com/watch?v=hY7m5jjJ9mM']

This will be the list of cat videos we will be pulling from to send to the user. You can either use the links provided in our example list, or go on YouTube and find your own!

Also add this line of code under import os

import random

random allows us to generate random numbers, which we will have our bot use to choose which cat video to send to us.

Add this snippet of code under the definition of hello() that we previously wrote:

@bot.command()
async def cat(ctx):
    await ctx.send(random.choice(bot.videos))

The command random.choice allows use to choose a random object from a list that we pass in. We pass in bot.videos so that it can pull a random video from the bot.videos list to send to the user.

Now, the user can call !cat and the bot will give them a cat video.

Third Task : Happy and Sad

Let’s create a wholesome bot that makes people happy!

In this task we will create two commands: !happy and !sad

  • !happy: Takes in an input of something that makes the user happy and stores it in a list.
  • !sad: Takes a random item from that list and prints out that item.

First, we need a list to store our happy objects! Under bot.videos, declare and initialize a new variable as such:

bot.happylist = []

For the !happy command, add this snippet of code under our previous definition of the cat() command:

@bot.command()
async def happy(ctx, *, item):
    await ctx.send("Awesome!")
    bot.happylist.append(item)
    print(bot.happylist)

As you can see, the inputs for our happy() function are slightly different. The * allows us to type an input into the command, and our input gets stored in the item variable to be used later.

Then, our command gets the item variable that stored our input and appends it to our list, meaning that it adds it to the list. To help us keep track of the items in our list, the print statement in the function will print our current list into the console.

For the !sad command, add this snippet of code under our definition for happy:

@bot.command()
async def sad(ctx):
  await ctx.send("Hope this makes you feel better!")
  await ctx.send(random.choice(bot.happylist))

This command is more straightforward. We are getting all the happy things we added to the happylist and choosing a random one with the random.choice() function.

Fourth Task : Calculator

We’re now going to add the !calc command, which will enable us to do the four standard calculator operations. This command will help us learn about collecting inputs and how to branch accordingly based on those inputs.

Copy the following function into your code:

@bot.command()
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")

Notice that we had to add more parameters after ctx, as we are dealing with multiple inputs for our command. So if we restart our bot and ask it !calc 7 + 6, it will respond with 13.

This code can be shortened by having python automatically convert the input numbers from strings to floats. Currently, all inputs are strings by default, so in order to fix this, we can change our function heading and remove the conversion we wrote for x and y within our command’s definition. This is what the new function heading should look like:

async def calc(ctx, x: float, fn: str, y: float):

So, now your command should look like this:

@bot.command()
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")

And there you have it! You now have a custom Discord bot that you can continue to add commands to and cusomize to your liking! You could also use your new knowledge to try adding more functionality to some of the above commands.

Learn More About Chatbots

Learn More About Python Concepts

Contributors: Nehal, Savannah, Harsh, Maaheen