import asyncio from beaver.foundation.events import OutboundMessage from beaver.interfaces.channels.platforms.qqbot import QQBotAdapter class FakeSink: def __init__(self) -> None: self.messages = [] async def accept_inbound(self, message): self.messages.append(message) class FakeQQBotClient: def __init__(self) -> None: self.sent = [] async def send_text(self, *, peer_type: str, peer_id: str, content: str, message_id: str | None): self.sent.append( { "peer_type": peer_type, "peer_id": peer_id, "content": content, "message_id": message_id, } ) def test_qqbot_normalizes_private_c2c_message() -> None: async def run() -> None: sink = FakeSink() adapter = QQBotAdapter( channel_id="qq-main", kind="qqbot", mode="websocket", account_id="qq-bot", display_name=None, inbound_sink=sink, secrets={"appId": "app", "clientSecret": "secret"}, config={}, client=FakeQQBotClient(), ) await adapter.handle_event_payload( { "t": "C2C_MESSAGE_CREATE", "d": { "id": "m1", "author": {"user_openid": "u1"}, "content": "hello", }, } ) message = sink.messages[0] assert message.content == "hello" assert message.session_id == "qq-main:qq-bot:u1" assert message.channel_identity.peer_type == "dm" assert message.channel_identity.user_id == "u1" asyncio.run(run()) def test_qqbot_normalizes_group_message() -> None: async def run() -> None: sink = FakeSink() adapter = QQBotAdapter( channel_id="qq-main", kind="qqbot", mode="websocket", account_id="qq-bot", display_name=None, inbound_sink=sink, secrets={"appId": "app", "clientSecret": "secret"}, config={}, client=FakeQQBotClient(), ) await adapter.handle_event_payload( { "t": "GROUP_AT_MESSAGE_CREATE", "d": { "id": "m2", "group_openid": "g1", "author": {"member_openid": "u1"}, "content": "hello group", }, } ) message = sink.messages[0] assert message.session_id == "qq-main:qq-bot:g1" assert message.channel_identity.peer_type == "group" assert message.channel_identity.user_id == "u1" asyncio.run(run()) def test_qqbot_sends_reply_with_original_message_id() -> None: async def run() -> None: sink = FakeSink() client = FakeQQBotClient() adapter = QQBotAdapter( channel_id="qq-main", kind="qqbot", mode="websocket", account_id="qq-bot", display_name=None, inbound_sink=sink, secrets={"appId": "app", "clientSecret": "secret"}, config={}, client=client, ) await adapter.handle_event_payload( { "t": "GROUP_AT_MESSAGE_CREATE", "d": { "id": "m2", "group_openid": "g1", "author": {"member_openid": "u1"}, "content": "hello group", }, } ) await adapter.send( OutboundMessage( channel="qq-main", content="ok", session_id=sink.messages[0].session_id, finish_reason="stop", channel_identity=sink.messages[0].channel_identity, ) ) assert client.sent[0] == { "peer_type": "group", "peer_id": "g1", "content": "ok", "message_id": "m2", } asyncio.run(run())