Skip to content

Commit 7b41d33

Browse files
authored
Merge branch 'EvolutionAPI:v2.0.0' into v2.0.0
2 parents 0a4b8d2 + d84713f commit 7b41d33

File tree

10 files changed

+100
-53
lines changed

10 files changed

+100
-53
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ LOG_COLOR=true
1616
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
1717
LOG_BAILEYS=error
1818

19+
# Set the maximum number of listeners that can be registered for an event
20+
EVENT_EMITTER_MAX_LISTENERS=50
21+
1922
# Determine how long the instance should be deleted from memory in case of no connection.
2023
# Default time: 5 minutes
2124
# If you don't even want an expiration, enter the value false

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Features
44

55
* Sync lost messages on chatwoot
6+
* Set the maximum number of listeners that can be registered for events
67

78
### Fixed
89

@@ -12,6 +13,14 @@
1213
* Validate message before sending chatwoot
1314
* Adds the message status to the return of the "prepareMessage" function
1415
* Fixed openai setting when send a message with chatwoot
16+
* Fix buildkey function in hSet and hDelete
17+
* Fix mexico number
18+
* Update baileys version
19+
* Update in Baileys version that fixes timeout when updating profile picture
20+
* Adjusts for fix timeout error on send status message
21+
* Chatwoot verbose logs
22+
* Adjusts on prisma connections
23+
* License terms updated
1524

1625
# 2.1.1 (2024-09-22 10:31)
1726

LICENSE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ a. Multi-tenant SaaS service: Unless explicitly authorized in writing, you may n
99

1010
b. LOGO and copyright information: In the process of using Evolution API's frontend components, you may not remove or modify the LOGO or copyright information in the Evolution API console or applications. This restriction is inapplicable to uses of Evolution API that do not involve its frontend components.
1111

12+
c. Usage Notification Requirement: If Evolution API is used as part of any project, including closed-source systems (e.g., proprietary software), the user is required to display a clear notification within the system that Evolution API is being utilized. This notification should be visible to system administrators and accessible from the system's documentation or settings page. Failure to comply with this requirement may result in the necessity for a commercial license, as determined by the producer.
13+
1214
Please contact contato@atendai.com to inquire about licensing matters.
1315

1416
2. As a contributor, you should agree that:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"@sentry/node": "^8.28.0",
5656
"amqplib": "^0.10.3",
5757
"axios": "^1.6.5",
58-
"baileys": "6.7.7",
58+
"baileys": "6.7.8",
5959
"class-validator": "^0.14.1",
6060
"compression": "^1.7.4",
6161
"cors": "^2.8.5",

src/api/guards/instance.guard.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { InstanceDto } from '@api/dto/instance.dto';
2-
import { cache, waMonitor } from '@api/server.module';
2+
import { cache, prismaRepository, waMonitor } from '@api/server.module';
33
import { CacheConf, configService } from '@config/env.config';
44
import { BadRequestException, ForbiddenException, InternalServerErrorException, NotFoundException } from '@exceptions';
5-
import { prismaServer } from '@libs/prisma.connect';
65
import { NextFunction, Request, Response } from 'express';
76

87
async function getInstance(instanceName: string) {
@@ -17,9 +16,7 @@ async function getInstance(instanceName: string) {
1716
return exists || keyExists;
1817
}
1918

20-
const prisma = prismaServer;
21-
22-
return exists || (await prisma.instance.findMany({ where: { name: instanceName } })).length > 0;
19+
return exists || (await prismaRepository.instance.findMany({ where: { name: instanceName } })).length > 0;
2320
} catch (error) {
2421
throw new InternalServerErrorException(error?.toString());
2522
}

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,10 +1195,11 @@ export class BaileysStartupService extends ChannelStartupService {
11951195
);
11961196
}
11971197

1198-
this.prismaRepository.contact.updateMany({
1199-
where: { remoteJid: received.key.remoteJid, instanceId: this.instanceId },
1200-
data: contactRaw,
1201-
});
1198+
if (this.configService.get<Database>('DATABASE').SAVE_DATA.CONTACTS)
1199+
await this.prismaRepository.contact.create({
1200+
data: contactRaw,
1201+
});
1202+
12021203
return;
12031204
}
12041205

