fix:修复路径遗留问题

This commit is contained in:
SengokuCola
2025-06-12 21:20:06 +08:00
parent 70d8f3642b
commit b9a04b32f6
17 changed files with 95 additions and 283 deletions

View File

@@ -172,7 +172,7 @@ ChatState.ABSENT # 离开模式
```python ```python
from typing import Tuple from typing import Tuple
from src.chat.actions.plugin_action import PluginAction, register_action from src.plugin_system.base.base_action import BaseAction as PluginAction, register_action
from src.chat.heart_flow.sub_heartflow import ChatState from src.chat.heart_flow.sub_heartflow import ChatState
@register_action @register_action

View File

@@ -1,216 +0,0 @@
import re
from abc import ABC, abstractmethod
from typing import Dict, List, Type, Optional, Tuple, Pattern
from src.common.logger import get_logger
from src.chat.message_receive.message import MessageRecv
from src.chat.focus_chat.hfc_utils import create_empty_anchor_message
from src.chat.focus_chat.expressors.default_expressor import DefaultExpressor
logger = get_logger("command_handler")
# 全局命令注册表
_COMMAND_REGISTRY: Dict[str, Type["BaseCommand"]] = {}
_COMMAND_PATTERNS: Dict[Pattern, Type["BaseCommand"]] = {}
class BaseCommand(ABC):
"""命令基类,所有自定义命令都应该继承这个类"""
# 命令的基本属性
command_name: str = "" # 命令名称
command_description: str = "" # 命令描述
command_pattern: str = "" # 命令匹配模式(正则表达式)
command_help: str = "" # 命令帮助信息
command_examples: List[str] = [] # 命令使用示例
enable_command: bool = True # 是否启用命令
def __init__(self, message: MessageRecv):
"""初始化命令处理器
Args:
message: 接收到的消息对象
"""
self.message = message
self.matched_groups: Dict[str, str] = {} # 存储正则表达式匹配的命名组
self._services = {"chat_stream": message.chat_stream} # 存储内部服务
# 日志前缀
self.log_prefix = f"[Command:{self.command_name}]"
@abstractmethod
async def execute(self) -> Tuple[bool, Optional[str]]:
"""执行命令的抽象方法,需要被子类实现
Returns:
Tuple[bool, Optional[str]]: (是否执行成功, 可选的回复消息)
"""
pass
def set_matched_groups(self, groups: Dict[str, str]) -> None:
"""设置正则表达式匹配的命名组
Args:
groups: 正则表达式匹配的命名组
"""
self.matched_groups = groups
async def send_reply(self, content: str) -> None:
"""发送回复消息
Args:
content: 回复内容
"""
try:
# 获取聊天流
chat_stream = self.message.chat_stream
if not chat_stream:
logger.error(f"{self.log_prefix} 无法发送消息缺少chat_stream")
return
# 创建空的锚定消息
anchor_message = await create_empty_anchor_message(
chat_stream.platform, chat_stream.group_info, chat_stream
)
# 创建表达器传入chat_stream参数
expressor = DefaultExpressor(chat_stream)
# 设置服务
self._services["expressor"] = expressor
# 发送消息
response_set = [
("text", content),
]
# 调用表达器发送消息
await expressor.send_response_messages(
anchor_message=anchor_message,
response_set=response_set,
display_message="",
)
logger.info(f"{self.log_prefix} 命令回复消息发送成功: {content[:30]}...")
except Exception as e:
logger.error(f"{self.log_prefix} 发送命令回复消息失败: {e}")
import traceback
logger.error(traceback.format_exc())
def register_command(cls):
"""
命令注册装饰器
用法:
@register_command
class MyCommand(BaseCommand):
command_name = "my_command"
command_description = "我的命令"
command_pattern = r"^/mycommand\s+(?P<arg1>\w+)\s+(?P<arg2>\w+)$"
...
"""
# 检查类是否有必要的属性
if (
not hasattr(cls, "command_name")
or not hasattr(cls, "command_description")
or not hasattr(cls, "command_pattern")
):
logger.error(f"命令类 {cls.__name__} 缺少必要的属性: command_name, command_description 或 command_pattern")
return cls
command_name = cls.command_name
command_pattern = cls.command_pattern
is_enabled = getattr(cls, "enable_command", True) # 默认启用命令
if not command_name or not command_pattern:
logger.error(f"命令类 {cls.__name__} 的 command_name 或 command_pattern 为空")
return cls
# 将命令类注册到全局注册表
_COMMAND_REGISTRY[command_name] = cls
# 编译正则表达式并注册
try:
pattern = re.compile(command_pattern, re.IGNORECASE | re.DOTALL)
_COMMAND_PATTERNS[pattern] = cls
logger.info(f"已注册命令: {command_name} -> {cls.__name__},命令启用: {is_enabled}")
except re.error as e:
logger.error(f"命令 {command_name} 的正则表达式编译失败: {e}")
return cls
class CommandManager:
"""命令管理器,负责处理命令(不再负责加载,加载由统一的插件加载器处理)"""
def __init__(self):
"""初始化命令管理器"""
# 命令加载现在由统一的插件加载器处理,这里只需要初始化
logger.info("命令管理器初始化完成")
async def process_command(self, message: MessageRecv) -> Tuple[bool, Optional[str], bool]:
"""处理消息中的命令
Args:
message: 接收到的消息对象
Returns:
Tuple[bool, Optional[str], bool]: (是否找到并执行了命令, 命令执行结果, 是否继续处理消息)
"""
if not message.processed_plain_text:
await message.process()
text = message.processed_plain_text
# 检查是否匹配任何命令模式
for pattern, command_cls in _COMMAND_PATTERNS.items():
match = pattern.match(text)
if match and getattr(command_cls, "enable_command", True):
# 创建命令实例
command_instance = command_cls(message)
# 提取命名组并设置
groups = match.groupdict()
command_instance.set_matched_groups(groups)
try:
# 执行命令
success, response = await command_instance.execute()
# 记录命令执行结果
if success:
logger.info(f"命令 {command_cls.command_name} 执行成功")
if response:
# 使用命令实例的send_reply方法发送回复
await command_instance.send_reply(response)
else:
logger.warning(f"命令 {command_cls.command_name} 执行失败: {response}")
if response:
# 使用命令实例的send_reply方法发送错误信息
await command_instance.send_reply(f"命令执行失败: {response}")
# 命令执行后不再继续处理消息
return True, response, False
except Exception as e:
logger.error(f"执行命令 {command_cls.command_name} 时出错: {e}")
import traceback
logger.error(traceback.format_exc())
try:
# 使用命令实例的send_reply方法发送错误信息
await command_instance.send_reply(f"命令执行出错: {str(e)}")
except Exception as send_error:
logger.error(f"发送错误消息失败: {send_error}")
# 命令执行出错后不再继续处理消息
return True, str(e), False
# 没有匹配到任何命令,继续处理消息
return False, None, True
# 创建全局命令管理器实例
command_manager = CommandManager()

