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.errors import EventNotFoundError, GuildNotFoundError 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 @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: 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)) return try: pycord_event: PycordEvent = await self.bot.find_event(event_id=event) except (InvalidId, EventNotFoundError): await ctx.respond(self.bot._("event_not_found", "messages", locale=ctx.locale)) 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: await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale)) return if pycord_event._id in user.registered_event_ids: await ctx.respond(self.bot._("register_already_registered", "messages", locale=ctx.locale)) return await user.event_register(pycord_event._id, cache=self.bot.cache) event_ongoing: bool = pycord_event.starts.replace(tzinfo=ZoneInfo("UTC")) < datetime.now( tz=ZoneInfo("UTC") ) registered_message: str = ( self.bot._("register_success_ongoing", "messages", locale=ctx.locale).format( event_name=pycord_event.name ) if event_ongoing else self.bot._("register_success_scheduled", "messages", locale=ctx.locale).format( event_name=pycord_event.name, event_starts=get_unix_timestamp(pycord_event.starts, to_utc=True), ) ) await ctx.respond(registered_message) if event_ongoing: 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, self.bot._("admin_user_channel_creation_failed", "messages", locale=ctx.locale).format( display_name=ctx.author.display_name, mention=ctx.author.mention, event_name=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"]) ) await user_channel.send( self.bot._("register_already_started", "messages", locale=ctx.locale).format( event_name=pycord_event.name ), 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))