Note : Before you start this tutorial, You should already know the language python, how to create applications in discord and you should've already invited the bot to your server.
Step 1 : Setting up
Create a new folder for your bot, it can be anything. For reference, I will name itSample Bot.
Open upcommand promptorterminaland type the following commands in it.
$ pip install -U discord.py
Now create a new file namedmain.pyin your bot's folder. This file will hold the main bot.
Also create a new directory namedcogsin your bot's directory, this will hold our command groups (aka cogs).
Now you're ready to code
Step 2 : The main bot
Open up yourmain.pyfile. Given below is some basic code with everything explained using comments.
from discord.ext import commands
def get_prefix(client, message):
prefixes = ['=', '=='] # sets the prefixes, u can keep it as an array of only 1 item if you need only one prefix
if not message.guild:
prefixes = ['=='] # Only allow '==' as a prefix when in DMs, this is optional
# Allow users to @mention the bot instead of using a prefix when using a command. Also optional
# Do `return prefixes` if u don't want to allow mentions instead of prefix.
return commands.when_mentioned_or(*prefixes)(client, message)
bot = commands.Bot( # Create a new bot
command_prefix=get_prefix, # Set the prefix
description='A bot used for tutorial', # Set a description for the bot
owner_id=374886124126208000, # Your unique User ID
case_insensitive=True # Make the commands case insensitive
)
# case_insensitive=True is used as the commands are case sensitive by default
@bot.event
async def on_ready(): # Do this when the bot is logged in
print(f'Logged in as {bot.user.name} - {bot.user.id}') # Print the name and ID of the bot logged in.
return
# Finally, login the bot
bot.run('BOT TOKEN here', bot=True, reconnect=True)
Now run this file, commands extension will prepare a defaulthelpcommand for you, you should see something similar to this when you use it: -
Note that it doesn't show help when=helpis used as this was done in DMs, and we only allowed==helpin DMs.
Next we add the commands from thecogsdirectory.
Inside thecogsdirectory, create a new file namedbasic.py.
Add the following code above the
@bot.event
async def on_ready():
part in themain.pyfile
cogs = ['cogs.basic']
This basically points to thebasic.pyfile in thecogsfolder.
Next, change
async def on_ready():
print(f'Logged in as {bot.user.name} - {bot.user.id}')
return
to
async def on_ready():
print(f'Logged in as {bot.user.name} - {bot.user.id}')
for cog in cogs:
bot.load_extension(cog)
return
This will load the all the files specified in the cogs variable.
Next, open up thebasic.pyfile and write the following code in it.
from discord.ext import commands
from datetime import datetime as d
# New - The Cog class must extend the commands.Cog class
class Basic(commands.Cog):
def __init__(self, bot):
self.bot = bot
# Define a new command
@commands.command(
name='ping',
description='The ping command',
aliases=['p']
)
async def ping_command(self, ctx):
start = d.timestamp(d.now())
# Gets the timestamp when the command was used
msg = await ctx.send(content='Pinging')
# Sends a message to the user in the channel the message with the command was received.
# Notifies the user that pinging has started
await msg.edit(content=f'Pong!\nOne message round-trip took {( d.timestamp( d.now() ) - start ) * 1000 }ms.')
# Ping completed and round-trip duration show in ms
# Since it takes a while to send the messages
# it will calculate how much time it takes to edit an message.
# It depends usually on your internet connection speed
return
def setup(bot):
bot.add_cog(Basic(bot))
# Adds the Basic commands to the bot
# Note: The "setup" function has to be there in every cog file
This will add a new ping command to your bot!
Save the file
Step 3 : Checking the new command
Run the main.py again.
Use thehelpcommand. It should look something like this: -
Observe the new Basic category and ping command listed under it. This means that our command was successfully loaded.
Now use thehelp pingcommand, should look something like this: -
Note that in the example, it shows the prefix used by you!
Finally, let's use the ping command.
This is an example run (my internet is a bit slow)
Step 4 : Commands with arguments
Open up thebasic.pyfile and add the following command to it by typing it just below thereturnstatement of the ping command. This is a say command that repeats the words said by the user (in bold): -
@commands.command(
name='say',
description='The say command',
aliases=['repeat', 'parrot'],
usage='<text>'
)
async def say_command(self, ctx):
# The 'usage' only needs to show the parameters
# As the rest of the format is generated automatically
# Lets see what the parameters are: -
# The self is just a regular reference to the class
# ctx - is the Context related to the command
# For more reference - https://discordpy.readthedocs.io/en/rewrite/ext/commands/api.html#context
# Next we get the message with the command in it.
msg = ctx.message.content
# Extracting the text sent by the user
# ctx.invoked_with gives the alias used
# ctx.prefix gives the prefix used while invoking the command
prefix_used = ctx.prefix
alias_used = ctx.invoked_with
text = msg[len(prefix_used) + len(alias_used):]
# Next, we check if the user actually passed some text
if text == '':
# User didn't specify the text
await ctx.send(content='You need to specify the text!')
pass
else:
# User specified the text.
await ctx.send(content=f"**{text}**")
pass
return
Next, let's use this command!
As you can see, works perfectly!
Step 5 : Embeds
Since, we've already done this, let's do one final command. The embed command.
What this command will do?
Ask for the title of the embed.
Ask the user to specify the text for the embed description.
Set a random color to the embed.
Send the embed in the channel
What this will help you learn?
How to create and send embeds.
How to wait for user's response.
In your cogs directory, create a new file namedembed.py
In yourmain.pyfile, to the cogs list which formerly wascogs = ['cogs.basic']add a new cog i.e.'cogs.embed', making it -cogs = ['cogs.basic', 'cogs.embed']. This will tell it to also treat theembed.pyfile as another cog.
Open up theembed.pyfile and write the following code in it: -
from discord.ext import commands
import discord
import random
# These color constants are taken from discord.js library
colors = {
'DEFAULT': 0x000000,
'WHITE': 0xFFFFFF,
'AQUA': 0x1ABC9C,
'GREEN': 0x2ECC71,
'BLUE': 0x3498DB,
'PURPLE': 0x9B59B6,
'LUMINOUS_VIVID_PINK': 0xE91E63,
'GOLD': 0xF1C40F,
'ORANGE': 0xE67E22,
'RED': 0xE74C3C,
'GREY': 0x95A5A6,
'NAVY': 0x34495E,
'DARK_AQUA': 0x11806A,
'DARK_GREEN': 0x1F8B4C,
'DARK_BLUE': 0x206694,
'DARK_PURPLE': 0x71368A,
'DARK_VIVID_PINK': 0xAD1457,
'DARK_GOLD': 0xC27C0E,
'DARK_ORANGE': 0xA84300,
'DARK_RED': 0x992D22,
'DARK_GREY': 0x979C9F,
'DARKER_GREY': 0x7F8C8D,
'LIGHT_GREY': 0xBCC0C0,
'DARK_NAVY': 0x2C3E50,
'BLURPLE': 0x7289DA,
'GREYPLE': 0x99AAB5,
'DARK_BUT_NOT_BLACK': 0x2C2F33,
'NOT_QUITE_BLACK': 0x23272A
}
class Embed(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(
name='embed',
description='The embed command',
)
async def embed_command(self, ctx):
# Define a check function that validates the message received by the bot
def check(ms):
# Look for the message sent in the same channel where the command was used
# As well as by the user who used the command.
return ms.channel == ctx.message.channel and ms.author == ctx.message.author
# First ask the user for the title
await ctx.send(content='What would you like the title to be?')
# Wait for a response and get the title
msg = await self.bot.wait_for('message', check=check)
title = msg.content # Set the title
# Next, ask for the content
await ctx.send(content='What would you like the Description to be?')
msg = await self.bot.wait_for('message', check=check)
desc = msg.content
# Finally make the embed and send it
msg = await ctx.send(content='Now generating the embed...')
color_list = [c for c in colors.values()]
# Convert the colors into a list
# To be able to use random.choice on it
embed = discord.Embed(
title=title,
description=desc,
color=random.choice(color_list)
)
# Also set the thumbnail to be the bot's pfp
embed.set_thumbnail(url=self.bot.user.avatar_url)
# Also set the embed author to the command user
embed.set_author(
name=ctx.message.author.name,
icon_url=ctx.message.author.avatar_url
)
await msg.edit(
embed=embed,
content=None
)
# Editing the message
# We have to specify the content to be 'None' here
# Since we don't want it to stay to 'Now generating embed...'
return
def setup(bot):
bot.add_cog(Embed(bot))
# Adds the Basic commands to the bot
# Note: The "setup" function has to be there in every cog file
Now, let's run this command!
And that's it!
Step 6 : Changing the default help command
As we've already seen, commands extension already comes with a built-in help command. Let's use it again!
Pretty clearly, it's very ugly. So, let's change it!
So, what we'll do is, remove the pre-defined help command and then create a new help command in theembed.pyfile.
Open up the main.py file and make the following changes: -
@bot.event
async def on_ready():
print(f'Logged in as {bot.user.name} - {bot.user.id}')
bot.remove_command('help')
# Removes the help command
# Make sure to do this before loading the cogs
for cog in cogs:
bot.load_extension(cog)
return
Open theembed.pyfile and make a new help command is given below: -
NOTE : We're making this in the embed.py file because this help command will be using embeds too. ( though it's not necessary to do even if it uses embeds, I just don't want to create another file with all those colors).
What this help command will do?
Get all the cogs registered.
If the user has passed a cog argument, then list all commands under that cog.
Else, list all cogs and commands under them.
@commands.command(
name='help',
description='The help command!',
aliases=['commands', 'command'],
usage='cog'
)
async def help_command(self, ctx, cog='all'):
# The third parameter comes into play when
# only one word argument has to be passed by the user
# Prepare the embed
color_list = [c for c in colors.values()]
help_embed = discord.Embed(
title='Help',
color=random.choice(color_list)
)
help_embed.set_thumbnail(url=self.bot.user.avatar_url)
help_embed.set_footer(
text=f'Requested by {ctx.message.author.name}',
icon_url=self.bot.user.avatar_url
)
# Get a list of all cogs
cogs = [c for c in self.bot.cogs.keys()]
# If cog is not specified by the user, we list all cogs and commands
if cog == 'all':
for cog in cogs:
# Get a list of all commands under each cog
cog_commands = self.bot.get_cog(cog).get_commands()
commands_list = ''
for comm in cog_commands:
commands_list += f'**{comm.name}** - *{comm.description}*\n'
# Add the cog's details to the embed.
help_embed.add_field(
name=cog,
value=commands_list,
inline=False
).add_field(
name='\u200b', value='\u200b', inline=False
)
# Also added a blank field '\u200b' is a whitespace character.
pass
else:
# If the cog was specified
lower_cogs = [c.lower() for c in cogs]
# If the cog actually exists.
if cog.lower() in lower_cogs:
# Get a list of all commands in the specified cog
commands_list = self.bot.get_cog(cogs[ lower_cogs.index(cog.lower()) ]).get_commands()
help_text=''
# Add details of each command to the help text
# Command Name
# Description
# [Aliases]
#
# Format
for command in commands_list:
help_text += f'```{command.name}```\n' \
f'**{command.description}**\n\n'
# Also add aliases, if there are any
if len(command.aliases) > 0:
help_text += f'**Aliases :** `{"`, `".join(command.aliases)}`\n\n\n'
else:
# Add a newline character to keep it pretty
# That IS the whole purpose of custom help
help_text += '\n'
# Finally the format
help_text += f'Format: `@{self.bot.user.name}#{self.bot.user.discriminator}' \
f' {command.name} {command.usage if command.usage is not None else ""}`\n\n\n\n'
help_embed.description = help_text
else:
# Notify the user of invalid cog and finish the command
await ctx.send('Invalid cog specified.\nUse `help` command to list all cogs.')
return
await ctx.send(embed=help_embed)
return
This is just an example and gives you an basic idea of what it is like. Below is a sample run of this new help command.
No cog specified, commands listed
Embed cogspecified, show the details of commands under Embed category.
Invalid cog specified, send error message.
Quick Tip
Use .env files to store your token. I've used .env file to store my token in the final code. You can learn more about how to use .env files here.
The End
Those are all the basics you'll need to know, refer to API Reference for reference on the discord.py commands extension. You can also refer to the main library docs. All of the above code can be obtained at here. Also you can visit this link to learn how to host your discord bots on repl.it!
Discord.py Rewrite
Note : Before you start this tutorial, You should already know the language python, how to create applications in discord and you should've already invited the bot to your server.
Step 1 : Setting up
Create a new folder for your bot, it can be anything. For reference, I will name it
Sample Bot
.Open up
command prompt
orterminal
and type the following commands in it.Now create a new file named
main.py
in your bot's folder. This file will hold the main bot.Also create a new directory named
cogs
in your bot's directory, this will hold our command groups (aka cogs).Now you're ready to code
Step 2 : The main bot
Open up your
main.py
file. Given below is some basic code with everything explained using comments.Now run this file, commands extension will prepare a default
help
command for you, you should see something similar to this when you use it: -Note that it doesn't show help when
=help
is used as this was done in DMs, and we only allowed==help
in DMs.Next we add the commands from the
cogs
directory.Inside the
cogs
directory, create a new file namedbasic.py
.Add the following code above the
part in the
main.py
fileThis basically points to the
basic.py
file in thecogs
folder.Next, change
to
This will load the all the files specified in the cogs variable.
Next, open up the
basic.py
file and write the following code in it.This will add a new ping command to your bot!
Save the file
Step 3 : Checking the new command
Run the main.py again.
Use the
help
command. It should look something like this: -Observe the new Basic category and ping command listed under it. This means that our command was successfully loaded.
Now use the
help ping
command, should look something like this: -Note that in the example, it shows the prefix used by you!
Finally, let's use the ping command.
This is an example run (my internet is a bit slow)
Step 4 : Commands with arguments
Open up the
basic.py
file and add the following command to it by typing it just below thereturn
statement of the ping command. This is a say command that repeats the words said by the user (in bold): -Next, let's use this command!
As you can see, works perfectly!
Step 5 : Embeds
Since, we've already done this, let's do one final command. The embed command.
What this command will do?
What this will help you learn?
In your cogs directory, create a new file named
embed.py
In your
main.py
file, to the cogs list which formerly wascogs = ['cogs.basic']
add a new cog i.e.'cogs.embed'
, making it -cogs = ['cogs.basic', 'cogs.embed']
. This will tell it to also treat theembed.py
file as another cog.Open up the embed.py file and write the following code in it: -
Now, let's run this command!
And that's it!
Step 6 : Changing the default help command
As we've already seen, commands extension already comes with a built-in help command. Let's use it again!
Pretty clearly, it's very ugly. So, let's change it!
So, what we'll do is, remove the pre-defined help command and then create a new help command in the
embed.py
file.Open up the main.py file and make the following changes: -
Open the
embed.py
file and make a new help command is given below: -NOTE : We're making this in the embed.py file because this help command will be using embeds too. ( though it's not necessary to do even if it uses embeds, I just don't want to create another file with all those colors).
What this help command will do?
Get all the cogs registered.
If the user has passed a cog argument,
then list all commands under that cog.
Else, list all cogs and commands under them.
This is just an example and gives you an basic idea of what it is like. Below is a sample run of this new help command.
No cog specified, commands listed
Embed cog specified, show the details of commands under Embed category.
Invalid cog specified, send error message.
Quick Tip
Use
.env
files to store your token. I've used .env file to store my token in the final code. You can learn more about how to use.env
files here.The End
Those are all the basics you'll need to know, refer to API Reference for reference on the discord.py commands extension. You can also refer to the main library docs. All of the above code can be obtained at here. Also you can visit this link to learn how to host your discord bots on repl.it!
@AkimotoRyou Thanks for the patience, I have updated both my tutorial and the final example to match the latest requirements. Thanks for informing me.