From 79f799256d0daa2faa41fb5e57e353cd23bb6a77 Mon Sep 17 00:00:00 2001 From: Nick Sullivan Date: Thu, 29 Jan 2026 12:53:31 -0600 Subject: [PATCH] fix(whatsapp): update reaction docs + suppress pairing for reactions - Update docs: reaction removals now emit events with isRemoval=true - Pass no-op sendMessage to access control to prevent pairing messages being sent when unknown users react (pairing is for messages, not reactions) (Cursor review) Co-Authored-By: Claude Opus 4.5 --- docs/channels/whatsapp.md | 3 ++- src/web/inbound/monitor.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/channels/whatsapp.md b/docs/channels/whatsapp.md index ae2838ef9..34ab16613 100644 --- a/docs/channels/whatsapp.md +++ b/docs/channels/whatsapp.md @@ -304,9 +304,10 @@ When someone reacts to a message in a WhatsApp chat, the gateway emits a system ``` WhatsApp reaction added: 👍 by +1234567890 msg BAE5ABC123 +WhatsApp reaction removed by +1234567890 msg BAE5ABC123 ``` -- Reaction removals (empty emoji) are silently skipped. +- Reaction removals emit events with `isRemoval: true` and no emoji in the message. - Self-reactions in DMs are correctly attributed to the bot's own JID. - Group reactions include the participant who reacted. - Events are deduplicated by message ID, sender, and emoji to avoid repeat notifications. diff --git a/src/web/inbound/monitor.ts b/src/web/inbound/monitor.ts index e68763468..1423d2135 100644 --- a/src/web/inbound/monitor.ts +++ b/src/web/inbound/monitor.ts @@ -357,6 +357,7 @@ export async function monitorWebInbox(options: { if (!isOwnReaction) { const from = group ? chatJid : await resolveInboundJid(chatJid); if (!from) continue; + // No-op sendMessage: reactions shouldn't trigger pairing replies const access = await checkInboundAccessControl({ accountId: options.accountId, from, @@ -365,7 +366,7 @@ export async function monitorWebInbox(options: { group, isFromMe: false, connectedAtMs, - sock: { sendMessage: (jid, content) => sock.sendMessage(jid, content) }, + sock: { sendMessage: async () => ({}) }, remoteJid: chatJid, }); if (!access.allowed) {