modified: app.py

modified:   bot.py
	modified:   templates/server_admin_dashboard.html
	new file:   templates/server_settings.html
This commit is contained in:
SimolZimol
2025-08-19 18:35:32 +02:00
parent 59a9960155
commit 196d2ac570
4 changed files with 1298 additions and 8 deletions

771
bot.py
View File

@@ -112,7 +112,7 @@ loop = asyncio.get_event_loop()
def close_database_connection(connection):
connection.close()
def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filter_value, chat_history, xp=0, level=1, nickname="", profile_picture="", join_date=None, leave_date=None):
def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filter_value, chat_history, xp=0, level=1, nickname="", profile_picture="", join_date=None, leave_date=None, ai_ban=0, mutes=0, warns=0):
"""Fügt neue Benutzerdaten in die Datenbank ein mit Connection Pool"""
connection = None
cursor = None
@@ -120,11 +120,11 @@ def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filt
connection = connect_to_database()
cursor = connection.cursor()
insert_query = """
INSERT INTO user_data (user_id, guild_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level, nickname, profile_picture, join_date, leave_date)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
INSERT INTO user_data (user_id, guild_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level, nickname, profile_picture, join_date, leave_date, ai_ban, mutes, warns)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
serialized_chat_history = json.dumps(chat_history)
data = (user_id, guild_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, xp, level, nickname, profile_picture, join_date, leave_date)
data = (user_id, guild_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, xp, level, nickname, profile_picture, join_date, leave_date, ai_ban, mutes, warns)
cursor.execute(insert_query, data)
connection.commit()
@@ -246,7 +246,10 @@ async def create_user_data_with_member(user_id, guild_id, member=None):
"asknotes_history": [],
"xp": 0,
"level": 1,
"nickname": nickname
"nickname": nickname,
"ai_ban": 0,
"mutes": 0,
"warns": 0
}
insert_user_data(
@@ -292,7 +295,10 @@ def load_user_data_from_mysql(user_id, guild_id):
"asknotes_history": json.loads(result[9]) if result[9] else [],
"xp": int(result[10]) if result[10] is not None else 0,
"level": int(result[11]) if result[11] is not None else 1,
"nickname": result[12]
"nickname": result[12],
"ai_ban": int(result[15]) if len(result) > 15 and result[15] is not None else 0,
"mutes": int(result[16]) if len(result) > 16 and result[16] is not None else 0,
"warns": int(result[17]) if len(result) > 17 and result[17] is not None else 0
}
else:
user_data = {
@@ -308,7 +314,10 @@ def load_user_data_from_mysql(user_id, guild_id):
"asknotes_history": [],
"xp": 0,
"level": 1,
"nickname": ""
"nickname": "",
"ai_ban": 0,
"mutes": 0,
"warns": 0
}
insert_user_data(
user_data["user_id"],
@@ -404,7 +413,10 @@ def load_user_data_sync(user_id, guild_id):
"asknotes_history": [],
"xp": 0,
"level": 1,
"nickname": ""
"nickname": "",
"ai_ban": 0,
"mutes": 0,
"warns": 0
}
insert_user_data(
user_data["user_id"],
@@ -2146,6 +2158,749 @@ async def version(ctx):
"""Displays the current version of the bot."""
await ctx.send(f"The current version of the bot is: {__version__}")
# ================================ GUILD SETTINGS SYSTEM ================================
def get_guild_settings(guild_id):
"""Lädt die Guild-Einstellungen aus der Datenbank"""
connection = None
cursor = None
try:
connection = connect_to_database()
cursor = connection.cursor()
select_query = "SELECT * FROM guild_settings WHERE guild_id = %s"
cursor.execute(select_query, (guild_id,))
result = cursor.fetchone()
if result:
return {
"guild_id": result[0],
"mute_role_id": result[1],
"mute_role_name": result[2] or "Muted",
"auto_create_mute_role": bool(result[3]) if result[3] is not None else True,
"max_warn_threshold": result[4] or 3,
"auto_mute_on_warns": bool(result[5]) if result[5] is not None else False,
"auto_mute_duration": result[6] or "1h",
"log_channel_id": result[7],
"mod_log_enabled": bool(result[8]) if result[8] is not None else True
}
else:
# Erstelle Default-Einstellungen
default_settings = {
"guild_id": guild_id,
"mute_role_id": None,
"mute_role_name": "Muted",
"auto_create_mute_role": True,
"max_warn_threshold": 3,
"auto_mute_on_warns": False,
"auto_mute_duration": "1h",
"log_channel_id": None,
"mod_log_enabled": True
}
save_guild_settings(guild_id, default_settings)
return default_settings
except Exception as e:
logger.error(f"Error loading guild settings: {e}")
# Return default settings on error
return {
"guild_id": guild_id,
"mute_role_id": None,
"mute_role_name": "Muted",
"auto_create_mute_role": True,
"max_warn_threshold": 3,
"auto_mute_on_warns": False,
"auto_mute_duration": "1h",
"log_channel_id": None,
"mod_log_enabled": True
}
finally:
if cursor:
cursor.close()
if connection:
close_database_connection(connection)
def save_guild_settings(guild_id, settings):
"""Speichert Guild-Einstellungen in der Datenbank"""
connection = None
cursor = None
try:
connection = connect_to_database()
cursor = connection.cursor()
insert_query = """
INSERT INTO guild_settings (guild_id, mute_role_id, mute_role_name, auto_create_mute_role,
max_warn_threshold, auto_mute_on_warns, auto_mute_duration,
log_channel_id, mod_log_enabled)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
mute_role_id = VALUES(mute_role_id),
mute_role_name = VALUES(mute_role_name),
auto_create_mute_role = VALUES(auto_create_mute_role),
max_warn_threshold = VALUES(max_warn_threshold),
auto_mute_on_warns = VALUES(auto_mute_on_warns),
auto_mute_duration = VALUES(auto_mute_duration),
log_channel_id = VALUES(log_channel_id),
mod_log_enabled = VALUES(mod_log_enabled)
"""
cursor.execute(insert_query, (
guild_id,
settings.get("mute_role_id"),
settings.get("mute_role_name", "Muted"),
settings.get("auto_create_mute_role", True),
settings.get("max_warn_threshold", 3),
settings.get("auto_mute_on_warns", False),
settings.get("auto_mute_duration", "1h"),
settings.get("log_channel_id"),
settings.get("mod_log_enabled", True)
))
connection.commit()
logger.info(f"Guild settings saved for guild {guild_id}")
except Exception as e:
logger.error(f"Error saving guild settings: {e}")
if connection:
connection.rollback()
finally:
if cursor:
cursor.close()
if connection:
close_database_connection(connection)
async def get_or_create_mute_role(guild, settings):
"""Holt oder erstellt die Mute-Rolle basierend auf Guild-Einstellungen"""
mute_role = None
# Versuche zuerst über ID zu finden
if settings["mute_role_id"]:
mute_role = guild.get_role(settings["mute_role_id"])
if mute_role:
return mute_role
# Versuche über Name zu finden
mute_role = discord.utils.get(guild.roles, name=settings["mute_role_name"])
if mute_role:
# Update die ID in den Einstellungen
settings["mute_role_id"] = mute_role.id
save_guild_settings(guild.id, settings)
return mute_role
# Erstelle neue Rolle, falls auto_create_mute_role aktiviert ist
if settings["auto_create_mute_role"]:
try:
mute_role = await guild.create_role(
name=settings["mute_role_name"],
color=discord.Color.dark_gray(),
reason="Auto-created mute role for moderation system"
)
# Konfiguriere Berechtigungen für alle Kanäle
for channel in guild.channels:
try:
await channel.set_permissions(
mute_role,
send_messages=False,
speak=False,
add_reactions=False,
create_private_threads=False,
create_public_threads=False,
send_messages_in_threads=False
)
except discord.Forbidden:
logger.warning(f"Could not set permissions for {channel.name} in guild {guild.id}")
continue
# Speichere die neue Rolle-ID
settings["mute_role_id"] = mute_role.id
save_guild_settings(guild.id, settings)
logger.info(f"Created mute role '{settings['mute_role_name']}' for guild {guild.id}")
return mute_role
except discord.Forbidden:
logger.error(f"No permission to create mute role in guild {guild.id}")
return None
return None
# ================================ MODERATION SYSTEM ================================
# Moderation Helper Functions
def check_moderation_permission(user_permission):
"""Überprüft, ob der Nutzer Moderationsrechte hat (Permission 5 oder höher)"""
return user_permission >= 5
async def save_user_roles(user_id, guild_id, roles):
"""Speichert die Rollen eines Users vor einem Mute"""
connection = None
cursor = None
try:
connection = connect_to_database()
cursor = connection.cursor()
# Serialisiere die Rollen-IDs
role_ids = [str(role.id) for role in roles if not role.is_default()]
serialized_roles = json.dumps(role_ids)
insert_query = """
INSERT INTO user_saved_roles (user_id, guild_id, roles, saved_at)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE roles = %s, saved_at = %s
"""
current_time = datetime.now()
cursor.execute(insert_query, (user_id, guild_id, serialized_roles, current_time, serialized_roles, current_time))
connection.commit()
logger.info(f"Saved roles for user {user_id} in guild {guild_id}")
except Exception as e:
logger.error(f"Error saving user roles: {e}")
if connection:
connection.rollback()
finally:
if cursor:
cursor.close()
if connection:
close_database_connection(connection)
async def restore_user_roles(user, guild):
"""Stellt die gespeicherten Rollen eines Users wieder her"""
connection = None
cursor = None
try:
connection = connect_to_database()
cursor = connection.cursor()
select_query = "SELECT roles FROM user_saved_roles WHERE user_id = %s AND guild_id = %s"
cursor.execute(select_query, (user.id, guild.id))
result = cursor.fetchone()
if result:
role_ids = json.loads(result[0])
roles_to_add = []
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
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_query = "DELETE FROM user_saved_roles WHERE user_id = %s AND guild_id = %s"
cursor.execute(delete_query, (user.id, guild.id))
connection.commit()
except Exception as e:
logger.error(f"Error restoring user roles: {e}")
if connection:
connection.rollback()
finally:
if cursor:
cursor.close()
if connection:
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)"""
try:
# Lade Moderator-Daten
mod_data = await load_user_data(ctx.author.id, ctx.guild.id)
# Überprüfe Moderationsrechte
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)")
return
# Lade User-Daten
user_data = await load_user_data(user.id, ctx.guild.id)
# Erhöhe Warn-Count
user_data["warns"] += 1
update_user_data(user.id, ctx.guild.id, "warns", user_data["warns"])
# Erstelle Embed
embed = discord.Embed(
title="⚠️ Warnung erhalten",
description=f"{user.mention} wurde gewarnt.",
color=0xff9500,
timestamp=datetime.now()
)
embed.add_field(name="Grund", 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.set_footer(text=f"User ID: {user.id}")
await ctx.send(embed=embed)
# 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
if user_data["warns"] >= 3:
embed_auto = discord.Embed(
title="🚨 Auto-Aktion ausgelöst",
description=f"{user.mention} hat {user_data['warns']} Warnungen erreicht!",
color=0xff0000
)
embed_auto.add_field(name="Empfehlung", value="Erwäge weitere Moderationsmaßnahmen", 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.")
@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)
Beispiele für Dauer:
- 10m = 10 Minuten
- 1h = 1 Stunde
- 2d = 2 Tage
"""
try:
# Lade Moderator-Daten
mod_data = await load_user_data(ctx.author.id, ctx.guild.id)
# Überprüfe Moderationsrechte
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)")
return
# Parse Dauer
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")
return
duration_seconds = int(duration[:-1]) * time_units[duration[-1]]
end_time = datetime.now() + timedelta(seconds=duration_seconds)
# Hole Member-Objekt
member = ctx.guild.get_member(user.id)
if not member:
await ctx.send("❌ Benutzer nicht auf diesem Server gefunden.")
return
# Lade Guild-Einstellungen
guild_settings = get_guild_settings(ctx.guild.id)
# Speichere aktuelle Rollen
await save_user_roles(user.id, ctx.guild.id, member.roles)
# Entferne alle Rollen außer @everyone
roles_to_remove = [role for role in member.roles if not role.is_default()]
if roles_to_remove:
await member.remove_roles(*roles_to_remove, reason=f"Muted by {ctx.author}")
# Hole oder erstelle Mute-Rolle basierend auf Einstellungen
mute_role = await get_or_create_mute_role(ctx.guild, guild_settings)
if not mute_role:
await ctx.send("❌ Konnte Mute-Rolle nicht finden oder erstellen. Überprüfe die Server-Einstellungen.")
return
# Vergebe Mute-Rolle
await member.add_roles(mute_role, reason=f"Muted by {ctx.author} for {duration}")
# Update User-Daten
user_data = await load_user_data(user.id, ctx.guild.id)
user_data["mutes"] += 1
update_user_data(user.id, ctx.guild.id, "mutes", user_data["mutes"])
# Erstelle Active Process für Auto-Unmute
process_data = {
"user_id": user.id,
"guild_id": ctx.guild.id,
"channel_id": ctx.channel.id,
"reason": reason,
"moderator_id": ctx.author.id,
"mute_role_id": mute_role.id
}
process_uuid = create_active_process(
process_type="mute",
guild_id=ctx.guild.id,
channel_id=ctx.channel.id,
user_id=user.id,
target_id=user.id,
end_time=end_time,
data=process_data
)
# Erstelle Embed
embed = discord.Embed(
title="🔇 Benutzer gemutet",
description=f"{user.mention} wurde gemutet.",
color=0xff0000,
timestamp=datetime.now()
)
embed.add_field(name="Dauer", value=duration, inline=True)
embed.add_field(name="Endet am", value=end_time.strftime("%Y-%m-%d %H:%M:%S"), inline=True)
embed.add_field(name="Grund", value=reason, inline=False)
embed.add_field(name="Moderator", value=ctx.author.mention, inline=True)
embed.add_field(name="Mute-Count", value=f"{user_data['mutes']}", inline=True)
embed.set_footer(text=f"User ID: {user.id} | Process ID: {str(process_uuid)[:8]}")
await ctx.send(embed=embed)
# Log the action
logger.info(f"User {user.id} muted by {ctx.author.id} in guild {ctx.guild.id} for {duration}. Reason: {reason}")
except Exception as e:
logger.error(f"Error in mute command: {e}")
await ctx.send("❌ Ein Fehler ist aufgetreten beim Muten des Benutzers.")
@client.hybrid_command()
async def unmute(ctx, user: discord.User):
"""Entmutet einen Benutzer manuell (Benötigt Permission Level 5 oder höher)"""
try:
# Lade Moderator-Daten
mod_data = await load_user_data(ctx.author.id, ctx.guild.id)
# Überprüfe Moderationsrechte
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)")
return
# Hole Member-Objekt
member = ctx.guild.get_member(user.id)
if not member:
await ctx.send("❌ Benutzer nicht auf diesem Server gefunden.")
return
# Lade Guild-Einstellungen
guild_settings = get_guild_settings(ctx.guild.id)
# Finde Mute-Rolle basierend auf Einstellungen
mute_role = None
if guild_settings["mute_role_id"]:
mute_role = ctx.guild.get_role(guild_settings["mute_role_id"])
if not mute_role:
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:
await ctx.send("❌ Benutzer ist nicht gemutet.")
return
# Entferne Mute-Rolle
await member.remove_roles(mute_role, reason=f"Unmuted by {ctx.author}")
# Stelle Rollen wieder her
await restore_user_roles(member, ctx.guild)
# Finde und aktualisiere aktiven Mute-Prozess
active_processes = get_active_processes(process_type="mute", guild_id=ctx.guild.id)
for process in active_processes:
if process["target_id"] == user.id:
update_process_status(process["uuid"], "cancelled_manual")
break
# Erstelle Embed
embed = discord.Embed(
title="🔊 Benutzer entmutet",
description=f"{user.mention} wurde entmutet.",
color=0x00ff00,
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)
# Log the action
logger.info(f"User {user.id} unmuted by {ctx.author.id} in guild {ctx.guild.id}")
except Exception as e:
logger.error(f"Error in unmute command: {e}")
await ctx.send("❌ Ein Fehler ist aufgetreten beim Entmuten des Benutzers.")
@client.hybrid_command()
async def modstats(ctx, user: discord.User = None):
"""Zeigt Moderationsstatistiken für einen Benutzer an"""
try:
# Falls kein User angegeben, zeige eigene Stats
target_user = user or ctx.author
# Lade User-Daten
user_data = await load_user_data(target_user.id, ctx.guild.id)
# Erstelle Embed
embed = discord.Embed(
title=f"📊 Moderationsstatistiken",
description=f"Statistiken für {target_user.mention}",
color=0x3498db,
timestamp=datetime.now()
)
embed.add_field(name="🤖 AI Bans", value=user_data.get("ai_ban", 0), inline=True)
embed.add_field(name="🔇 Mutes", value=user_data.get("mutes", 0), inline=True)
embed.add_field(name="⚠️ Warnungen", value=user_data.get("warns", 0), inline=True)
embed.add_field(name="🛡️ Permission Level", value=user_data.get("permission", 0), inline=True)
embed.add_field(name="⭐ Level", value=user_data.get("level", 1), inline=True)
embed.add_field(name="💰 Punkte", value=user_data.get("points", 0), inline=True)
embed.set_thumbnail(url=target_user.display_avatar.url)
embed.set_footer(text=f"User ID: {target_user.id}")
await ctx.send(embed=embed)
except Exception as e:
logger.error(f"Error in modstats command: {e}")
await ctx.send("❌ Ein Fehler ist aufgetreten beim Laden der Moderationsstatistiken.")
@client.hybrid_command()
async def modconfig(ctx, setting: str = None, *, value: str = None):
"""Konfiguriert Moderationseinstellungen für den Server (Benötigt Permission Level 8 oder höher)
Verfügbare Einstellungen:
- mute_role <@role/role_name> - Setzt die Mute-Rolle
- mute_role_name <name> - Setzt den Namen für auto-erstellte Mute-Rollen
- auto_create_mute_role <true/false> - Auto-Erstellung von Mute-Rollen
- max_warn_threshold <number> - Anzahl Warnungen vor Auto-Aktion
- auto_mute_on_warns <true/false> - Auto-Mute bei zu vielen Warnungen
- auto_mute_duration <duration> - Dauer für Auto-Mutes (z.B. 1h, 30m)
- log_channel <#channel> - Kanal für Moderations-Logs
- mod_log_enabled <true/false> - Aktiviert/Deaktiviert Moderations-Logs
"""
try:
# Lade Moderator-Daten
mod_data = await load_user_data(ctx.author.id, ctx.guild.id)
# Überprüfe Admin-Rechte (Level 8+)
if mod_data["permission"] < 8:
await ctx.send("❌ Du hast keine Berechtigung, Moderationseinstellungen zu ändern. (Benötigt Permission Level 8 oder höher)")
return
# Lade aktuelle Einstellungen
guild_settings = get_guild_settings(ctx.guild.id)
# Zeige Einstellungen an, falls keine Parameter
if not setting:
embed = discord.Embed(
title="🛠️ Moderationseinstellungen",
description=f"Aktuelle Einstellungen für **{ctx.guild.name}**",
color=0x3498db,
timestamp=datetime.now()
)
# Mute-Rolle Info
mute_role_info = "Nicht gesetzt"
if guild_settings["mute_role_id"]:
role = ctx.guild.get_role(guild_settings["mute_role_id"])
mute_role_info = role.mention if role else f"❌ Rolle nicht gefunden (ID: {guild_settings['mute_role_id']})"
embed.add_field(name="🔇 Mute-Rolle", value=mute_role_info, inline=False)
embed.add_field(name="📝 Mute-Rollen-Name", value=guild_settings["mute_role_name"], inline=True)
embed.add_field(name="🔧 Auto-Erstellen", value="" if guild_settings["auto_create_mute_role"] else "", inline=True)
embed.add_field(name="⚠️ Warn-Limit", value=guild_settings["max_warn_threshold"], inline=True)
embed.add_field(name="🔄 Auto-Mute bei Warns", value="" if guild_settings["auto_mute_on_warns"] else "", inline=True)
embed.add_field(name="⏱️ Auto-Mute-Dauer", value=guild_settings["auto_mute_duration"], inline=True)
# Log-Kanal Info
log_info = "Nicht gesetzt"
if guild_settings["log_channel_id"]:
channel = ctx.guild.get_channel(guild_settings["log_channel_id"])
log_info = channel.mention if channel else f"❌ Kanal nicht gefunden (ID: {guild_settings['log_channel_id']})"
embed.add_field(name="📊 Log-Kanal", value=log_info, inline=True)
embed.add_field(name="📝 Logs Aktiviert", value="" if guild_settings["mod_log_enabled"] else "", inline=True)
embed.set_footer(text="Verwende -modconfig <setting> <value> zum Ändern")
await ctx.send(embed=embed)
return
# Ändere Einstellungen
setting = setting.lower()
if setting == "mute_role":
if not value:
await ctx.send("❌ Bitte gib eine Rolle an: `-modconfig mute_role @MuteRole`")
return
# Parse Rolle
role = None
if value.startswith("<@&") and value.endswith(">"):
role_id = int(value[3:-1])
role = ctx.guild.get_role(role_id)
else:
role = discord.utils.get(ctx.guild.roles, name=value)
if not role:
await ctx.send("❌ Rolle nicht gefunden.")
return
guild_settings["mute_role_id"] = role.id
guild_settings["mute_role_name"] = role.name
save_guild_settings(ctx.guild.id, guild_settings)
await ctx.send(f"✅ Mute-Rolle auf {role.mention} gesetzt.")
elif setting == "mute_role_name":
if not value:
await ctx.send("❌ Bitte gib einen Namen an: `-modconfig mute_role_name Stumm`")
return
guild_settings["mute_role_name"] = value
save_guild_settings(ctx.guild.id, guild_settings)
await ctx.send(f"✅ Mute-Rollen-Name auf `{value}` gesetzt.")
elif setting == "auto_create_mute_role":
if value.lower() in ["true", "1", "ja", "yes", "on"]:
guild_settings["auto_create_mute_role"] = True
await ctx.send("✅ Auto-Erstellung von Mute-Rollen aktiviert.")
elif value.lower() in ["false", "0", "nein", "no", "off"]:
guild_settings["auto_create_mute_role"] = False
await ctx.send("✅ Auto-Erstellung von Mute-Rollen deaktiviert.")
else:
await ctx.send("❌ Ungültiger Wert. Verwende: true/false")
return
save_guild_settings(ctx.guild.id, guild_settings)
elif setting == "max_warn_threshold":
try:
threshold = int(value)
if threshold < 1 or threshold > 10:
await ctx.send("❌ Warn-Limit muss zwischen 1 und 10 liegen.")
return
guild_settings["max_warn_threshold"] = threshold
save_guild_settings(ctx.guild.id, guild_settings)
await ctx.send(f"✅ Warn-Limit auf {threshold} gesetzt.")
except ValueError:
await ctx.send("❌ Ungültiger Wert. Verwende eine Nummer zwischen 1 und 10.")
return
elif setting == "auto_mute_on_warns":
if value.lower() in ["true", "1", "ja", "yes", "on"]:
guild_settings["auto_mute_on_warns"] = True
await ctx.send("✅ Auto-Mute bei zu vielen Warnungen aktiviert.")
elif value.lower() in ["false", "0", "nein", "no", "off"]:
guild_settings["auto_mute_on_warns"] = False
await ctx.send("✅ Auto-Mute bei zu vielen Warnungen deaktiviert.")
else:
await ctx.send("❌ Ungültiger Wert. Verwende: true/false")
return
save_guild_settings(ctx.guild.id, guild_settings)
elif setting == "auto_mute_duration":
# Validiere Dauer-Format
time_units = {'m': 60, 'h': 3600, 'd': 86400}
if not value or not value[-1] in time_units or not value[:-1].isdigit():
await ctx.send("❌ Ungültiges Zeitformat. Verwende: 10m, 1h, 2d")
return
guild_settings["auto_mute_duration"] = value
save_guild_settings(ctx.guild.id, guild_settings)
await ctx.send(f"✅ Auto-Mute-Dauer auf {value} gesetzt.")
elif setting == "log_channel":
if not value:
await ctx.send("❌ Bitte gib einen Kanal an: `-modconfig log_channel #mod-log`")
return
# Parse Kanal
channel = None
if value.startswith("<#") and value.endswith(">"):
channel_id = int(value[2:-1])
channel = ctx.guild.get_channel(channel_id)
else:
channel = discord.utils.get(ctx.guild.channels, name=value.replace("#", ""))
if not channel:
await ctx.send("❌ Kanal nicht gefunden.")
return
guild_settings["log_channel_id"] = channel.id
save_guild_settings(ctx.guild.id, guild_settings)
await ctx.send(f"✅ Log-Kanal auf {channel.mention} gesetzt.")
elif setting == "mod_log_enabled":
if value.lower() in ["true", "1", "ja", "yes", "on"]:
guild_settings["mod_log_enabled"] = True
await ctx.send("✅ Moderations-Logs aktiviert.")
elif value.lower() in ["false", "0", "nein", "no", "off"]:
guild_settings["mod_log_enabled"] = False
await ctx.send("✅ Moderations-Logs deaktiviert.")
else:
await ctx.send("❌ Ungültiger Wert. Verwende: true/false")
return
save_guild_settings(ctx.guild.id, guild_settings)
else:
await ctx.send("❌ Unbekannte Einstellung. Verwende `-modconfig` ohne Parameter für eine Liste aller Einstellungen.")
except Exception as e:
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):