mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 15:14:49 -06:00
Merge branch 'v2.0.0' into v2
This commit is contained in:
commit
b93725dd32
@ -3,10 +3,14 @@
|
||||
### Features
|
||||
|
||||
* Define a global proxy to be used if the instance does not have one
|
||||
* Save is on whatsapp on the database
|
||||
|
||||
### Fixed
|
||||
|
||||
* Validate if cache exists before accessing it
|
||||
* Missing autoCreate chatwoot in instance create
|
||||
* Fixed bugs in the frontend, on the event screens
|
||||
* Fixed use chatwoot with evolution channel
|
||||
|
||||
# 2.1.0 (2024-08-26 15:33)
|
||||
|
||||
|
381
manager/dist/assets/index-B-Bdu2zN.js
vendored
Normal file
381
manager/dist/assets/index-B-Bdu2zN.js
vendored
Normal file
File diff suppressed because one or more lines are too long
381
manager/dist/assets/index-efsrmrux.js
vendored
381
manager/dist/assets/index-efsrmrux.js
vendored
File diff suppressed because one or more lines are too long
2
manager/dist/index.html
vendored
2
manager/dist/index.html
vendored
@ -5,7 +5,7 @@
|
||||
<link rel="icon" type="image/png" href="/assets/images/evolution-logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Evolution Manager</title>
|
||||
<script type="module" crossorigin src="/assets/index-efsrmrux.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-B-Bdu2zN.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DNOCacL_.css">
|
||||
</head>
|
||||
<body>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "evolution-api",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"description": "Rest api for communication with WhatsApp",
|
||||
"main": "./dist/main.js",
|
||||
"type": "commonjs",
|
||||
@ -52,8 +52,7 @@
|
||||
"@figuro/chatwoot-sdk": "^1.1.16",
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@prisma/client": "^5.15.0",
|
||||
"@sentry/node": "^7.119.0",
|
||||
"@sentry/profiling-node": "^8.26.0",
|
||||
"@sentry/node": "^8.28.0",
|
||||
"amqplib": "^0.10.3",
|
||||
"axios": "^1.6.5",
|
||||
"baileys": "6.7.7",
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `is_on_whatsapp` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropTable
|
||||
DROP TABLE "is_on_whatsapp";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "IsOnWhatsapp" (
|
||||
"id" TEXT NOT NULL,
|
||||
"remoteJid" VARCHAR(100) NOT NULL,
|
||||
"jidOptions" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP NOT NULL,
|
||||
|
||||
CONSTRAINT "IsOnWhatsapp_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "IsOnWhatsapp_remoteJid_key" ON "IsOnWhatsapp"("remoteJid");
|
@ -676,10 +676,8 @@ model FlowiseSetting {
|
||||
|
||||
model IsOnWhatsapp {
|
||||
id String @id @default(cuid())
|
||||
remoteJid String @unique @map("remote_jid") @db.VarChar(100)
|
||||
jidOptions String @map("jid_options")
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp
|
||||
|
||||
@@map("is_on_whatsapp")
|
||||
remoteJid String @unique @db.VarChar(100)
|
||||
jidOptions String
|
||||
createdAt DateTime @default(now()) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { Events, wa } from '@api/types/wa.types';
|
||||
import { Chatwoot, ConfigService, Openai } from '@config/env.config';
|
||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export class EvolutionStartupService extends ChannelStartupService {
|
||||
constructor(
|
||||
@ -92,7 +93,7 @@ export class EvolutionStartupService extends ChannelStartupService {
|
||||
|
||||
if (received.message) {
|
||||
const key = {
|
||||
id: received.key.id,
|
||||
id: received.key.id || v4(),
|
||||
remoteJid: received.key.remoteJid,
|
||||
fromMe: received.key.fromMe,
|
||||
};
|
||||
@ -159,48 +160,10 @@ export class EvolutionStartupService extends ChannelStartupService {
|
||||
data: messageRaw,
|
||||
});
|
||||
|
||||
const contact = await this.prismaRepository.contact.findFirst({
|
||||
where: { instanceId: this.instanceId, remoteJid: key.remoteJid },
|
||||
});
|
||||
|
||||
const contactRaw: any = {
|
||||
await this.updateContact({
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
pushName: received.pushName,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
if (contactRaw.remoteJid === 'status@broadcast') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contact) {
|
||||
const contactRaw: any = {
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
pushName: received.pushName,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPDATE, contactRaw);
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
|
||||
await this.chatwootService.eventWhatsapp(
|
||||
Events.CONTACTS_UPDATE,
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
contactRaw,
|
||||
);
|
||||
}
|
||||
|
||||
await this.prismaRepository.contact.updateMany({
|
||||
where: { remoteJid: contact.remoteJid },
|
||||
data: contactRaw,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
||||
|
||||
this.prismaRepository.contact.create({
|
||||
data: contactRaw,
|
||||
pushName: messageRaw.pushName,
|
||||
profilePicUrl: received.profilePicUrl,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@ -208,6 +171,79 @@ export class EvolutionStartupService extends ChannelStartupService {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateContact(data: { remoteJid: string; pushName?: string; profilePicUrl?: string }) {
|
||||
const contact = await this.prismaRepository.contact.findFirst({
|
||||
where: { instanceId: this.instanceId, remoteJid: data.remoteJid },
|
||||
});
|
||||
|
||||
if (contact) {
|
||||
const contactRaw: any = {
|
||||
remoteJid: data.remoteJid,
|
||||
pushName: data?.pushName,
|
||||
instanceId: this.instanceId,
|
||||
profilePicUrl: data?.profilePicUrl,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPDATE, contactRaw);
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
|
||||
await this.chatwootService.eventWhatsapp(
|
||||
Events.CONTACTS_UPDATE,
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
contactRaw,
|
||||
);
|
||||
}
|
||||
|
||||
await this.prismaRepository.contact.updateMany({
|
||||
where: { remoteJid: contact.remoteJid },
|
||||
data: contactRaw,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const contactRaw: any = {
|
||||
remoteJid: data.remoteJid,
|
||||
pushName: data?.pushName,
|
||||
instanceId: this.instanceId,
|
||||
profilePicUrl: data?.profilePicUrl,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
||||
|
||||
await this.prismaRepository.contact.create({
|
||||
data: contactRaw,
|
||||
});
|
||||
|
||||
const chat = await this.prismaRepository.chat.findFirst({
|
||||
where: { instanceId: this.instanceId, remoteJid: data.remoteJid },
|
||||
});
|
||||
|
||||
if (chat) {
|
||||
const chatRaw: any = {
|
||||
remoteJid: data.remoteJid,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CHATS_UPDATE, chatRaw);
|
||||
|
||||
await this.prismaRepository.chat.updateMany({
|
||||
where: { remoteJid: chat.remoteJid },
|
||||
data: chatRaw,
|
||||
});
|
||||
}
|
||||
|
||||
const chatRaw: any = {
|
||||
remoteJid: data.remoteJid,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CHATS_UPSERT, chatRaw);
|
||||
|
||||
await this.prismaRepository.chat.create({
|
||||
data: chatRaw,
|
||||
});
|
||||
}
|
||||
|
||||
protected async sendMessageWithTyping(number: string, message: any, options?: Options, isIntegration = false) {
|
||||
try {
|
||||
let quoted: any;
|
||||
@ -225,12 +261,18 @@ export class EvolutionStartupService extends ChannelStartupService {
|
||||
quoted = msg;
|
||||
}
|
||||
|
||||
if (options.delay) {
|
||||
await new Promise((resolve) => setTimeout(resolve, options.delay));
|
||||
}
|
||||
|
||||
if (options?.webhookUrl) {
|
||||
webhookUrl = options.webhookUrl;
|
||||
}
|
||||
|
||||
const messageId = v4();
|
||||
|
||||
const messageRaw: any = {
|
||||
key: { fromMe: true, id: 'ID', remoteJid: this.createJid(number) },
|
||||
key: { fromMe: true, id: messageId, remoteJid: number },
|
||||
message: {
|
||||
...message,
|
||||
quoted,
|
||||
|
@ -321,7 +321,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
try {
|
||||
const message: any = received;
|
||||
|
||||
const id = message[message.type].id;
|
||||
const id = message.messages[0][message.messages[0].type].id;
|
||||
let urlServer = this.configService.get<WaBusiness>('WA_BUSINESS').URL;
|
||||
const version = this.configService.get<WaBusiness>('WA_BUSINESS').VERSION;
|
||||
urlServer = `${urlServer}/${version}/${id}`;
|
||||
|
@ -1130,6 +1130,11 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
const mediaUrl = await s3Service.getObjectUrl(fullName);
|
||||
|
||||
messageRaw.message.mediaUrl = mediaUrl;
|
||||
|
||||
await this.prismaRepository.message.update({
|
||||
where: { id: msg.id },
|
||||
data: messageRaw,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error('line 1181');
|
||||
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);
|
||||
@ -2034,6 +2039,11 @@ export class BaileysStartupService extends ChannelStartupService {
|
||||
const mediaUrl = await s3Service.getObjectUrl(fullName);
|
||||
|
||||
messageRaw.message.mediaUrl = mediaUrl;
|
||||
|
||||
await this.prismaRepository.message.update({
|
||||
where: { id: msg.id },
|
||||
data: messageRaw,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error('line 1181');
|
||||
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);
|
||||
|
@ -306,10 +306,13 @@ export class ChatwootService {
|
||||
data = {
|
||||
inbox_id: inboxId,
|
||||
name: name || phoneNumber,
|
||||
phone_number: `+${phoneNumber}`,
|
||||
identifier: jid,
|
||||
avatar_url: avatar_url,
|
||||
};
|
||||
|
||||
if (jid.includes('@')) {
|
||||
data['phone_number'] = `+${phoneNumber}`;
|
||||
}
|
||||
} else {
|
||||
data = {
|
||||
inbox_id: inboxId,
|
||||
@ -1135,8 +1138,7 @@ export class ChatwootService {
|
||||
return { message: 'bot' };
|
||||
}
|
||||
|
||||
const chatId =
|
||||
body.conversation.meta.sender?.phone_number?.replace('+', '') || body.conversation.meta.sender?.identifier;
|
||||
const chatId = body.conversation.meta.sender?.identifier;
|
||||
// Chatwoot to Whatsapp
|
||||
const messageReceived = body.content
|
||||
? body.content
|
||||
@ -1819,14 +1821,12 @@ export class ChatwootService {
|
||||
return;
|
||||
}
|
||||
|
||||
// fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled
|
||||
if (body.message?.ephemeralMessage?.message) {
|
||||
body.message = {
|
||||
...body.message?.ephemeralMessage?.message,
|
||||
};
|
||||
}
|
||||
|
||||
// Whatsapp to Chatwoot
|
||||
const originalMessage = await this.getConversationMessage(body.message);
|
||||
const bodyMessage = originalMessage
|
||||
? originalMessage
|
||||
|
@ -527,12 +527,6 @@ export class ChannelStartupService {
|
||||
participants?: string;
|
||||
};
|
||||
|
||||
const remoteJid = keyFilters?.remoteJid
|
||||
? keyFilters?.remoteJid.includes('@')
|
||||
? keyFilters?.remoteJid
|
||||
: this.createJid(keyFilters?.remoteJid)
|
||||
: null;
|
||||
|
||||
const count = await this.prismaRepository.message.count({
|
||||
where: {
|
||||
instanceId: this.instanceId,
|
||||
@ -542,7 +536,7 @@ export class ChannelStartupService {
|
||||
AND: [
|
||||
keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {},
|
||||
keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {},
|
||||
remoteJid ? { key: { path: ['remoteJid'], equals: remoteJid } } : {},
|
||||
keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {},
|
||||
keyFilters?.participants ? { key: { path: ['participants'], equals: keyFilters?.participants } } : {},
|
||||
],
|
||||
},
|
||||
@ -565,7 +559,7 @@ export class ChannelStartupService {
|
||||
AND: [
|
||||
keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {},
|
||||
keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {},
|
||||
remoteJid ? { key: { path: ['remoteJid'], equals: remoteJid } } : {},
|
||||
keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {},
|
||||
keyFilters?.participants ? { key: { path: ['participants'], equals: keyFilters?.participants } } : {},
|
||||
],
|
||||
},
|
||||
@ -623,7 +617,7 @@ export class ChannelStartupService {
|
||||
let result;
|
||||
if (remoteJid) {
|
||||
result = await this.prismaRepository.$queryRaw`
|
||||
SELECT
|
||||
SELECT
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
@ -633,14 +627,24 @@ export class ChannelStartupService {
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl"
|
||||
FROM "Chat"
|
||||
INNER JOIN "Message" ON "Chat"."remoteJid" = "Message"."key"->>'remoteJid'
|
||||
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
||||
WHERE "Chat"."instanceId" = ${this.instanceId}
|
||||
AND "Chat"."remoteJid" = ${remoteJid}
|
||||
ORDER BY "Chat"."updatedAt" DESC
|
||||
GROUP BY
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
"Chat"."labels",
|
||||
"Chat"."createdAt",
|
||||
"Chat"."updatedAt",
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl"
|
||||
ORDER BY "Chat"."updatedAt" DESC;
|
||||
`;
|
||||
} else {
|
||||
result = await this.prismaRepository.$queryRaw`
|
||||
SELECT
|
||||
SELECT
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
@ -650,9 +654,19 @@ export class ChannelStartupService {
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl"
|
||||
FROM "Chat"
|
||||
INNER JOIN "Message" ON "Chat"."remoteJid" = "Message"."key"->>'remoteJid'
|
||||
LEFT JOIN "Contact" ON "Chat"."remoteJid" = "Contact"."remoteJid"
|
||||
WHERE "Chat"."instanceId" = ${this.instanceId}
|
||||
ORDER BY "Chat"."updatedAt" DESC
|
||||
GROUP BY
|
||||
"Chat"."id",
|
||||
"Chat"."remoteJid",
|
||||
"Chat"."name",
|
||||
"Chat"."labels",
|
||||
"Chat"."createdAt",
|
||||
"Chat"."updatedAt",
|
||||
"Contact"."pushName",
|
||||
"Contact"."profilePicUrl"
|
||||
ORDER BY "Chat"."updatedAt" DESC;
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ async function bootstrap() {
|
||||
dsn: dsn,
|
||||
environment: process.env.NODE_ENV || 'development',
|
||||
tracesSampleRate: 1.0,
|
||||
profilesSampleRate: 1.0,
|
||||
});
|
||||
app.use(Sentry.Handlers.requestHandler());
|
||||
app.use(Sentry.Handlers.tracingHandler());
|
||||
app.use(Sentry.Handlers.errorHandler());
|
||||
|
||||
Sentry.setupExpressErrorHandler(app);
|
||||
}
|
||||
|
||||
let providerFiles: ProviderFiles = null;
|
||||
|
Loading…
Reference in New Issue
Block a user