View File

@@ -15,8 +15,6 @@ from src.chat.focus_chat.info.info_base import InfoBase
from src.chat.focus_chat.info_processors.chattinginfo_processor import ChattingInfoProcessor from src.chat.focus_chat.info_processors.chattinginfo_processor import ChattingInfoProcessor
from src.chat.focus_chat.info_processors.relationship_processor import RelationshipProcessor from src.chat.focus_chat.info_processors.relationship_processor import RelationshipProcessor
from src.chat.focus_chat.info_processors.working_memory_processor import WorkingMemoryProcessor from src.chat.focus_chat.info_processors.working_memory_processor import WorkingMemoryProcessor
# from src.chat.focus_chat.info_processors.action_processor import ActionProcessor
from src.chat.heart_flow.observation.hfcloop_observation import HFCloopObservation from src.chat.heart_flow.observation.hfcloop_observation import HFCloopObservation
from src.chat.heart_flow.observation.working_observation import WorkingMemoryObservation from src.chat.heart_flow.observation.working_observation import WorkingMemoryObservation
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation from src.chat.heart_flow.observation.chatting_observation import ChattingObservation

View File

@@ -1,5 +1,5 @@
from typing import Dict, List, Optional, Type, Any from typing import Dict, List, Optional, Type, Any
from src.chat.actions.base_action import BaseAction, _ACTION_REGISTRY from src.plugin_system.base.base_action import BaseAction, _ACTION_REGISTRY
from src.chat.heart_flow.observation.observation import Observation from src.chat.heart_flow.observation.observation import Observation
from src.chat.focus_chat.replyer.default_replyer import DefaultReplyer from src.chat.focus_chat.replyer.default_replyer import DefaultReplyer
from src.chat.focus_chat.expressors.default_expressor import DefaultExpressor from src.chat.focus_chat.expressors.default_expressor import DefaultExpressor

