How to write a Discord bot in Python

In this tutorial, you'll learn to create a simple Discord bot with Python.
In case you don't know what Discord is, it is a Slack-like service aimed at gamers essentially.

In Discord, you can join multiple servers, and you must have noticed that these servers have many bots.
These bots can do a lot of things, from playing music for you to simple chat moderations.
I was really fascinated by these bots, so I decided to write one of my own using Python.
So, let's jump right in!

Related article

SET UP

Let's first create out bot's account.
Head over to https://discordapp.com/developers/applications/me and create a new app.
Give your bot a fancy name and give it a profile picture.

enter image description here

Scroll down and click on "Create Bot User".
Once done, you can get the secret bot token.

enter image description here

And now you can click to reveal bot toke.

enter image description here

NEVER share this token with anyone, because with they can hijack your bot.
Soon after writing this I will change the token.

CODE

Now the fun begins.

Prerequisites

Discord.py (rewrite)

Now we're going to install the rewrite version of the discord.py library.
The discord.py on pip is not actively maintained, so install the rewrite version of the library.

$ python3 -m pip install -U https://github.com/Rapptz/discord.py/archive/rewrite.zip

To check what version of discord.py you're using,

>>> import discord
>>> discord.__version__
'1.0.0a'

Now that we are set, let's down to writing the bot.

import discord
from discord.ext import commands

If this gives ModuleNotFoundError or ImportError then there's something wrong with your discord.py installation.

bot = commands.Bot(command_prefix='$', description='A bot that greets the user back.')

The command prefix is what the message content must contain initially to have a command invoked.

@bot.event
async def on_ready():
    print('Logged in as')
    print(bot.user.name)
    print(bot.user.id)
    print('------')

on_ready() called when the client is done preparing the data received from Discord.
Usually after bot's login is successful.

Now let's add some functions to our bot.

@bot.command()
async def add(ctx, a: int, b: int):
    await ctx.send(a+b)

@bot.command()
async def multiply(ctx, a: int, b: int):
    await ctx.send(a*b)

@bot.command()
async def greet(ctx):
    await ctx.send(":smiley: :wave: Hello, there!")

@bot.cmmands()
async def cat(ctx):
    await ctx.send("https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif")

Before running it, the bot must be invited to your server.
This OAuth2 url can be generated from your bot's settigns page.
Head over to https://discordapp.com/developers and click on your bot's profile and generate the oAuth2 url.

Imgur

This is where you'll decide what permissions to give tothe bot.
For our usage right now, we will just need permission to send messages.

Now run the bot by running this in command-line.

$ python bot.py

Imgur

Now, let's test out bot.

Imgur

Imgur

There's a list of good practices that should be followed while making a Discord bot.
I suggest you read the entire document here https://github.com/meew0/discord-bot-best-practices

Have an info command.
It should provide information about the bot such as what framework it is using and the used version, help command and, most importantly, who made it.

@bot.command()
async def info(ctx):
    embed = discord.Embed(title="nice bot", description="Nicest bot there is ever.", color=0xeee657)
    
    # give info about you here
    embed.add_field(name="Author", value="<YOUR-USERNAME>")
    
    # Shows the number of servers the bot is member of.
    embed.add_field(name="Server count", value=f"{len(bot.guilds)}")

    # give users a link to invite thsi bot to their server
    embed.add_field(name="Invite", value="[Invite link](<insert your OAuth invitation link here>)")

    await ctx.send(embed=embed)

Imgur

The discord.py generates an help command automatically.
So, to write our own, we would first have to remove the one given by it.

bot.remove_command('help')

Now we can write our own help command. Here you decribe usage of your bot.

@bot.command()
async def help(ctx):
    embed = discord.Embed(title="nice bot", description="A Very Nice bot. List of commands are:", color=0xeee657)

    embed.add_field(name="$add X Y", value="Gives the addition of **X** and **Y**", inline=False)
    embed.add_field(name="$multiply X Y", value="Gives the multiplication of **X** and **Y**", inline=False)
    embed.add_field(name="$greet", value="Gives a nice greet message", inline=False)
    embed.add_field(name="$cat", value="Gives a cute cat gif to lighten up the mood.", inline=False)
    embed.add_field(name="$info", value="Gives a little info about the bot", inline=False)
    embed.add_field(name="$help", value="Gives this message", inline=False)

    await ctx.send(embed=embed)

