Move modlog and events into jarvis.client
This commit is contained in:
parent
10fe938409
commit
0b3c2e7121
9 changed files with 367 additions and 445 deletions
|
@ -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)
|
||||
|
|
363
jarvis/client.py
363
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)
|
||||
|
|
|
@ -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)
|
|
@ -1 +0,0 @@
|
|||
"""JARVIS member modlog processing."""
|
|
@ -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)
|
|
@ -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
|
|
@ -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")
|
|
@ -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)
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Reference in a new issue