diff --git a/src/altlinux/altlinux/__main__.py b/src/altlinux/altlinux/__main__.py index ffd1e3b..d49b85a 100644 --- a/src/altlinux/altlinux/__main__.py +++ b/src/altlinux/altlinux/__main__.py @@ -1,4 +1,5 @@ import asyncio +from importlib.metadata import version from ocab_core import OCAB from ocab_modules import module_loader @@ -14,7 +15,9 @@ async def main(): module_loader("standard", "filters", safe=False), module_loader("standard", "report"), module_loader("standard", "welcome", safe=False), - ] + module_loader("standard", "help"), + ], + metainfo={"app_version": version("altlinux")}, ) await ocab.start() diff --git a/src/ocab_core/ocab_core/main.py b/src/ocab_core/ocab_core/main.py index 83a0b5c..fb91365 100644 --- a/src/ocab_core/ocab_core/main.py +++ b/src/ocab_core/ocab_core/main.py @@ -17,9 +17,11 @@ class OCAB: def __init__(self) -> None: pass - async def init_app(self, bot_modules): + async def init_app(self, bot_modules, metainfo=None): setup_logger() singleton = Singleton() + if isinstance(metainfo, dict): + singleton.storage["metainfo"] = metainfo try: singleton.modules_manager = ModulesManager() diff --git a/src/ocab_core/ocab_core/modules_system/public_api/__init__.py b/src/ocab_core/ocab_core/modules_system/public_api/__init__.py index 1a1cadb..866f4d6 100644 --- a/src/ocab_core/ocab_core/modules_system/public_api/__init__.py +++ b/src/ocab_core/ocab_core/modules_system/public_api/__init__.py @@ -3,6 +3,7 @@ from ocab_core.logger import log from .public_api import ( Storage, get_fsm_context, + get_metainfo, get_module, register_outer_message_middleware, register_router, diff --git a/src/ocab_core/ocab_core/modules_system/public_api/public_api.py b/src/ocab_core/ocab_core/modules_system/public_api/public_api.py index d7598ec..e9ce931 100644 --- a/src/ocab_core/ocab_core/modules_system/public_api/public_api.py +++ b/src/ocab_core/ocab_core/modules_system/public_api/public_api.py @@ -26,6 +26,11 @@ def register_outer_message_middleware(middleware: BaseMiddleware): app.storage["_outer_message_middlewares"].append(middleware) +def get_metainfo(): + app = Singleton() + return app.storage["metainfo"].copy() + + async def set_my_commands(commands): app = Singleton() await app.bot.set_my_commands(commands) diff --git a/src/ocab_core/ocab_core/modules_system/safe/policy.py b/src/ocab_core/ocab_core/modules_system/safe/policy.py index 08810c9..d74fe6f 100644 --- a/src/ocab_core/ocab_core/modules_system/safe/policy.py +++ b/src/ocab_core/ocab_core/modules_system/safe/policy.py @@ -12,6 +12,7 @@ from RestrictedPython import ( from RestrictedPython.Eval import default_guarded_getitem, default_guarded_getiter from RestrictedPython.Guards import ( # guarded_setattr,; full_write_guard, _write_wrapper, + guarded_iter_unpack_sequence, guarded_unpack_sequence, safer_getattr, ) @@ -138,6 +139,7 @@ BUILTINS["_getitem_"] = default_guarded_getitem BUILTINS["_getattr_"] = safes_getattr BUILTINS["_getiter_"] = default_guarded_getiter BUILTINS["_write_"] = write_guard() +BUILTINS["_iter_unpack_sequence_"] = guarded_iter_unpack_sequence BUILTINS["_unpack_sequence_"] = guarded_unpack_sequence BUILTINS["staticmethod"] = staticmethod BUILTINS["tuple"] = tuple diff --git a/src/ocab_modules/ocab_modules/standard/command_helper/__init__.py b/src/ocab_modules/ocab_modules/standard/command_helper/__init__.py index 90596da..3461e7b 100644 --- a/src/ocab_modules/ocab_modules/standard/command_helper/__init__.py +++ b/src/ocab_modules/ocab_modules/standard/command_helper/__init__.py @@ -1 +1 @@ -from .main import module_late_init, register_command +from .main import get_user_commands, module_late_init, register_command diff --git a/src/ocab_modules/ocab_modules/standard/command_helper/main.py b/src/ocab_modules/ocab_modules/standard/command_helper/main.py index f7c417e..9fcb5f9 100644 --- a/src/ocab_modules/ocab_modules/standard/command_helper/main.py +++ b/src/ocab_modules/ocab_modules/standard/command_helper/main.py @@ -32,5 +32,11 @@ async def set_user_commands(): ) +def get_user_commands(): + if "USER" in commands: + return commands["USER"].copy() + return {} + + async def module_late_init(): await set_user_commands() diff --git a/src/ocab_modules/ocab_modules/standard/help/__init__.py b/src/ocab_modules/ocab_modules/standard/help/__init__.py new file mode 100644 index 0000000..c8fccb0 --- /dev/null +++ b/src/ocab_modules/ocab_modules/standard/help/__init__.py @@ -0,0 +1 @@ +from .main import module_init diff --git a/src/ocab_modules/ocab_modules/standard/help/info.json b/src/ocab_modules/ocab_modules/standard/help/info.json new file mode 100644 index 0000000..30cbbe6 --- /dev/null +++ b/src/ocab_modules/ocab_modules/standard/help/info.json @@ -0,0 +1,21 @@ +{ + "id": "standard.help", + "name": "Help", + "description": "Модуль для вывода /help сообщения", + "author": "OCAB Team", + "version": "1.0.0", + "privileged": false, + "dependencies": { + "required": { + "standard.config": "^1.0.0" + }, + "optional": { + "standard.command_helper": "^1.0.0" + } + }, + "pythonDependencies": { + "required": { + "string": "*" + } + } +} diff --git a/src/ocab_modules/ocab_modules/standard/help/main.py b/src/ocab_modules/ocab_modules/standard/help/main.py new file mode 100644 index 0000000..6dedb83 --- /dev/null +++ b/src/ocab_modules/ocab_modules/standard/help/main.py @@ -0,0 +1,81 @@ +import string +from typing import TYPE_CHECKING + +from aiogram import Router +from aiogram.filters import Command +from aiogram.types import Message + +from ocab_core.modules_system.public_api import ( + get_metainfo, + get_module, + register_router, +) + +if TYPE_CHECKING: + from ocab_modules.standard.config import IConfig + +config: "IConfig" = get_module("standard.config", "config") + +try: + (register_command, get_user_commands) = get_module( + "standard.command_helper", ["register_command", "get_user_commands"] + ) + COMMAND_HELPER_MODULE_LOADED = True +except Exception: + COMMAND_HELPER_MODULE_LOADED = False + pass + +FOOTER = """=== + +Разработано командой ALT Gnome Infrastructure в рамках проекта Каркас. + +Исходный код: https://gitflic.ru/project/alt-gnome/karkas +Оставить репорт: https://gitflic.ru/project/alt-gnome/karkas/issue/create + +Руководитель проекта: Семен Фомченков +Ведущий разработчик: Максим Слипенко + +Версия: $version +""" + + +def format_commands(commands_dict): + formatted_commands = [] + for command, details in commands_dict.items(): + formatted_commands.append(f"/{command} - {details['description']}") + return "\n".join(formatted_commands) + + +async def help(message: Message): + commands = "" + version = "" + + if COMMAND_HELPER_MODULE_LOADED: + commands = format_commands(get_user_commands()) + + metainfo = get_metainfo() + if "app_version" in metainfo: + version = metainfo["app_version"] + + await message.reply( + string.Template(config.get("help::message") + "\n\n" + FOOTER).substitute( + commands=commands, version=version or "не указана" + ) + ) + + +async def module_init(): + config.register( + "help::message", + "string", + default_value="$commands", + ) + + router = Router() + + router.message.register(help, Command("help")) + + register_router(router) + + if COMMAND_HELPER_MODULE_LOADED: + register_command("help", "Cправка")