Update main.py
Browse files
main.py
CHANGED
|
@@ -22,7 +22,7 @@ def home():
|
|
| 22 |
return "hey, bot started✅"
|
| 23 |
|
| 24 |
def run_web():
|
| 25 |
-
app.run(host='0.0.0.0', port=
|
| 26 |
|
| 27 |
# Start web server in a thread
|
| 28 |
web_thread = Thread(target=run_web)
|
|
@@ -35,7 +35,7 @@ if not TOKEN:
|
|
| 35 |
|
| 36 |
# Bot intents
|
| 37 |
intents = discord.Intents.default()
|
| 38 |
-
intents.message_content = True
|
| 39 |
intents.members = True
|
| 40 |
intents.presences = True
|
| 41 |
|
|
@@ -43,7 +43,7 @@ intents.presences = True
|
|
| 43 |
bot = commands.Bot(
|
| 44 |
command_prefix='!',
|
| 45 |
intents=intents,
|
| 46 |
-
help_command=None,
|
| 47 |
case_insensitive=True
|
| 48 |
)
|
| 49 |
|
|
@@ -53,7 +53,6 @@ async def on_ready():
|
|
| 53 |
logger.info(f'✅ Bot logged in as {bot.user.name} ({bot.user.id})')
|
| 54 |
logger.info(f'🌐 Connected to {len(bot.guilds)} guilds')
|
| 55 |
|
| 56 |
-
# Set bot status
|
| 57 |
await bot.change_presence(
|
| 58 |
activity=discord.Activity(
|
| 59 |
type=discord.ActivityType.watching,
|
|
@@ -62,7 +61,6 @@ async def on_ready():
|
|
| 62 |
status=discord.Status.online
|
| 63 |
)
|
| 64 |
|
| 65 |
-
# Start background tasks
|
| 66 |
status_update.start()
|
| 67 |
|
| 68 |
# Background task: Update status every 5 minutes
|
|
@@ -76,34 +74,26 @@ async def status_update():
|
|
| 76 |
status=discord.Status.online
|
| 77 |
)
|
| 78 |
|
| 79 |
-
# Event: When bot joins a new guild
|
| 80 |
@bot.event
|
| 81 |
async def on_guild_join(guild):
|
| 82 |
logger.info(f'➕ Joined guild: {guild.name} ({guild.id})')
|
| 83 |
|
| 84 |
-
# Event: When bot leaves a guild
|
| 85 |
@bot.event
|
| 86 |
async def on_guild_remove(guild):
|
| 87 |
logger.info(f'➖ Left guild: {guild.name} ({guild.id})')
|
| 88 |
|
| 89 |
-
# Event: Handle messages (for non-command messages)
|
| 90 |
@bot.event
|
| 91 |
async def on_message(message):
|
| 92 |
-
# Ignore bot messages
|
| 93 |
if message.author.bot:
|
| 94 |
return
|
| 95 |
-
|
| 96 |
-
# Process commands
|
| 97 |
await bot.process_commands(message)
|
| 98 |
|
| 99 |
# ==================== COMMANDS ====================
|
| 100 |
|
| 101 |
-
# Help Command
|
| 102 |
@bot.command(name='help', aliases=['h', 'commands'])
|
| 103 |
async def help_command(ctx, command_name: str = None):
|
| 104 |
"""Show help information"""
|
| 105 |
if command_name:
|
| 106 |
-
# Show specific command help
|
| 107 |
command = bot.get_command(command_name)
|
| 108 |
if command:
|
| 109 |
embed = discord.Embed(
|
|
@@ -126,7 +116,6 @@ async def help_command(ctx, command_name: str = None):
|
|
| 126 |
else:
|
| 127 |
await ctx.send(f"❌ Command `!{command_name}` not found!")
|
| 128 |
else:
|
| 129 |
-
# Show all commands
|
| 130 |
embed = discord.Embed(
|
| 131 |
title="🤖 Bot Commands",
|
| 132 |
description="Here are all available commands:",
|
|
@@ -134,7 +123,6 @@ async def help_command(ctx, command_name: str = None):
|
|
| 134 |
timestamp=datetime.now()
|
| 135 |
)
|
| 136 |
|
| 137 |
-
# Categorize commands
|
| 138 |
categories = {
|
| 139 |
"General": ['help', 'ping', 'info', 'serverinfo', 'userinfo'],
|
| 140 |
"Fun": ['say', 'embed', 'poll', '8ball', 'coinflip'],
|
|
@@ -157,7 +145,6 @@ async def help_command(ctx, command_name: str = None):
|
|
| 157 |
embed.set_footer(text=f"Use !help <command> for more details | Prefix: !")
|
| 158 |
await ctx.send(embed=embed)
|
| 159 |
|
| 160 |
-
# Ping Command
|
| 161 |
@bot.command(name='ping', aliases=['latency'])
|
| 162 |
async def ping_command(ctx):
|
| 163 |
"""Check bot latency"""
|
|
@@ -171,7 +158,6 @@ async def ping_command(ctx):
|
|
| 171 |
embed.set_footer(text=f"Requested by {ctx.author.name}")
|
| 172 |
await ctx.send(embed=embed)
|
| 173 |
|
| 174 |
-
# Info Command
|
| 175 |
@bot.command(name='info', aliases=['botinfo', 'about'])
|
| 176 |
async def info_command(ctx):
|
| 177 |
"""Show bot information"""
|
|
@@ -196,7 +182,6 @@ async def info_command(ctx):
|
|
| 196 |
|
| 197 |
await ctx.send(embed=embed)
|
| 198 |
|
| 199 |
-
# Server Info Command
|
| 200 |
@bot.command(name='serverinfo', aliases=['server', 'guildinfo'])
|
| 201 |
async def serverinfo_command(ctx):
|
| 202 |
"""Show server information"""
|
|
@@ -221,7 +206,6 @@ async def serverinfo_command(ctx):
|
|
| 221 |
|
| 222 |
await ctx.send(embed=embed)
|
| 223 |
|
| 224 |
-
# User Info Command
|
| 225 |
@bot.command(name='userinfo', aliases=['whois', 'profile'])
|
| 226 |
async def userinfo_command(ctx, member: discord.Member = None):
|
| 227 |
"""Show user information"""
|
|
@@ -251,7 +235,6 @@ async def userinfo_command(ctx, member: discord.Member = None):
|
|
| 251 |
|
| 252 |
await ctx.send(embed=embed)
|
| 253 |
|
| 254 |
-
# Avatar Command
|
| 255 |
@bot.command(name='avatar', aliases=['av', 'pfp'])
|
| 256 |
async def avatar_command(ctx, member: discord.Member = None):
|
| 257 |
"""Show user's avatar"""
|
|
@@ -268,14 +251,12 @@ async def avatar_command(ctx, member: discord.Member = None):
|
|
| 268 |
|
| 269 |
await ctx.send(embed=embed)
|
| 270 |
|
| 271 |
-
# Say Command
|
| 272 |
@bot.command(name='say', aliases=['echo'])
|
| 273 |
async def say_command(ctx, *, message: str):
|
| 274 |
"""Make the bot say something"""
|
| 275 |
await ctx.message.delete()
|
| 276 |
await ctx.send(message)
|
| 277 |
|
| 278 |
-
# Embed Command
|
| 279 |
@bot.command(name='embed', aliases=['em'])
|
| 280 |
async def embed_command(ctx, *, message: str):
|
| 281 |
"""Create a custom embed"""
|
|
@@ -287,7 +268,6 @@ async def embed_command(ctx, *, message: str):
|
|
| 287 |
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
| 288 |
await ctx.send(embed=embed)
|
| 289 |
|
| 290 |
-
# Poll Command
|
| 291 |
@bot.command(name='poll', aliases=['vote'])
|
| 292 |
async def poll_command(ctx, *, question: str):
|
| 293 |
"""Create a poll"""
|
|
@@ -304,7 +284,6 @@ async def poll_command(ctx, *, question: str):
|
|
| 304 |
await poll_message.add_reaction("👎")
|
| 305 |
await poll_message.add_reaction("🤷")
|
| 306 |
|
| 307 |
-
# 8Ball Command
|
| 308 |
@bot.command(name='8ball', aliases=['magic8ball', 'ask'])
|
| 309 |
async def eightball_command(ctx, *, question: str):
|
| 310 |
"""Ask the magic 8-ball"""
|
|
@@ -342,7 +321,6 @@ async def eightball_command(ctx, *, question: str):
|
|
| 342 |
|
| 343 |
await ctx.send(embed=embed)
|
| 344 |
|
| 345 |
-
# Coin Flip Command
|
| 346 |
@bot.command(name='coinflip', aliases=['flip', 'coin'])
|
| 347 |
async def coinflip_command(ctx):
|
| 348 |
"""Flip a coin"""
|
|
@@ -359,7 +337,6 @@ async def coinflip_command(ctx):
|
|
| 359 |
|
| 360 |
await ctx.send(embed=embed)
|
| 361 |
|
| 362 |
-
# Invite Command
|
| 363 |
@bot.command(name='invite', aliases=['addbot'])
|
| 364 |
async def invite_command(ctx):
|
| 365 |
"""Get bot invite link"""
|
|
@@ -387,7 +364,6 @@ async def invite_command(ctx):
|
|
| 387 |
|
| 388 |
await ctx.send(embed=embed)
|
| 389 |
|
| 390 |
-
# Clear Command
|
| 391 |
@bot.command(name='clear', aliases=['purge', 'clean'])
|
| 392 |
@commands.has_permissions(manage_messages=True)
|
| 393 |
async def clear_command(ctx, amount: int = 5):
|
|
@@ -405,7 +381,6 @@ async def clear_command(ctx, amount: int = 5):
|
|
| 405 |
await asyncio.sleep(3)
|
| 406 |
await msg.delete()
|
| 407 |
|
| 408 |
-
# Uptime Command
|
| 409 |
@bot.command(name='uptime', aliases=['up'])
|
| 410 |
async def uptime_command(ctx):
|
| 411 |
"""Show bot uptime"""
|
|
@@ -416,44 +391,67 @@ async def uptime_command(ctx):
|
|
| 416 |
)
|
| 417 |
await ctx.send(embed=embed)
|
| 418 |
|
| 419 |
-
#
|
|
|
|
| 420 |
@bot.event
|
| 421 |
async def on_command_error(ctx, error):
|
| 422 |
-
if
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
|
| 458 |
# Helper function: Get uptime
|
| 459 |
start_time = datetime.now()
|
|
@@ -475,10 +473,13 @@ def get_uptime():
|
|
| 475 |
|
| 476 |
return " ".join(parts)
|
| 477 |
|
| 478 |
-
# Run the bot
|
| 479 |
if __name__ == "__main__":
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
return "hey, bot started✅"
|
| 23 |
|
| 24 |
def run_web():
|
| 25 |
+
app.run(host='0.0.0.0', port=3000)
|
| 26 |
|
| 27 |
# Start web server in a thread
|
| 28 |
web_thread = Thread(target=run_web)
|
|
|
|
| 35 |
|
| 36 |
# Bot intents
|
| 37 |
intents = discord.Intents.default()
|
| 38 |
+
intents.message_content = True
|
| 39 |
intents.members = True
|
| 40 |
intents.presences = True
|
| 41 |
|
|
|
|
| 43 |
bot = commands.Bot(
|
| 44 |
command_prefix='!',
|
| 45 |
intents=intents,
|
| 46 |
+
help_command=None,
|
| 47 |
case_insensitive=True
|
| 48 |
)
|
| 49 |
|
|
|
|
| 53 |
logger.info(f'✅ Bot logged in as {bot.user.name} ({bot.user.id})')
|
| 54 |
logger.info(f'🌐 Connected to {len(bot.guilds)} guilds')
|
| 55 |
|
|
|
|
| 56 |
await bot.change_presence(
|
| 57 |
activity=discord.Activity(
|
| 58 |
type=discord.ActivityType.watching,
|
|
|
|
| 61 |
status=discord.Status.online
|
| 62 |
)
|
| 63 |
|
|
|
|
| 64 |
status_update.start()
|
| 65 |
|
| 66 |
# Background task: Update status every 5 minutes
|
|
|
|
| 74 |
status=discord.Status.online
|
| 75 |
)
|
| 76 |
|
|
|
|
| 77 |
@bot.event
|
| 78 |
async def on_guild_join(guild):
|
| 79 |
logger.info(f'➕ Joined guild: {guild.name} ({guild.id})')
|
| 80 |
|
|
|
|
| 81 |
@bot.event
|
| 82 |
async def on_guild_remove(guild):
|
| 83 |
logger.info(f'➖ Left guild: {guild.name} ({guild.id})')
|
| 84 |
|
|
|
|
| 85 |
@bot.event
|
| 86 |
async def on_message(message):
|
|
|
|
| 87 |
if message.author.bot:
|
| 88 |
return
|
|
|
|
|
|
|
| 89 |
await bot.process_commands(message)
|
| 90 |
|
| 91 |
# ==================== COMMANDS ====================
|
| 92 |
|
|
|
|
| 93 |
@bot.command(name='help', aliases=['h', 'commands'])
|
| 94 |
async def help_command(ctx, command_name: str = None):
|
| 95 |
"""Show help information"""
|
| 96 |
if command_name:
|
|
|
|
| 97 |
command = bot.get_command(command_name)
|
| 98 |
if command:
|
| 99 |
embed = discord.Embed(
|
|
|
|
| 116 |
else:
|
| 117 |
await ctx.send(f"❌ Command `!{command_name}` not found!")
|
| 118 |
else:
|
|
|
|
| 119 |
embed = discord.Embed(
|
| 120 |
title="🤖 Bot Commands",
|
| 121 |
description="Here are all available commands:",
|
|
|
|
| 123 |
timestamp=datetime.now()
|
| 124 |
)
|
| 125 |
|
|
|
|
| 126 |
categories = {
|
| 127 |
"General": ['help', 'ping', 'info', 'serverinfo', 'userinfo'],
|
| 128 |
"Fun": ['say', 'embed', 'poll', '8ball', 'coinflip'],
|
|
|
|
| 145 |
embed.set_footer(text=f"Use !help <command> for more details | Prefix: !")
|
| 146 |
await ctx.send(embed=embed)
|
| 147 |
|
|
|
|
| 148 |
@bot.command(name='ping', aliases=['latency'])
|
| 149 |
async def ping_command(ctx):
|
| 150 |
"""Check bot latency"""
|
|
|
|
| 158 |
embed.set_footer(text=f"Requested by {ctx.author.name}")
|
| 159 |
await ctx.send(embed=embed)
|
| 160 |
|
|
|
|
| 161 |
@bot.command(name='info', aliases=['botinfo', 'about'])
|
| 162 |
async def info_command(ctx):
|
| 163 |
"""Show bot information"""
|
|
|
|
| 182 |
|
| 183 |
await ctx.send(embed=embed)
|
| 184 |
|
|
|
|
| 185 |
@bot.command(name='serverinfo', aliases=['server', 'guildinfo'])
|
| 186 |
async def serverinfo_command(ctx):
|
| 187 |
"""Show server information"""
|
|
|
|
| 206 |
|
| 207 |
await ctx.send(embed=embed)
|
| 208 |
|
|
|
|
| 209 |
@bot.command(name='userinfo', aliases=['whois', 'profile'])
|
| 210 |
async def userinfo_command(ctx, member: discord.Member = None):
|
| 211 |
"""Show user information"""
|
|
|
|
| 235 |
|
| 236 |
await ctx.send(embed=embed)
|
| 237 |
|
|
|
|
| 238 |
@bot.command(name='avatar', aliases=['av', 'pfp'])
|
| 239 |
async def avatar_command(ctx, member: discord.Member = None):
|
| 240 |
"""Show user's avatar"""
|
|
|
|
| 251 |
|
| 252 |
await ctx.send(embed=embed)
|
| 253 |
|
|
|
|
| 254 |
@bot.command(name='say', aliases=['echo'])
|
| 255 |
async def say_command(ctx, *, message: str):
|
| 256 |
"""Make the bot say something"""
|
| 257 |
await ctx.message.delete()
|
| 258 |
await ctx.send(message)
|
| 259 |
|
|
|
|
| 260 |
@bot.command(name='embed', aliases=['em'])
|
| 261 |
async def embed_command(ctx, *, message: str):
|
| 262 |
"""Create a custom embed"""
|
|
|
|
| 268 |
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
| 269 |
await ctx.send(embed=embed)
|
| 270 |
|
|
|
|
| 271 |
@bot.command(name='poll', aliases=['vote'])
|
| 272 |
async def poll_command(ctx, *, question: str):
|
| 273 |
"""Create a poll"""
|
|
|
|
| 284 |
await poll_message.add_reaction("👎")
|
| 285 |
await poll_message.add_reaction("🤷")
|
| 286 |
|
|
|
|
| 287 |
@bot.command(name='8ball', aliases=['magic8ball', 'ask'])
|
| 288 |
async def eightball_command(ctx, *, question: str):
|
| 289 |
"""Ask the magic 8-ball"""
|
|
|
|
| 321 |
|
| 322 |
await ctx.send(embed=embed)
|
| 323 |
|
|
|
|
| 324 |
@bot.command(name='coinflip', aliases=['flip', 'coin'])
|
| 325 |
async def coinflip_command(ctx):
|
| 326 |
"""Flip a coin"""
|
|
|
|
| 337 |
|
| 338 |
await ctx.send(embed=embed)
|
| 339 |
|
|
|
|
| 340 |
@bot.command(name='invite', aliases=['addbot'])
|
| 341 |
async def invite_command(ctx):
|
| 342 |
"""Get bot invite link"""
|
|
|
|
| 364 |
|
| 365 |
await ctx.send(embed=embed)
|
| 366 |
|
|
|
|
| 367 |
@bot.command(name='clear', aliases=['purge', 'clean'])
|
| 368 |
@commands.has_permissions(manage_messages=True)
|
| 369 |
async def clear_command(ctx, amount: int = 5):
|
|
|
|
| 381 |
await asyncio.sleep(3)
|
| 382 |
await msg.delete()
|
| 383 |
|
|
|
|
| 384 |
@bot.command(name='uptime', aliases=['up'])
|
| 385 |
async def uptime_command(ctx):
|
| 386 |
"""Show bot uptime"""
|
|
|
|
| 391 |
)
|
| 392 |
await ctx.send(embed=embed)
|
| 393 |
|
| 394 |
+
# ==================== ERROR HANDLER (FIXED) ====================
|
| 395 |
+
|
| 396 |
@bot.event
|
| 397 |
async def on_command_error(ctx, error):
|
| 398 |
+
# Ignore if we can't send messages due to connection issues
|
| 399 |
+
try:
|
| 400 |
+
if isinstance(error, commands.CommandNotFound):
|
| 401 |
+
return
|
| 402 |
+
|
| 403 |
+
elif isinstance(error, commands.MissingRequiredArgument):
|
| 404 |
+
embed = discord.Embed(
|
| 405 |
+
title="❌ Missing Argument",
|
| 406 |
+
description=f"Missing required argument: `{error.param.name}`\nUse `!help {ctx.command.name}` for usage info.",
|
| 407 |
+
color=discord.Color.red()
|
| 408 |
+
)
|
| 409 |
+
await ctx.send(embed=embed)
|
| 410 |
+
|
| 411 |
+
elif isinstance(error, commands.MissingPermissions):
|
| 412 |
+
embed = discord.Embed(
|
| 413 |
+
title="❌ Missing Permissions",
|
| 414 |
+
description=f"You need `{', '.join(error.missing_permissions)}` permission to use this command.",
|
| 415 |
+
color=discord.Color.red()
|
| 416 |
+
)
|
| 417 |
+
await ctx.send(embed=embed)
|
| 418 |
+
|
| 419 |
+
elif isinstance(error, commands.MemberNotFound):
|
| 420 |
+
embed = discord.Embed(
|
| 421 |
+
title="❌ User Not Found",
|
| 422 |
+
description="The specified user was not found.",
|
| 423 |
+
color=discord.Color.red()
|
| 424 |
+
)
|
| 425 |
+
await ctx.send(embed=embed)
|
| 426 |
+
|
| 427 |
+
elif isinstance(error, commands.CommandInvokeError):
|
| 428 |
+
# Handle connection errors gracefully
|
| 429 |
+
original = error.original
|
| 430 |
+
if isinstance(original, aiohttp.ClientConnectorError):
|
| 431 |
+
logger.warning(f"Connection error in command {ctx.command.name}: {original}")
|
| 432 |
+
# Don't try to send message - connection is down
|
| 433 |
+
return
|
| 434 |
+
else:
|
| 435 |
+
logger.error(f"Command error: {error}")
|
| 436 |
+
embed = discord.Embed(
|
| 437 |
+
title="❌ Error",
|
| 438 |
+
description="An unexpected error occurred. Please try again later.",
|
| 439 |
+
color=discord.Color.red()
|
| 440 |
+
)
|
| 441 |
+
await ctx.send(embed=embed)
|
| 442 |
+
|
| 443 |
+
else:
|
| 444 |
+
logger.error(f"Command error: {error}")
|
| 445 |
+
embed = discord.Embed(
|
| 446 |
+
title="❌ Error",
|
| 447 |
+
description="An unexpected error occurred. Please try again later.",
|
| 448 |
+
color=discord.Color.red()
|
| 449 |
+
)
|
| 450 |
+
await ctx.send(embed=embed)
|
| 451 |
+
|
| 452 |
+
except Exception as e:
|
| 453 |
+
# If we can't even send the error message, just log it
|
| 454 |
+
logger.error(f"Failed to send error message: {e}")
|
| 455 |
|
| 456 |
# Helper function: Get uptime
|
| 457 |
start_time = datetime.now()
|
|
|
|
| 473 |
|
| 474 |
return " ".join(parts)
|
| 475 |
|
| 476 |
+
# Run the bot with auto-reconnect
|
| 477 |
if __name__ == "__main__":
|
| 478 |
+
while True:
|
| 479 |
+
try:
|
| 480 |
+
bot.run(TOKEN, reconnect=True)
|
| 481 |
+
except Exception as e:
|
| 482 |
+
logger.error(f"Bot crashed: {e}")
|
| 483 |
+
logger.info("Restarting bot in 10 seconds...")
|
| 484 |
+
import time
|
| 485 |
+
time.sleep(10)
|