Skip to content

Commit a1d30c7

Browse files
committed
Merge branch 'develop' of https://github.com/neocol83/evolution-api into develop
2 parents 78ec10d + 9889035 commit a1d30c7

9 files changed

Lines changed: 157 additions & 93 deletions

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ RABBITMQ_EVENTS_MESSAGES_EDITED=false
6262
RABBITMQ_EVENTS_MESSAGES_UPDATE=false
6363
RABBITMQ_EVENTS_MESSAGES_DELETE=false
6464
RABBITMQ_EVENTS_SEND_MESSAGE=false
65+
RABBITMQ_EVENTS_SEND_MESSAGE_UPDATE=false
6566
RABBITMQ_EVENTS_CONTACTS_SET=false
6667
RABBITMQ_EVENTS_CONTACTS_UPSERT=false
6768
RABBITMQ_EVENTS_CONTACTS_UPDATE=false
@@ -108,6 +109,7 @@ PUSHER_EVENTS_MESSAGES_EDITED=true
108109
PUSHER_EVENTS_MESSAGES_UPDATE=true
109110
PUSHER_EVENTS_MESSAGES_DELETE=true
110111
PUSHER_EVENTS_SEND_MESSAGE=true
112+
PUSHER_EVENTS_SEND_MESSAGE_UPDATE=true
111113
PUSHER_EVENTS_CONTACTS_SET=true
112114
PUSHER_EVENTS_CONTACTS_UPSERT=true
113115
PUSHER_EVENTS_CONTACTS_UPDATE=true
@@ -149,6 +151,7 @@ WEBHOOK_EVENTS_MESSAGES_EDITED=true
149151
WEBHOOK_EVENTS_MESSAGES_UPDATE=true
150152
WEBHOOK_EVENTS_MESSAGES_DELETE=true
151153
WEBHOOK_EVENTS_SEND_MESSAGE=true
154+
WEBHOOK_EVENTS_SEND_MESSAGE_UPDATE=true
152155
WEBHOOK_EVENTS_CONTACTS_SET=true
153156
WEBHOOK_EVENTS_CONTACTS_UPSERT=true
154157
WEBHOOK_EVENTS_CONTACTS_UPDATE=true