View File

@@ -6,7 +6,7 @@ from src.chat.heart_flow.observation.chatting_observation import ChattingObserva
from src.chat.message_receive.chat_stream import get_chat_manager from src.chat.message_receive.chat_stream import get_chat_manager
from src.config.config import global_config from src.config.config import global_config
from src.llm_models.utils_model import LLMRequest from src.llm_models.utils_model import LLMRequest
from src.chat.actions.base_action import ActionActivationType, ChatMode from src.plugin_system.base.base_action import ActionActivationType, ChatMode
import random import random
import asyncio import asyncio
import hashlib import hashlib

View File

@@ -15,7 +15,7 @@ from src.common.logger import get_logger
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.individuality.individuality import get_individuality from src.individuality.individuality import get_individuality
from src.chat.focus_chat.planners.action_manager import ActionManager from src.chat.focus_chat.planners.action_manager import ActionManager
from src.chat.actions.base_action import ChatMode from src.plugin_system.base.base_action import ChatMode
from json_repair import repair_json from json_repair import repair_json
from src.chat.focus_chat.planners.base_planner import BasePlanner from src.chat.focus_chat.planners.base_planner import BasePlanner
from datetime import datetime from datetime import datetime

View File

@@ -1,7 +1,7 @@
from typing import List, Any, Dict from typing import List, Any, Dict
from src.common.logger import get_logger from src.common.logger import get_logger
from src.chat.focus_chat.planners.action_manager import ActionManager from src.chat.focus_chat.planners.action_manager import ActionManager
from src.chat.actions.base_action import ActionActivationType, ChatMode from src.plugin_system.base.base_action import ActionActivationType, ChatMode
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
from src.config.config import global_config from src.config.config import global_config
import random import random

View File

@@ -7,7 +7,7 @@ from src.common.logger import get_logger
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.individuality.individuality import get_individuality from src.individuality.individuality import get_individuality
from src.chat.focus_chat.planners.action_manager import ActionManager from src.chat.focus_chat.planners.action_manager import ActionManager
from src.chat.actions.base_action import ChatMode from src.plugin_system.base.base_action import ChatMode
from src.chat.message_receive.message import MessageThinking from src.chat.message_receive.message import MessageThinking
from json_repair import repair_json from json_repair import repair_json
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat

View File

@@ -112,7 +112,7 @@ class BaseAction(ABC):
return attr.value return attr.value
return str(attr) return str(attr)
async def send_reply(self, content: str) -> bool: async def send_text(self, content: str) -> bool:
"""发送回复消息 """发送回复消息
Args: Args:
@@ -137,7 +137,7 @@ class BaseAction(ABC):
text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform
) )
async def send_type_reply(self, type: str, text: str) -> bool: async def send_type(self, type: str, text: str) -> bool:
"""发送回复消息 """发送回复消息
Args: Args:
@@ -173,7 +173,7 @@ class BaseAction(ABC):
async def send_command(self, command_name: str, args: dict = None, display_message: str = None) -> bool: async def send_command(self, command_name: str, args: dict = None, display_message: str = None) -> bool:
"""发送命令消息 """发送命令消息
使用和send_reply相同的方式通过MessageAPI发送命令 使用和send_text相同的方式通过MessageAPI发送命令
Args: Args:
command_name: 命令名称 command_name: 命令名称

View File

