[ModLog API] Add default casetypes, remove need for a specific auditlog action (#2901)

* I know this needs a changelog entry and docs still

* update tests for new behavior

* update docs, filter; add changelog

* Ready for review

* stop fetching the same Audit logs when the bot is the mod

* I forgot to press save

* fix a comprehension

* Fix AttributeError

* And the other place that happens

* timing fixes
This commit is contained in:
DiscordLiz
2019-07-27 15:37:29 -04:00
committed by Michael H
parent 6280fd9c28
commit 20091cc10a
16 changed files with 251 additions and 214 deletions

View File

@@ -40,7 +40,7 @@ class Filter(commands.Cog):
async def register_filterban():
try:
await modlog.register_casetype(
"filterban", False, ":filing_cabinet: :hammer:", "Filter ban", "ban"
"filterban", False, ":filing_cabinet: :hammer:", "Filter ban"
)
except RuntimeError:
pass

View File

@@ -17,8 +17,6 @@ class MixinMeta(ABC):
self.settings: Config
self.bot: Red
self.cache: dict
self.ban_queue: List[Tuple[int, int]]
self.unban_queue: List[Tuple[int, int]]
@staticmethod
@abstractmethod
@@ -26,15 +24,3 @@ class MixinMeta(ABC):
ctx: commands.Context, user_voice_state: Optional[discord.VoiceState], **perms: bool
) -> bool:
raise NotImplementedError()
@classmethod
@abstractmethod
async def get_audit_entry_info(
cls, guild: discord.Guild, action: discord.AuditLogAction, target
):
raise NotImplementedError()
@staticmethod
@abstractmethod
async def get_audit_log_entry(guild: discord.Guild, action: discord.AuditLogAction, target):
raise NotImplementedError()

View File

@@ -94,77 +94,6 @@ class Events(MixinMeta):
if not deleted:
await self.check_mention_spam(message)
@commands.Cog.listener()
async def on_member_ban(self, guild: discord.Guild, member: discord.Member):
if (guild.id, member.id) in self.ban_queue:
self.ban_queue.remove((guild.id, member.id))
return
try:
await modlog.get_modlog_channel(guild)
except RuntimeError:
return # No modlog channel so no point in continuing
mod, reason, date = await self.get_audit_entry_info(
guild, discord.AuditLogAction.ban, member
)
if date is None:
date = datetime.now()
try:
await modlog.create_case(
self.bot, guild, date, "ban", member, mod, reason if reason else None
)
except RuntimeError as e:
print(e)
@commands.Cog.listener()
async def on_member_unban(self, guild: discord.Guild, user: discord.User):
if (guild.id, user.id) in self.unban_queue:
self.unban_queue.remove((guild.id, user.id))
return
try:
await modlog.get_modlog_channel(guild)
except RuntimeError:
return # No modlog channel so no point in continuing
mod, reason, date = await self.get_audit_entry_info(
guild, discord.AuditLogAction.unban, user
)
if date is None:
date = datetime.now()
try:
await modlog.create_case(self.bot, guild, date, "unban", user, mod, reason)
except RuntimeError as e:
print(e)
@commands.Cog.listener()
async def on_modlog_case_create(self, case: modlog.Case):
"""
An event for modlog case creation
"""
try:
mod_channel = await modlog.get_modlog_channel(case.guild)
except RuntimeError:
return
use_embeds = await case.bot.embed_requested(mod_channel, case.guild.me)
case_content = await case.message_content(use_embeds)
if use_embeds:
msg = await mod_channel.send(embed=case_content)
else:
msg = await mod_channel.send(case_content)
await case.edit({"message": msg})
@commands.Cog.listener()
async def on_modlog_case_edit(self, case: modlog.Case):
"""
Event for modlog case edits
"""
if not case.message:
return
use_embed = await case.bot.embed_requested(case.message.channel, case.guild.me)
case_content = await case.message_content(use_embed)
if use_embed:
await case.message.edit(embed=case_content)
else:
await case.message.edit(content=case_content)
@commands.Cog.listener()
async def on_member_update(self, before: discord.Member, after: discord.Member):
if before.name != after.name:

View File

