feat:将旧版示例插件更新,更新mute插件(tts,vtb,doubaopic持续炸裂中)
This commit is contained in:
@@ -26,6 +26,34 @@ class ConfigAPI:
|
||||
"""
|
||||
return global_config.get(key, default)
|
||||
|
||||
def get_config(self, key: str, default: Any = None) -> Any:
|
||||
"""
|
||||
从插件配置中获取值,支持嵌套键访问
|
||||
|
||||
Args:
|
||||
key: 配置键名,支持嵌套访问如 "section.subsection.key"
|
||||
default: 如果配置不存在时返回的默认值
|
||||
|
||||
Returns:
|
||||
Any: 配置值或默认值
|
||||
"""
|
||||
# 获取插件配置
|
||||
plugin_config = getattr(self, '_plugin_config', {})
|
||||
if not plugin_config:
|
||||
return default
|
||||
|
||||
# 支持嵌套键访问
|
||||
keys = key.split('.')
|
||||
current = plugin_config
|
||||
|
||||
for k in keys:
|
||||
if isinstance(current, dict) and k in current:
|
||||
current = current[k]
|
||||
else:
|
||||
return default
|
||||
|
||||
return current
|
||||
|
||||
async def get_user_id_by_person_name(self, person_name: str) -> tuple[str, str]:
|
||||
"""根据用户名获取用户ID
|
||||
|
||||
|
||||
@@ -160,201 +160,7 @@ class MessageAPI:
|
||||
message_type="text", content=text, platform=platform, target_id=user_id, is_group=False
|
||||
)
|
||||
|
||||
async def send_message(self, type: str, data: str, target: Optional[str] = "", display_message: str = "") -> bool:
|
||||
"""发送消息的简化方法
|
||||
|
||||
Args:
|
||||
type: 消息类型,如"text"、"image"等
|
||||
data: 消息内容
|
||||
target: 目标消息(可选)
|
||||
display_message: 显示的消息内容(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
try:
|
||||
# 安全获取服务和日志前缀
|
||||
services = getattr(self, "_services", {})
|
||||
log_prefix = getattr(self, "log_prefix", "[MessageAPI]")
|
||||
|
||||
expressor: DefaultExpressor = services.get("expressor")
|
||||
chat_stream: ChatStream = services.get("chat_stream")
|
||||
|
||||
if not expressor or not chat_stream:
|
||||
logger.error(f"{log_prefix} 无法发送消息:缺少必要的内部服务")
|
||||
return False
|
||||
|
||||
# 获取锚定消息(如果有)
|
||||
observations = services.get("observations", [])
|
||||
|
||||
if len(observations) > 0:
|
||||
chatting_observation: ChattingObservation = next(
|
||||
(obs for obs in observations if isinstance(obs, ChattingObservation)), None
|
||||
)
|
||||
|
||||
if chatting_observation:
|
||||
anchor_message = chatting_observation.search_message_by_text(target)
|
||||
else:
|
||||
anchor_message = None
|
||||
else:
|
||||
anchor_message = None
|
||||
|
||||
# 如果没有找到锚点消息,创建一个占位符
|
||||
if not anchor_message:
|
||||
logger.info(f"{log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
response_set = [
|
||||
(type, data),
|
||||
]
|
||||
|
||||
# 调用内部方法发送消息
|
||||
success = await expressor.send_response_messages(
|
||||
anchor_message=anchor_message,
|
||||
response_set=response_set,
|
||||
display_message=display_message,
|
||||
)
|
||||
|
||||
return success
|
||||
except Exception as e:
|
||||
log_prefix = getattr(self, "log_prefix", "[MessageAPI]")
|
||||
logger.error(f"{log_prefix} 发送消息时出错: {e}")
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
async def send_message_by_expressor(self, text: str, target: Optional[str] = None) -> bool:
|
||||
"""通过expressor发送文本消息的简化方法
|
||||
|
||||
Args:
|
||||
text: 要发送的消息文本
|
||||
target: 目标消息(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
# 安全获取服务和日志前缀
|
||||
services = getattr(self, "_services", {})
|
||||
log_prefix = getattr(self, "log_prefix", "[MessageAPI]")
|
||||
|
||||
expressor: DefaultExpressor = services.get("expressor")
|
||||
chat_stream: ChatStream = services.get("chat_stream")
|
||||
|
||||
if not expressor or not chat_stream:
|
||||
logger.error(f"{log_prefix} 无法发送消息:缺少必要的内部服务")
|
||||
return False
|
||||
|
||||
# 构造简化的动作数据
|
||||
reply_data = {"text": text, "target": target or "", "emojis": []}
|
||||
|
||||
# 获取锚定消息(如果有)
|
||||
observations = services.get("observations", [])
|
||||
|
||||
# 查找 ChattingObservation 实例
|
||||
chatting_observation = None
|
||||
for obs in observations:
|
||||
if isinstance(obs, ChattingObservation):
|
||||
chatting_observation = obs
|
||||
break
|
||||
|
||||
if not chatting_observation:
|
||||
logger.warning(f"{log_prefix} 未找到 ChattingObservation 实例,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message = chatting_observation.search_message_by_text(reply_data["target"])
|
||||
if not anchor_message:
|
||||
logger.info(f"{log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
# 调用内部方法发送消息
|
||||
cycle_timers = getattr(self, "cycle_timers", {})
|
||||
reasoning = getattr(self, "reasoning", "插件生成")
|
||||
thinking_id = getattr(self, "thinking_id", "plugin_thinking")
|
||||
|
||||
success, _ = await expressor.deal_reply(
|
||||
cycle_timers=cycle_timers,
|
||||
action_data=reply_data,
|
||||
anchor_message=anchor_message,
|
||||
reasoning=reasoning,
|
||||
thinking_id=thinking_id,
|
||||
)
|
||||
|
||||
return success
|
||||
|
||||
async def send_message_by_replyer(
|
||||
self, target: Optional[str] = None, extra_info_block: Optional[str] = None
|
||||
) -> bool:
|
||||
"""通过replyer发送消息的简化方法
|
||||
|
||||
Args:
|
||||
target: 目标消息(可选)
|
||||
extra_info_block: 额外信息块(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
# 安全获取服务和日志前缀
|
||||
services = getattr(self, "_services", {})
|
||||
log_prefix = getattr(self, "log_prefix", "[MessageAPI]")
|
||||
|
||||
replyer: DefaultReplyer = services.get("replyer")
|
||||
chat_stream: ChatStream = services.get("chat_stream")
|
||||
|
||||
if not replyer or not chat_stream:
|
||||
logger.error(f"{log_prefix} 无法发送消息:缺少必要的内部服务")
|
||||
return False
|
||||
|
||||
# 构造简化的动作数据
|
||||
reply_data = {"target": target or "", "extra_info_block": extra_info_block}
|
||||
|
||||
# 获取锚定消息(如果有)
|
||||
observations = services.get("observations", [])
|
||||
|
||||
# 查找 ChattingObservation 实例
|
||||
chatting_observation = None
|
||||
for obs in observations:
|
||||
if isinstance(obs, ChattingObservation):
|
||||
chatting_observation = obs
|
||||
break
|
||||
|
||||
if not chatting_observation:
|
||||
logger.warning(f"{log_prefix} 未找到 ChattingObservation 实例,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message = chatting_observation.search_message_by_text(reply_data["target"])
|
||||
if not anchor_message:
|
||||
logger.info(f"{log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
# 调用内部方法发送消息
|
||||
cycle_timers = getattr(self, "cycle_timers", {})
|
||||
reasoning = getattr(self, "reasoning", "插件生成")
|
||||
thinking_id = getattr(self, "thinking_id", "plugin_thinking")
|
||||
|
||||
success, _ = await replyer.deal_reply(
|
||||
cycle_timers=cycle_timers,
|
||||
action_data=reply_data,
|
||||
anchor_message=anchor_message,
|
||||
reasoning=reasoning,
|
||||
thinking_id=thinking_id,
|
||||
)
|
||||
|
||||
return success
|
||||
|
||||
def get_chat_type(self) -> str:
|
||||
"""获取当前聊天类型
|
||||
|
||||
@@ -33,7 +33,7 @@ class PluginAPI(MessageAPI, LLMAPI, DatabaseAPI, ConfigAPI, UtilsAPI, StreamAPI,
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, chat_stream=None, expressor=None, replyer=None, observations=None, log_prefix: str = "[PluginAPI]"
|
||||
self, chat_stream=None, expressor=None, replyer=None, observations=None, log_prefix: str = "[PluginAPI]", plugin_config: dict = None
|
||||
):
|
||||
"""
|
||||
初始化插件API
|
||||
@@ -44,6 +44,7 @@ class PluginAPI(MessageAPI, LLMAPI, DatabaseAPI, ConfigAPI, UtilsAPI, StreamAPI,
|
||||
replyer: 回复器对象
|
||||
observations: 观察列表
|
||||
log_prefix: 日志前缀
|
||||
plugin_config: 插件配置字典
|
||||
"""
|
||||
# 存储依赖对象
|
||||
self._services = {
|
||||
@@ -61,6 +62,9 @@ class PluginAPI(MessageAPI, LLMAPI, DatabaseAPI, ConfigAPI, UtilsAPI, StreamAPI,
|
||||
# 调用所有父类的初始化
|
||||
super().__init__()
|
||||
|
||||
# 存储插件配置
|
||||
self._plugin_config = plugin_config or {}
|
||||
|
||||
logger.debug(f"{self.log_prefix} PluginAPI 初始化完成")
|
||||
|
||||
def set_chat_stream(self, chat_stream):
|
||||
@@ -105,7 +109,7 @@ class PluginAPI(MessageAPI, LLMAPI, DatabaseAPI, ConfigAPI, UtilsAPI, StreamAPI,
|
||||
|
||||
# 便捷的工厂函数
|
||||
def create_plugin_api(
|
||||
chat_stream=None, expressor=None, replyer=None, observations=None, log_prefix: str = "[Plugin]"
|
||||
chat_stream=None, expressor=None, replyer=None, observations=None, log_prefix: str = "[Plugin]", plugin_config: dict = None
|
||||
) -> PluginAPI:
|
||||
"""
|
||||
创建插件API实例的便捷函数
|
||||
@@ -116,12 +120,13 @@ def create_plugin_api(
|
||||
replyer: 回复器对象
|
||||
observations: 观察列表
|
||||
log_prefix: 日志前缀
|
||||
plugin_config: 插件配置字典
|
||||
|
||||
Returns:
|
||||
PluginAPI: 配置好的插件API实例
|
||||
"""
|
||||
return PluginAPI(
|
||||
chat_stream=chat_stream, expressor=expressor, replyer=replyer, observations=observations, log_prefix=log_prefix
|
||||
chat_stream=chat_stream, expressor=expressor, replyer=replyer, observations=observations, log_prefix=log_prefix, plugin_config=plugin_config
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ class BaseAction(ABC):
|
||||
chat_stream=None,
|
||||
log_prefix: str = "",
|
||||
shutting_down: bool = False,
|
||||
plugin_config: dict = None,
|
||||
**kwargs,
|
||||
):
|
||||
"""初始化Action组件
|
||||
@@ -50,6 +51,7 @@ class BaseAction(ABC):
|
||||
chat_stream: 聊天流对象
|
||||
log_prefix: 日志前缀
|
||||
shutting_down: 是否正在关闭
|
||||
plugin_config: 插件配置字典
|
||||
**kwargs: 其他参数
|
||||
"""
|
||||
self.action_data = action_data
|
||||
@@ -84,6 +86,7 @@ class BaseAction(ABC):
|
||||
replyer=replyer or kwargs.get("replyer"),
|
||||
observations=observations or kwargs.get("observations", []),
|
||||
log_prefix=log_prefix,
|
||||
plugin_config=plugin_config or kwargs.get("plugin_config"),
|
||||
)
|
||||
|
||||
# 设置API的action上下文
|
||||
@@ -118,7 +121,221 @@ class BaseAction(ABC):
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
return await self.api.send_message("text", content)
|
||||
chat_stream = self.api.get_service('chat_stream')
|
||||
if not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 没有可用的聊天流发送回复")
|
||||
return False
|
||||
|
||||
if chat_stream.group_info:
|
||||
# 群聊
|
||||
return await self.api.send_text_to_group(
|
||||
text=content,
|
||||
group_id=str(chat_stream.group_info.group_id),
|
||||
platform=chat_stream.platform
|
||||
)
|
||||
else:
|
||||
# 私聊
|
||||
return 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.api.get_service('chat_stream')
|
||||
if not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 没有可用的聊天流发送命令")
|
||||
return False
|
||||
|
||||
command_content = str(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
|
||||
|
||||
async def send_message_by_expressor(self, text: str, target: str = "") -> bool:
|
||||
"""通过expressor发送文本消息的Action专用方法
|
||||
|
||||
Args:
|
||||
text: 要发送的消息文本
|
||||
target: 目标消息(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
try:
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.chat.message_receive.message import create_empty_anchor_message
|
||||
|
||||
# 获取服务
|
||||
expressor = self.api.get_service("expressor")
|
||||
chat_stream = self.api.get_service("chat_stream")
|
||||
observations = self.api.get_service("observations") or []
|
||||
|
||||
if not expressor or not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 无法通过expressor发送消息:缺少必要的服务")
|
||||
return False
|
||||
|
||||
# 构造动作数据
|
||||
reply_data = {"text": text, "target": target, "emojis": []}
|
||||
|
||||
# 查找 ChattingObservation 实例
|
||||
chatting_observation = None
|
||||
for obs in observations:
|
||||
if isinstance(obs, ChattingObservation):
|
||||
chatting_observation = obs
|
||||
break
|
||||
|
||||
if not chatting_observation:
|
||||
logger.warning(f"{self.log_prefix} 未找到 ChattingObservation 实例,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message = chatting_observation.search_message_by_text(target)
|
||||
if not anchor_message:
|
||||
logger.info(f"{self.log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
# 使用Action上下文信息发送消息
|
||||
success, _ = await expressor.deal_reply(
|
||||
cycle_timers=self.cycle_timers,
|
||||
action_data=reply_data,
|
||||
anchor_message=anchor_message,
|
||||
reasoning=self.reasoning,
|
||||
thinking_id=self.thinking_id,
|
||||
)
|
||||
|
||||
if success:
|
||||
logger.info(f"{self.log_prefix} 成功通过expressor发送消息")
|
||||
else:
|
||||
logger.error(f"{self.log_prefix} 通过expressor发送消息失败")
|
||||
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} 通过expressor发送消息时出错: {e}")
|
||||
return False
|
||||
|
||||
async def send_message_by_replyer(self, target: str = "", extra_info_block: str = None) -> bool:
|
||||
"""通过replyer发送消息的Action专用方法
|
||||
|
||||
Args:
|
||||
target: 目标消息(可选)
|
||||
extra_info_block: 额外信息块(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
try:
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.chat.message_receive.message import create_empty_anchor_message
|
||||
|
||||
# 获取服务
|
||||
replyer = self.api.get_service("replyer")
|
||||
chat_stream = self.api.get_service("chat_stream")
|
||||
observations = self.api.get_service("observations") or []
|
||||
|
||||
if not replyer or not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 无法通过replyer发送消息:缺少必要的服务")
|
||||
return False
|
||||
|
||||
# 构造动作数据
|
||||
reply_data = {"target": target, "extra_info_block": extra_info_block}
|
||||
|
||||
# 查找 ChattingObservation 实例
|
||||
chatting_observation = None
|
||||
for obs in observations:
|
||||
if isinstance(obs, ChattingObservation):
|
||||
chatting_observation = obs
|
||||
break
|
||||
|
||||
if not chatting_observation:
|
||||
logger.warning(f"{self.log_prefix} 未找到 ChattingObservation 实例,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message = chatting_observation.search_message_by_text(target)
|
||||
if not anchor_message:
|
||||
logger.info(f"{self.log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
# 使用Action上下文信息发送消息
|
||||
success, _ = await replyer.deal_reply(
|
||||
cycle_timers=self.cycle_timers,
|
||||
action_data=reply_data,
|
||||
anchor_message=anchor_message,
|
||||
reasoning=self.reasoning,
|
||||
thinking_id=self.thinking_id,
|
||||
)
|
||||
|
||||
if success:
|
||||
logger.info(f"{self.log_prefix} 成功通过replyer发送消息")
|
||||
else:
|
||||
logger.error(f"{self.log_prefix} 通过replyer发送消息失败")
|
||||
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} 通过replyer发送消息时出错: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_action_info(cls, name: str = None, description: str = None) -> "ActionInfo":
|
||||
@@ -132,12 +349,14 @@ class BaseAction(ABC):
|
||||
ActionInfo: 生成的Action信息对象
|
||||
"""
|
||||
|
||||
# 自动生成名称和描述
|
||||
# 优先使用类属性,然后自动生成
|
||||
if name is None:
|
||||
name = cls.__name__.lower().replace("action", "")
|
||||
name = getattr(cls, "action_name", cls.__name__.lower().replace("action", ""))
|
||||
if description is None:
|
||||
description = cls.__doc__ or f"{cls.__name__} Action组件"
|
||||
description = description.strip().split("\n")[0] # 取第一行作为描述
|
||||
description = getattr(cls, "action_description", None)
|
||||
if description is None:
|
||||
description = cls.__doc__ or f"{cls.__name__} Action组件"
|
||||
description = description.strip().split("\n")[0] # 取第一行作为描述
|
||||
|
||||
# 安全获取激活类型值
|
||||
def get_enum_value(attr_name, default):
|
||||
|
||||
@@ -17,24 +17,27 @@ class BaseCommand(ABC):
|
||||
- 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):
|
||||
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]")
|
||||
self.api = PluginAPI(chat_stream=message.chat_stream, log_prefix="[Command]", plugin_config=plugin_config)
|
||||
|
||||
self.log_prefix = "[Command]"
|
||||
|
||||
@@ -77,6 +80,62 @@ class BaseCommand(ABC):
|
||||
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 = str(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
|
||||
@@ -89,12 +148,14 @@ class BaseCommand(ABC):
|
||||
CommandInfo: 生成的Command信息对象
|
||||
"""
|
||||
|
||||
# 自动生成名称和描述
|
||||
# 优先使用类属性,然后自动生成
|
||||
if name is None:
|
||||
name = cls.__name__.lower().replace("command", "")
|
||||
name = getattr(cls, "command_name", cls.__name__.lower().replace("command", ""))
|
||||
if description is None:
|
||||
description = cls.__doc__ or f"{cls.__name__} Command组件"
|
||||
description = description.strip().split("\n")[0] # 取第一行作为描述
|
||||
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,
|
||||
@@ -103,4 +164,5 @@ class BaseCommand(ABC):
|
||||
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,
|
||||
)
|
||||
|
||||
@@ -86,6 +86,7 @@ class CommandInfo(ComponentInfo):
|
||||
command_pattern: str = "" # 命令匹配模式(正则表达式)
|
||||
command_help: str = "" # 命令帮助信息
|
||||
command_examples: List[str] = None # 命令使用示例
|
||||
intercept_message: bool = True # 是否拦截消息处理(默认拦截)
|
||||
|
||||
def __post_init__(self):
|
||||
super().__post_init__()
|
||||
|
||||
@@ -141,14 +141,14 @@ class ComponentRegistry:
|
||||
info = self.get_component_info(command_name)
|
||||
return info if isinstance(info, CommandInfo) else None
|
||||
|
||||
def find_command_by_text(self, text: str) -> Optional[tuple[Type, dict]]:
|
||||
def find_command_by_text(self, text: str) -> Optional[tuple[Type, dict, bool, str]]:
|
||||
"""根据文本查找匹配的命令
|
||||
|
||||
Args:
|
||||
text: 输入文本
|
||||
|
||||
Returns:
|
||||
Optional[tuple[Type, dict]]: (命令类, 匹配的命名组) 或 None
|
||||
Optional[tuple[Type, dict, bool, str]]: (命令类, 匹配的命名组, 是否拦截消息, 插件名) 或 None
|
||||
"""
|
||||
for pattern, command_class in self._command_patterns.items():
|
||||
match = pattern.match(text)
|
||||
@@ -164,7 +164,7 @@ class ComponentRegistry:
|
||||
if command_name:
|
||||
command_info = self.get_command_info(command_name)
|
||||
if command_info and command_info.enabled:
|
||||
return command_class, match.groupdict()
|
||||
return command_class, match.groupdict(), command_info.intercept_message, command_info.plugin_name
|
||||
return None
|
||||
|
||||
# === 插件管理方法 ===
|
||||
@@ -205,6 +205,20 @@ class ComponentRegistry:
|
||||
plugin_info = self.get_plugin_info(plugin_name)
|
||||
return plugin_info.components if plugin_info else []
|
||||
|
||||
def get_plugin_config(self, plugin_name: str) -> Optional[dict]:
|
||||
"""获取插件配置
|
||||
|
||||
Args:
|
||||
plugin_name: 插件名称
|
||||
|
||||
Returns:
|
||||
Optional[dict]: 插件配置字典或None
|
||||
"""
|
||||
# 从插件管理器获取插件实例的配置
|
||||
from src.plugin_system.core.plugin_manager import plugin_manager
|
||||
plugin_instance = plugin_manager.get_plugin_instance(plugin_name)
|
||||
return plugin_instance.config if plugin_instance else None
|
||||
|
||||
# === 状态管理方法 ===
|
||||
|
||||
def enable_component(self, component_name: str) -> bool:
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import Dict, List, Optional, Any, TYPE_CHECKING
|
||||
import os
|
||||
import importlib
|
||||
import importlib.util
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -72,9 +73,10 @@ class PluginManager:
|
||||
if plugin_dir:
|
||||
self.plugin_paths[plugin_name] = plugin_dir
|
||||
|
||||
if instantiate_and_register_plugin(plugin_class, plugin_dir):
|
||||
plugin_instance = plugin_class(plugin_dir=plugin_dir)
|
||||
if plugin_instance.register_plugin():
|
||||
total_registered += 1
|
||||
self.loaded_plugins[plugin_name] = plugin_class
|
||||
self.loaded_plugins[plugin_name] = plugin_instance
|
||||
|
||||
# 📊 显示插件详细信息
|
||||
plugin_info = component_registry.get_plugin_info(plugin_name)
|
||||
@@ -288,6 +290,17 @@ class PluginManager:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_plugin_instance(self, plugin_name: str) -> Optional["BasePlugin"]:
|
||||
"""获取插件实例
|
||||
|
||||
Args:
|
||||
plugin_name: 插件名称
|
||||
|
||||
Returns:
|
||||
Optional[BasePlugin]: 插件实例或None
|
||||
"""
|
||||
return self.loaded_plugins.get(plugin_name)
|
||||
|
||||
def get_plugin_stats(self) -> Dict[str, Any]:
|
||||
"""获取插件统计信息"""
|
||||
all_plugins = component_registry.get_all_plugins()
|
||||
|
||||
Reference in New Issue
Block a user