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