wpms commited on
Commit
d9357d5
·
verified ·
1 Parent(s): 0cf1968

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +386 -257
main.py CHANGED
@@ -1,339 +1,468 @@
1
  import discord
2
- from discord.ext import commands
3
  import os
4
  import asyncio
5
- from flask import Flask
6
- from threading import Thread
7
- import time
8
 
9
- # Bot setup
 
 
 
 
 
 
 
 
 
 
 
 
10
  intents = discord.Intents.default()
11
- intents.message_content = True
12
  intents.members = True
13
  intents.presences = True
14
 
15
- bot = commands.Bot(command_prefix="!", intents=intents, help_command=None)
16
-
17
- # Global variables for web status
18
- bot_status = {
19
- "ready": False,
20
- "name": "Loading...",
21
- "id": "...",
22
- "latency": 0,
23
- "servers": 0,
24
- "error": None,
25
- "start_time": time.time()
26
- }
27
-
28
- # Keep-alive server for Hugging Face
29
- app = Flask(__name__)
30
-
31
- @app.route('/')
32
- def home():
33
- status_text = "Online ✅" if bot_status["ready"] else ("Error ❌" if bot_status["error"] else "Connecting...")
34
- status_color = "#00ff00" if bot_status["ready"] else ("#ff0000" if bot_status["error"] else "#ffa500")
35
-
36
- error_html = f"""
37
- <div style="background: #ff4444; color: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
38
- <strong>⚠️ Error:</strong> {bot_status["error"]}
39
- </div>
40
- """ if bot_status["error"] else ""
41
-
42
- return f"""
43
- <html>
44
- <head>
45
- <title>{bot_status["name"]} - Discord Bot Status</title>
46
- <meta http-equiv="refresh" content="10">
47
- <style>
48
- body {{ font-family: 'Segoe UI', Arial, sans-serif; padding: 40px; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); color: white; min-height: 100vh; }}
49
- .container {{ max-width: 800px; margin: 0 auto; }}
50
- .status-card {{ background: rgba(255,255,255,0.1); padding: 30px; border-radius: 15px; backdrop-filter: blur(10px); margin-bottom: 20px; }}
51
- .status-indicator {{ display: inline-block; width: 15px; height: 15px; border-radius: 50%; background: {status_color}; margin-right: 10px; animation: pulse 2s infinite; }}
52
- @keyframes pulse {{ 0% {{ opacity: 1; }} 50% {{ opacity: 0.5; }} 100% {{ opacity: 1; }} }}
53
- .info-grid {{ display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 20px; }}
54
- .info-item {{ background: rgba(255,255,255,0.05); padding: 15px; border-radius: 8px; }}
55
- .info-label {{ color: #aaa; font-size: 12px; text-transform: uppercase; }}
56
- .info-value {{ font-size: 18px; font-weight: bold; margin-top: 5px; }}
57
- .commands {{ background: rgba(255,255,255,0.05); padding: 20px; border-radius: 10px; }}
58
- .command {{ background: rgba(0,0,0,0.3); padding: 8px 12px; border-radius: 5px; margin: 5px 0; font-family: monospace; }}
59
- .token-error {{ background: #ff4444; color: white; padding: 20px; border-radius: 10px; margin: 20px 0; }}
60
- </style>
61
- </head>
62
- <body>
63
- <div class="container">
64
- <div class="status-card">
65
- <h1>🤖 Discord Bot Status</h1>
66
- <div style="font-size: 24px; margin: 20px 0;">
67
- <span class="status-indicator"></span>
68
- <strong>{status_text}</strong>
69
- </div>
70
- {error_html}
71
- <div class="info-grid">
72
- <div class="info-item">
73
- <div class="info-label">Bot Name</div>
74
- <div class="info-value">{bot_status["name"]}</div>
75
- </div>
76
- <div class="info-item">
77
- <div class="info-label">Bot ID</div>
78
- <div class="info-value">{bot_status["id"]}</div>
79
- </div>
80
- <div class="info-item">
81
- <div class="info-label">Latency</div>
82
- <div class="info-value">{round(bot_status["latency"] * 1000, 2) if bot_status["ready"] else "..."} ms</div>
83
- </div>
84
- <div class="info-item">
85
- <div class="info-label">Servers</div>
86
- <div class="info-value">{bot_status["servers"]}</div>
87
- </div>
88
- </div>
89
- </div>
90
-
91
- <div class="commands">
92
- <h3>📋 Available Commands:</h3>
93
- <div class="command">!ping</div>
94
- <div class="command">!server</div>
95
- <div class="command">!user @mention</div>
96
- <div class="command">!clear [amount]</div>
97
- <div class="command">!say [message]</div>
98
- <div class="command">!embed [title] | [description]</div>
99
- <div class="command">!poll [question]</div>
100
- <div class="command">!avatar @mention</div>
101
- <div class="command">!help</div>
102
- </div>
103
-
104
- <div style="margin-top: 30px; text-align: center; color: #888; font-size: 12px;">
105
- Last updated: {time.strftime("%Y-%m-%d %H:%M:%S")} | Auto-refresh: 10s
106
- </div>
107
- </div>
108
- </body>
109
- </html>
110
- """
111
-
112
- @app.route('/health')
113
- def health():
114
- return {"status": "healthy", "bot_ready": bot_status["ready"], "bot_name": bot_status["name"]}, 200
115
-
116
- def run_flask():
117
- app.run(host='0.0.0.0', port=7860)
118
 
