mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-15 19:52:54 -06:00
Merge pull request #958 from jesus-chacon/features/last_message_in_chat
Added last message to fetch chats
This commit is contained in:
commit
f38f3e5ba5
@ -667,7 +667,6 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
instanceId: this.instanceId,
|
instanceId: this.instanceId,
|
||||||
remoteJid: chat.id,
|
remoteJid: chat.id,
|
||||||
name: chat.name,
|
name: chat.name,
|
||||||
unreadMessages: typeof chat.unreadCount === 'number' ? chat.unreadCount : 0,
|
|
||||||
},
|
},
|
||||||
data: { remoteJid: chat.id },
|
data: { remoteJid: chat.id },
|
||||||
});
|
});
|
||||||
@ -985,8 +984,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
for (const received of messages) {
|
for (const received of messages) {
|
||||||
if (received.message?.conversation || received.message?.extendedTextMessage?.text) {
|
if (received.message?.conversation || received.message?.extendedTextMessage?.text) {
|
||||||
const text = received.message?.conversation || received.message?.extendedTextMessage?.text;
|
const text = received.message?.conversation || received.message?.extendedTextMessage?.text;
|
||||||
|
|
||||||
if (text == 'requestPlaceholder' && !requestId) {
|
if (text == 'requestPlaceholder' && !requestId) {
|
||||||
const messageId = await this.client.requestPlaceholderResend(received.key);
|
const messageId = await this.client.requestPlaceholderResend(received.key);
|
||||||
|
|
||||||
console.log('requested placeholder resync, id=', messageId);
|
console.log('requested placeholder resync, id=', messageId);
|
||||||
} else if (requestId) {
|
} else if (requestId) {
|
||||||
console.log('Message received from phone, id=', requestId, received);
|
console.log('Message received from phone, id=', requestId, received);
|
||||||
@ -1020,6 +1021,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
message: received,
|
message: received,
|
||||||
retry: 0,
|
retry: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1036,7 +1038,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
received.message?.pollUpdateMessage ||
|
received.message?.pollUpdateMessage ||
|
||||||
!received?.message
|
!received?.message
|
||||||
) {
|
) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Long.isLong(received.messageTimestamp)) {
|
if (Long.isLong(received.messageTimestamp)) {
|
||||||
@ -1044,7 +1046,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (settings?.groupsIgnore && received.key.remoteJid.includes('@g.us')) {
|
if (settings?.groupsIgnore && received.key.remoteJid.includes('@g.us')) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageRaw = this.prepareMessage(received);
|
const messageRaw = this.prepareMessage(received);
|
||||||
@ -1107,6 +1109,17 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
data: messageRaw,
|
data: messageRaw,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (received.key.fromMe === false) {
|
||||||
|
if (msg.status === status[3]) {
|
||||||
|
this.logger.log(`Update not read messages ${received.key.remoteJid}`);
|
||||||
|
// is received not read message
|
||||||
|
await this.updateChatUnreadMessages(received.key.remoteJid);
|
||||||
|
} else if (msg.status === status[4]) {
|
||||||
|
this.logger.log(`Update readed messages ${received.key.remoteJid} - ${msg.messageTimestamp}`);
|
||||||
|
this.updateMessagesReadedByTimestamp(received.key.remoteJid, msg.messageTimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isMedia) {
|
if (isMedia) {
|
||||||
if (this.configService.get<S3>('S3').ENABLE) {
|
if (this.configService.get<S3>('S3').ENABLE) {
|
||||||
try {
|
try {
|
||||||
@ -1119,11 +1132,8 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { buffer, mediaType, fileName, size } = media;
|
const { buffer, mediaType, fileName, size } = media;
|
||||||
|
|
||||||
const mimetype = mime.getType(fileName).toString();
|
const mimetype = mime.getType(fileName).toString();
|
||||||
|
|
||||||
const fullName = join(`${this.instance.id}`, received.key.remoteJid, mediaType, fileName);
|
const fullName = join(`${this.instance.id}`, received.key.remoteJid, mediaType, fileName);
|
||||||
|
|
||||||
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, {
|
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, {
|
||||||
'Content-Type': mimetype,
|
'Content-Type': mimetype,
|
||||||
});
|
});
|
||||||
@ -1192,7 +1202,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (contactRaw.remoteJid === 'status@broadcast') {
|
if (contactRaw.remoteJid === 'status@broadcast') {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contact) {
|
if (contact) {
|
||||||
@ -1213,7 +1223,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
update: contactRaw,
|
update: contactRaw,
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
||||||
@ -1240,11 +1250,11 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'messages.update': async (args: WAMessageUpdate[], settings: any) => {
|
'messages.update': async (args: WAMessageUpdate[], settings: any) => {
|
||||||
const unreadChatToUpdate: Record<string, number> = {}; // {remoteJid: readedMessages}
|
const readChatToUpdate: Record<string, true> = {}; // {remoteJid: true}
|
||||||
|
|
||||||
for await (const { key, update } of args) {
|
for await (const { key, update } of args) {
|
||||||
if (settings?.groupsIgnore && key.remoteJid?.includes('@g.us')) {
|
if (settings?.groupsIgnore && key.remoteJid?.includes('@g.us')) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status[update.status] === 'READ' && key.fromMe) {
|
if (status[update.status] === 'READ' && key.fromMe) {
|
||||||
@ -1259,6 +1269,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
if (key.remoteJid !== 'status@broadcast') {
|
if (key.remoteJid !== 'status@broadcast') {
|
||||||
let pollUpdates: any;
|
let pollUpdates: any;
|
||||||
|
|
||||||
if (update.pollUpdates) {
|
if (update.pollUpdates) {
|
||||||
const pollCreation = await this.getMessage(key);
|
const pollCreation = await this.getMessage(key);
|
||||||
|
|
||||||
@ -1281,7 +1292,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!findMessage) {
|
if (!findMessage) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update.message === null && update.status === undefined) {
|
if (update.message === null && update.status === undefined) {
|
||||||
@ -1310,15 +1321,18 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
continue;
|
||||||
} else if (update.status !== undefined && status[update.status] !== findMessage.status) {
|
} else if (update.status !== undefined && status[update.status] !== findMessage.status) {
|
||||||
if (!unreadChatToUpdate[key.remoteJid!]) {
|
if (!key.fromMe && key.remoteJid) {
|
||||||
unreadChatToUpdate[key.remoteJid!] = 0;
|
readChatToUpdate[key.remoteJid] = true;
|
||||||
|
|
||||||
|
if (status[update.status] === status[4]) {
|
||||||
|
this.logger.log(`Update as read ${key.remoteJid} - ${findMessage.messageTimestamp}`);
|
||||||
|
this.updateMessagesReadedByTimestamp(key.remoteJid, findMessage.messageTimestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unreadChatToUpdate[key.remoteJid!]++;
|
await this.prismaRepository.message.update({
|
||||||
|
|
||||||
this.prismaRepository.message.update({
|
|
||||||
where: { id: findMessage.id },
|
where: { id: findMessage.id },
|
||||||
data: { status: status[update.status] },
|
data: { status: status[update.status] },
|
||||||
});
|
});
|
||||||
@ -1344,16 +1358,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for await (const [remoteJid, unreadMessages] of Object.entries(unreadChatToUpdate)) {
|
await Promise.all(Object.keys(readChatToUpdate).map((remoteJid) => this.updateChatUnreadMessages(remoteJid)));
|
||||||
const chat = await this.prismaRepository.chat.findFirst({ where: { remoteJid } });
|
|
||||||
|
|
||||||
if (chat) {
|
|
||||||
this.prismaRepository.chat.update({
|
|
||||||
where: { id: chat.id },
|
|
||||||
data: { unreadMessages: Math.max(0, chat.unreadMessages - unreadMessages) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3713,6 +3718,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
source: getDevice(message.key.id),
|
source: getDevice(message.key.id),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!messageRaw.status && message.key.fromMe === false) {
|
||||||
|
messageRaw.status = status[3]; // DELIVERED MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
if (messageRaw.message.extendedTextMessage) {
|
if (messageRaw.message.extendedTextMessage) {
|
||||||
messageRaw.messageType = 'conversation';
|
messageRaw.messageType = 'conversation';
|
||||||
messageRaw.message.conversation = messageRaw.message.extendedTextMessage.text;
|
messageRaw.message.conversation = messageRaw.message.extendedTextMessage.text;
|
||||||
@ -3740,4 +3749,52 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
task.start();
|
task.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async updateMessagesReadedByTimestamp(remoteJid: string, timestamp?: number): Promise<number> {
|
||||||
|
if (timestamp === undefined || timestamp === null) return 0;
|
||||||
|
|
||||||
|
const result = await this.prismaRepository.message.updateMany({
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{ key: { path: ['remoteJid'], equals: remoteJid } },
|
||||||
|
{ key: { path: ['fromMe'], equals: false } },
|
||||||
|
{ messageTimestamp: { lte: timestamp } },
|
||||||
|
{
|
||||||
|
OR: [{ status: null }, { status: status[3] }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
data: { status: status[4] },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return result.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateChatUnreadMessages(remoteJid: string): Promise<number> {
|
||||||
|
const [chat, unreadMessages] = await Promise.all([
|
||||||
|
this.prismaRepository.chat.findFirst({ where: { remoteJid } }),
|
||||||
|
this.prismaRepository.message.count({
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{ key: { path: ['remoteJid'], equals: remoteJid } },
|
||||||
|
{ key: { path: ['fromMe'], equals: false } },
|
||||||
|
{ status: { equals: status[3] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (chat && chat.unreadMessages !== unreadMessages) {
|
||||||
|
await this.prismaRepository.chat.update({
|
||||||
|
where: { id: chat.id },
|
||||||
|
data: { unreadMessages },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return unreadMessages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import { Logger } from '@config/logger.config';
|
|||||||
import { NotFoundException } from '@exceptions';
|
import { NotFoundException } from '@exceptions';
|
||||||
import { Contact, Message } from '@prisma/client';
|
import { Contact, Message } from '@prisma/client';
|
||||||
import { WASocket } from 'baileys';
|
import { WASocket } from 'baileys';
|
||||||
|
import { isArray } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
@ -627,35 +628,114 @@ export class ChannelStartupService {
|
|||||||
: this.createJid(query.where?.remoteJid)
|
: this.createJid(query.where?.remoteJid)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const result = await this.prismaRepository.$queryRaw`
|
let results = [];
|
||||||
SELECT
|
|
||||||
"Chat"."id",
|
|
||||||
"Chat"."remoteJid",
|
|
||||||
"Chat"."name",
|
|
||||||
"Chat"."labels",
|
|
||||||
"Chat"."createdAt",
|
|
||||||
"Chat"."updatedAt",
|
|
||||||
"Contact"."pushName",
|
|
||||||
"Contact"."profilePicUrl",
|
|
||||||
"Contact"."unreadMessages"
|
|
||||||
FROM "Chat"
|
|
||||||
INNER JOIN "Message" ON "Chat"."remoteJid" = "Message"."key"->>'remoteJid'
|
|
||||||
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
|
||||||
WHERE "Chat"."instanceId" = ${this.instanceId}
|
|
||||||
${remoteJid ? 'AND "Chat"."remoteJid" = ${remoteJid}' : ''}
|
|
||||||
GROUP BY
|
|
||||||
"Chat"."id",
|
|
||||||
"Chat"."remoteJid",
|
|
||||||
"Chat"."name",
|
|
||||||
"Chat"."labels",
|
|
||||||
"Chat"."createdAt",
|
|
||||||
"Chat"."updatedAt",
|
|
||||||
"Contact"."pushName",
|
|
||||||
"Contact"."profilePicUrl",
|
|
||||||
"Contact"."unreadMessages"
|
|
||||||
ORDER BY "Chat"."updatedAt" DESC;
|
|
||||||
`;
|
|
||||||
|
|
||||||
return result;
|
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_pushName,
|
||||||
|
(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_messageType,
|
||||||
|
(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_contextInfo,
|
||||||
|
(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_messageTimestamp,
|
||||||
|
(ARRAY_AGG("Message"."instanceId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_instanceId,
|
||||||
|
(ARRAY_AGG("Message"."sessionId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_sessionId,
|
||||||
|
(ARRAY_AGG("Message"."status" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_status
|
||||||
|
FROM "Chat"
|
||||||
|
LEFT JOIN "Message" ON "Message"."key"->>'remoteJid' = "Chat"."remoteJid"
|
||||||
|
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
||||||
|
WHERE
|
||||||
|
"Chat"."instanceId" = ${this.instanceId}
|
||||||
|
GROUP BY
|
||||||
|
"Chat"."id",
|
||||||
|
"Chat"."remoteJid",
|
||||||
|
"Contact"."id",
|
||||||
|
"Message"."messageTimestamp"
|
||||||
|
ORDER BY "Message"."messageTimestamp" 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_pushName,
|
||||||
|
(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_messageType,
|
||||||
|
(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_contextInfo,
|
||||||
|
(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_messageTimestamp,
|
||||||
|
(ARRAY_AGG("Message"."instanceId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_instanceId,
|
||||||
|
(ARRAY_AGG("Message"."sessionId" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_sessionId,
|
||||||
|
(ARRAY_AGG("Message"."status" ORDER BY "Message"."messageTimestamp" DESC))[1] AS last_message_status
|
||||||
|
FROM "Chat"
|
||||||
|
LEFT JOIN "Message" ON "Message"."key"->>'remoteJid' = "Chat"."remoteJid"
|
||||||
|
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
||||||
|
WHERE
|
||||||
|
"Chat"."instanceId" = ${this.instanceId} AND "Chat"."remoteJid" = ${remoteJid}
|
||||||
|
GROUP BY
|
||||||
|
"Chat"."id",
|
||||||
|
"Chat"."remoteJid",
|
||||||
|
"Contact"."id",
|
||||||
|
"Message"."messageTimestamp"
|
||||||
|
ORDER BY "Message"."messageTimestamp" DESC NULLS LAST, "Chat"."updatedAt" DESC;
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results && isArray(results) && results.length > 0) {
|
||||||
|
return results.map((chat) => {
|
||||||
|
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_pushName,
|
||||||
|
participant: chat.last_message_participant,
|
||||||
|
messageType: chat.last_message_messageType,
|
||||||
|
message: chat.last_message_message,
|
||||||
|
contextInfo: chat.last_message_contextInfo,
|
||||||
|
source: chat.last_message_source,
|
||||||
|
messageTimestamp: chat.last_message_messageTimestamp,
|
||||||
|
instanceId: chat.last_message_instanceId,
|
||||||
|
sessionId: chat.last_message_sessionId,
|
||||||
|
status: chat.last_message_status,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user