Improved some messages and prepared them for i18n
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
from datetime import datetime
|
||||
from logging import Logger
|
||||
from pathlib import Path
|
||||
from typing import Any, override, List, Dict
|
||||
from typing import Any, Dict, List, override
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from bson import ObjectId
|
||||
from discord import Guild, User, TextChannel, Attachment, File
|
||||
from discord import Attachment, File, Guild, TextChannel, User
|
||||
from libbot.cache.classes import CacheMemcached, CacheRedis
|
||||
from libbot.cache.manager import create_cache_client
|
||||
from libbot.pycord.classes import PycordBot as LibPycordBot
|
||||
|
||||
from classes import PycordEvent, PycordEventStage, PycordGuild, PycordUser
|
||||
from modules.database import col_users, col_events
|
||||
from modules.database import col_events, col_users
|
||||
from modules.utils import get_logger
|
||||
|
||||
logger: Logger = get_logger(__name__)
|
||||
@@ -53,9 +53,7 @@ class PycordBot(LibPycordBot):
|
||||
await super().close(**kwargs)
|
||||
|
||||
async def _schedule_tasks(self) -> None:
|
||||
self.scheduler.add_job(
|
||||
self._execute_event_controller, trigger="cron", minute="*/1", id="event_controller"
|
||||
)
|
||||
self.scheduler.add_job(self._execute_event_controller, trigger="cron", minute="*/1", id="event_controller")
|
||||
|
||||
async def _execute_event_controller(self) -> None:
|
||||
await self._process_events_start()
|
||||
@@ -105,9 +103,7 @@ class PycordBot(LibPycordBot):
|
||||
|
||||
first_stage_files: List[File] | None = first_stage.get_media_files()
|
||||
|
||||
await user_channel.send(
|
||||
f"First stage...\n\n{first_stage.question}", files=first_stage_files
|
||||
)
|
||||
await user_channel.send(f"First stage...\n\n{first_stage.question}", files=first_stage_files)
|
||||
|
||||
# TODO Make a nice message
|
||||
await self.notify_admins(
|
||||
@@ -126,7 +122,7 @@ class PycordBot(LibPycordBot):
|
||||
for event in events:
|
||||
guild: Guild = self.get_guild(event.guild_id)
|
||||
pycord_guild: PycordGuild = await self.find_guild(guild)
|
||||
stages: List[PycordEventStage] = await self._get_event_stages(event)
|
||||
stages: List[PycordEventStage] = await self.get_event_stages(event)
|
||||
|
||||
# TODO Make a nice message
|
||||
stages_string: str = "\n\n".join(
|
||||
@@ -174,7 +170,8 @@ class PycordBot(LibPycordBot):
|
||||
|
||||
return users
|
||||
|
||||
async def _get_event_stages(self, event: PycordEvent) -> List[PycordEventStage]:
|
||||
# TODO Add documentation
|
||||
async def get_event_stages(self, event: PycordEvent) -> List[PycordEventStage]:
|
||||
return [(await self.find_event_stage(stage_id)) for stage_id in event.stage_ids]
|
||||
|
||||
# TODO Add documentation
|
||||
@@ -254,9 +251,7 @@ class PycordBot(LibPycordBot):
|
||||
return event_stage
|
||||
|
||||
# TODO Document this method
|
||||
async def find_event(
|
||||
self, event_id: str | ObjectId | None = None, event_name: str | None = None
|
||||
) -> PycordEvent:
|
||||
async def find_event(self, event_id: str | ObjectId | None = None, event_name: str | None = None) -> PycordEvent:
|
||||
if event_id is None and event_name is None:
|
||||
raise AttributeError("Either event's ID or name must be provided!")
|
||||
|
||||
|
@@ -286,9 +286,7 @@ class PycordEvent:
|
||||
stage_index: int = self.stage_ids.index(event_stage_id)
|
||||
old_stage_index: int = old_stage_ids.index(event_stage_id)
|
||||
|
||||
logger.debug(
|
||||
"Indexes for %s: was %s and is now %s", event_stage_id, old_stage_index, stage_index
|
||||
)
|
||||
logger.debug("Indexes for %s: was %s and is now %s", event_stage_id, old_stage_index, stage_index)
|
||||
|
||||
if stage_index != old_stage_index:
|
||||
await (await bot.find_event_stage(event_stage_id)).update(cache, sequence=stage_index)
|
||||
|
@@ -4,7 +4,15 @@ from logging import Logger
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from bson import ObjectId
|
||||
from discord import Bot, Guild, Member, PermissionOverwrite, TextChannel, Forbidden, Role
|
||||
from discord import (
|
||||
Bot,
|
||||
Forbidden,
|
||||
Guild,
|
||||
Member,
|
||||
PermissionOverwrite,
|
||||
Role,
|
||||
TextChannel,
|
||||
)
|
||||
from discord.abc import GuildChannel
|
||||
from libbot.cache.classes import Cache
|
||||
from pymongo.results import InsertOneResult
|
||||
@@ -106,12 +114,8 @@ class PycordUser:
|
||||
"guild_id": self.guild_id,
|
||||
"event_channels": self.event_channels,
|
||||
"is_jailed": self.is_jailed,
|
||||
"current_event_id": (
|
||||
self.current_event_id if not json_compatible else str(self.current_event_id)
|
||||
),
|
||||
"current_stage_id": (
|
||||
self.current_stage_id if not json_compatible else str(self.current_stage_id)
|
||||
),
|
||||
"current_event_id": (self.current_event_id if not json_compatible else str(self.current_event_id)),
|
||||
"current_stage_id": (self.current_stage_id if not json_compatible else str(self.current_stage_id)),
|
||||
"registered_event_ids": (
|
||||
self.registered_event_ids
|
||||
if not json_compatible
|
||||
@@ -367,9 +371,7 @@ class PycordUser:
|
||||
|
||||
# TODO Add documentation
|
||||
async def set_event_stage(self, stage_id: str | ObjectId | None, cache: Optional[Cache] = None) -> None:
|
||||
await self._set(
|
||||
cache, current_stage_id=stage_id if isinstance(stage_id, str) else ObjectId(stage_id)
|
||||
)
|
||||
await self._set(cache, current_stage_id=stage_id if isinstance(stage_id, str) else ObjectId(stage_id))
|
||||
|
||||
async def jail(self, cache: Optional[Cache] = None) -> None:
|
||||
await self._set(cache, is_jailed=True)
|
||||
|
@@ -9,14 +9,14 @@ from discord import (
|
||||
)
|
||||
from discord.ext.commands import Cog
|
||||
from discord.utils import basic_autocomplete
|
||||
from libbot.i18n import in_every_locale, _
|
||||
from libbot.i18n import _, in_every_locale
|
||||
|
||||
from classes import PycordGuild
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import autocomplete_timezones
|
||||
from modules.utils import autocomplete_timezones, is_operation_confirmed
|
||||
|
||||
|
||||
class Config(Cog):
|
||||
class CogConfig(Cog):
|
||||
"""Cog with guild configuration commands."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -36,18 +36,14 @@ class Config(Cog):
|
||||
@option(
|
||||
"category",
|
||||
description=_("description", "commands", "config_set", "options", "category"),
|
||||
description_localizations=in_every_locale(
|
||||
"description", "commands", "config_set", "options", "category"
|
||||
),
|
||||
description_localizations=in_every_locale("description", "commands", "config_set", "options", "category"),
|
||||
required=True,
|
||||
)
|
||||
@option("channel", description="Text channel for admin notifications", required=True)
|
||||
@option(
|
||||
"timezone",
|
||||
description=_("description", "commands", "config_set", "options", "timezone"),
|
||||
description_localizations=in_every_locale(
|
||||
"description", "commands", "config_set", "options", "timezone"
|
||||
),
|
||||
description_localizations=in_every_locale("description", "commands", "config_set", "options", "timezone"),
|
||||
autocomplete=basic_autocomplete(autocomplete_timezones),
|
||||
required=True,
|
||||
)
|
||||
@@ -63,9 +59,7 @@ class Config(Cog):
|
||||
try:
|
||||
timezone_parsed: ZoneInfo = ZoneInfo(timezone)
|
||||
except ZoneInfoNotFoundError:
|
||||
await ctx.respond(
|
||||
self.bot._("timezone_invalid", "messages", locale=ctx.locale).format(timezone=timezone)
|
||||
)
|
||||
await ctx.respond(self.bot._("timezone_invalid", "messages", locale=ctx.locale).format(timezone=timezone))
|
||||
return
|
||||
|
||||
await guild.update(
|
||||
@@ -85,14 +79,11 @@ class Config(Cog):
|
||||
@option(
|
||||
"confirm",
|
||||
description=_("description", "commands", "config_reset", "options", "confirm"),
|
||||
description_localizations=in_every_locale(
|
||||
"description", "commands", "config_reset", "options", "confirm"
|
||||
),
|
||||
description_localizations=in_every_locale("description", "commands", "config_reset", "options", "confirm"),
|
||||
required=False,
|
||||
)
|
||||
async def command_config_reset(self, ctx: ApplicationContext, confirm: bool = False) -> None:
|
||||
if confirm is None or not confirm:
|
||||
await ctx.respond(self.bot._("operation_unconfirmed", "messages", locale=ctx.locale))
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
@@ -123,4 +114,4 @@ class Config(Cog):
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Config(bot))
|
||||
bot.add_cog(CogConfig(bot))
|
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any
|
||||
from typing import Any, Dict, List
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from bson.errors import InvalidId
|
||||
@@ -12,12 +12,17 @@ from discord import (
|
||||
from discord.ext.commands import Cog
|
||||
from discord.utils import basic_autocomplete
|
||||
|
||||
from classes import PycordEvent, PycordGuild
|
||||
from classes import PycordEvent, PycordEventStage, PycordGuild
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import autocomplete_active_events, validate_event_validity
|
||||
from modules.utils import (
|
||||
autocomplete_active_events,
|
||||
get_unix_timestamp,
|
||||
is_operation_confirmed,
|
||||
validate_event_validity,
|
||||
)
|
||||
|
||||
|
||||
class Event(Cog):
|
||||
class CogEvent(Cog):
|
||||
"""Cog with event management commands."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -46,8 +51,7 @@ class Event(Cog):
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
guild_timezone: ZoneInfo = ZoneInfo(guild.timezone)
|
||||
@@ -59,8 +63,10 @@ class Event(Cog):
|
||||
start_date = start_date.replace(tzinfo=guild_timezone)
|
||||
end_date = end_date.replace(tzinfo=guild_timezone)
|
||||
except ValueError:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Could not parse start and end dates.")
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(
|
||||
"Could not parse start and end dates. Please, make sure these are provided in `DD.MM.YYYY HH:MM` format."
|
||||
)
|
||||
return
|
||||
|
||||
await validate_event_validity(ctx, name, start_date, end_date, guild_timezone)
|
||||
@@ -78,8 +84,10 @@ class Event(Cog):
|
||||
thumbnail=processed_media[0] if thumbnail else None,
|
||||
)
|
||||
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Event has been created.")
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(
|
||||
f"Event **{event.name}** has been created and will take place <t:{get_unix_timestamp(event.starts)}:R>."
|
||||
)
|
||||
|
||||
# TODO Introduce i18n
|
||||
@command_group.command(
|
||||
@@ -115,8 +123,7 @@ class Event(Cog):
|
||||
return
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
guild_timezone: ZoneInfo = ZoneInfo(guild.timezone)
|
||||
@@ -132,9 +139,7 @@ class Event(Cog):
|
||||
return
|
||||
|
||||
try:
|
||||
end_date: datetime = (
|
||||
pycord_event.ends if end is None else datetime.strptime(end, "%d.%m.%Y %H:%M")
|
||||
)
|
||||
end_date: datetime = pycord_event.ends if end is None else datetime.strptime(end, "%d.%m.%Y %H:%M")
|
||||
end_date = end_date.replace(tzinfo=guild_timezone)
|
||||
except ValueError:
|
||||
# TODO Make a nice message
|
||||
@@ -155,8 +160,12 @@ class Event(Cog):
|
||||
thumbnail=pycord_event.thumbnail if thumbnail is None else processed_media[0],
|
||||
)
|
||||
|
||||
# TODO Notify participants about time changes
|
||||
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Event has been updated.")
|
||||
await ctx.respond(
|
||||
f"Event **{pycord_event.name}** has been updated and will take place <t:{get_unix_timestamp(pycord_event.starts)}:R>."
|
||||
)
|
||||
|
||||
# TODO Introduce i18n
|
||||
@command_group.command(
|
||||
@@ -176,9 +185,7 @@ class Event(Cog):
|
||||
event: str,
|
||||
confirm: bool = False,
|
||||
) -> None:
|
||||
if confirm is None or not confirm:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Operation not confirmed.")
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
@@ -191,8 +198,7 @@ class Event(Cog):
|
||||
return
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
start_date: datetime = pycord_event.starts.replace(tzinfo=ZoneInfo("UTC"))
|
||||
@@ -210,8 +216,10 @@ class Event(Cog):
|
||||
|
||||
await pycord_event.cancel()
|
||||
|
||||
# TODO Notify participants about cancellation
|
||||
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Event was cancelled.")
|
||||
await ctx.respond(f"Event **{pycord_event.name}** was cancelled.")
|
||||
|
||||
# TODO Introduce i18n
|
||||
@command_group.command(
|
||||
@@ -237,11 +245,21 @@ class Event(Cog):
|
||||
starts_date: datetime = pycord_event.starts.replace(tzinfo=ZoneInfo("UTC"))
|
||||
ends_date: datetime = pycord_event.ends.replace(tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
stages: List[PycordEventStage] = await self.bot.get_event_stages(pycord_event)
|
||||
|
||||
# TODO Make a nice message
|
||||
stages_string: str = "\n\n".join(
|
||||
f"**Stage {stage.sequence+1}**\nQuestion: {stage.question}\nAnswer: ||{stage.answer}||"
|
||||
for stage in stages
|
||||
)
|
||||
|
||||
# TODO Show users registered for the event
|
||||
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(
|
||||
f"**Event details**\n\nName: {pycord_event.name}\nStarts: <t:{int(starts_date.timestamp())}>\nEnds: <t:{int(ends_date.timestamp())}>"
|
||||
f"**Event details**\n\nName: {pycord_event.name}\nStarts: <t:{get_unix_timestamp(starts_date)}>\nEnds: <t:{get_unix_timestamp(ends_date)}>\n\nStages:\n{stages_string}"
|
||||
)
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Event(bot))
|
||||
bot.add_cog(CogEvent(bot))
|
@@ -2,13 +2,13 @@ from typing import List
|
||||
|
||||
from bson import ObjectId
|
||||
from bson.errors import InvalidId
|
||||
from discord import ApplicationContext, Cog, option, slash_command, File
|
||||
from discord import ApplicationContext, Cog, File, option, slash_command
|
||||
|
||||
from classes import PycordEvent, PycordUser, PycordGuild, PycordEventStage
|
||||
from classes import PycordEvent, PycordEventStage, PycordGuild, PycordUser
|
||||
from classes.pycord_bot import PycordBot
|
||||
|
||||
|
||||
class Guess(Cog):
|
||||
class CogGuess(Cog):
|
||||
"""Cog with the guessing command."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -24,17 +24,14 @@ class Guess(Cog):
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not 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."
|
||||
)
|
||||
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:
|
||||
@@ -47,9 +44,7 @@ class Guess(Cog):
|
||||
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."
|
||||
)
|
||||
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)]:
|
||||
@@ -107,4 +102,4 @@ class Guess(Cog):
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Guess(bot))
|
||||
bot.add_cog(CogGuess(bot))
|
@@ -1,15 +1,13 @@
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from bson.errors import InvalidId
|
||||
from discord import ApplicationContext, Cog, option, slash_command
|
||||
from discord.utils import basic_autocomplete
|
||||
|
||||
from classes import PycordEvent, PycordGuild, PycordUser
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import autocomplete_active_events
|
||||
from modules.utils import autocomplete_active_events, get_unix_timestamp
|
||||
|
||||
|
||||
class Register(Cog):
|
||||
class CogRegister(Cog):
|
||||
"""Cog with the event registration command."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -36,17 +34,14 @@ class Register(Cog):
|
||||
return
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not 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."
|
||||
)
|
||||
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:
|
||||
@@ -58,9 +53,9 @@ class Register(Cog):
|
||||
|
||||
# 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 <t:{int((pycord_event.starts.replace(tzinfo=ZoneInfo('UTC'))).timestamp())}:R>. Good luck!"
|
||||
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 <t:{get_unix_timestamp(pycord_event.starts)}:R>. Good luck!"
|
||||
)
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Register(bot))
|
||||
bot.add_cog(CogRegister(bot))
|
@@ -1,6 +1,4 @@
|
||||
from datetime import datetime
|
||||
from typing import List, Dict, Any
|
||||
from zoneinfo import ZoneInfo
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from bson.errors import InvalidId
|
||||
from discord import ApplicationContext, Attachment, SlashCommandGroup, option
|
||||
@@ -9,31 +7,15 @@ from discord.utils import basic_autocomplete
|
||||
|
||||
from classes import PycordEvent, PycordEventStage, PycordGuild
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import autocomplete_active_events, autocomplete_event_stages
|
||||
from modules.utils import (
|
||||
autocomplete_active_events,
|
||||
autocomplete_event_stages,
|
||||
is_event_status_valid,
|
||||
is_operation_confirmed,
|
||||
)
|
||||
|
||||
|
||||
async def validate_event_status(
|
||||
ctx: ApplicationContext,
|
||||
event: PycordEvent,
|
||||
) -> bool:
|
||||
if event.is_cancelled:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("This event was cancelled.")
|
||||
return False
|
||||
|
||||
if (
|
||||
event.starts.replace(tzinfo=ZoneInfo("UTC"))
|
||||
<= datetime.now(tz=ZoneInfo("UTC"))
|
||||
<= event.ends.replace(tzinfo=ZoneInfo("UTC"))
|
||||
):
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Ongoing events cannot be modified.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class Stage(Cog):
|
||||
class CogStage(Cog):
|
||||
"""Cog with event stage management commands."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -67,8 +49,7 @@ class Stage(Cog):
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -78,12 +59,10 @@ class Stage(Cog):
|
||||
await ctx.respond("Event was not found.")
|
||||
return
|
||||
|
||||
if not (await validate_event_status(ctx, pycord_event)):
|
||||
if not (await is_event_status_valid(ctx, pycord_event)):
|
||||
return
|
||||
|
||||
processed_media: List[Dict[str, Any]] = (
|
||||
[] if media is None else await self.bot.process_attachments([media])
|
||||
)
|
||||
processed_media: List[Dict[str, Any]] = [] if media is None else await self.bot.process_attachments([media])
|
||||
|
||||
event_stage: PycordEventStage = await self.bot.create_event_stage(
|
||||
event=pycord_event,
|
||||
@@ -137,8 +116,7 @@ class Stage(Cog):
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -148,7 +126,7 @@ class Stage(Cog):
|
||||
await ctx.respond("Event was not found.")
|
||||
return
|
||||
|
||||
if not (await validate_event_status(ctx, pycord_event)):
|
||||
if not (await is_event_status_valid(ctx, pycord_event)):
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -163,9 +141,7 @@ class Stage(Cog):
|
||||
await ctx.respond("Stage sequence out of range.")
|
||||
return
|
||||
|
||||
processed_media: List[Dict[str, Any]] = (
|
||||
[] if media is None else await self.bot.process_attachments([media])
|
||||
)
|
||||
processed_media: List[Dict[str, Any]] = [] if media is None else await self.bot.process_attachments([media])
|
||||
|
||||
if not (question is None and answer is None and media is None and remove_media is False):
|
||||
await event_stage.update(
|
||||
@@ -201,16 +177,13 @@ class Stage(Cog):
|
||||
async def command_stage_delete(
|
||||
self, ctx: ApplicationContext, event: str, stage: str, confirm: bool = False
|
||||
) -> None:
|
||||
if confirm is None or not confirm:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Operation not confirmed.")
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not configured.")
|
||||
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -220,7 +193,7 @@ class Stage(Cog):
|
||||
await ctx.respond("Event was not found.")
|
||||
return
|
||||
|
||||
if not (await validate_event_status(ctx, pycord_event)):
|
||||
if not (await is_event_status_valid(ctx, pycord_event)):
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -238,4 +211,4 @@ class Stage(Cog):
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Stage(bot))
|
||||
bot.add_cog(CogStage(bot))
|
@@ -4,10 +4,10 @@ from discord.utils import basic_autocomplete
|
||||
|
||||
from classes import PycordEvent, PycordGuild, PycordUser
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import autocomplete_user_registered_events
|
||||
from modules.utils import autocomplete_user_registered_events, is_operation_confirmed
|
||||
|
||||
|
||||
class Unregister(Cog):
|
||||
class CogUnregister(Cog):
|
||||
"""Cog with the event unregistration command."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -25,9 +25,7 @@ class Unregister(Cog):
|
||||
)
|
||||
@option("confirm", description="Confirmation of the operation", required=False)
|
||||
async def command_unregister(self, ctx: ApplicationContext, event: str, confirm: bool = False) -> None:
|
||||
if confirm is None or not confirm:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Operation not confirmed.")
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
|
||||
@@ -40,17 +38,14 @@ class Unregister(Cog):
|
||||
return
|
||||
|
||||
if not guild.is_configured():
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Guild is not 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."
|
||||
)
|
||||
await ctx.respond("You are jailed and cannot interact with events. Please, contact the administrator.")
|
||||
return
|
||||
|
||||
if pycord_event._id not in user.registered_event_ids:
|
||||
@@ -66,4 +61,4 @@ class Unregister(Cog):
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(Unregister(bot))
|
||||
bot.add_cog(CogUnregister(bot))
|
@@ -8,9 +8,10 @@ from discord.ext.commands import Cog
|
||||
|
||||
from classes import PycordUser
|
||||
from classes.pycord_bot import PycordBot
|
||||
from modules.utils import is_operation_confirmed
|
||||
|
||||
|
||||
class User(Cog):
|
||||
class CogUser(Cog):
|
||||
"""Cog with user management commands."""
|
||||
|
||||
def __init__(self, bot: PycordBot):
|
||||
@@ -53,9 +54,7 @@ class User(Cog):
|
||||
description="Selected user",
|
||||
)
|
||||
@option("confirm", description="Confirmation of the operation", required=False)
|
||||
async def command_user_delete_channel(
|
||||
self, ctx: ApplicationContext, user: User, confirm: bool = False
|
||||
) -> None:
|
||||
async def command_user_delete_channel(self, ctx: ApplicationContext, user: User, confirm: bool = False) -> None:
|
||||
await ctx.respond("Not implemented.")
|
||||
|
||||
# TODO Introduce i18n
|
||||
@@ -69,23 +68,20 @@ class User(Cog):
|
||||
)
|
||||
@option("confirm", description="Confirmation of the operation", required=False)
|
||||
async def command_user_jail(self, ctx: ApplicationContext, user: User, confirm: bool = False) -> None:
|
||||
if confirm is None or not confirm:
|
||||
await ctx.respond(self.bot._("operation_unconfirmed", "messages", locale=ctx.locale))
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
pycord_user: PycordUser = await self.bot.find_user(user, ctx.guild)
|
||||
|
||||
if pycord_user.is_jailed:
|
||||
# TODO Make a nice message
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(f"User **{user.display_name}** is already jailed.")
|
||||
return
|
||||
|
||||
await pycord_user.jail(self.bot.cache)
|
||||
|
||||
# TODO Make a nice message
|
||||
await ctx.respond(
|
||||
f"User **{user.display_name}** has been jailed and cannot interact with events anymore."
|
||||
)
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(f"User **{user.display_name}** has been jailed and cannot interact with events anymore.")
|
||||
|
||||
# TODO Introduce i18n
|
||||
@command_group.command(
|
||||
@@ -98,24 +94,21 @@ class User(Cog):
|
||||
)
|
||||
@option("confirm", description="Confirmation of the operation", required=False)
|
||||
async def command_user_unjail(self, ctx: ApplicationContext, user: User, confirm: bool = False) -> None:
|
||||
if confirm is None or not confirm:
|
||||
await ctx.respond(self.bot._("operation_unconfirmed", "messages", locale=ctx.locale))
|
||||
if not (await is_operation_confirmed(ctx, confirm)):
|
||||
return
|
||||
|
||||
pycord_user: PycordUser = await self.bot.find_user(user, ctx.guild)
|
||||
|
||||
if not pycord_user.is_jailed:
|
||||
# TODO Make a nice message
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(f"User **{user.display_name}** is not jailed.")
|
||||
return
|
||||
|
||||
await pycord_user.unjail(self.bot.cache)
|
||||
|
||||
# TODO Make a nice message
|
||||
await ctx.respond(
|
||||
f"User **{user.display_name}** has been unjailed and can interact with events again."
|
||||
)
|
||||
# TODO Introduce i18n
|
||||
await ctx.respond(f"User **{user.display_name}** has been unjailed and can interact with events again.")
|
||||
|
||||
|
||||
def setup(bot: PycordBot) -> None:
|
||||
bot.add_cog(User(bot))
|
||||
bot.add_cog(CogUser(bot))
|
2
main.py
2
main.py
@@ -6,7 +6,7 @@ from os import makedirs
|
||||
from pathlib import Path
|
||||
from sys import exit
|
||||
|
||||
from discord import LoginFailure, Intents
|
||||
from discord import Intents, LoginFailure
|
||||
from libbot.utils import config_get
|
||||
|
||||
from classes.pycord_bot import PycordBot
|
||||
|
@@ -7,5 +7,7 @@ from .autocomplete_utils import (
|
||||
autocomplete_user_registered_events,
|
||||
)
|
||||
from .cache_utils import restore_from_cache
|
||||
from .datetime_utils import get_unix_timestamp
|
||||
from .event_utils import validate_event_validity
|
||||
from .logging_utils import get_logger, get_logging_config
|
||||
from .validation_utils import is_event_status_valid, is_operation_confirmed
|
||||
|
@@ -92,8 +92,6 @@ async def autocomplete_event_stages(ctx: AutocompleteContext) -> List[OptionChoi
|
||||
event_stages: List[OptionChoice] = []
|
||||
|
||||
async for result in col_stages.find(query).sort([("sequence", ASCENDING)]):
|
||||
event_stages.append(
|
||||
OptionChoice(f"{result['sequence']+1} ({result['question']})", str(result["_id"]))
|
||||
)
|
||||
event_stages.append(OptionChoice(f"{result['sequence']+1} ({result['question']})", str(result["_id"])))
|
||||
|
||||
return event_stages
|
||||
|
7
modules/utils/datetime_utils.py
Normal file
7
modules/utils/datetime_utils.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
|
||||
# TODO Add documentation
|
||||
def get_unix_timestamp(date: datetime) -> int:
|
||||
return int((date.replace(tzinfo=ZoneInfo("UTC"))).timestamp())
|
33
modules/utils/validation_utils.py
Normal file
33
modules/utils/validation_utils.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from discord import ApplicationContext
|
||||
|
||||
|
||||
async def is_operation_confirmed(ctx: ApplicationContext, confirm: bool) -> bool:
|
||||
if confirm is None or not confirm:
|
||||
await ctx.respond(ctx.bot._("operation_unconfirmed", "messages", locale=ctx.locale))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def is_event_status_valid(
|
||||
ctx: ApplicationContext,
|
||||
event: "PycordEvent",
|
||||
) -> bool:
|
||||
if event.is_cancelled:
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("This event was cancelled.")
|
||||
return False
|
||||
|
||||
if (
|
||||
event.starts.replace(tzinfo=ZoneInfo("UTC"))
|
||||
<= datetime.now(tz=ZoneInfo("UTC"))
|
||||
<= event.ends.replace(tzinfo=ZoneInfo("UTC"))
|
||||
):
|
||||
# TODO Make a nice message
|
||||
await ctx.respond("Ongoing events cannot be modified.")
|
||||
return False
|
||||
|
||||
return True
|
@@ -5,7 +5,7 @@ readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
|
||||
[tool.black]
|
||||
line-length = 108
|
||||
line-length = 118
|
||||
target-version = ["py311", "py312", "py313"]
|
||||
|
||||
[tool.isort]
|
||||
|
Reference in New Issue
Block a user