Skip to content

Commit 53dcbf1

Browse files
committed
test(wecomcs): cover bounded message IDs and images
1 parent 2492a67 commit 53dcbf1

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

src/langbot/libs/wecom_customer_service_api/api.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,34 @@ async def send_text_msg(self, open_kfid: str, external_userid: str, msgid: str,
295295
raise Exception('Failed to send message')
296296
return data
297297

298+
@_bounded_token_retry
299+
async def send_image_msg(self, open_kfid: str, external_userid: str, msgid: str, media_id: str):
300+
if not await self.check_access_token():
301+
self.access_token = await self.get_access_token(self.secret)
302+
303+
url = f'{self.base_url}/kf/send_msg?access_token={self.access_token}'
304+
payload = {
305+
'touser': external_userid,
306+
'open_kfid': open_kfid,
307+
'msgid': msgid,
308+
'msgtype': 'image',
309+
'image': {
310+
'media_id': media_id,
311+
},
312+
}
313+
314+
async with self._http_client_context() as client:
315+
response = await client.post(url, json=payload)
316+
317+
data = await httpclient.parse_json_response(response)
318+
if data['errcode'] == 40014 or data['errcode'] == 42001:
319+
self.access_token = await self.get_access_token(self.secret)
320+
return await self.send_image_msg(open_kfid, external_userid, msgid, media_id)
321+
if data['errcode'] != 0:
322+
await self.logger.error(f'发送图片失败:{data}')
323+
raise Exception('Failed to send image message')
324+
return data
325+
298326
async def handle_callback_request(self):
299327
"""处理回调请求(独立端口模式,使用全局 request)。"""
300328
return await self._handle_callback_internal(request)

tests/unit_tests/platform/test_wecomcs_adapter.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import uuid
12
from types import SimpleNamespace
23
from unittest.mock import AsyncMock
34

@@ -49,7 +50,29 @@ async def test_send_message_sends_text_to_customer_service_user():
4950
assert kwargs['open_kfid'] == 'kf-test'
5051
assert kwargs['external_userid'] == 'external-user'
5152
assert kwargs['content'] == 'hello'
52-
assert kwargs['msgid'].startswith('langbot_')
53+
assert len(kwargs['msgid'].encode()) <= 32
54+
assert uuid.UUID(hex=kwargs['msgid']).hex == kwargs['msgid']
55+
56+
57+
@pytest.mark.asyncio
58+
async def test_send_message_sends_image_to_customer_service_user():
59+
adapter = make_adapter()
60+
adapter.bot_account_id = 'kf-test'
61+
adapter.bot = SimpleNamespace(
62+
get_media_id=AsyncMock(return_value='media-id'),
63+
send_image_msg=AsyncMock(),
64+
)
65+
66+
message = platform_message.MessageChain([platform_message.Image(base64='aW1hZ2U=')])
67+
68+
await adapter.send_message('person', 'uexternal-user', message)
69+
70+
adapter.bot.send_image_msg.assert_awaited_once()
71+
kwargs = adapter.bot.send_image_msg.await_args.kwargs
72+
assert kwargs['open_kfid'] == 'kf-test'
73+
assert kwargs['external_userid'] == 'external-user'
74+
assert kwargs['media_id'] == 'media-id'
75+
assert len(kwargs['msgid'].encode()) <= 32
5376

5477

5578
@pytest.mark.asyncio
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from __future__ import annotations
2+
3+
import httpx
4+
import pytest
5+
6+
from langbot.libs.wecom_customer_service_api.api import WecomCSClient
7+
8+
9+
@pytest.mark.asyncio
10+
async def test_send_image_msg_posts_customer_service_image_payload() -> None:
11+
captured_request: httpx.Request | None = None
12+
13+
def handle_request(request: httpx.Request) -> httpx.Response:
14+
nonlocal captured_request
15+
captured_request = request
16+
return httpx.Response(200, json={'errcode': 0})
17+
18+
client = WecomCSClient(
19+
corpid='corp-id',
20+
secret='secret',
21+
token='token',
22+
EncodingAESKey='encoding-key',
23+
logger=None,
24+
unified_mode=True,
25+
)
26+
client.access_token = 'access-token'
27+
client._http_client = httpx.AsyncClient(transport=httpx.MockTransport(handle_request))
28+
29+
try:
30+
await client.send_image_msg(
31+
open_kfid='kf-test',
32+
external_userid='external-user',
33+
msgid='a' * 32,
34+
media_id='media-id',
35+
)
36+
finally:
37+
await client.close()
38+
39+
assert captured_request is not None
40+
assert captured_request.url.path == '/cgi-bin/kf/send_msg'
41+
assert captured_request.url.params['access_token'] == 'access-token'
42+
assert captured_request.method == 'POST'
43+
assert captured_request.read().decode() == (
44+
'{"touser":"external-user","open_kfid":"kf-test","msgid":"'
45+
+ 'a' * 32
46+
+ '","msgtype":"image","image":{"media_id":"media-id"}}'
47+
)

0 commit comments

Comments
 (0)