diff --git a/=5.0 b/=5.0 deleted file mode 100644 index e69de29..0000000 diff --git a/commands/emote_credits.py b/commands/emote_credits.py index 665cfb1..6669298 100644 --- a/commands/emote_credits.py +++ b/commands/emote_credits.py @@ -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): diff --git a/events/ping_protect.py b/events/ping_protect.py index a7be1cb..4d0cdae 100644 --- a/events/ping_protect.py +++ b/events/ping_protect.py @@ -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") diff --git a/utils/constants.py b/utils/constants.py index a59765c..573b512 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -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