from typing import List from bson import ObjectId from bson.errors import InvalidId from discord import ApplicationContext, Cog, File, option, slash_command from classes import PycordEvent, PycordEventStage, PycordGuild, PycordUser from classes.pycord_bot import PycordBot class CogGuess(Cog): """Cog with the guessing command.""" def __init__(self, bot: PycordBot): self.bot: PycordBot = bot # TODO Implement the command @slash_command( name="guess", description="Propose an answer to the current event stage", ) @option("answer", description="An answer to the current stage") async def command_guess(self, ctx: ApplicationContext, answer: str) -> None: guild: PycordGuild = await self.bot.find_guild(ctx.guild.id) if not guild.is_configured(): await ctx.respond(self.bot._("guild_unconfigured", "messages", locale=ctx.locale)) return user: PycordUser = await self.bot.find_user(ctx.author, ctx.guild) if user.is_jailed: # TODO Make a nice message await ctx.respond("You are jailed and cannot interact with events. Please, contact the administrator.") return if user.current_event_id is None or user.current_stage_id is None: # TODO Make a nice message await ctx.respond("You have no ongoing events.") 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, RuntimeError): # TODO Make a nice message await ctx.respond("Your event could not be found. Please, report this issue to the event's management.") return if ctx.channel_id != user.event_channels[str(event._id)]: # TODO Make a nice message await ctx.respond("Usage outside own event channel is not allowed.", ephemeral=True) return if answer.lower() != stage.answer.lower(): # TODO Make a nice message # await ctx.respond("Provided answer is wrong.") await ctx.respond(self.bot.config["emojis"]["guess_wrong"]) 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: # TODO Make a nice message 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("Congratulations! You have completed the event!") await self.bot.notify_admins( ctx.guild, guild, f"User **{ctx.author.display_name}** ({ctx.author.mention}) has completed the event", ) return next_stage: PycordEventStage = await self.bot.find_event_stage(next_stage_id) files: List[File] | None = next_stage.get_media_files() await ctx.respond( f"Provided answer is correct! Next stage...\n\n{next_stage.question}", files=files, ) await user.set_event_stage(next_stage._id, cache=self.bot.cache) await self.bot.notify_admins( ctx.guild, guild, f"User **{ctx.author.display_name}** ({ctx.author.mention}) has completed the stage {stage.sequence+1} of the event **{event.name}**.", ) def setup(bot: PycordBot) -> None: bot.add_cog(CogGuess(bot))