diff --git a/bot.py b/bot.py index c4e1958..93f23eb 100644 --- a/bot.py +++ b/bot.py @@ -1834,6 +1834,7 @@ async def bothelp(ctx): "`/level [user]` - View level and XP information\n" "`/leaderboard` - View the server XP leaderboard\n" "`/permissionlevel` - Check your permission level\n" + "`/mywarns` - View your moderation statistics\n" "`/version` - Show bot version information" ), inline=False @@ -1913,6 +1914,7 @@ async def help(ctx): "`/level [user]` - View level and XP information\n" "`/leaderboard` - View the server XP leaderboard\n" "`/permissionlevel` - Check your permission level\n" + "`/mywarns` - View your moderation statistics\n" "`/version` - Show bot version information" ), inline=False @@ -2582,18 +2584,18 @@ async def get_or_create_mute_role(guild, settings): # Moderation Helper Functions def check_moderation_permission(user_permission): - """Überprüft, ob der Nutzer Moderationsrechte hat (Permission 5 oder höher)""" + """Checks if the user has moderation rights (Permission 5 or higher)""" return user_permission >= 5 async def save_user_roles(user_id, guild_id, roles): - """Speichert die Rollen eines Users vor einem Mute""" + """Saves a user's roles before a mute""" connection = None cursor = None try: connection = connect_to_database() cursor = connection.cursor() - # Serialisiere die Rollen-IDs + # Serialize the role IDs role_ids = [str(role.id) for role in roles if not role.is_default()] serialized_roles = json.dumps(role_ids) @@ -2619,7 +2621,7 @@ async def save_user_roles(user_id, guild_id, roles): close_database_connection(connection) async def restore_user_roles(user, guild): - """Stellt die gespeicherten Rollen eines Users wieder her""" + """Restores a user's saved roles""" connection = None cursor = None try: @@ -2636,14 +2638,14 @@ async def restore_user_roles(user, guild): for role_id in role_ids: role = guild.get_role(int(role_id)) - if role and role < guild.me.top_role: # Überprüfe, ob Bot die Rolle vergeben kann + if role and role < guild.me.top_role: # Check if bot can assign the role roles_to_add.append(role) if roles_to_add: await user.add_roles(*roles_to_add, reason="Mute expired - restoring roles") logger.info(f"Restored {len(roles_to_add)} roles for user {user.id}") - # Lösche die gespeicherten Rollen + # Delete the saved roles delete_query = "DELETE FROM user_saved_roles WHERE user_id = %s AND guild_id = %s" cursor.execute(delete_query, (user.id, guild.id)) connection.commit() @@ -2659,34 +2661,34 @@ async def restore_user_roles(user, guild): close_database_connection(connection) @client.hybrid_command() -async def warn(ctx, user: discord.User, *, reason: str = "Keine Begründung angegeben"): - """Warnt einen Benutzer (Benötigt Permission Level 5 oder höher)""" +async def warn(ctx, user: discord.User, *, reason: str = "No reason provided"): + """Warns a user (Requires Permission Level 5 or higher)""" try: - # Lade Moderator-Daten + # Load moderator data mod_data = await load_user_data(ctx.author.id, ctx.guild.id) - # Überprüfe Moderationsrechte + # Check moderation rights if not check_moderation_permission(mod_data["permission"]): - await ctx.send("❌ Du hast keine Berechtigung, diesen Befehl zu verwenden. (Benötigt Permission Level 5 oder höher)") + await ctx.send("❌ You don't have permission to use this command. (Requires Permission Level 5 or higher)") return - # Lade User-Daten + # Load user data user_data = await load_user_data(user.id, ctx.guild.id) - # Erhöhe Warn-Count + # Increase warn count user_data["warns"] += 1 update_user_data(user.id, ctx.guild.id, "warns", user_data["warns"]) - # Erstelle Embed + # Create embed embed = discord.Embed( - title="⚠️ Warnung erhalten", - description=f"{user.mention} wurde gewarnt.", + title="⚠️ Warning issued", + description=f"{user.mention} has been warned.", color=0xff9500, timestamp=datetime.now() ) - embed.add_field(name="Grund", value=reason, inline=False) + embed.add_field(name="Reason", value=reason, inline=False) embed.add_field(name="Moderator", value=ctx.author.mention, inline=True) - embed.add_field(name="Warn-Count", value=f"{user_data['warns']}", inline=True) + embed.add_field(name="Warning Count", value=f"{user_data['warns']}", inline=True) embed.set_footer(text=f"User ID: {user.id}") await ctx.send(embed=embed) @@ -2694,42 +2696,125 @@ async def warn(ctx, user: discord.User, *, reason: str = "Keine Begründung ange # Log the action logger.info(f"User {user.id} warned by {ctx.author.id} in guild {ctx.guild.id}. Reason: {reason}") - # Auto-Aktionen basierend auf Warn-Count + # Auto-actions based on warning count if user_data["warns"] >= 3: embed_auto = discord.Embed( - title="🚨 Auto-Aktion ausgelöst", - description=f"{user.mention} hat {user_data['warns']} Warnungen erreicht!", + title="🚨 Auto-action triggered", + description=f"{user.mention} has reached {user_data['warns']} warnings!", color=0xff0000 ) - embed_auto.add_field(name="Empfehlung", value="Erwäge weitere Moderationsmaßnahmen", inline=False) + embed_auto.add_field(name="Recommendation", value="Consider further moderation measures", inline=False) await ctx.send(embed=embed_auto) except Exception as e: logger.error(f"Error in warn command: {e}") - await ctx.send("❌ Ein Fehler ist aufgetreten beim Warnen des Benutzers.") + await ctx.send("❌ An error occurred while warning the user.") @client.hybrid_command() -async def mute(ctx, user: discord.User, duration: str, *, reason: str = "Keine Begründung angegeben"): - """Mutet einen Benutzer für eine bestimmte Dauer (Benötigt Permission Level 5 oder höher) +async def mywarns(ctx): + """Shows your current warning count and moderation statistics""" + try: + user_data = await load_user_data(ctx.author.id, ctx.guild.id) + + embed = discord.Embed( + title="📊 Your Moderation Statistics", + description=f"Moderation data for {ctx.author.mention}", + color=0x3498db, + timestamp=datetime.now() + ) + + # Warning information + warn_color = "🟢" if user_data["warns"] == 0 else "🟡" if user_data["warns"] < 3 else "🔴" + embed.add_field( + name=f"{warn_color} Warnings", + value=f"**{user_data['warns']}** warning(s)", + inline=True + ) + + # Mute information + mute_color = "🟢" if user_data["mutes"] == 0 else "🟡" if user_data["mutes"] < 3 else "🔴" + embed.add_field( + name=f"{mute_color} Mutes", + value=f"**{user_data['mutes']}** mute(s)", + inline=True + ) + + # AI Ban information + ai_ban_color = "🟢" if user_data["ai_ban"] == 0 else "🔴" + embed.add_field( + name=f"{ai_ban_color} AI Violations", + value=f"**{user_data['ai_ban']}** violation(s)", + inline=True + ) + + # Status assessment + total_infractions = user_data["warns"] + user_data["mutes"] + user_data["ai_ban"] + if total_infractions == 0: + status = "✅ **Clean Record** - No infractions" + status_color = 0x00ff00 + elif total_infractions <= 2: + status = "⚠️ **Minor Infractions** - Stay careful" + status_color = 0xffa500 + elif total_infractions <= 5: + status = "🔶 **Multiple Infractions** - Improve behavior" + status_color = 0xff6600 + else: + status = "🔴 **High Risk** - Serious moderation attention" + status_color = 0xff0000 + + embed.add_field(name="📈 Status", value=status, inline=False) + embed.color = status_color + + # Get guild settings for thresholds + guild_settings = get_guild_settings(ctx.guild.id) + threshold_info = f"Warning threshold: **{guild_settings['max_warn_threshold']}** warnings" + if guild_settings["auto_mute_on_warns"]: + threshold_info += f"\nAuto-mute duration: **{guild_settings['auto_mute_duration']}**" + + embed.add_field(name="⚙️ Server Settings", value=threshold_info, inline=False) + + # Tips for improvement + if total_infractions > 0: + tips = ( + "� **Tips to improve:**\n" + "• Follow server rules carefully\n" + "• Be respectful to other members\n" + "• Ask moderators if you're unsure about something\n" + "• Avoid spam and inappropriate content" + ) + embed.add_field(name="Improvement Guide", value=tips, inline=False) + + embed.set_thumbnail(url=ctx.author.display_avatar.url) + embed.set_footer(text=f"User ID: {ctx.author.id}") + + await ctx.send(embed=embed) + + except Exception as e: + logger.error(f"Error in mywarns command: {e}") + await ctx.send("❌ An error occurred while retrieving your warning information.") + +@client.hybrid_command() +async def mute(ctx, user: discord.User, duration: str, *, reason: str = "No reason provided"): + """Mutes a user for a specified duration (Requires Permission Level 5 or higher) - Beispiele für Dauer: - - 10m = 10 Minuten - - 1h = 1 Stunde - - 2d = 2 Tage + Duration examples: + - 10m = 10 minutes + - 1h = 1 hour + - 2d = 2 days """ try: - # Lade Moderator-Daten + # Load moderator data mod_data = await load_user_data(ctx.author.id, ctx.guild.id) - # Überprüfe Moderationsrechte + # Check moderation rights if not check_moderation_permission(mod_data["permission"]): - await ctx.send("❌ Du hast keine Berechtigung, diesen Befehl zu verwenden. (Benötigt Permission Level 5 oder höher)") + await ctx.send("❌ You don't have permission to use this command. (Requires Permission Level 5 or higher)") return - # Parse Dauer + # Parse duration time_units = {'m': 60, 'h': 3600, 'd': 86400} if not duration[-1] in time_units or not duration[:-1].isdigit(): - await ctx.send("❌ Ungültiges Zeitformat. Verwende: 10m, 1h, 2d") + await ctx.send("❌ Invalid time format. Use: 10m, 1h, 2d") return duration_seconds = int(duration[:-1]) * time_units[duration[-1]]