This comprehensive tutorial will guide you through the process of setting up Botkit, creating your first bot extension using Pycord, and understanding the core concepts of Discord bot development.
Before we begin, ensure you have the following:
- Python 3.11 or higher installed
- Basic understanding of Python and Discord concepts
- A Discord account and access to the Discord Developer Portal
[!IMPORTANT] If you haven't already, create a Discord application and bot user in the Discord Developer Portal. You'll need the bot token for later steps.
If you don't have Git installed, you'll need to install it to clone the Botkit repository.
- Visit the Git website and download the appropriate version for your operating system.
- Follow the installation instructions for your OS.
[!TIP] On Windows, you can use the Git Bash terminal that comes with Git for a Unix-like command-line experience.
To verify Git is installed correctly, open a terminal or command prompt and run:
git --version
You should see the installed Git version in the output.
Now that Git is installed, let's clone the Botkit repository:
- Open a terminal or command prompt.
- Navigate to the directory where you want to store your bot project.
- Run the following command:
git clone https://github.com/nicebots-xyz/botkit
- Once the cloning is complete, navigate into the Botkit directory:
cd botkit
[!NOTE] Cloning the repository creates a local copy of Botkit on your machine, allowing you to build your bot using the Botkit framework.
It's a good practice to use a virtual environment for your Python projects. This keeps your project dependencies isolated from your system-wide Python installation.
- Create a virtual environment:
python -m venv venv
- Activate the virtual environment:
- On Windows:
venv\Scripts\activate
- On macOS and Linux:
source venv/bin/activate
- On Windows:
[!TIP] You'll know the virtual environment is active when you see
(venv)
at the beginning of your terminal prompt.
Install the required dependencies using PDM (Python Dependency Manager):
- If you haven't installed PDM yet, install it using pip:
pip install pdm
- Install the project dependencies:
pdm install
[!NOTE] PDM will read the
pyproject.toml
file and install all necessary dependencies for Botkit.
- In the root directory of your Botkit project, create a file named
config.yml
. - Open
config.yml
in a text editor and add the following content:
bot:
token: "YOUR_BOT_TOKEN_HERE"
Replace YOUR_BOT_TOKEN_HERE
with the actual token of your Discord bot.
[!CAUTION] Never share your bot token publicly or commit it to version control. Treat it like a password.
Now, let's create a new folder for our extension:
- Navigate to the
src/extensions
directory in your Botkit project. - Create a new folder called
my_first_extension
:
mkdir src/extensions/my_first_extension
The __init__.py
file is crucial for Python to recognize the directory as a package:
- Inside the
my_first_extension
folder, create a file named__init__.py
:
touch src/extensions/my_first_extension/__init__.py
- Open
__init__.py
in your preferred text editor and add the following content:
from .main import setup, default, schema
__all__ = ["setup", "default", "schema"]
[!NOTE] This file imports and exposes the necessary components from our
main.py
file (which we'll create next). It allows Botkit to access these components when loading the extension.
The main.py
file will contain the main logic for our extension:
- In the
my_first_extension
folder, create a file namedmain.py
:
touch src/extensions/my_first_extension/main.py
- Open
main.py
in your text editor and add the following content:
import discord
from discord.ext import commands
from typing import Dict, Any
class MyFirstExtension(commands.Cog):
def __init__(self, bot: discord.Bot):
self.bot = bot
def setup(bot: discord.Bot):
bot.add_cog(MyFirstExtension(bot))
default = {
"enabled": True
}
schema = {
"enabled": bool
}
Let's break down what we've done here:
- We import the necessary modules from discord and discord.ext.
- We use
typing
to add type hints, which improves code readability and helps catch errors early. - We define a
MyFirstExtension
class that inherits fromcommands.Cog
. This class will contain our commands and listeners. - The
setup
function is required by Botkit to add our cog to the bot. - We define
default
andschema
dictionaries for the extension's configuration.
[!TIP] Using type hints (like
bot: discord.Bot
) helps catch errors early and improves code readability. It's a good practice to use them consistently in your code.
Now, let's add some commands to our extension. We'll create a simple "hello" command and a more complex "userinfo" command.
Add the following methods to your MyFirstExtension
class in main.py
:
@discord.slash_command(name="hello", description="Say hello to the bot")
async def hello(self, ctx: discord.ApplicationContext):
await ctx.respond(f"Hello, {ctx.author.name}!")
@discord.slash_command(name="userinfo", description="Get information about a user")
async def userinfo(
self,
ctx: discord.ApplicationContext,
user: discord.Option(discord.Member, "The user to get info about", default=None)
):
user = user or ctx.author
embed = discord.Embed(title=f"User Info - {user.name}", color=user.color)
embed.set_thumbnail(url=user.display_avatar.url)
embed.add_field(name="ID", value=user.id)
embed.add_field(name="Joined Server", value=user.joined_at.strftime("%Y-%m-%d %H:%M:%S"))
embed.add_field(name="Account Created", value=user.created_at.strftime("%Y-%m-%d %H:%M:%S"))
embed.add_field(name="Roles", value=", ".join([role.name for role in user.roles[1:]]) or "None")
await ctx.respond(embed=embed)
Let's explain these commands:
-
The
hello
command:- Uses the
@discord.slash_command
decorator to create a slash command. - Takes only the
ctx
(context) parameter, which is automatically provided by Discord. - Responds with a greeting using the author's name.
- Uses the
-
The
userinfo
command:- Also uses
@discord.slash_command
to create a slash command. - Takes an optional
user
parameter, which defaults to the command author if not provided. - Creates an embed with various pieces of information about the user.
- Responds with the created embed.
- Also uses
[!NOTE] Slash commands are the modern way to create Discord bot commands. They provide better user experience and are easier to discover than traditional prefix-based commands.
Let's add an event listener to our extension to demonstrate how to respond to Discord events. We'll add a simple listener that logs when the bot is ready.
Add the following method to your MyFirstExtension
class in main.py
:
@commands.Cog.listener()
async def on_ready(self):
print(f"Bot is ready! Logged in as {self.bot.user}")
This listener will print a message to the console when the bot has successfully connected to Discord.
[!TIP] Event listeners are great for performing actions based on Discord events, such as when a member joins a server or when a message is deleted.
Your complete main.py
file should now look like this:
import discord
from discord.ext import commands
from typing import Dict, Any
class MyFirstExtension(commands.Cog):
def __init__(self, bot: discord.Bot):
self.bot = bot
@discord.slash_command(name="hello", description="Say hello to the bot")
async def hello(self, ctx: discord.ApplicationContext):
await ctx.respond(f"Hello, {ctx.author.name}!")
@discord.slash_command(name="userinfo", description="Get information about a user")
async def userinfo(
self,
ctx: discord.ApplicationContext,
user: discord.Option(discord.Member, "The user to get info about", default=None)
):
user = user or ctx.author
embed = discord.Embed(title=f"User Info - {user.name}", color=user.color)
embed.set_thumbnail(url=user.display_avatar.url)
embed.add_field(name="ID", value=user.id)
embed.add_field(name="Joined Server", value=user.joined_at.strftime("%Y-%m-%d %H:%M:%S"))
embed.add_field(name="Account Created", value=user.created_at.strftime("%Y-%m-%d %H:%M:%S"))
embed.add_field(name="Roles", value=", ".join([role.name for role in user.roles[1:]]) or "None")
await ctx.respond(embed=embed)
@commands.Cog.listener()
async def on_ready(self):
print(f"Bot is ready! Logged in as {self.bot.user}")
def setup(bot: discord.Bot):
bot.add_cog(MyFirstExtension(bot))
default = {
"enabled": True
}
schema = {
"enabled": bool
}
Now that we've created our extension, let's run the bot:
- Make sure you're in the root directory of your Botkit project.
- Run the following command:
pdm run start
[!IMPORTANT] Ensure your bot token is correctly set in the
config.yml
file before running the bot.
If everything is set up correctly, you should see the "Bot is ready!" message in your console, indicating that your bot is now online and ready to respond to commands.
Congratulations! You've now created your first bot extension using Botkit and Pycord. This extension includes:
- A simple "hello" slash command
- A more complex "userinfo" slash command that creates an embed
- An event listener for the "on_ready" event
[!TIP] To continue improving your bot, consider adding more commands, implementing additional event listeners, or integrating with external APIs or databases.
[!WARNING] Always be cautious when handling user data and permissions in your bot. Ensure you're following Discord's Terms of Service and Developer Policy.
Remember to always use type hinting in your code. It helps with code readability, catches potential errors early, and provides better autocomplete suggestions in many IDEs.
Happy coding, and enjoy building your Discord bot!