From 2d8cd2f5f17bc87e1d9134e46ba787bff75201ce Mon Sep 17 00:00:00 2001 From: "louise.lu" Date: Fri, 24 Jul 2026 19:09:40 +0800 Subject: [PATCH] fix(weixin): reject nonzero send ret --- raven/channels/adapters/weixin/channel.py | 5 +++-- tests/test_channels_weixin.py | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/raven/channels/adapters/weixin/channel.py b/raven/channels/adapters/weixin/channel.py index 042da4e..6ca04fc 100644 --- a/raven/channels/adapters/weixin/channel.py +++ b/raven/channels/adapters/weixin/channel.py @@ -608,8 +608,9 @@ def _bot_msg(self, to_user: str, ctx_token: str, item_list: list[dict] | None = async def _send_text(self, to_user: str, text: str, ctx_token: str) -> None: item_list = [{"type": p.ITEM_TEXT, "text_item": {"text": text}}] if text else [] data = await self._post("ilink/bot/sendmessage", {"msg": self._bot_msg(to_user, ctx_token, item_list)}) - if errcode := data.get("errcode", 0): - raise RuntimeError(f"WeChat send text error (code {errcode}): {data.get('errmsg', '')}") + ret, errcode = data.get("ret", 0), data.get("errcode", 0) + if (ret and ret != 0) or (errcode and errcode != 0): + raise RuntimeError(f"WeChat send text error: ret={ret} errcode={errcode} errmsg={data.get('errmsg', '')}") async def _send_media_file(self, to_user: str, media_path: str, ctx_token: str) -> None: """Upload to the iLink CDN (AES-encrypted) and send it as a media message.""" diff --git a/tests/test_channels_weixin.py b/tests/test_channels_weixin.py index 7f41a5e..1fdeed8 100644 --- a/tests/test_channels_weixin.py +++ b/tests/test_channels_weixin.py @@ -231,6 +231,14 @@ def test_send_raises_when_context_token_missing(): asyncio.run(ch.send("u1", "hi")) +def test_send_text_rejects_nonzero_ret_even_when_errcode_is_zero(): + ch = _channel() + ch._post = AsyncMock(return_value={"ret": -2, "errcode": 0, "errmsg": "prepare failed"}) + + with pytest.raises(RuntimeError, match=r"ret=-2.*errcode=0.*prepare failed"): + asyncio.run(ch._send_text("u1", "hi", "ctok")) + + # ── _process_message gating + dedup (text path, no network) ───────────