init
This commit is contained in:
91
wechat-bot/bot/handlers.py
Normal file
91
wechat-bot/bot/handlers.py
Normal 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}]"
|
||||
Reference in New Issue
Block a user