119
  # Event: Bot ready
120
  @bot.event
121
  async def on_ready():
122
- bot_status["ready"] = True
123
- bot_status["name"] = bot.user.name
124
- bot_status["id"] = str(bot.user.id)
125
- bot_status["error"] = None
126
- print(f'✅ Logged in as {bot.user.name} ({bot.user.id})')
127
- print(f'📊 Connected to {len(bot.guilds)} servers')
128
  await bot.change_presence(
129
  activity=discord.Activity(
130
- type=discord.ActivityType.watching,
131
- name="!help for commands"
132
- )
 
133
  )
 
 
 
134
 
135
- # Event: Member join
 
 
 
 
 
 
 
 
 
 
 
136
  @bot.event
137
- async def on_member_join(member):
138
- channel = discord.utils.get(member.guild.text_channels, name='general')
139
- if channel:
140
- embed = discord.Embed(
141
- title="Welcome! 🎉",
142
- description=f"Hey {member.mention}, welcome to **{member.guild.name}**!",
143
- color=discord.Color.green()
144
- )
145
- embed.set_thumbnail(url=member.avatar.url if member.avatar else member.default_avatar.url)
146
- await channel.send(embed=embed)
147
 
148
- # Event: Message
 
 
 
 
 
149
  @bot.event
150
  async def on_message(message):
 
151
  if message.author.bot:
152
  return
153
- if bot.user in message.mentions:
154
- await message.add_reaction('👋')
155
  await bot.process_commands(message)
156
 
157
- # ============ COMMANDS ============
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
- @bot.command()
160
- async def ping(ctx):
161
- latency = round(bot.latency * 1000, 2)
 
 
 
