| name | discord-bot |
| description | Discord Bot development with discord.py v2.x. Provides patterns for bot setup, Cogs, slash commands, UI components (buttons/selects/modals), events, permissions, embeds, error handling, database integration, and deployment. Use when: (1) Creating a new Discord bot, (2) Adding commands or features to an existing bot, (3) Working with discord.py code, (4) Debugging Discord bot issues, (5) Setting up bot project structure. Triggers on: discord.py imports, bot development requests, Discord API questions. |
Discord Bot Development
Quick Start Workflow
- New bot project -> Set up project structure (see below)
- Adding features -> Use Cog pattern, reference discordpy-api.md
- Discord API limits/concepts -> Reference discord-api.md
Project Structure
bot-project/
├── .env # DISCORD_TOKEN=xxx (gitignored)
├── .env.example # DISCORD_TOKEN=
├── .gitignore
├── requirements.txt # discord.py, python-dotenv, aiosqlite
├── bot.py # Entry point
└── cogs/
├── __init__.py
└── general.py # First cog
Bot Entry Point Template
import asyncio
import logging
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)-8s %(name)s: %(message)s")
logging.getLogger("discord.http").setLevel(logging.WARNING)
logging.getLogger("discord.gateway").setLevel(logging.WARNING)
logger = logging.getLogger("bot")
EXTENSIONS = [
"cogs.general",
]
async def main():
token = os.getenv("DISCORD_TOKEN")
if not token:
raise RuntimeError("DISCORD_TOKEN not set")
intents = discord.Intents.default()
intents.message_content = True
async with commands.Bot(
command_prefix=commands.when_mentioned_or("!"),
intents=intents,
) as bot:
@bot.event
async def on_ready():
logger.info(f"Ready as {bot.user} | {len(bot.guilds)} guilds")
for ext in EXTENSIONS:
try:
await bot.load_extension(ext)
logger.info(f"Loaded: {ext}")
except Exception as e:
logger.error(f"Failed: {ext}: {e}")
await bot.start(token)
if __name__ == "__main__":
asyncio.run(main())
Key Decisions
Slash Commands vs Prefix Commands
- Slash commands (
app_commands): Modern, discoverable, built-in parameter validation. Prefer for new bots.
- Prefix commands (
commands.command): Text-based (!help). Use when slash commands are insufficient.
- Hybrid commands (
commands.hybrid_command): Work as both. Good for migration.
Command Sync Strategy
- Development: Guild-specific sync (instant)
- Production: Global sync (up to 1 hour propagation)
- Never sync in
on_ready -- causes rate limit issues
Interaction Response Rules
- Must respond within 3 seconds or call
defer()
interaction.response is one-time -- use followup after first response
- Modal must be the initial response (cannot defer first)
References
- discord.py API patterns: references/discordpy-api.md -- Bot setup, Cogs, slash commands, UI components, events, permissions, embeds, error handling, database, tasks, production patterns
- Discord platform specs: references/discord-api.md -- Developer Portal setup, OAuth2, rate limits, message/embed/command limits
Checklist Before Deployment