From 65a55b97e05dba69692cf3558589d888314fd9bd Mon Sep 17 00:00:00 2001 From: Jake Date: Mon, 5 Jan 2026 09:43:14 +1300 Subject: [PATCH] WhatsApp: mark offline/history messages as read --- src/web/inbound.ts | 6 +++++- src/web/monitor-inbox.test.ts | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/web/inbound.ts b/src/web/inbound.ts index c4e653c41..fe147e2fe 100644 --- a/src/web/inbound.ts +++ b/src/web/inbound.ts @@ -130,7 +130,7 @@ export async function monitorWebInbox(options: { type?: string; messages?: Array; }) => { - if (upsert.type !== "notify") return; + if (upsert.type !== "notify" && upsert.type !== "append") return; for (const msg of upsert.messages ?? []) { const id = msg.key?.id ?? undefined; // De-dupe on message id; Baileys can emit retries. @@ -205,6 +205,10 @@ export async function monitorWebInbox(options: { logVerbose(`Self-chat mode: skipping read receipt for ${id}`); } + // If this is history/offline catch-up, we marked it as read above, + // but we skip triggering the auto-reply logic to avoid spamming old context. + if (upsert.type === "append") continue; + let body = extractText(msg.message ?? undefined); if (!body) { body = extractMediaPlaceholder(msg.message ?? undefined); diff --git a/src/web/monitor-inbox.test.ts b/src/web/monitor-inbox.test.ts index 9220e5cfc..9a47fa78a 100644 --- a/src/web/monitor-inbox.test.ts +++ b/src/web/monitor-inbox.test.ts @@ -842,3 +842,39 @@ it("defaults to self-only when no config is present", async () => { await listener.close(); }); + +it("handles append messages by marking them read but skipping auto-reply", async () => { + const onMessage = vi.fn(); + const listener = await monitorWebInbox({ verbose: false, onMessage }); + const sock = await createWaSocket(); + + const upsert = { + type: "append", + messages: [ + { + key: { id: "history1", fromMe: false, remoteJid: "999@s.whatsapp.net" }, + message: { conversation: "old message" }, + messageTimestamp: 1_700_000_000, + pushName: "History Sender", + }, + ], + }; + + sock.ev.emit("messages.upsert", upsert); + await new Promise((resolve) => setImmediate(resolve)); + + // Verify it WAS marked as read + expect(sock.readMessages).toHaveBeenCalledWith([ + { + remoteJid: "999@s.whatsapp.net", + id: "history1", + participant: undefined, + fromMe: false, + }, + ]); + + // Verify it WAS NOT passed to onMessage + expect(onMessage).not.toHaveBeenCalled(); + + await listener.close(); +});