Imgur

CONGRATULATIONS! You've just created a Discord bot written in Python.

HOSTING

For now, the bot will only be online till you're running the script.
So, in case you want your bot to run all the time, you have to host it online or you can also host it locally, for example on a RaspberryPi.
Hosting services range widely from Free(Heroku's free tier) to Paid(Digital Ocean).
I run my bot on Heroku's free tier, and haven't faced any issue so far.

Source code

import discord
from discord.ext import commands

bot = commands.Bot(command_prefix='$')

@bot.event
async def on_ready():
    print('Logged in as')
    print(bot.user.name)
    print(bot.user.id)
    print('------')

@bot.command()
async def add(ctx, a: int, b: int):
    await ctx.send(a+b)

@bot.command()
async def multiply(ctx, a: int, b: int):
    await ctx.send(a*b)

@bot.command()
async def greet(ctx):
    await ctx.send(":smiley: :wave: Hello, there!")

@bot.command()
async def cat(ctx):
    await ctx.send("https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif")

@bot.command()
async def info(ctx):
    embed = discord.Embed(title="nice bot", description="Nicest bot there is ever.", color=0xeee657)
    
    # give info about you here
    embed.add_field(name="Author", value="<YOUR-USERNAME>")
    
    # Shows the number of servers the bot is member of.
    embed.add_field(name="Server count", value=f"{len(bot.guilds)}")

    # give users a link to invite thsi bot to their server
    embed.add_field(name="Invite", value="[Invite link](<insert your OAuth invitation link here>)")

    await ctx.send(embed=embed)

bot.remove_command('help')

@bot.command()
async def help(ctx):
    embed = discord.Embed(title="nice bot", description="A Very Nice bot. List of commands are:", color=0xeee657)

    embed.add_field(name="$add X Y", value="Gives the addition of **X** and **Y**", inline=False)
    embed.add_field(name="$multiply X Y", value="Gives the multiplication of **X** and **Y**", inline=False)
    embed.add_field(name="$greet", value="Gives a nice greet message", inline=False)
    embed.add_field(name="$cat", value="Gives a cute cat gif to lighten up the mood.", inline=False)
    embed.add_field(name="$info", value="Gives a little info about the bot", inline=False)
    embed.add_field(name="$help", value="Gives this message", inline=False)

    await ctx.send(embed=embed)

bot.run('NDE0MzIyMDQ1MzA0OTYzMDcy.DWl2qw.nTxSDf9wIcf42te4uSCMuk2VDa0')

Related article


📣 Sponsored

BoostIO launches a funding/sourcing platform for open-source projects called IssueHunt for sustainable OSS ecosystem.

Anyone can fund any issues on GitHub and these money will be distributed to maintainers and contributors.

https://issuehunt.io/

image

AUTHOR

Will you have a tutorial on how to host? I'm kind of lost in this part.

@vagner2k18 you need to do bot.run('<your token here>') at the end of your setup code

7 months ago

Good job!

How about an update?

but Nice

I'm working on a mac and so had to use "Install Certificates.command" for this to work. You find this file in the Python 3.6 Application folder.

about 2 months ago

I become a error. runfile('C:/Users/Luca/Documents/Python_DC_BOT/eigen/main.py', wdir='C:/Users/Luca/Documents/Python_DC_BOT/eigen') Traceback (most recent call last): File "<ipython-input-1-c851fb6d342a>", line 1, in <module> runfile('C:/Users/Luca/Documents/Python_DC_BOT/eigen/main.py', wdir='C:/Users/Luca/Documents/Python_DC_BOT/eigen') File "C:\Users\Luca\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile execfile(filename, namespace) File "C:\Users\Luca\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace) File "C:/Users/Luca/Documents/Python_DC_BOT/eigen/main.py", line 49, in <module> bot.run(TOKEN) File "C:\Users\Luca\Anaconda3\lib\site-packages\discord\client.py", line 572, in run loop.close() File "C:\Users\Luca\Anaconda3\lib\asyncio\selector_events.py", line 107, in close raise RuntimeError("Cannot close a running event loop") RuntimeError: Cannot close a running event loop Kernel died, restarting

about 1 month ago

Where the documentation for this rewrite?

READ NEXT

Boostlog is an online community for developers
who want to share ideas and grow each other.

Delete an article

Deleted articles are gone forever. Are you sure?