@@ -60,7 +60,7 @@ class BaseCommand(ABC):
""" """
pass pass
async def send_reply(self, content: str) -> None: async def send_text(self, content: str) -> None:
"""发送回复消息 """发送回复消息
Args: Args:
@@ -80,10 +80,45 @@ class BaseCommand(ABC):
text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform
) )
async def send_type(self, message_type: str, content: str, display_message: str = None) -> bool:
"""发送指定类型的回复消息到当前聊天环境
Args:
message_type: 消息类型,如"text""image""emoji"
content: 消息内容
display_message: 显示消息(可选)
Returns:
bool: 是否发送成功
"""
# 获取聊天流信息
chat_stream = self.message.chat_stream
if chat_stream.group_info:
# 群聊
return await self.api.send_message_to_target(
message_type=message_type,
content=content,
platform=chat_stream.platform,
target_id=str(chat_stream.group_info.group_id),
is_group=True,
display_message=display_message,
)
else:
# 私聊
return await self.api.send_message_to_target(
message_type=message_type,
content=content,
platform=chat_stream.platform,
target_id=str(chat_stream.user_info.user_id),
is_group=False,
display_message=display_message,
)
async def send_command(self, command_name: str, args: dict = None, display_message: str = None) -> bool: async def send_command(self, command_name: str, args: dict = None, display_message: str = None) -> bool:
"""发送命令消息 """发送命令消息
使用和send_reply相同的方式通过MessageAPI发送命令 使用和send_text相同的方式通过MessageAPI发送命令
Args: Args:
command_name: 命令名称 command_name: 命令名称

View File

@@ -378,7 +378,7 @@ class PingCommand(BaseCommand):
message = self.matched_groups.get("message", "") message = self.matched_groups.get("message", "")
reply_text = f"🏓 Pong! {message}" if message else "🏓 Pong!" reply_text = f"🏓 Pong! {message}" if message else "🏓 Pong!"
await self.send_reply(reply_text) await self.send_text(reply_text)
return True, f"发送ping响应: {reply_text}" return True, f"发送ping响应: {reply_text}"
except Exception as e: except Exception as e:

View File

@@ -105,14 +105,14 @@ class DoubaoImageGenerationAction(BaseAction):
if not (http_base_url and http_api_key): if not (http_base_url and http_api_key):
error_msg = "抱歉图片生成功能所需的HTTP配置如API地址或密钥不完整无法提供服务。" error_msg = "抱歉图片生成功能所需的HTTP配置如API地址或密钥不完整无法提供服务。"
await self.send_reply(error_msg) await self.send_text(error_msg)
logger.error(f"{self.log_prefix} HTTP调用配置缺失: base_url 或 volcano_generate_api_key.") logger.error(f"{self.log_prefix} HTTP调用配置缺失: base_url 或 volcano_generate_api_key.")
return False, "HTTP配置不完整" return False, "HTTP配置不完整"
# API密钥验证 # API密钥验证
if http_api_key == "YOUR_DOUBAO_API_KEY_HERE": if http_api_key == "YOUR_DOUBAO_API_KEY_HERE":
error_msg = "图片生成功能尚未配置请设置正确的API密钥。" error_msg = "图片生成功能尚未配置请设置正确的API密钥。"
await self.send_reply(error_msg) await self.send_text(error_msg)
logger.error(f"{self.log_prefix} API密钥未配置") logger.error(f"{self.log_prefix} API密钥未配置")
return False, "API密钥未配置" return False, "API密钥未配置"
@@ -120,7 +120,7 @@ class DoubaoImageGenerationAction(BaseAction):
description = self.action_data.get("description") description = self.action_data.get("description")
if not description or not description.strip(): if not description or not description.strip():
logger.warning(f"{self.log_prefix} 图片描述为空,无法生成图片。") logger.warning(f"{self.log_prefix} 图片描述为空,无法生成图片。")
await self.send_reply("你需要告诉我想要画什么样的图片哦~ 比如说'画一只可爱的小猫'") await self.send_text("你需要告诉我想要画什么样的图片哦~ 比如说'画一只可爱的小猫'")
return False, "图片描述为空" return False, "图片描述为空"
# 清理和验证描述 # 清理和验证描述
@@ -143,12 +143,12 @@ class DoubaoImageGenerationAction(BaseAction):
if cache_key in self._request_cache: if cache_key in self._request_cache:
cached_result = self._request_cache[cache_key] cached_result = self._request_cache[cache_key]
logger.info(f"{self.log_prefix} 使用缓存的图片结果") logger.info(f"{self.log_prefix} 使用缓存的图片结果")
await self.send_reply("我之前画过类似的图片,用之前的结果~") await self.send_text("我之前画过类似的图片,用之前的结果~")
# 直接发送缓存的结果 # 直接发送缓存的结果
send_success = await self._send_image(cached_result) send_success = await self._send_image(cached_result)
if send_success: if send_success:
await self.send_reply("图片已发送!") await self.send_text("图片已发送!")
return True, "图片已发送(缓存)" return True, "图片已发送(缓存)"
else: else:
# 缓存失败,清除这个缓存项并继续正常流程 # 缓存失败,清除这个缓存项并继续正常流程
@@ -159,7 +159,7 @@ class DoubaoImageGenerationAction(BaseAction):
seed_val = self._get_seed() seed_val = self._get_seed()
watermark_val = self._get_watermark() watermark_val = self._get_watermark()
await self.send_reply( await self.send_text(
f"收到!正在为您生成关于 '{description}' 的图片,请稍候...(模型: {default_model}, 尺寸: {image_size}" f"收到!正在为您生成关于 '{description}' 的图片,请稍候...(模型: {default_model}, 尺寸: {image_size}"
) )

