custom emoji in inline buttons/ CLI 0.3.9/ updated dependencies/ other minor changes
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import aiogram.types
|
||||
|
||||
_OriginalInlineKeyboardButton = aiogram.types.InlineKeyboardButton
|
||||
|
||||
_button_icon_config: dict[str, dict[str, str]] = {}
|
||||
|
||||
|
||||
def apply_button_icons_patch(config: dict[str, dict[str, str]] | None = None) -> None:
|
||||
"""
|
||||
Патчит InlineKeyboardButton, добавляя поддержку глобального конфига для иконок и стилей кнопок по callback_data или url.
|
||||
"""
|
||||
if config is not None:
|
||||
_button_icon_config.clear()
|
||||
_button_icon_config.update(config)
|
||||
|
||||
class _PatchedInlineKeyboardButton(_OriginalInlineKeyboardButton):
|
||||
def __init__(self, **kwargs: object):
|
||||
key = kwargs.get("callback_data") or kwargs.get("url")
|
||||
if key is not None and isinstance(key, str) and key in _button_icon_config:
|
||||
kwargs = {**kwargs, **_button_icon_config[key]}
|
||||
super().__init__(**kwargs)
|
||||
|
||||
aiogram.types.InlineKeyboardButton = _PatchedInlineKeyboardButton
|
||||
|
||||
|
||||
def set_button_icon_config(config: dict[str, dict[str, str]]) -> None:
|
||||
"""Подставить конфиг кнопок (вызвать после загрузки handlers, из handlers.buttons.BUTTON_ICON_CONFIG)."""
|
||||
_button_icon_config.clear()
|
||||
_button_icon_config.update(config)
|
||||
|
||||
|
||||
def inline_button(
|
||||
text: str,
|
||||
callback_data: str | None = None,
|
||||
url: str | None = None,
|
||||
web_app: object | None = None,
|
||||
*,
|
||||
icon_custom_emoji_id: str | None = None,
|
||||
style: str | None = None,
|
||||
) -> _OriginalInlineKeyboardButton:
|
||||
"""Собирает InlineKeyboardButton с опциональной иконкой (custom emoji) и стилем."""
|
||||
kwargs: dict = {"text": text}
|
||||
if callback_data is not None:
|
||||
kwargs["callback_data"] = callback_data
|
||||
if url is not None:
|
||||
kwargs["url"] = url
|
||||
if web_app is not None:
|
||||
kwargs["web_app"] = web_app
|
||||
if icon_custom_emoji_id is not None:
|
||||
kwargs["icon_custom_emoji_id"] = icon_custom_emoji_id
|
||||
if style is not None:
|
||||
kwargs["style"] = style
|
||||
return aiogram.types.InlineKeyboardButton(**kwargs)
|
||||
@@ -12,12 +12,18 @@ from .modules_manager import manager
|
||||
|
||||
modules_hub = Router(name="modules_hub")
|
||||
|
||||
def _is_safe_module_name(name: str) -> bool:
|
||||
return bool(name and name.isidentifier() and "." not in name and "/" not in name and "\\" not in name)
|
||||
|
||||
|
||||
def load_modules_from_folder(folder: str = "modules") -> list[Router]:
|
||||
routers = []
|
||||
base_path = Path(folder)
|
||||
|
||||
for _finder, name, _ispkg in pkgutil.iter_modules([str(base_path)]):
|
||||
if not _is_safe_module_name(name):
|
||||
logger.warning(f"[Modules] Пропуск недопустимого имени модуля: {name!r}")
|
||||
continue
|
||||
if not manager.should_autostart(name):
|
||||
logger.info(f"[Modules] Пропуск автозапуска модуля '{name}' (отключён).")
|
||||
continue
|
||||
@@ -43,6 +49,8 @@ def load_module_webhooks(folder: str = "modules") -> list[dict]:
|
||||
base_path = Path(folder)
|
||||
|
||||
for _finder, name, _ispkg in pkgutil.iter_modules([str(base_path)]):
|
||||
if not _is_safe_module_name(name):
|
||||
continue
|
||||
if not manager.should_autostart(name):
|
||||
logger.info(f"[Modules] Пропуск вебхуков модуля '{name}' (отключён).")
|
||||
continue
|
||||
@@ -65,6 +73,8 @@ def load_module_fast_flow_handlers(folder: str = "modules") -> dict:
|
||||
base_path = Path(folder)
|
||||
|
||||
for _finder, name, _ispkg in pkgutil.iter_modules([str(base_path)]):
|
||||
if not _is_safe_module_name(name):
|
||||
continue
|
||||
if not manager.should_autostart(name):
|
||||
logger.info(f"[Modules] Пропуск fast-flow модуля '{name}' (отключён).")
|
||||
continue
|
||||
|
||||
@@ -57,7 +57,12 @@ class ModulesManager:
|
||||
rec.enabled = True
|
||||
self.registry[name] = rec
|
||||
|
||||
def _is_safe_module_name(self, name: str) -> bool:
|
||||
return bool(name and name.isidentifier() and "." not in name and "/" not in name and "\\" not in name)
|
||||
|
||||
async def start(self, name: str) -> None:
|
||||
if not self._is_safe_module_name(name):
|
||||
raise ValueError(f"[Modules] Недопустимое имя модуля: {name!r}")
|
||||
rec = self.registry.get(name) or ModuleRecord(name, self.pkg(name))
|
||||
if rec.enabled:
|
||||
logger.info(f"[Modules] {name} уже активен.")
|
||||
|
||||
Reference in New Issue
Block a user