diff --git a/bot.py b/bot.py index af0a9eb..1866e67 100644 --- a/bot.py +++ b/bot.py @@ -790,17 +790,94 @@ async def handle_expired_giveaway(process_uuid, data): update_process_status(process_uuid, "failed") async def handle_expired_mute(process_uuid, data): - """Handles expired mute processes - placeholder for future implementation""" + """Handles expired mute processes""" try: - # TODO: Implement mute removal logic guild_id = data.get("guild_id") user_id = data.get("user_id") + mute_role_id = data.get("mute_role_id") + channel_id = data.get("channel_id") + reason = data.get("reason", "Automatic unmute - time expired") - logger.info(f"Mute expired for user {user_id} in guild {guild_id}") + if not guild_id or not user_id: + logger.error(f"Missing guild_id or user_id in mute process {process_uuid}") + update_process_status(process_uuid, "failed") + return + + # Get guild and member + guild = client.get_guild(int(guild_id)) + if not guild: + logger.error(f"Guild {guild_id} not found for expired mute {process_uuid}") + update_process_status(process_uuid, "failed") + return + + member = guild.get_member(int(user_id)) + if not member: + logger.info(f"User {user_id} no longer in guild {guild_id}, marking mute as completed") + update_process_status(process_uuid, "completed") + return + + # Get mute role + mute_role = None + if mute_role_id: + mute_role = guild.get_role(int(mute_role_id)) + + # If mute role not found, try to get it from guild settings + if not mute_role: + guild_settings = get_guild_settings(guild_id) + if guild_settings and guild_settings.get("mute_role_id"): + mute_role = guild.get_role(int(guild_settings["mute_role_id"])) + + # Remove mute role if user still has it + if mute_role and mute_role in member.roles: + await member.remove_roles(mute_role, reason="Automatic unmute - time expired") + logger.info(f"Removed mute role from user {user_id} in guild {guild_id}") + + # Restore previous roles if they were saved + try: + restored_roles = await restore_user_roles(member, guild) + if restored_roles: + logger.info(f"Restored {len(restored_roles)} roles for user {user_id} in guild {guild_id}") + except Exception as e: + logger.warning(f"Could not restore roles for user {user_id}: {e}") + + # Send notification to channel if possible + if channel_id: + try: + channel = guild.get_channel(int(channel_id)) + if 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="πŸ“ Reason", value="Mute duration expired", inline=False) + embed.set_footer(text=f"Process ID: {process_uuid}") + await channel.send(embed=embed) + except Exception as e: + logger.warning(f"Could not send unmute notification: {e}") + + # Try to DM the user + try: + user = await client.fetch_user(int(user_id)) + if user: + dm_embed = discord.Embed( + title="πŸ”Š You have been unmuted", + description=f"Your mute in **{guild.name}** has expired.", + color=0x00ff00, + timestamp=datetime.now() + ) + dm_embed.set_footer(text=f"Server: {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"Successfully unmuted user {user_id} in guild {guild_id}") update_process_status(process_uuid, "completed") except Exception as e: logger.error(f"Error handling expired mute {process_uuid}: {e}") + update_process_status(process_uuid, "failed") async def handle_expired_ban(process_uuid, data): """Handles expired ban processes - placeholder for future implementation""" @@ -836,6 +913,9 @@ async def restore_active_processes_on_startup(): if process["process_type"] == "giveaway": await restore_giveaway_process(process) restored_count += 1 + elif process["process_type"] == "mute": + await restore_mute_process(process) + restored_count += 1 # Add more process types as needed except Exception as e: @@ -869,6 +949,58 @@ async def restore_giveaway_process(process): except Exception as e: logger.error(f"Error restoring giveaway process: {e}") +async def restore_mute_process(process): + """Restores a mute process from the database""" + try: + logger.info(f"Restoring mute process {process['uuid']}") + + # Extract process data + data = process.get("data", {}) + user_id = data.get("user_id") or process.get("user_id") + guild_id = data.get("guild_id") or process.get("guild_id") + end_time = process.get("end_time") + + if not user_id or not guild_id or not end_time: + logger.error(f"Missing required data for mute process {process['uuid']}") + update_process_status(process["uuid"], "error") + return + + # Get guild and user + guild = client.get_guild(int(guild_id)) + if not guild: + logger.error(f"Guild {guild_id} not found for mute process {process['uuid']}") + update_process_status(process["uuid"], "error") + return + + member = guild.get_member(int(user_id)) + if not member: + logger.info(f"User {user_id} no longer in guild {guild_id}, marking mute process as completed") + update_process_status(process["uuid"], "completed") + return + + # Check if mute has already expired + if datetime.now() >= end_time: + logger.info(f"Mute process {process['uuid']} has already expired, executing unmute") + await handle_expired_process(process["uuid"], "mute", data) + else: + # Schedule the unmute for when it's supposed to end + remaining_time = (end_time - datetime.now()).total_seconds() + logger.info(f"Scheduling mute process {process['uuid']} to complete in {remaining_time:.0f} seconds") + + # Check if the user is actually still muted (has mute role) + mute_role_id = data.get("mute_role_id") + if mute_role_id: + mute_role = guild.get_role(int(mute_role_id)) + if mute_role and mute_role in member.roles: + logger.info(f"User {user_id} still has mute role, mute process {process['uuid']} is valid") + else: + logger.info(f"User {user_id} no longer has mute role, marking process as completed") + update_process_status(process["uuid"], "completed") + + except Exception as e: + logger.error(f"Error restoring mute process: {e}") + update_process_status(process["uuid"], "error") + #----------------------------------------------------------------------------------------------------------- async def update_all_users(batch_size=20, pause_duration=1): @@ -4417,59 +4549,6 @@ async def modconfig(ctx, setting: str = None, *, value: str = None): logger.error(f"Error in modconfig command: {e}") await ctx.send("❌ Ein Fehler ist aufgetreten beim Konfigurieren der Moderationseinstellungen.") -# Erweitere handle_expired_mute Funktion -async def handle_expired_mute(process_uuid, data): - """Handles expired mute processes""" - try: - guild_id = data.get("guild_id") - user_id = data.get("user_id") - mute_role_id = data.get("mute_role_id") - - if not all([guild_id, user_id]): - logger.error(f"Missing data in mute process {process_uuid}") - update_process_status(process_uuid, "failed") - return - - # Hole Guild und Member - guild = client.get_guild(guild_id) - if not guild: - logger.error(f"Guild {guild_id} not found for mute process {process_uuid}") - update_process_status(process_uuid, "failed") - return - - member = guild.get_member(user_id) - if not member: - logger.warning(f"Member {user_id} not found in guild {guild_id} for mute process {process_uuid}") - update_process_status(process_uuid, "completed") - return - - # Finde Mute-Rolle basierend auf Guild-Einstellungen - guild_settings = get_guild_settings(guild_id) - mute_role = None - - if mute_role_id: - mute_role = guild.get_role(mute_role_id) - - if not mute_role and guild_settings["mute_role_id"]: - mute_role = guild.get_role(guild_settings["mute_role_id"]) - - if not mute_role: - mute_role = discord.utils.get(guild.roles, name=guild_settings["mute_role_name"]) - - # Entferne Mute-Rolle falls vorhanden - if mute_role and mute_role in member.roles: - await member.remove_roles(mute_role, reason="Mute expired automatically") - - # Stelle Rollen wieder her - await restore_user_roles(member, guild) - - update_process_status(process_uuid, "completed") - logger.info(f"Successfully unmuted user {user_id} in guild {guild_id} (expired mute)") - - except Exception as e: - logger.error(f"Error handling expired mute {process_uuid}: {e}") - update_process_status(process_uuid, "failed") - # Cache-Ordner fΓΌr Notizen CACHE_DIR = "cache" if not os.path.exists(CACHE_DIR):