Delete modules/pirate_report/pirate_report.py
This commit is contained in:
parent
2f35e022b7
commit
671fdeb9a9
@ -1,579 +0,0 @@
|
||||
import re
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord import app_commands
|
||||
|
||||
from mod_perms import (
|
||||
is_moderator_member,
|
||||
is_moderator_userid,
|
||||
require_mod_ctx,
|
||||
require_mod_interaction,
|
||||
)
|
||||
|
||||
CHECK = '✅'
|
||||
CROSS = '❌'
|
||||
|
||||
# --------------------- Helpers ---------------------
|
||||
|
||||
_ACCT_RE = re.compile(r'.+#\d{5}$')
|
||||
|
||||
def _acct_ok(s: str) -> bool:
|
||||
return bool(_ACCT_RE.fullmatch(s.strip()))
|
||||
|
||||
def _now_utc_str() -> str:
|
||||
return datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')
|
||||
|
||||
def _parse_bool(s: str) -> bool:
|
||||
v = s.strip().lower()
|
||||
if v in ('y', 'yes', 'true', 't', '1'):
|
||||
return True
|
||||
if v in ('n', 'no', 'false', 'f', '0'):
|
||||
return False
|
||||
raise ValueError("Please enter yes or no")
|
||||
|
||||
# --------------------- Modals ----------------------
|
||||
|
||||
class ReportModal(discord.ui.Modal, title="Submit Pirate Report"):
|
||||
def __init__(self, cog: "PirateReportCog"):
|
||||
super().__init__()
|
||||
self.cog = cog
|
||||
|
||||
self.character_name = discord.ui.TextInput(
|
||||
label="In-game nickname",
|
||||
placeholder="e.g., SandStalker",
|
||||
max_length=64,
|
||||
required=True
|
||||
)
|
||||
self.account_name = discord.ui.TextInput(
|
||||
label="Account (Name#12345)",
|
||||
placeholder="Must end with # and 5 digits",
|
||||
max_length=64,
|
||||
required=True
|
||||
)
|
||||
|
||||
self.add_item(self.character_name)
|
||||
self.add_item(self.account_name)
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
if not interaction.guild:
|
||||
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
|
||||
|
||||
char = self.character_name.value.strip()
|
||||
acct = self.account_name.value.strip()
|
||||
|
||||
if not _acct_ok(acct):
|
||||
return await interaction.response.send_message(
|
||||
"❌ Invalid account format. It must end with `#` and **five digits** (e.g. `SomeUser#12345`).",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
dm = self.cog.bot.data_manager
|
||||
char_l = char.lower()
|
||||
acct_l = acct.lower()
|
||||
|
||||
# Anti-spam: 60s per reporter
|
||||
now = time.time()
|
||||
recent = [r for r in dm.get('reports')
|
||||
if r.get('submitter_id') == interaction.user.id and (now - r.get('ts', now)) < 60]
|
||||
if recent:
|
||||
return await interaction.response.send_message("⏱️ Please wait 60 seconds before submitting another report.", ephemeral=True)
|
||||
|
||||
# Already approved?
|
||||
if any(p['account_name'].lower() == acct_l for p in dm.get('pirates')):
|
||||
return await interaction.response.send_message("❌ This player is already in the pirate list.", ephemeral=True)
|
||||
|
||||
# Pending duplicate?
|
||||
if any(r['character_name'].lower() == char_l and r['account_name'].lower() == acct_l for r in dm.get('reports')):
|
||||
return await interaction.response.send_message("⏳ A report for this player is already pending moderation.", ephemeral=True)
|
||||
|
||||
# Acknowledge in channel so we can edit later when approved/rejected
|
||||
try:
|
||||
ack = await interaction.channel.send(f"{interaction.user.mention} thanks — your report was sent to moderators for review.")
|
||||
except Exception as e:
|
||||
print("[pirate_report] ack send failed:", repr(e))
|
||||
ack = None
|
||||
|
||||
# Send to mod channel with ✅/❌
|
||||
mod_ch = interaction.guild.get_channel(self.cog.mod_channel)
|
||||
if not mod_ch:
|
||||
return await interaction.response.send_message("❌ Mod channel not configured.", ephemeral=True)
|
||||
|
||||
try:
|
||||
mod_msg = await mod_ch.send(
|
||||
f"🚩 **Pirate Report**\n"
|
||||
f"**Character:** {char}\n"
|
||||
f"**Account:** {acct}\n"
|
||||
f"**Submitted by:** {interaction.user.mention}"
|
||||
)
|
||||
await mod_msg.add_reaction(CHECK)
|
||||
await mod_msg.add_reaction(CROSS)
|
||||
except Exception as e:
|
||||
print("[pirate_report] mod message failed:", repr(e))
|
||||
return await interaction.response.send_message("❌ Failed to send to mod channel.", ephemeral=True)
|
||||
|
||||
dm.add('reports', {
|
||||
'report_id': mod_msg.id,
|
||||
'guild_id': interaction.guild.id,
|
||||
'character_name': char,
|
||||
'account_name': acct,
|
||||
'submitter_id': interaction.user.id,
|
||||
'origin_channel_id': interaction.channel.id if interaction.channel else 0,
|
||||
'ack_message_id': ack.id if ack else 0,
|
||||
'status': 'pending',
|
||||
'ts': now
|
||||
})
|
||||
|
||||
await interaction.response.send_message("✅ Report submitted to moderators.", ephemeral=True)
|
||||
|
||||
class EditPirateModal(discord.ui.Modal, title="Edit Pirate Entry"):
|
||||
def __init__(self, cog: "PirateReportCog"):
|
||||
super().__init__()
|
||||
self.cog = cog
|
||||
|
||||
self.old_account = discord.ui.TextInput(
|
||||
label="Current account (Name#12345)",
|
||||
placeholder="Exact current account in the list",
|
||||
max_length=64,
|
||||
required=True
|
||||
)
|
||||
self.new_character = discord.ui.TextInput(
|
||||
label="New in-game nickname (optional)",
|
||||
placeholder="Leave blank to keep existing",
|
||||
max_length=64,
|
||||
required=False
|
||||
)
|
||||
self.new_account = discord.ui.TextInput(
|
||||
label="New account (optional, Name#12345)",
|
||||
placeholder="Leave blank to keep existing",
|
||||
max_length=64,
|
||||
required=False
|
||||
)
|
||||
|
||||
self.add_item(self.old_account)
|
||||
self.add_item(self.new_character)
|
||||
self.add_item(self.new_account)
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
if not interaction.guild:
|
||||
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
|
||||
|
||||
if not is_moderator_member(interaction.user, self.cog.bot):
|
||||
return await interaction.response.send_message("This action is restricted to moderators.", ephemeral=True)
|
||||
|
||||
old_acct = self.old_account.value.strip()
|
||||
new_char = (self.new_character.value or "").strip()
|
||||
new_acct = (self.new_account.value or "").strip()
|
||||
|
||||
if not new_char and not new_acct:
|
||||
return await interaction.response.send_message(
|
||||
"❌ Provide **at least one** of: new nickname or new account.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
dm = self.cog.bot.data_manager
|
||||
pirates = dm.get('pirates')
|
||||
rec = next((p for p in pirates if p['account_name'].lower() == old_acct.lower()), None)
|
||||
if not rec:
|
||||
return await interaction.response.send_message("❌ Pirate not found.", ephemeral=True)
|
||||
|
||||
if new_acct:
|
||||
if not _acct_ok(new_acct):
|
||||
return await interaction.response.send_message("❌ Invalid new account format (Name#12345).", ephemeral=True)
|
||||
if new_acct.lower() != old_acct.lower() and any(p['account_name'].lower() == new_acct.lower() for p in pirates):
|
||||
return await interaction.response.send_message("❌ Another pirate already has that account.", ephemeral=True)
|
||||
|
||||
before = rec.copy()
|
||||
dm.remove('pirates', lambda p: p['account_name'].lower() == old_acct.lower())
|
||||
if new_char:
|
||||
rec['character_name'] = new_char
|
||||
if new_acct:
|
||||
rec['account_name'] = new_acct
|
||||
dm.add('pirates', rec)
|
||||
|
||||
await self.cog._modlog(
|
||||
interaction.guild,
|
||||
f"✏️ Edited pirate by {interaction.user.mention}: "
|
||||
f"{'name ' + before['character_name'] + ' → ' + rec['character_name'] if new_char else ''} "
|
||||
f"{'/ account ' + before['account_name'] + ' → ' + rec['account_name'] if new_acct else ''}".strip()
|
||||
)
|
||||
await interaction.response.send_message("✅ Pirate updated.", ephemeral=True)
|
||||
await self.cog._refresh_pirates_list(interaction.guild)
|
||||
|
||||
class EncounterModal(discord.ui.Modal, title="Log Pirate Encounter"):
|
||||
def __init__(self, cog: "PirateReportCog"):
|
||||
super().__init__()
|
||||
self.cog = cog
|
||||
|
||||
self.identifier = discord.ui.TextInput(
|
||||
label="Pirate (name or account)",
|
||||
placeholder="MuadDib or MuadDib#12345",
|
||||
required=True,
|
||||
max_length=64
|
||||
)
|
||||
self.group_size = discord.ui.TextInput(
|
||||
label="Group size (including this pirate)",
|
||||
placeholder="How many pirates were in the group?",
|
||||
required=True
|
||||
)
|
||||
self.kills = discord.ui.TextInput(
|
||||
label="Kills (integer ≥ 0; 0 = none/unknown)",
|
||||
placeholder="How many did the pirate kill during the encounter",
|
||||
required=True
|
||||
)
|
||||
self.destruction = discord.ui.TextInput(
|
||||
label="Destructive? (yes/no)",
|
||||
placeholder="Did they destroy a base/ornithopter? yes or no",
|
||||
required=True
|
||||
)
|
||||
self.skill = discord.ui.TextInput(
|
||||
label="Perceived Skill (0–5, 0 = unknown)",
|
||||
placeholder="0..5",
|
||||
required=True
|
||||
)
|
||||
|
||||
self.add_item(self.identifier)
|
||||
self.add_item(self.group_size)
|
||||
self.add_item(self.kills)
|
||||
self.add_item(self.destruction)
|
||||
self.add_item(self.skill)
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
ident_raw = self.identifier.value.strip()
|
||||
guild = interaction.guild
|
||||
if guild is None:
|
||||
return await interaction.response.send_message("This can only be used in a server.", ephemeral=True)
|
||||
|
||||
# Parse numeric fields
|
||||
try:
|
||||
group_size = int(self.group_size.value.strip()); assert group_size >= 1
|
||||
except Exception:
|
||||
return await interaction.response.send_message("❌ **Group size** must be an integer ≥ 1.", ephemeral=True)
|
||||
try:
|
||||
kills = int(self.kills.value.strip()); assert kills >= 0
|
||||
except Exception:
|
||||
return await interaction.response.send_message("❌ **Kills** must be an integer ≥ 0.", ephemeral=True)
|
||||
try:
|
||||
destruction = _parse_bool(self.destruction.value)
|
||||
except ValueError:
|
||||
return await interaction.response.send_message("❌ **Destructive** must be **yes** or **no**.", ephemeral=True)
|
||||
try:
|
||||
skill = int(self.skill.value.strip()); assert 0 <= skill <= 5
|
||||
except Exception:
|
||||
return await interaction.response.send_message("❌ **Skill** must be an integer between **0** and **5**.", ephemeral=True)
|
||||
|
||||
# Resolve to a single pirate record and canonical account identifier
|
||||
pirate, error = self.cog.resolve_pirate(ident_raw)
|
||||
if error:
|
||||
return await interaction.response.send_message(error, ephemeral=True)
|
||||
if not pirate:
|
||||
return await interaction.response.send_message(
|
||||
"❌ No such pirate registered. Ask a moderator to add them, or submit a **/report** for review.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
canonical_acct = pirate['account_name'] # <- always store account here
|
||||
acct_l = canonical_acct.lower()
|
||||
char_l = pirate['character_name'].lower()
|
||||
|
||||
dm = self.cog.bot.data_manager
|
||||
now = time.time()
|
||||
|
||||
# Rate-limit by canonical account
|
||||
recent = [
|
||||
e for e in dm.get('encounters')
|
||||
if e['reporter_id'] == interaction.user.id
|
||||
and e.get('identifier','').lower() in (acct_l, char_l) # respect legacy
|
||||
and (now - e['timestamp']) < 600
|
||||
]
|
||||
if recent:
|
||||
return await interaction.response.send_message(
|
||||
"⏱️ You can only report the same pirate once every **10 minutes**.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
# Store with canonical account as identifier
|
||||
rec = {
|
||||
'identifier': canonical_acct,
|
||||
'reporter_id': interaction.user.id,
|
||||
'timestamp': now,
|
||||
'group_size': group_size,
|
||||
'kills': kills,
|
||||
'destruction': destruction,
|
||||
'skill': skill
|
||||
}
|
||||
dm.add('encounters', rec)
|
||||
|
||||
# Recalculate threat (count both new account-based and legacy name-based entries)
|
||||
encs = [e for e in dm.get('encounters') if e.get('identifier','').lower() in (acct_l, char_l)]
|
||||
total = len(encs)
|
||||
if total:
|
||||
group_threshold = self.cog.group_threshold
|
||||
kill_rate = sum(e['kills'] > 0 for e in encs) / total
|
||||
group_rate = sum(e['group_size'] >= group_threshold for e in encs) / total
|
||||
destroy_rate = sum(bool(e['destruction']) for e in encs) / total
|
||||
skill_samples = [e['skill'] / 5 for e in encs if e['skill'] > 0]
|
||||
skill_rate = (sum(skill_samples) / len(skill_samples)) if skill_samples else 0.0
|
||||
|
||||
w_k, w_d, w_g, w_s = self.cog.w_kill, self.cog.w_destruction, self.cog.w_group, self.cog.w_skill
|
||||
weighted = (w_k * kill_rate) + (w_d * destroy_rate) + (w_g * group_rate) + (w_s * skill_rate)
|
||||
threat_level = int(round(100 * min(1.0, max(0.0, weighted))))
|
||||
|
||||
# Update pirate record
|
||||
pirates = dm.get('pirates')
|
||||
def match(p): return p['account_name'].lower() == acct_l
|
||||
rec0 = next((p for p in pirates if match(p)), None)
|
||||
if rec0:
|
||||
dm.remove('pirates', match)
|
||||
rec0.update({'threat_level': threat_level, 'encounter_count': total})
|
||||
dm.add('pirates', rec0)
|
||||
|
||||
await interaction.response.send_message(
|
||||
f"✅ Encounter recorded for **{canonical_acct}**.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
await self.cog._refresh_pirates_list(interaction.guild)
|
||||
|
||||
# -------------- Cog: commands + listeners ---------------
|
||||
|
||||
class PirateReportCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
cfg = bot.config['DEFAULT']
|
||||
self.mod_channel = int(cfg['mod_channel_id'])
|
||||
self.modlog_channel_id = int(cfg['modlog_channel_id'])
|
||||
|
||||
# Optional threat weights (normalized elsewhere if you added them)
|
||||
try:
|
||||
self.group_threshold = int(cfg.get('threat_group_threshold', '3'))
|
||||
except Exception:
|
||||
self.group_threshold = 3
|
||||
# Defaults if not already present in your earlier version:
|
||||
self.w_kill = float(cfg.get('threat_w_kill', '0.35'))
|
||||
self.w_destruction = float(cfg.get('threat_w_destruction', '0.30'))
|
||||
self.w_group = float(cfg.get('threat_w_group', '0.20'))
|
||||
self.w_skill = float(cfg.get('threat_w_skill', '0.15'))
|
||||
|
||||
async def _refresh_pirates_list(self, guild: discord.Guild):
|
||||
plist = self.bot.get_cog('PiratesListCog')
|
||||
if plist:
|
||||
await plist.refresh_list(guild)
|
||||
|
||||
async def _modlog(self, guild: discord.Guild, content: str):
|
||||
ch = guild.get_channel(self.modlog_channel_id)
|
||||
if ch:
|
||||
try:
|
||||
await ch.send(content)
|
||||
except Exception as e:
|
||||
print("[pirate_report] modlog send failed:", repr(e))
|
||||
self.bot.data_manager.add('modlog', {'ts': time.time(), 'guild_id': guild.id, 'content': content})
|
||||
|
||||
# --- Resolver: name/account -> pirate record (handles ambiguity) ---
|
||||
def resolve_pirate(self, ident: str):
|
||||
"""Return (pirate_record or None, error_message or None)."""
|
||||
dm = self.bot.data_manager
|
||||
pirates = dm.get('pirates')
|
||||
s = ident.strip()
|
||||
s_l = s.lower()
|
||||
if '#' in s and _acct_ok(s):
|
||||
rec = next((p for p in pirates if p['account_name'].lower() == s_l), None)
|
||||
return (rec, None)
|
||||
# resolve by character; must be unambiguous
|
||||
matches = [p for p in pirates if p['character_name'].lower() == s_l]
|
||||
if not matches:
|
||||
return (None, None)
|
||||
if len(matches) > 1:
|
||||
return (None, "❌ That character name is **ambiguous**. Please use the account (e.g. `Name#12345`).")
|
||||
return (matches[0], None)
|
||||
|
||||
# Remove pirate (mod-only)
|
||||
@commands.hybrid_command(name='remove_pirate', description='Remove an approved pirate entry')
|
||||
async def remove_pirate(self, ctx, account_name: str):
|
||||
if not await require_mod_ctx(ctx, "This command is restricted to moderators."):
|
||||
return
|
||||
acct_lower = account_name.strip().lower()
|
||||
dm = self.bot.data_manager
|
||||
if not any(p['account_name'].lower() == acct_lower for p in dm.get('pirates')):
|
||||
return await ctx.reply("Pirate not found.")
|
||||
dm.remove('pirates', lambda p: p['account_name'].lower() == acct_lower)
|
||||
await self._modlog(ctx.guild, f"🗑️ Removed pirate {account_name} by {ctx.author.mention}")
|
||||
await self._refresh_pirates_list(ctx.guild)
|
||||
await ctx.reply("Removed.", ephemeral=hasattr(ctx, "interaction") and ctx.interaction is not None)
|
||||
|
||||
# Modal launchers
|
||||
@app_commands.command(name="report", description="Submit a pirate report for moderator review (opens a form)")
|
||||
async def report(self, interaction: discord.Interaction):
|
||||
if not interaction.guild:
|
||||
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
|
||||
await interaction.response.send_modal(ReportModal(self))
|
||||
|
||||
@app_commands.command(name="edit_pirate", description="Edit a pirate entry (opens a form)")
|
||||
async def edit_pirate(self, interaction: discord.Interaction):
|
||||
if not await require_mod_interaction(interaction):
|
||||
return
|
||||
await interaction.response.send_modal(EditPirateModal(self))
|
||||
|
||||
@app_commands.command(name="encounter", description="Log a pirate encounter (opens a form)")
|
||||
async def encounter(self, interaction: discord.Interaction):
|
||||
if not interaction.guild:
|
||||
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
|
||||
await interaction.response.send_modal(EncounterModal(self))
|
||||
|
||||
# ---- Migration: convert encounter identifiers to accounts (mod-only) ----
|
||||
@commands.hybrid_command(name='encounters_migrate_ids', description='Migrate encounter identifiers to account names')
|
||||
async def encounters_migrate_ids(self, ctx: commands.Context):
|
||||
if not await require_mod_ctx(ctx, "This command is restricted to moderators."):
|
||||
return
|
||||
dm = self.bot.data_manager
|
||||
pirates = dm.get('pirates')
|
||||
by_char = {}
|
||||
for p in pirates:
|
||||
by_char.setdefault(p['character_name'].lower(), []).append(p)
|
||||
by_acct = {p['account_name'].lower(): p for p in pirates}
|
||||
|
||||
changed = 0
|
||||
ambiguous = 0
|
||||
missing = 0
|
||||
already = 0
|
||||
|
||||
for e in dm.get('encounters'):
|
||||
ident = e.get('identifier', '')
|
||||
if not ident:
|
||||
continue
|
||||
if '#' in ident:
|
||||
already += 1
|
||||
continue
|
||||
key = ident.lower()
|
||||
matches = by_char.get(key, [])
|
||||
if not matches:
|
||||
missing += 1
|
||||
continue
|
||||
if len(matches) > 1:
|
||||
ambiguous += 1
|
||||
continue
|
||||
acct = matches[0]['account_name']
|
||||
# update this one entry atomically
|
||||
def pred(x, ts=e['timestamp'], rid=e['reporter_id'], ident_old=ident):
|
||||
return x.get('timestamp') == ts and x.get('reporter_id') == rid and x.get('identifier') == ident_old
|
||||
def upd(x, acct_new=acct):
|
||||
x['identifier'] = acct_new
|
||||
return x
|
||||
ok = dm.update('encounters', pred, upd)
|
||||
if ok:
|
||||
changed += 1
|
||||
|
||||
await ctx.reply(
|
||||
f"Migration complete.\n"
|
||||
f"- Updated to accounts: **{changed}**\n"
|
||||
f"- Already accounts: **{already}**\n"
|
||||
f"- Ambiguous character names (skipped): **{ambiguous}**\n"
|
||||
f"- Not found in pirates list (skipped): **{missing}**",
|
||||
ephemeral=hasattr(ctx, "interaction") and ctx.interaction is not None
|
||||
)
|
||||
|
||||
await self._refresh_pirates_list(ctx.guild)
|
||||
|
||||
# Moderator reaction handling (atomic claim)
|
||||
@commands.Cog.listener()
|
||||
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
|
||||
if (
|
||||
payload.channel_id != self.mod_channel
|
||||
or str(payload.emoji) not in (CHECK, CROSS)
|
||||
or payload.user_id == self.bot.user.id
|
||||
):
|
||||
return
|
||||
|
||||
channel = self.bot.get_channel(payload.channel_id)
|
||||
if not channel or not channel.guild:
|
||||
return
|
||||
if not is_moderator_userid(channel.guild, payload.user_id, self.bot):
|
||||
return
|
||||
|
||||
try:
|
||||
msg = await channel.fetch_message(payload.message_id)
|
||||
except Exception as e:
|
||||
print("[pirate_report] fetch mod msg failed:", repr(e))
|
||||
return
|
||||
|
||||
dm = self.bot.data_manager
|
||||
|
||||
# Atomically claim this report
|
||||
claimed = dm.update(
|
||||
'reports',
|
||||
lambda r: r.get('report_id') == msg.id and r.get('status') == 'pending',
|
||||
lambda r: (r.update({'status': 'deciding'}), r)[1]
|
||||
)
|
||||
if not claimed:
|
||||
return
|
||||
|
||||
report = next((r for r in dm.get('reports') if r.get('report_id') == msg.id), None)
|
||||
if not report:
|
||||
return
|
||||
|
||||
approved = (str(payload.emoji) == CHECK)
|
||||
guild = channel.guild
|
||||
stamp = _now_utc_str()
|
||||
|
||||
header_emoji = CHECK if approved else CROSS
|
||||
new_content = (
|
||||
f"{header_emoji} **Pirate Report**\n"
|
||||
f"**Character:** {report['character_name']}\n"
|
||||
f"**Account:** {report['account_name']}\n"
|
||||
f"**Submitted by:** <@{report['submitter_id']}>\n\n"
|
||||
f"**Status:** {'Approved' if approved else 'Rejected'} by <@{payload.user_id}> on {stamp}"
|
||||
)
|
||||
try:
|
||||
await msg.clear_reactions()
|
||||
except Exception as e:
|
||||
print("[pirate_report] clear reactions failed:", repr(e))
|
||||
try:
|
||||
await msg.edit(content=new_content)
|
||||
except Exception as e:
|
||||
print("[pirate_report] edit mod msg failed:", repr(e))
|
||||
|
||||
if approved:
|
||||
acct_lower = report['account_name'].lower()
|
||||
if not any(p['account_name'].lower() == acct_lower for p in dm.get('pirates')):
|
||||
dm.add('pirates', {
|
||||
'character_name': report['character_name'],
|
||||
'account_name': report['account_name'],
|
||||
'submitter': str(report['submitter_id']),
|
||||
'threat_level': 0,
|
||||
'encounter_count': 0,
|
||||
'added_ts': time.time()
|
||||
})
|
||||
await self._refresh_pirates_list(guild)
|
||||
|
||||
await self._modlog(guild, f"{'✅ Approved' if approved else '❌ Rejected'} report for {report['character_name']} ({report['account_name']}) by <@{payload.user_id}>.")
|
||||
|
||||
try:
|
||||
if report.get('origin_channel_id') and report.get('ack_message_id'):
|
||||
ch = guild.get_channel(report['origin_channel_id'])
|
||||
if ch:
|
||||
ack_msg = await ch.fetch_message(report['ack_message_id'])
|
||||
await ack_msg.edit(content=f"{('✅ Approved' if approved else '❌ Rejected')} pirate report of {report['character_name']} ({report['account_name']}) by <@{payload.user_id}> on {stamp}.")
|
||||
except Exception as e:
|
||||
print("[pirate_report] edit ack msg failed:", repr(e))
|
||||
|
||||
dm.remove('reports', lambda r: r.get('report_id') == msg.id)
|
||||
|
||||
async def setup(bot):
|
||||
cog = PirateReportCog(bot)
|
||||
await bot.add_cog(cog)
|
||||
|
||||
try:
|
||||
home_gid = int(bot.config['DEFAULT'].get('home_guild_id', '0'))
|
||||
except Exception:
|
||||
home_gid = 0
|
||||
|
||||
if home_gid:
|
||||
guild_obj = discord.Object(id=home_gid)
|
||||
bot.tree.add_command(cog.report, guild=guild_obj)
|
||||
bot.tree.add_command(cog.edit_pirate, guild=guild_obj)
|
||||
bot.tree.add_command(cog.encounter, guild=guild_obj)
|
||||
else:
|
||||
bot.tree.add_command(cog.report)
|
||||
bot.tree.add_command(cog.edit_pirate)
|
||||
bot.tree.add_command(cog.encounter)
|
Loading…
Reference in New Issue
Block a user