0.3.9.3.a4

Added mod-tools to recreate nickname reviews
This commit is contained in:
Franz Rolfsvaag 2025-08-11 00:18:10 +02:00
parent f14e84b89c
commit 7b5bcff6ac
2 changed files with 94 additions and 2 deletions

2
bot.py
View File

@ -9,7 +9,7 @@ from modules.common.boot_notice import post_boot_notice
# Version consists of: # Version consists of:
# Major.Enhancement.Minor.Patch.Test (Test is alphanumeric; doesnt trigger auto update) # Major.Enhancement.Minor.Patch.Test (Test is alphanumeric; doesnt trigger auto update)
VERSION = "0.3.9.3.a3" VERSION = "0.3.9.3.a4"
# ---------- Env loading ---------- # ---------- Env loading ----------

View File

@ -394,7 +394,7 @@ class NickNudgeCog(commands.Cog):
except Exception: except Exception:
pass pass
# ---------- Mod command to clear pending reviews from datafile ---------- # ---------- Mod commands to manipulate nickname reviews ----------
@app_commands.command(name="clear_nick_reviews", description="Delete all PENDING nickname review records for this server.") @app_commands.command(name="clear_nick_reviews", description="Delete all PENDING nickname review records for this server.")
async def clear_nick_reviews(self, interaction: discord.Interaction): async def clear_nick_reviews(self, interaction: discord.Interaction):
@ -437,5 +437,97 @@ class NickNudgeCog(commands.Cog):
ephemeral=True ephemeral=True
) )
@app_commands.command(name="recreate_nick_reviews", description="Scan and recreate any missing pending nickname reviews for this server.")
async def recreate_nick_reviews(self, interaction: discord.Interaction):
"""Moderator-only bulk fixer for 'grey checkmark' users (claimed but no pending review)."""
if not interaction.guild:
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
if not await require_mod_interaction(interaction):
return # already replied
dm = self.bot.data_manager
guild = interaction.guild
agreed = set(dm.get('agreed_nickname'))
verified = set(dm.get('nick_verified'))
# Build a quick lookup of existing pending reviews
pending_reviews = {
(r.get('guild_id'), r.get('user_id'))
for r in dm.get('nick_reviews')
if r.get('status') == 'pending'
}
to_fix = []
for uid in agreed:
# Needs a review if not verified and no pending review exists
if (guild.id, uid) not in pending_reviews and uid not in verified:
m = guild.get_member(uid)
if m and not m.bot:
to_fix.append(m)
fixed = 0
skipped = 0
for member in to_fix:
try:
# Clear stale pending so the atomic method will transition and open a new one
dm.remove('nick_claim_pending', lambda x, _uid=member.id: x == _uid)
await self.ensure_pending_and_maybe_open(guild, member, source="recreate")
fixed += 1
except Exception:
skipped += 1
try:
await self._modlog(guild, f"🛠️ {interaction.user.mention} recreated **{fixed}** nickname review(s); skipped **{skipped}**.")
except Exception:
pass
await interaction.response.send_message(
f"Recreated **{fixed}** review(s); skipped **{skipped}**.",
ephemeral=True
)
@app_commands.command(name="recreate", description="Recreate a missing pending nickname review for one user.")
@app_commands.describe(user="Member to recreate review for")
async def recreate_nick_review(self, interaction: discord.Interaction, user: discord.Member):
"""Moderator-only single-user fixer."""
if not interaction.guild:
return await interaction.response.send_message("Use this in a server.", ephemeral=True)
if not await require_mod_interaction(interaction):
return # already replied
guild = interaction.guild
dm = self.bot.data_manager
# If already verified, nothing to do
if user.id in dm.get('nick_verified'):
return await interaction.response.send_message("User is already verified — no review needed.", ephemeral=True)
# If a pending review already exists, nothing to do
has_pending = any(
r.get('guild_id') == guild.id and r.get('user_id') == user.id and r.get('status') == 'pending'
for r in dm.get('nick_reviews')
)
if has_pending:
return await interaction.response.send_message("A pending review already exists for this user.", ephemeral=True)
# If they never agreed/claimed, mark claim now so the state is consistent
if user.id not in dm.get('agreed_nickname'):
dm.add('agreed_nickname', int(user.id))
# Clear stale pending flag, then open atomically
dm.remove('nick_claim_pending', lambda x: x == user.id)
try:
await self.ensure_pending_and_maybe_open(guild, user, source="recreate")
except Exception:
return await interaction.response.send_message("Failed to create the review (see logs).", ephemeral=True)
try:
await self._modlog(guild, f"🛠️ {interaction.user.mention} recreated a nickname review for {user.mention}.")
except Exception:
pass
await interaction.response.send_message("Recreated the nickname review for that user.", ephemeral=True)
async def setup(bot): async def setup(bot):
await bot.add_cog(NickNudgeCog(bot)) await bot.add_cog(NickNudgeCog(bot))