166 lines
5.9 KiB
Python
166 lines
5.9 KiB
Python
from abc import ABC, abstractmethod
|
|
from typing import Dict, Tuple, Optional, List
|
|
from src.common.logger import get_logger
|
|
from src.plugin_system.apis.plugin_api import PluginAPI
|
|
from src.plugin_system.base.component_types import CommandInfo, ComponentType
|
|
from src.chat.message_receive.message import MessageRecv
|
|
|
|
logger = get_logger("base_command")
|
|
|
|
|
|
class BaseCommand(ABC):
|
|
"""Command组件基类
|
|
|
|
Command是插件的一种组件类型,用于处理命令请求
|
|
|
|
子类可以通过类属性定义命令模式:
|
|
- command_pattern: 命令匹配的正则表达式
|
|
- command_help: 命令帮助信息
|
|
- command_examples: 命令使用示例列表
|
|
- intercept_message: 是否拦截消息处理(默认True拦截,False继续传递)
|
|
"""
|
|
|
|
# 默认命令设置(子类可以覆盖)
|
|
command_pattern: str = ""
|
|
command_help: str = ""
|
|
command_examples: List[str] = []
|
|
intercept_message: bool = True # 默认拦截消息,不继续处理
|
|
|
|
def __init__(self, message: MessageRecv, plugin_config: dict = None):
|
|
"""初始化Command组件
|
|
|
|
Args:
|
|
message: 接收到的消息对象
|
|
plugin_config: 插件配置字典
|
|
"""
|
|
self.message = message
|
|
self.matched_groups: Dict[str, str] = {} # 存储正则表达式匹配的命名组
|
|
|
|
# 创建API实例
|
|
self.api = PluginAPI(chat_stream=message.chat_stream, log_prefix="[Command]", plugin_config=plugin_config)
|
|
|
|
self.log_prefix = "[Command]"
|
|
|
|
logger.debug(f"{self.log_prefix} Command组件初始化完成")
|
|
|
|
def set_matched_groups(self, groups: Dict[str, str]) -> None:
|
|
"""设置正则表达式匹配的命名组
|
|
|
|
Args:
|
|
groups: 正则表达式匹配的命名组
|
|
"""
|
|
self.matched_groups = groups
|
|
|
|
@abstractmethod
|
|
async def execute(self) -> Tuple[bool, Optional[str]]:
|
|
"""执行Command的抽象方法,子类必须实现
|
|
|
|
Returns:
|
|
Tuple[bool, Optional[str]]: (是否执行成功, 可选的回复消息)
|
|
"""
|
|
pass
|
|
|
|
async def send_reply(self, content: str) -> None:
|
|
"""发送回复消息
|
|
|
|
Args:
|
|
content: 回复内容
|
|
"""
|
|
# 获取聊天流信息
|
|
chat_stream = self.message.chat_stream
|
|
|
|
if chat_stream.group_info:
|
|
# 群聊
|
|
await self.api.send_text_to_group(
|
|
text=content, group_id=str(chat_stream.group_info.group_id), platform=chat_stream.platform
|
|
)
|
|
else:
|
|
# 私聊
|
|
await self.api.send_text_to_user(
|
|
text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform
|
|
)
|
|
|
|
async def send_command(self, command_name: str, args: dict = None, display_message: str = None) -> bool:
|
|
"""发送命令消息
|
|
|
|
使用和send_reply相同的方式通过MessageAPI发送命令
|
|
|
|
Args:
|
|
command_name: 命令名称
|
|
args: 命令参数
|
|
display_message: 显示消息
|
|
|
|
Returns:
|
|
bool: 是否发送成功
|
|
"""
|
|
try:
|
|
# 构造命令数据
|
|
command_data = {"name": command_name, "args": args or {}}
|
|
|
|
# 使用send_message_to_target方法发送命令
|
|
chat_stream = self.message.chat_stream
|
|
command_content = command_data
|
|
|
|
if chat_stream.group_info:
|
|
# 群聊
|
|
success = await self.api.send_message_to_target(
|
|
message_type="command",
|
|
content=command_content,
|
|
platform=chat_stream.platform,
|
|
target_id=str(chat_stream.group_info.group_id),
|
|
is_group=True,
|
|
display_message=display_message or f"执行命令: {command_name}",
|
|
)
|
|
else:
|
|
# 私聊
|
|
success = await self.api.send_message_to_target(
|
|
message_type="command",
|
|
content=command_content,
|
|
platform=chat_stream.platform,
|
|
target_id=str(chat_stream.user_info.user_id),
|
|
is_group=False,
|
|
display_message=display_message or f"执行命令: {command_name}",
|
|
)
|
|
|
|
if success:
|
|
logger.info(f"{self.log_prefix} 成功发送命令: {command_name}")
|
|
else:
|
|
logger.error(f"{self.log_prefix} 发送命令失败: {command_name}")
|
|
|
|
return success
|
|
|
|
except Exception as e:
|
|
logger.error(f"{self.log_prefix} 发送命令时出错: {e}")
|
|
return False
|
|
|
|
@classmethod
|
|
def get_command_info(cls, name: str = None, description: str = None) -> "CommandInfo":
|
|
"""从类属性生成CommandInfo
|
|
|
|
Args:
|
|
name: Command名称,如果不提供则使用类名
|
|
description: Command描述,如果不提供则使用类文档字符串
|
|
|
|
Returns:
|
|
CommandInfo: 生成的Command信息对象
|
|
"""
|
|
|
|
# 优先使用类属性,然后自动生成
|
|
if name is None:
|
|
name = getattr(cls, "command_name", cls.__name__.lower().replace("command", ""))
|
|
if description is None:
|
|
description = getattr(cls, "command_description", None)
|
|
if description is None:
|
|
description = cls.__doc__ or f"{cls.__name__} Command组件"
|
|
description = description.strip().split("\n")[0] # 取第一行作为描述
|
|
|
|
return CommandInfo(
|
|
name=name,
|
|
component_type=ComponentType.COMMAND,
|
|
description=description,
|
|
command_pattern=cls.command_pattern,
|
|
command_help=cls.command_help,
|
|
command_examples=cls.command_examples.copy() if cls.command_examples else [],
|
|
intercept_message=cls.intercept_message,
|
|
)
|