emote credits: add /emote_credits_resolve admin command

ping protect: use pronoun roles in disabled-ping replies
chore: remove stray =5.0 file, clean up constants

emote credits:
- Add /emote_credits_resolve — scans credits where artist starts with
  "@", fuzzes against guild members (username, global_name,
  display_name), rewrites matches as <@id> mentions; reports resolved
  vs not-found in chunked ephemeral output

ping protect:
- Add _get_subject_pronoun() — reads pronoun roles (he/him, she/her,
  it/its) to return the correct subject pronoun
- Add _get_verb() — returns "has" or "have" to match
- Reply now reads e.g. "She has pings disabled" instead of always
  "they have pings disabled"

chore:
- Delete =5.0 (stray file from unquoted pip install shell redirect)
- Remove unused ARG channel ID constants from utils/constants.py
This commit is contained in:
Lilac-Rose
2026-03-11 17:01:56 +01:00
parent 1fffb78ed8
commit cdaf9430ef
4 changed files with 84 additions and 8 deletions

0
=5.0
View File

View File

@@ -406,6 +406,69 @@ class EmoteCredits(ModerationBase, commands.Cog):
summary += f"Total missing: {len(missing_emojis) + len(missing_stickers)}"
await interaction.followup.send(summary)
@app_commands.command(name="emote_credits_resolve", description="[Admin] Auto-convert @username credits to user mentions where possible")
@ModerationBase.is_admin()
async def emote_credits_resolve(self, interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
guild = interaction.guild
if not guild:
await interaction.followup.send("Server only.", ephemeral=True)
return
# Fetch all members so we can search by username/display name
await guild.chunk()
async with aiosqlite.connect(self.db_path) as conn:
async with conn.execute(
"SELECT emote_name, artist FROM emote_credits WHERE artist LIKE '@%'"
) as cursor:
rows = await cursor.fetchall()
if not rows:
await interaction.followup.send("No raw @username credits found.", ephemeral=True)
return
resolved = []
skipped = []
async with aiosqlite.connect(self.db_path) as conn:
for emote_name, artist in rows:
# Strip leading @ and any trailing whitespace
raw_name = artist.lstrip("@").strip()
# Try to match against username, global_name, or display_name (case-insensitive)
match = discord.utils.find(
lambda m, n=raw_name: (
m.name.lower() == n.lower()
or (m.global_name and m.global_name.lower() == n.lower())
or m.display_name.lower() == n.lower()
),
guild.members
)
if match:
new_artist = f"<@{match.id}>"
await conn.execute(
"UPDATE emote_credits SET artist = ? WHERE LOWER(emote_name) = LOWER(?)",
(new_artist, emote_name)
)
resolved.append(f"`{emote_name}`: {artist}{new_artist}")
else:
skipped.append(f"`{emote_name}`: {artist}")
await conn.commit()
lines = []
if resolved:
lines.append(f"**Resolved ({len(resolved)}):**\n" + "\n".join(resolved))
if skipped:
lines.append(f"**Not found ({len(skipped)}):**\n" + "\n".join(skipped))
# Split into chunks if needed to stay under Discord's message limit
output = "\n\n".join(lines)
for chunk in [output[i:i+1900] for i in range(0, len(output), 1900)]:
await interaction.followup.send(chunk, ephemeral=True)
@commands.command(name="missing_credits")
@ModerationBase.is_admin()
async def missing_credits_text(self, ctx):

View File

@@ -66,6 +66,21 @@ class PingProtect(commands.GroupCog, name="noping"):
)
return await cursor.fetchone() is not None
def _get_subject_pronoun(self, member: discord.Member | None) -> str:
if not member:
return "They"
role_names = {r.name.lower() for r in member.roles}
if "he/him" in role_names:
return "He"
if "she/her" in role_names:
return "She"
if "it/its" in role_names:
return "It"
return "They"
def _get_verb(self, pronoun: str) -> str:
return "have" if pronoun == "They" else "has"
@commands.Cog.listener()
async def on_message(self, message: discord.Message):
if message.author.bot or not message.guild:
@@ -96,8 +111,12 @@ class PingProtect(commands.GroupCog, name="noping"):
await db.commit()
await message.reply("Please don't ping faer", mention_author=False)
else:
name = member.display_name if member else user.name
await message.reply(f"Please don't ping {name}, they have pings disabled.", mention_author=False)
pronoun = self._get_subject_pronoun(member)
verb = self._get_verb(pronoun)
await message.reply(
f"Please don't ping {user.name}. {pronoun} {verb} pings disabled.",
mention_author=False
)
@app_commands.command(name="allow", description="Allow someone to ping you")
@app_commands.describe(user="The user to allow")

View File

@@ -20,12 +20,6 @@ BOT_TRAP_ROLE_ID = 1439354601672282335
SERVER_ADMIN_ROLE_ID = 952560403970416722
BOT_DEV_ROLE_ID = 1470439484549234866
# --- ARG ---
ARG_ANNOUNCEMENT_CHANNEL_ID = 876772600704020533 # #chat — initial anomaly post
ARG_LORE_CHANNEL_ID = 1229700500010569750 # #lore-and-theories — hints + 0187: reveal
ARG_ARCHIVE_CHANNEL_ID = 1478997241565020280 # #the-archive — visitor arrival announcements
ARG_ARCHIVIST_ROLE_NAME = "Archivist"
# --- Emojis ---
SALT_EMOJI_ID = 1074583707459010560