This commit is contained in:
2026-04-08 11:00:31 +08:00
parent fb21a127b5
commit 7019cf180d
17 changed files with 960 additions and 1 deletions

View File

@@ -0,0 +1,91 @@
"""
消息处理器模块
提供统一的消息处理流程,消除各消息类型处理器之间的重复代码。
处理流程:
1. 解析消息元数据和内容
2. (可选)下载附件(图片/文件/视频)
3. 调用 Agent 获取回复
"""
import logging
from aibot import generate_req_id
from bot.agent_client import call_agent_stream
from bot.message_parser import extract_metadata, extract_text_content
logger = logging.getLogger(__name__)
async def handle_message(ws_client, frame: dict, msg_type: str):
"""
通用消息处理器,适用于所有消息类型。
对于需要下载附件的消息类型image/file/video
会先尝试下载附件并附加描述信息。
"""
meta = extract_metadata(frame)
user_id = meta["user_id"]
# ---- 提取消息内容 ----
content = await _resolve_content(ws_client, frame, msg_type, meta)
logger.info("收到%s消息 - 用户: %s, 内容: %s", msg_type, user_id, content[:100])
# ---- 调用 Agent ----
reply = await call_agent_stream(ws_client, frame, user_id, content)
# ---- 兜底:未收到回复 ----
if not reply:
stream_id = generate_req_id("stream")
await ws_client.reply_stream(frame, stream_id, "(未收到回复)", True)
async def _resolve_content(
ws_client, frame: dict, msg_type: str, meta: dict
) -> str:
"""
解析消息内容。
对于文本类消息直接提取文本;对于附件类消息尝试下载并附加描述。
"""
if msg_type in ("text", "voice", "mixed"):
return extract_text_content(frame)
if msg_type == "image":
return await _download_and_describe(ws_client, frame, "image", "图片")
if msg_type == "file":
return await _download_and_describe(ws_client, frame, "file", "文件")
if msg_type == "video":
return await _download_and_describe(ws_client, frame, "video", "视频")
return extract_text_content(frame)
async def _download_and_describe(
ws_client, frame: dict, media_type: str, label: str
) -> str:
"""
尝试下载附件并返回描述文本。
下载失败时返回简单描述,不阻断流程。
"""
body = frame.get("body", {})
media_info = body.get(media_type, {})
if not media_info:
return f"[用户发送了一个{label}]"
url = media_info.get("url")
aeskey = media_info.get("aeskey")
if not url:
return f"[用户发送了一个{label}]"
try:
buffer, filename = await ws_client.download_file(url, aeskey)
desc = f"[用户发送了{label}: {filename}, 大小: {len(buffer)} bytes]"
logger.info("%s下载成功: %s, 大小: %d bytes", label, filename, len(buffer))
return desc
except Exception as e:
logger.warning("%s下载失败: %s", label, e)
return f"[用户发送了一个{label}]"