from typing import List from bson import ObjectId from bson.errors import InvalidId from discord import ApplicationContext, Cog, File, option, slash_command from libbot.i18n import _, in_every_locale from classes import PycordEvent, PycordEventStage, PycordGuild, PycordUser from classes.errors import ( EventNotFoundError, EventStageNotFoundError, GuildNotFoundError, ) from classes.pycord_bot import PycordBot class CogGuess(Cog): """Cog with the guessing command.""" def __init__(self, bot: PycordBot): self.bot: PycordBot = bot @slash_command( name="guess", description=_("description", "commands", "guess"), description_localizations=in_every_locale("description", "commands", "guess"), ) @option( "answer", description=_("description", "commands", "guess", "options", "answer"), description_localizations=in_every_locale("description", "commands", "guess", "options", "answer"), ) async def command_guess(self, ctx: ApplicationContext, answer: str) -> None: try: guild: PycordGuild = await self.bot.find_guild(ctx.guild.id) except (InvalidId, GuildNotFoundError): await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True) return if not guild.is_configured(): await ctx.respond( self.bot._("guild_unconfigured", "messages", locale=ctx.locale), ephemeral=True ) return user: PycordUser = await self.bot.find_user(ctx.author, ctx.guild) if user.is_jailed: await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale)) return if user.current_event_id is None or user.current_stage_id is None: await ctx.respond(self.bot._("guess_unregistered", "messages", locale=ctx.locale)) return try: event: PycordEvent = await self.bot.find_event(event_id=user.current_event_id) stage: PycordEventStage = await self.bot.find_event_stage(user.current_stage_id) except (InvalidId, EventNotFoundError, EventStageNotFoundError): await ctx.respond(self.bot._("guess_incorrect_event", "messages", locale=ctx.locale)) return if ctx.channel_id != user.event_channels[str(event._id)]: await ctx.respond( self.bot._("guess_incorrect_channel", "messages", locale=ctx.locale), ephemeral=True ) return if answer.lower() != stage.answer.lower(): await ctx.respond( self.bot.config["emojis"]["guess_wrong"] if guild.prefer_emojis else self.bot._("guess_incorrect", "messages", locale=ctx.locale) ) return next_stage_index = stage.sequence + 1 next_stage_id: ObjectId | None = ( None if len(event.stage_ids) < next_stage_index + 1 else event.stage_ids[next_stage_index] ) if next_stage_id is None: user.completed_event_ids.append(event._id) await user._set( self.bot.cache, current_event_id=None, current_stage_id=None, completed_event_ids=user.completed_event_ids, ) await ctx.respond(self.bot._("guess_completed_event", "messages", locale=ctx.locale)) await self.bot.notify_admins( ctx.guild, guild, self.bot._("admin_user_completed_event", "messages", locale=ctx.locale).format( display_name=ctx.author.display_name, mention=ctx.author.mention, event_name=event.name ), ) return next_stage: PycordEventStage = await self.bot.find_event_stage(next_stage_id) files: List[File] | None = next_stage.get_media_files() next_question_chunks: List[str] = next_stage.get_question_chunked(2000) next_question_chunks_length: int = len(next_question_chunks) for index, chunk in enumerate(next_question_chunks): await ctx.respond(chunk, files=None if index != next_question_chunks_length - 1 else files) await user.set_event_stage(next_stage._id, cache=self.bot.cache) await self.bot.notify_admins( ctx.guild, guild, self.bot._("admin_user_completed_stage", "messages", locale=ctx.locale).format( display_name=ctx.author.display_name, mention=ctx.author.mention, stage_sequence=stage.sequence + 1, event_name=event.name, ), ) def setup(bot: PycordBot) -> None: bot.add_cog(CogGuess(bot))