diff --git a/jarvis/__init__.py b/jarvis/__init__.py index 45d3232..78628f8 100644 --- a/jarvis/__init__.py +++ b/jarvis/__init__.py @@ -8,7 +8,6 @@ from jarvis_core.db import connect from jarvis import utils from jarvis.client import Jarvis from jarvis.config import get_config -from jarvis.events import member, message jconfig = get_config() @@ -36,11 +35,4 @@ def run() -> None: jarvis.load_extension(extension) jarvis.max_messages = jconfig.max_messages - - # Add event listeners - if jconfig.events: - _ = [ - member.MemberEventHandler(jarvis), - message.MessageEventHandler(jarvis), - ] jarvis.start(jconfig.token) diff --git a/jarvis/client.py b/jarvis/client.py index c3ff3da..f7e6df3 100644 --- a/jarvis/client.py +++ b/jarvis/client.py @@ -1,13 +1,19 @@ """Custom JARVIS client.""" +import re import traceback from datetime import datetime from dis_snek import Snake, listen +from dis_snek.api.events.discord import MessageCreate, MessageDelete, MessageUpdate +from dis_snek.client.utils.misc_utils import find, find_all from dis_snek.models.discord.channel import DMChannel from dis_snek.models.discord.embed import EmbedField +from dis_snek.models.discord.message import Message +from dis_snek.models.discord.user import Member from dis_snek.models.snek.context import Context, InteractionContext from jarvis_core.db import q -from jarvis_core.db.models import Setting +from jarvis_core.db.models import Autopurge, Autoreact, Roleping, Setting, Warning +from jarvis_core.filters import invites from jarvis_core.util import build_embed from jarvis_core.util.ansi import RESET, Fore, Format, fmt from pastypy import AsyncPaste as Paste @@ -45,32 +51,6 @@ class Jarvis(Snake): "{}&permissions=8&scope=bot%20applications.commands".format(self.user.id) ) - async def on_command(self, ctx: InteractionContext) -> None: - """Lepton on_command override.""" - if not isinstance(ctx.channel, DMChannel) and ctx.invoked_name not in ["pw"]: - modlog = await Setting.find_one(q(guild=ctx.guild.id, setting="modlog")) - if modlog: - channel = await ctx.guild.fetch_channel(modlog.value) - args = " ".join(f"{KEY_FMT}{k}:{VAL_FMT}{v}{RESET}" for k, v in ctx.kwargs.items()) - fields = [ - EmbedField( - name="Command", - value=f"```ansi\n{CMD_FMT}{ctx.invoked_name}{RESET} {args}\n```", - inline=False, - ), - ] - embed = build_embed( - title="Command Invoked", - description=f"{ctx.author.mention} invoked a command", - fields=fields, - color="#fc9e3f", - ) - embed.set_author(name=ctx.author.username, icon_url=ctx.author.display_avatar.url) - embed.set_footer( - text=f"{ctx.author.username}#{ctx.author.discriminator} | {ctx.author.id}" - ) - await channel.send(embed=embed) - async def on_command_error( self, ctx: Context, error: Exception, *args: list, **kwargs: dict ) -> None: @@ -113,3 +93,332 @@ class Jarvis(Snake): ) await ctx.send("Whoops! Encountered an error. The error has been logged.", ephemeral=True) return await super().on_command_error(ctx, error, *args, **kwargs) + + # Modlog + async def on_command(self, ctx: InteractionContext) -> None: + """Lepton on_command override.""" + if not isinstance(ctx.channel, DMChannel) and ctx.invoked_name not in ["pw"]: + modlog = await Setting.find_one(q(guild=ctx.guild.id, setting="modlog")) + if modlog: + channel = await ctx.guild.fetch_channel(modlog.value) + args = " ".join(f"{KEY_FMT}{k}:{VAL_FMT}{v}{RESET}" for k, v in ctx.kwargs.items()) + fields = [ + EmbedField( + name="Command", + value=f"```ansi\n{CMD_FMT}{ctx.invoked_name}{RESET} {args}\n```", + inline=False, + ), + ] + embed = build_embed( + title="Command Invoked", + description=f"{ctx.author.mention} invoked a command", + fields=fields, + color="#fc9e3f", + ) + embed.set_author(name=ctx.author.username, icon_url=ctx.author.display_avatar.url) + embed.set_footer( + text=f"{ctx.author.username}#{ctx.author.discriminator} | {ctx.author.id}" + ) + await channel.send(embed=embed) + + async def on_message_edit(self, event: MessageUpdate) -> None: + """Process on_message_edit events.""" + before = event.before + after = event.after + if not before.author.bot: + modlog = await Setting.find_one(q(guild=after.guild.id, setting="modlog")) + if modlog: + if before.content == after.content or before.content is None: + return + channel = before.guild.get_channel(modlog.value) + fields = [ + EmbedField( + "Original Message", + before.content if before.content else "N/A", + False, + ), + EmbedField( + "New Message", + after.content if after.content else "N/A", + False, + ), + ] + embed = build_embed( + title="Message Edited", + description=f"{before.author.mention} edited a message", + fields=fields, + color="#fc9e3f", + timestamp=after.edited_timestamp, + url=after.jump_url, + ) + embed.set_author( + name=before.author.username, + icon_url=before.author.display_avatar.url, + url=after.jump_url, + ) + embed.set_footer( + text=f"{before.author.username}#{before.author.discriminator} | {before.author.id}" + ) + await channel.send(embed=embed) + if not isinstance(after.channel, DMChannel) and not after.author.bot: + await self.massmention(after) + await self.roleping(after) + await self.checks(after) + await self.roleping(after) + await self.checks(after) + + async def on_message_delete(self, event: MessageDelete) -> None: + """Process on_message_delete events.""" + message = event.message + modlog = await Setting.find_one(q(guild=message.guild.id, setting="modlog")) + if modlog: + fields = [EmbedField("Original Message", message.content or "N/A", False)] + + if message.attachments: + value = "\n".join([f"[{x.filename}]({x.url})" for x in message.attachments]) + fields.append( + EmbedField( + name="Attachments", + value=value, + inline=False, + ) + ) + + if message.sticker_items: + value = "\n".join([f"Sticker: {x.name}" for x in message.sticker_items]) + fields.append( + EmbedField( + name="Stickers", + value=value, + inline=False, + ) + ) + + if message.embeds: + value = str(len(message.embeds)) + " embeds" + fields.append( + EmbedField( + name="Embeds", + value=value, + inline=False, + ) + ) + + channel = message.guild.get_channel(modlog.value) + embed = build_embed( + title="Message Deleted", + description=f"{message.author.mention}'s message was deleted", + fields=fields, + color="#fc9e3f", + ) + + embed.set_author( + name=message.author.username, + icon_url=message.author.display_avatar.url, + url=message.jump_url, + ) + embed.set_footer( + text=f"{message.author.username}#{message.author.discriminator} | {message.author.id}" + ) + await channel.send(embed=embed) + + # Events + async def on_member_join(self, user: Member) -> None: + """Handle on_member_join event.""" + guild = user.guild + unverified = await Setting.find_one(q(guild=guild.id, setting="unverified")) + if unverified: + role = guild.get_role(unverified.value) + if role not in user.roles: + await user.add_roles(role, reason="User just joined and is unverified") + + async def autopurge(self, message: Message) -> None: + """Handle autopurge events.""" + autopurge = await Autopurge.find_one(q(guild=message.guild.id, channel=message.channel.id)) + if autopurge: + await message.delete(delay=autopurge.delay) + + async def autoreact(self, message: Message) -> None: + """Handle autoreact events.""" + autoreact = await Autoreact.find_one( + q( + guild=message.guild.id, + channel=message.channel.id, + ) + ) + if autoreact: + for reaction in autoreact.reactions: + await message.add_reaction(reaction) + + async def checks(self, message: Message) -> None: + """Other message checks.""" + # #tech + channel = find(lambda x: x.id == 599068193339736096, message.channel_mentions) + if channel and message.author.id == 293795462752894976: + await channel.send( + content="https://cdn.discordapp.com/attachments/664621130044407838/805218508866453554/tech.gif" # noqa: E501 + ) + content = re.sub(r"\s+", "", message.content) + match = invites.search(content) + setting = await Setting.find_one(q(guild=message.guild.id, setting="noinvite")) + if not setting: + setting = Setting(guild=message.guild.id, setting="noinvite", value=True) + await setting.commit() + if match: + guild_invites = await message.guild.invites() + allowed = [x.code for x in guild_invites] + [ + "dbrand", + "VtgZntXcnZ", + "gPfYGbvTCE", + ] + if match.group(1) not in allowed and setting.value: + await message.delete() + w = Warning( + active=True, + admin=self.user.id, + duration=24, + guild=message.guild.id, + reason="Sent an invite link", + user=message.author.id, + ) + await w.commit() + fields = [ + EmbedField( + name="Reason", + value="Sent an invite link", + inline=False, + ) + ] + embed = build_embed( + title="Warning", + description=f"{message.author.mention} has been warned", + fields=fields, + ) + embed.set_author( + name=message.author.nick if message.author.nick else message.author.name, + icon_url=message.author.display_avatar.url, + ) + embed.set_footer( + text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" # noqa: E501 + ) + await message.channel.send(embed=embed) + + async def massmention(self, message: Message) -> None: + """Handle massmention events.""" + massmention = await Setting.find_one( + q( + guild=message.guild.id, + setting="massmention", + ) + ) + if ( + massmention + and massmention.value > 0 # noqa: W503 + and len(message.mentions) # noqa: W503 + - (1 if message.author in message.mentions else 0) # noqa: W503 + > massmention.value # noqa: W503 + ): + w = Warning( + active=True, + admin=self.user.id, + duration=24, + guild=message.guild.id, + reason="Mass Mention", + user=message.author.id, + ) + await w.commit() + fields = [EmbedField(name="Reason", value="Mass Mention", inline=False)] + embed = build_embed( + title="Warning", + description=f"{message.author.mention} has been warned", + fields=fields, + ) + embed.set_author( + name=message.author.nick if message.author.nick else message.author.name, + icon_url=message.author.display_avatar.url, + ) + embed.set_footer( + text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" + ) + await message.channel.send(embed=embed) + + async def roleping(self, message: Message) -> None: + """Handle roleping events.""" + rolepings = await Roleping.find(q(guild=message.guild.id, active=True)) + + if not rolepings: + return + + # Get all role IDs involved with message + roles = [] + for mention in message.role_mentions: + roles.append(mention.id) + for mention in message.mentions: + for role in mention.roles: + roles.append(role.id) + + if not roles: + return + + # Get all roles that are rolepinged + roleping_ids = [r.role for r in rolepings] + + # Get roles in rolepings + role_in_rolepings = find_all(lambda x: x in roleping_ids, roles) + + # Check if the user has the role, so they are allowed to ping it + user_missing_role = any(x.id not in roleping_ids for x in message.author.roles) + + # Admins can ping whoever + user_is_admin = message.author.guild_permissions.ADMINISTRATOR + + # Check if user in a bypass list + user_has_bypass = False + for roleping in rolepings: + if message.author.id in roleping.bypass["users"]: + user_has_bypass = True + break + if any(role.id in roleping.bypass["roles"] for role in message.author.roles): + user_has_bypass = True + break + + if role_in_rolepings and user_missing_role and not user_is_admin and not user_has_bypass: + w = Warning( + active=True, + admin=self.user.id, + duration=24, + guild=message.guild.id, + reason="Pinged a blocked role/user with a blocked role", + user=message.author.id, + ) + await w.commit() + fields = [ + EmbedField( + name="Reason", + value="Pinged a blocked role/user with a blocked role", + inline=False, + ) + ] + embed = build_embed( + title="Warning", + description=f"{message.author.mention} has been warned", + fields=fields, + ) + embed.set_author( + name=message.author.nick if message.author.nick else message.author.name, + icon_url=message.author.display_avatar.url, + ) + embed.set_footer( + text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" + ) + await message.channel.send(embed=embed) + + async def on_message(self, event: MessageCreate) -> None: + """Handle on_message event. Calls other event handlers.""" + message = event.message + if not isinstance(message.channel, DMChannel) and not message.author.bot: + await self.autoreact(message) + await self.massmention(message) + await self.roleping(message) + await self.autopurge(message) + await self.checks(message) diff --git a/jarvis/cogs/modlog/__init__.py b/jarvis/cogs/modlog/__init__.py deleted file mode 100644 index f59f2c3..0000000 --- a/jarvis/cogs/modlog/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""J.A.R.V.I.S. Modlog Cogs.""" -from dis_snek import Snake - -from jarvis.cogs.modlog import command, message - - -def setup(bot: Snake) -> None: - """Add modlog cogs to J.A.R.V.I.S.""" - command.ModlogCommandCog(bot) - # member.ModlogMemberCog(bot) - message.ModlogMessageCog(bot) diff --git a/jarvis/cogs/modlog/member.py b/jarvis/cogs/modlog/member.py deleted file mode 100644 index b00514e..0000000 --- a/jarvis/cogs/modlog/member.py +++ /dev/null @@ -1 +0,0 @@ -"""JARVIS member modlog processing.""" diff --git a/jarvis/cogs/modlog/message.py b/jarvis/cogs/modlog/message.py deleted file mode 100644 index 848a929..0000000 --- a/jarvis/cogs/modlog/message.py +++ /dev/null @@ -1,112 +0,0 @@ -"""J.A.R.V.I.S. ModlogMessageCog.""" -from dis_snek import Scale, Snake, listen -from dis_snek.api.events.discord import MessageDelete, MessageUpdate -from dis_snek.models.discord.embed import EmbedField -from jarvis_core.db import q -from jarvis_core.db.models import Setting - -from jarvis.utils import build_embed - - -class ModlogMessageCog(Scale): - """J.A.R.V.I.S. ModlogMessageCog.""" - - def __init__(self, bot: Snake): - self.bot = bot - - @listen() - async def on_message_edit(self, event: MessageUpdate) -> None: - """Process on_message_edit events.""" - before = event.before - after = event.after - if not before.author.bot: - modlog = await Setting.find_one(q(guild=after.guild.id, setting="modlog")) - if modlog: - if before.content == after.content or before.content is None: - return - channel = before.guild.get_channel(modlog.value) - fields = [ - EmbedField( - "Original Message", - before.content if before.content else "N/A", - False, - ), - EmbedField( - "New Message", - after.content if after.content else "N/A", - False, - ), - ] - embed = build_embed( - title="Message Edited", - description=f"{before.author.mention} edited a message", - fields=fields, - color="#fc9e3f", - timestamp=after.edited_timestamp, - url=after.jump_url, - ) - embed.set_author( - name=before.author.username, - icon_url=before.author.display_avatar.url, - url=after.jump_url, - ) - embed.set_footer( - text=f"{before.author.username}#{before.author.discriminator} | {before.author.id}" - ) - await channel.send(embed=embed) - - @listen() - async def on_message_delete(self, event: MessageDelete) -> None: - """Process on_message_delete events.""" - message = event.message - modlog = await Setting.find_one(q(guild=message.guild.id, setting="modlog")) - if modlog: - fields = [EmbedField("Original Message", message.content or "N/A", False)] - - if message.attachments: - value = "\n".join([f"[{x.filename}]({x.url})" for x in message.attachments]) - fields.append( - EmbedField( - name="Attachments", - value=value, - inline=False, - ) - ) - - if message.sticker_items: - value = "\n".join([f"Sticker: {x.name}" for x in message.sticker_items]) - fields.append( - EmbedField( - name="Stickers", - value=value, - inline=False, - ) - ) - - if message.embeds: - value = str(len(message.embeds)) + " embeds" - fields.append( - EmbedField( - name="Embeds", - value=value, - inline=False, - ) - ) - - channel = message.guild.get_channel(modlog.value) - embed = build_embed( - title="Message Deleted", - description=f"{message.author.mention}'s message was deleted", - fields=fields, - color="#fc9e3f", - ) - - embed.set_author( - name=message.author.username, - icon_url=message.author.display_avatar.url, - url=message.jump_url, - ) - embed.set_footer( - text=f"{message.author.username}#{message.author.discriminator} | {message.author.id}" - ) - await channel.send(embed=embed) diff --git a/jarvis/cogs/modlog/utils.py b/jarvis/cogs/modlog/utils.py deleted file mode 100644 index 72b5cbe..0000000 --- a/jarvis/cogs/modlog/utils.py +++ /dev/null @@ -1,34 +0,0 @@ -"""J.A.R.V.I.S. Modlog Cog Utilities.""" -from dis_snek.models.discord.embed import Embed, EmbedField -from dis_snek.models.discord.guild import AuditLogEntry -from dis_snek.models.discord.user import Member - -from jarvis.utils import build_embed - - -def modlog_embed( - member: Member, - admin: Member, - log: AuditLogEntry, - title: str, - desc: str, -) -> Embed: - """Get modlog embed.""" - fields = [ - EmbedField( - name="Moderator", - value=f"{admin.mention} ({admin.username}#{admin.discriminator})", - ), - ] - if log.reason: - fields.append(EmbedField(name="Reason", value=log.reason, inline=False)) - embed = build_embed( - title=title, - description=desc, - color="#fc9e3f", - fields=fields, - timestamp=log.created_at, - ) - embed.set_author(name=f"{member.username}", icon_url=member.display_avatar.url) - embed.set_footer(text=f"{member.username}#{member.discriminator} | {member.id}") - return embed diff --git a/jarvis/events/member.py b/jarvis/events/member.py deleted file mode 100644 index f7e4ada..0000000 --- a/jarvis/events/member.py +++ /dev/null @@ -1,23 +0,0 @@ -"""J.A.R.V.I.S. Member event handler.""" -from dis_snek import Snake, listen -from dis_snek.models.discord.user import Member -from jarvis_core.db import q -from jarvis_core.db.models import Setting - - -class MemberEventHandler(object): - """J.A.R.V.I.S. Member event handler.""" - - def __init__(self, bot: Snake): - self.bot = bot - self.bot.add_listener(self.on_member_join) - - @listen() - async def on_member_join(self, user: Member) -> None: - """Handle on_member_join event.""" - guild = user.guild - unverified = await Setting.find_one(q(guild=guild.id, setting="unverified")) - if unverified: - role = guild.get_role(unverified.value) - if role not in user.roles: - await user.add_roles(role, reason="User just joined and is unverified") diff --git a/jarvis/events/message.py b/jarvis/events/message.py deleted file mode 100644 index 693bc3c..0000000 --- a/jarvis/events/message.py +++ /dev/null @@ -1,228 +0,0 @@ -"""J.A.R.V.I.S. Message event handler.""" -import re - -from dis_snek import Snake, listen -from dis_snek.client.utils.misc_utils import find, find_all -from dis_snek.models.discord.channel import DMChannel -from dis_snek.models.discord.embed import EmbedField -from dis_snek.models.discord.message import Message -from jarvis_core.db import q -from jarvis_core.db.models import Autopurge, Autoreact, Roleping, Setting, Warning - -import jarvis -from jarvis.utils import build_embed - -invites = re.compile( - r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501 - flags=re.IGNORECASE, -) - - -class MessageEventHandler(object): - """J.A.R.V.I.S. Message event handler.""" - - def __init__(self, bot: Snake): - self.bot = bot - self.bot.add_listener(self.on_message) - self.bot.add_listener(self.on_message_edit) - - async def autopurge(self, message: Message) -> None: - """Handle autopurge events.""" - autopurge = await Autopurge.find_one(q(guild=message.guild.id, channel=message.channel.id)) - if autopurge: - await message.delete(delay=autopurge.delay) - - async def autoreact(self, message: Message) -> None: - """Handle autoreact events.""" - autoreact = await Autoreact.find_one( - q( - guild=message.guild.id, - channel=message.channel.id, - ) - ) - if autoreact: - for reaction in autoreact.reactions: - await message.add_reaction(reaction) - - async def checks(self, message: Message) -> None: - """Other message checks.""" - # #tech - channel = find(lambda x: x.id == 599068193339736096, message.channel_mentions) - if channel and message.author.id == 293795462752894976: - await channel.send( - content="https://cdn.discordapp.com/attachments/664621130044407838/805218508866453554/tech.gif" # noqa: E501 - ) - content = re.sub(r"\s+", "", message.content) - match = invites.search(content) - setting = await Setting.find_one(q(guild=message.guild.id, setting="noinvite")) - if not setting: - setting = Setting(guild=message.guild.id, setting="noinvite", value=True) - await setting.commit() - if match: - guild_invites = await message.guild.invites() - allowed = [x.code for x in guild_invites] + [ - "dbrand", - "VtgZntXcnZ", - "gPfYGbvTCE", - ] - if match.group(1) not in allowed and setting.value: - await message.delete() - w = Warning( - active=True, - admin=jarvis.jconfig.client_id, - duration=24, - guild=message.guild.id, - reason="Sent an invite link", - user=message.author.id, - ) - await w.commit() - fields = [ - EmbedField( - name="Reason", - value="Sent an invite link", - inline=False, - ) - ] - embed = build_embed( - title="Warning", - description=f"{message.author.mention} has been warned", - fields=fields, - ) - embed.set_author( - name=message.author.nick if message.author.nick else message.author.name, - icon_url=message.author.display_avatar.url, - ) - embed.set_footer( - text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" # noqa: E501 - ) - await message.channel.send(embed=embed) - - async def massmention(self, message: Message) -> None: - """Handle massmention events.""" - massmention = await Setting.find_one( - q( - guild=message.guild.id, - setting="massmention", - ) - ) - if ( - massmention - and massmention.value > 0 # noqa: W503 - and len(message.mentions) # noqa: W503 - - (1 if message.author in message.mentions else 0) # noqa: W503 - > massmention.value # noqa: W503 - ): - w = Warning( - active=True, - admin=jarvis.jconfig.client_id, - duration=24, - guild=message.guild.id, - reason="Mass Mention", - user=message.author.id, - ) - await w.commit() - fields = [EmbedField(name="Reason", value="Mass Mention", inline=False)] - embed = build_embed( - title="Warning", - description=f"{message.author.mention} has been warned", - fields=fields, - ) - embed.set_author( - name=message.author.nick if message.author.nick else message.author.name, - icon_url=message.author.display_avatar.url, - ) - embed.set_footer( - text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" - ) - await message.channel.send(embed=embed) - - async def roleping(self, message: Message) -> None: - """Handle roleping events.""" - rolepings = await Roleping.find(q(guild=message.guild.id, active=True)) - - if not rolepings: - return - - # Get all role IDs involved with message - roles = [] - for mention in message.role_mentions: - roles.append(mention.id) - for mention in message.mentions: - for role in mention.roles: - roles.append(role.id) - - if not roles: - return - - # Get all roles that are rolepinged - roleping_ids = [r.role for r in rolepings] - - # Get roles in rolepings - role_in_rolepings = find_all(lambda x: x in roleping_ids, roles) - - # Check if the user has the role, so they are allowed to ping it - user_missing_role = any(x.id not in roleping_ids for x in message.author.roles) - - # Admins can ping whoever - user_is_admin = message.author.guild_permissions.ADMINISTRATOR - - # Check if user in a bypass list - user_has_bypass = False - for roleping in rolepings: - if message.author.id in roleping.bypass["users"]: - user_has_bypass = True - break - if any(role.id in roleping.bypass["roles"] for role in message.author.roles): - user_has_bypass = True - break - - if role_in_rolepings and user_missing_role and not user_is_admin and not user_has_bypass: - w = Warning( - active=True, - admin=jarvis.jconfig.client_id, - duration=24, - guild=message.guild.id, - reason="Pinged a blocked role/user with a blocked role", - user=message.author.id, - ) - await w.commit() - fields = [ - EmbedField( - name="Reason", - value="Pinged a blocked role/user with a blocked role", - inline=False, - ) - ] - embed = build_embed( - title="Warning", - description=f"{message.author.mention} has been warned", - fields=fields, - ) - embed.set_author( - name=message.author.nick if message.author.nick else message.author.name, - icon_url=message.author.display_avatar.url, - ) - embed.set_footer( - text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}" - ) - await message.channel.send(embed=embed) - - @listen() - async def on_message(self, message: Message) -> None: - """Handle on_message event. Calls other event handlers.""" - if not isinstance(message.channel, DMChannel) and not message.author.bot: - await self.autoreact(message) - await self.massmention(message) - await self.roleping(message) - await self.autopurge(message) - await self.checks(message) - - @listen() - async def on_message_edit(self, before: Message, after: Message) -> None: - """Handle on_message_edit event. Calls other event handlers.""" - if not isinstance(after.channel, DMChannel) and not after.author.bot: - await self.massmention(after) - await self.roleping(after) - await self.checks(after) - await self.roleping(after) - await self.checks(after) diff --git a/jarvis/utils/__init__.py b/jarvis/utils/__init__.py index 009d24b..ad04b08 100644 --- a/jarvis/utils/__init__.py +++ b/jarvis/utils/__init__.py @@ -3,7 +3,9 @@ from datetime import datetime from pkgutil import iter_modules import git -from dis_snek.models.discord.embed import Embed +from dis_snek.models.discord.embed import Embed, EmbedField +from dis_snek.models.discord.guild import AuditLogEntry +from dis_snek.models.discord.user import Member import jarvis.cogs import jarvis.db @@ -35,6 +37,34 @@ def build_embed( return embed +def modlog_embed( + member: Member, + admin: Member, + log: AuditLogEntry, + title: str, + desc: str, +) -> Embed: + """Get modlog embed.""" + fields = [ + EmbedField( + name="Moderator", + value=f"{admin.mention} ({admin.username}#{admin.discriminator})", + ), + ] + if log.reason: + fields.append(EmbedField(name="Reason", value=log.reason, inline=False)) + embed = build_embed( + title=title, + description=desc, + color="#fc9e3f", + fields=fields, + timestamp=log.created_at, + ) + embed.set_author(name=f"{member.username}", icon_url=member.display_avatar.url) + embed.set_footer(text=f"{member.username}#{member.discriminator} | {member.id}") + return embed + + def get_extensions(path: str = jarvis.cogs.__path__) -> list: """Get J.A.R.V.I.S. cogs.""" config = get_config()