From 57ea6707bc882b28fe93cb5bb408f7cc5766c83b Mon Sep 17 00:00:00 2001 From: Spiller Date: Mon, 29 Sep 2025 20:50:39 -0300 Subject: [PATCH 1/3] feat: convert LID to phoneNumber on GROUP_PARTICIPANTS_UPDATE --- .../whatsapp/whatsapp.baileys.service.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 34ef1366b..3e39db2db 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -1591,12 +1591,38 @@ export class BaileysStartupService extends ChannelStartupService { }); }, - 'group-participants.update': (participantsUpdate: { + 'group-participants.update': async (participantsUpdate: { id: string; participants: string[]; action: ParticipantAction; }) => { - this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, participantsUpdate); + try { + // Usa o mesmo método que o endpoint /group/participants + const groupParticipants = await this.findParticipants({ groupJid: participantsUpdate.id }); + + // Filtra apenas os participantes que estão no evento + const resolvedParticipants = participantsUpdate.participants.map((participantId) => { + const participantData = groupParticipants.participants.find(p => p.id === participantId); + + return { + jid: participantId, + phoneNumber: participantData?.phoneNumber || participantId, + name: participantData?.name, + imgUrl: participantData?.imgUrl, + }; + }); + + const enhancedParticipantsUpdate = { + ...participantsUpdate, + participants: resolvedParticipants + }; + + this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, enhancedParticipantsUpdate); + } catch (error) { + console.log('Erro ao buscar dados dos participantes para webhook:', error); + // Fallback - envia sem conversão + this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, participantsUpdate); + } this.updateGroupMetadataCache(participantsUpdate.id); }, From fb1fa4d91ad8845dc4ee4aa85d16c6dc137e7b26 Mon Sep 17 00:00:00 2001 From: Spiller Date: Tue, 30 Sep 2025 10:12:14 -0300 Subject: [PATCH 2/3] feat: add participantsData field maintaining backward compatibility - Keep original participants array (string[]) for backward compatibility - Add new participantsData field with resolved phone numbers and metadata - Consumers can migrate gradually from participants to participantsData - No breaking changes to existing webhook integrations Payload structure: - participants: string[] (original JID strings) - participantsData: object[] (enhanced with phoneNumber, name, imgUrl) --- .../whatsapp/whatsapp.baileys.service.ts | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 3e39db2db..ea6952124 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -1596,30 +1596,57 @@ export class BaileysStartupService extends ChannelStartupService { participants: string[]; action: ParticipantAction; }) => { + // ENHANCEMENT: Adds participantsData field while maintaining backward compatibility + // MAINTAINS: participants: string[] (original JID strings) + // ADDS: participantsData: { jid: string, phoneNumber: string, name?: string, imgUrl?: string }[] + // This enables LID to phoneNumber conversion without breaking existing webhook consumers + + // Helper to normalize participantId as phone number + const normalizePhoneNumber = (id: string): string => { + // Remove @lid, @s.whatsapp.net suffixes and extract just the number part + return id.split('@')[0]; + }; + try { // Usa o mesmo método que o endpoint /group/participants const groupParticipants = await this.findParticipants({ groupJid: participantsUpdate.id }); + // Validação para garantir que temos dados válidos + if (!groupParticipants?.participants || !Array.isArray(groupParticipants.participants)) { + throw new Error('Invalid participant data received from findParticipants'); + } + // Filtra apenas os participantes que estão no evento const resolvedParticipants = participantsUpdate.participants.map((participantId) => { const participantData = groupParticipants.participants.find(p => p.id === participantId); + let phoneNumber: string; + if (participantData?.phoneNumber) { + phoneNumber = participantData.phoneNumber; + } else { + phoneNumber = normalizePhoneNumber(participantId); + } + return { jid: participantId, - phoneNumber: participantData?.phoneNumber || participantId, + phoneNumber, name: participantData?.name, imgUrl: participantData?.imgUrl, }; }); + // Mantém formato original + adiciona dados resolvidos const enhancedParticipantsUpdate = { ...participantsUpdate, - participants: resolvedParticipants + participants: participantsUpdate.participants, // Mantém array original de strings + participantsData: resolvedParticipants // Adiciona dados resolvidos em campo separado }; this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, enhancedParticipantsUpdate); } catch (error) { - console.log('Erro ao buscar dados dos participantes para webhook:', error); + this.logger.error( + `Failed to resolve participant data for GROUP_PARTICIPANTS_UPDATE webhook: ${error.message} | Group: ${participantsUpdate.id} | Participants: ${participantsUpdate.participants.length}` + ); // Fallback - envia sem conversão this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, participantsUpdate); } From bedfb019aa8eb0efbc31275117d51314eeff43e2 Mon Sep 17 00:00:00 2001 From: Spiller Date: Mon, 6 Oct 2025 11:53:50 -0300 Subject: [PATCH 3/3] fix lint --- .../whatsapp/whatsapp.baileys.service.ts | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index ea6952124..44b0122c9 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -500,8 +500,8 @@ export class BaileysStartupService extends ChannelStartupService { try { // Use raw SQL to avoid JSON path issues const webMessageInfo = (await this.prismaRepository.$queryRaw` - SELECT * FROM "Message" - WHERE "instanceId" = ${this.instanceId} + SELECT * FROM "Message" + WHERE "instanceId" = ${this.instanceId} AND "key"->>'id' = ${key.id} `) as proto.IWebMessageInfo[]; @@ -1491,8 +1491,8 @@ export class BaileysStartupService extends ChannelStartupService { if (configDatabaseData.HISTORIC || configDatabaseData.NEW_MESSAGE) { // Use raw SQL to avoid JSON path issues const messages = (await this.prismaRepository.$queryRaw` - SELECT * FROM "Message" - WHERE "instanceId" = ${this.instanceId} + SELECT * FROM "Message" + WHERE "instanceId" = ${this.instanceId} AND "key"->>'id' = ${key.id} LIMIT 1 `) as any[]; @@ -1600,33 +1600,33 @@ export class BaileysStartupService extends ChannelStartupService { // MAINTAINS: participants: string[] (original JID strings) // ADDS: participantsData: { jid: string, phoneNumber: string, name?: string, imgUrl?: string }[] // This enables LID to phoneNumber conversion without breaking existing webhook consumers - + // Helper to normalize participantId as phone number const normalizePhoneNumber = (id: string): string => { // Remove @lid, @s.whatsapp.net suffixes and extract just the number part return id.split('@')[0]; }; - + try { - // Usa o mesmo método que o endpoint /group/participants + // Usa o mesmo método que o endpoint /group/participants const groupParticipants = await this.findParticipants({ groupJid: participantsUpdate.id }); - + // Validação para garantir que temos dados válidos if (!groupParticipants?.participants || !Array.isArray(groupParticipants.participants)) { throw new Error('Invalid participant data received from findParticipants'); } - + // Filtra apenas os participantes que estão no evento const resolvedParticipants = participantsUpdate.participants.map((participantId) => { - const participantData = groupParticipants.participants.find(p => p.id === participantId); - + const participantData = groupParticipants.participants.find((p) => p.id === participantId); + let phoneNumber: string; if (participantData?.phoneNumber) { phoneNumber = participantData.phoneNumber; } else { phoneNumber = normalizePhoneNumber(participantId); } - + return { jid: participantId, phoneNumber, @@ -1639,13 +1639,14 @@ export class BaileysStartupService extends ChannelStartupService { const enhancedParticipantsUpdate = { ...participantsUpdate, participants: participantsUpdate.participants, // Mantém array original de strings - participantsData: resolvedParticipants // Adiciona dados resolvidos em campo separado + // Adiciona dados resolvidos em campo separado + participantsData: resolvedParticipants, }; - + this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, enhancedParticipantsUpdate); } catch (error) { this.logger.error( - `Failed to resolve participant data for GROUP_PARTICIPANTS_UPDATE webhook: ${error.message} | Group: ${participantsUpdate.id} | Participants: ${participantsUpdate.participants.length}` + `Failed to resolve participant data for GROUP_PARTICIPANTS_UPDATE webhook: ${error.message} | Group: ${participantsUpdate.id} | Participants: ${participantsUpdate.participants.length}`, ); // Fallback - envia sem conversão this.sendDataWebhook(Events.GROUP_PARTICIPANTS_UPDATE, participantsUpdate); @@ -4514,7 +4515,7 @@ export class BaileysStartupService extends ChannelStartupService { // Use raw SQL to avoid JSON path issues const result = await this.prismaRepository.$executeRaw` - UPDATE "Message" + UPDATE "Message" SET "status" = ${status[4]} WHERE "instanceId" = ${this.instanceId} AND "key"->>'remoteJid' = ${remoteJid} @@ -4539,7 +4540,7 @@ export class BaileysStartupService extends ChannelStartupService { this.prismaRepository.chat.findFirst({ where: { remoteJid } }), // Use raw SQL to avoid JSON path issues this.prismaRepository.$queryRaw` - SELECT COUNT(*)::int as count FROM "Message" + SELECT COUNT(*)::int as count FROM "Message" WHERE "instanceId" = ${this.instanceId} AND "key"->>'remoteJid' = ${remoteJid} AND ("key"->>'fromMe')::boolean = false