diff --git a/payphone/cogs/calls/cog.py b/payphone/cogs/calls/cog.py index de345fc..3bec21b 100644 --- a/payphone/cogs/calls/cog.py +++ b/payphone/cogs/calls/cog.py @@ -636,6 +636,30 @@ class Calls(base.Cog): }, ) + @commands.command( + extras={ + "show_in_help": False, + "help_name": "Cat Mask", + "help_error_message": "No.", + } + ) + async def catmask(self, ctx: commands.Context) -> None: + """First easter egg. How'd you find it?""" + + await ctx.message.delete() + + call = await self.bot.call_handler.get_call_by_channel_id(ctx.channel.id) + + if not call: + return + + participant = await call.get_participant(ctx.author.id) + + if not participant: + return + + await participant.set_mask(masks.get_random_mask(call.masks, masks.CAT_MASKS)) + def setup(bot: Payphone) -> None: """Loads the Calls cog into the bot. diff --git a/payphone/core/calls.py b/payphone/core/calls.py index 31b472d..ea5b462 100644 --- a/payphone/core/calls.py +++ b/payphone/core/calls.py @@ -2,8 +2,6 @@ from dataclasses import dataclass import orjson -import discord - from payphone.db import models from payphone.bot import Payphone from payphone.core import masks @@ -21,6 +19,7 @@ class Participant: mask: str is_masked: bool channel_id: int + call_id: int user: models.User | None = None @property @@ -47,6 +46,36 @@ class Participant: else masks.get_mask_image_url(self.mask) ) + async def set_mask(self, mask: str) -> None: + """Sets the mask of the participant. + + Args: + mask (str): The mask to set. + """ + + if mask == self.mask: + return + + pipe = self._bot.redis.pipeline() + pipe.srem(f"calls:{self.call_id}:masks", self.mask) + pipe.sadd(f"calls:{self.call_id}:masks", mask) + await pipe.execute() + + self.mask = mask + self.is_masked = True + + data = orjson.dumps( + { + "name": self.name, + "avatar_url": self.avatar_url, + "mask": mask, + "is_masked": True, + "channel_id": self.channel_id, + } + ) + + await self._bot.redis.hset(f"calls:{self.call_id}:participants", self.id, data) + @dataclass class Message: @@ -220,6 +249,7 @@ class Call: is_masked=user.is_masked, channel_id=channel_id, user=user, + call_id=self.id, ), (user.is_masked != participant.is_masked if participant else True) async def get_participant(self, user_id: int) -> Participant | None: @@ -247,6 +277,7 @@ class Call: mask=data["mask"], is_masked=data["is_masked"], channel_id=data["channel_id"], + call_id=self.id, ) async def get_participants(self) -> list["Participant"]: @@ -272,6 +303,7 @@ class Call: mask=data["mask"], is_masked=data["is_masked"], channel_id=data["channel_id"], + call_id=self.id ) ) diff --git a/payphone/core/help_command.py b/payphone/core/help_command.py index d1c19cc..eb9d510 100644 --- a/payphone/core/help_command.py +++ b/payphone/core/help_command.py @@ -48,7 +48,8 @@ class HelpCommand(commands.HelpCommand): for command in cog_commands: if isinstance(command, commands.Command): - bot_commands += [command] + if command.extras.get("show_in_help", True): + bot_commands += [command] embed = discord.Embed( author=self.context.bot.embed_author, @@ -75,6 +76,11 @@ class HelpCommand(commands.HelpCommand): await self.context.send(embed=embed, view=HelpView()) async def send_command_help(self, command: commands.Command) -> None: + error_message = command.extras.get("help_error_message") + + if error_message: + return await self.context.send(f"❌ {error_message}") + command_name = ( command.name if isinstance(command, discord.SlashCommand) @@ -84,11 +90,7 @@ class HelpCommand(commands.HelpCommand): [f" <{option.name}>" for option in command.options] if isinstance(command, discord.SlashCommand) else [ - ( - f" [{name}]" - if utils.is_optional(info.annotation) - else f" <{name}>" - ) + (f" [{name}]" if utils.is_optional(info.annotation) else f" <{name}>") for name, info in command.params.items() if name not in ["self", "ctx"] ] diff --git a/payphone/core/masks.py b/payphone/core/masks.py index f58b600..76f75fa 100644 --- a/payphone/core/masks.py +++ b/payphone/core/masks.py @@ -56,18 +56,27 @@ MASKS = { "parrot": 1278175706798489642 if constants.IS_DEBUG else 1278172600702337074, } +CAT_MASKS = { + "dinosaur": 1278255435652010014 if constants.IS_DEBUG else 1278254725833297965, + "shleepy cat": 1278255475066146816 if constants.IS_DEBUG else 1278254779767984181, + "cozy cat": 1278255420124696663 if constants.IS_DEBUG else 1278254704324771893, + "coquette cat": 1278255408254816300 if constants.IS_DEBUG else 1278254684200636428, + "panic cat": 1278255451993145345 if constants.IS_DEBUG else 1278254760700674098, +} -def get_random_mask(not_int: list[str] = []) -> str: + +def get_random_mask(not_int: list[str] = [], masks: dict[str, int] = MASKS) -> str: """Returns a random mask. Args: not_int (list[str], optional): Masks to exclude. Defaults to []. + masks (dict[str, int], optional): The masks. Defaults to MASKS. Returns: str: The mask. """ - return random.choice([mask for mask in MASKS if mask not in not_int]) + return random.choice([mask for mask in masks.keys() if mask not in not_int]) def get_mask_name(mask: str) -> str: @@ -93,7 +102,7 @@ def get_mask_image_url(mask: str) -> str: str: The URL of the mask image. """ - return f"https://cdn.discordapp.com/emojis/{MASKS[mask]}.png" + return f"https://cdn.discordapp.com/emojis/{MASKS[mask] if mask in MASKS else CAT_MASKS[mask]}.png" def get_mask_emoji(mask: str) -> str: @@ -106,4 +115,4 @@ def get_mask_emoji(mask: str) -> str: str: The emoji of the mask. """ - return f"<:{mask.replace(" ", "")}:{MASKS[mask]}>" + return f"<:{mask.replace(" ", "")}:{MASKS[mask] if mask in MASKS else CAT_MASKS[mask]}>" diff --git a/uv.lock b/uv.lock index c5a18a7..79d2993 100644 --- a/uv.lock +++ b/uv.lock @@ -414,7 +414,7 @@ wheels = [ [[package]] name = "payphone" -version = "0.75.0" +version = "0.76.0" source = { virtual = "." } dependencies = [ { name = "aerich" },