modified: bot.py

This commit is contained in:
SimolZimol
2025-10-07 16:12:45 +02:00
parent 505da5554b
commit 7012475a72

242
bot.py
View File

@@ -915,8 +915,34 @@ async def handle_expired_mute(process_uuid, data):
except Exception as e: except Exception as e:
logger.warning(f"Could not restore roles for user {user_id}: {e}") logger.warning(f"Could not restore roles for user {user_id}: {e}")
# Send notification to channel if possible # Send notification to mod log channel (preferred) or original channel as fallback
if channel_id: notification_sent = False
# Try to send to mod log channel first
try:
guild_settings = get_guild_settings(guild_id)
if guild_settings and guild_settings.get("mod_log_channel_id"):
mod_log_channel = guild.get_channel(int(guild_settings["mod_log_channel_id"]))
if mod_log_channel:
embed = discord.Embed(
title="🔊 User Automatically Unmuted",
description=f"{member.mention} has been automatically unmuted.",
color=0x00ff00,
timestamp=datetime.now()
)
embed.add_field(name="👤 User", value=f"{member.mention}\n`{member.id}`", inline=True)
embed.add_field(name="📝 Reason", value="Mute duration expired", inline=True)
embed.add_field(name="📍 Original Channel", value=f"<#{channel_id}>" if channel_id else "Unknown", inline=True)
embed.set_footer(text=f"Process ID: {process_uuid}")
embed.set_thumbnail(url=member.display_avatar.url)
await mod_log_channel.send(embed=embed)
notification_sent = True
logger.info(f"Sent auto-unmute notification to mod log channel for user {user_id}")
except Exception as e:
logger.warning(f"Could not send unmute notification to mod log channel: {e}")
# Fallback to original channel if mod log failed
if not notification_sent and channel_id:
try: try:
channel = guild.get_channel(int(channel_id)) channel = guild.get_channel(int(channel_id))
if channel: if channel:
@@ -929,8 +955,13 @@ async def handle_expired_mute(process_uuid, data):
embed.add_field(name="📝 Reason", value="Mute duration expired", inline=False) embed.add_field(name="📝 Reason", value="Mute duration expired", inline=False)
embed.set_footer(text=f"Process ID: {process_uuid}") embed.set_footer(text=f"Process ID: {process_uuid}")
await channel.send(embed=embed) await channel.send(embed=embed)
notification_sent = True
logger.info(f"Sent auto-unmute notification to original channel for user {user_id}")
except Exception as e: except Exception as e:
logger.warning(f"Could not send unmute notification: {e}") logger.warning(f"Could not send unmute notification to original channel: {e}")
if not notification_sent:
logger.warning(f"No channel available for auto-unmute notification for user {user_id}")
# Try to DM the user # Try to DM the user
try: try:
@@ -5498,26 +5529,63 @@ async def mute(ctx, user: discord.User, duration: str, reason: str = "No reason
@client.hybrid_command() @client.hybrid_command()
async def unmute(ctx, user: discord.User): async def unmute(ctx, user: discord.User):
"""Entmutet einen Benutzer manuell (Benötigt Permission Level 5 oder höher)""" """Unmutes a user manually (Requires Permission Level 5 or higher)"""
# Check if it's a slash command and defer if needed
is_slash_command = hasattr(ctx, 'interaction') and ctx.interaction
if is_slash_command:
await ctx.defer()
# Helper function for sending responses
async def send_response(content=None, embed=None, ephemeral=False, file=None):
try:
if is_slash_command:
if hasattr(ctx, 'followup') and ctx.followup:
await ctx.followup.send(content=content, embed=embed, ephemeral=ephemeral, file=file)
elif hasattr(ctx, 'response') and not ctx.response.is_done():
await ctx.response.send_message(content=content, embed=embed, ephemeral=ephemeral, file=file)
else:
await ctx.send(content=content, embed=embed, file=file)
else:
await ctx.send(content=content, embed=embed, file=file)
except Exception as e:
logger.error(f"Error sending response in unmute command: {e}")
try:
if embed:
await ctx.send(embed=embed)
elif content:
await ctx.send(content=content)
except Exception as fallback_error:
logger.error(f"Fallback send also failed: {fallback_error}")
try: try:
# Lade Moderator-Daten # Load moderator data
mod_data = await load_user_data(ctx.author.id, ctx.guild.id) mod_data = await load_user_data(ctx.author.id, ctx.guild.id)
# Überprüfe Moderationsrechte # Check moderation permissions
if not check_moderation_permission(mod_data["permission"]): 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)") embed = discord.Embed(
title="❌ Insufficient Permissions",
description="You need moderation permissions (Level 5 or higher) to use this command.",
color=0xff0000
)
await send_response(embed=embed, ephemeral=True)
return return
# Hole Member-Objekt # Get member object
member = ctx.guild.get_member(user.id) member = ctx.guild.get_member(user.id)
if not member: if not member:
await ctx.send("❌ Benutzer nicht auf diesem Server gefunden.") embed = discord.Embed(
title="❌ User Not Found",
description="User not found on this server.",
color=0xff0000
)
await send_response(embed=embed, ephemeral=True)
return return
# Lade Guild-Einstellungen # Load guild settings
guild_settings = get_guild_settings(ctx.guild.id) guild_settings = get_guild_settings(ctx.guild.id)
# Finde Mute-Rolle basierend auf Einstellungen # Find mute role based on settings
mute_role = None mute_role = None
if guild_settings["mute_role_id"]: if guild_settings["mute_role_id"]:
mute_role = ctx.guild.get_role(guild_settings["mute_role_id"]) mute_role = ctx.guild.get_role(guild_settings["mute_role_id"])
@@ -5526,40 +5594,160 @@ async def unmute(ctx, user: discord.User):
mute_role = discord.utils.get(ctx.guild.roles, name=guild_settings["mute_role_name"]) mute_role = discord.utils.get(ctx.guild.roles, name=guild_settings["mute_role_name"])
if not mute_role or mute_role not in member.roles: if not mute_role or mute_role not in member.roles:
await ctx.send("❌ Benutzer ist nicht gemutet.") embed = discord.Embed(
title="❌ User Not Muted",
description="This user is not currently muted.",
color=0xff0000
)
await send_response(embed=embed, ephemeral=True)
return return
# Entferne Mute-Rolle # Find active mute records in user_mutes table
await member.remove_roles(mute_role, reason=f"Unmuted by {ctx.author}") connection = None
cursor = None
active_mute_records = []
# Stelle Rollen wieder her try:
await restore_user_roles(member, ctx.guild) connection = connect_to_database()
cursor = connection.cursor()
# Finde und aktualisiere aktiven Mute-Prozess # Get active mute records for this user
select_query = """
SELECT id, process_uuid, reason, start_time, end_time, duration
FROM user_mutes
WHERE user_id = %s AND guild_id = %s AND aktiv = TRUE AND status = 'active'
ORDER BY start_time DESC
"""
cursor.execute(select_query, (user.id, ctx.guild.id))
results = cursor.fetchall()
for result in results:
mute_id, process_uuid, reason, start_time, end_time, duration = result
active_mute_records.append({
'id': mute_id,
'process_uuid': process_uuid,
'reason': reason,
'start_time': start_time,
'end_time': end_time,
'duration': duration
})
finally:
if cursor:
cursor.close()
if connection:
close_database_connection(connection)
if not active_mute_records:
embed = discord.Embed(
title="❌ No Active Mutes Found",
description="No active mute records found for this user in the database.",
color=0xff0000
)
await send_response(embed=embed, ephemeral=True)
return
# Remove mute role
await member.remove_roles(mute_role, reason=f"Manually unmuted by {ctx.author}")
# Restore user roles
try:
restored_roles = await restore_user_roles(member, ctx.guild)
restored_count = len(restored_roles) if restored_roles else 0
except Exception as e:
logger.warning(f"Could not restore roles for user {user.id}: {e}")
restored_count = 0
# Deactivate all active mute records
deactivated_mutes = []
for mute_record in active_mute_records:
try:
await deactivate_mute(mute_record['id'], unmuted_by=ctx.author.id, auto_unmuted=False)
deactivated_mutes.append(mute_record)
except Exception as e:
logger.error(f"Error deactivating mute record {mute_record['id']}: {e}")
# Cancel active processes
cancelled_processes = []
active_processes = get_active_processes(process_type="mute", guild_id=ctx.guild.id) active_processes = get_active_processes(process_type="mute", guild_id=ctx.guild.id)
for process in active_processes: for process in active_processes:
if process["target_id"] == user.id: if process["target_id"] == user.id:
update_process_status(process["uuid"], "cancelled_manual") update_process_status(process["uuid"], "cancelled")
break cancelled_processes.append(process["uuid"])
# Erstelle Embed # Create success embed
embed = discord.Embed( embed = discord.Embed(
title="🔊 Benutzer entmutet", title="🔊 User Unmuted Successfully",
description=f"{user.mention} wurde entmutet.", description=f"{user.mention} has been manually unmuted.",
color=0x00ff00, color=0x00ff00,
timestamp=datetime.now() timestamp=datetime.now()
) )
embed.add_field(name="Moderator", value=ctx.author.mention, inline=True)
embed.set_footer(text=f"User ID: {user.id}")
await ctx.send(embed=embed) embed.add_field(name="👮 Moderator", value=ctx.author.mention, inline=True)
embed.add_field(name="🔓 Mutes Deactivated", value=str(len(deactivated_mutes)), inline=True)
if restored_count > 0:
embed.add_field(name="🎭 Roles Restored", value=str(restored_count), inline=True)
# Show deactivated mute details
if deactivated_mutes:
mute_details = []
for mute in deactivated_mutes[:3]: # Show first 3 mutes
mute_info = f"**ID {mute['id']}**: {mute['reason'][:30]}{'...' if len(mute['reason']) > 30 else ''}"
mute_info += f" ({mute['duration']})"
mute_details.append(mute_info)
if len(deactivated_mutes) > 3:
mute_details.append(f"*+{len(deactivated_mutes) - 3} more mutes deactivated*")
embed.add_field(name="📋 Deactivated Mutes", value="\n".join(mute_details), inline=False)
embed.set_footer(text=f"User ID: {user.id} | {len(cancelled_processes)} process(es) cancelled")
embed.set_thumbnail(url=user.display_avatar.url)
await send_response(embed=embed)
# Log the action # Log the action
logger.info(f"User {user.id} unmuted by {ctx.author.id} in guild {ctx.guild.id}") log_additional_info = {
"Mutes Deactivated": str(len(deactivated_mutes)),
"Roles Restored": str(restored_count),
"Processes Cancelled": str(len(cancelled_processes))
}
await log_moderation_action(
guild=ctx.guild,
action_type="unmute",
moderator=ctx.author,
target_user=user,
reason="Manual unmute",
additional_info=log_additional_info
)
# Try to DM the user
try:
dm_embed = discord.Embed(
title="🔊 You have been unmuted",
description=f"Your mute in **{ctx.guild.name}** has been manually removed by a moderator.",
color=0x00ff00,
timestamp=datetime.now()
)
dm_embed.add_field(name="👮 Unmuted by", value=ctx.author.mention, inline=True)
dm_embed.set_footer(text=f"Server: {ctx.guild.name}")
await user.send(embed=dm_embed)
except (discord.Forbidden, discord.NotFound):
pass # User has DMs disabled or doesn't exist
logger.info(f"User {user.id} manually unmuted by {ctx.author.id} in guild {ctx.guild.id} - {len(deactivated_mutes)} mute(s) deactivated")
except Exception as e: except Exception as e:
logger.error(f"Error in unmute command: {e}") logger.error(f"Error in unmute command: {e}")
await ctx.send("❌ Ein Fehler ist aufgetreten beim Entmuten des Benutzers.") embed = discord.Embed(
title="❌ Error",
description="An error occurred while unmuting the user.",
color=0xff0000
)
await send_response(embed=embed, ephemeral=True)
@client.hybrid_command() @client.hybrid_command()
async def listmutes(ctx, status: str = "active"): async def listmutes(ctx, status: str = "active"):