补齐864消息接口适配并记录联调分层结论
- 修正 send_voice 到真实 SendVoice 路由 - 为 864 补上名片发送与视频发送的初版适配入口 - 更新路线图,记录消息接口在未建立连接对象时返回该链接不存在的联调结论
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
- 已实现 864 第一版登录、初始化等待、HTTP 消息轮询、联系人、群信息、资料与朋友圈基础接口
|
||||
- 已在 [robot.py](/d:/learn/abot/robot.py:1) 中为 864 增加登录态硬隔离,默认不再回读 855 的历史 `config.toml` 与动态字段
|
||||
- 已基于真实 864 服务联调修正首批路由差异:二维码返回结构、联系人详情路由、群公告路由、二维码有效期倒计时同步
|
||||
- 已确认 864 的消息发送类接口在“尚未建立连接对象”时会优先返回“该链接不存在”,这与登录态接口返回“需要重新登录”属于不同阶段
|
||||
|
||||
当前尚未完成的关键项:
|
||||
|
||||
|
||||
@@ -161,7 +161,11 @@ class MessageMixin(Server864APIClientBase):
|
||||
voice_base64 = await self._read_base64_payload(voice)
|
||||
data = await self._request_data(
|
||||
"post",
|
||||
"/message/UploadVoiceRequest",
|
||||
# 864 的语音发送真实路由是 `/message/SendVoice`:
|
||||
# 1. controller 方法名虽然叫 `UploadVoiceRequestApi`;
|
||||
# 2. 但 router.go 暴露给外部的路径是 `SendVoice`;
|
||||
# 3. 这里按真实注册路由适配,避免后续一接登录态就踩 404。
|
||||
"/message/SendVoice",
|
||||
json_body={
|
||||
"ToUserName": wxid,
|
||||
"VoiceData": voice_base64,
|
||||
@@ -233,13 +237,60 @@ class MessageMixin(Server864APIClientBase):
|
||||
return True
|
||||
|
||||
async def send_video_message(self, wxid: str, video: Union[str, bytes, os.PathLike], image=None):
|
||||
"""864 首版暂未做视频主动发送,先明确抛错避免静默失败。"""
|
||||
del wxid, video, image
|
||||
raise NotImplementedError("server_864 第一版暂未实现 send_video_message,可后续补 CDN 视频发送适配")
|
||||
"""发送视频消息。
|
||||
|
||||
当前实现说明:
|
||||
1. 864 走的是 `CdnUploadVideo` 路由,而不是 855 的 `SendVideo`;
|
||||
2. body 里的 `VideoData` 在 JSON 中要传整数数组,因此这里会把视频字节展开成 `list[int]`;
|
||||
3. 返回结构和旧项目三元组并不完全一致,所以仍复用本地兜底消息回执。
|
||||
"""
|
||||
return await self._queue_message(self._send_video_message, wxid, video, image)
|
||||
|
||||
async def _send_video_message(self, wxid: str, video: Union[str, bytes, os.PathLike], image=None):
|
||||
if isinstance(video, str):
|
||||
video_bytes = base64.b64decode(video.split(",", 1)[1] if "," in video else video)
|
||||
elif isinstance(video, bytes):
|
||||
video_bytes = video
|
||||
elif isinstance(video, os.PathLike):
|
||||
async with aiofiles.open(video, "rb") as f:
|
||||
video_bytes = await f.read()
|
||||
else:
|
||||
raise ValueError("video should be str, bytes, or path")
|
||||
|
||||
thumb_base64 = ""
|
||||
if image is not None:
|
||||
thumb_base64 = await self._read_base64_payload(image)
|
||||
|
||||
data = await self._request_data(
|
||||
"post",
|
||||
"/message/CdnUploadVideo",
|
||||
json_body={
|
||||
"ToUserName": wxid,
|
||||
"VideoData": list(video_bytes),
|
||||
"ThumbData": thumb_base64,
|
||||
},
|
||||
timeout=120,
|
||||
)
|
||||
return self._extract_send_message_result(data, fallback_target=wxid)
|
||||
|
||||
async def send_card_message(self, wxid: str, card_wxid: str, card_nickname: str, card_alias: str = ""):
|
||||
del wxid, card_wxid, card_nickname, card_alias
|
||||
raise NotImplementedError("server_864 第一版暂未实现 send_card_message")
|
||||
"""发送名片消息。"""
|
||||
return await self._queue_message(self._send_card_message, wxid, card_wxid, card_nickname, card_alias)
|
||||
|
||||
async def _send_card_message(self, wxid: str, card_wxid: str, card_nickname: str, card_alias: str = ""):
|
||||
data = await self._request_data(
|
||||
"post",
|
||||
"/message/ShareCardMessage",
|
||||
json_body={
|
||||
"ToUserName": wxid,
|
||||
"CardWxId": card_wxid,
|
||||
"CardNickName": card_nickname,
|
||||
"CardAlias": card_alias,
|
||||
"CardFlag": 0,
|
||||
},
|
||||
timeout=20,
|
||||
)
|
||||
return self._extract_send_message_result(data, fallback_target=wxid)
|
||||
|
||||
async def send_app_message(self, wxid: str, xml: str, type: int):
|
||||
data = await self._request_data(
|
||||
|
||||
Reference in New Issue
Block a user