PYTHON
client.py🐍python
"""
Main bot client setup.
"""
import discord
from discord.ext import commands
import logging
from .config import settings
from .database import Database
logger = logging.getLogger(__name__)
class MyBot(commands.Bot):
"""Custom bot class with additional features."""
def __init__(self):
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
super().__init__(
command_prefix=settings.BOT_PREFIX,
description=settings.BOT_DESCRIPTION,
intents=intents,
help_command=commands.DefaultHelpCommand()
)
self.db = Database(settings.DATABASE_PATH)
async def setup_hook(self):
"""Called when bot is starting up."""
# Initialize database
await self.db.initialize()
# Load cogs
cog_modules = [
'bot.cogs.admin',
'bot.cogs.fun',
'bot.cogs.moderation',
'bot.cogs.reminders',
'bot.cogs.polls',
'bot.cogs.stats',
]
for cog in cog_modules:
try:
await self.load_extension(cog)
logger.info(f"Loaded cog: {cog}")
except Exception as e:
logger.error(f"Failed to load cog {cog}: {e}")
async def on_ready(self):
"""Called when bot is ready."""
logger.info(f"Logged in as {self.user} (ID: {self.user.id})")
logger.info(f"Connected to {len(self.guilds)} guilds")
# Set presence
activity = discord.Activity(
type=discord.ActivityType.watching,
name=f"{settings.BOT_PREFIX}help"
)
await self.change_presence(activity=activity)
async def on_guild_join(self, guild: discord.Guild):
"""Called when bot joins a new server."""
logger.info(f"Joined guild: {guild.name} (ID: {guild.id})")
# Send welcome message to system channel
if guild.system_channel:
embed = discord.Embed(
title="👋 Thanks for adding me!",
description=f"Use `{settings.BOT_PREFIX}help` to see available commands.",
color=discord.Color.green()
)
await guild.system_channel.send(embed=embed)
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
"""Global error handler for commands."""
if isinstance(error, commands.CommandNotFound):
return # Ignore unknown commands
if isinstance(error, commands.MissingPermissions):
await ctx.send("❌ You don't have permission to use this command.")
return
if isinstance(error, commands.MissingRequiredArgument):
await ctx.send(f"❌ Missing argument: `{error.param.name}`")
return
if isinstance(error, commands.BadArgument):
await ctx.send(f"❌ Invalid argument: {error}")
return
if isinstance(error, commands.CommandOnCooldown):
await ctx.send(f"⏳ Command on cooldown. Try again in {error.retry_after:.1f}s")
return
# Log unexpected errors
logger.error(f"Command error: {error}", exc_info=error)
await ctx.send("❌ An error occurred while processing your command.")
async def close(self):
"""Cleanup when bot shuts down."""
await self.db.close()
await super().close()
def create_bot() -> MyBot:
"""Factory function to create bot instance."""
return MyBot()