@@ -1743,9 +1744,25 @@ export class BaileysStartupService extends ChannelStartupService {
17431744
}
17441745

17451746
if (sender === 'status@broadcast') {
1746-
const jidList = message['status'].option.statusJidList;
1747+
let jidList;
1748+
if (message['status'].option.allContacts) {
1749+
const contacts = await this.prismaRepository.contact.findMany({
1750+
where: {
1751+
instanceId: this.instanceId,
1752+
remoteJid: {
1753+
not: {
1754+
endsWith: '@g.us',
1755+
},
1756+
},
1757+
},
1758+
});
1759+
1760+
jidList = contacts.map((contact) => contact.remoteJid);
1761+
} else {
1762+
jidList = message['status'].option.statusJidList;
1763+
}
17471764

1748-
const batchSize = 500;
1765+
const batchSize = 10;
17491766

17501767
const batches = Array.from({ length: Math.ceil(jidList.length / batchSize) }, (_, i) =>
17511768
jidList.slice(i * batchSize, i * batchSize + batchSize),
@@ -2736,7 +2753,7 @@ export class BaileysStartupService extends ChannelStartupService {
27362753
if (!numberVerified && (user.number.startsWith('52') || user.number.startsWith('54'))) {
27372754
let prefix = '';
27382755
if (user.number.startsWith('52')) {
2739-
prefix = '1';
2756+
prefix = '';
27402757
}
27412758
if (user.number.startsWith('54')) {
27422759
prefix = '9';

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

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -538,26 +538,37 @@ export class ChatwootService {
538538

539539
public async createConversation(instance: InstanceDto, body: any) {
540540
try {
541+
this.logger.verbose('--- Start createConversation ---');
542+
this.logger.verbose(`Instance: ${JSON.stringify(instance)}`);
543+
this.logger.verbose(`Body: ${JSON.stringify(body)}`);
544+
541545
const client = await this.clientCw(instance);
542546

543547
if (!client) {
544-
this.logger.warn('client not found');
548+
this.logger.warn(`Client not found for instance: ${JSON.stringify(instance)}`);
545549
return null;
546550
}
547551

548552
const cacheKey = `${instance.instanceName}:createConversation-${body.key.remoteJid}`;
553+
this.logger.verbose(`Cache key: ${cacheKey}`);
554+
549555
if (await this.cache.has(cacheKey)) {
556+
this.logger.verbose(`Cache hit for key: ${cacheKey}`);
550557
const conversationId = (await this.cache.get(cacheKey)) as number;
558+
this.logger.verbose(`Cached conversation ID: ${conversationId}`);
551559
let conversationExists: conversation | boolean;
552560
try {
553561
conversationExists = await client.conversations.get({
554562
accountId: this.provider.accountId,
555563
conversationId: conversationId,
556564
});
565+
this.logger.verbose(`Conversation exists: ${JSON.stringify(conversationExists)}`);
557566
} catch (error) {
567+
this.logger.error(`Error getting conversation: ${error}`);
558568
conversationExists = false;
559569
}
560570
if (!conversationExists) {
571+
this.logger.verbose('Conversation does not exist, re-calling createConversation');
561572
this.cache.delete(cacheKey);
562573
return await this.createConversation(instance, body);
563574
}
@@ -566,30 +577,37 @@ export class ChatwootService {
566577
}
567578

568579
const isGroup = body.key.remoteJid.includes('@g.us');
580+
this.logger.verbose(`Is group: ${isGroup}`);
569581

570582
const chatId = isGroup ? body.key.remoteJid : body.key.remoteJid.split('@')[0];
583+
this.logger.verbose(`Chat ID: ${chatId}`);
571584

572585
let nameContact: string;
573586

574587
nameContact = !body.key.fromMe ? body.pushName : chatId;
588+
this.logger.verbose(`Name contact: ${nameContact}`);
575589

576590
const filterInbox = await this.getInbox(instance);
577591

578592
if (!filterInbox) {
579-
this.logger.warn('inbox not found');
593+
this.logger.warn(`Inbox not found for instance: ${JSON.stringify(instance)}`);
580594
return null;
581595
}
582596

583597
if (isGroup) {
598+
this.logger.verbose('Processing group conversation');
584599
const group = await this.waMonitor.waInstances[instance.instanceName].client.groupMetadata(chatId);
600+
this.logger.verbose(`Group metadata: ${JSON.stringify(group)}`);
585601

586602
nameContact = `${group.subject} (GROUP)`;
587603

588604
const picture_url = await this.waMonitor.waInstances[instance.instanceName].profilePicture(
589605
body.key.participant.split('@')[0],
590606
);
607+
this.logger.verbose(`Participant profile picture URL: ${JSON.stringify(picture_url)}`);
591608

592609
const findParticipant = await this.findContact(instance, body.key.participant.split('@')[0]);
610+
this.logger.verbose(`Found participant: ${JSON.stringify(findParticipant)}`);
593611

594612
if (findParticipant) {
595613
if (!findParticipant.name || findParticipant.name === chatId) {
@@ -612,8 +630,10 @@ export class ChatwootService {
612630
}
613631

614632
const picture_url = await this.waMonitor.waInstances[instance.instanceName].profilePicture(chatId);
633+
this.logger.verbose(`Contact profile picture URL: ${JSON.stringify(picture_url)}`);
615634

616635
let contact = await this.findContact(instance, chatId);
636+
this.logger.verbose(`Found contact: ${JSON.stringify(contact)}`);
617637

618638
if (contact) {
619639
if (!body.key.fromMe) {
@@ -630,8 +650,10 @@ export class ChatwootService {
630650
)
631651
: false);
632652

633-
const contactNeedsUpdate = pictureNeedsUpdate || nameNeedsUpdate;
634-
if (contactNeedsUpdate) {
653+
this.logger.verbose(`Picture needs update: ${pictureNeedsUpdate}`);
654+
this.logger.verbose(`Name needs update: ${nameNeedsUpdate}`);
655+
656+
if (pictureNeedsUpdate || nameNeedsUpdate) {
635657
contact = await this.updateContact(instance, contact.id, {
636658
...(nameNeedsUpdate && { name: nameContact }),
637659
...(waProfilePictureFile === '' && { avatar: null }),
@@ -653,38 +675,50 @@ export class ChatwootService {
653675
}
654676

655677
if (!contact) {
656-
this.logger.warn('contact not found');
678+
this.logger.warn('Contact not created or found');
657679
return null;
658680
}
659681

660682
const contactId = contact?.payload?.id || contact?.payload?.contact?.id || contact?.id;
683+
this.logger.verbose(`Contact ID: ${contactId}`);
661684

662685
const contactConversations = (await client.contacts.listConversations({
663686
accountId: this.provider.accountId,
664687
id: contactId,
665688
})) as any;
689+
this.logger.verbose(`Contact conversations: ${JSON.stringify(contactConversations)}`);
690+
691+
if (!contactConversations || !contactConversations.payload) {
692+
this.logger.error('No conversations found or payload is undefined');
693+
return null;
694+
}
666695

667-
if (contactConversations?.payload?.length) {
696+
if (contactConversations.payload.length) {
668697
let conversation: any;
669698
if (this.provider.reopenConversation) {
670699
conversation = contactConversations.payload.find((conversation) => conversation.inbox_id == filterInbox.id);
700+
this.logger.verbose(`Found conversation in reopenConversation mode: ${JSON.stringify(conversation)}`);
671701

672702
if (this.provider.conversationPending) {
673-
await client.conversations.toggleStatus({
674-
accountId: this.provider.accountId,
675-
conversationId: conversation.id,
676-
data: {
677-
status: 'pending',
678-
},
679-
});
703+
if (conversation) {
704+
await client.conversations.toggleStatus({
705+
accountId: this.provider.accountId,
706+
conversationId: conversation.id,
707+
data: {
708+
status: 'pending',
709+
},
710+
});
711+
}
680712
}
681713
} else {
682714
conversation = contactConversations.payload.find(
683715
(conversation) => conversation.status !== 'resolved' && conversation.inbox_id == filterInbox.id,
684716
);
717+
this.logger.verbose(`Found conversation: ${JSON.stringify(conversation)}`);
685718
}
686719

687720
if (conversation) {
721+
this.logger.verbose(`Returning existing conversation ID: ${conversation.id}`);
688722
this.cache.set(cacheKey, conversation.id);
689723
return conversation.id;
690724
}
@@ -705,14 +739,15 @@ export class ChatwootService {
705739
});
706740

707741
if (!conversation) {
708-
this.logger.warn('conversation not found');
742+
this.logger.warn('Conversation not created or found');
709743
return null;
710744
}
711745

746+
this.logger.verbose(`New conversation created with ID: ${conversation.id}`);
712747
this.cache.set(cacheKey, conversation.id);
713748
return conversation.id;
714749
} catch (error) {
715-
this.logger.error(error);
750+
this.logger.error(`Error in createConversation: ${error}`);
716751
}
717752
}
718753

src/config/event.config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import EventEmitter2 from 'eventemitter2';
22

3+
const maxListeners = parseInt(process.env.EVENT_EMITTER_MAX_LISTENERS, 10) || 50;
4+
35
export const eventEmitter = new EventEmitter2({
46
delimiter: '.',
57
newListener: false,
68
ignoreErrors: false,
7-
maxListeners: 50,
9+
maxListeners: maxListeners,
810
});

src/libs/prisma.connect.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/utils/use-multi-file-auth-state-prisma.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1+
import { prismaRepository } from '@api/server.module';
12
import { CacheService } from '@api/services/cache.service';
23
import { INSTANCE_DIR } from '@config/path.config';
3-
import { prismaServer } from '@libs/prisma.connect';
44
import { AuthenticationState, BufferJSON, initAuthCreds, WAProto as proto } from 'baileys';
55
import fs from 'fs/promises';
66
import path from 'path';
77

8-
const prisma = prismaServer;
9-
108
// const fixFileName = (file: string): string | undefined => {
119
// if (!file) {
1210
// return undefined;
@@ -18,7 +16,7 @@ const prisma = prismaServer;
1816

1917
export async function keyExists(sessionId: string): Promise<any> {
2018
try {
21-
const key = await prisma.session.findUnique({ where: { sessionId: sessionId } });
19+
const key = await prismaRepository.session.findUnique({ where: { sessionId: sessionId } });
2220
return !!key;
2321
} catch (error) {
2422
return false;
@@ -29,13 +27,13 @@ export async function saveKey(sessionId: string, keyJson: any): Promise<any> {
2927
const exists = await keyExists(sessionId);
3028
try {
3129
if (!exists)
32-
return await prisma.session.create({
30+
return await prismaRepository.session.create({
3331
data: {
3432
sessionId: sessionId,
3533
creds: JSON.stringify(keyJson),
3634
},
3735
});
38-
await prisma.session.update({
36+
await prismaRepository.session.update({
3937
where: { sessionId: sessionId },
4038
data: { creds: JSON.stringify(keyJson) },
4139
});
@@ -48,7 +46,7 @@ export async function getAuthKey(sessionId: string): Promise<any> {
4846
try {
4947
const register = await keyExists(sessionId);
5048
if (!register) return null;
51-
const auth = await prisma.session.findUnique({ where: { sessionId: sessionId } });
49+
const auth = await prismaRepository.session.findUnique({ where: { sessionId: sessionId } });
5250
return JSON.parse(auth?.creds);
5351
} catch (error) {
5452
return null;
@@ -59,7 +57,7 @@ async function deleteAuthKey(sessionId: string): Promise<any> {
5957
try {
6058
const register = await keyExists(sessionId);
6159
if (!register) return;
62-
await prisma.session.delete({ where: { sessionId: sessionId } });
60+
await prismaRepository.session.delete({ where: { sessionId: sessionId } });
6361
} catch (error) {
6462
return;
6563
}

0 commit comments

Comments
 (0)