import discord import json import os from datetime import datetime from typing import Optional, Dict, List from src.logger import kuby_logger class AdvancedLogger: def __init__(self, bot): self.bot = bot self.logs_dir = "data/logs" self.member_logs_dir = "data/member_logs" self.ensure_directories() def ensure_directories(self): """Ensure log directories exist""" os.makedirs(self.logs_dir, exist_ok=True) os.makedirs(self.member_logs_dir, exist_ok=True) def log_message_event(self, message: discord.Message, event_type: str, details: Dict = None): """Log message events (sent, edited, deleted)""" log_data = { "timestamp": datetime.now().isoformat(), "event_type": event_type, "message_id": message.id, "channel_id": message.channel.id, "channel_name": str(message.channel), "author_id": message.author.id, "author_name": str(message.author), "author_roles": [role.id for role in message.author.roles] if hasattr(message.author, 'roles') else [], "content": message.content, "attachments": [att.url for att in message.attachments], "embeds": [embed.to_dict() for embed in message.embeds], "details": details or {} } self._write_log("messages", log_data) def log_role_event(self, member: discord.Member, role: discord.Role, event_type: str): """Log role changes (added/removed)""" log_data = { "timestamp": datetime.now().isoformat(), "event_type": event_type, "member_id": member.id, "member_name": str(member), "role_id": role.id, "role_name": role.name, "role_color": str(role.color), "role_permissions": role.permissions.value } self._write_log("roles", log_data) def log_voice_event(self, member: discord.Member, channel: discord.VoiceChannel, event_type: str): """Log voice channel events (join/leave)""" log_data = { "timestamp": datetime.now().isoformat(), "event_type": event_type, "member_id": member.id, "member_name": str(member), "channel_id": channel.id, "channel_name": channel.name, "channel_type": str(channel.type) } self._write_log("voice", log_data) def log_member_leave(self, member: discord.Member): """Log when a member leaves the server""" roles_data = { "role_ids": [role.id for role in member.roles if role.name != "@everyone"], "role_names": [role.name for role in member.roles if role.name != "@everyone"], "permissions": [role.permissions.value for role in member.roles if role.name != "@everyone"] } log_data = { "timestamp": datetime.now().isoformat(), "event_type": "member_leave", "member_id": member.id, "member_name": str(member), "member_discriminator": member.discriminator, "member_avatar": str(member.avatar.url) if member.avatar else None, "roles": roles_data, "joined_at": member.joined_at.isoformat() if member.joined_at else None } # Save to member-specific log self._write_member_log(member.id, log_data) # Also save to general logs self._write_log("member_events", log_data) def log_member_join(self, member: discord.Member): """Log when a member joins the server""" log_data = { "timestamp": datetime.now().isoformat(), "event_type": "member_join", "member_id": member.id, "member_name": str(member), "member_discriminator": member.discriminator, "member_avatar": str(member.avatar.url) if member.avatar else None } self._write_log("member_events", log_data) def check_previous_roles(self, member_id: int) -> Optional[Dict]: """Check if member has previous role data when rejoining""" member_log_file = f"{self.member_logs_dir}/{member_id}.json" if not os.path.exists(member_log_file): return None try: with open(member_log_file, 'r', encoding='utf-8') as f: logs = json.load(f) # Find the most recent leave event leave_events = [log for log in logs if log.get("event_type") == "member_leave"] if leave_events: return leave_events[-1].get("roles", {}) except Exception as e: kuby_logger.error(f"Error checking previous roles for {member_id}: {e}") return None def _write_log(self, log_type: str, data: Dict): """Write log data to appropriate file""" date_str = datetime.now().strftime("%Y-%m-%d") log_file = f"{self.logs_dir}/{log_type}_{date_str}.json" try: # Append to existing file or create new if os.path.exists(log_file): with open(log_file, 'r', encoding='utf-8') as f: existing_logs = json.load(f) else: existing_logs = [] existing_logs.append(data) with open(log_file, 'w', encoding='utf-8') as f: json.dump(existing_logs, f, indent=2, ensure_ascii=False) except Exception as e: kuby_logger.error(f"Error writing log for {log_type}: {e}") def _write_member_log(self, member_id: int, data: Dict): """Write member-specific log""" member_log_file = f"{self.member_logs_dir}/{member_id}.json" try: # Append to existing file or create new if os.path.exists(member_log_file): with open(member_log_file, 'r', encoding='utf-8') as f: existing_logs = json.load(f) else: existing_logs = [] existing_logs.append(data) with open(member_log_file, 'w', encoding='utf-8') as f: json.dump(existing_logs, f, indent=2, ensure_ascii=False) except Exception as e: kuby_logger.error(f"Error writing member log for {member_id}: {e}") async def send_leave_notification(self, member: discord.Member, channel: discord.TextChannel): """Send notification when member leaves""" embed = discord.Embed( title="👋 Membre parti", description=f"{member.mention} ({member.name}#{member.discriminator}) a quitté le serveur.", color=discord.Color.red(), timestamp=datetime.now() ) embed.add_field( name="ID", value=str(member.id), inline=True ) roles = [role for role in member.roles if role.name != "@everyone"] if roles: embed.add_field( name="Rôles", value=", ".join([role.mention for role in roles]), inline=False ) embed.set_footer(text=f"ID: {member.id}") try: await channel.send(embed=embed) return True except Exception as e: kuby_logger.error(f"Error sending leave notification: {e}") return False