Files
payphone/payphone/cogs/mods/views.py
T

232 lines
7.7 KiB
Python

import discord
from discord import errors
from discord.ext import pages
from discord.utils import find
from tortoise import transactions
from payphone import bot
from payphone.db import models
from payphone.core import constants, formatting as fmt
from payphone.cogs.mods import modals, views, embeds
class ReportView(discord.ui.View):
"""The view sent together with the report embed."""
def __init__(
self, bot: bot.Payphone, report: models.Report, remaining_reports: int
) -> None:
"""Initializes the view.
Args:
bot (bot.Payphone): The bot.
report (models.Report): The report.
remaining_reports (int): The amount of reports that need to be reviewed remaining.
"""
super().__init__(timeout=900, disable_on_timeout=True)
self.bot = bot
self.report = report
option_labels = set(
f"Ban {rs.profile.name} [ID: {rs.user_id}]" for rs in report.call.call_rss
)
actions = discord.ui.Select(
placeholder="Actions",
options=[discord.SelectOption(label=label) for label in option_labels],
)
async def actions_callback(interaction: discord.Interaction) -> None:
# interaction.data = {'values': ['Ban Nyeki (JPP)'], 'custom_id': 'staff_call_report:actions', 'component_type': 3}
value = interaction.data["values"][0]
user_id = int(value.rsplit("[ID: ", 1)[1][:-1])
await interaction.response.send_modal(
modals.BanUserModal(
bot,
find(
lambda rs: rs.user_id == user_id, report.call.call_rss
).profile,
report.id,
)
)
actions.callback = actions_callback
self.add_item(actions)
self.add_item(
discord.ui.Button(
label=f"Remaining: {remaining_reports}", disabled=True, row=2
)
)
@discord.ui.button(label="Message Logs", style=discord.ButtonStyle.gray, row=2)
async def message_logs(
self, _button: discord.ui.Button, interaction: discord.Interaction
) -> None:
report = self.report
messages = (
await models.Message.filter(call=report.call)
.order_by("id")
.prefetch_related("contents")
)
logs = []
reporter_channel_id = find(
lambda rs: rs.user_id == report.reported_by_id, report.call.call_rss
).channel_id
profiles_to_relationship_mapping = {
rs.profile_id: rs for rs in report.call.call_rss
}
last_user_id = None
last_channel_id = None
current_block = ""
for message in messages:
is_new_block = (
message.user_id != last_user_id or last_channel_id != message.channel_id
)
if is_new_block:
logs.append(current_block)
current_block = ""
current_block += f"{"+" if message.channel_id == reporter_channel_id else "-"} {f"{profiles_to_relationship_mapping[message.profile_id].profile.name}{f" (Masked as {profiles_to_relationship_mapping[message.profile_id].mask_name})" if profiles_to_relationship_mapping[message.profile_id].is_masked else ""}" if message.profile_id in profiles_to_relationship_mapping else "Unknown"}:"
for content in message.contents:
current_block += (
f"\n{"!" if not content.was_propagated else "X" if message.was_deleted else " "} {content.content}"
)
last_user_id = message.user_id
last_channel_id = message.channel_id
log_pages = []
for current_block in logs:
if len(log_pages) > 0 and len(log_pages[-1]) + len(current_block) < 1000:
log_pages[-1] += "\n\n" + current_block.replace(
"```",
f"`{constants.INVISIBLE_CHARACTER}`{constants.INVISIBLE_CHARACTER}`",
)
else:
log_pages.append(
current_block.replace(
"```",
f"`{constants.INVISIBLE_CHARACTER}`{constants.INVISIBLE_CHARACTER}`",
)
)
await pages.Paginator(
[f"```diff\n{page}\n```" for page in log_pages],
timeout=300,
).respond(interaction, ephemeral=True)
@discord.ui.button(label="Accept", style=discord.ButtonStyle.green, row=2)
@transactions.atomic()
async def accept(
self, _button: discord.ui.Button, interaction: discord.Interaction
) -> None:
report = self.report
report.status = models.ReportStatus.ACCEPTED
await report.save()
next_report = (
await models.Report.filter(status=models.ReportStatus.ON_REVIEW)
.order_by("-priority")
.limit(1)
.first()
.select_related("call")
.prefetch_related("call__call_rss", "call__call_rss__profile")
)
total = await models.Report.filter(status=models.ReportStatus.ON_REVIEW).count()
banned_user_ids = (
await models.Ban.filter(report=report)
.distinct()
.values_list("user_id", flat=True)
)
if next_report is None:
await interaction.response.edit_message(
content="✅ No reports left, have this cookie 🍪 !!",
embed=None,
view=None,
)
else:
await interaction.response.edit_message(
embed=embeds.ReportEmbed(self.bot, next_report),
view=views.ReportView(self.bot, next_report, total),
)
if len(banned_user_ids) > 0:
profiles = [
rs.profile
for rs in report.call.call_rss
if rs.user_id in banned_user_ids
]
try:
await (await self.bot.get_or_fetch_user(report.reported_by_id)).send(
f"🔔 Your report for call `{report.call_id}` helped us ban "
+ fmt.text_join(
[
(
f"`{p.name}`"
if p.user_id != report.reported_by_id
else "`you`"
)
for p in profiles
]
)
+ ". Thank you for your report!"
)
except errors.DiscordException:
pass
@discord.ui.button(label="Decline", style=discord.ButtonStyle.red, row=2)
@transactions.atomic()
async def decline(
self, _button: discord.ui.Button, interaction: discord.Interaction
) -> None:
report = self.report
report.status = models.ReportStatus.DECLINED
await report.save()
report = (
await models.Report.filter(status=models.ReportStatus.ON_REVIEW)
.order_by("-priority")
.limit(1)
.first()
.select_related("call")
.prefetch_related("call__call_rss", "call__call_rss__profile")
)
total = await models.Report.filter(status=models.ReportStatus.ON_REVIEW).count()
if report is None:
await interaction.response.edit_message(
content="✅ No reports left, have this cookie 🍪 !!",
embed=None,
view=None,
)
return
await interaction.response.edit_message(
embed=embeds.ReportEmbed(self.bot, report),
view=views.ReportView(self.bot, report, total),
)