from datetime import datetime from logging import Logger from pathlib import Path from typing import List from zoneinfo import ZoneInfo from bson.errors import InvalidId from discord import ApplicationContext, Cog, File, TextChannel, option, slash_command from discord.utils import basic_autocomplete from libbot.i18n import _, in_every_locale from classes import PycordEvent, PycordEventStage, PycordGuild, PycordUser from classes.pycord_bot import PycordBot from modules.utils import autocomplete_active_events, get_logger, get_unix_timestamp logger: Logger = get_logger(__name__) class CogRegister(Cog): """Cog with the event registration command.""" def __init__(self, bot: PycordBot): self.bot: PycordBot = bot # TODO Introduce i18n @slash_command( name="register", description=_("description", "commands", "register"), description_localizations=in_every_locale("description", "commands", "register"), ) @option( "event", description=_("description", "commands", "register", "options", "event"), description_localizations=in_every_locale( "description", "commands", "register", "options", "event" ), autocomplete=basic_autocomplete(autocomplete_active_events), ) async def command_register(self, ctx: ApplicationContext, event: str) -> None: guild: PycordGuild = await self.bot.find_guild(ctx.guild.id) try: pycord_event: PycordEvent = await self.bot.find_event(event_id=event) except (InvalidId, RuntimeError): # TODO Make a nice message await ctx.respond("Event was not found.") return 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 pycord_event._id in user.registered_event_ids: # TODO Make a nice message await ctx.respond("You are already registered for this event.") return await user.event_register(pycord_event._id, cache=self.bot.cache) # TODO Make a nice message await ctx.respond( f"You are now registered for the event **{pycord_event.name}**.\n\nNew channel will be created for you and further instructions will be provided as soon as the event starts . Good luck!" ) if pycord_event.starts.replace(tzinfo=ZoneInfo("UTC")) < datetime.now(tz=ZoneInfo("UTC")): await user.set_event(pycord_event._id, cache=self.bot.cache) user_channel: TextChannel = await user.setup_event_channel( self.bot, ctx.guild, guild, pycord_event, cache=self.bot.cache ) if user_channel is None: logger.error( "Event channel was not created for user %s from guild %s and event %s after registration.", ctx.author.id, guild.id, pycord_event._id, ) await self.bot.notify_admins( ctx.guild, guild, f"Event channel could not be created for user **{ctx.author.display_name}** ({ctx.author.mention}) and event **{pycord_event.name}**.", ) return thumbnail: File | None = ( None if pycord_event.thumbnail is None else File(Path(f"data/{pycord_event.thumbnail['id']}"), pycord_event.thumbnail["filename"]) ) # TODO Make a nice message await user_channel.send( f"Event **{pycord_event.name}** has already started!\n\nUse slash command `/guess` to suggest your answers to each event stage.", file=thumbnail, ) first_stage: PycordEventStage = await self.bot.find_event_stage(pycord_event.stage_ids[0]) await user.set_event_stage(first_stage._id, cache=self.bot.cache) first_stage_files: List[File] | None = first_stage.get_media_files() question_chunks: List[str] = first_stage.get_question_chunked(2000) question_chunks_length: int = len(question_chunks) for index, chunk in enumerate(question_chunks): await user_channel.send( chunk, files=None if index != question_chunks_length - 1 else first_stage_files ) def setup(bot: PycordBot) -> None: bot.add_cog(CogRegister(bot))