Implemented "/user update_channels" (#10)

This commit is contained in:
2025-05-02 14:07:00 +02:00
parent 5507295b1b
commit 3dcae36dec
6 changed files with 110 additions and 36 deletions

View File

@@ -24,6 +24,7 @@ from modules.utils import (
) )
# noinspection Mypy
class CogEvent(Cog): class CogEvent(Cog):
"""Cog with event management commands.""" """Cog with event management commands."""
@@ -94,11 +95,8 @@ class CogEvent(Cog):
guild_timezone: ZoneInfo = ZoneInfo(guild.timezone) guild_timezone: ZoneInfo = ZoneInfo(guild.timezone)
try: try:
start_date: datetime = datetime.strptime(start, "%d.%m.%Y %H:%M") start_date: datetime = datetime.strptime(start, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
end_date: datetime = datetime.strptime(end, "%d.%m.%Y %H:%M") end_date: datetime = datetime.strptime(end, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
start_date = start_date.replace(tzinfo=guild_timezone)
end_date = end_date.replace(tzinfo=guild_timezone)
except ValueError: except ValueError:
# TODO Introduce i18n # TODO Introduce i18n
await ctx.respond( await ctx.respond(
@@ -202,13 +200,9 @@ class CogEvent(Cog):
try: try:
start_date: datetime = ( start_date: datetime = (
pycord_event.starts if start is None else datetime.strptime(start, "%d.%m.%Y %H:%M") pycord_event.starts.replace(tzinfo=ZoneInfo("UTC"))
)
start_date = (
start_date.replace(tzinfo=ZoneInfo("UTC"))
if start is None if start is None
else start_date.replace(tzinfo=guild_timezone) else datetime.strptime(start, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
) )
except ValueError: except ValueError:
# TODO Make a nice message # TODO Make a nice message
@@ -219,13 +213,9 @@ class CogEvent(Cog):
try: try:
end_date: datetime = ( end_date: datetime = (
pycord_event.ends if end is None else datetime.strptime(end, "%d.%m.%Y %H:%M") pycord_event.ends.replace(tzinfo=ZoneInfo("UTC"))
)
end_date = (
end_date.replace(tzinfo=ZoneInfo("UTC"))
if end is None if end is None
else end_date.replace(tzinfo=guild_timezone) else datetime.strptime(end, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
) )
except ValueError: except ValueError:
# TODO Make a nice message # TODO Make a nice message
@@ -234,7 +224,14 @@ class CogEvent(Cog):
) )
return return
if not await validate_event_validity(ctx, name, start_date, end_date, to_utc=True): if not await validate_event_validity(
ctx,
pycord_event.name if name is None else name,
start_date,
end_date,
event_id=pycord_event._id,
to_utc=True,
):
return return
processed_media: List[Dict[str, Any]] = ( processed_media: List[Dict[str, Any]] = (

View File

@@ -115,7 +115,7 @@ class CogRegister(Cog):
) )
await user_channel.send( await user_channel.send(
self.bot._("register_already_started", "messages", locale=ctx.locale).format( self.bot._("notice_event_already_started", "messages", locale=ctx.locale).format(
event_name=pycord_event.name event_name=pycord_event.name
), ),
file=thumbnail, file=thumbnail,

View File

@@ -1,14 +1,25 @@
from datetime import datetime
from pathlib import Path
from typing import List, Dict, Any
from zoneinfo import ZoneInfo
from bson import ObjectId
from bson.errors import InvalidId
from discord import ( from discord import (
ApplicationContext, ApplicationContext,
SlashCommandGroup, SlashCommandGroup,
User, User,
option, option,
File,
TextChannel,
) )
from discord.ext.commands import Cog from discord.ext.commands import Cog
from libbot.i18n import _, in_every_locale from libbot.i18n import _, in_every_locale
from classes import PycordUser from classes import PycordUser, PycordEvent, PycordGuild
from classes.errors import GuildNotFoundError
from classes.pycord_bot import PycordBot from classes.pycord_bot import PycordBot
from modules.database import col_users
from modules.utils import is_operation_confirmed from modules.utils import is_operation_confirmed
@@ -37,16 +48,82 @@ class CogUser(Cog):
# await ctx.respond("Not implemented.") # await ctx.respond("Not implemented.")
# TODO Implement the command # TODO Implement the command
# @command_group.command( @command_group.command(
# name="update_channel", name="update_channels",
# description="Update user's channel", description="Update user's event channels",
# ) )
# @option( @option(
# "user", "user",
# description="Selected user", description="Selected user",
# ) )
# async def command_user_update_channel(self, ctx: ApplicationContext, user: User) -> None: async def command_user_update_channels(self, ctx: ApplicationContext, user: User) -> None:
# await ctx.respond("Not implemented.") 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
pycord_user: PycordUser = await self.bot.find_user(user.id, ctx.guild.id)
events: List[PycordEvent] = []
pipeline: List[Dict[str, Any]] = [
{"$match": {"id": pycord_user.id}},
{
"$lookup": {
"from": "events",
"localField": "registered_event_ids",
"foreignField": "_id",
"as": "registered_events",
}
},
{
"$match": {
"registered_events.ended": None,
"registered_events.ends": {"$gt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.starts": {"$lt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.is_cancelled": False,
}
},
]
async for result in col_users.aggregate(pipeline):
for registered_event in result["registered_events"]:
events.append(PycordEvent(**registered_event))
for event in events:
if pycord_user.current_event_id is not None and pycord_user.current_event_id != event._id:
continue
if pycord_user.current_event_id is None:
await pycord_user.set_event(event._id, cache=self.bot.cache)
channel: TextChannel | None = await pycord_user.fix_event_channel(
self.bot, ctx.guild, guild, event, cache=self.bot.cache
)
if channel is None:
continue
thumbnail: File | None = (
None
if event.thumbnail is None
else File(Path(f"data/{event.thumbnail['id']}"), event.thumbnail["filename"])
)
await channel.send(
self.bot._("notice_event_already_started", "messages").format(event_name=event.name),
file=thumbnail,
)
stage_id: ObjectId = (
event.stage_ids[0] if pycord_user.current_stage_id is None else pycord_user.current_stage_id
)
await pycord_user.set_event_stage(stage_id, cache=self.bot.cache)
await self.bot.send_stage_question(channel, event, await self.bot.find_event_stage(stage_id))
await ctx.respond("Channels were updated.")
# TODO Implement the command # TODO Implement the command
# @command_group.command( # @command_group.command(

View File

@@ -123,7 +123,7 @@ class CogUtility(Cog):
) )
await channel.send( await channel.send(
self.bot._("register_already_started", "messages").format(event_name=event.name), self.bot._("notice_event_already_started", "messages").format(event_name=event.name),
file=thumbnail, file=thumbnail,
) )

View File

@@ -14,9 +14,9 @@
"guild_unconfigured": "Guild is not configured. Please, report this to the administrator.", "guild_unconfigured": "Guild is not configured. Please, report this to the administrator.",
"guild_unconfigured_admin": "Guild is not configured. Please, configure it using `/config set`.", "guild_unconfigured_admin": "Guild is not configured. Please, configure it using `/config set`.",
"jailed_error": "You are jailed and cannot interact with events. Please, contact the administrator.", "jailed_error": "You are jailed and cannot interact with events. Please, contact the administrator.",
"notice_event_already_started": "Event **{event_name}** has already started!\n\nUse slash command `/guess` to suggest your answers to each event stage.",
"operation_unconfirmed": "Operation not confirmed.", "operation_unconfirmed": "Operation not confirmed.",
"register_already_registered": "You are already registered for this event.", "register_already_registered": "You are already registered for this event.",
"register_already_started": "Event **{event_name}** has already started!\n\nUse slash command `/guess` to suggest your answers to each event stage.",
"register_success_ongoing": "You are now registered for the event **{event_name}**.\n\nNew channel has been created for you and further instructions will are provided in it. Good luck!", "register_success_ongoing": "You are now registered for the event **{event_name}**.\n\nNew channel has been created for you and further instructions will are provided in it. Good luck!",
"register_success_scheduled": "You are now registered for the event **{event_name}**.\n\nNew channel will be created for you and further instructions will be provided as soon as the event starts <t:{event_starts}:R>. Good luck!", "register_success_scheduled": "You are now registered for the event **{event_name}**.\n\nNew channel will be created for you and further instructions will be provided as soon as the event starts <t:{event_starts}:R>. Good luck!",
"status": "**QuizBot** v{version}\n\nUptime: since <t:{start_time}>", "status": "**QuizBot** v{version}\n\nUptime: since <t:{start_time}>",

View File

@@ -1,5 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Any, Dict from typing import Any, Dict, Optional
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from bson import ObjectId from bson import ObjectId
@@ -13,9 +13,9 @@ from modules.database import col_events
async def validate_event_validity( async def validate_event_validity(
ctx: ApplicationContext, ctx: ApplicationContext,
name: str, name: str,
start_date: datetime | None, start_date: datetime,
end_date: datetime | None, end_date: datetime,
event_id: ObjectId | None = None, event_id: Optional[ObjectId] = None,
to_utc: bool = False, to_utc: bool = False,
) -> bool: ) -> bool:
start_date_internal: datetime = start_date.astimezone(ZoneInfo("UTC")) if to_utc else start_date start_date_internal: datetime = start_date.astimezone(ZoneInfo("UTC")) if to_utc else start_date