jarvis-bot/jarvis/client/events/components.py

179 lines
7 KiB
Python

"""JARVIS component event mixin."""
from jarvis_core.db import q
from jarvis_core.db.models import Action, Modlog, Note, Phishlist, Reminder, Star
from naff import listen
from naff.api.events.internal import ButtonPressed
from naff.models.discord.embed import EmbedField
from naff.models.discord.enums import Permissions
from jarvis.utils import build_embed
class ComponentEventMixin:
async def _handle_modcase_button(self, event: ButtonPressed) -> bool:
context = event.ctx
if not context.custom_id.startswith("modcase|"):
return False # Failsafe
if not context.deferred and not context.responded:
await context.defer(ephemeral=True)
if not context.author.has_permission(Permissions.MODERATE_MEMBERS):
return False
user_key = f"msg|{context.message.id}"
action_key = ""
if context.custom_id == "modcase|yes":
if user_id := await self.redis.get(user_key):
action_key = f"{user_id}|{context.guild.id}"
if (user := await context.guild.fetch_member(user_id)) and (
action_data := await self.redis.get(action_key)
):
name, parent = action_data.split("|")[:2]
action = Action(action_type=name, parent=parent)
note = Note(admin=context.author.id, content="Moderation case opened via message")
modlog = await Modlog.find_one(q(user=user.id, guild=context.guild.id, open=True))
if modlog:
self.logger.debug("User already has active case in guild")
await context.send(f"User already has open case: {modlog.nanoid}", ephemeral=True)
else:
modlog = Modlog(
user=user.id,
admin=context.author.id,
guild=context.guild.id,
actions=[action],
notes=[note],
)
await modlog.commit()
fields = (
EmbedField(name="Admin", value=context.author.mention),
EmbedField(name="Opening Action", value=f"{name} {parent}"),
)
embed = build_embed(
title="Moderation Case Opened",
description=f"Moderation case opened against {user.mention}",
fields=fields,
)
embed.set_author(
name=user.username + "#" + user.discriminator,
icon_url=user.display_avatar.url,
)
await context.message.edit(embeds=embed)
elif not user:
self.logger.debug("User no longer in guild")
await context.send("User no longer in guild", ephemeral=True)
else:
self.logger.warn("Unable to get action data ( %s )", action_key)
await context.send("Unable to get action data", ephemeral=True)
for row in context.message.components:
for component in row.components:
component.disabled = True
await context.message.edit(components=context.message.components)
msg = "Cancelled" if context.custom_id == "modcase|no" else "Moderation case opened"
await context.send(msg)
await self.redis.delete(user_key)
await self.redis.delete(action_key)
return True
async def _handle_delete_button(self, event: ButtonPressed) -> bool:
context = event.ctx
if not context.custom_id.startswith("delete|"):
return False # Failsafe
if not context.deferred and not context.responded:
await context.defer(ephemeral=True)
uid = context.custom_id.split("|")[1]
if (
not context.author.has_permission(Permissions.MANAGE_MESSAGES)
and not context.author.has_permission(Permissions.ADMINISTRATOR)
and not str(context.author.id) == uid
):
await context.send("I'm afraid I can't let you do that", ephemeral=True)
return True # User does not have perms to delete
if star := await Star.find_one(q(star=context.message.id, guild=context.guild.id)):
await star.delete()
await context.message.delete()
await context.send("Message deleted", ephemeral=True)
return True
async def _handle_copy_button(self, event: ButtonPressed) -> bool:
context = event.ctx
if not context.custom_id.startswith("copy|"):
return False
if not context.deferred and not context.responded:
await context.defer(ephemeral=True)
what, rid = context.custom_id.split("|")[1:]
if what == "rme":
reminder = await Reminder.find_one(q(_id=rid))
if reminder:
new_reminder = Reminder(
user=context.author.id,
channel=context.channel.id,
guild=context.guild.id,
message=reminder.message,
remind_at=reminder.remind_at,
private=reminder.private,
active=reminder.active,
)
await new_reminder.commit()
await context.send("Reminder copied!", ephemeral=True)
return True
async def _handle_phishlist_button(self, event: ButtonPressed) -> bool:
context = event.ctx
if not context.custom_id.startswith("pl|"):
return False
if not context.deferred and not context.responded:
await context.defer(ephemeral=True)
_, valid, id_ = context.custom_id.split("|")
valid = valid == "valid"
pl = await Phishlist.find_one(q(_id=id_))
if not pl:
self.logger.warn(f"Phishlist {id_} does not exist!")
return False
pl.valid = valid
pl.confirmed = True
await pl.commit()
for row in context.message.components:
for component in row.components:
component.disabled = True
embed = context.message.embeds[0]
embed.add_field(name="Valid", value="Yes" if valid else "No")
await context.message.edit(components=context.message.components, embeds=embed)
await context.send("Confirmed! Thank you for confirming this URL.")
return True
@listen()
async def on_button(self, event: ButtonPressed) -> None:
"""Process button events."""
modcase = await self._handle_modcase_button(event)
delete = await self._handle_delete_button(event)
copy = await self._handle_copy_button(event)
phishlist = await self._handle_phishlist_button(event)
if not any([modcase, delete, copy, phishlist]):
# self.logger.warn(f"Unhandled ButtonPressed event: {event.ctx.custom_id}")
pass