UNPKG

@faouzkk/baileys

Version:

A WebSockets library for interacting with WhatsApp Web

171 lines 7.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LIDMappingStore = void 0; const lru_cache_1 = require("lru-cache"); const WABinary_1 = require("../WABinary"); class LIDMappingStore { constructor(keys, logger, pnToLIDFunc) { this.mappingCache = new lru_cache_1.LRUCache({ ttl: 7 * 24 * 60 * 60 * 1000, // 7 days ttlAutopurge: true, updateAgeOnGet: true }); this.keys = keys; this.pnToLIDFunc = pnToLIDFunc; this.logger = logger; } /** * Store LID-PN mapping - USER LEVEL */ async storeLIDPNMappings(pairs) { // Validate inputs const pairMap = {}; for (const { lid, pn } of pairs) { if (!(((0, WABinary_1.isLidUser)(lid) && (0, WABinary_1.isPnUser)(pn)) || ((0, WABinary_1.isPnUser)(lid) && (0, WABinary_1.isLidUser)(pn)))) { this.logger.warn(`Invalid LID-PN mapping: ${lid}, ${pn}`); continue; } const lidDecoded = (0, WABinary_1.jidDecode)(lid); const pnDecoded = (0, WABinary_1.jidDecode)(pn); if (!lidDecoded || !pnDecoded) return; const pnUser = pnDecoded.user; const lidUser = lidDecoded.user; let existingLidUser = this.mappingCache.get(`pn:${pnUser}`); if (!existingLidUser) { this.logger.trace(`Cache miss for PN user ${pnUser}; checking database`); const stored = await this.keys.get('lid-mapping', [pnUser]); existingLidUser = stored[pnUser]; if (existingLidUser) { // Update cache with database value this.mappingCache.set(`pn:${pnUser}`, existingLidUser); this.mappingCache.set(`lid:${existingLidUser}`, pnUser); } } if (existingLidUser === lidUser) { this.logger.debug({ pnUser, lidUser }, 'LID mapping already exists, skipping'); continue; } pairMap[pnUser] = lidUser; } this.logger.trace({ pairMap }, `Storing ${Object.keys(pairMap).length} pn mappings`); await this.keys.transaction(async () => { for (const [pnUser, lidUser] of Object.entries(pairMap)) { await this.keys.set({ 'lid-mapping': { [pnUser]: lidUser, [`${lidUser}_reverse`]: pnUser } }); this.mappingCache.set(`pn:${pnUser}`, lidUser); this.mappingCache.set(`lid:${lidUser}`, pnUser); } }, 'lid-mapping'); } /** * Get LID for PN - Returns device-specific LID based on user mapping */ async getLIDForPN(pn) { return (await this.getLIDsForPNs([pn]))?.[0]?.lid || null; } async getLIDsForPNs(pns) { const usyncFetch = {}; // mapped from pn to lid mapping to prevent duplication in results later const successfulPairs = {}; for (const pn of pns) { if (!(0, WABinary_1.isPnUser)(pn)) continue; const decoded = (0, WABinary_1.jidDecode)(pn); if (!decoded) continue; // Check cache first for PN → LID mapping const pnUser = decoded.user; let lidUser = this.mappingCache.get(`pn:${pnUser}`); if (!lidUser) { // Cache miss - check database const stored = await this.keys.get('lid-mapping', [pnUser]); lidUser = stored[pnUser]; if (lidUser) { this.mappingCache.set(`pn:${pnUser}`, lidUser); this.mappingCache.set(`lid:${lidUser}`, pnUser); } else { this.logger.trace(`No LID mapping found for PN user ${pnUser}; batch getting from USync`); const device = decoded.device || 0; const normalizedPn = (0, WABinary_1.jidNormalizedUser)(pn); if (!usyncFetch[normalizedPn]) { usyncFetch[normalizedPn] = [device]; } else { usyncFetch[normalizedPn].push(device); } continue; } } lidUser = lidUser.toString(); if (!lidUser) { this.logger.warn(`Invalid or empty LID user for PN ${pn}: lidUser = "${lidUser}"`); return null; } // Push the PN device ID to the LID to maintain device separation const pnDevice = decoded.device !== undefined ? decoded.device : 0; const deviceSpecificLid = `${lidUser}${!!pnDevice ? `:${pnDevice}` : ``}@lid`; this.logger.trace(`getLIDForPN: ${pn}${deviceSpecificLid} (user mapping with device ${pnDevice})`); successfulPairs[pn] = { lid: deviceSpecificLid, pn }; } if (Object.keys(usyncFetch).length > 0) { const result = await this.pnToLIDFunc?.(Object.keys(usyncFetch)); // this function already adds LIDs to mapping if (result && result.length > 0) { this.storeLIDPNMappings(result); for (const pair of result) { const pnUser = (0, WABinary_1.jidDecode)(pair.pn)?.user; if (!pnUser) continue; const lidUser = (0, WABinary_1.jidDecode)(pair.lid)?.user; if (!lidUser) continue; for (const device of usyncFetch[pair.pn]) { const deviceSpecificLid = `${lidUser}${!!device ? `:${device}` : ``}@lid`; this.logger.trace(`getLIDForPN: USYNC success for ${pair.pn}${deviceSpecificLid} (user mapping with device ${device})`); const deviceSpecificPn = `${pnUser}${!!device ? `:${device}` : ``}@s.whatsapp.net`; successfulPairs[deviceSpecificPn] = { lid: deviceSpecificLid, pn: deviceSpecificPn }; } } } else { return null; } } return Object.values(successfulPairs); } /** * Get PN for LID - USER LEVEL with device construction */ async getPNForLID(lid) { if (!(0, WABinary_1.isLidUser)(lid)) return null; const decoded = (0, WABinary_1.jidDecode)(lid); if (!decoded) return null; // Check cache first for LID → PN mapping const lidUser = decoded.user; let pnUser = this.mappingCache.get(`lid:${lidUser}`); if (!pnUser || typeof pnUser !== 'string') { // Cache miss - check database const stored = await this.keys.get('lid-mapping', [`${lidUser}_reverse`]); pnUser = stored[`${lidUser}_reverse`]; if (!pnUser || typeof pnUser !== 'string') { this.logger.trace(`No reverse mapping found for LID user: ${lidUser}`); return null; } this.mappingCache.set(`lid:${lidUser}`, pnUser); } // Construct device-specific PN JID const lidDevice = decoded.device !== undefined ? decoded.device : 0; const pnJid = `${pnUser}:${lidDevice}@s.whatsapp.net`; this.logger.trace(`Found reverse mapping: ${lid}${pnJid}`); return pnJid; } } exports.LIDMappingStore = LIDMappingStore; //# sourceMappingURL=lid-mapping.js.map