Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop

This commit is contained in:
Davidson Gomes 2025-05-21 15:01:22 -03:00
commit fbfa364df9
3 changed files with 95 additions and 65 deletions

View File

@ -1173,8 +1173,8 @@ export class BaileysStartupService extends ChannelStartupService {
const oldMessage = await this.getMessage(editedMessage.key, true);
if ((oldMessage as any)?.id) {
const editedMessageTimestamp = Long.isLong(editedMessage?.timestampMs)
? editedMessage.timestampMs?.toNumber()
: (editedMessage.timestampMs as number);
? Math.floor(editedMessage.timestampMs.toNumber() / 1000)
: Math.floor((editedMessage.timestampMs as number) / 1000);
await this.prismaRepository.message.update({
where: { id: (oldMessage as any).id },
@ -1205,7 +1205,7 @@ export class BaileysStartupService extends ChannelStartupService {
continue;
}
await this.baileysCache.set(messageKey, true, 30 * 60);
await this.baileysCache.set(messageKey, true, 5 * 60);
if (
(type !== 'notify' && type !== 'append') ||
@ -1311,21 +1311,31 @@ export class BaileysStartupService extends ChannelStartupService {
data: messageRaw,
});
if (received.key.fromMe === false) {
if (msg.status === status[3]) {
this.logger.log(`Update not read messages ${received.key.remoteJid}`);
const {remoteJid} = received.key;
const timestamp = msg.messageTimestamp;
const fromMe = received.key.fromMe.toString();
const messageKey = `${remoteJid}_${timestamp}_${fromMe}`;
await this.updateChatUnreadMessages(received.key.remoteJid);
} else if (msg.status === status[4]) {
this.logger.log(`Update readed messages ${received.key.remoteJid} - ${msg.messageTimestamp}`);
const cachedTimestamp = await this.baileysCache.get(messageKey);
await this.updateMessagesReadedByTimestamp(received.key.remoteJid, msg.messageTimestamp);
if (!cachedTimestamp) {
if (!received.key.fromMe) {
if (msg.status === status[3]) {
this.logger.log(`Update not read messages ${remoteJid}`);
await this.updateChatUnreadMessages(remoteJid);
} else if (msg.status === status[4]) {
this.logger.log(`Update readed messages ${remoteJid} - ${timestamp}`);
await this.updateMessagesReadedByTimestamp(remoteJid, timestamp);
}
} else {
// is send message by me
this.logger.log(`Update readed messages ${remoteJid} - ${timestamp}`);
await this.updateMessagesReadedByTimestamp(remoteJid, timestamp);
}
} else {
// is send message by me
this.logger.log(`Update readed messages ${received.key.remoteJid} - ${msg.messageTimestamp}`);
await this.updateMessagesReadedByTimestamp(received.key.remoteJid, msg.messageTimestamp);
await this.baileysCache.set(messageKey, true, 5 * 60);
} else {
this.logger.info(`Update readed messages duplicated ignored [avoid deadlock]: ${messageKey}`);
}
if (isMedia) {
@ -1498,7 +1508,7 @@ export class BaileysStartupService extends ChannelStartupService {
const cached = await this.baileysCache.get(updateKey);
if (cached) {
this.logger.info(`Message duplicated ignored: ${key.id}`);
this.logger.info(`Message duplicated ignored [avoid deadlock]: ${updateKey}`);
continue;
}
@ -1514,7 +1524,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
}
if (key.remoteJid !== 'status@broadcast') {
if (key.remoteJid !== 'status@broadcast' && key.id !== undefined) {
let pollUpdates: any;
if (update.pollUpdates) {
@ -1542,19 +1552,20 @@ export class BaileysStartupService extends ChannelStartupService {
continue;
}
const message: any = {
messageId: findMessage.id,
keyId: key.id,
remoteJid: key?.remoteJid,
fromMe: key.fromMe,
participant: key?.remoteJid,
status: status[update.status] ?? 'DELETED',
pollUpdates,
instanceId: this.instanceId,
};
if (update.message === null && update.status === undefined) {
this.sendDataWebhook(Events.MESSAGES_DELETE, key);
const message: any = {
messageId: findMessage.id,
keyId: key.id,
remoteJid: key.remoteJid,
fromMe: key.fromMe,
participant: key?.remoteJid,
status: 'DELETED',
instanceId: this.instanceId,
};
if (this.configService.get<Database>('DATABASE').SAVE_DATA.MESSAGE_UPDATE)
await this.prismaRepository.messageUpdate.create({
data: message,
@ -1573,29 +1584,32 @@ export class BaileysStartupService extends ChannelStartupService {
if (!key.fromMe && key.remoteJid) {
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);
const {remoteJid} = key;
const timestamp = findMessage.messageTimestamp;
const fromMe = key.fromMe.toString();
const messageKey = `${remoteJid}_${timestamp}_${fromMe}`;
const cachedTimestamp = await this.baileysCache.get(messageKey);
if (!cachedTimestamp) {
if (status[update.status] === status[4]) {
this.logger.log(`Update as read in message.update ${remoteJid} - ${timestamp}`);
await this.updateMessagesReadedByTimestamp(remoteJid, timestamp);
await this.baileysCache.set(messageKey, true, 5 * 60);
}
await this.prismaRepository.message.update({
where: { id: findMessage.id },
data: { status: status[update.status] },
});
} else {
this.logger.info(
`Update readed messages duplicated ignored in message.update [avoid deadlock]: ${messageKey}`,
);
}
}
await this.prismaRepository.message.update({
where: { id: findMessage.id },
data: { status: status[update.status] },
});
}
const message: any = {
messageId: findMessage.id,
keyId: key.id,
remoteJid: key.remoteJid,
fromMe: key.fromMe,
participant: key?.remoteJid,
status: status[update.status],
pollUpdates,
instanceId: this.instanceId,
};
this.sendDataWebhook(Events.MESSAGES_UPDATE, message);
if (this.configService.get<Database>('DATABASE').SAVE_DATA.MESSAGE_UPDATE)
@ -3769,6 +3783,10 @@ export class BaileysStartupService extends ChannelStartupService {
}
}
if ('messageContextInfo' in msg.message && Object.keys(msg.message).length === 1) {
throw 'The message is messageContextInfo';
}
let mediaMessage: any;
let mediaType: string;
@ -3779,7 +3797,7 @@ export class BaileysStartupService extends ChannelStartupService {
break;
}
}
if (!mediaMessage) {
throw 'The message is not of the media type';
}
@ -3844,7 +3862,7 @@ export class BaileysStartupService extends ChannelStartupService {
buffer: getBuffer ? buffer : null,
};
} catch (error) {
this.logger.error('Error processing media message:');
this.logger.error('Error processing media message:');
this.logger.error(error);
throw new BadRequestException(error.toString());
}

View File

@ -930,7 +930,7 @@ export class ChatwootService {
quotedMsg?: MessageModel,
) {
if (sourceId && this.isImportHistoryAvailable()) {
const messageAlreadySaved = await chatwootImport.getExistingSourceIds([sourceId]);
const messageAlreadySaved = await chatwootImport.getExistingSourceIds([sourceId], conversationId);
if (messageAlreadySaved) {
if (messageAlreadySaved.size > 0) {
this.logger.warn('Message already saved on chatwoot');

View File

@ -169,7 +169,7 @@ class ChatwootImport {
}
}
public async getExistingSourceIds(sourceIds: string[]): Promise<Set<string>> {
public async getExistingSourceIds(sourceIds: string[], conversationId?: number): Promise<Set<string>> {
try {
const existingSourceIdsSet = new Set<string>();
@ -178,9 +178,17 @@ class ChatwootImport {
}
const formattedSourceIds = sourceIds.map((sourceId) => `WAID:${sourceId.replace('WAID:', '')}`); // Make sure the sourceId is always formatted as WAID:1234567890
const query = 'SELECT source_id FROM messages WHERE source_id = ANY($1)';
let query: string;
if (conversationId) {
query = 'SELECT source_id FROM messages WHERE source_id = ANY($1)';
}
if(!conversationId) {
query = 'SELECT source_id FROM messages WHERE source_id = ANY($1) AND conversation_id = $2';
}
const pgClient = postgresClient.getChatwootConnection();
const result = await pgClient.query(query, [formattedSourceIds]);
const result = await pgClient.query(query, [formattedSourceIds, conversationId]);
for (const row of result.rows) {
existingSourceIdsSet.add(row.source_id);
@ -499,25 +507,29 @@ class ChatwootImport {
stickerMessage: msg.message.stickerMessage,
templateMessage: msg.message.templateMessage?.hydratedTemplate?.hydratedContentText,
};
const typeKey = Object.keys(types).find((key) => types[key] !== undefined);
const typeKey = Object.keys(types).find(
(key) => types[key] !== undefined && types[key] !== null
);
switch (typeKey) {
case 'documentMessage':
return `_<File: ${msg.message.documentMessage.fileName}${
msg.message.documentMessage.caption ? ` ${msg.message.documentMessage.caption}` : ''
}>_`;
case 'documentMessage': {
const doc = msg.message.documentMessage;
const fileName = doc?.fileName || 'document';
const caption = doc?.caption ? ` ${doc.caption}` : '';
return `_<File: ${fileName}${caption}>_`;
}
case 'documentWithCaptionMessage':
return `_<File: ${msg.message.documentWithCaptionMessage.message.documentMessage.fileName}${
msg.message.documentWithCaptionMessage.message.documentMessage.caption
? ` ${msg.message.documentWithCaptionMessage.message.documentMessage.caption}`
: ''
}>_`;
case 'documentWithCaptionMessage': {
const doc = msg.message.documentWithCaptionMessage?.message?.documentMessage;
const fileName = doc?.fileName || 'document';
const caption = doc?.caption ? ` ${doc.caption}` : '';
return `_<File: ${fileName}${caption}>_`;
}
case 'templateMessage':
return msg.message.templateMessage.hydratedTemplate.hydratedTitleText
? `*${msg.message.templateMessage.hydratedTemplate.hydratedTitleText}*\\n`
: '' + msg.message.templateMessage.hydratedTemplate.hydratedContentText;
const template = msg.message.templateMessage?.hydratedTemplate;
return (template?.hydratedTitleText ? `*${template.hydratedTitleText}*\n` : '') +
(template?.hydratedContentText || '');
case 'imageMessage':
return '_<Image Message>_';