import discord from discord.ext import commands from discord import app_commands import sqlite3 import datetime class AuditLog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self.db_connection = sqlite3.connect("xalos_data.db") self.db_cursor = self.db_connection.cursor() # Tabelle für server-spezifische Einstellungen self.db_cursor.execute(""" CREATE TABLE IF NOT EXISTS server_configs ( guild_id INTEGER PRIMARY KEY, log_channel_id INTEGER ) """) async def get_log_channel(self, guild_id: int) -> discord.TextChannel | None: """Holt den Log-Kanal für einen Server aus der DB.""" self.db_cursor.execute("SELECT log_channel_id FROM server_configs WHERE guild_id = ?", (guild_id,)) result = self.db_cursor.fetchone() if result and result[0]: return self.bot.get_channel(result[0]) return None @app_commands.command(name="setlogchannel", description="Setzt den Kanal für die Audit-Logs.") @app_commands.describe(channel="Der Kanal, in den die Logs gesendet werden sollen.") @app_commands.checks.has_permissions(manage_guild=True) async def set_log_channel(self, interaction: discord.Interaction, channel: discord.TextChannel): """Speichert den Log-Kanal in der Datenbank.""" self.db_cursor.execute( "INSERT OR REPLACE INTO server_configs (guild_id, log_channel_id) VALUES (?, ?)", (interaction.guild.id, channel.id) ) self.db_connection.commit() await interaction.response.send_message(f"✅ Der Log-Kanal wurde auf {channel.mention} gesetzt.", ephemeral=True) @commands.Cog.listener() async def on_message_delete(self, message: discord.Message): if message.author.bot or not message.guild: return log_channel = await self.get_log_channel(message.guild.id) if log_channel: embed = discord.Embed( title="🗑️ Nachricht gelöscht", description=f"**Autor:** {message.author.mention}\n" f"**Kanal:** {message.channel.mention}", color=discord.Color.orange(), timestamp=datetime.datetime.now(datetime.timezone.utc) ) # Füge den Inhalt hinzu, wenn er nicht zu lang ist if message.content: embed.add_field(name="Inhalt", value=message.content[:1024], inline=False) await log_channel.send(embed=embed) @commands.Cog.listener() async def on_message_edit(self, before: discord.Message, after: discord.Message): if before.author.bot or not before.guild or before.content == after.content: return log_channel = await self.get_log_channel(before.guild.id) if log_channel: embed = discord.Embed( title="✏️ Nachricht bearbeitet", description=f"**Autor:** {before.author.mention}\n" f"**Kanal:** {before.channel.mention}\n" f"[Zur Nachricht springen]({after.jump_url})", color=discord.Color.blue(), timestamp=datetime.datetime.now(datetime.timezone.utc) ) # Füge den alten und neuen Inhalt hinzu, wenn er nicht zu lang ist embed.add_field(name="Vorher", value=before.content[:1024], inline=False) embed.add_field(name="Nachher", value=after.content[:1024], inline=False) await log_channel.send(embed=embed) @commands.Cog.listener() async def on_member_ban(self, guild: discord.Guild, user: discord.User | discord.Member): log_channel = await self.get_log_channel(guild.id) if log_channel: embed = discord.Embed( title="🔨 Mitglied gebannt", description=f"**Mitglied:** {user.mention} (`{user.id}`)", color=discord.Color.dark_red(), timestamp=datetime.datetime.now(datetime.timezone.utc) ) await log_channel.send(embed=embed) @commands.Cog.listener() async def on_member_remove(self, member: discord.Member): # Dieser Event wird auch bei einem Kick oder Bann ausgelöst. Wir warten kurz, # um zu sehen, ob es ein Bann war, um doppelte Logs zu vermeiden. await asyncio.sleep(2) try: # Wenn der Nutzer gebannt wurde, existiert ein Ban-Eintrag await member.guild.fetch_ban(member) return # Es war ein Bann, on_member_ban kümmert sich darum except discord.NotFound: # Es war kein Bann (also ein Kick oder freiwilliger Leave) log_channel = await self.get_log_channel(member.guild.id) if log_channel: embed = discord.Embed( title="🚪 Mitglied hat den Server verlassen", description=f"**Mitglied:** {member.mention} (`{member.id}`)", color=discord.Color.greyple(), timestamp=datetime.datetime.now(datetime.timezone.utc) ) await log_channel.send(embed=embed) async def setup(bot: commands.Bot): # Wir brauchen asyncio für das Warten im on_member_remove Event import asyncio await bot.add_cog(AuditLog(bot))