mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 07:04:50 -06:00
feat(IsOnWhatsapp): add optional lid field and update related logic
- Introduced a new optional `lid` field in the IsOnWhatsapp model to enhance data tracking. - Updated migration script to add the `lid` column to the database. - Modified OnWhatsAppDto to include the `lid` property for better integration with WhatsApp user data. - Enhanced the WhatsApp Baileys service to handle `lid` numbers separately and improve user verification logic. - Updated cache handling functions to support the new `lid` field for consistent data management.
This commit is contained in:
parent
c17b48bca0
commit
afc2927837
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "IsOnWhatsapp" ADD COLUMN "lid" VARCHAR(100);
|
@ -648,6 +648,7 @@ model IsOnWhatsapp {
|
||||
id String @id @default(cuid())
|
||||
remoteJid String @unique @db.VarChar(100)
|
||||
jidOptions String
|
||||
lid String? @db.VarChar(100)
|
||||
createdAt DateTime @default(now()) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ export class OnWhatsAppDto {
|
||||
public readonly exists: boolean,
|
||||
public readonly number: string,
|
||||
public readonly name?: string,
|
||||
public readonly lid?: string,
|
||||
) {}
|
||||
}
|
||||
|
||||
|
@ -1170,7 +1170,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
) {
|
||||
const chatwootSentMessage = await this.chatwootService.eventWhatsapp(
|
||||
Events.MESSAGES_UPSERT,
|
||||
{ instanceName: this.instance.name, instanceId: this.instance.id },
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
messageRaw,
|
||||
);
|
||||
|
||||
@ -3131,10 +3131,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
const group = await this.findGroup({ groupJid: jid }, 'inner');
|
||||
|
||||
if (!group) {
|
||||
new OnWhatsAppDto(jid, false, number);
|
||||
return new OnWhatsAppDto(jid, false, number);
|
||||
}
|
||||
|
||||
return new OnWhatsAppDto(group.id, !!group?.id, number, group?.subject);
|
||||
return new OnWhatsAppDto(group.id, true, number, group?.subject);
|
||||
}),
|
||||
);
|
||||
onWhatsapp.push(...groups);
|
||||
@ -3144,84 +3144,126 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
where: { instanceId: this.instanceId, remoteJid: { in: jids.users.map(({ jid }) => jid) } },
|
||||
});
|
||||
|
||||
const numbersToVerify = jids.users.map(({ jid }) => jid.replace('+', ''));
|
||||
// Separate @lid numbers from normal numbers
|
||||
const lidUsers = jids.users.filter(({ jid }) => jid.includes('@lid'));
|
||||
const normalUsers = jids.users.filter(({ jid }) => !jid.includes('@lid'));
|
||||
|
||||
const cachedNumbers = await getOnWhatsappCache(numbersToVerify);
|
||||
const filteredNumbers = numbersToVerify.filter(
|
||||
(jid) => !cachedNumbers.some((cached) => cached.jidOptions.includes(jid)),
|
||||
);
|
||||
// For normal numbers, use traditional Baileys verification
|
||||
let normalVerifiedUsers: OnWhatsAppDto[] = [];
|
||||
if (normalUsers.length > 0) {
|
||||
console.log('normalUsers', normalUsers);
|
||||
const numbersToVerify = normalUsers.map(({ jid }) => jid.replace('+', ''));
|
||||
console.log('numbersToVerify', numbersToVerify);
|
||||
|
||||
const verify = await this.client.onWhatsApp(...filteredNumbers);
|
||||
const users: OnWhatsAppDto[] = await Promise.all(
|
||||
jids.users.map(async (user) => {
|
||||
let numberVerified: (typeof verify)[0] | null = null;
|
||||
const cachedNumbers = await getOnWhatsappCache(numbersToVerify);
|
||||
console.log('cachedNumbers', cachedNumbers);
|
||||
|
||||
const cached = cachedNumbers.find((cached) => cached.jidOptions.includes(user.jid.replace('+', '')));
|
||||
if (cached) {
|
||||
return {
|
||||
exists: true,
|
||||
jid: cached.remoteJid,
|
||||
name: contacts.find((c) => c.remoteJid === cached.remoteJid)?.pushName,
|
||||
number: user.number,
|
||||
};
|
||||
}
|
||||
const filteredNumbers = numbersToVerify.filter(
|
||||
(jid) => !cachedNumbers.some((cached) => cached.jidOptions.includes(jid)),
|
||||
);
|
||||
console.log('filteredNumbers', filteredNumbers);
|
||||
|
||||
// Brazilian numbers
|
||||
if (user.number.startsWith('55')) {
|
||||
const numberWithDigit =
|
||||
user.number.slice(4, 5) === '9' && user.number.length === 13
|
||||
? user.number
|
||||
: `${user.number.slice(0, 4)}9${user.number.slice(4)}`;
|
||||
const numberWithoutDigit =
|
||||
user.number.length === 12 ? user.number : user.number.slice(0, 4) + user.number.slice(5);
|
||||
const verify = await this.client.onWhatsApp(...filteredNumbers);
|
||||
console.log('verify', verify);
|
||||
normalVerifiedUsers = await Promise.all(
|
||||
normalUsers.map(async (user) => {
|
||||
let numberVerified: (typeof verify)[0] | null = null;
|
||||
|
||||
numberVerified = verify.find(
|
||||
(v) => v.jid === `${numberWithDigit}@s.whatsapp.net` || v.jid === `${numberWithoutDigit}@s.whatsapp.net`,
|
||||
);
|
||||
}
|
||||
|
||||
// Mexican/Argentina numbers
|
||||
// Ref: https://faq.whatsapp.com/1294841057948784
|
||||
if (!numberVerified && (user.number.startsWith('52') || user.number.startsWith('54'))) {
|
||||
let prefix = '';
|
||||
if (user.number.startsWith('52')) {
|
||||
prefix = '';
|
||||
}
|
||||
if (user.number.startsWith('54')) {
|
||||
prefix = '9';
|
||||
const cached = cachedNumbers.find((cached) => cached.jidOptions.includes(user.jid.replace('+', '')));
|
||||
if (cached) {
|
||||
return new OnWhatsAppDto(
|
||||
cached.remoteJid,
|
||||
true,
|
||||
user.number,
|
||||
contacts.find((c) => c.remoteJid === cached.remoteJid)?.pushName,
|
||||
cached.lid || (cached.remoteJid.includes('@lid') ? cached.remoteJid.split('@')[1] : undefined),
|
||||
);
|
||||
}
|
||||
|
||||
const numberWithDigit =
|
||||
user.number.slice(2, 3) === prefix && user.number.length === 13
|
||||
? user.number
|
||||
: `${user.number.slice(0, 2)}${prefix}${user.number.slice(2)}`;
|
||||
const numberWithoutDigit =
|
||||
user.number.length === 12 ? user.number : user.number.slice(0, 2) + user.number.slice(3);
|
||||
// Brazilian numbers
|
||||
if (user.number.startsWith('55')) {
|
||||
const numberWithDigit =
|
||||
user.number.slice(4, 5) === '9' && user.number.length === 13
|
||||
? user.number
|
||||
: `${user.number.slice(0, 4)}9${user.number.slice(4)}`;
|
||||
const numberWithoutDigit =
|
||||
user.number.length === 12 ? user.number : user.number.slice(0, 4) + user.number.slice(5);
|
||||
|
||||
numberVerified = verify.find(
|
||||
(v) => v.jid === `${numberWithDigit}@s.whatsapp.net` || v.jid === `${numberWithoutDigit}@s.whatsapp.net`,
|
||||
numberVerified = verify.find(
|
||||
(v) => v.jid === `${numberWithDigit}@s.whatsapp.net` || v.jid === `${numberWithoutDigit}@s.whatsapp.net`,
|
||||
);
|
||||
}
|
||||
|
||||
// Mexican/Argentina numbers
|
||||
// Ref: https://faq.whatsapp.com/1294841057948784
|
||||
if (!numberVerified && (user.number.startsWith('52') || user.number.startsWith('54'))) {
|
||||
let prefix = '';
|
||||
if (user.number.startsWith('52')) {
|
||||
prefix = '1';
|
||||
}
|
||||
if (user.number.startsWith('54')) {
|
||||
prefix = '9';
|
||||
}
|
||||
|
||||
const numberWithDigit =
|
||||
user.number.slice(2, 3) === prefix && user.number.length === 13
|
||||
? user.number
|
||||
: `${user.number.slice(0, 2)}${prefix}${user.number.slice(2)}`;
|
||||
const numberWithoutDigit =
|
||||
user.number.length === 12 ? user.number : user.number.slice(0, 2) + user.number.slice(3);
|
||||
|
||||
numberVerified = verify.find(
|
||||
(v) => v.jid === `${numberWithDigit}@s.whatsapp.net` || v.jid === `${numberWithoutDigit}@s.whatsapp.net`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!numberVerified) {
|
||||
numberVerified = verify.find((v) => v.jid === user.jid);
|
||||
}
|
||||
|
||||
const numberJid = numberVerified?.jid || user.jid;
|
||||
const lid =
|
||||
typeof numberVerified?.lid === 'string'
|
||||
? numberVerified.lid
|
||||
: numberJid.includes('@lid')
|
||||
? numberJid.split('@')[1]
|
||||
: undefined;
|
||||
return new OnWhatsAppDto(
|
||||
numberJid,
|
||||
!!numberVerified?.exists,
|
||||
user.number,
|
||||
contacts.find((c) => c.remoteJid === numberJid)?.pushName,
|
||||
lid,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!numberVerified) {
|
||||
numberVerified = verify.find((v) => v.jid === user.jid);
|
||||
}
|
||||
// For @lid numbers, always consider them as valid
|
||||
const lidVerifiedUsers: OnWhatsAppDto[] = lidUsers.map((user) => {
|
||||
return new OnWhatsAppDto(
|
||||
user.jid,
|
||||
true,
|
||||
user.number,
|
||||
contacts.find((c) => c.remoteJid === user.jid)?.pushName,
|
||||
user.jid.split('@')[1],
|
||||
);
|
||||
});
|
||||
|
||||
const numberJid = numberVerified?.jid || user.jid;
|
||||
// Combine results
|
||||
onWhatsapp.push(...normalVerifiedUsers, ...lidVerifiedUsers);
|
||||
|
||||
return {
|
||||
exists: !!numberVerified?.exists,
|
||||
jid: numberJid,
|
||||
name: contacts.find((c) => c.remoteJid === numberJid)?.pushName,
|
||||
number: user.number,
|
||||
};
|
||||
}),
|
||||
// Save to cache only valid numbers
|
||||
await saveOnWhatsappCache(
|
||||
onWhatsapp
|
||||
.filter((user) => user.exists)
|
||||
.map((user) => ({
|
||||
remoteJid: user.jid,
|
||||
jidOptions: user.jid.replace('+', ''),
|
||||
lid: user.lid,
|
||||
})),
|
||||
);
|
||||
|
||||
await saveOnWhatsappCache(users.filter((user) => user.exists).map((user) => ({ remoteJid: user.jid })));
|
||||
|
||||
onWhatsapp.push(...users);
|
||||
|
||||
return onWhatsapp;
|
||||
}
|
||||
|
||||
|
@ -46,14 +46,19 @@ export class ChatRouter extends RouterBroker {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('whatsappNumbers'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<WhatsAppNumberDto>({
|
||||
request: req,
|
||||
schema: whatsappNumberSchema,
|
||||
ClassRef: WhatsAppNumberDto,
|
||||
execute: (instance, data) => chatController.whatsappNumber(instance, data),
|
||||
});
|
||||
try {
|
||||
const response = await this.dataValidate<WhatsAppNumberDto>({
|
||||
request: req,
|
||||
schema: whatsappNumberSchema,
|
||||
ClassRef: WhatsAppNumberDto,
|
||||
execute: (instance, data) => chatController.whatsappNumber(instance, data),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return res.status(HttpStatus.BAD_REQUEST).json(error);
|
||||
}
|
||||
})
|
||||
.post(this.routerPath('markMessageAsRead'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<ReadMessageDto>({
|
||||
|
@ -52,7 +52,9 @@ function getAvailableNumbers(remoteJid: string) {
|
||||
|
||||
interface ISaveOnWhatsappCacheParams {
|
||||
remoteJid: string;
|
||||
lid?: string;
|
||||
}
|
||||
|
||||
export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) {
|
||||
if (configService.get<Database>('DATABASE').SAVE_DATA.IS_ON_WHATSAPP) {
|
||||
const upsertsQuery = data.map((item) => {
|
||||
@ -60,8 +62,15 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) {
|
||||
const numbersAvailable = getAvailableNumbers(remoteJid);
|
||||
|
||||
return prismaRepository.isOnWhatsapp.upsert({
|
||||
create: { remoteJid: remoteJid, jidOptions: numbersAvailable.join(',') },
|
||||
update: { jidOptions: numbersAvailable.join(',') },
|
||||
create: {
|
||||
remoteJid: remoteJid,
|
||||
jidOptions: numbersAvailable.join(','),
|
||||
lid: item.lid,
|
||||
},
|
||||
update: {
|
||||
jidOptions: numbersAvailable.join(','),
|
||||
lid: item.lid,
|
||||
},
|
||||
where: { remoteJid: remoteJid },
|
||||
});
|
||||
});
|
||||
@ -75,6 +84,7 @@ export async function getOnWhatsappCache(remoteJids: string[]) {
|
||||
remoteJid: string;
|
||||
number: string;
|
||||
jidOptions: string[];
|
||||
lid?: string;
|
||||
}[] = [];
|
||||
|
||||
if (configService.get<Database>('DATABASE').SAVE_DATA.IS_ON_WHATSAPP) {
|
||||
@ -93,6 +103,7 @@ export async function getOnWhatsappCache(remoteJids: string[]) {
|
||||
remoteJid: item.remoteJid,
|
||||
number: item.remoteJid.split('@')[0],
|
||||
jidOptions: item.jidOptions.split(','),
|
||||
lid: item.lid,
|
||||
}));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user