View File

@@ -97,13 +97,13 @@ class MuteAction(BaseAction):
if not target: if not target:
error_msg = "禁言目标不能为空" error_msg = "禁言目标不能为空"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("没有指定禁言对象呢~") await self.send_text("没有指定禁言对象呢~")
return False, error_msg return False, error_msg
if not duration: if not duration:
error_msg = "禁言时长不能为空" error_msg = "禁言时长不能为空"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("没有指定禁言时长呢~") await self.send_text("没有指定禁言时长呢~")
return False, error_msg return False, error_msg
# 获取时长限制配置 # 获取时长限制配置
@@ -116,7 +116,7 @@ class MuteAction(BaseAction):
if duration_int <= 0: if duration_int <= 0:
error_msg = "禁言时长必须大于0" error_msg = "禁言时长必须大于0"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("禁言时长必须是正数哦~") await self.send_text("禁言时长必须是正数哦~")
return False, error_msg return False, error_msg
# 限制禁言时长范围 # 限制禁言时长范围
@@ -130,7 +130,7 @@ class MuteAction(BaseAction):
except (ValueError, TypeError): except (ValueError, TypeError):
error_msg = f"禁言时长格式无效: {duration}" error_msg = f"禁言时长格式无效: {duration}"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("禁言时长必须是数字哦~") await self.send_text("禁言时长必须是数字哦~")
return False, error_msg return False, error_msg
# 获取用户ID # 获取用户ID
@@ -139,12 +139,12 @@ class MuteAction(BaseAction):
except Exception as e: except Exception as e:
error_msg = f"查找用户ID时出错: {e}" error_msg = f"查找用户ID时出错: {e}"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("查找用户信息时出现问题~") await self.send_text("查找用户信息时出现问题~")
return False, error_msg return False, error_msg
if not user_id: if not user_id:
error_msg = f"未找到用户 {target} 的ID" error_msg = f"未找到用户 {target} 的ID"
await self.send_reply(f"找不到 {target} 这个人呢~") await self.send_text(f"找不到 {target} 这个人呢~")
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
return False, error_msg return False, error_msg
@@ -154,7 +154,7 @@ class MuteAction(BaseAction):
# 获取模板化消息 # 获取模板化消息
message = self._get_template_message(target, time_str, reason) message = self._get_template_message(target, time_str, reason)
# await self.send_reply(message) # await self.send_text(message)
await self.send_message_by_expressor(message) await self.send_message_by_expressor(message)
# 发送群聊禁言命令 # 发送群聊禁言命令
@@ -170,7 +170,7 @@ class MuteAction(BaseAction):
else: else:
error_msg = "发送禁言命令失败" error_msg = "发送禁言命令失败"
logger.error(f"{self.log_prefix} {error_msg}") logger.error(f"{self.log_prefix} {error_msg}")
await self.send_reply("执行禁言动作失败") await self.send_text("执行禁言动作失败")
return False, error_msg return False, error_msg
def _get_template_message(self, target: str, duration_str: str, reason: str) -> str: def _get_template_message(self, target: str, duration_str: str, reason: str) -> str:
@@ -237,7 +237,7 @@ class MuteCommand(BaseCommand):
reason = self.matched_groups.get("reason", "管理员操作") reason = self.matched_groups.get("reason", "管理员操作")
if not all([target, duration]): if not all([target, duration]):
await self.send_reply("❌ 命令参数不完整,请检查格式") await self.send_text("❌ 命令参数不完整,请检查格式")
return False, "参数不完整" return False, "参数不完整"
# 获取时长限制配置 # 获取时长限制配置
@@ -248,19 +248,19 @@ class MuteCommand(BaseCommand):
try: try:
duration_int = int(duration) duration_int = int(duration)
if duration_int <= 0: if duration_int <= 0:
await self.send_reply("❌ 禁言时长必须大于0") await self.send_text("❌ 禁言时长必须大于0")
return False, "时长无效" return False, "时长无效"
# 限制禁言时长范围 # 限制禁言时长范围
if duration_int < min_duration: if duration_int < min_duration:
duration_int = min_duration duration_int = min_duration
await self.send_reply(f"⚠️ 禁言时长过短,调整为{min_duration}") await self.send_text(f"⚠️ 禁言时长过短,调整为{min_duration}")
elif duration_int > max_duration: elif duration_int > max_duration:
duration_int = max_duration duration_int = max_duration
await self.send_reply(f"⚠️ 禁言时长过长,调整为{max_duration}") await self.send_text(f"⚠️ 禁言时长过长,调整为{max_duration}")
except ValueError: except ValueError:
await self.send_reply("❌ 禁言时长必须是数字") await self.send_text("❌ 禁言时长必须是数字")
return False, "时长格式错误" return False, "时长格式错误"
# 获取用户ID # 获取用户ID
@@ -268,11 +268,11 @@ class MuteCommand(BaseCommand):
platform, user_id = await self.api.get_user_id_by_person_name(target) platform, user_id = await self.api.get_user_id_by_person_name(target)
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 查找用户ID时出错: {e}") logger.error(f"{self.log_prefix} 查找用户ID时出错: {e}")
await self.send_reply("❌ 查找用户信息时出现问题") await self.send_text("❌ 查找用户信息时出现问题")
return False, str(e) return False, str(e)
if not user_id: if not user_id:
await self.send_reply(f"❌ 找不到用户: {target}") await self.send_text(f"❌ 找不到用户: {target}")
return False, "用户不存在" return False, "用户不存在"
# 格式化时长显示 # 格式化时长显示
@@ -291,17 +291,17 @@ class MuteCommand(BaseCommand):
if success: if success:
# 获取并发送模板化消息 # 获取并发送模板化消息
message = self._get_template_message(target, time_str, reason) message = self._get_template_message(target, time_str, reason)
await self.send_reply(message) await self.send_text(message)
logger.info(f"{self.log_prefix} 成功禁言 {target}({user_id}),时长 {duration_int}") logger.info(f"{self.log_prefix} 成功禁言 {target}({user_id}),时长 {duration_int}")
return True, f"成功禁言 {target},时长 {time_str}" return True, f"成功禁言 {target},时长 {time_str}"
else: else:
await self.send_reply("❌ 发送禁言命令失败") await self.send_text("❌ 发送禁言命令失败")
return False, "发送禁言命令失败" return False, "发送禁言命令失败"
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 禁言命令执行失败: {e}") logger.error(f"{self.log_prefix} 禁言命令执行失败: {e}")
await self.send_reply(f"❌ 禁言命令错误: {str(e)}") await self.send_text(f"❌ 禁言命令错误: {str(e)}")
return False, str(e) return False, str(e)
def _get_template_message(self, target: str, duration_str: str, reason: str) -> str: def _get_template_message(self, target: str, duration_str: str, reason: str) -> str:

