From c4ebd1b891538ad6ce1276c367242a98d26c8958 Mon Sep 17 00:00:00 2001 From: profitroll Date: Mon, 28 Apr 2025 13:06:55 +0200 Subject: [PATCH] Added /status command --- classes/pycord_bot.py | 6 ++++++ cogs/cog_status.py | 42 ++++++++++++++++++++++++++++++++++++++ locale/en-US.json | 7 ++++++- main.py | 4 +++- modules/utils/__init__.py | 1 + modules/utils/git_utils.py | 27 ++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 cogs/cog_status.py create mode 100644 modules/utils/git_utils.py diff --git a/classes/pycord_bot.py b/classes/pycord_bot.py index cda9992..0bc25a6 100644 --- a/classes/pycord_bot.py +++ b/classes/pycord_bot.py @@ -20,6 +20,9 @@ logger: Logger = get_logger(__name__) class PycordBot(LibPycordBot): + __version__ = "0.1.0" + + started: datetime cache: CacheMemcached | CacheRedis | None = None def __init__(self, *args, **kwargs) -> None: @@ -48,6 +51,9 @@ class PycordBot(LibPycordBot): @override async def start(self, *args: Any, **kwargs: Any) -> None: await self._schedule_tasks() + + self.started = datetime.now(tz=ZoneInfo("UTC")) + await super().start(*args, **kwargs) @override diff --git a/cogs/cog_status.py b/cogs/cog_status.py new file mode 100644 index 0000000..d2a17a7 --- /dev/null +++ b/cogs/cog_status.py @@ -0,0 +1,42 @@ +from discord import ApplicationContext, Cog, slash_command +from libbot.i18n import _, in_every_locale + +from classes.pycord_bot import PycordBot +from modules.utils import get_current_commit, get_unix_timestamp + + +class CogStatus(Cog): + """Cog with the status command.""" + + def __init__(self, bot: PycordBot): + self.bot: PycordBot = bot + + @slash_command( + name="status", + description=_("description", "commands", "status"), + description_localizations=in_every_locale("description", "commands", "status"), + ) + async def command_status(self, ctx: ApplicationContext) -> None: + current_commit: str | None = await get_current_commit() + + if current_commit is None: + await ctx.respond( + self.bot._("status", "messages", locale=ctx.locale).format( + version=self.bot.__version__, + start_time=get_unix_timestamp(self.bot.started), + ) + ) + + return + + await ctx.respond( + self.bot._("status_git", "messages", locale=ctx.locale).format( + version=self.bot.__version__, + commit=current_commit if len(current_commit) < 10 else current_commit[:10], + start_time=get_unix_timestamp(self.bot.started), + ) + ) + + +def setup(bot: PycordBot) -> None: + bot.add_cog(CogStatus(bot)) diff --git a/locale/en-US.json b/locale/en-US.json index f7527c1..6df5eb7 100644 --- a/locale/en-US.json +++ b/locale/en-US.json @@ -6,7 +6,9 @@ "timezone_invalid": "Timezone **{timezone}** was not found. Please, select one of the timezones provided by the autocompletion.", "config_set": "Configuration has been updated. You can review it anytime using `/config show`.", "config_reset": "Configuration has been reset. You can update it using `/config set`, otherwise no events can be held.", - "config_show": "**Guild config**\n\nChannel: <#{channel_id}>\nCategory: <#{category_id}>\nTimezone: {timezone}" + "config_show": "**Guild config**\n\nChannel: <#{channel_id}>\nCategory: <#{category_id}>\nTimezone: {timezone}", + "status": "**QuizBot** v{version}\n\nUptime: since ", + "status_git": "**QuizBot** v{version} (`{commit}`)\n\nUptime: since " }, "commands": { "config": { @@ -172,6 +174,9 @@ } } }, + "status": { + "description": "Get status of the bot" + }, "unregister": { "description": "Leave the selected event", "options": { diff --git a/main.py b/main.py index d86b1ed..db14de2 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,5 @@ +"""Main module with entry point that must be executed for the bot to start""" + import contextlib import logging.config from argparse import ArgumentParser @@ -39,7 +41,7 @@ with contextlib.suppress(ImportError): uvloop.install() -def main(): +def main() -> None: # Perform migration if command line argument was provided if args.migrate: migrate_database() diff --git a/modules/utils/__init__.py b/modules/utils/__init__.py index c3f0ed2..f15d19e 100644 --- a/modules/utils/__init__.py +++ b/modules/utils/__init__.py @@ -9,5 +9,6 @@ from .autocomplete_utils import ( from .cache_utils import restore_from_cache from .datetime_utils import get_unix_timestamp from .event_utils import validate_event_validity +from .git_utils import get_current_commit from .logging_utils import get_logger, get_logging_config from .validation_utils import is_event_status_valid, is_operation_confirmed diff --git a/modules/utils/git_utils.py b/modules/utils/git_utils.py new file mode 100644 index 0000000..3c61fb0 --- /dev/null +++ b/modules/utils/git_utils.py @@ -0,0 +1,27 @@ +from pathlib import Path + +import aiofiles + + +# TODO Add documentation +async def get_current_commit() -> str | None: + head_path: Path = Path(".git/HEAD") + + if not head_path.exists(): + return None + + async with aiofiles.open(head_path, "r", encoding="utf-8") as head_file: + head_content: str = (await head_file.read()).strip() + + if not head_content.startswith("ref:"): + return head_content + + head_ref_path: Path = Path(".git/").joinpath(" ".join(head_content.split(" ")[1:])) + + if not head_ref_path.exists(): + return None + + async with aiofiles.open(head_ref_path, "r", encoding="utf-8") as head_ref_file: + head_ref_content: str = (await head_ref_file.read()).strip() + + return head_ref_content