From c179c82ccaefac378c37c87f071ac22256c74bd1 Mon Sep 17 00:00:00 2001 From: Renato Alcara Date: Sat, 25 Apr 2026 13:16:22 -0300 Subject: [PATCH] perf(messages-recv): early-ignore JIDs before buffer/queue (#383) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf(messages-recv): early-ignore JIDs before buffer/queue Aligns with Baileys upstream PR #2352. Moves the shouldIgnoreJid check out of handleMessage/handleReceipt/handleNotification and into processNode so ignored stanzas are acked and dropped before entering ev.buffer(), the offline queue, or the keyed mutexes. Skips the LID->PN resolution work in handleReceipt for ignored receipts as a side effect. Diverges from upstream by excluding type='call' from the early-ignore check — InfiniteAPI's handleCall has never used shouldIgnoreJid, so keeping calls outside this filter preserves existing behavior for integrators that filter messages but still want call events. Carousel, buttons, LID/PN normalization, Bad MAC fix and retry manager untouched. Co-Authored-By: Renato Alcara --- src/Socket/messages-recv.ts | 51 ++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 53723194..77aa0118 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -2124,12 +2124,6 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { if (resolvedRemoteJid) key.remoteJid = resolvedRemoteJid if (resolvedParticipant) key.participant = resolvedParticipant - if (shouldIgnoreJid(remoteJid!) && remoteJid !== S_WHATSAPP_NET) { - logger.trace({ remoteJid }, 'ignoring receipt from jid') - await sendMessageAck(node) - return - } - const ids = [attrs.id!] if (Array.isArray(content)) { const items = getBinaryNodeChildren(content[0], 'item') @@ -2205,11 +2199,6 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const handleNotification = async (node: BinaryNode) => { const remoteJid = node.attrs.from - if (shouldIgnoreJid(remoteJid!) && remoteJid !== S_WHATSAPP_NET) { - logger.trace({ remoteJid }, 'ignored notification') - await sendMessageAck(node) - return - } try { await Promise.all([ @@ -2246,12 +2235,6 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } const handleMessage = async (node: BinaryNode) => { - if (shouldIgnoreJid(node.attrs.from!) && node.attrs.from !== S_WHATSAPP_NET) { - logger.trace({ from: node.attrs.from }, 'ignored message') - await sendMessageAck(node) - return - } - const encNode = getBinaryNodeChild(node, 'enc') const unavailableNode = getBinaryNodeChild(node, 'unavailable') @@ -3105,6 +3088,40 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { identifier: string, exec: (node: BinaryNode) => Promise ) => { + // Fast path: ack and drop ignored JIDs before entering the buffer/queue. + // Skips type='call' so call events are never silently dropped via + // shouldIgnoreJid (preserves InfiniteAPI's pre-existing behavior). + // Wrapped in try/catch so a throw from shouldIgnoreJid (user callback) + // or sendMessageAck (e.g. websocket closed) is routed through + // onUnexpectedError instead of becoming an unhandled rejection — + // matches the protection processNodeWithBuffer provides. + if (type !== 'call') { + try { + const from = node.attrs.from + let ignoreJid = from + if (type === 'receipt' && from) { + const attrs = node.attrs + const isLid = attrs.from!.includes('lid') + const isNodeFromMe = areJidsSameUser( + attrs.participant || attrs.from, + isLid ? authState.creds.me?.lid : authState.creds.me?.id + ) + ignoreJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient + } + + if (ignoreJid && ignoreJid !== S_WHATSAPP_NET && shouldIgnoreJid(ignoreJid)) { + // Plain ack (no NACK error code) preserves InfiniteAPI's prior + // behavior — ignored stanzas are an intentional drop, not a + // processing failure, so we don't want server-side retries. + await sendMessageAck(node) + return + } + } catch (error) { + onUnexpectedError(error as Error, identifier) + return + } + } + const isOffline = !!node.attrs.offline if (isOffline) {