EveCogs/wormhole/ui/modals.py

85 lines
3.2 KiB
Python

"""Discord UI modals for Wormhole (e.g. report form)."""
from __future__ import annotations
from datetime import datetime, timezone
from typing import TYPE_CHECKING
import discord
from ..utils import ok_embed, truncate, warn_embed
if TYPE_CHECKING:
from ..core import Wormhole
class ReportModal(discord.ui.Modal, title="Report Message"):
reason = discord.ui.TextInput(
label="Reason",
style=discord.TextStyle.paragraph,
placeholder="Describe why you're reporting this message...",
required=True,
max_length=1000,
)
def __init__(self, cog: Wormhole, net_name: str, message: discord.Message) -> None:
super().__init__()
self.cog = cog
self.net_name = net_name
self.message = message
async def on_submit(self, interaction: discord.Interaction) -> None:
# report_id must be computed and written inside the same locked
# section — reading report_counter beforehand let two concurrent
# reports land on the same id and left the counter not advanced.
async with self.cog.config.networks() as ns:
nd = ns.get(self.net_name)
if not nd:
await interaction.response.send_message("Network not found.", ephemeral=True)
return
report_id = nd.get("report_counter", 0) + 1
report = {
"id": report_id,
"reporter_id": interaction.user.id,
"author_id": self.message.author.id,
"message_id": self.message.id,
"channel_id": self.message.channel.id,
"guild_id": self.message.guild.id if self.message.guild else None,
"content_preview": truncate(self.message.content or "*[no text]*", 300),
"jump_url": self.message.jump_url,
"reason": self.reason.value,
"timestamp": datetime.now(timezone.utc).isoformat(),
"resolved": False,
"resolved_by": None,
"resolution": None,
}
nd.setdefault("reports", []).append(report)
nd["report_counter"] = report_id
owner = self.cog.bot.get_user(nd.get("owner_id"))
if owner:
try:
await owner.send(
embed=warn_embed(
f"**Report #{report_id}** in `{self.net_name}`\n"
f"Reporter: {interaction.user} (`{interaction.user.id}`)\n"
f"Author: {self.message.author} (`{self.message.author.id}`)\n"
f"Reason: {self.reason.value}",
title="🚩 New Report",
)
)
except discord.Forbidden:
pass
# Notify configured report channel with action buttons
try:
nd_full = await self.cog._net(self.net_name)
await self.cog._notify_report_channel(nd_full, self.net_name, report)
except Exception:
pass
await interaction.response.send_message(
embed=ok_embed(f"Report #{report_id} submitted. Staff will review it."),
ephemeral=True,
)