Docker/swarm/evolution_api_v2.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ services:
3434
- RABBITMQ_EVENTS_MESSAGES_UPDATE=false
3535
- RABBITMQ_EVENTS_MESSAGES_DELETE=false
3636
- RABBITMQ_EVENTS_SEND_MESSAGE=false
37+
- RABBITMQ_EVENTS_SEND_MESSAGE_UPDATE=false
3738
- RABBITMQ_EVENTS_CONTACTS_SET=false
3839
- RABBITMQ_EVENTS_CONTACTS_UPSERT=false
3940
- RABBITMQ_EVENTS_CONTACTS_UPDATE=false
@@ -71,6 +72,7 @@ services:
7172
- WEBHOOK_EVENTS_MESSAGES_UPDATE=true
7273
- WEBHOOK_EVENTS_MESSAGES_DELETE=true
7374
- WEBHOOK_EVENTS_SEND_MESSAGE=true
75+
- WEBHOOK_EVENTS_SEND_MESSAGE_UPDATE=true
7476
- WEBHOOK_EVENTS_CONTACTS_SET=true
7577
- WEBHOOK_EVENTS_CONTACTS_UPSERT=true
7678
- WEBHOOK_EVENTS_CONTACTS_UPDATE=true

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 118 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,37 +1135,39 @@ export class BaileysStartupService extends ChannelStartupService {
11351135
const editedMessage =
11361136
received?.message?.protocolMessage || received?.message?.editedMessage?.message?.protocolMessage;
11371137

1138-
if (received.message?.protocolMessage?.editedMessage || received.message?.editedMessage?.message) {
1139-
if (editedMessage) {
1140-
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled)
1141-
this.chatwootService.eventWhatsapp(
1142-
'messages.edit',
1143-
{ instanceName: this.instance.name, instanceId: this.instance.id },
1144-
editedMessage,
1145-
);
1138+
if (received.message?.protocolMessage?.editedMessage && editedMessage) {
1139+
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled)
1140+
this.chatwootService.eventWhatsapp(
1141+
'messages.edit',
1142+
{ instanceName: this.instance.name, instanceId: this.instance.id },
1143+
editedMessage,
1144+
);
11461145

1147-
await this.sendDataWebhook(Events.MESSAGES_EDITED, editedMessage);
1148-
const oldMessage = await this.getMessage(editedMessage.key, true);
1149-
if ((oldMessage as any)?.id) {
1150-
await this.prismaRepository.message.update({
1151-
where: { id: (oldMessage as any).id },
1152-
data: {
1153-
message: editedMessage.editedMessage as any,
1154-
messageTimestamp: (editedMessage.timestampMs as Long).toNumber(),
1155-
status: 'EDITED',
1156-
},
1157-
});
1158-
await this.prismaRepository.messageUpdate.create({
1159-
data: {
1160-
fromMe: editedMessage.key.fromMe,
1161-
keyId: editedMessage.key.id,
1162-
remoteJid: editedMessage.key.remoteJid,
1163-
status: 'EDITED',
1164-
instanceId: this.instanceId,
1165-
messageId: (oldMessage as any).id,
1166-
},
1167-
});
1168-
}
1146+
await this.sendDataWebhook(Events.MESSAGES_EDITED, editedMessage);
1147+
const oldMessage = await this.getMessage(editedMessage.key, true);
1148+
if ((oldMessage as any)?.id) {
1149+
const editedMessageTimestamp = Long.isLong(editedMessage?.timestampMs)
1150+
? editedMessage.timestampMs?.toNumber()
1151+
: (editedMessage.timestampMs as number);
1152+
1153+
await this.prismaRepository.message.update({
1154+
where: { id: (oldMessage as any).id },
1155+
data: {
1156+
message: editedMessage.editedMessage as any,
1157+
messageTimestamp: editedMessageTimestamp,
1158+
status: 'EDITED',
1159+
},
1160+
});
1161+
await this.prismaRepository.messageUpdate.create({
1162+
data: {
1163+
fromMe: editedMessage.key.fromMe,
1164+
keyId: editedMessage.key.id,
1165+
remoteJid: editedMessage.key.remoteJid,
1166+
status: 'EDITED',
1167+
instanceId: this.instanceId,
1168+
messageId: (oldMessage as any).id,
1169+
},
1170+
});
11691171
}
11701172
}
11711173

@@ -1223,7 +1225,8 @@ export class BaileysStartupService extends ChannelStartupService {
12231225
existingChat &&
12241226
received.pushName &&
12251227
existingChat.name !== received.pushName &&
1226-
received.pushName.trim().length > 0
1228+
received.pushName.trim().length > 0 &&
1229+
!received.key.remoteJid.includes('@g.us')
12271230
) {
12281231
this.sendDataWebhook(Events.CHATS_UPSERT, [{ ...existingChat, name: received.pushName }]);
12291232
if (this.configService.get<Database>('DATABASE').SAVE_DATA.CHATS) {
@@ -1329,7 +1332,12 @@ export class BaileysStartupService extends ChannelStartupService {
13291332

13301333
const { buffer, mediaType, fileName, size } = media;
13311334
const mimetype = mimeTypes.lookup(fileName).toString();
1332-
const fullName = join(`${this.instance.id}`, received.key.remoteJid, mediaType, fileName);
1335+
const fullName = join(
1336+
`${this.instance.id}`,
1337+
received.key.remoteJid,
1338+
mediaType,
1339+
`${Date.now()}_${fileName}`,
1340+
);
13331341
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, {
13341342
'Content-Type': mimetype,
13351343
});
@@ -2751,15 +2759,35 @@ export class BaileysStartupService extends ChannelStartupService {
27512759
imageBuffer = Buffer.from(response.data, 'binary');
27522760
}
27532761

2754-
const webpBuffer = await sharp(imageBuffer).webp().toBuffer();
2762+
const isAnimated = this.isAnimated(image, imageBuffer);
27552763

2756-
return webpBuffer;
2764+
if (isAnimated) {
2765+
return await sharp(imageBuffer, { animated: true }).webp({ quality: 80 }).toBuffer();
2766+
} else {
2767+
return await sharp(imageBuffer).webp().toBuffer();
2768+
}
27572769
} catch (error) {
27582770
console.error('Erro ao converter a imagem para WebP:', error);
27592771
throw error;
27602772
}
27612773
}
27622774

2775+
private isAnimatedWebp(buffer: Buffer): boolean {
2776+
if (buffer.length < 12) return false;
2777+
2778+
return buffer.indexOf(Buffer.from('ANIM')) !== -1;
2779+
}
2780+
2781+
private isAnimated(image: string, buffer: Buffer): boolean {
2782+
const lowerCaseImage = image.toLowerCase();
2783+
2784+
if (lowerCaseImage.includes('.gif')) return true;
2785+
2786+
if (lowerCaseImage.includes('.webp')) return this.isAnimatedWebp(buffer);
2787+
2788+
return false;
2789+
}
2790+
27632791
public async mediaSticker(data: SendStickerDto, file?: any) {
27642792
const mediaData: SendStickerDto = { ...data };
27652793

@@ -3971,71 +3999,71 @@ export class BaileysStartupService extends ChannelStartupService {
39713999
throw new BadRequestException('Message is older than 15 minutes');
39724000
}
39734001

3974-
const response = await this.client.sendMessage(jid, {
4002+
const messageSent = await this.client.sendMessage(jid, {
39754003
...(options as any),
39764004
edit: data.key,
39774005
});
3978-
if (response) {
3979-
const messageId = response.message?.protocolMessage?.key?.id;
3980-
if (messageId) {
3981-
let message = await this.prismaRepository.message.findFirst({
3982-
where: {
3983-
key: {
3984-
path: ['id'],
3985-
equals: messageId,
4006+
if (messageSent) {
4007+
const editedMessage =
4008+
messageSent?.message?.protocolMessage || messageSent?.message?.editedMessage?.message?.protocolMessage;
4009+
4010+
if (editedMessage) {
4011+
this.sendDataWebhook(Events.SEND_MESSAGE_UPDATE, editedMessage);
4012+
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled)
4013+
this.chatwootService.eventWhatsapp(
4014+
'send.message.update',
4015+
{ instanceName: this.instance.name, instanceId: this.instance.id },
4016+
editedMessage,
4017+
);
4018+
4019+
const messageId = messageSent.message?.protocolMessage?.key?.id;
4020+
if (messageId) {
4021+
let message = await this.prismaRepository.message.findFirst({
4022+
where: {
4023+
key: {
4024+
path: ['id'],
4025+
equals: messageId,
4026+
},
39864027
},
3987-
},
3988-
});
3989-
if (!message) throw new NotFoundException('Message not found');
4028+
});
4029+
if (!message) throw new NotFoundException('Message not found');
39904030

3991-
if (!(message.key.valueOf() as any).fromMe) {
3992-
new BadRequestException('You cannot edit others messages');
3993-
}
3994-
if ((message.key.valueOf() as any)?.deleted) {
3995-
new BadRequestException('You cannot edit deleted messages');
3996-
}
3997-
if (oldMessage.messageType === 'conversation' || oldMessage.messageType === 'extendedTextMessage') {
3998-
oldMessage.message.conversation = data.text;
3999-
} else {
4000-
oldMessage.message[oldMessage.messageType].caption = data.text;
4001-
}
4002-
message = await this.prismaRepository.message.update({
4003-
where: { id: message.id },
4004-
data: {
4005-
message: oldMessage.message,
4031+
if (!(message.key.valueOf() as any).fromMe) {
4032+
new BadRequestException('You cannot edit others messages');
4033+
}
4034+
if ((message.key.valueOf() as any)?.deleted) {
4035+
new BadRequestException('You cannot edit deleted messages');
4036+
}
4037+
if (oldMessage.messageType === 'conversation' || oldMessage.messageType === 'extendedTextMessage') {
4038+
oldMessage.message.conversation = data.text;
4039+
} else {
4040+
oldMessage.message[oldMessage.messageType].caption = data.text;
4041+
}
4042+
message = await this.prismaRepository.message.update({
4043+
where: { id: message.id },
4044+
data: {
4045+
message: oldMessage.message,
4046+
status: 'EDITED',
4047+
messageTimestamp: Math.floor(Date.now() / 1000), // Convert to int32 by dividing by 1000 to get seconds
4048+
},
4049+
});
4050+
const messageUpdate: any = {
4051+
messageId: message.id,
4052+
keyId: messageId,
4053+
remoteJid: messageSent.key.remoteJid,
4054+
fromMe: messageSent.key.fromMe,
4055+
participant: messageSent.key?.remoteJid,
40064056
status: 'EDITED',
4007-
messageTimestamp: Math.floor(Date.now() / 1000), // Convert to int32 by dividing by 1000 to get seconds
4008-
},
4009-
});
4010-
const messageUpdate: any = {
4011-
messageId: message.id,
4012-
keyId: messageId,
4013-
remoteJid: response.key.remoteJid,
4014-
fromMe: response.key.fromMe,
4015-
participant: response.key?.remoteJid,
4016-
status: 'EDITED',
4017-
instanceId: this.instanceId,
4018-
};
4019-
await this.prismaRepository.messageUpdate.create({
4020-
data: messageUpdate,
4021-
});
4022-
4023-
this.sendDataWebhook(Events.MESSAGES_EDITED, {
4024-
id: message.id,
4025-
instanceId: message.instanceId,
4026-
key: message.key,
4027-
messageType: message.messageType,
4028-
status: 'EDITED',
4029-
source: message.source,
4030-
messageTimestamp: message.messageTimestamp,
4031-
pushName: message.pushName,
4032-
participant: message.participant,
4033-
message: message.message,
4034-
});
4057+
instanceId: this.instanceId,
4058+
};
4059+
await this.prismaRepository.messageUpdate.create({
4060+
data: messageUpdate,
4061+
});
4062+
}
40354063
}
40364064
}
40374065

4038-
return response;
4066+
return messageSent;
40394067
} catch (error) {
40404068
this.logger.error(error);
40414069
throw error;

src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@ export class ChatwootService {
21992199
}
22002200
}
22012201

2202-
if (event === 'messages.edit') {
2202+
if (event === 'messages.edit' || event === 'send.message.update') {
22032203
const editedText = `${
22042204
body?.editedMessage?.conversation || body?.editedMessage?.extendedTextMessage?.text
22052205
}\n\n_\`${i18next.t('cw.message.edited')}.\`_`;

src/api/integrations/event/event.controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export class EventController {
132132
'MESSAGES_UPDATE',
133133
'MESSAGES_DELETE',
134134
'SEND_MESSAGE',
135+
'SEND_MESSAGE_UPDATE',
135136
'CONTACTS_SET',
136137
'CONTACTS_UPSERT',
137138
'CONTACTS_UPDATE',

src/api/services/channel.service.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,17 @@ export class ChannelStartupService {
503503
where['remoteJid'] = remoteJid;
504504
}
505505

506-
return await this.prismaRepository.contact.findMany({
506+
const contactFindManyArgs: Prisma.ContactFindManyArgs = {
507507
where,
508-
});
508+
};
509+
510+
if (query.offset) contactFindManyArgs.take = query.offset;
511+
if (query.page) {
512+
const validPage = Math.max(query.page as number, 1);
513+
contactFindManyArgs.skip = query.offset * (validPage - 1);
514+
}
515+
516+
return await this.prismaRepository.contact.findMany(contactFindManyArgs);
509517
}
510518

511519
public cleanMessageData(message: any) {
@@ -674,6 +682,13 @@ export class ChannelStartupService {
674682
: createJid(query.where?.remoteJid)
675683
: null;
676684

685+
const limit =
686+
query.offset && !query.page
687+
? Prisma.sql` LIMIT ${query.offset}`
688+
: query.offset && query.page
689+
? Prisma.sql` LIMIT ${query.offset} OFFSET ${((query.page as number) - 1) * query.offset}`
690+
: Prisma.sql``;
691+
677692
const where = {
678693
instanceId: this.instanceId,
679694
};
@@ -700,6 +715,7 @@ export class ChannelStartupService {
700715
to_timestamp("Message"."messageTimestamp"::double precision),
701716
"Contact"."updatedAt"
702717
) as "updatedAt",
718+
"Chat"."name" as "chatName",
703719
"Chat"."createdAt" as "windowStart",
704720
"Chat"."createdAt" + INTERVAL '24 hours' as "windowExpires",
705721
CASE
@@ -730,6 +746,7 @@ export class ChannelStartupService {
730746
ORDER BY
731747
"Contact"."remoteJid",
732748
"Message"."messageTimestamp" DESC
749+
${limit}
733750
)
734751
SELECT * FROM rankedMessages
735752
ORDER BY "updatedAt" DESC NULLS LAST;
@@ -758,6 +775,7 @@ export class ChannelStartupService {
758775
id: contact.id,
759776
remoteJid: contact.remoteJid,
760777
pushName: contact.pushName,
778+
chatName: contact.chatName,
761779
profilePicUrl: contact.profilePicUrl,
762780
updatedAt: contact.updatedAt,
763781
windowStart: contact.windowStart,

src/api/types/wa.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export enum Events {
1515
MESSAGES_UPDATE = 'messages.update',
1616
MESSAGES_DELETE = 'messages.delete',
1717
SEND_MESSAGE = 'send.message',
18+
SEND_MESSAGE_UPDATE = 'send.message.update',
1819
CONTACTS_SET = 'contacts.set',
1920
CONTACTS_UPSERT = 'contacts.upsert',
2021
CONTACTS_UPDATE = 'contacts.update',

0 commit comments

Comments
 (0)