Improved some messages and prepared them for i18n

This commit is contained in:
2025-04-26 18:21:09 +02:00
parent a17b1cd768
commit ca1e47b55a
16 changed files with 167 additions and 172 deletions

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))