Skip to content
19 changes: 7 additions & 12 deletions src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1148,12 +1148,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
}

if (
(type !== 'notify' && type !== 'append') ||
editedMessage ||
received.message?.pollUpdateMessage ||
!received?.message
) {
if ((type !== 'notify' && type !== 'append') || editedMessage || !received?.message) {
continue;
}

Expand Down Expand Up @@ -1447,18 +1442,18 @@ export class BaileysStartupService extends ChannelStartupService {
continue;
}

if (update.message !== null && update.status === undefined) continue;
if (update.message === null && update.status === undefined) continue;

const updateKey = `${this.instance.id}_${key.id}_${update.status}`;

const cached = await this.baileysCache.get(updateKey);

if (cached) {
if (cached && update.messageTimestamp == cached.messageTimestamp) {
this.logger.info(`Update Message duplicated ignored [avoid deadlock]: ${updateKey}`);
continue;
}

await this.baileysCache.set(updateKey, true, 30 * 60);
await this.baileysCache.set(updateKey, update.messageTimestamp, 30 * 60);

if (status[update.status] === 'READ' && key.fromMe) {
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
Expand Down Expand Up @@ -1489,7 +1484,7 @@ export class BaileysStartupService extends ChannelStartupService {
remoteJid: key?.remoteJid,
fromMe: key.fromMe,
participant: key?.participant,
status: status[update.status] ?? 'DELETED',
status: status[update.status] ?? 'SERVER_ACK',
pollUpdates,
instanceId: this.instanceId,
};
Expand Down Expand Up @@ -1614,9 +1609,9 @@ export class BaileysStartupService extends ChannelStartupService {
// This enables LID to phoneNumber conversion without breaking existing webhook consumers

// Helper to normalize participantId as phone number
const normalizePhoneNumber = (id: string): string => {
const normalizePhoneNumber = (id: string | any): string => {
// Remove @lid, @s.whatsapp.net suffixes and extract just the number part
return id.split('@')[0];
return String(id || '').split('@')[0];
};

try {
Expand Down
6 changes: 3 additions & 3 deletions src/api/integrations/chatbot/base-chatbot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,15 @@ export abstract class BaseChatbotService<BotType = any, SettingsType = any> {
try {
if (mediaType === 'audio') {
await instance.audioWhatsapp({
number: remoteJid.split('@')[0],
number: remoteJid,
delay: (settings as any)?.delayMessage || 1000,
audio: url,
caption: altText,
});
} else {
await instance.mediaMessage(
{
number: remoteJid.split('@')[0],
number: remoteJid,
delay: (settings as any)?.delayMessage || 1000,
mediatype: mediaType,
media: url,
Expand Down Expand Up @@ -290,7 +290,7 @@ export abstract class BaseChatbotService<BotType = any, SettingsType = any> {
setTimeout(async () => {
await instance.textMessage(
{
number: remoteJid.split('@')[0],
number: remoteJid,
delay: settings?.delayMessage || 1000,
text: message,
linkPreview,
Expand Down
75 changes: 72 additions & 3 deletions src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,16 @@ export class ChatwootService {

return contact;
} catch (error) {
if ((error.status === 422 || error.response?.status === 422) && jid) {
this.logger.warn(`Contact with identifier ${jid} creation failed (422). Checking if it already exists...`);
const existingContact = await this.findContactByIdentifier(instance, jid);
if (existingContact) {
const contactId = existingContact.id;
await this.addLabelToContact(this.provider.nameInbox, contactId);
return existingContact;
}
}

this.logger.error('Error creating contact');
console.log(error);
return null;
Expand Down Expand Up @@ -415,6 +425,55 @@ export class ChatwootService {
}
}

public async findContactByIdentifier(instance: InstanceDto, identifier: string) {
const client = await this.clientCw(instance);

if (!client) {
this.logger.warn('client not found');
return null;
}

// Direct search by query (q) - most common way to search by identifier/email/phone
const contact = (await (client as any).get('contacts/search', {
params: {
q: identifier,
sort: 'name',
},
})) as any;

if (contact && contact.data && contact.data.payload && contact.data.payload.length > 0) {
return contact.data.payload[0];
}

// Fallback for older API versions or different response structures
if (contact && contact.payload && contact.payload.length > 0) {
return contact.payload[0];
}

// Try search by attribute
const contactByAttr = (await (client as any).post('contacts/filter', {
payload: [
{
attribute_key: 'identifier',
filter_operator: 'equal_to',
values: [identifier],
query_operator: null,
},
],
})) as any;

if (contactByAttr && contactByAttr.payload && contactByAttr.payload.length > 0) {
return contactByAttr.payload[0];
}

// Check inside data property if using axios interceptors wrapper
if (contactByAttr && contactByAttr.data && contactByAttr.data.payload && contactByAttr.data.payload.length > 0) {
return contactByAttr.data.payload[0];
}

return null;
}

public async findContact(instance: InstanceDto, phoneNumber: string) {
const client = await this.clientCw(instance);

Expand Down Expand Up @@ -1574,7 +1633,11 @@ export class ChatwootService {
this.logger.verbose(`Update result: ${result} rows affected`);

if (this.isImportHistoryAvailable()) {
chatwootImport.updateMessageSourceID(chatwootMessageIds.messageId, key.id);
try {
await chatwootImport.updateMessageSourceID(chatwootMessageIds.messageId, key.id);
} catch (error) {
this.logger.error(`Error updating Chatwoot message source ID: ${error}`);
}
}
}

Expand Down Expand Up @@ -2024,7 +2087,7 @@ export class ChatwootService {
if (body.key.remoteJid.includes('@g.us')) {
const participantName = body.pushName;
const rawPhoneNumber =
body.key.addressingMode === 'lid' && !body.key.fromMe
body.key.addressingMode === 'lid' && !body.key.fromMe && body.key.participantAlt
? body.key.participantAlt.split('@')[0].split(':')[0]
: body.key.participant.split('@')[0].split(':')[0];
const formattedPhoneNumber = parsePhoneNumberFromString(`+${rawPhoneNumber}`).formatInternational();
Expand Down Expand Up @@ -2206,7 +2269,7 @@ export class ChatwootService {
if (body.key.remoteJid.includes('@g.us')) {
const participantName = body.pushName;
const rawPhoneNumber =
body.key.addressingMode === 'lid' && !body.key.fromMe
body.key.addressingMode === 'lid' && !body.key.fromMe && body.key.participantAlt
? body.key.participantAlt.split('@')[0].split(':')[0]
: body.key.participant.split('@')[0].split(':')[0];
const formattedPhoneNumber = parsePhoneNumberFromString(`+${rawPhoneNumber}`).formatInternational();
Expand Down Expand Up @@ -2465,6 +2528,12 @@ export class ChatwootService {
}

public getNumberFromRemoteJid(remoteJid: string) {
if (!remoteJid) {
return '';
}
if (remoteJid.includes('@lid')) {
return remoteJid;
}
return remoteJid.replace(/:\d+/, '').split('@')[0];
}

Expand Down
10 changes: 5 additions & 5 deletions src/api/integrations/chatbot/typebot/services/typebot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
if (message.type === 'image') {
await instance.mediaMessage(
{
number: session.remoteJid.split('@')[0],
number: session.remoteJid,
delay: settings?.delayMessage || 1000,
mediatype: 'image',
media: message.content.url,
Expand All @@ -342,7 +342,7 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
if (message.type === 'video') {
await instance.mediaMessage(
{
number: session.remoteJid.split('@')[0],
number: session.remoteJid,
delay: settings?.delayMessage || 1000,
mediatype: 'video',
media: message.content.url,
Expand All @@ -357,7 +357,7 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
if (message.type === 'audio') {
await instance.audioWhatsapp(
{
number: session.remoteJid.split('@')[0],
number: session.remoteJid,
delay: settings?.delayMessage || 1000,
encoding: true,
audio: message.content.url,
Expand Down Expand Up @@ -441,7 +441,7 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
*/
private async processListMessage(instance: any, formattedText: string, remoteJid: string) {
const listJson = {
number: remoteJid.split('@')[0],
number: remoteJid,
title: '',
description: '',
buttonText: '',
Expand Down Expand Up @@ -490,7 +490,7 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
*/
private async processButtonMessage(instance: any, formattedText: string, remoteJid: string) {
const buttonJson = {
number: remoteJid.split('@')[0],
number: remoteJid,
thumbnailUrl: undefined,
title: '',
description: '',
Expand Down
Loading