View File

@@ -1,6 +1,6 @@
from src.common.logger import get_logger from src.common.logger import get_logger
from src.chat.actions.base_action import ActionActivationType from src.plugin_system.base.base_action import ActionActivationType
from src.chat.actions.plugin_action import PluginAction, register_action from src.plugin_system.base.base_action import BaseAction as PluginAction, register_action
from typing import Tuple from typing import Tuple
logger = get_logger("tts_action") logger = get_logger("tts_action")

View File

@@ -1,5 +1,6 @@
from src.common.logger import get_logger from src.common.logger import get_logger
from src.chat.actions.plugin_action import PluginAction, register_action, ActionActivationType from src.plugin_system.base.base_action import BaseAction as PluginAction, ActionActivationType
from src.plugin_system.base.base_action import register_action
from typing import Tuple from typing import Tuple
logger = get_logger("vtb_action") logger = get_logger("vtb_action")

View File

@@ -157,12 +157,6 @@ src/plugins/built_in/example_comprehensive/
此插件展示了从旧插件系统到新插件系统的完整升级: 此插件展示了从旧插件系统到新插件系统的完整升级:
### 旧系统特征
- 使用 `@register_command` 装饰器
- 继承旧的 `BaseCommand`
- 硬编码的消息处理逻辑
- 有限的配置支持
### 新系统特征 ### 新系统特征
- 使用统一的组件注册机制 - 使用统一的组件注册机制
- 新的 `BaseAction``BaseCommand` 基类 - 新的 `BaseAction``BaseCommand` 基类

