Skip to content

Commit 796bc4c

Browse files
Implement LID to phone number mapping and caching
Added LID to phone number mapping and resolution logic to handle LID addresses. Implemented caching for LID mappings and added methods to clean and save mappings.
1 parent 22048fe commit 796bc4c

File tree

1 file changed

+129
-4
lines changed

1 file changed

+129
-4
lines changed

src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export class ChatwootService {
5353
private processedOrderIds: Map<string, number> = new Map();
5454
private readonly ORDER_CACHE_TTL_MS = 30000; // 30 segundos
5555

56+
// Cache para mapeamento LID → Número Normal (resolve problema de @lid)
57+
private lidToPhoneMap: Map<string, { phone: string; timestamp: number }> = new Map();
58+
private readonly LID_CACHE_TTL_MS = 3600000; // 1 hora
59+
5660
constructor(
5761
private readonly waMonitor: WAMonitoringService,
5862
private readonly configService: ConfigService,
@@ -636,10 +640,32 @@ export class ChatwootService {
636640
public async createConversation(instance: InstanceDto, body: any) {
637641
const isLid = body.key.addressingMode === 'lid';
638642
const isGroup = body.key.remoteJid.endsWith('@g.us');
639-
const phoneNumber = isLid && !isGroup ? body.key.remoteJidAlt : body.key.remoteJid;
640-
const { remoteJid } = body.key;
641-
const cacheKey = `${instance.instanceName}:createConversation-${remoteJid}`;
642-
const lockKey = `${instance.instanceName}:lock:createConversation-${remoteJid}`;
643+
let phoneNumber = isLid && !isGroup ? body.key.remoteJidAlt : body.key.remoteJid;
644+
let { remoteJid } = body.key;
645+
646+
// CORREÇÃO LID: Resolve LID para número normal antes de processar
647+
if (isLid && !isGroup) {
648+
const resolvedPhone = await this.resolveLidToPhone(instance, body.key);
649+
650+
if (resolvedPhone && resolvedPhone !== remoteJid) {
651+
this.logger.verbose(`LID detected and resolved: ${remoteJid}${resolvedPhone}`);
652+
phoneNumber = resolvedPhone;
653+
654+
// Salva mapeamento se temos remoteJidAlt
655+
if (body.key.remoteJidAlt) {
656+
this.saveLidMapping(remoteJid, body.key.remoteJidAlt);
657+
}
658+
} else if (body.key.remoteJidAlt) {
659+
// Se não resolveu mas tem remoteJidAlt, usa ele
660+
phoneNumber = body.key.remoteJidAlt;
661+
this.saveLidMapping(remoteJid, body.key.remoteJidAlt);
662+
this.logger.verbose(`Using remoteJidAlt for LID: ${remoteJid}${phoneNumber}`);
663+
}
664+
}
665+
666+
// Usa phoneNumber como base para cache (não o LID)
667+
const cacheKey = `${instance.instanceName}:createConversation-${phoneNumber}`;
668+
const lockKey = `${instance.instanceName}:lock:createConversation-${phoneNumber}`;
643669
const maxWaitTime = 5000; // 5 seconds
644670
const client = await this.clientCw(instance);
645671
if (!client) return null;
@@ -2070,6 +2096,29 @@ export class ChatwootService {
20702096
}
20712097
}
20722098

2099+
// CORREÇÃO LID: Resolve LID para número normal antes de processar evento
2100+
if (body?.key?.remoteJid && body.key.remoteJid.includes('@lid') && !body.key.remoteJid.endsWith('@g.us')) {
2101+
const originalJid = body.key.remoteJid;
2102+
const resolvedPhone = await this.resolveLidToPhone(instance, body.key);
2103+
2104+
if (resolvedPhone && resolvedPhone !== originalJid) {
2105+
this.logger.verbose(`Event LID resolved: ${originalJid}${resolvedPhone}`);
2106+
body.key.remoteJid = resolvedPhone;
2107+
2108+
// Salva mapeamento se temos remoteJidAlt
2109+
if (body.key.remoteJidAlt) {
2110+
this.saveLidMapping(originalJid, body.key.remoteJidAlt);
2111+
}
2112+
} else if (body.key.remoteJidAlt && !body.key.remoteJidAlt.includes('@lid')) {
2113+
// Se não resolveu mas tem remoteJidAlt válido, usa ele
2114+
this.logger.verbose(`Using remoteJidAlt for event: ${originalJid}${body.key.remoteJidAlt}`);
2115+
body.key.remoteJid = body.key.remoteJidAlt;
2116+
this.saveLidMapping(originalJid, body.key.remoteJidAlt);
2117+
} else {
2118+
this.logger.warn(`Could not resolve LID for event, keeping original: ${originalJid}`);
2119+
}
2120+
}
2121+
20732122
if (event === 'messages.upsert' || event === 'send.message') {
20742123
this.logger.info(`[${event}] New message received - Instance: ${JSON.stringify(body, null, 2)}`);
20752124
if (body.key.remoteJid === 'status@broadcast') {
@@ -2614,6 +2663,82 @@ export class ChatwootService {
26142663
return remoteJid.replace(/:\d+/, '').split('@')[0];
26152664
}
26162665

2666+
/**
2667+
* Limpa entradas antigas do cache de mapeamento LID
2668+
*/
2669+
private cleanLidCache() {
2670+
const now = Date.now();
2671+
this.lidToPhoneMap.forEach((value, lid) => {
2672+
if (now - value.timestamp > this.LID_CACHE_TTL_MS) {
2673+
this.lidToPhoneMap.delete(lid);
2674+
}
2675+
});
2676+
}
2677+
2678+
/**
2679+
* Salva mapeamento LID → Número Normal
2680+
*/
2681+
private saveLidMapping(lid: string, phoneNumber: string) {
2682+
if (!lid || !phoneNumber || !lid.includes('@lid')) {
2683+
return;
2684+
}
2685+
2686+
this.cleanLidCache();
2687+
this.lidToPhoneMap.set(lid, {
2688+
phone: phoneNumber,
2689+
timestamp: Date.now(),
2690+
});
2691+
2692+
this.logger.verbose(`LID mapping saved: ${lid}${phoneNumber}`);
2693+
}
2694+
2695+
/**
2696+
* Resolve LID para Número Normal
2697+
* Retorna o número normal se encontrado, ou o LID original se não encontrado
2698+
*/
2699+
private async resolveLidToPhone(instance: InstanceDto, messageKey: any): Promise<string | null> {
2700+
const { remoteJid, remoteJidAlt } = messageKey;
2701+
2702+
// Se não for LID, retorna o próprio remoteJid
2703+
if (!remoteJid || !remoteJid.includes('@lid')) {
2704+
return remoteJid;
2705+
}
2706+
2707+
// 1. Tenta buscar no cache
2708+
const cached = this.lidToPhoneMap.get(remoteJid);
2709+
if (cached) {
2710+
this.logger.verbose(`LID resolved from cache: ${remoteJid}${cached.phone}`);
2711+
return cached.phone;
2712+
}
2713+
2714+
// 2. Se tem remoteJidAlt (número alternativo), usa ele e salva no cache
2715+
if (remoteJidAlt && !remoteJidAlt.includes('@lid')) {
2716+
this.saveLidMapping(remoteJid, remoteJidAlt);
2717+
this.logger.verbose(`LID resolved from remoteJidAlt: ${remoteJid}${remoteJidAlt}`);
2718+
return remoteJidAlt;
2719+
}
2720+
2721+
// 3. Tenta buscar no banco de dados do Chatwoot
2722+
try {
2723+
const lidIdentifier = this.normalizeJidIdentifier(remoteJid);
2724+
const contact = await this.findContactByIdentifier(instance, lidIdentifier);
2725+
2726+
if (contact && contact.phone_number) {
2727+
// Converte +554498860240 → [email protected]
2728+
const phoneNumber = contact.phone_number.replace('+', '') + '@s.whatsapp.net';
2729+
this.saveLidMapping(remoteJid, phoneNumber);
2730+
this.logger.verbose(`LID resolved from database: ${remoteJid}${phoneNumber}`);
2731+
return phoneNumber;
2732+
}
2733+
} catch (error) {
2734+
this.logger.warn(`Error resolving LID from database: ${error}`);
2735+
}
2736+
2737+
// 4. Se não encontrou, retorna null (será necessário criar novo contato)
2738+
this.logger.warn(`Could not resolve LID: ${remoteJid}`);
2739+
return null;
2740+
}
2741+
26172742
public startImportHistoryMessages(instance: InstanceDto) {
26182743
if (!this.isImportHistoryAvailable()) {
26192744
return;

0 commit comments

Comments
 (0)