mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 15:14:49 -06:00
Refactor JID creation and fetch chats
- Introduced a new utility function `createJid` to standardize JID creation across the application, replacing the previous method in `ChannelStartupService`. - Updated multiple services to utilize the new `createJid` function for improved consistency and maintainability. - Added a `cleanMessageData` method in `ChannelStartupService` to sanitize message objects before processing. - Updated CHANGELOG to reflect the refactor on chat fetching logic and the introduction of the new JID utility.
This commit is contained in:
parent
b0219e5e5a
commit
ab5eb80edd
@ -9,6 +9,7 @@
|
||||
|
||||
* Correction of webhook global
|
||||
* Fixed send audio with whatsapp cloud api
|
||||
* Refactor on fetch chats
|
||||
|
||||
# 2.2.0 (2024-10-18 10:00)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { ChannelStartupService } from '@api/services/channel.service';
|
||||
import { Events, wa } from '@api/types/wa.types';
|
||||
import { Chatwoot, ConfigService, Openai } from '@config/env.config';
|
||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||
import { createJid } from '@utils/createJid';
|
||||
import { status } from '@utils/renderStatus';
|
||||
import { isURL } from 'class-validator';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
@ -57,7 +58,7 @@ export class EvolutionStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async profilePicture(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
return {
|
||||
wuid: jid,
|
||||
|
@ -22,6 +22,7 @@ import { ChannelStartupService } from '@api/services/channel.service';
|
||||
import { Events, wa } from '@api/types/wa.types';
|
||||
import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@config/env.config';
|
||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||
import { createJid } from '@utils/createJid';
|
||||
import { status } from '@utils/renderStatus';
|
||||
import axios from 'axios';
|
||||
import { arrayUnique, isURL } from 'class-validator';
|
||||
@ -88,7 +89,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async profilePicture(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
return {
|
||||
wuid: jid,
|
||||
@ -132,9 +133,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
|
||||
this.eventHandler(content);
|
||||
|
||||
this.phoneNumber = this.createJid(
|
||||
content.messages ? content.messages[0].from : content.statuses[0]?.recipient_id,
|
||||
);
|
||||
this.phoneNumber = createJid(content.messages ? content.messages[0].from : content.statuses[0]?.recipient_id);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new InternalServerErrorException(error?.toString());
|
||||
@ -231,7 +230,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
if (!contact.phones[0]?.wa_id) {
|
||||
contact.phones[0].wa_id = this.createJid(contact.phones[0].phone);
|
||||
contact.phones[0].wa_id = createJid(contact.phones[0].phone);
|
||||
}
|
||||
|
||||
result +=
|
||||
@ -915,7 +914,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
const messageRaw: any = {
|
||||
key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: this.createJid(number) },
|
||||
key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: createJid(number) },
|
||||
message: this.convertMessageToRaw(message, content),
|
||||
messageType: this.renderMessageType(content.type),
|
||||
messageTimestamp: (messageSent?.messages[0]?.timestamp as number) || Math.round(new Date().getTime() / 1000),
|
||||
@ -1274,7 +1273,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
if (!contact.wuid) {
|
||||
contact.wuid = this.createJid(contact.phoneNumber);
|
||||
contact.wuid = createJid(contact.phoneNumber);
|
||||
}
|
||||
|
||||
result += `item1.TEL;waid=${contact.wuid}:${contact.phoneNumber}\n` + 'item1.X-ABLabel:Celular\n' + 'END:VCARD';
|
||||
|
@ -78,6 +78,7 @@ import ffmpegPath from '@ffmpeg-installer/ffmpeg';
|
||||
import { Boom } from '@hapi/boom';
|
||||
import { createId as cuid } from '@paralleldrive/cuid2';
|
||||
import { Instance } from '@prisma/client';
|
||||
import { createJid } from '@utils/createJid';
|
||||
import { makeProxyAgent } from '@utils/makeProxyAgent';
|
||||
import { getOnWhatsappCache, saveOnWhatsappCache } from '@utils/onWhatsappCache';
|
||||
import { status } from '@utils/renderStatus';
|
||||
@ -1323,17 +1324,21 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
|
||||
if (this.localWebhook.enabled) {
|
||||
if (isMedia && this.localWebhook.webhookBase64) {
|
||||
const buffer = await downloadMediaMessage(
|
||||
{ key: received.key, message: received?.message },
|
||||
'buffer',
|
||||
{},
|
||||
{
|
||||
logger: P({ level: 'error' }) as any,
|
||||
reuploadRequest: this.client.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
try {
|
||||
const buffer = await downloadMediaMessage(
|
||||
{ key: received.key, message: received?.message },
|
||||
'buffer',
|
||||
{},
|
||||
{
|
||||
logger: P({ level: 'error' }) as any,
|
||||
reuploadRequest: this.client.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
|
||||
messageRaw.message.base64 = buffer ? buffer.toString('base64') : undefined;
|
||||
messageRaw.message.base64 = buffer ? buffer.toString('base64') : undefined;
|
||||
} catch (error) {
|
||||
this.logger.error(['Error converting media to base64', error?.message]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1809,7 +1814,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async profilePicture(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
try {
|
||||
const profilePictureUrl = await this.client.profilePictureUrl(jid, 'image');
|
||||
@ -1827,7 +1832,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async getStatus(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
try {
|
||||
return {
|
||||
@ -1843,7 +1848,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async fetchProfile(instanceName: string, number?: string) {
|
||||
const jid = number ? this.createJid(number) : this.client?.user?.id;
|
||||
const jid = number ? createJid(number) : this.client?.user?.id;
|
||||
|
||||
const onWhatsapp = (await this.whatsappNumber({ numbers: [jid] }))?.shift();
|
||||
|
||||
@ -1899,7 +1904,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async offerCall({ number, isVideo, callDuration }: OfferCallDto) {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
try {
|
||||
const call = await this.client.offerCall(jid, isVideo);
|
||||
@ -2170,7 +2175,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
mentions = group.participants.map((participant) => participant.id);
|
||||
} else if (options?.mentioned?.length) {
|
||||
mentions = options.mentioned.map((mention) => {
|
||||
const jid = this.createJid(mention);
|
||||
const jid = createJid(mention);
|
||||
if (isJidGroup(jid)) {
|
||||
return null;
|
||||
}
|
||||
@ -2292,17 +2297,21 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
|
||||
if (this.localWebhook.enabled) {
|
||||
if (isMedia && this.localWebhook.webhookBase64) {
|
||||
const buffer = await downloadMediaMessage(
|
||||
{ key: messageRaw.key, message: messageRaw?.message },
|
||||
'buffer',
|
||||
{},
|
||||
{
|
||||
logger: P({ level: 'error' }) as any,
|
||||
reuploadRequest: this.client.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
try {
|
||||
const buffer = await downloadMediaMessage(
|
||||
{ key: messageRaw.key, message: messageRaw?.message },
|
||||
'buffer',
|
||||
{},
|
||||
{
|
||||
logger: P({ level: 'error' }) as any,
|
||||
reuploadRequest: this.client.updateMediaMessage,
|
||||
},
|
||||
);
|
||||
|
||||
messageRaw.message.base64 = buffer ? buffer.toString('base64') : undefined;
|
||||
messageRaw.message.base64 = buffer ? buffer.toString('base64') : undefined;
|
||||
} catch (error) {
|
||||
this.logger.error(['Error converting media to base64', error?.message]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3240,7 +3249,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
if (!contact.wuid) {
|
||||
contact.wuid = this.createJid(contact.phoneNumber);
|
||||
contact.wuid = createJid(contact.phoneNumber);
|
||||
}
|
||||
|
||||
result += `item1.TEL;waid=${contact.wuid}:${contact.phoneNumber}\n` + 'item1.X-ABLabel:Celular\n' + 'END:VCARD';
|
||||
@ -3290,7 +3299,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
};
|
||||
|
||||
data.numbers.forEach((number) => {
|
||||
const jid = this.createJid(number);
|
||||
const jid = createJid(number);
|
||||
|
||||
if (isJidGroup(jid)) {
|
||||
jids.groups.push({ number, jid });
|
||||
@ -3483,7 +3492,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
archive: data.archive,
|
||||
lastMessages: [last_message],
|
||||
},
|
||||
this.createJid(number),
|
||||
createJid(number),
|
||||
);
|
||||
|
||||
return {
|
||||
@ -3520,7 +3529,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
markRead: false,
|
||||
lastMessages: [last_message],
|
||||
},
|
||||
this.createJid(number),
|
||||
createJid(number),
|
||||
);
|
||||
|
||||
return {
|
||||
@ -3725,7 +3734,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
|
||||
public async fetchBusinessProfile(number: string): Promise<NumberBusiness> {
|
||||
try {
|
||||
const jid = number ? this.createJid(number) : this.instance.wuid;
|
||||
const jid = number ? createJid(number) : this.instance.wuid;
|
||||
|
||||
const profile = await this.client.getBusinessProfile(jid);
|
||||
|
||||
@ -3873,7 +3882,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
}
|
||||
|
||||
public async updateMessage(data: UpdateMessageDto) {
|
||||
const jid = this.createJid(data.number);
|
||||
const jid = createJid(data.number);
|
||||
|
||||
const options = await this.formatUpdateMessage(data);
|
||||
|
||||
@ -4163,7 +4172,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
|
||||
const inviteUrl = inviteCode.inviteUrl;
|
||||
|
||||
const numbers = id.numbers.map((number) => this.createJid(number));
|
||||
const numbers = id.numbers.map((number) => createJid(number));
|
||||
const description = id.description ?? '';
|
||||
|
||||
const msg = `${description}\n\n${inviteUrl}`;
|
||||
@ -4234,7 +4243,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
|
||||
public async updateGParticipant(update: GroupUpdateParticipantDto) {
|
||||
try {
|
||||
const participants = update.participants.map((p) => this.createJid(p));
|
||||
const participants = update.participants.map((p) => createJid(p));
|
||||
const updateParticipants = await this.client.groupParticipantsUpdate(
|
||||
update.groupJid,
|
||||
participants,
|
||||
|
@ -12,7 +12,8 @@ import { Events, wa } from '@api/types/wa.types';
|
||||
import { Auth, Chatwoot, ConfigService, HttpServer } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { NotFoundException } from '@exceptions';
|
||||
import { Contact, Message } from '@prisma/client';
|
||||
import { Contact, Message, Prisma } from '@prisma/client';
|
||||
import { createJid } from '@utils/createJid';
|
||||
import { WASocket } from 'baileys';
|
||||
import { isArray } from 'class-validator';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
@ -487,47 +488,11 @@ export class ChannelStartupService {
|
||||
}
|
||||
}
|
||||
|
||||
public createJid(number: string): string {
|
||||
if (number.includes('@g.us') || number.includes('@s.whatsapp.net') || number.includes('@lid')) {
|
||||
return number;
|
||||
}
|
||||
|
||||
if (number.includes('@broadcast')) {
|
||||
return number;
|
||||
}
|
||||
|
||||
number = number
|
||||
?.replace(/\s/g, '')
|
||||
.replace(/\+/g, '')
|
||||
.replace(/\(/g, '')
|
||||
.replace(/\)/g, '')
|
||||
.split(':')[0]
|
||||
.split('@')[0];
|
||||
|
||||
if (number.includes('-') && number.length >= 24) {
|
||||
number = number.replace(/[^\d-]/g, '');
|
||||
return `${number}@g.us`;
|
||||
}
|
||||
|
||||
number = number.replace(/\D/g, '');
|
||||
|
||||
if (number.length >= 18) {
|
||||
number = number.replace(/[^\d-]/g, '');
|
||||
return `${number}@g.us`;
|
||||
}
|
||||
|
||||
number = this.formatMXOrARNumber(number);
|
||||
|
||||
number = this.formatBRNumber(number);
|
||||
|
||||
return `${number}@s.whatsapp.net`;
|
||||
}
|
||||
|
||||
public async fetchContacts(query: Query<Contact>) {
|
||||
const remoteJid = query?.where?.remoteJid
|
||||
? query?.where?.remoteJid.includes('@')
|
||||
? query.where?.remoteJid
|
||||
: this.createJid(query.where?.remoteJid)
|
||||
: createJid(query.where?.remoteJid)
|
||||
: null;
|
||||
|
||||
const where = {
|
||||
@ -543,6 +508,64 @@ export class ChannelStartupService {
|
||||
});
|
||||
}
|
||||
|
||||
public cleanMessageData(message: any) {
|
||||
if (!message) return message;
|
||||
|
||||
const cleanedMessage = { ...message };
|
||||
|
||||
const mediaUrl = cleanedMessage.message.mediaUrl;
|
||||
|
||||
delete cleanedMessage.message.base64;
|
||||
|
||||
if (cleanedMessage.message) {
|
||||
// Limpa imageMessage
|
||||
if (cleanedMessage.message.imageMessage) {
|
||||
cleanedMessage.message.imageMessage = {
|
||||
caption: cleanedMessage.message.imageMessage.caption,
|
||||
};
|
||||
}
|
||||
|
||||
// Limpa videoMessage
|
||||
if (cleanedMessage.message.videoMessage) {
|
||||
cleanedMessage.message.videoMessage = {
|
||||
caption: cleanedMessage.message.videoMessage.caption,
|
||||
};
|
||||
}
|
||||
|
||||
// Limpa audioMessage
|
||||
if (cleanedMessage.message.audioMessage) {
|
||||
cleanedMessage.message.audioMessage = {
|
||||
seconds: cleanedMessage.message.audioMessage.seconds,
|
||||
};
|
||||
}
|
||||
|
||||
// Limpa stickerMessage
|
||||
if (cleanedMessage.message.stickerMessage) {
|
||||
cleanedMessage.message.stickerMessage = {};
|
||||
}
|
||||
|
||||
// Limpa documentMessage
|
||||
if (cleanedMessage.message.documentMessage) {
|
||||
cleanedMessage.message.documentMessage = {
|
||||
caption: cleanedMessage.message.documentMessage.caption,
|
||||
name: cleanedMessage.message.documentMessage.name,
|
||||
};
|
||||
}
|
||||
|
||||
// Limpa documentWithCaptionMessage
|
||||
if (cleanedMessage.message.documentWithCaptionMessage) {
|
||||
cleanedMessage.message.documentWithCaptionMessage = {
|
||||
caption: cleanedMessage.message.documentWithCaptionMessage.caption,
|
||||
name: cleanedMessage.message.documentWithCaptionMessage.name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaUrl) cleanedMessage.message.mediaUrl = mediaUrl;
|
||||
|
||||
return cleanedMessage;
|
||||
}
|
||||
|
||||
public async fetchMessages(query: Query<Message>) {
|
||||
const keyFilters = query?.where?.key as {
|
||||
id?: string;
|
||||
@ -648,113 +671,95 @@ export class ChannelStartupService {
|
||||
const remoteJid = query?.where?.remoteJid
|
||||
? query?.where?.remoteJid.includes('@')
|
||||
? query.where?.remoteJid
|
||||
: this.createJid(query.where?.remoteJid)
|
||||
: createJid(query.where?.remoteJid)
|
||||
: null;
|
||||
|
||||
let results = [];
|
||||
const where = {
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
if (!remoteJid) {
|
||||
results = await this.prismaRepository.$queryRaw`
|
||||
SELECT
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
"Chat"."labels",
|
||||
"Chat"."createdAt",
|
||||
"Chat"."updatedAt",
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl",
|
||||
"Chat"."unreadMessages",
|
||||
(ARRAY_AGG("Message"."id" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_id,
|
||||
(ARRAY_AGG("Message"."key" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_key,
|
||||
(ARRAY_AGG("Message"."pushName" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_push_name,
|
||||
(ARRAY_AGG("Message"."participant" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_participant,
|
||||
(ARRAY_AGG("Message"."messageType" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message_type,
|
||||
(ARRAY_AGG("Message"."message" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message,
|
||||
(ARRAY_AGG("Message"."contextInfo" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_context_info,
|
||||
(ARRAY_AGG("Message"."source" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_source,
|
||||
(ARRAY_AGG("Message"."messageTimestamp" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message_timestamp,
|
||||
(ARRAY_AGG("Message"."instanceId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_instance_id,
|
||||
(ARRAY_AGG("Message"."sessionId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_session_id,
|
||||
(ARRAY_AGG("Message"."status" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_status
|
||||
FROM "Chat"
|
||||
LEFT JOIN "Message" ON "Message"."messageType" != 'reactionMessage' and "Message"."key"->>'remoteJid' = "Chat"."remoteJid" AND "Chat"."instanceId" = "Message"."instanceId"
|
||||
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid" AND "Chat"."instanceId" = "Contact"."instanceId"
|
||||
WHERE
|
||||
"Chat"."instanceId" = ${this.instanceId}
|
||||
GROUP BY
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Contact"."id"
|
||||
ORDER BY last_message_message_timestamp DESC NULLS LAST, "Chat"."updatedAt" DESC;
|
||||
`;
|
||||
} else {
|
||||
results = await this.prismaRepository.$queryRaw`
|
||||
SELECT
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
"Chat"."labels",
|
||||
"Chat"."createdAt",
|
||||
"Chat"."updatedAt",
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl",
|
||||
"Chat"."unreadMessages",
|
||||
(ARRAY_AGG("Message"."id" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_id,
|
||||
(ARRAY_AGG("Message"."key" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_key,
|
||||
(ARRAY_AGG("Message"."pushName" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_push_name,
|
||||
(ARRAY_AGG("Message"."participant" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_participant,
|
||||
(ARRAY_AGG("Message"."messageType" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message_type,
|
||||
(ARRAY_AGG("Message"."message" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message,
|
||||
(ARRAY_AGG("Message"."contextInfo" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_context_info,
|
||||
(ARRAY_AGG("Message"."source" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_source,
|
||||
(ARRAY_AGG("Message"."messageTimestamp" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_message_timestamp,
|
||||
(ARRAY_AGG("Message"."instanceId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_instance_id,
|
||||
(ARRAY_AGG("Message"."sessionId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_session_id,
|
||||
(ARRAY_AGG("Message"."status" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_status
|
||||
FROM "Chat"
|
||||
LEFT JOIN "Message" ON "Message"."messageType" != 'reactionMessage' and "Message"."key"->>'remoteJid' = "Chat"."remoteJid" AND "Chat"."instanceId" = "Message"."instanceId"
|
||||
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid" AND "Chat"."instanceId" = "Contact"."instanceId"
|
||||
WHERE
|
||||
"Chat"."instanceId" = ${this.instanceId} AND "Chat"."remoteJid" = ${remoteJid} and "Message"."messageType" != 'reactionMessage'
|
||||
GROUP BY
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Contact"."id"
|
||||
ORDER BY last_message_message_timestamp DESC NULLS LAST, "Chat"."updatedAt" DESC;
|
||||
`;
|
||||
if (remoteJid) {
|
||||
where['remoteJid'] = remoteJid;
|
||||
}
|
||||
|
||||
const results = await this.prismaRepository.$queryRaw`
|
||||
WITH rankedMessages AS (
|
||||
SELECT DISTINCT ON ("Contact"."remoteJid")
|
||||
"Contact"."id",
|
||||
"Contact"."remoteJid",
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl",
|
||||
COALESCE(
|
||||
to_timestamp("Message"."messageTimestamp"::double precision),
|
||||
"Contact"."updatedAt"
|
||||
) as "updatedAt",
|
||||
"Chat"."createdAt" as "windowStart",
|
||||
"Chat"."createdAt" + INTERVAL '24 hours' as "windowExpires",
|
||||
CASE
|
||||
WHEN "Chat"."createdAt" + INTERVAL '24 hours' > NOW() THEN true
|
||||
ELSE false
|
||||
END as "windowActive",
|
||||
"Message"."id" AS lastMessageId,
|
||||
"Message"."key" AS lastMessage_key,
|
||||
"Message"."pushName" AS lastMessagePushName,
|
||||
"Message"."participant" AS lastMessageParticipant,
|
||||
"Message"."messageType" AS lastMessageMessageType,
|
||||
"Message"."message" AS lastMessageMessage,
|
||||
"Message"."contextInfo" AS lastMessageContextInfo,
|
||||
"Message"."source" AS lastMessageSource,
|
||||
"Message"."messageTimestamp" AS lastMessageMessageTimestamp,
|
||||
"Message"."instanceId" AS lastMessageInstanceId,
|
||||
"Message"."sessionId" AS lastMessageSessionId,
|
||||
"Message"."status" AS lastMessageStatus
|
||||
FROM "Contact"
|
||||
INNER JOIN "Message" ON "Message"."key"->>'remoteJid' = "Contact"."remoteJid"
|
||||
LEFT JOIN "Chat" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
||||
AND "Chat"."instanceId" = "Contact"."instanceId"
|
||||
WHERE
|
||||
"Contact"."instanceId" = ${this.instanceId}
|
||||
AND "Message"."instanceId" = ${this.instanceId}
|
||||
${remoteJid ? Prisma.sql`AND "Contact"."remoteJid" = ${remoteJid}` : Prisma.sql``}
|
||||
ORDER BY
|
||||
"Contact"."remoteJid",
|
||||
"Message"."messageTimestamp" DESC
|
||||
)
|
||||
SELECT * FROM rankedMessages
|
||||
ORDER BY updatedAt DESC NULLS LAST;
|
||||
`;
|
||||
|
||||
if (results && isArray(results) && results.length > 0) {
|
||||
return results.map((chat) => {
|
||||
const mappedResults = results.map((contact) => {
|
||||
const lastMessage = contact.lastMessageId
|
||||
? {
|
||||
id: contact.lastMessageId,
|
||||
key: contact.lastMessageKey,
|
||||
pushName: contact.lastMessagePushName,
|
||||
participant: contact.lastMessageParticipant,
|
||||
messageType: contact.lastMessageMessageType,
|
||||
message: contact.lastMessageMessage,
|
||||
contextInfo: contact.lastMessageContextInfo,
|
||||
source: contact.lastMessageSource,
|
||||
messageTimestamp: contact.lastMessageMessageTimestamp,
|
||||
instanceId: contact.lastMessageInstanceId,
|
||||
sessionId: contact.lastMessageSessionId,
|
||||
status: contact.lastMessageStatus,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
id: chat.id,
|
||||
remoteJid: chat.remoteJid,
|
||||
name: chat.name,
|
||||
labels: chat.labels,
|
||||
createdAt: chat.createdAt,
|
||||
updatedAt: chat.updatedAt,
|
||||
pushName: chat.pushName,
|
||||
profilePicUrl: chat.profilePicUrl,
|
||||
unreadMessages: chat.unreadMessages,
|
||||
lastMessage: chat.last_message_id
|
||||
? {
|
||||
id: chat.last_message_id,
|
||||
key: chat.last_message_key,
|
||||
pushName: chat.last_message_push_name,
|
||||
participant: chat.last_message_participant,
|
||||
messageType: chat.last_message_message_type,
|
||||
message: chat.last_message_message,
|
||||
contextInfo: chat.last_message_context_info,
|
||||
source: chat.last_message_source,
|
||||
messageTimestamp: chat.last_message_message_timestamp,
|
||||
instanceId: chat.last_message_instance_id,
|
||||
sessionId: chat.last_message_session_id,
|
||||
status: chat.last_message_status,
|
||||
}
|
||||
: undefined,
|
||||
id: contact.id,
|
||||
remoteJid: contact.remoteJid,
|
||||
pushName: contact.pushName,
|
||||
profilePicUrl: contact.profilePicUrl,
|
||||
updatedAt: contact.updatedAt,
|
||||
windowStart: contact.windowStart,
|
||||
windowExpires: contact.windowExpires,
|
||||
windowActive: contact.windowActive,
|
||||
lastMessage: lastMessage ? this.cleanMessageData(lastMessage) : undefined,
|
||||
};
|
||||
});
|
||||
|
||||
return mappedResults;
|
||||
}
|
||||
|
||||
return [];
|
||||
|
71
src/utils/createJid.ts
Normal file
71
src/utils/createJid.ts
Normal file
@ -0,0 +1,71 @@
|
||||
// Check if the number is MX or AR
|
||||
function formatMXOrARNumber(jid: string): string {
|
||||
const countryCode = jid.substring(0, 2);
|
||||
|
||||
if (Number(countryCode) === 52 || Number(countryCode) === 54) {
|
||||
if (jid.length === 13) {
|
||||
const number = countryCode + jid.substring(3);
|
||||
return number;
|
||||
}
|
||||
|
||||
return jid;
|
||||
}
|
||||
return jid;
|
||||
}
|
||||
|
||||
// Check if the number is br
|
||||
function formatBRNumber(jid: string) {
|
||||
const regexp = new RegExp(/^(\d{2})(\d{2})\d{1}(\d{8})$/);
|
||||
if (regexp.test(jid)) {
|
||||
const match = regexp.exec(jid);
|
||||
if (match && match[1] === '55') {
|
||||
const joker = Number.parseInt(match[3][0]);
|
||||
const ddd = Number.parseInt(match[2]);
|
||||
if (joker < 7 || ddd < 31) {
|
||||
return match[0];
|
||||
}
|
||||
return match[1] + match[2] + match[3];
|
||||
}
|
||||
return jid;
|
||||
} else {
|
||||
return jid;
|
||||
}
|
||||
}
|
||||
|
||||
export function createJid(number: string): string {
|
||||
number = number.replace(/:\d+/, '');
|
||||
|
||||
if (number.includes('@g.us') || number.includes('@s.whatsapp.net') || number.includes('@lid')) {
|
||||
return number;
|
||||
}
|
||||
|
||||
if (number.includes('@broadcast')) {
|
||||
return number;
|
||||
}
|
||||
|
||||
number = number
|
||||
?.replace(/\s/g, '')
|
||||
.replace(/\+/g, '')
|
||||
.replace(/\(/g, '')
|
||||
.replace(/\)/g, '')
|
||||
.split(':')[0]
|
||||
.split('@')[0];
|
||||
|
||||
if (number.includes('-') && number.length >= 24) {
|
||||
number = number.replace(/[^\d-]/g, '');
|
||||
return `${number}@g.us`;
|
||||
}
|
||||
|
||||
number = number.replace(/\D/g, '');
|
||||
|
||||
if (number.length >= 18) {
|
||||
number = number.replace(/[^\d-]/g, '');
|
||||
return `${number}@g.us`;
|
||||
}
|
||||
|
||||
number = formatMXOrARNumber(number);
|
||||
|
||||
number = formatBRNumber(number);
|
||||
|
||||
return `${number}@s.whatsapp.net`;
|
||||
}
|
Loading…
Reference in New Issue
Block a user