@vreden/meta
Version:
Baileys is a lightweight JavaScript library for interacting with the WhatsApp Web API using WebSocket.
184 lines (142 loc) • 6.77 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true })
const lru_cache_1 = require("lru-cache")
const WABinary_1 = require("../WABinary")
class LIDMappingStore {
constructor(keys, onWhatsAppFunc, logger) {
this.mappingCache = new lru_cache_1.LRUCache({
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
ttlAutopurge: true,
updateAgeOnGet: true
})
this.keys = keys
this.logger = logger
this.onWhatsAppFunc = onWhatsAppFunc // needed to get LID from PN if not found
}
/**
* Store LID-PN mapping - USER LEVEL
*/
async storeLIDPNMappings(pairs) {
// Validate inputs
const pairMap = {}
const logger = this.logger
for (const { lid, pn } of pairs) {
if (!((WABinary_1.isLidUser(lid) && WABinary_1.isJidUser(pn)) || (WABinary_1.isJidUser(lid) && WABinary_1.isLidUser(pn)))) {
logger.warn(`Invalid LID-PN mapping: ${lid}, ${pn}`)
continue
}
const [lidJid, pnJid] = WABinary_1.isLidUser(lid) ? [lid, pn] : [pn, lid]
const lidDecoded = WABinary_1.jidDecode(lidJid)
const pnDecoded = WABinary_1.jidDecode(pnJid)
if (!lidDecoded || !pnDecoded) return
const pnUser = pnDecoded.user
const lidUser = lidDecoded.user
// Check if mapping already exists (cache first, then database)
let existingLidUser = this.mappingCache.get(`pn:${pnUser}`)
if (!existingLidUser) {
// Cache miss - check 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) {
logger.debug({ pnUser, lidUser }, 'LID mapping already exists, skipping')
continue
}
pairMap[pnUser] = lidUser
}
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, // "554396160286" -> "102765716062358"
[`${lidUser}_reverse`]: pnUser // "102765716062358_reverse" -> "554396160286"
}
})
// Update cache with both directions
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) {
if (!WABinary_1.isJidUser(pn)) return null
const logger = this.logger
const decoded = WABinary_1.jidDecode(pn)
if (!decoded) return null
// 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) {
// Cache the database result
this.mappingCache.set(`pn:${pnUser}`, lidUser)
}
else {
// Not in database - try USync
logger.trace(`No LID mapping found for PN user ${pnUser}; getting from USync`)
const { exists, lid } = (await this.onWhatsAppFunc?.(pn))?.[0] // this function already adds LIDs to mapping
if (exists && lid) {
lidUser = WABinary_1.jidDecode(lid)?.user
if (lidUser) {
// Cache the USync result
this.mappingCache.set(`pn:${pnUser}`, lidUser)
}
}
else {
return null
}
}
}
if (typeof lidUser !== 'string' || !lidUser) {
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}@lid`
logger.trace(`getLIDForPN: ${pn} → ${deviceSpecificLid} (user mapping with device ${pnDevice})`)
return deviceSpecificLid
}
/**
* Get PN for LID - USER LEVEL with device construction
*/
async getPNForLID(lid) {
if (!WABinary_1.isLidUser(lid)) return null
const logger = this.logger
const decoded = 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') {
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`
logger.trace(`Found reverse mapping: ${lid} → ${pnJid}`)
return pnJid
}
}
module.exports = {
LIDMappingStore
}