@@ -85,7 +85,6 @@ class KickBanMixin(MixinMeta):
audit_reason = get_audit_reason(author, reason)
queue_entry = (guild.id, user.id)
self.ban_queue.append(queue_entry)
try:
await guild.ban(user, reason=audit_reason, delete_message_days=days)
log.info(
@@ -94,10 +93,8 @@ class KickBanMixin(MixinMeta):
)
)
except discord.Forbidden:
self.ban_queue.remove(queue_entry)
return _("I'm not allowed to do that.")
except Exception as e:
self.ban_queue.remove(queue_entry)
return e # TODO: impproper return type? Is this intended to be re-raised?
if create_modlog_case:
@@ -134,15 +131,13 @@ class KickBanMixin(MixinMeta):
if now > unban_time: # Time to unban the user
user = await self.bot.fetch_user(uid)
queue_entry = (guild.id, user.id)
self.unban_queue.append(queue_entry)
try:
await guild.unban(user, reason=_("Tempban finished"))
guild_tempbans.remove(uid)
except discord.Forbidden:
self.unban_queue.remove(queue_entry)
log.info("Failed to unban member due to permissions")
except discord.HTTPException:
self.unban_queue.remove(queue_entry)
except discord.HTTPException as e:
log.info(f"Failed to unban member: error code: {e.code}")
await asyncio.sleep(60)
@commands.command()
@@ -319,16 +314,13 @@ class KickBanMixin(MixinMeta):
user = discord.Object(id=user_id)
audit_reason = get_audit_reason(author, reason)
queue_entry = (guild.id, user_id)
self.ban_queue.append(queue_entry)
try:
await guild.ban(user, reason=audit_reason, delete_message_days=days)
log.info("{}({}) hackbanned {}".format(author.name, author.id, user_id))
except discord.NotFound:
self.ban_queue.remove(queue_entry)
errors[user_id] = _("User {user_id} does not exist.").format(user_id=user_id)
continue
except discord.Forbidden:
self.ban_queue.remove(queue_entry)
errors[user_id] = _("Could not ban {user_id}: missing permissions.").format(
user_id=user_id
)
@@ -389,7 +381,6 @@ class KickBanMixin(MixinMeta):
invite_link=invite,
)
)
self.ban_queue.append(queue_entry)
try:
await guild.ban(user)
except discord.Forbidden:
@@ -455,24 +446,19 @@ class KickBanMixin(MixinMeta):
)
except discord.HTTPException:
msg = None
self.ban_queue.append(queue_entry)
try:
await guild.ban(user, reason=audit_reason, delete_message_days=1)
except discord.errors.Forbidden:
self.ban_queue.remove(queue_entry)
await ctx.send(_("My role is not high enough to softban that user."))
if msg is not None:
await msg.delete()
return
except discord.HTTPException as e:
self.ban_queue.remove(queue_entry)
print(e)
return
self.unban_queue.append(queue_entry)
try:
await guild.unban(user)
except discord.HTTPException as e:
self.unban_queue.remove(queue_entry)
print(e)
return
else:
@@ -571,11 +557,9 @@ class KickBanMixin(MixinMeta):
await ctx.send(_("It seems that user isn't banned!"))
return
queue_entry = (guild.id, user.id)
self.unban_queue.append(queue_entry)
try:
await guild.unban(user, reason=audit_reason)
except discord.HTTPException:
self.unban_queue.remove(queue_entry)
await ctx.send(_("Something went wrong while attempting to unban that user"))
return
else:

View File

@@ -71,10 +71,7 @@ class Mod(
self.settings.register_channel(**self.default_channel_settings)
self.settings.register_member(**self.default_member_settings)
self.settings.register_user(**self.default_user_settings)
self.ban_queue: List[Tuple[int, int]] = []
self.unban_queue: List[Tuple[int, int]] = []
self.cache: dict = {}
self.registration_task = self.bot.loop.create_task(self._casetype_registration())
self.tban_expiry_task = self.bot.loop.create_task(self.check_tempban_expirations())
self.last_case: dict = defaultdict(dict)
@@ -99,13 +96,6 @@ class Mod(
await self.settings.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.settings.version.set(__version__)
@staticmethod
async def _casetype_registration():
try:
await modlog.register_casetypes(CASETYPES)
except RuntimeError:
pass
# TODO: Move this to core.
# This would be in .movetocore , but the double-under name here makes that more trouble
async def bot_check(self, ctx):
@@ -126,59 +116,3 @@ class Mod(
guild_ignored = await self.settings.guild(ctx.guild).ignored()
chann_ignored = await self.settings.channel(ctx.channel).ignored()
return not (guild_ignored or chann_ignored and not perms.manage_channels)
@classmethod
async def get_audit_entry_info(
cls, guild: discord.Guild, action: discord.AuditLogAction, target
):
"""Get info about an audit log entry.
Parameters
----------
guild : discord.Guild
Same as ``guild`` in `get_audit_log_entry`.
action : int
Same as ``action`` in `get_audit_log_entry`.
target : `discord.User` or `discord.Member`
Same as ``target`` in `get_audit_log_entry`.
Returns
-------
tuple
A tuple in the form``(mod: discord.Member, reason: str,
date_created: datetime.datetime)``. Returns ``(None, None, None)``
if the audit log entry could not be found.
"""
try:
entry = await cls.get_audit_log_entry(guild, action=action, target=target)
except discord.HTTPException:
entry = None
if entry is None:
return None, None, None
return entry.user, entry.reason, entry.created_at
@staticmethod
async def get_audit_log_entry(guild: discord.Guild, action: discord.AuditLogAction, target):
"""Get an audit log entry.
Any exceptions encountered when looking through the audit log will be
propogated out of this function.
Parameters
----------
guild : discord.Guild
The guild for the audit log.
action : int
The audit log action (see `discord.AuditLogAction`).
target : `discord.Member` or `discord.User`
The target of the audit log action.
Returns
-------
discord.AuditLogEntry
The audit log entry. Returns ``None`` if not found.
"""
async for entry in guild.audit_logs(action=action):
if entry.target == target:
return entry