fix: fire-and-forget read receipts, add docs (#70340 salvage)

- Change await self._send_read_receipt to asyncio.create_task to avoid
  blocking message dispatch on slow bridge responses (matches BlueBubbles
  pattern). Up to 5s per-message latency eliminated.
- Update tests: assert_called_once_with instead of assert_awaited_once_with
  since the receipt is now scheduled, not directly awaited.
- Add send_read_receipts documentation to whatsapp.md following the
  BlueBubbles docs pattern.
This commit is contained in:
kshitijk4poor 2026-07-28 17:11:18 +05:00 committed by kshitij
parent 652d858f2e
commit bd1c782456
3 changed files with 10 additions and 4 deletions

View file

@ -1271,7 +1271,10 @@ class WhatsAppAdapter(WhatsAppBehaviorMixin, BasePlatformAdapter):
for msg_data in messages:
event = await self._build_message_event(msg_data)
if event:
await self._send_read_receipt(msg_data)
# Fire-and-forget: a slow bridge /read must not
# delay message dispatch (matches BlueBubbles
# asyncio.create_task pattern for mark_read).
asyncio.create_task(self._send_read_receipt(msg_data))
if event.message_type == MessageType.TEXT:
self._enqueue_text_event(event)
else:

View file

@ -200,10 +200,10 @@ class TestReadReceiptPolicyOrdering:
await adapter._poll_messages()
adapter._send_read_receipt.assert_not_awaited()
adapter._send_read_receipt.assert_not_called()
@pytest.mark.asyncio
async def test_policy_accepted_message_is_marked_read_before_dispatch(self, monkeypatch):
async def test_policy_accepted_message_is_marked_read_fire_and_forget(self, monkeypatch):
from plugins.platforms.whatsapp.adapter import WhatsAppAdapter
adapter = WhatsAppAdapter(
@ -230,7 +230,7 @@ class TestReadReceiptPolicyOrdering:
await adapter._poll_messages()
adapter._send_read_receipt.assert_awaited_once_with(raw)
adapter._send_read_receipt.assert_called_once_with(raw)
adapter.handle_message.assert_awaited_once_with(event)

View file

@ -180,8 +180,11 @@ Hermes supports voice on WhatsApp:
whatsapp:
reply_prefix: "" # Empty string disables the header
# reply_prefix: "🤖 *My Bot*\n──────\n" # Custom prefix (supports \n for newlines)
send_read_receipts: false # Mark accepted inbound messages as read (blue ticks)
```
When `send_read_receipts` is `true`, the adapter marks policy-accepted inbound messages as read after DM/group/mention filtering passes. Rejected messages (e.g., from non-allowlisted senders) are not marked read. Disabled by default for privacy. Changing this setting automatically restarts the bridge subprocess on the next connection.
---
## Message Formatting & Delivery