162
  embed = discord.Embed(
163
  title="🏓 Pong!",
164
- description=f"Latency: **{latency}ms**",
165
- color=discord.Color.blue()
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  await ctx.send(embed=embed)
168
 
169
- @bot.command()
170
- async def server(ctx):
 
 
171
  guild = ctx.guild
 
172
  embed = discord.Embed(
173
- title=f"📊 {guild.name} Info",
174
- color=discord.Color.purple()
 
175
  )
176
- embed.add_field(name="Owner", value=guild.owner.mention, inline=True)
 
 
177
  embed.add_field(name="Members", value=guild.member_count, inline=True)
178
- embed.add_field(name="Channels", value=len(guild.channels), inline=True)
179
  embed.add_field(name="Roles", value=len(guild.roles), inline=True)
180
  embed.add_field(name="Created", value=guild.created_at.strftime("%Y-%m-%d"), inline=True)
181
- embed.add_field(name="Boosts", value=guild.premium_subscription_count or 0, inline=True)
 
182
  if guild.icon:
183
  embed.set_thumbnail(url=guild.icon.url)
 
184
  await ctx.send(embed=embed)
185
 
186
- @bot.command()
187
- async def user(ctx, member: discord.Member = None):
 
 
188
  member = member or ctx.author
 
189
  embed = discord.Embed(
190
- title=f"👤 {member.name} Info",
191
- color=member.color if member.color != discord.Color.default() else discord.Color.blue()
 
192
  )
 
 
 
193
  embed.add_field(name="ID", value=member.id, inline=True)
194
- embed.add_field(name="Nickname", value=member.nick or "None", inline=True)
 
195
  embed.add_field(name="Status", value=str(member.status).title(), inline=True)
196
- embed.add_field(name="Joined Server", value=member.joined_at.strftime("%Y-%m-%d") if member.joined_at else "Unknown", inline=True)
197
- embed.add_field(name="Account Created", value=member.created_at.strftime("%Y-%m-%d"), inline=True)
198
  embed.add_field(name="Top Role", value=member.top_role.mention, inline=True)
 
 
 
 
 
 
199
  embed.set_thumbnail(url=member.avatar.url if member.avatar else member.default_avatar.url)
 
 
200
  await ctx.send(embed=embed)
201
 
202
- @bot.command()
203
- @commands.has_permissions(manage_messages=True)
204
- async def clear(ctx, amount: int = 5):
205
- if amount < 1 or amount > 100:
206
- await ctx.send("❌ Please specify a number between 1 and 100!")
207
- return
208
- deleted = await ctx.channel.purge(limit=amount + 1)
209
  embed = discord.Embed(
210
- description=f"🗑️ Deleted **{len(deleted)-1}** messages!",
211
- color=discord.Color.red()
212
  )
213
- msg = await ctx.send(embed=embed)
214
- await asyncio.sleep(3)
215
- await msg.delete()
 
 
 
216
 
217
- @bot.command()
218
- async def say(ctx, *, message):
 
 
219
  await ctx.message.delete()
220
  await ctx.send(message)
221
 
222
- @bot.command()
223
- async def embed(ctx, *, content):
224
- parts = content.split("|", 1)
225
- title = parts[0].strip()
226
- description = parts[1].strip() if len(parts) > 1 else ""
227
  embed = discord.Embed(
228
- title=title,
229
- description=description,
230
- color=discord.Color.random()
231
  )
232
- embed.set_footer(text=f"Created by {ctx.author.name}", icon_url=ctx.author.avatar.url if ctx.author.avatar else None)
233
  await ctx.send(embed=embed)
234
 
235
- @bot.command()
236
- async def poll(ctx, *, question):
 
 
237
  embed = discord.Embed(
238
  title="📊 Poll",
239
- description=f"**{question}**",
240
- color=discord.Color.gold()
 
241
  )
242
  embed.set_footer(text=f"Poll by {ctx.author.name}")
243
- msg = await ctx.send(embed=embed)
244
- await msg.add_reaction('👍')
245
- await msg.add_reaction('👎')
246
- await msg.add_reaction('🤷')
 
247
 
248
- @bot.command()
249
- async def avatar(ctx, member: discord.Member = None):
250
- member = member or ctx.author
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  embed = discord.Embed(
252
- title=f"🖼️ {member.name}'s Avatar",
253
- color=discord.Color.blue()
254
  )
255
- avatar_url = member.avatar.url if member.avatar else member.default_avatar.url
256
- embed.set_image(url=avatar_url)
257
- embed.add_field(name="Download", value=f"[Click Here]({avatar_url})", inline=False)
258
  await ctx.send(embed=embed)
259
 
260
- @bot.command()
261
- async def help(ctx):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  embed = discord.Embed(
263
- title="🤖 Bot Commands",
264
- description="Here are all available commands:",
265
  color=discord.Color.blue()
266
  )
267
- commands_list = [
268
- ("!ping", "Check bot latency"),
269
- ("!server", "Server information"),
270
- ("!user @mention", "User information"),
271
- ("!clear [amount]", "Clear messages (1-100)"),
272
- ("!say [message]", "Bot says something"),
273
- ("!embed Title | Desc", "Create custom embed"),
274
- ("!poll [question]", "Create a poll"),
275
- ("!avatar @mention", "Get user avatar"),
276
- ("!help", "Show this message")
277
- ]
278
- for cmd, desc in commands_list:
279
- embed.add_field(name=cmd, value=desc, inline=False)
280
- embed.set_footer(text=f"Requested by {ctx.author.name}")
281
  await ctx.send(embed=embed)
282
 
283
- # Error handling
284
  @bot.event
285
  async def on_command_error(ctx, error):
286
  if isinstance(error, commands.CommandNotFound):
287
- return
288
- elif isinstance(error, commands.MissingPermissions):
289
- await ctx.send("❌ You don't have permission to use this command!")
290
  elif isinstance(error, commands.MissingRequiredArgument):
291
- await ctx.send(f"❌ Missing argument! Usage: `{ctx.command.signature}`")
292
- elif isinstance(error, commands.BadArgument):
293
- await ctx.send("❌ Invalid argument provided!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  else:
295
- print(f"Error: {error}")
296
-
297
- async def start_bot():
298
- TOKEN = os.getenv("DISCORD_TOKEN")
299
- if not TOKEN:
300
- error_msg = "DISCORD_TOKEN not found! Please set it in Hugging Face secrets."
301
- bot_status["error"] = error_msg
302
- bot_status["name"] = "Token Missing"
303
- print(f"❌ {error_msg}")
304
- return
305
 
306
- max_retries = 5
307
- retry_count = 0
308
 
309
- while retry_count < max_retries:
310
- try:
311
- print(f"🔄 Attempting to connect to Discord... (Attempt {retry_count + 1}/{max_retries})")
312
- await bot.start(TOKEN)
313
- break
314
- except discord.LoginFailure as e:
315
- error_msg = f"Invalid Discord token! Please check your token. Error: {str(e)}"
316
- bot_status["error"] = error_msg
317
- bot_status["name"] = "Invalid Token"
318
- print(f"❌ {error_msg}")
319
- break
320
- except Exception as e:
321
- retry_count += 1
322
- error_msg = f"Connection error: {str(e)}. Retrying in 10 seconds..."
323
- bot_status["error"] = error_msg
324
- bot_status["name"] = "Connection Error"
325
- print(f"⚠️ {error_msg}")
326
- if retry_count < max_retries:
327
- await asyncio.sleep(10)
328
- else:
329
- bot_status["error"] = f"Failed to connect after {max_retries} attempts. Discord API might be down or network blocked."
330
- bot_status["name"] = "Connection Failed"
331
- print(f"❌ {bot_status['error']}")
332
 
333
- # Run bot
334
  if __name__ == "__main__":
335
- flask_thread = Thread(target=run_flask)
336
- flask_thread.daemon = True
337
- flask_thread.start()
338
-
339
- asyncio.run(start_bot())
 
1
  import discord
2
+ from discord.ext import commands, tasks
3
  import os
4
  import asyncio
5
+ from datetime import datetime
6
+ import logging
 
7
 
8
+ # Setup logging
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
12
+ )
13
+ logger = logging.getLogger('discord_bot')
14
+
15
+ # Bot configuration
16
+ TOKEN = os.getenv('DISCORD_TOKEN')
17
+ if not TOKEN:
18
+ raise ValueError("DISCORD_TOKEN environment variable is required!")
19
+
20
+ # Bot intents
21
  intents = discord.Intents.default()
22
+ intents.message_content = True # Required for reading message content
23
  intents.members = True
24
  intents.presences = True
25
 
26
+ # Create bot instance
27
+ bot = commands.Bot(
28
+ command_prefix='!',
29
+ intents=intents,
30
+ help_command=None, # Custom help command
31
+ case_insensitive=True
32
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  # Event: Bot ready
35
  @bot.event
36
  async def on_ready():
37
+ logger.info(f'✅ Bot logged in as {bot.user.name} ({bot.user.id})')
38
+ logger.info(f'🌐 Connected to {len(bot.guilds)} guilds')
39
+
40
+ # Set bot status
 
 
41
  await bot.change_presence(
42
  activity=discord.Activity(
43
+ type=discord.ActivityType.watching,
44
+ name=f"{len(bot.guilds)} servers | !help"
45
+ ),
46
+ status=discord.Status.online
47
  )
48
+
49
+ # Start background tasks
50
+ status_update.start()
51
 
52
+ # Background task: Update status every 5 minutes
53
+ @tasks.loop(minutes=5)
54
+ async def status_update():
55
+ await bot.change_presence(
56
+ activity=discord.Activity(
57
+ type=discord.ActivityType.watching,
58
+ name=f"{len(bot.guilds)} servers | !help"
59
+ ),
60
+ status=discord.Status.online
61
+ )
62
+
63
+ # Event: When bot joins a new guild
64
  @bot.event
65
+ async def on_guild_join(guild):
66
+ logger.info(f'➕ Joined guild: {guild.name} ({guild.id})')
 
 
 
 
 
 
 
 
67
 
68
+ # Event: When bot leaves a guild
69
+ @bot.event
70
+ async def on_guild_remove(guild):
71
+ logger.info(f'➖ Left guild: {guild.name} ({guild.id})')
72
+
73
+ # Event: Handle messages (for non-command messages)
74
  @bot.event
75
  async def on_message(message):
76
+ # Ignore bot messages
77
  if message.author.bot:
78
  return
79
+
80
+ # Process commands
81
  await bot.process_commands(message)
82
 
83
+ # ==================== COMMANDS ====================
84
+
85
+ # Help Command
86
+ @bot.command(name='help', aliases=['h', 'commands'])
87
+ async def help_command(ctx, command_name: str = None):
88
+ """Show help information"""
89
+ if command_name:
90
+ # Show specific command help
91
+ command = bot.get_command(command_name)
92
+ if command:
93
+ embed = discord.Embed(
94
+ title=f"📖 Help: !{command.name}",
95
+ description=command.help or "No description available",
96
+ color=discord.Color.blue()
97
+ )
98
+ embed.add_field(
99
+ name="Usage",
100
+ value=f"`!{command.name} {command.signature}`" if command.signature else f"`!{command.name}`",
101
+ inline=False
102
+ )
103
+ if command.aliases:
104
+ embed.add_field(
105
+ name="Aliases",
106
+ value=", ".join([f"`!{alias}`" for alias in command.aliases]),
107
+ inline=False
108
+ )
109
+ await ctx.send(embed=embed)
110
+ else:
111
+ await ctx.send(f"❌ Command `!{command_name}` not found!")
112
+ else:
113
+ # Show all commands
114
+ embed = discord.Embed(
115
+ title="🤖 Bot Commands",
116
+ description="Here are all available commands:",
117
+ color=discord.Color.blue(),
118
+ timestamp=datetime.now()
119
+ )
120
+
121
+ # Categorize commands
122
+ categories = {
123
+ "General": ['help', 'ping', 'info', 'serverinfo', 'userinfo'],
124
+ "Fun": ['say', 'embed', 'poll', '8ball', 'coinflip'],
125
+ "Utility": ['avatar', 'invite', 'uptime', 'clear']
126
+ }
127
+
128
+ for category, cmds in categories.items():
129
+ valid_cmds = []
130
+ for cmd_name in cmds:
131
+ cmd = bot.get_command(cmd_name)
132
+ if cmd:
133
+ valid_cmds.append(f"`!{cmd.name}`")
134
+ if valid_cmds:
135
+ embed.add_field(
136
+ name=f"📁 {category}",
137
+ value=" | ".join(valid_cmds),
138
+ inline=False
139
+ )
140
+
141
+ embed.set_footer(text=f"Use !help <command> for more details | Prefix: !")
142
+ await ctx.send(embed=embed)
143
 
144
+ # Ping Command
145
+ @bot.command(name='ping', aliases=['latency'])
146
+ async def ping_command(ctx):
147
+ """Check bot latency"""
148
+ latency = round(bot.latency * 1000)
149
+
150
  embed = discord.Embed(
151
  title="🏓 Pong!",
152
+ description=f"**Latency:** `{latency}ms`\n**API Latency:** `{round(bot.latency * 1000)}ms`",
153
+ color=discord.Color.green() if latency < 200 else discord.Color.orange() if latency < 500 else discord.Color.red()
154
+ )
155
+ embed.set_footer(text=f"Requested by {ctx.author.name}")
156
+ await ctx.send(embed=embed)
157
+
158
+ # Info Command
159
+ @bot.command(name='info', aliases=['botinfo', 'about'])
160
+ async def info_command(ctx):
161
+ """Show bot information"""
162
+ embed = discord.Embed(
163
+ title="🤖 Bot Information",
164
+ description="A Discord bot powered by discord.py",
165
+ color=discord.Color.blue(),
166
+ timestamp=datetime.now()
167
  )
168
+
169
+ embed.add_field(name="Bot Name", value=bot.user.name, inline=True)
170
+ embed.add_field(name="Bot ID", value=bot.user.id, inline=True)
171
+ embed.add_field(name="Servers", value=len(bot.guilds), inline=True)
172
+ embed.add_field(name="Users", value=sum(g.member_count for g in bot.guilds), inline=True)
173
+ embed.add_field(name="Library", value="discord.py", inline=True)
174
+ embed.add_field(name="Python Version", value="3.10+", inline=True)
175
+ embed.add_field(name="Created", value=bot.user.created_at.strftime("%Y-%m-%d"), inline=True)
176
+ embed.add_field(name="Uptime", value=get_uptime(), inline=True)
177
+
178
+ embed.set_thumbnail(url=bot.user.avatar.url if bot.user.avatar else bot.user.default_avatar.url)
179
+ embed.set_footer(text="Made with ❤️ using discord.py")
180
+
181
  await ctx.send(embed=embed)
182
 
183
+ # Server Info Command
184
+ @bot.command(name='serverinfo', aliases=['server', 'guildinfo'])
185
+ async def serverinfo_command(ctx):
186
+ """Show server information"""
187
  guild = ctx.guild
188
+
189
  embed = discord.Embed(
190
+ title=f"📊 {guild.name} Server Info",
191
+ color=discord.Color.blue(),
192
+ timestamp=datetime.now()
193
  )
194
+
195
+ embed.add_field(name="Server ID", value=guild.id, inline=True)
196
+ embed.add_field(name="Owner", value=guild.owner.mention if guild.owner else "Unknown", inline=True)
197
  embed.add_field(name="Members", value=guild.member_count, inline=True)
198
+ embed.add_field(name="Channels", value=f"{len(guild.text_channels)} Text | {len(guild.voice_channels)} Voice", inline=True)
199
  embed.add_field(name="Roles", value=len(guild.roles), inline=True)
200
  embed.add_field(name="Created", value=guild.created_at.strftime("%Y-%m-%d"), inline=True)
201
+ embed.add_field(name="Boost Level", value=f"Level {guild.premium_tier} ({guild.premium_subscription_count} boosts)", inline=True)
202
+
203
  if guild.icon:
204
  embed.set_thumbnail(url=guild.icon.url)
205
+
206
  await ctx.send(embed=embed)
207
 
208
+ # User Info Command
209
+ @bot.command(name='userinfo', aliases=['whois', 'profile'])
210
+ async def userinfo_command(ctx, member: discord.Member = None):
211
+ """Show user information"""
212
  member = member or ctx.author
213
+
214
  embed = discord.Embed(
215
+ title=f"👤 {member.name}'s Profile",
216
+ color=member.color if member.color != discord.Color.default() else discord.Color.blue(),
217
+ timestamp=datetime.now()
218
  )
219
+
220
+ embed.add_field(name="Username", value=member.name, inline=True)
221
+ embed.add_field(name="Display Name", value=member.display_name, inline=True)
222
  embed.add_field(name="ID", value=member.id, inline=True)
223
+ embed.add_field(name="Joined Server", value=member.joined_at.strftime("%Y-%m-%d %H:%M") if member.joined_at else "Unknown", inline=True)
224
+ embed.add_field(name="Account Created", value=member.created_at.strftime("%Y-%m-%d %H:%M"), inline=True)
225
  embed.add_field(name="Status", value=str(member.status).title(), inline=True)
 
 
226
  embed.add_field(name="Top Role", value=member.top_role.mention, inline=True)
227
+ embed.add_field(name="Bot?", value="Yes" if member.bot else "No", inline=True)
228
+
229
+ roles = [role.mention for role in member.roles if role != ctx.guild.default_role]
230
+ if roles:
231
+ embed.add_field(name=f"Roles ({len(roles)})", value=" ".join(roles[:10]) + ("..." if len(roles) > 10 else ""), inline=False)
232
+
233
  embed.set_thumbnail(url=member.avatar.url if member.avatar else member.default_avatar.url)
234
+ embed.set_footer(text=f"Requested by {ctx.author.name}")
235
+
236
  await ctx.send(embed=embed)
237
 
238
+ # Avatar Command
239
+ @bot.command(name='avatar', aliases=['av', 'pfp'])
240
+ async def avatar_command(ctx, member: discord.Member = None):
241
+ """Show user's avatar"""
242
+ member = member or ctx.author
243
+
 
244
  embed = discord.Embed(
245
+ title=f"🖼️ {member.name}'s Avatar",
246
+ color=discord.Color.blue()
247
  )
248
+
249
+ avatar_url = member.avatar.url if member.avatar else member.default_avatar.url
250
+ embed.set_image(url=avatar_url)
251
+ embed.add_field(name="Links", value=f"[PNG]({member.avatar.url if member.avatar else member.default_avatar.url}) | [WEBP]({member.avatar.url if member.avatar else member.default_avatar.url})", inline=False)
252
+
253
+ await ctx.send(embed=embed)
254
 
255
+ # Say Command
256
+ @bot.command(name='say', aliases=['echo'])
257
+ async def say_command(ctx, *, message: str):
258
+ """Make the bot say something"""
259
  await ctx.message.delete()
260
  await ctx.send(message)
261
 
262
+ # Embed Command
263
+ @bot.command(name='embed', aliases=['em'])
264
+ async def embed_command(ctx, *, message: str):
265
+ """Create a custom embed"""
 
266
  embed = discord.Embed(
267
+ description=message,
268
+ color=discord.Color.blue(),
269
+ timestamp=datetime.now()
270
  )
271
+ embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
272
  await ctx.send(embed=embed)
273
 
274
+ # Poll Command
275
+ @bot.command(name='poll', aliases=['vote'])
276
+ async def poll_command(ctx, *, question: str):
277
+ """Create a poll"""
278
  embed = discord.Embed(
279
  title="📊 Poll",
280
+ description=question,
281
+ color=discord.Color.blue(),
282
+ timestamp=datetime.now()
283
  )
284
  embed.set_footer(text=f"Poll by {ctx.author.name}")
285
+
286
+ poll_message = await ctx.send(embed=embed)
287
+ await poll_message.add_reaction("👍")
288
+ await poll_message.add_reaction("👎")
289
+ await poll_message.add_reaction("🤷")
290
 
291
+ # 8Ball Command
292
+ @bot.command(name='8ball', aliases=['magic8ball', 'ask'])
293
+ async def eightball_command(ctx, *, question: str):
294
+ """Ask the magic 8-ball"""
295
+ import random
296
+
297
+ responses = [
298
+ "🎱 It is certain.",
299
+ "🎱 It is decidedly so.",
300
+ "🎱 Without a doubt.",
301
+ "🎱 Yes definitely.",
302
+ "🎱 You may rely on it.",
303
+ "🎱 As I see it, yes.",
304
+ "🎱 Most likely.",
305
+ "🎱 Outlook good.",
306
+ "🎱 Yes.",
307
+ "🎱 Signs point to yes.",
308
+ "🎱 Reply hazy, try again.",
309
+ "🎱 Ask again later.",
310
+ "🎱 Better not tell you now.",
311
+ "🎱 Cannot predict now.",
312
+ "🎱 Concentrate and ask again.",
313
+ "🎱 Don't count on it.",
314
+ "🎱 My reply is no.",
315
+ "🎱 My sources say no.",
316
+ "🎱 Outlook not so good.",
317
+ "🎱 Very doubtful."
318
+ ]
319
+
320
  embed = discord.Embed(
321
+ title="🎱 Magic 8-Ball",
322
+ color=discord.Color.purple()
323
  )
324
+ embed.add_field(name="Question", value=question, inline=False)
325
+ embed.add_field(name="Answer", value=random.choice(responses), inline=False)
326
+
327
  await ctx.send(embed=embed)
328
 
329
+ # Coin Flip Command
330
+ @bot.command(name='coinflip', aliases=['flip', 'coin'])
331
+ async def coinflip_command(ctx):
332
+ """Flip a coin"""
333
+ import random
334
+
335
+ result = random.choice(["Heads", "Tails"])
336
+ emoji = "🪙" if result == "Heads" else "🪙"
337
+
338
+ embed = discord.Embed(
339
+ title=f"{emoji} Coin Flip",
340
+ description=f"**Result:** {result}",
341
+ color=discord.Color.gold()
342
+ )
343
+
344
+ await ctx.send(embed=embed)
345
+
346
+ # Invite Command
347
+ @bot.command(name='invite', aliases=['addbot'])
348
+ async def invite_command(ctx):
349
+ """Get bot invite link"""
350
+ permissions = discord.Permissions(
351
+ send_messages=True,
352
+ embed_links=True,
353
+ read_messages=True,
354
+ read_message_history=True,
355
+ add_reactions=True,
356
+ use_external_emojis=True,
357
+ attach_files=True,
358
+ manage_messages=True,
359
+ connect=True,
360
+ speak=True
361
+ )
362
+
363
+ invite_url = discord.utils.oauth_url(bot.user.id, permissions=permissions)
364
+
365
+ embed = discord.Embed(
366
+ title="🔗 Invite Bot",
367
+ description=f"[Click here to invite me!]({invite_url})",
368
+ color=discord.Color.green()
369
+ )
370
+ embed.add_field(name="Bot ID", value=bot.user.id, inline=False)
371
+
372
+ await ctx.send(embed=embed)
373
+
374
+ # Clear Command
375
+ @bot.command(name='clear', aliases=['purge', 'clean'])
376
+ @commands.has_permissions(manage_messages=True)
377
+ async def clear_command(ctx, amount: int = 5):
378
+ """Clear messages (requires Manage Messages permission)"""
379
+ if amount < 1 or amount > 100:
380
+ await ctx.send("❌ Please specify a number between 1 and 100!")
381
+ return
382
+
383
+ deleted = await ctx.channel.purge(limit=amount + 1)
384
+ embed = discord.Embed(
385
+ description=f"🗑️ Deleted {len(deleted) - 1} messages!",
386
+ color=discord.Color.green()
387
+ )
388
+ msg = await ctx.send(embed=embed)
389
+ await asyncio.sleep(3)
390
+ await msg.delete()
391
+
392
+ # Uptime Command
393
+ @bot.command(name='uptime', aliases=['up'])
394
+ async def uptime_command(ctx):
395
+ """Show bot uptime"""
396
  embed = discord.Embed(
397
+ title="⏱️ Bot Uptime",
398
+ description=get_uptime(),
399
  color=discord.Color.blue()
400
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  await ctx.send(embed=embed)
402
 
403
+ # Error Handler
404
  @bot.event
405
  async def on_command_error(ctx, error):
406
  if isinstance(error, commands.CommandNotFound):
407
+ return # Ignore unknown commands
408
+
 
409
  elif isinstance(error, commands.MissingRequiredArgument):
410
+ embed = discord.Embed(
411
+ title="❌ Missing Argument",
412
+ description=f"Missing required argument: `{error.param.name}`\nUse `!help {ctx.command.name}` for usage info.",
413
+ color=discord.Color.red()
414
+ )
415
+ await ctx.send(embed=embed)
416
+
417
+ elif isinstance(error, commands.MissingPermissions):
418
+ embed = discord.Embed(
419
+ title="❌ Missing Permissions",
420
+ description=f"You need `{', '.join(error.missing_permissions)}` permission to use this command.",
421
+ color=discord.Color.red()
422
+ )
423
+ await ctx.send(embed=embed)
424
+
425
+ elif isinstance(error, commands.MemberNotFound):
426
+ embed = discord.Embed(
427
+ title="❌ User Not Found",
428
+ description="The specified user was not found.",
429
+ color=discord.Color.red()
430
+ )
431
+ await ctx.send(embed=embed)
432
+
433
  else:
434
+ logger.error(f"Command error: {error}")
435
+ embed = discord.Embed(
436
+ title="❌ Error",
437
+ description="An unexpected error occurred. Please try again later.",
438
+ color=discord.Color.red()
439
+ )
440
+ await ctx.send(embed=embed)
 
 
 
441
 
442
+ # Helper function: Get uptime
443
+ start_time = datetime.now()
444
 
445
+ def get_uptime():
446
+ delta = datetime.now() - start_time
447
+ days = delta.days
448
+ hours, remainder = divmod(delta.seconds, 3600)
449
+ minutes, seconds = divmod(remainder, 60)
450
+
451
+ parts = []
452
+ if days > 0:
453
+ parts.append(f"{days}d")
454
+ if hours > 0:
455
+ parts.append(f"{hours}h")
456
+ if minutes > 0:
457
+ parts.append(f"{minutes}m")
458
+ parts.append(f"{seconds}s")
459
+
460
+ return " ".join(parts)
 
 
 
 
 
 
 
461
 
462
+ # Run the bot
463
  if __name__ == "__main__":
464
+ try:
465
+ bot.run(TOKEN)
466
+ except Exception as e:
467
+ logger.error(f"Failed to start bot: {e}")
468
+ raise