diff --git a/core/commands/base.py b/core/commands/base.py new file mode 100644 index 0000000..54a4235 --- /dev/null +++ b/core/commands/base.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +""" +Базовый класс для всех команд бота. +Реализует: +- алиасы (альтернативные имена команд) +- проверку прав доступа (admin) +- парсинг аргументов (через core.utils.arg_parser) +- метод справки get_help() +- кэширование результатов (опционально) + +Изменения для групповой работы: +- метод execute теперь принимает дополнительный параметр room_jid (None для личных чатов). +- Команды, которым нужен контекст комнаты, могут его использовать. +""" + +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Dict, Any, Tuple, List, Optional +import time + +from core.utils.arg_parser import parse_args # путь изменён: arg_parser перенесён в utils + +if TYPE_CHECKING: + from core.xmpp.client import Bot # обновлённый импорт + + +class Command(ABC): + """Абстрактный базовый класс команды. Все команды должны наследоваться от него.""" + + # Основное имя команды (например "!info") + name: str = None + # Альтернативные имена (например ["!help", "!справка"]) + aliases: List[str] = [] + # Необходимые права: None – любой, "admin" – только администраторы + permission: Optional[str] = None + # Время жизни кэша в секундах (0 – не кэшировать) + cache_ttl: int = 0 + + def __init__(self, bot: 'Bot'): + self.bot = bot + # Кэш: ключ -> (время, результат) + self._cache: Dict[str, Tuple[float, Any]] = {} + + @abstractmethod + async def execute(self, msg, args: str, user_jid: str, room_jid: str = None): + """ + Выполнить команду. + + :param msg: объект сообщения slixmpp (для ответа) + :param args: полная строка аргументов (включая имя команды) + :param user_jid: JID пользователя (без ресурса) + :param room_jid: JID комнаты, если команда вызвана в групповом чате; иначе None + """ + pass + + def get_help(self) -> str: + """Возвращает строку справки для команды. Переопределяется в дочерних классах.""" + return "Нет описания." + + def check_permission(self, user_jid: str) -> bool: + """Проверяет, имеет ли пользователь право на выполнение команды.""" + if self.permission is None: + return True + if self.permission == "admin": + return user_jid in self.bot.config.admin_jids + return False + + def get_cache_key(self, user_jid: str, args: str) -> str: + """Формирует ключ для кэширования (по умолчанию user_jid).""" + return user_jid + + def parse_args(self, args_str: str) -> Tuple[str, Dict[str, Any], List[str]]: + """Разбирает строку аргументов на команду, флаги и позиционные аргументы.""" + return parse_args(args_str) + + def _cache_result(self, key: str, result: str): + """Сохраняет результат в кэш (вызывается из команды).""" + self._cache[key] = (time.time(), result) \ No newline at end of file