Skip to content

Commit 27be03e

Browse files
Merge pull request #2162 from moothz/fix/saveOnWhatsappCache-remoteJid-failed-constraint
fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint)
2 parents 71322cd + 9b73252 commit 27be03e

File tree

1 file changed

+92
-48
lines changed

1 file changed

+92
-48
lines changed

src/utils/onWhatsappCache.ts

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -65,73 +65,117 @@ interface ISaveOnWhatsappCacheParams {
6565
lid?: 'lid' | undefined;
6666
}
6767

68+
function normalizeJid(jid: string | null | undefined): string | null {
69+
if (!jid) return null;
70+
return jid.startsWith('+') ? jid.slice(1) : jid;
71+
}
72+
6873
export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) {
69-
if (configService.get<Database>('DATABASE').SAVE_DATA.IS_ON_WHATSAPP) {
70-
for (const item of data) {
71-
const remoteJid = item.remoteJid.startsWith('+') ? item.remoteJid.slice(1) : item.remoteJid;
74+
if (!configService.get<Database>('DATABASE').SAVE_DATA.IS_ON_WHATSAPP) {
75+
return;
76+
}
7277

73-
// TODO: Buscar registro existente PRIMEIRO para preservar dados
74-
const allJids = [remoteJid];
78+
// Processa todos os itens em paralelo para melhor performance
79+
const processingPromises = data.map(async (item) => {
80+
try {
81+
const remoteJid = normalizeJid(item.remoteJid);
82+
if (!remoteJid) {
83+
logger.warn('[saveOnWhatsappCache] Item skipped, missing remoteJid.');
84+
return;
85+
}
7586

76-
const altJid =
77-
item.remoteJidAlt && item.remoteJidAlt.includes('@lid')
78-
? item.remoteJidAlt.startsWith('+')
79-
? item.remoteJidAlt.slice(1)
80-
: item.remoteJidAlt
81-
: null;
87+
const altJidNormalized = normalizeJid(item.remoteJidAlt);
88+
const lidAltJid = altJidNormalized && altJidNormalized.includes('@lid') ? altJidNormalized : null;
8289

83-
if (altJid) {
84-
allJids.push(altJid);
90+
const baseJids = [remoteJid]; // Garante que o remoteJid esteja na lista inicial
91+
if (lidAltJid) {
92+
baseJids.push(lidAltJid);
8593
}
8694

87-
const expandedJids = allJids.flatMap((jid) => getAvailableNumbers(jid));
95+
const expandedJids = baseJids.flatMap((jid) => getAvailableNumbers(jid));
8896

97+
// 1. Busca entrada por jidOptions e também remoteJid
98+
// Às vezes acontece do remoteJid atual NÃO ESTAR no jidOptions ainda, ocasionando o erro:
99+
// 'Unique constraint failed on the fields: (`remoteJid`)'
100+
// Isso acontece principalmente em grupos que possuem o número do criador no ID (ex.: '559911223345-1234567890@g.us')
89101
const existingRecord = await prismaRepository.isOnWhatsapp.findFirst({
90102
where: {
91-
OR: expandedJids.map((jid) => ({ jidOptions: { contains: jid } })),
103+
OR: [
104+
...expandedJids.map((jid) => ({ jidOptions: { contains: jid } })),
105+
{ remoteJid: remoteJid }, // TODO: Descobrir o motivo que causa o remoteJid não estar (às vezes) incluso na lista de jidOptions
106+
],
92107
},
93108
});
94109

95-
logger.verbose(`Register exists: ${existingRecord ? existingRecord.remoteJid : 'não not found'}`);
110+
logger.verbose(
111+
`[saveOnWhatsappCache] Register exists for [${expandedJids.join(',')}]? => ${existingRecord ? existingRecord.remoteJid : 'Not found'}`,
112+
);
96113

97-
const finalJidOptions = [...expandedJids];
114+
// 2. Unifica todos os JIDs usando um Set para garantir valores únicos
115+
const finalJidOptions = new Set(expandedJids);
98116

99-
if (existingRecord?.jidOptions) {
100-
const existingJids = existingRecord.jidOptions.split(',');
101-
// TODO: Adicionar JIDs existentes que não estão na lista atual
102-
existingJids.forEach((jid) => {
103-
if (!finalJidOptions.includes(jid)) {
104-
finalJidOptions.push(jid);
105-
}
106-
});
117+
if (lidAltJid) {
118+
finalJidOptions.add(lidAltJid);
107119
}
108120

109-
// TODO: Se tiver remoteJidAlt com @lid novo, adicionar
110-
if (altJid && !finalJidOptions.includes(altJid)) {
111-
finalJidOptions.push(altJid);
121+
if (existingRecord?.jidOptions) {
122+
existingRecord.jidOptions.split(',').forEach((jid) => finalJidOptions.add(jid));
112123
}
113124

114-
const uniqueNumbers = Array.from(new Set(finalJidOptions));
115-
116-
logger.verbose(
117-
`Saving: remoteJid=${remoteJid}, jidOptions=${uniqueNumbers.join(',')}, lid=${item.lid === 'lid' || item.remoteJid?.includes('@lid') ? 'lid' : null}`,
118-
);
119-
120-
await prismaRepository.isOnWhatsapp.upsert({
121-
where: { remoteJid: remoteJid },
122-
123-
update: {
124-
jidOptions: uniqueNumbers.join(','),
125-
lid: item.lid === 'lid' || item.remoteJid?.includes('@lid') ? 'lid' : null,
126-
},
127-
create: {
128-
remoteJid: remoteJid,
129-
jidOptions: uniqueNumbers.join(','),
130-
lid: item.lid === 'lid' || item.remoteJid?.includes('@lid') ? 'lid' : null,
131-
},
132-
});
125+
// 3. Prepara o payload final
126+
// Ordena os JIDs para garantir consistência na string final
127+
const sortedJidOptions = [...finalJidOptions].sort();
128+
const newJidOptionsString = sortedJidOptions.join(',');
129+
const newLid = item.lid === 'lid' || item.remoteJid?.includes('@lid') ? 'lid' : null;
130+
131+
const dataPayload = {
132+
remoteJid: remoteJid,
133+
jidOptions: newJidOptionsString,
134+
lid: newLid,
135+
};
136+
137+
// 4. Decide entre Criar ou Atualizar
138+
if (existingRecord) {
139+
// Compara a string de JIDs ordenada existente com a nova
140+
const existingJidOptionsString = existingRecord.jidOptions
141+
? existingRecord.jidOptions.split(',').sort().join(',')
142+
: '';
143+
144+
const isDataSame =
145+
existingRecord.remoteJid === dataPayload.remoteJid &&
146+
existingJidOptionsString === dataPayload.jidOptions &&
147+
existingRecord.lid === dataPayload.lid;
148+
149+
if (isDataSame) {
150+
logger.verbose(`[saveOnWhatsappCache] Data for ${remoteJid} is already up-to-date. Skipping update.`);
151+
return; // Pula para o próximo item
152+
}
153+
154+
// Os dados são diferentes, então atualiza
155+
logger.verbose(
156+
`[saveOnWhatsappCache] Register exists, updating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}, lid=${dataPayload.lid}`,
157+
);
158+
await prismaRepository.isOnWhatsapp.update({
159+
where: { id: existingRecord.id },
160+
data: dataPayload,
161+
});
162+
} else {
163+
// Cria nova entrada
164+
logger.verbose(
165+
`[saveOnWhatsappCache] Register does not exist, creating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}, lid=${dataPayload.lid}`,
166+
);
167+
await prismaRepository.isOnWhatsapp.create({
168+
data: dataPayload,
169+
});
170+
}
171+
} catch (e) {
172+
// Loga o erro mas não para a execução dos outros promises
173+
logger.error(`[saveOnWhatsappCache] Error processing item for ${item.remoteJid}: `, e);
133174
}
134-
}
175+
});
176+
177+
// Espera todas as operações paralelas terminarem
178+
await Promise.allSettled(processingPromises);
135179
}
136180

137181
export async function getOnWhatsappCache(remoteJids: string[]) {

0 commit comments

Comments
 (0)