fix(onebot): keep protocol metadata out of business events

This commit is contained in:
Hyu
2026-10-12 12:45:31 +08:00
parent 9b273d3fdc
commit d34d974e6d
3 changed files with 30 additions and 2 deletions
@@ -212,6 +212,9 @@ class AiocqhttpAdapter(AiocqhttpAPIMixin, abstract_platform_adapter.AbstractPlat
async def _handle_native_event(self, event: aiocqhttp.Event):
self.bot_account_id = str(getattr(event, 'self_id', '') or self.bot_account_id)
# Connection metadata belongs to the adapter, never business event routing.
if getattr(event, 'type', None) == 'meta_event':
return
if getattr(event, 'type', None) == 'message' and str(getattr(event, 'user_id', '')) == self.bot_account_id:
return
try:
@@ -34,8 +34,6 @@ class AiocqhttpEventConverter(abstract_platform_adapter.AbstractEventConverter):
return AiocqhttpEventConverter.notice_to_eba(event, bot_user_id)
if event_type == 'request':
return AiocqhttpEventConverter.request_to_eba(event)
if event_type == 'meta_event':
return AiocqhttpEventConverter.platform_specific(event, f'meta.{getattr(event, "detail_type", "")}')
return None
@staticmethod
@@ -55,6 +55,33 @@ def onebot_event(payload: dict) -> aiocqhttp.Event:
return aiocqhttp.Event.from_payload(payload)
@pytest.mark.parametrize('meta_type', ['heartbeat', 'lifecycle', 'future_transport_metadata'])
async def test_protocol_metadata_never_reaches_business_listeners(meta_type):
adapter = make_adapter()
listener = AsyncMock()
adapter.register_listener(platform_events.EBAEvent, listener)
payload = {'post_type': 'meta_event', 'meta_event_type': meta_type, 'self_id': 42, 'time': 1700000000}
assert await AiocqhttpEventConverter.target2yiri(onebot_event(payload)) is None
await adapter._receive_event(payload)
listener.assert_not_awaited()
assert adapter.bot_account_id == '42'
# Genuine platform-specific user interactions still reach business routing.
await adapter._receive_event(
{
'post_type': 'notice',
'notice_type': 'notify',
'sub_type': 'poke',
'self_id': 42,
'time': 1700000001,
'user_id': 10001,
'target_id': 42,
}
)
listener.assert_awaited_once()
assert listener.await_args.args[0].type == 'platform.specific'
def test_aiocqhttp_supported_events_match_manifest():
assert make_adapter().get_supported_events() == manifest()['spec']['supported_events']