diff --git a/flanabot/bots/flana_disc_bot.py b/flanabot/bots/flana_disc_bot.py index 094c6d3..d423116 100644 --- a/flanabot/bots/flana_disc_bot.py +++ b/flanabot/bots/flana_disc_bot.py @@ -1,6 +1,7 @@ __all__ = ['FlanaDiscBot'] import asyncio +import datetime import math import os import random @@ -9,7 +10,7 @@ from typing import Sequence import discord import flanautils from flanautils import Media, NotFoundError, OrderedSet -from multibot import BadRoleError, DiscordBot, Role, User, constants as multibot_constants +from multibot import BadRoleError, DiscordBot, Role, User, bot_mentioned, constants as multibot_constants, group import constants from flanabot.bots.flana_bot import FlanaBot @@ -59,6 +60,8 @@ class FlanaDiscBot(DiscordBot, FlanaBot): self.client.add_listener(self._on_member_remove, 'on_member_remove') self.client.add_listener(self._on_voice_state_update, 'on_voice_state_update') + self.register(self._on_audit_log, multibot_constants.KEYWORDS['audit']) + async def _changeable_roles(self, group_: int | str | Chat | Message) -> list[Role]: group_id = self.get_group_id(group_) return [role for role in await self.get_group_roles(group_) if role.id in CHANGEABLE_ROLES[group_id]] @@ -151,6 +154,30 @@ class FlanaDiscBot(DiscordBot, FlanaBot): # ---------------------------------------------- # # HANDLERS # # ---------------------------------------------- # + @group + @bot_mentioned + async def _on_audit_log(self, message: Message): + audit_entries = await self.find_audit_entries( + message, + limit=constants.AUDIT_LOG_LIMIT, + actions=(discord.AuditLogAction.member_disconnect, discord.AuditLogAction.member_move), + after=datetime.datetime.now(datetime.timezone.utc) - constants.AUDIT_LOG_AGE + ) + await self.delete_message(message) + if not audit_entries: + await self.send_error(f'No hay entradas en el registro de auditoría (desconectar y mover) en la última hora {random.choice(multibot_constants.SAD_EMOJIS)}', message) + return + + message_parts = ['Registro de auditoría (solo desconectar y mover):', ''] + for entry in audit_entries: + author = self._create_user_from_discord_user(entry.user) + if entry.action is discord.AuditLogAction.member_disconnect: + message_parts.append(f"{author.name} ha desconectado {entry.extra.count} {'usuario' if entry.extra.count == 1 else 'usuarios'} ({entry.created_at.astimezone().strftime('%d/%m/%Y %H:%M:%S')})") + elif entry.action is discord.AuditLogAction.member_move: + message_parts.append(f"{author.name} ha movido {entry.extra.count} {'usuario' if entry.extra.count == 1 else 'usuarios'} a {entry.extra.channel.name} ({entry.created_at.astimezone().strftime('%d/%m/%Y %H:%M:%S')})") + + await self.send('\n'.join(message_parts), message) + async def _on_member_join(self, member: discord.Member): user = self._create_user_from_discord_user(member) user.pull_from_database(overwrite_fields=('roles',)) diff --git a/flanabot/constants.py b/flanabot/constants.py index b3491ff..2e51183 100644 --- a/flanabot/constants.py +++ b/flanabot/constants.py @@ -2,6 +2,8 @@ import datetime import flanautils +AUDIT_LOG_AGE = datetime.timedelta(hours=1) +AUDIT_LOG_LIMIT = 5 AUTO_WEATHER_EVERY = datetime.timedelta(hours=6) CHECK_PUNISHMENTS_EVERY_SECONDS = datetime.timedelta(hours=1).total_seconds() FLOOD_2s_LIMIT = 4