From 392ba6262c6b83aa5e480eeaa02240a9b777578c Mon Sep 17 00:00:00 2001 From: yingchao Date: Wed, 4 Feb 2026 06:33:50 +0800 Subject: [PATCH] fix: translate WhatsApp LID JIDs to phone JIDs for self-chat messages (#62) WhatsApp recently changed to send self-chat messages using LID (Linked ID) format (e.g., xxxxxx@lid) instead of phone number format (e.g., xxxxxx@s.whatsapp.net). This caused messages to yourself to be silently dropped because they didn't match any registered group. ## How to reproduce 1. Send a message to yourself on WhatsApp with the trigger 2. Message is received by Baileys but remoteJid is in LID format 3. LID JID doesn't match registered group JID (phone format) 4. Message is not stored and no response is sent ## The fix - Build a LID-to-phone mapping from sock.user on connection open - Translate incoming LID JIDs to phone JIDs before storing/processing messages - This allows self-chat messages to correctly match the registered main channel The mapping is populated from sock.user.id (phone) and sock.user.lid (LID) which Baileys provides after successful authentication. --- src/index.ts | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9f450df..07702ec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,6 +55,23 @@ let lastTimestamp = ''; let sessions: Session = {}; let registeredGroups: Record = {}; let lastAgentTimestamp: Record = {}; +// LID to phone number mapping (WhatsApp now sends LID JIDs for self-chats) +let lidToPhoneMap: Record = {}; + +/** + * Translate a JID from LID format to phone format if we have a mapping. + * Returns the original JID if no mapping exists. + */ +function translateJid(jid: string): string { + if (!jid.endsWith('@lid')) return jid; + const lidUser = jid.split('@')[0].split(':')[0]; + const phoneJid = lidToPhoneMap[lidUser]; + if (phoneJid) { + logger.debug({ lidJid: jid, phoneJid }, 'Translated LID to phone JID'); + return phoneJid; + } + return jid; +} async function setTyping(jid: string, isTyping: boolean): Promise { try { @@ -670,6 +687,17 @@ async function connectWhatsApp(): Promise { } } else if (connection === 'open') { logger.info('Connected to WhatsApp'); + + // Build LID to phone mapping from auth state for self-chat translation + if (sock.user) { + const phoneUser = sock.user.id.split(':')[0]; + const lidUser = sock.user.lid?.split(':')[0]; + if (lidUser && phoneUser) { + lidToPhoneMap[lidUser] = `${phoneUser}@s.whatsapp.net`; + logger.debug({ lidUser, phoneUser }, 'LID to phone mapping set'); + } + } + // Sync group metadata on startup (respects 24h cache) syncGroupMetadata().catch((err) => logger.error({ err }, 'Initial group sync failed'), @@ -695,9 +723,12 @@ async function connectWhatsApp(): Promise { sock.ev.on('messages.upsert', ({ messages }) => { for (const msg of messages) { if (!msg.message) continue; - const chatJid = msg.key.remoteJid; - if (!chatJid || chatJid === 'status@broadcast') continue; + const rawJid = msg.key.remoteJid; + if (!rawJid || rawJid === 'status@broadcast') continue; + // Translate LID JID to phone JID if applicable + const chatJid = translateJid(rawJid); + const timestamp = new Date( Number(msg.messageTimestamp) * 1000, ).toISOString();