修复代码格式和文件名大小写问题

This commit is contained in:
Windpicker-owo
2025-08-31 20:50:17 +08:00
parent a187130613
commit fe472dff60
213 changed files with 6897 additions and 8252 deletions

View File

@@ -76,7 +76,7 @@ class ChatBot:
self.heartflow_message_receiver = HeartFCMessageReceiver() # 新增
self.s4u_message_processor = S4UMessageProcessor()
# 初始化反注入系统
self._initialize_anti_injector()
@@ -84,10 +84,12 @@ class ChatBot:
"""初始化反注入系统"""
try:
initialize_anti_injector()
anti_injector_logger.info(f"反注入系统已初始化 - 启用: {global_config.anti_prompt_injection.enabled}, "
f"模式: {global_config.anti_prompt_injection.process_mode}, "
f"规则: {global_config.anti_prompt_injection.enabled_rules}, LLM: {global_config.anti_prompt_injection.enabled_LLM}")
anti_injector_logger.info(
f"反注入系统已初始化 - 启用: {global_config.anti_prompt_injection.enabled}, "
f"模式: {global_config.anti_prompt_injection.process_mode}, "
f"规则: {global_config.anti_prompt_injection.enabled_rules}, LLM: {global_config.anti_prompt_injection.enabled_LLM}"
)
except Exception as e:
anti_injector_logger.error(f"反注入系统初始化失败: {e}")
@@ -102,56 +104,61 @@ class ChatBot:
"""独立处理PlusCommand系统"""
try:
text = message.processed_plain_text
# 获取配置的命令前缀
from src.config.config import global_config
prefixes = global_config.command.command_prefixes
# 检查是否以任何前缀开头
matched_prefix = None
for prefix in prefixes:
if text.startswith(prefix):
matched_prefix = prefix
break
if not matched_prefix:
return False, None, True # 不是命令,继续处理
# 移除前缀
command_part = text[len(matched_prefix):].strip()
command_part = text[len(matched_prefix) :].strip()
# 分离命令名和参数
parts = command_part.split(None, 1)
if not parts:
return False, None, True # 没有命令名,继续处理
command_word = parts[0].lower()
args_text = parts[1] if len(parts) > 1 else ""
# 查找匹配的PlusCommand
plus_command_registry = component_registry.get_plus_command_registry()
matching_commands = []
for plus_command_name, plus_command_class in plus_command_registry.items():
plus_command_info = component_registry.get_registered_plus_command_info(plus_command_name)
if not plus_command_info:
continue
# 检查命令名是否匹配(命令名和别名)
all_commands = [plus_command_name.lower()] + [alias.lower() for alias in plus_command_info.command_aliases]
all_commands = [plus_command_name.lower()] + [
alias.lower() for alias in plus_command_info.command_aliases
]
if command_word in all_commands:
matching_commands.append((plus_command_class, plus_command_info, plus_command_name))
if not matching_commands:
return False, None, True # 没有找到匹配的PlusCommand继续处理
# 如果有多个匹配,按优先级排序
if len(matching_commands) > 1:
matching_commands.sort(key=lambda x: x[1].priority, reverse=True)
logger.warning(f"文本 '{text}' 匹配到多个PlusCommand: {[cmd[2] for cmd in matching_commands]},使用优先级最高的")
logger.warning(
f"文本 '{text}' 匹配到多个PlusCommand: {[cmd[2] for cmd in matching_commands]},使用优先级最高的"
)
plus_command_class, plus_command_info, plus_command_name = matching_commands[0]
# 检查命令是否被禁用
if (
message.chat_stream
@@ -161,51 +168,54 @@ class ChatBot:
):
logger.info("用户禁用的PlusCommand跳过处理")
return False, None, True
message.is_command = True
# 获取插件配置
plugin_config = component_registry.get_plugin_config(plus_command_name)
# 创建PlusCommand实例
plus_command_instance = plus_command_class(message, plugin_config)
try:
# 检查聊天类型限制
if not plus_command_instance.is_chat_type_allowed():
is_group = hasattr(message, 'is_group_message') and message.is_group_message
logger.info(f"PlusCommand {plus_command_class.__name__} 不支持当前聊天类型: {'群聊' if is_group else '私聊'}")
is_group = hasattr(message, "is_group_message") and message.is_group_message
logger.info(
f"PlusCommand {plus_command_class.__name__} 不支持当前聊天类型: {'群聊' if is_group else '私聊'}"
)
return False, None, True # 跳过此命令,继续处理其他消息
# 设置参数
from src.plugin_system.base.command_args import CommandArgs
command_args = CommandArgs(args_text)
plus_command_instance.args = command_args
# 执行命令
success, response, intercept_message = await plus_command_instance.execute(command_args)
# 记录命令执行结果
if success:
logger.info(f"PlusCommand执行成功: {plus_command_class.__name__} (拦截: {intercept_message})")
else:
logger.warning(f"PlusCommand执行失败: {plus_command_class.__name__} - {response}")
# 根据命令的拦截设置决定是否继续处理消息
return True, response, not intercept_message # 找到命令根据intercept_message决定是否继续
except Exception as e:
logger.error(f"执行PlusCommand时出错: {plus_command_class.__name__} - {e}")
logger.error(traceback.format_exc())
try:
await plus_command_instance.send_text(f"命令执行出错: {str(e)}")
except Exception as send_error:
logger.error(f"发送错误消息失败: {send_error}")
# 命令出错时,根据命令的拦截设置决定是否继续处理消息
return True, str(e), False # 出错时继续处理消息
except Exception as e:
logger.error(f"处理PlusCommand时出错: {e}")
return False, None, True # 出错时继续处理消息
@@ -243,10 +253,12 @@ class ChatBot:
try:
# 检查聊天类型限制
if not command_instance.is_chat_type_allowed():
is_group = hasattr(message, 'is_group_message') and message.is_group_message
logger.info(f"命令 {command_class.__name__} 不支持当前聊天类型: {'群聊' if is_group else '私聊'}")
is_group = hasattr(message, "is_group_message") and message.is_group_message
logger.info(
f"命令 {command_class.__name__} 不支持当前聊天类型: {'群聊' if is_group else '私聊'}"
)
return False, None, True # 跳过此命令,继续处理其他消息
# 执行命令
success, response, intercept_message = await command_instance.execute()
@@ -285,9 +297,9 @@ class ChatBot:
# print(message)
return True
# 处理适配器响应消息
if hasattr(message, 'message_segment') and message.message_segment:
if hasattr(message, "message_segment") and message.message_segment:
if message.message_segment.type == "adapter_response":
await self.handle_adapter_response(message)
return True
@@ -295,24 +307,24 @@ class ChatBot:
# 适配器命令消息不需要进一步处理
logger.debug("收到适配器命令消息,跳过后续处理")
return True
return False
async def handle_adapter_response(self, message: MessageRecv):
"""处理适配器命令响应"""
try:
from src.plugin_system.apis.send_api import put_adapter_response
seg_data = message.message_segment.data
request_id = seg_data.get("request_id")
response_data = seg_data.get("response")
if request_id and response_data:
logger.debug(f"收到适配器响应: request_id={request_id}")
put_adapter_response(request_id, response_data)
else:
logger.warning("适配器响应消息格式不正确")
except Exception as e:
logger.error(f"处理适配器响应时出错: {e}")
@@ -356,7 +368,7 @@ class ChatBot:
try:
# 首先处理可能的切片消息重组
from src.utils.message_chunker import reassembler
# 尝试重组切片消息
reassembled_message = await reassembler.process_chunk(message_data)
if reassembled_message is None:
@@ -367,7 +379,7 @@ class ChatBot:
# 消息已被重组,使用重组后的消息
logger.info("使用重组后的完整消息进行处理")
message_data = reassembled_message
# 确保所有任务已启动
await self._ensure_started()
@@ -389,7 +401,8 @@ class ChatBot:
# logger.debug(str(message_data))
message = MessageRecv(message_data)
if await self.handle_notice_message(message): ...
if await self.handle_notice_message(message):
...
group_info = message.message_info.group_info
user_info = message.message_info.user_info
@@ -411,7 +424,7 @@ class ChatBot:
# 处理消息内容,生成纯文本
await message.process()
# 过滤检查
if _check_ban_words(message.processed_plain_text, chat, user_info) or _check_ban_regex( # type: ignore
message.raw_message, # type: ignore
@@ -422,26 +435,26 @@ class ChatBot:
# 命令处理 - 首先尝试PlusCommand独立处理
is_plus_command, plus_cmd_result, plus_continue_process = await self._process_plus_commands(message)
# 如果是PlusCommand且不需要继续处理则直接返回
if is_plus_command and not plus_continue_process:
await MessageStorage.store_message(message, chat)
logger.info(f"PlusCommand处理完成跳过后续消息处理: {plus_cmd_result}")
return
# 如果不是PlusCommand尝试传统的BaseCommand处理
if not is_plus_command:
is_command, cmd_result, continue_process = await self._process_commands_with_new_system(message)
# 如果是命令且不需要继续处理,则直接返回
if is_command and not continue_process:
await MessageStorage.store_message(message, chat)
logger.info(f"命令处理完成,跳过后续消息处理: {cmd_result}")
return
result = await event_manager.trigger_event(EventType.ON_MESSAGE,plugin_name="SYSTEM",message=message)
result = await event_manager.trigger_event(EventType.ON_MESSAGE, plugin_name="SYSTEM", message=message)
if not result.all_continue_process():
raise UserWarning(f"插件{result.get_summary().get('stopped_handlers','')}于消息到达时取消了消息处理")
raise UserWarning(f"插件{result.get_summary().get('stopped_handlers', '')}于消息到达时取消了消息处理")
# 确认从接口发来的message是否有自定义的prompt模板信息
if message.message_info.template_info and not message.message_info.template_info.template_default:

View File

@@ -13,6 +13,7 @@ from sqlalchemy.dialects.mysql import insert as mysql_insert
from src.common.database.sqlalchemy_models import ChatStreams # 新增导入
from src.common.database.sqlalchemy_database_api import get_db_session
from src.config.config import global_config # 新增导入
# 避免循环导入使用TYPE_CHECKING进行类型提示
if TYPE_CHECKING:
from .message import MessageRecv
@@ -23,6 +24,7 @@ install(extra_lines=3)
logger = get_logger("chat_stream")
class ChatMessageContext:
"""聊天消息上下文,存储消息的上下文信息"""
@@ -131,11 +133,11 @@ class ChatManager:
self.streams: Dict[str, ChatStream] = {} # stream_id -> ChatStream
self.last_messages: Dict[str, "MessageRecv"] = {} # stream_id -> last_message
# try:
# with get_db_session() as session:
# db.connect(reuse_if_open=True)
# # 确保 ChatStreams 表存在
# session.execute(text("CREATE TABLE IF NOT EXISTS chat_streams (stream_id TEXT PRIMARY KEY, platform TEXT, create_time REAL, last_active_time REAL, user_platform TEXT, user_id TEXT, user_nickname TEXT, user_cardname TEXT, group_platform TEXT, group_id TEXT, group_name TEXT)"))
# session.commit()
# with get_db_session() as session:
# db.connect(reuse_if_open=True)
# # 确保 ChatStreams 表存在
# session.execute(text("CREATE TABLE IF NOT EXISTS chat_streams (stream_id TEXT PRIMARY KEY, platform TEXT, create_time REAL, last_active_time REAL, user_platform TEXT, user_id TEXT, user_nickname TEXT, user_cardname TEXT, group_platform TEXT, group_id TEXT, group_name TEXT)"))
# session.commit()
# except Exception as e:
# logger.error(f"数据库连接或 ChatStreams 表创建失败: {e}")
@@ -351,10 +353,7 @@ class ChatManager:
# 根据数据库类型选择插入语句
if global_config.database.database_type == "sqlite":
stmt = sqlite_insert(ChatStreams).values(stream_id=s_data_dict["stream_id"], **fields_to_save)
stmt = stmt.on_conflict_do_update(
index_elements=['stream_id'],
set_=fields_to_save
)
stmt = stmt.on_conflict_do_update(index_elements=["stream_id"], set_=fields_to_save)
elif global_config.database.database_type == "mysql":
stmt = mysql_insert(ChatStreams).values(stream_id=s_data_dict["stream_id"], **fields_to_save)
stmt = stmt.on_duplicate_key_update(
@@ -363,10 +362,7 @@ class ChatManager:
else:
# 默认使用通用插入尝试SQLite语法
stmt = sqlite_insert(ChatStreams).values(stream_id=s_data_dict["stream_id"], **fields_to_save)
stmt = stmt.on_conflict_do_update(
index_elements=['stream_id'],
set_=fields_to_save
)
stmt = stmt.on_conflict_do_update(index_elements=["stream_id"], set_=fields_to_save)
session.execute(stmt)
session.commit()

View File

@@ -203,12 +203,12 @@ class MessageRecv(Message):
self.is_voice = False
self.is_video = True
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
# 检查视频分析功能是否可用
if not is_video_analysis_available():
logger.warning("⚠️ Rust视频处理模块不可用跳过视频分析")
return "[视频]"
if global_config.video_analysis.enable:
logger.info("已启用视频识别,开始识别")
if isinstance(segment.data, dict):
@@ -216,25 +216,23 @@ class MessageRecv(Message):
# 从Adapter接收的视频数据
video_base64 = segment.data.get("base64")
filename = segment.data.get("filename", "video.mp4")
logger.info(f"视频文件名: {filename}")
logger.info(f"Base64数据长度: {len(video_base64) if video_base64 else 0}")
if video_base64:
# 解码base64视频数据
video_bytes = base64.b64decode(video_base64)
logger.info(f"解码后视频大小: {len(video_bytes)} 字节")
# 使用video analyzer分析视频
video_analyzer = get_video_analyzer()
result = await video_analyzer.analyze_video_from_bytes(
video_bytes,
filename,
prompt=global_config.video_analysis.batch_analysis_prompt
video_bytes, filename, prompt=global_config.video_analysis.batch_analysis_prompt
)
logger.info(f"视频分析结果: {result}")
# 返回视频分析结果
summary = result.get("summary", "")
if summary:
@@ -247,6 +245,7 @@ class MessageRecv(Message):
except Exception as e:
logger.error(f"视频处理失败: {str(e)}")
import traceback
logger.error(f"错误详情: {traceback.format_exc()}")
return "[收到视频,但处理时出现错误]"
else:
@@ -278,9 +277,9 @@ class MessageRecvS4U(MessageRecv):
self.is_screen = False
self.is_internal = False
self.voice_done = None
self.chat_info = None
async def process(self) -> None:
self.processed_plain_text = await self._process_message_segments(self.message_segment)
@@ -382,14 +381,14 @@ class MessageRecvS4U(MessageRecv):
self.is_voice = False
self.is_picid = False
self.is_emoji = False
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
# 检查视频分析功能是否可用
if not is_video_analysis_available():
logger.warning("⚠️ Rust视频处理模块不可用跳过视频分析")
return "[视频]"
if global_config.video_analysis.enable:
logger.info("已启用视频识别,开始识别")
if isinstance(segment.data, dict):
@@ -397,25 +396,23 @@ class MessageRecvS4U(MessageRecv):
# 从Adapter接收的视频数据
video_base64 = segment.data.get("base64")
filename = segment.data.get("filename", "video.mp4")
logger.info(f"视频文件名: {filename}")
logger.info(f"Base64数据长度: {len(video_base64) if video_base64 else 0}")
if video_base64:
# 解码base64视频数据
video_bytes = base64.b64decode(video_base64)
logger.info(f"解码后视频大小: {len(video_bytes)} 字节")
# 使用video analyzer分析视频
video_analyzer = get_video_analyzer()
result = await video_analyzer.analyze_video_from_bytes(
video_bytes,
filename,
prompt=global_config.video_analysis.batch_analysis_prompt
video_bytes, filename, prompt=global_config.video_analysis.batch_analysis_prompt
)
logger.info(f"视频分析结果: {result}")
# 返回视频分析结果
summary = result.get("summary", "")
if summary:
@@ -428,6 +425,7 @@ class MessageRecvS4U(MessageRecv):
except Exception as e:
logger.error(f"视频处理失败: {str(e)}")
import traceback
logger.error(f"错误详情: {traceback.format_exc()}")
return "[收到视频,但处理时出现错误]"
else:

View File

@@ -13,6 +13,7 @@ from sqlalchemy import select, update, desc
logger = get_logger("message_storage")
class MessageStorage:
@staticmethod
def _serialize_keywords(keywords) -> str:
@@ -92,7 +93,7 @@ class MessageStorage:
user_info_from_chat = chat_info_dict.get("user_info") or {}
# 将priority_info字典序列化为JSON字符串以便存储到数据库的Text字段
priority_info_json = orjson.dumps(priority_info).decode('utf-8') if priority_info else None
priority_info_json = orjson.dumps(priority_info).decode("utf-8") if priority_info else None
# 获取数据库会话
@@ -134,7 +135,7 @@ class MessageStorage:
with get_db_session() as session:
session.add(new_message)
session.commit()
except Exception:
logger.exception("存储消息失败")
logger.error(f"消息:{message}")
@@ -146,9 +147,9 @@ class MessageStorage:
try:
mmc_message_id = message.message_info.message_id
qq_message_id = None
logger.debug(f"尝试更新消息ID: {mmc_message_id}, 消息段类型: {message.message_segment.type}")
# 根据消息段类型提取message_id
if message.message_segment.type == "notify":
qq_message_id = message.message_segment.data.get("id")
@@ -167,7 +168,7 @@ class MessageStorage:
else:
logger.debug(f"未知的消息段类型: {message.message_segment.type}跳过ID更新")
return
if not qq_message_id:
logger.debug(f"消息段类型 {message.message_segment.type} 中未找到有效的message_id跳过更新")
logger.debug(f"消息段数据: {message.message_segment.data}")
@@ -175,6 +176,7 @@ class MessageStorage:
# 使用上下文管理器确保session正确管理
from src.common.database.sqlalchemy_models import get_db_session
with get_db_session() as session:
matched_message = session.execute(
select(Messages).where(Messages.message_id == mmc_message_id).order_by(desc(Messages.time))
@@ -192,8 +194,10 @@ class MessageStorage:
except Exception as e:
logger.error(f"更新消息ID失败: {e}")
logger.error(f"消息信息: message_id={getattr(message.message_info, 'message_id', 'N/A')}, "
f"segment_type={getattr(message.message_segment, 'type', 'N/A')}")
logger.error(
f"消息信息: message_id={getattr(message.message_info, 'message_id', 'N/A')}, "
f"segment_type={getattr(message.message_segment, 'type', 'N/A')}"
)
@staticmethod
def replace_image_descriptions(text: str) -> str:
@@ -210,6 +214,7 @@ class MessageStorage:
description = match.group(1).strip()
try:
from src.common.database.sqlalchemy_models import get_db_session
with get_db_session() as session:
image_record = session.execute(
select(Images).where(Images.description == description).order_by(desc(Images.timestamp))