#971 微信Bot P2 - 接收侧媒体下载解密
CI / gate (push) Has been cancelled

实现CDN媒体下载解密(parse_aes_key支持base64(raw16B)和base64(hex32)两种编码)+extract_inbound_media(图片/语音/文件/视频)。接收循环检测媒体消息下载解密保存到/tmp。图片已保存供后续vision模型接入。
This commit is contained in:
qihu-bot committed 2026-08-15 18:40:01 +08:00
1 parent e284d43cc7
commit 51d8df6e6a
2 files changed
+156 -1

No files matched your search

+40 -1
View File
@@ -425,6 +425,42 @@ def _wechat_extract_text(msg: dict) -> str:
return "\n".join(parts)
def _extract_and_save_inbound_media(msg: dict) -> str:
"""检测入站媒体消息(图片/语音/文件/视频),下载解密保存,返回给 LLM 的提示文本。
无媒体或解密失败返回空字符串。图片已保存到本地,供后续 vision 模型接入。
"""
try:
from app.api.im_ilink_media import extract_inbound_media
import os as _os
for it in (msg.get("item_list") or []):
if it.get("type") in (2, 3, 4, 5):
kind, data = extract_inbound_media(it)
if kind and data:
_dir = "/tmp/wechat_inbound_media"
_os.makedirs(_dir, exist_ok=True)
_ext = {"image": "jpg", "voice": "silk", "file": "bin", "video": "mp4"}.get(kind, "bin")
_path = _os.path.join(_dir, "%d_%s.%s" % (int(time.time() * 1000), kind, _ext))
with open(_path, "wb") as _f:
_f.write(data)
_label = {"image": "图片", "voice": "语音", "file": "文件", "video": "视频"}.get(kind, kind)
try:
with open("/tmp/wechat_inbound_media.log", "a", encoding="utf-8") as _f:
_f.write(_beijing_now().isoformat() + " %s saved=%s size=%d\n"
% (kind, _path, len(data)))
except Exception:
pass
return "[用户发送了%s,已保存到 %s(%d 字节)]" % (_label, _path, len(data))
return ""
except Exception as _e:
try:
with open("/tmp/wechat_inbound_media.log", "a", encoding="utf-8") as _f:
_f.write(_beijing_now().isoformat() + " MEDIA_EXTRACT_ERR %s\n" % (_e,))
except Exception:
pass
return ""
def _wechat_sender_id(m: dict) -> str:
"""从入站消息中提取发送者 id(兼容多套字段名)。"""
for k in ("from_user_id", "from_user_name", "from_username", "user_id",
@@ -576,7 +612,10 @@ def _wechat_receiver_loop(account_id: int):
continue # 仅跳过 bot 自己发出的回声,其余(含后续追问)均尝试处理
content = _wechat_extract_text(m)
if not content:
continue
# 入站媒体(图片/语音/文件/视频):下载解密保存,供 LLM 感知
content = _extract_and_save_inbound_media(m)
if not content:
continue
sender = _wechat_sender_id(m)
ctx = _wechat_context_token(m)
# 诊断:记录原始入站消息,定位字段名 / 第二轮不回复