Merge branch 'ev2' into v2.0.0

This commit is contained in:
Stênio Aníbal
2024-08-20 11:26:34 -03:00
21 changed files with 675 additions and 398 deletions
+7
View File
@@ -1,3 +1,10 @@
# 2.1.0 (develop)
### Features
* Improved layout manager
* Translation in manager: English, Portuguese, Spanish and French
# 2.0.10 (2024-08-16 16:23) # 2.0.10 (2024-08-16 16:23)
### Features ### Features
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -5,8 +5,8 @@
<link rel="icon" type="image/png" href="/assets/images/evolution-logo.png" /> <link rel="icon" type="image/png" href="/assets/images/evolution-logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Evolution Manager</title> <title>Evolution Manager</title>
<script type="module" crossorigin src="/assets/index-Cqx_OwQi.js"></script> <script type="module" crossorigin src="/assets/index-CNPbB3iJ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DZ0gaAHg.css"> <link rel="stylesheet" crossorigin href="/assets/index-BJ9JMAl_.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "evolution-api", "name": "evolution-api",
"version": "2.0.10", "version": "2.1.0",
"description": "Rest api for communication with WhatsApp", "description": "Rest api for communication with WhatsApp",
"main": "./dist/main.js", "main": "./dist/main.js",
"type": "commonjs", "type": "commonjs",
+1
View File
@@ -37,6 +37,7 @@ enum TriggerType {
all all
keyword keyword
none none
advanced
} }
enum TriggerOperator { enum TriggerOperator {
@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "TriggerType" ADD VALUE 'advanced';
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "IntegrationSession" ADD COLUMN "context" JSONB;
+2
View File
@@ -37,6 +37,7 @@ enum TriggerType {
all all
keyword keyword
none none
advanced
} }
enum TriggerOperator { enum TriggerOperator {
@@ -393,6 +394,7 @@ model IntegrationSession {
pushName String? pushName String?
status SessionStatus status SessionStatus
awaitUser Boolean @default(false) @db.Boolean awaitUser Boolean @default(false) @db.Boolean
context Json?
createdAt DateTime? @default(now()) @db.Timestamp createdAt DateTime? @default(now()) @db.Timestamp
updatedAt DateTime @updatedAt @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp
Message Message[] Message Message[]
@@ -5,6 +5,7 @@ import { WAMonitoringService } from '@api/services/monitor.service';
import { Auth, ConfigService, HttpServer, S3 } from '@config/env.config'; import { Auth, ConfigService, HttpServer, S3 } from '@config/env.config';
import { Logger } from '@config/logger.config'; import { Logger } from '@config/logger.config';
import { Dify, DifySetting, IntegrationSession, Message } from '@prisma/client'; import { Dify, DifySetting, IntegrationSession, Message } from '@prisma/client';
import { advancedOperatorsSearch } from '@utils/advancedOperatorsSearch';
import { sendTelemetry } from '@utils/sendTelemetry'; import { sendTelemetry } from '@utils/sendTelemetry';
import axios from 'axios'; import axios from 'axios';
import { Readable } from 'stream'; import { Readable } from 'stream';
@@ -114,6 +115,23 @@ export class DifyService {
} }
} }
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.dify.findFirst({
where: {
triggerValue: data.triggerValue,
instanceId: instanceId,
},
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
try { try {
const dify = await this.prismaRepository.dify.create({ const dify = await this.prismaRepository.dify.create({
data: { data: {
@@ -239,9 +257,25 @@ export class DifyService {
where: { where: {
triggerOperator: data.triggerOperator, triggerOperator: data.triggerOperator,
triggerValue: data.triggerValue, triggerValue: data.triggerValue,
id: { id: { not: difyId },
not: difyId, instanceId: instanceId,
}, },
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.dify.findFirst({
where: {
triggerValue: data.triggerValue,
id: { not: difyId },
instanceId: instanceId, instanceId: instanceId,
}, },
}); });
@@ -727,6 +761,19 @@ export class DifyService {
if (findTriggerAll) return findTriggerAll; if (findTriggerAll) return findTriggerAll;
const findTriggerAdvanced = await this.prismaRepository.dify.findMany({
where: {
enabled: true,
triggerType: 'advanced',
instanceId: instanceId,
},
});
for (const advanced of findTriggerAdvanced) {
if (advancedOperatorsSearch(content, advanced.triggerValue)) {
return advanced;
}
}
// Check for exact match // Check for exact match
const findTriggerEquals = await this.prismaRepository.dify.findFirst({ const findTriggerEquals = await this.prismaRepository.dify.findFirst({
where: { where: {
@@ -29,7 +29,7 @@ export const difySchema: JSONSchema7 = {
botType: { type: 'string', enum: ['chatBot', 'textGenerator', 'agent', 'workflow'] }, botType: { type: 'string', enum: ['chatBot', 'textGenerator', 'agent', 'workflow'] },
apiUrl: { type: 'string' }, apiUrl: { type: 'string' },
apiKey: { type: 'string' }, apiKey: { type: 'string' },
triggerType: { type: 'string', enum: ['all', 'keyword', 'none'] }, triggerType: { type: 'string', enum: ['all', 'keyword', 'none', 'advanced'] },
triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] }, triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] },
triggerValue: { type: 'string' }, triggerValue: { type: 'string' },
expire: { type: 'integer' }, expire: { type: 'integer' },
@@ -10,6 +10,7 @@ import { WAMonitoringService } from '@api/services/monitor.service';
import { ConfigService, Language, S3 } from '@config/env.config'; import { ConfigService, Language, S3 } from '@config/env.config';
import { Logger } from '@config/logger.config'; import { Logger } from '@config/logger.config';
import { IntegrationSession, Message, OpenaiBot, OpenaiCreds, OpenaiSetting } from '@prisma/client'; import { IntegrationSession, Message, OpenaiBot, OpenaiCreds, OpenaiSetting } from '@prisma/client';
import { advancedOperatorsSearch } from '@utils/advancedOperatorsSearch';
import { sendTelemetry } from '@utils/sendTelemetry'; import { sendTelemetry } from '@utils/sendTelemetry';
import axios from 'axios'; import axios from 'axios';
import { downloadMediaMessage } from 'baileys'; import { downloadMediaMessage } from 'baileys';
@@ -238,6 +239,23 @@ export class OpenaiService {
} }
} }
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.openaiBot.findFirst({
where: {
triggerValue: data.triggerValue,
instanceId: instanceId,
},
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
try { try {
const openaiBot = await this.prismaRepository.openaiBot.create({ const openaiBot = await this.prismaRepository.openaiBot.create({
data: { data: {
@@ -390,9 +408,25 @@ export class OpenaiService {
where: { where: {
triggerOperator: data.triggerOperator, triggerOperator: data.triggerOperator,
triggerValue: data.triggerValue, triggerValue: data.triggerValue,
id: { id: { not: openaiBotId },
not: openaiBotId, instanceId: instanceId,
}, },
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.openaiBot.findFirst({
where: {
triggerValue: data.triggerValue,
id: { not: openaiBotId },
instanceId: instanceId, instanceId: instanceId,
}, },
}); });
@@ -452,7 +486,7 @@ export class OpenaiService {
const openaiBots = await this.prismaRepository.openaiBot.findMany({ const openaiBots = await this.prismaRepository.openaiBot.findMany({
where: { where: {
instanceId: instanceId, instanceId,
}, },
include: { include: {
sessions: true, sessions: true,
@@ -600,13 +634,14 @@ export class OpenaiService {
public async fetchDefaultSettings(instance: InstanceDto) { public async fetchDefaultSettings(instance: InstanceDto) {
try { try {
const instanceId = await this.prismaRepository.instance const instanceId = (
.findFirst({ await this.prismaRepository.instance.findFirst({
select: { id: true },
where: { where: {
name: instance.instanceName, name: instance.instanceName,
}, },
}) })
.then((instance) => instance.id); )?.id;
const settings = await this.prismaRepository.openaiSetting.findFirst({ const settings = await this.prismaRepository.openaiSetting.findFirst({
where: { where: {
@@ -931,6 +966,19 @@ export class OpenaiService {
if (findTriggerAll) return findTriggerAll; if (findTriggerAll) return findTriggerAll;
const findTriggerAdvanced = await this.prismaRepository.openaiBot.findMany({
where: {
enabled: true,
triggerType: 'advanced',
instanceId: instanceId,
},
});
for (const advanced of findTriggerAdvanced) {
if (advancedOperatorsSearch(content, advanced.triggerValue)) {
return advanced;
}
}
// Check for exact match // Check for exact match
const findTriggerEquals = await this.prismaRepository.openaiBot.findFirst({ const findTriggerEquals = await this.prismaRepository.openaiBot.findFirst({
where: { where: {
@@ -1070,7 +1118,7 @@ export class OpenaiService {
}, debounceTime * 1000); }, debounceTime * 1000);
} }
public async sendOpenai(instance: InstanceDto, remoteJid: string, msg: Message) { public async sendOpenai(instance: InstanceDto, remoteJid: string, pushName: string, msg: Message) {
try { try {
const settings = await this.prismaRepository.openaiSetting.findFirst({ const settings = await this.prismaRepository.openaiSetting.findFirst({
where: { where: {
@@ -1193,7 +1241,7 @@ export class OpenaiService {
}; };
if (stopBotFromMe && key.fromMe && session) { if (stopBotFromMe && key.fromMe && session) {
await this.prismaRepository.integrationSession.update({ session = await this.prismaRepository.integrationSession.update({
where: { where: {
id: session.id, id: session.id,
}, },
@@ -1201,7 +1249,6 @@ export class OpenaiService {
status: 'paused', status: 'paused',
}, },
}); });
return;
} }
if (!listeningFromMe && key.fromMe) { if (!listeningFromMe && key.fromMe) {
@@ -1214,6 +1261,8 @@ export class OpenaiService {
await this.processOpenaiAssistant( await this.processOpenaiAssistant(
this.waMonitor.waInstances[instance.instanceName], this.waMonitor.waInstances[instance.instanceName],
remoteJid, remoteJid,
pushName,
key.fromMe,
findOpenai, findOpenai,
session, session,
settings, settings,
@@ -1237,6 +1286,8 @@ export class OpenaiService {
await this.processOpenaiAssistant( await this.processOpenaiAssistant(
this.waMonitor.waInstances[instance.instanceName], this.waMonitor.waInstances[instance.instanceName],
remoteJid, remoteJid,
pushName,
key.fromMe,
findOpenai, findOpenai,
session, session,
settings, settings,
@@ -1304,6 +1355,8 @@ export class OpenaiService {
private async initAssistantNewSession( private async initAssistantNewSession(
instance: any, instance: any,
remoteJid: string, remoteJid: string,
pushName: string,
fromMe: boolean,
openaiBot: OpenaiBot, openaiBot: OpenaiBot,
settings: OpenaiSetting, settings: OpenaiSetting,
session: IntegrationSession, session: IntegrationSession,
@@ -1320,7 +1373,7 @@ export class OpenaiService {
} }
const messageData: any = { const messageData: any = {
role: 'user', role: fromMe ? 'assistant' : 'user',
content: [{ type: 'text', text: content }], content: [{ type: 'text', text: content }],
}; };
@@ -1342,6 +1395,11 @@ export class OpenaiService {
await this.client.beta.threads.messages.create(data.session.sessionId, messageData); await this.client.beta.threads.messages.create(data.session.sessionId, messageData);
if (fromMe) {
sendTelemetry('/message/sendText');
return;
}
const runAssistant = await this.client.beta.threads.runs.create(data.session.sessionId, { const runAssistant = await this.client.beta.threads.runs.create(data.session.sessionId, {
assistant_id: openaiBot.assistantId, assistant_id: openaiBot.assistantId,
}); });
@@ -1350,7 +1408,13 @@ export class OpenaiService {
await instance.client.sendPresenceUpdate('composing', remoteJid); await instance.client.sendPresenceUpdate('composing', remoteJid);
const response = await this.getAIResponse(data.session.sessionId, runAssistant.id, openaiBot.functionUrl); const response = await this.getAIResponse(
data.session.sessionId,
runAssistant.id,
openaiBot.functionUrl,
remoteJid,
pushName,
);
await instance.client.sendPresenceUpdate('paused', remoteJid); await instance.client.sendPresenceUpdate('paused', remoteJid);
@@ -1426,10 +1490,15 @@ export class OpenaiService {
} }
} }
private async getAIResponse(threadId: string, runId: string, functionUrl: string) { private async getAIResponse(
threadId: string,
runId: string,
functionUrl: string,
remoteJid: string,
pushName: string,
) {
const getRun = await this.client.beta.threads.runs.retrieve(threadId, runId); const getRun = await this.client.beta.threads.runs.retrieve(threadId, runId);
let toolCalls; let toolCalls;
switch (getRun.status) { switch (getRun.status) {
case 'requires_action': case 'requires_action':
toolCalls = getRun?.required_action?.submit_tool_outputs?.tool_calls; toolCalls = getRun?.required_action?.submit_tool_outputs?.tool_calls;
@@ -1447,7 +1516,7 @@ export class OpenaiService {
try { try {
const { data } = await axios.post(functionUrl, { const { data } = await axios.post(functionUrl, {
name: functionName, name: functionName,
arguments: functionArgument, arguments: { ...functionArgument, remoteJid, pushName },
}); });
output = JSON.stringify(data) output = JSON.stringify(data)
@@ -1476,13 +1545,13 @@ export class OpenaiService {
} }
} }
return this.getAIResponse(threadId, runId, functionUrl); return this.getAIResponse(threadId, runId, functionUrl, remoteJid, pushName);
case 'queued': case 'queued':
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
return this.getAIResponse(threadId, runId, functionUrl); return this.getAIResponse(threadId, runId, functionUrl, remoteJid, pushName);
case 'in_progress': case 'in_progress':
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
return this.getAIResponse(threadId, runId, functionUrl); return this.getAIResponse(threadId, runId, functionUrl, remoteJid, pushName);
case 'completed': case 'completed':
return await this.client.beta.threads.messages.list(threadId, { return await this.client.beta.threads.messages.list(threadId, {
run_id: runId, run_id: runId,
@@ -1498,12 +1567,14 @@ export class OpenaiService {
private async processOpenaiAssistant( private async processOpenaiAssistant(
instance: any, instance: any,
remoteJid: string, remoteJid: string,
pushName: string,
fromMe: boolean,
openaiBot: OpenaiBot, openaiBot: OpenaiBot,
session: IntegrationSession, session: IntegrationSession,
settings: OpenaiSetting, settings: OpenaiSetting,
content: string, content: string,
) { ) {
if (session && session.status !== 'opened') { if (session && session.status === 'closed') {
return; return;
} }
@@ -1535,25 +1606,35 @@ export class OpenaiService {
}); });
} }
await this.initAssistantNewSession(instance, remoteJid, openaiBot, settings, session, content); await this.initAssistantNewSession(
instance,
remoteJid,
pushName,
fromMe,
openaiBot,
settings,
session,
content,
);
return; return;
} }
} }
if (!session) { if (!session) {
await this.initAssistantNewSession(instance, remoteJid, openaiBot, settings, session, content); await this.initAssistantNewSession(instance, remoteJid, pushName, fromMe, openaiBot, settings, session, content);
return; return;
} }
await this.prismaRepository.integrationSession.update({ if (session.status !== 'paused')
where: { await this.prismaRepository.integrationSession.update({
id: session.id, where: {
}, id: session.id,
data: { },
status: 'opened', data: {
awaitUser: false, status: 'opened',
}, awaitUser: false,
}); },
});
if (!content) { if (!content) {
if (settings.unknownMessage) { if (settings.unknownMessage) {
@@ -1607,7 +1688,7 @@ export class OpenaiService {
const threadId = session.sessionId; const threadId = session.sessionId;
const messageData: any = { const messageData: any = {
role: 'user', role: fromMe ? 'assistant' : 'user',
content: [{ type: 'text', text: content }], content: [{ type: 'text', text: content }],
}; };
@@ -1629,15 +1710,24 @@ export class OpenaiService {
await this.client.beta.threads.messages.create(threadId, messageData); await this.client.beta.threads.messages.create(threadId, messageData);
if (fromMe || session?.status === 'paused') {
sendTelemetry('/message/sendText');
return;
}
const runAssistant = await this.client.beta.threads.runs.create(threadId, { const runAssistant = await this.client.beta.threads.runs.create(threadId, {
assistant_id: openaiBot.assistantId, assistant_id: openaiBot.assistantId,
additional_instructions: `WhatsappApiInfo:
Name: ${pushName}
RemoteJid: ${remoteJid}
`,
}); });
await instance.client.presenceSubscribe(remoteJid); await instance.client.presenceSubscribe(remoteJid);
await instance.client.sendPresenceUpdate('composing', remoteJid); await instance.client.sendPresenceUpdate('composing', remoteJid);
const response = await this.getAIResponse(threadId, runAssistant.id, openaiBot.functionUrl); const response = await this.getAIResponse(threadId, runAssistant.id, openaiBot.functionUrl, remoteJid, pushName);
await instance.client.sendPresenceUpdate('paused', remoteJid); await instance.client.sendPresenceUpdate('paused', remoteJid);
@@ -35,7 +35,7 @@ export const openaiSchema: JSONSchema7 = {
assistantMessages: { type: 'array', items: { type: 'string' } }, assistantMessages: { type: 'array', items: { type: 'string' } },
userMessages: { type: 'array', items: { type: 'string' } }, userMessages: { type: 'array', items: { type: 'string' } },
maxTokens: { type: 'integer' }, maxTokens: { type: 'integer' },
triggerType: { type: 'string', enum: ['all', 'keyword', 'none'] }, triggerType: { type: 'string', enum: ['all', 'keyword', 'none', 'advanced'] },
triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] }, triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] },
triggerValue: { type: 'string' }, triggerValue: { type: 'string' },
expire: { type: 'integer' }, expire: { type: 'integer' },
@@ -6,6 +6,7 @@ import { Events } from '@api/types/wa.types';
import { Auth, ConfigService, HttpServer, S3, Typebot } from '@config/env.config'; import { Auth, ConfigService, HttpServer, S3, Typebot } from '@config/env.config';
import { Logger } from '@config/logger.config'; import { Logger } from '@config/logger.config';
import { Instance, IntegrationSession, Message, Typebot as TypebotModel } from '@prisma/client'; import { Instance, IntegrationSession, Message, Typebot as TypebotModel } from '@prisma/client';
import { advancedOperatorsSearch } from '@utils/advancedOperatorsSearch';
import { sendTelemetry } from '@utils/sendTelemetry'; import { sendTelemetry } from '@utils/sendTelemetry';
import axios from 'axios'; import axios from 'axios';
@@ -113,6 +114,23 @@ export class TypebotService {
} }
} }
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.typebot.findFirst({
where: {
triggerValue: data.triggerValue,
instanceId: instanceId,
},
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
try { try {
const typebot = await this.prismaRepository.typebot.create({ const typebot = await this.prismaRepository.typebot.create({
data: { data: {
@@ -250,6 +268,24 @@ export class TypebotService {
} }
} }
if (data.triggerType === 'advanced') {
if (!data.triggerValue) {
throw new Error('Trigger value is required');
}
const checkDuplicate = await this.prismaRepository.typebot.findFirst({
where: {
triggerValue: data.triggerValue,
id: { not: typebotId },
instanceId: instanceId,
},
});
if (checkDuplicate) {
throw new Error('Trigger already exists');
}
}
try { try {
const typebot = await this.prismaRepository.typebot.update({ const typebot = await this.prismaRepository.typebot.update({
where: { where: {
@@ -1287,6 +1323,19 @@ export class TypebotService {
if (findTriggerAll) return findTriggerAll; if (findTriggerAll) return findTriggerAll;
const findTriggerAdvanced = await this.prismaRepository.typebot.findMany({
where: {
enabled: true,
triggerType: 'advanced',
instanceId: instanceId,
},
});
for (const advanced of findTriggerAdvanced) {
if (advancedOperatorsSearch(content, advanced.triggerValue)) {
return advanced;
}
}
// Check for exact match // Check for exact match
const findTriggerEquals = await this.prismaRepository.typebot.findFirst({ const findTriggerEquals = await this.prismaRepository.typebot.findFirst({
where: { where: {
@@ -28,7 +28,7 @@ export const typebotSchema: JSONSchema7 = {
description: { type: 'string' }, description: { type: 'string' },
url: { type: 'string' }, url: { type: 'string' },
typebot: { type: 'string' }, typebot: { type: 'string' },
triggerType: { type: 'string', enum: ['all', 'keyword', 'none'] }, triggerType: { type: 'string', enum: ['all', 'keyword', 'none', 'advanced'] },
triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] }, triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] },
triggerValue: { type: 'string' }, triggerValue: { type: 'string' },
expire: { type: 'integer' }, expire: { type: 'integer' },
+3
View File
@@ -78,6 +78,9 @@ router
return res.status(HttpStatus.OK).json({ return res.status(HttpStatus.OK).json({
status: HttpStatus.OK, status: HttpStatus.OK,
message: 'Credentials are valid', message: 'Credentials are valid',
facebookAppId: process.env.FACEBOOK_APP_ID,
facebookConfigId: process.env.FACEBOOK_CONFIG_ID,
facebookUserToken: process.env.FACEBOOK_USER_TOKEN,
}); });
}) })
.use('/instance', new InstanceRouter(configService, ...guards).router) .use('/instance', new InstanceRouter(configService, ...guards).router)
@@ -1243,6 +1243,7 @@ export class BaileysStartupService extends ChannelStartupService {
await this.openaiService.sendOpenai( await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId }, { instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid, messageRaw.key.remoteJid,
messageRaw.pushName,
messageRaw, messageRaw,
); );
} }
@@ -2056,6 +2057,7 @@ export class BaileysStartupService extends ChannelStartupService {
await this.openaiService.sendOpenai( await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId }, { instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid, messageRaw.key.remoteJid,
messageRaw.pushName,
messageRaw, messageRaw,
); );
} }
@@ -512,6 +512,7 @@ export class BusinessStartupService extends ChannelStartupService {
await this.openaiService.sendOpenai( await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId }, { instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid, messageRaw.key.remoteJid,
pushName,
messageRaw, messageRaw,
); );
} }
@@ -960,6 +961,7 @@ export class BusinessStartupService extends ChannelStartupService {
await this.openaiService.sendOpenai( await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId }, { instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid, messageRaw.key.remoteJid,
messageRaw.pushName,
messageRaw, messageRaw,
); );
} }
+45
View File
@@ -0,0 +1,45 @@
function normalizeString(str: string): string {
return str
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.toLowerCase();
}
export function advancedOperatorsSearch(data: string, query: string): boolean {
const filters = query.split(' ').reduce((acc: Record<string, string[]>, filter) => {
const [operator, ...values] = filter.split(':');
const value = values.join(':');
if (!acc[operator]) {
acc[operator] = [];
}
acc[operator].push(value);
return acc;
}, {});
const normalizedItem = normalizeString(data);
return Object.entries(filters).every(([operator, values]) => {
return values.some((val) => {
const subValues = val.split(',');
return subValues.every((subVal) => {
const normalizedSubVal = normalizeString(subVal);
switch (operator.toLowerCase()) {
case 'contains':
return normalizedItem.includes(normalizedSubVal);
case 'notcontains':
return !normalizedItem.includes(normalizedSubVal);
case 'startswith':
return normalizedItem.startsWith(normalizedSubVal);
case 'endswith':
return normalizedItem.endsWith(normalizedSubVal);
case 'exact':
return normalizedItem === normalizedSubVal;
default:
return false;
}
});
});
});
}