import discord from discord.ext import commands from discord.commands import Option from discord.commands import slash_command import configparser import time class actionlog(commands.Cog): def __init__(self, bot: discord.Bot): self.bot = bot def _load_config(self): config = configparser.ConfigParser() configFilePath = r'config.cfg' config.read(configFilePath) return config def _get_log_channel(self): config = self._load_config() log_channel_id = int(config["Logs"]["action_log"]) log_channel = self.bot.get_channel(log_channel_id) if log_channel is None: print(f"Log channel with ID {log_channel_id} not found.") return None return log_channel #Deleted Message Log @commands.Cog.listener() async def on_message_delete(self, message: discord.Message, moderator: discord.Member): if message.author.bot: return config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return else: if message.content is None and not message.attachments: content = "No content available" elif message.content is None: content = "Content not available, but there are attachments." else: content = message.content moderator = self.bot.get_user(moderator) embed = discord.Embed( title="Message Deleted", description=f"A message by {message.author.mention} was deleted in {message.channel.mention} by {moderator.mention}.", color=discord.Color.red(), timestamp=message.created_at ) embed.add_field(name="Message Content", value=content[:1024], inline=False) embed.set_footer(text=f"User ID: {message.author.id} | Message ID: {message.id}") await log_channel.send(embed=embed) #Edited Message Log @commands.Cog.listener() async def on_message_edit(self, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return if before.author.bot: return else: embed = discord.Embed( title="Message Edited", description=f"A message by {before.author.mention} was edited in {before.channel.mention}.", color=discord.Color.orange(), timestamp=after.edited_at or discord.utils.utcnow() ) embed.add_field(name="Before", value=before.content or "No content", inline=False) embed.add_field(name="After", value=after.content or "No content", inline=False) embed.set_footer(text=f"User ID: {before.author.id} | Message ID: {before.id}") await log_channel.send(embed=embed) #Member Join Log @commands.Cog.listener() async def on_member_join(self, member): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return embed = discord.Embed( title="Member Joined", description=f"{member.mention} has joined the server. Account created at: {member.created_at}", color=discord.Color.green(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"User ID: {member.id}") await log_channel.send(embed=embed) #Member Leave Log @commands.Cog.listener() async def on_member_remove(self, member): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return embed = discord.Embed( title="Member Left", description=f"{member.mention} has left the server. Joined at: {member.joined_at}", color=discord.Color.dark_red(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"User ID: {member.id}") await log_channel.send(embed=embed) #Role Update Log @commands.Cog.listener() async def on_guild_role_update(self, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(after.guild, discord.AuditLogAction.role_update, after.id) embed = discord.Embed( title="Role Updated", description=f"The role **{before.name}** has been updated by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.blue(), timestamp=discord.utils.utcnow() ) embed.add_field(name="Before", value=f"Name: {before.name}\nColor: {before.color}\nPermissions: {before.permissions}", inline=False) embed.add_field(name="After", value=f"Name: {after.name}\nColor: {after.color}\nPermissions: {after.permissions}", inline=False) embed.set_footer(text=f"Role ID: {before.id}") await log_channel.send(embed=embed) #Role added log @commands.Cog.listener() async def on_guild_role_create(self, role): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(role.guild, discord.AuditLogAction.role_create, role.id) embed = discord.Embed( title="Role Created", description=f"The role **{role.name}** has been created by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.green(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"Role ID: {role.id}") await log_channel.send(embed=embed) #Role deleted log @commands.Cog.listener() async def on_guild_role_delete(self, role): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(role.guild, discord.AuditLogAction.role_delete, role.id) embed = discord.Embed( title="Role Deleted", description=f"The role **{role.name}** has been deleted by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.red(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"Role ID: {role.id}") await log_channel.send(embed=embed) #User Role update log @commands.Cog.listener() async def on_member_update(self, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return before_roles = set(before.roles) after_roles = set(after.roles) added_roles = after_roles - before_roles removed_roles = before_roles - after_roles async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(after.guild, discord.AuditLogAction.member_role_update, after.id) for role in added_roles: embed = discord.Embed( title="Role Added", description=f"The role **{role.name}** has been added to {after.mention} by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.green(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"User ID: {after.id} | Role ID: {role.id}") await log_channel.send(embed=embed) for role in removed_roles: embed = discord.Embed( title="Role Removed", description=f"The role **{role.name}** has been removed from {after.mention} by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.red(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"User ID: {after.id} | Role ID: {role.id}") await log_channel.send(embed=embed) #Server Changes Log @commands.Cog.listener() async def on_guild_update(self, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(after, discord.AuditLogAction.guild_update, after.id) embed = discord.Embed( title="Server Updated", description=f"The server has been updated by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.blue(), timestamp=discord.utils.utcnow() ) embed.add_field(name="Before", value=f"Name: {before.name}\nDescription: {before.description}\nOwner: {before.owner}", inline=False) embed.add_field(name="After", value=f"Name: {after.name}\nDescription: {after.description}\nOwner: {after.owner}", inline=False) embed.set_footer(text=f"Server ID: {before.id}") await log_channel.send(embed=embed) #Voice channel log @commands.Cog.listener() async def on_voice_state_update(self, member, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return if before.channel is None and after.channel is not None: action = "joined" channel = after.channel elif before.channel is not None and after.channel is None: action = "left" channel = before.channel elif before.channel is not None and after.channel is not None and before.channel != after.channel: action = "moved from" channel = before.channel else: return embed = discord.Embed( title="Voice State Updated", description=f"{member.mention} has {action} the voice channel {channel.mention}.", color=discord.Color.purple(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"User ID: {member.id}") await log_channel.send(embed=embed) #Channel Update Log @commands.Cog.listener() async def on_guild_channel_update(self, before, after): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(after.guild, discord.AuditLogAction.channel_update, after.id) embed = discord.Embed( title="Channel Updated", description=f"The channel **{before.name}** has been updated by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.blue(), timestamp=discord.utils.utcnow() ) embed.add_field(name="Before", value=f"Name: {before.name}\nType: {before.type}\nPosition: {before.position}", inline=False) embed.add_field(name="After", value=f"Name: {after.name}\nType: {after.type}\nPosition: {after.position}", inline=False) embed.set_footer(text=f"Channel ID: {before.id}") await log_channel.send(embed=embed) #Channel Create Log @commands.Cog.listener() async def on_guild_channel_create(self, channel): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(channel.guild, discord.AuditLogAction.channel_create, channel.id) embed = discord.Embed( title="Channel Created", description=f"The channel **{channel.name}** has been created by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.green(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"Channel ID: {channel.id}") await log_channel.send(embed=embed) #Channel Delete Log @commands.Cog.listener() async def on_guild_channel_delete(self, channel): config = self._load_config() enable_log = config.getboolean("Logs","enable_action_log") if not enable_log: return log_channel = self._get_log_channel() if log_channel is None: return async def get_audit_log_user(guild, action, target_id): try: async for entry in guild.audit_logs(limit=10, action=action): if entry.target.id == target_id: return entry.user except discord.Forbidden: pass return None moderator = await get_audit_log_user(channel.guild, discord.AuditLogAction.channel_delete, channel.id) embed = discord.Embed( title="Channel Deleted", description=f"The channel **{channel.name}** has been deleted by {moderator.mention if moderator else 'Unknown'}.", color=discord.Color.red(), timestamp=discord.utils.utcnow() ) embed.set_footer(text=f"Channel ID: {channel.id}") await log_channel.send(embed=embed) def setup(bot: discord.Bot): bot.add_cog(actionlog(bot))