View File

@@ -82,7 +82,7 @@ class ComprehensiveHelpCommand(BaseCommand):
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 帮助命令执行失败: {e}") logger.error(f"{self.log_prefix} 帮助命令执行失败: {e}")
await self.send_reply(f"❌ 帮助系统错误: {str(e)}") await self.send_text(f"❌ 帮助系统错误: {str(e)}")
return False, str(e) return False, str(e)
async def _show_specific_help(self, command_name: str) -> Tuple[bool, str]: async def _show_specific_help(self, command_name: str) -> Tuple[bool, str]:
@@ -115,7 +115,7 @@ class ComprehensiveHelpCommand(BaseCommand):
{chr(10).join(f"{example}" for example in info["examples"])} {chr(10).join(f"{example}" for example in info["examples"])}
""".strip() """.strip()
await self.send_reply(response) await self.send_text(response)
return True, response return True, response
async def _show_all_commands(self) -> Tuple[bool, str]: async def _show_all_commands(self) -> Tuple[bool, str]:
@@ -143,7 +143,7 @@ class ComprehensiveHelpCommand(BaseCommand):
💡 使用 /help <命令名> 获取特定命令的详细说明 💡 使用 /help <命令名> 获取特定命令的详细说明
""".strip() """.strip()
await self.send_reply(help_text) await self.send_text(help_text)
return True, help_text return True, help_text
@@ -167,13 +167,13 @@ class MessageSendCommand(BaseCommand):
content = self.matched_groups.get("content") content = self.matched_groups.get("content")
if not all([target_type, target_id, content]): if not all([target_type, target_id, content]):
await self.send_reply("❌ 命令参数不完整,请检查格式") await self.send_text("❌ 命令参数不完整,请检查格式")
return False, "参数不完整" return False, "参数不完整"
# 长度限制检查 # 长度限制检查
max_length = self.api.get_config("send.max_message_length", 500) max_length = self.api.get_config("send.max_message_length", 500)
if len(content) > max_length: if len(content) > max_length:
await self.send_reply(f"❌ 消息过长,最大长度: {max_length} 字符") await self.send_text(f"❌ 消息过长,最大长度: {max_length} 字符")
return False, "消息过长" return False, "消息过长"
logger.info(f"{self.log_prefix} 发送消息: {target_type}:{target_id} -> {content[:50]}...") logger.info(f"{self.log_prefix} 发送消息: {target_type}:{target_id} -> {content[:50]}...")
@@ -186,23 +186,23 @@ class MessageSendCommand(BaseCommand):
success = await self.api.send_text_to_user(text=content, user_id=target_id, platform="qq") success = await self.api.send_text_to_user(text=content, user_id=target_id, platform="qq")
target_desc = f"用户 {target_id}" target_desc = f"用户 {target_id}"
else: else:
await self.send_reply(f"❌ 不支持的目标类型: {target_type}") await self.send_text(f"❌ 不支持的目标类型: {target_type}")
return False, f"不支持的目标类型: {target_type}" return False, f"不支持的目标类型: {target_type}"
# 返回结果 # 返回结果
if success: if success:
response = f"✅ 消息已成功发送到 {target_desc}" response = f"✅ 消息已成功发送到 {target_desc}"
await self.send_reply(response) await self.send_text(response)
return True, response return True, response
else: else:
response = f"❌ 消息发送失败,目标 {target_desc} 可能不存在" response = f"❌ 消息发送失败,目标 {target_desc} 可能不存在"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 消息发送失败: {e}") logger.error(f"{self.log_prefix} 消息发送失败: {e}")
error_msg = f"❌ 发送失败: {str(e)}" error_msg = f"❌ 发送失败: {str(e)}"
await self.send_reply(error_msg) await self.send_text(error_msg)
return False, str(e) return False, str(e)
@@ -232,15 +232,15 @@ class DiceCommand(BaseCommand):
count = int(count_str) count = int(count_str)
if count <= 0: if count <= 0:
response = "❌ 骰子数量必须大于0" response = "❌ 骰子数量必须大于0"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
if count > 10: # 限制最大数量 if count > 10: # 限制最大数量
response = "❌ 一次最多只能掷10个骰子" response = "❌ 一次最多只能掷10个骰子"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
except ValueError: except ValueError:
response = "❌ 骰子数量必须是整数" response = "❌ 骰子数量必须是整数"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
# 生成随机数 # 生成随机数
@@ -254,13 +254,13 @@ class DiceCommand(BaseCommand):
total = sum(results) total = sum(results)
message = f"🎲 掷出了 {count} 个骰子: [{dice_results}],总点数: {total}" message = f"🎲 掷出了 {count} 个骰子: [{dice_results}],总点数: {total}"
await self.send_reply(message) await self.send_text(message)
logger.info(f"{self.log_prefix} 执行骰子命令: {message}") logger.info(f"{self.log_prefix} 执行骰子命令: {message}")
return True, message return True, message
except Exception as e: except Exception as e:
error_msg = f"❌ 执行命令时出错: {str(e)}" error_msg = f"❌ 执行命令时出错: {str(e)}"
await self.send_reply(error_msg) await self.send_text(error_msg)
logger.error(f"{self.log_prefix} 执行骰子命令时出错: {e}") logger.error(f"{self.log_prefix} 执行骰子命令时出错: {e}")
return False, error_msg return False, error_msg
@@ -280,14 +280,14 @@ class EchoCommand(BaseCommand):
if not message: if not message:
response = "❌ 请提供要重复的消息!用法:/echo <消息内容>" response = "❌ 请提供要重复的消息!用法:/echo <消息内容>"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
# 检查消息长度限制 # 检查消息长度限制
max_length = self.api.get_config("echo.max_length", 200) max_length = self.api.get_config("echo.max_length", 200)
if len(message) > max_length: if len(message) > max_length:
response = f"❌ 消息过长,最大长度: {max_length} 字符" response = f"❌ 消息过长,最大长度: {max_length} 字符"
await self.send_reply(response) await self.send_text(response)
return False, response return False, response
# 格式化回声消息 # 格式化回声消息
@@ -297,14 +297,14 @@ class EchoCommand(BaseCommand):
else: else:
response = message response = message
await self.send_reply(response) await self.send_text(response)
logger.info(f"{self.log_prefix} 回声消息: {message}") logger.info(f"{self.log_prefix} 回声消息: {message}")
return True, response return True, response
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 回声命令失败: {e}") logger.error(f"{self.log_prefix} 回声命令失败: {e}")
error_msg = f"❌ 回声失败: {str(e)}" error_msg = f"❌ 回声失败: {str(e)}"
await self.send_reply(error_msg) await self.send_text(error_msg)
return False, str(e) return False, str(e)
@@ -369,14 +369,14 @@ class MessageInfoCommand(BaseCommand):
) )
response = "\n".join(info_parts) response = "\n".join(info_parts)
await self.send_reply(response) await self.send_text(response)
logger.info(f"{self.log_prefix} 显示消息信息: {user_info.user_id}") logger.info(f"{self.log_prefix} 显示消息信息: {user_info.user_id}")
return True, response return True, response
except Exception as e: except Exception as e:
logger.error(f"{self.log_prefix} 消息信息查询失败: {e}") logger.error(f"{self.log_prefix} 消息信息查询失败: {e}")
error_msg = f"❌ 信息查询失败: {str(e)}" error_msg = f"❌ 信息查询失败: {str(e)}"
await self.send_reply(error_msg) await self.send_text(error_msg)
return False, str(e) return False, str(e)