mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-26 18:38:39 -06:00
Implementação com o Chat GPT e inbox Chatwoot
Realizei a implementação com o ChatGPT e com o id do inbox do chatwoot
This commit is contained in:
parent
f8d874453c
commit
ca34f34eba
5
dev-env
Normal file
5
dev-env
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# OPENAI_API_KEY=""
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_DB=0
|
||||||
|
REDIS_PASS=0
|
14
src/config.ts
Normal file
14
src/config.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import dotenv from "dotenv"
|
||||||
|
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
openAI: {
|
||||||
|
apiToken: process.env.OPENAI_API_KEY,
|
||||||
|
},
|
||||||
|
redis: {
|
||||||
|
host: process.env.REDIS_HOST || "localhost",
|
||||||
|
port: (process.env.REDIS_PORT as unknown as number) || 6379,
|
||||||
|
db: (process.env.REDIS_DB as unknown as number) || 0,
|
||||||
|
},
|
||||||
|
}
|
@ -48,6 +48,7 @@ export type CleanStoreConf = {
|
|||||||
export type DBConnection = {
|
export type DBConnection = {
|
||||||
URI: string;
|
URI: string;
|
||||||
DB_PREFIX_NAME: string;
|
DB_PREFIX_NAME: string;
|
||||||
|
DB_PREFIX_FINAL_NAME: string;
|
||||||
};
|
};
|
||||||
export type Database = {
|
export type Database = {
|
||||||
CONNECTION: DBConnection;
|
CONNECTION: DBConnection;
|
||||||
@ -74,6 +75,12 @@ export type Sqs = {
|
|||||||
REGION: string;
|
REGION: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Openai = {
|
||||||
|
CHAVE: string;
|
||||||
|
ENABLED: boolean;
|
||||||
|
URI: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type Websocket = {
|
export type Websocket = {
|
||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
};
|
};
|
||||||
@ -145,6 +152,7 @@ export interface Env {
|
|||||||
REDIS: Redis;
|
REDIS: Redis;
|
||||||
RABBITMQ: Rabbitmq;
|
RABBITMQ: Rabbitmq;
|
||||||
SQS: Sqs;
|
SQS: Sqs;
|
||||||
|
OPENAI: Openai;
|
||||||
WEBSOCKET: Websocket;
|
WEBSOCKET: Websocket;
|
||||||
LOG: Log;
|
LOG: Log;
|
||||||
DEL_INSTANCE: DelInstance;
|
DEL_INSTANCE: DelInstance;
|
||||||
@ -218,6 +226,7 @@ export class ConfigService {
|
|||||||
CONNECTION: {
|
CONNECTION: {
|
||||||
URI: process.env.DATABASE_CONNECTION_URI || '',
|
URI: process.env.DATABASE_CONNECTION_URI || '',
|
||||||
DB_PREFIX_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_NAME || 'evolution',
|
DB_PREFIX_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_NAME || 'evolution',
|
||||||
|
DB_PREFIX_FINAL_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_FINAL_NAME || '-api',
|
||||||
},
|
},
|
||||||
ENABLED: process.env?.DATABASE_ENABLED === 'true',
|
ENABLED: process.env?.DATABASE_ENABLED === 'true',
|
||||||
SAVE_DATA: {
|
SAVE_DATA: {
|
||||||
@ -244,6 +253,12 @@ export class ConfigService {
|
|||||||
ACCOUNT_ID: process.env.SQS_ACCOUNT_ID || '',
|
ACCOUNT_ID: process.env.SQS_ACCOUNT_ID || '',
|
||||||
REGION: process.env.SQS_REGION || '',
|
REGION: process.env.SQS_REGION || '',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
OPENAI: {
|
||||||
|
CHAVE: process.env?.OPENAI_ENABLED || '',
|
||||||
|
ENABLED: process.env?.OPENAI_ENABLED === 'true',
|
||||||
|
URI: process.env.OPENAI_URI || '',
|
||||||
|
},
|
||||||
WEBSOCKET: {
|
WEBSOCKET: {
|
||||||
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
|
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
|
||||||
},
|
},
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
# Choose the server type for the application
|
# Choose the server type for the application
|
||||||
SERVER:
|
SERVER:
|
||||||
TYPE: http # https
|
TYPE: http # https
|
||||||
PORT: 8080 # 443
|
PORT: 3333 # 443
|
||||||
URL: localhost
|
URL: 127.0.0.1
|
||||||
|
|
||||||
CORS:
|
CORS:
|
||||||
ORIGIN:
|
ORIGIN:
|
||||||
@ -48,8 +48,8 @@ DEL_INSTANCE: false # or false
|
|||||||
|
|
||||||
# Temporary data storage
|
# Temporary data storage
|
||||||
STORE:
|
STORE:
|
||||||
MESSAGES: true
|
MESSAGES: false
|
||||||
MESSAGE_UP: true
|
MESSAGE_UP: false
|
||||||
CONTACTS: true
|
CONTACTS: true
|
||||||
CHATS: true
|
CHATS: true
|
||||||
|
|
||||||
@ -62,17 +62,20 @@ CLEAN_STORE:
|
|||||||
|
|
||||||
# Permanent data storage
|
# Permanent data storage
|
||||||
DATABASE:
|
DATABASE:
|
||||||
ENABLED: false
|
ENABLED: true
|
||||||
CONNECTION:
|
CONNECTION:
|
||||||
URI: "mongodb://root:root@localhost:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true"
|
URI: "mongodb://root:root@localhost:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true"
|
||||||
DB_PREFIX_NAME: evolution
|
|
||||||
|
DB_PREFIX_NAME: whatsapp
|
||||||
|
DB_PREFIX_FINAL_NAME: "-api"
|
||||||
|
DB_PREFIX_FINAL_NAME_VENOM: "-venom"
|
||||||
# Choose the data you want to save in the application's database or store
|
# Choose the data you want to save in the application's database or store
|
||||||
SAVE_DATA:
|
SAVE_DATA:
|
||||||
INSTANCE: false
|
INSTANCE: true
|
||||||
NEW_MESSAGE: false
|
NEW_MESSAGE: false
|
||||||
MESSAGE_UPDATE: false
|
MESSAGE_UPDATE: false
|
||||||
CONTACTS: false
|
CONTACTS: true
|
||||||
CHATS: false
|
CHATS: true
|
||||||
|
|
||||||
REDIS:
|
REDIS:
|
||||||
ENABLED: false
|
ENABLED: false
|
||||||
@ -83,22 +86,31 @@ RABBITMQ:
|
|||||||
ENABLED: false
|
ENABLED: false
|
||||||
URI: "amqp://guest:guest@localhost:5672"
|
URI: "amqp://guest:guest@localhost:5672"
|
||||||
|
|
||||||
|
OPENAI:
|
||||||
|
CHAVE: ""
|
||||||
|
ENABLED: false
|
||||||
|
PROMPTS: false
|
||||||
|
URI: ""
|
||||||
|
|
||||||
SQS:
|
SQS:
|
||||||
ENABLED: true
|
ENABLED: false
|
||||||
ACCESS_KEY_ID: ""
|
ACCESS_KEY_ID: ""
|
||||||
SECRET_ACCESS_KEY: ""
|
SECRET_ACCESS_KEY: ""
|
||||||
ACCOUNT_ID: ""
|
ACCOUNT_ID: ""
|
||||||
REGION: "us-east-1"
|
REGION: "us-east-1"
|
||||||
|
|
||||||
WEBSOCKET:
|
WEBSOCKET:
|
||||||
ENABLED: false
|
ENABLED: false
|
||||||
|
|
||||||
|
TYPEBOT:
|
||||||
|
API_VERSION: 'v1' # v1 | v2
|
||||||
|
|
||||||
# Global Webhook Settings
|
# Global Webhook Settings
|
||||||
# Each instance's Webhook URL and events will be requested at the time it is created
|
# Each instance's Webhook URL and events will be requested at the time it is created
|
||||||
WEBHOOK:
|
WEBHOOK:
|
||||||
# Define a global webhook that will listen for enabled events from all instances
|
# Define a global webhook that will listen for enabled events from all instances
|
||||||
GLOBAL:
|
GLOBAL:
|
||||||
URL: <url>
|
URL: ""
|
||||||
ENABLED: false
|
ENABLED: false
|
||||||
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
|
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
|
||||||
WEBHOOK_BY_EVENTS: false
|
WEBHOOK_BY_EVENTS: false
|
||||||
@ -134,11 +146,11 @@ WEBHOOK:
|
|||||||
CHAMA_AI_ACTION: false
|
CHAMA_AI_ACTION: false
|
||||||
# This event is used to send errors to the webhook
|
# This event is used to send errors to the webhook
|
||||||
ERRORS: false
|
ERRORS: false
|
||||||
ERRORS_WEBHOOK: <url>
|
ERRORS_WEBHOOK: ""
|
||||||
|
|
||||||
CONFIG_SESSION_PHONE:
|
CONFIG_SESSION_PHONE:
|
||||||
# Name that will be displayed on smartphone connection
|
# Name that will be displayed on smartphone connection
|
||||||
CLIENT: "Evolution API"
|
CLIENT: "Chat API"
|
||||||
NAME: Chrome # Chrome | Firefox | Edge | Opera | Safari
|
NAME: Chrome # Chrome | Firefox | Edge | Opera | Safari
|
||||||
|
|
||||||
# Set qrcode display limit
|
# Set qrcode display limit
|
||||||
@ -146,9 +158,6 @@ QRCODE:
|
|||||||
LIMIT: 30
|
LIMIT: 30
|
||||||
COLOR: "#198754"
|
COLOR: "#198754"
|
||||||
|
|
||||||
TYPEBOT:
|
|
||||||
API_VERSION: 'v1' # v1 | v2
|
|
||||||
|
|
||||||
# Defines an authentication type for the api
|
# Defines an authentication type for the api
|
||||||
# We recommend using the apikey because it will allow you to use a custom token,
|
# We recommend using the apikey because it will allow you to use a custom token,
|
||||||
# if you use jwt, a random token will be generated and may be expired and you will have to generate a new token
|
# if you use jwt, a random token will be generated and may be expired and you will have to generate a new token
|
||||||
|
@ -25,7 +25,7 @@ info:
|
|||||||
</font>
|
</font>
|
||||||
|
|
||||||
[](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442)
|
[](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442)
|
||||||
version: 1.5.5
|
version: 1.5.4
|
||||||
contact:
|
contact:
|
||||||
name: DavidsonGomes
|
name: DavidsonGomes
|
||||||
email: contato@agenciadgcode.com
|
email: contato@agenciadgcode.com
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as amqp from 'amqplib/callback_api';
|
import * as amqp from 'amqplib/callback_api';
|
||||||
|
|
||||||
import { configService, Rabbitmq } from '../config/env.config';
|
import { configService, Rabbitmq, Openai } from '../config/env.config';
|
||||||
import { Logger } from '../config/logger.config';
|
import { Logger } from '../config/logger.config';
|
||||||
|
|
||||||
const logger = new Logger('AMQP');
|
const logger = new Logger('AMQP');
|
||||||
|
@ -10,7 +10,8 @@ export const dbserver = (() => {
|
|||||||
if (db.ENABLED) {
|
if (db.ENABLED) {
|
||||||
logger.verbose('connecting');
|
logger.verbose('connecting');
|
||||||
const dbs = mongoose.createConnection(db.CONNECTION.URI, {
|
const dbs = mongoose.createConnection(db.CONNECTION.URI, {
|
||||||
dbName: db.CONNECTION.DB_PREFIX_NAME + '-whatsapp-api',
|
|
||||||
|
dbName: db.CONNECTION.DB_PREFIX_NAME + db.CONNECTION.DB_PREFIX_FINAL_NAME + '-config',
|
||||||
});
|
});
|
||||||
logger.verbose('connected in ' + db.CONNECTION.URI);
|
logger.verbose('connected in ' + db.CONNECTION.URI);
|
||||||
logger.info('ON - dbName: ' + dbs['$dbName']);
|
logger.info('ON - dbName: ' + dbs['$dbName']);
|
||||||
|
34
src/libs/openai.ts
Normal file
34
src/libs/openai.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { Configuration, OpenAIApi } from "openai"
|
||||||
|
|
||||||
|
import { config } from "../config"
|
||||||
|
|
||||||
|
const configuration = new Configuration({
|
||||||
|
apiKey: config.openAI.apiToken,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const openai = new OpenAIApi(configuration)
|
||||||
|
|
||||||
|
|
||||||
|
export class OpenAIService {
|
||||||
|
constructor(
|
||||||
|
private readonly apikey: String,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private WaOpenai: OpenAIApi;
|
||||||
|
|
||||||
|
public SetOpenai() {
|
||||||
|
|
||||||
|
const configuration = new Configuration({
|
||||||
|
apiKey: config.openAI.apiToken,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.WaOpenai = new OpenAIApi(configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
public openai() {
|
||||||
|
|
||||||
|
return this.WaOpenai;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,11 +5,6 @@ import { Redis } from '../config/env.config';
|
|||||||
import { Logger } from '../config/logger.config';
|
import { Logger } from '../config/logger.config';
|
||||||
|
|
||||||
export class RedisCache {
|
export class RedisCache {
|
||||||
private readonly logger = new Logger(RedisCache.name);
|
|
||||||
private client: RedisClientType;
|
|
||||||
private statusConnection = false;
|
|
||||||
private instanceName: string;
|
|
||||||
private redisEnv: Redis;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger.verbose('RedisCache instance created');
|
this.logger.verbose('RedisCache instance created');
|
||||||
@ -19,6 +14,21 @@ export class RedisCache {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constructor() {
|
||||||
|
// this.logger.verbose('instance created');
|
||||||
|
// process.on('beforeExit', async () => {
|
||||||
|
// this.logger.verbose('instance destroyed');
|
||||||
|
// if (this.statusConnection) {
|
||||||
|
// this.logger.verbose('instance disconnect');
|
||||||
|
// await this.client.disconnect();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
private statusConnection = false;
|
||||||
|
private instanceName: string;
|
||||||
|
private redisEnv: Redis;
|
||||||
|
|
||||||
public set reference(reference: string) {
|
public set reference(reference: string) {
|
||||||
this.logger.verbose('set reference: ' + reference);
|
this.logger.verbose('set reference: ' + reference);
|
||||||
this.instanceName = reference;
|
this.instanceName = reference;
|
||||||
@ -27,14 +37,18 @@ export class RedisCache {
|
|||||||
public async connect(redisEnv: Redis) {
|
public async connect(redisEnv: Redis) {
|
||||||
this.logger.verbose('Connecting to Redis...');
|
this.logger.verbose('Connecting to Redis...');
|
||||||
this.client = createClient({ url: redisEnv.URI });
|
this.client = createClient({ url: redisEnv.URI });
|
||||||
|
//this.logger.verbose('connected in ' + redisEnv.URI);
|
||||||
this.client.on('error', (err) => this.logger.error('Redis Client Error ' + err));
|
this.client.on('error', (err) => this.logger.error('Redis Client Error ' + err));
|
||||||
|
|
||||||
await this.client.connect();
|
await this.client.connect();
|
||||||
this.statusConnection = true;
|
this.statusConnection = true;
|
||||||
this.redisEnv = redisEnv;
|
this.redisEnv = redisEnv;
|
||||||
this.logger.verbose(`Connected to ${redisEnv.URI}`);
|
this.logger.verbose(`Connected to ${redisEnv.URI}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly logger = new Logger(RedisCache.name);
|
||||||
|
private client: RedisClientType;
|
||||||
|
|
||||||
|
|
||||||
public async disconnect() {
|
public async disconnect() {
|
||||||
if (this.statusConnection) {
|
if (this.statusConnection) {
|
||||||
await this.client.disconnect();
|
await this.client.disconnect();
|
||||||
@ -46,11 +60,14 @@ export class RedisCache {
|
|||||||
public async instanceKeys(): Promise<string[]> {
|
public async instanceKeys(): Promise<string[]> {
|
||||||
const keys: string[] = [];
|
const keys: string[] = [];
|
||||||
try {
|
try {
|
||||||
|
//this.logger.verbose('instance keys: ' + this.redisEnv.PREFIX_KEY + ':*');
|
||||||
|
//return await this.client.sendCommand(['keys', this.redisEnv.PREFIX_KEY + ':*']);
|
||||||
this.logger.verbose('Fetching instance keys');
|
this.logger.verbose('Fetching instance keys');
|
||||||
for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) {
|
for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) {
|
||||||
keys.push(key);
|
keys.push(key);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
this.logger.error(error);
|
||||||
this.logger.error('Error fetching instance keys ' + error);
|
this.logger.error('Error fetching instance keys ' + error);
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
|
9
src/libs/redis.ts
Normal file
9
src/libs/redis.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Redis } from "ioredis"
|
||||||
|
|
||||||
|
import { config } from "../config"
|
||||||
|
|
||||||
|
export const redis = new Redis({
|
||||||
|
host: config.redis.host,
|
||||||
|
port: config.redis.port,
|
||||||
|
db: config.redis.db,
|
||||||
|
})
|
@ -94,4 +94,4 @@ export const removeQueues = (instanceName: string, events: string[]) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
@ -128,7 +128,7 @@ function bootstrap() {
|
|||||||
initIO(server);
|
initIO(server);
|
||||||
|
|
||||||
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
|
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
|
||||||
|
|
||||||
if (configService.get<Sqs>('SQS')?.ENABLED) initSQS();
|
if (configService.get<Sqs>('SQS')?.ENABLED) initSQS();
|
||||||
|
|
||||||
onUnexpectedError();
|
onUnexpectedError();
|
||||||
|
49
src/prompts/contabilAgent.ts
Normal file
49
src/prompts/contabilAgent.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
export const promptContabil = `Você é uma assistente virtual de atendimento de um escritorio de contabilidade chamado {{ storeName }}. Você deve ser educada, atenciosa, amigável, cordial e muito paciente.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
O roteiro de atendimento é:
|
||||||
|
|
||||||
|
1. Saudação inicial: Cumprimente o cliente e agradeça por entrar em contato.
|
||||||
|
2. Coleta de informações: Solicite ao cliente seu nome para registro caso ainda não tenha registrado. Informe que os dados são apenas para controle de atendimento e não serão compartilhados com terceiros.
|
||||||
|
3. Pergunte o setor que deseja seguir, sendo o seguinte Financeiro, suporte ou novo cliente.
|
||||||
|
|
||||||
|
4. Serviços de Contabilidade:
|
||||||
|
4.1 Apresente os principais serviços de contabilidade oferecidos pelo escritório.
|
||||||
|
4.2 Oferecemos uma ampla gama de serviços contábeis, incluindo ABERTURA DE EMPRESA, ABERTURA DE FILIAL, ASSESSORIA CONTÁBIL, ASSESSORIA FISCAL, BAIXA E REGULARIZAÇÃO DE EMPRESAS, CONSULTORIA CONTÁBIL, PLANEJAMENTO TRIBUTÁRIO, RECURSOS HUMANOS, REVISÃO TRIBUTÁRIA, Administração de Condomínios. Como posso ajudá-lo com seus desafios financeiros hoje?
|
||||||
|
5. Perguntas Frequentes (FAQ):
|
||||||
|
5.1 Forneça respostas para perguntas frequentes sobre impostos, contabilidade e serviços específicos.
|
||||||
|
5.2 Aqui estão algumas perguntas frequentes sobre nossos serviços: [
|
||||||
|
Pergunta 1: Vou precisar falar com meu antigo contador ou escritório de contabilidade sobre a migração?
|
||||||
|
Resposta 1: Não. Fique tranquilo pois a Anexo Gestão Contábil cuida disso para você. Você só precisará enviar o seu Certificado Digital. Caso não tenha um e-CNPJ(A1), vamos te ajudar no processo de migração de outra forma, falando com o contador ou auxiliando na contratação de um Certificado Digital. Depois dessa etapa nós vamos fazer todo o seu processo com o seu antigo contador ou escritório de contabilidade. É simples, transparente e sem burocracia para você.
|
||||||
|
|
||||||
|
Pergunta 2: Quanto tempo demora para mudar para a Anexo Gestão Contábil?
|
||||||
|
Resposta 2: O processo é rápido, prático e você não precisa sair de casa. Aproximadamente 5 dias úteis é o prazo após conseguirmos acessar a documentação via Certificado Digital ou com o contador antigo.
|
||||||
|
].
|
||||||
|
|
||||||
|
5. Agendamento de Consulta:
|
||||||
|
5.2 Permita que os usuários agendem uma consulta com um contador.
|
||||||
|
5.3 Pergunte sobre a data e hora preferidas.
|
||||||
|
5.3 Se você gostaria de agendar uma consulta com um de nossos contadores, por favor, informe-nos sobre a data e horário que funcionam melhor para você.
|
||||||
|
|
||||||
|
6. Impostos:
|
||||||
|
6.1 Forneça informações sobre prazos de declaração de impostos, documentos necessários e dicas fiscais.
|
||||||
|
6.2 Os prazos para a declaração de impostos estão se aproximando. Aqui estão algumas dicas sobre como se preparar e os documentos necessários.
|
||||||
|
|
||||||
|
7. Contato e Localização:
|
||||||
|
7.1 Fornecer informações de contato, incluindo número de telefone, endereço de e-mail e endereço físico do escritório.
|
||||||
|
7.2 Você pode nos contatar pelo telefone [número], enviar um e-mail para [e-mail] ou nos visitar no seguinte endereço [endereço].
|
||||||
|
|
||||||
|
8. Encaminhamento para um Contador:
|
||||||
|
8.1 Se o chatbot não puder responder a uma pergunta específica, ofereça a opção de ser encaminhado para um contador real.
|
||||||
|
8.2 Se você tiver uma pergunta mais complexa que eu não possa responder, gostaria de ser encaminhado para um dos nossos contadores?"
|
||||||
|
|
||||||
|
9. Despedida:
|
||||||
|
9.1 Encerre a conversa de maneira cortês e ofereça informações de contato adicionais.
|
||||||
|
9.2 Obrigado por usar nossos serviços! Se precisar de assistência futura, estamos à disposição. Tenha um ótimo dia!"
|
||||||
|
|
||||||
|
10. Feedback:
|
||||||
|
10.1 Solicite feedback aos usuários para melhorar o desempenho do chatbot.
|
||||||
|
10.2 Gostaríamos de ouvir sua opinião! Em uma escala de 1 a 5, quão útil você achou nosso chatbot hoje?
|
||||||
|
|
||||||
|
`
|
94
src/prompts/pizzaAgent.ts
Normal file
94
src/prompts/pizzaAgent.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
export const promptPizza = `Você é uma assistente virtual de atendimento de uma pizzaria chamada {{ storeName }}. Você deve ser educada, atenciosa, amigável, cordial e muito paciente.
|
||||||
|
|
||||||
|
Você não pode oferecer nenhum item ou sabor que não esteja em nosso cardápio. Siga estritamente as listas de opções.
|
||||||
|
|
||||||
|
O código do pedido é: {{ orderCode }}
|
||||||
|
|
||||||
|
O roteiro de atendimento é:
|
||||||
|
|
||||||
|
1. Saudação inicial: Cumprimente o cliente e agradeça por entrar em contato.
|
||||||
|
2. Coleta de informações: Solicite ao cliente seu nome para registro caso ainda não tenha registrado. Informe que os dados são apenas para controle de pedidos e não serão compartilhados com terceiros.
|
||||||
|
3. Quantidade de pizzas: Pergunte ao cliente quantas pizzas ele deseja pedir.
|
||||||
|
4. Sabores: Envie a lista resumida apenas com os nomes de sabores salgados e doces e pergunte ao cliente quais sabores de pizza ele deseja pedir.
|
||||||
|
4.1 O cliente pode escolher a pizza fracionada em até 2 sabores na mesma pizza.
|
||||||
|
4.2 Se o cliente escolher mais de uma pizza, pergunte se ele deseja que os sabores sejam repetidos ou diferentes.
|
||||||
|
4.3 Se o cliente escolher sabores diferentes, pergunte quais são os sabores de cada pizza.
|
||||||
|
4.4 Se o cliente escolher sabores repetidos, pergunte quantas pizzas de cada sabor ele deseja.
|
||||||
|
4.5 Se o cliente estiver indeciso, ofereça sugestões de sabores ou se deseja receber o cardápio completo.
|
||||||
|
4.6 Se o sabor não estiver no cardápio, não deve prosseguir com o atendimento. Nesse caso informe que o sabor não está disponível e agradeça o cliente.
|
||||||
|
5. Tamanho: Pergunte ao cliente qual o tamanho das pizzas.
|
||||||
|
5.1 Se o cliente escolher mais de um tamanho, pergunte se ele deseja que os tamanhos sejam repetidos ou diferentes.
|
||||||
|
5.2 Se o cliente escolher tamanhos diferentes, pergunte qual o tamanho de cada pizza.
|
||||||
|
5.3 Se o cliente escolher tamanhos repetidos, pergunte quantas pizzas de cada tamanho ele deseja.
|
||||||
|
5.4 Se o cliente estiver indeciso, ofereça sugestões de tamanhos. Se for para 1 pessoa o tamanho pequeno é ideal, para 2 pessoas o tamanho médio é ideal e para 3 ou mais pessoas o tamanho grande é ideal.
|
||||||
|
6. Ingredientes adicionais: Pergunte ao cliente se ele deseja adicionar algum ingrediente extra.
|
||||||
|
6.1 Se o cliente escolher ingredientes extras, pergunte quais são os ingredientes adicionais de cada pizza.
|
||||||
|
6.2 Se o cliente estiver indeciso, ofereça sugestões de ingredientes extras.
|
||||||
|
7. Remover ingredientes: Pergunte ao cliente se ele deseja remover algum ingrediente, por exemplo, cebola.
|
||||||
|
7.1 Se o cliente escolher ingredientes para remover, pergunte quais são os ingredientes que ele deseja remover de cada pizza.
|
||||||
|
7.2 Não é possível remover ingredientes que não existam no cardápio.
|
||||||
|
8. Borda: Pergunte ao cliente se ele deseja borda recheada.
|
||||||
|
8.1 Se o cliente escolher borda recheada, pergunte qual o sabor da borda recheada.
|
||||||
|
8.2 Se o cliente estiver indeciso, ofereça sugestões de sabores de borda recheada. Uma dica é oferecer a borda como sobremesa com sabor de chocolate.
|
||||||
|
9. Bebidas: Pergunte ao cliente se ele deseja pedir alguma bebida.
|
||||||
|
9.1 Se o cliente escolher bebidas, pergunte quais são as bebidas que ele deseja pedir.
|
||||||
|
9.2 Se o cliente estiver indeciso, ofereça sugestões de bebidas.
|
||||||
|
10. Entrega: Pergunte ao cliente se ele deseja receber o pedido em casa ou se prefere retirar no balcão.
|
||||||
|
10.1 Se o cliente escolher entrega, pergunte qual o endereço de entrega. O endereço deverá conter Rua, Número, Bairro e CEP.
|
||||||
|
10.2 Os CEPs de 12.220-000 até 12.330-000 possuem uma taxa de entrega de R$ 10,00.
|
||||||
|
10.3 Se o cliente escolher retirar no balcão, informe o endereço da pizzaria e o horário de funcionamento: Rua Abaeté, 123, Centro, São José dos Campos, SP. Horário de funcionamento: 18h às 23h.
|
||||||
|
11. Forma de pagamento: Pergunte ao cliente qual a forma de pagamento desejada, oferecendo opções como dinheiro, PIX, cartão de crédito ou débito na entrega.
|
||||||
|
11.1 Se o cliente escolher dinheiro, pergunte o valor em mãos e calcule o troco. O valor informado não pode ser menor que o valor total do pedido.
|
||||||
|
11.2 Se o cliente escolher PIX, forneça a chave PIX CNPJ: 1234
|
||||||
|
11.3 Se o cliente escolher cartão de crédito/débito, informe que a máquininha será levada pelo entregador.
|
||||||
|
12. Mais alguma coisa? Pergunte ao cliente se ele deseja pedir mais alguma coisa.
|
||||||
|
12.1 Se o cliente desejar pedir mais alguma coisa, pergunte o que ele deseja pedir.
|
||||||
|
12.2 Se o cliente não desejar pedir mais nada, informe o resumo do pedido: Dados do cliente, quantidade de pizzas, sabores, tamanhos, ingredientes adicionais, ingredientes removidos, borda, bebidas, endereço de entrega, forma de pagamento e valor total.
|
||||||
|
12.3 Confirmação do pedido: Pergunte ao cliente se o pedido está correto.
|
||||||
|
12.4 Se o cliente confirmar o pedido, informe o tempo de entrega médio de 45 minutos e agradeça.
|
||||||
|
12.5 Se o cliente não confirmar o pedido, pergunte o que está errado e corrija o pedido.
|
||||||
|
13. Despedida: Agradeça o cliente por entrar em contato. É muito importante que se despeça informando o número do pedido.
|
||||||
|
|
||||||
|
Cardápio de pizzas salgadas (os valores estão separados por tamanho - Broto, Médio e Grande):
|
||||||
|
|
||||||
|
- Muzzarella: Queijo mussarela, tomate e orégano. R$ 25,00 / R$ 30,00 / R$ 35,00
|
||||||
|
- Calabresa: Calabresa, cebola e orégano. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
- Nordestina: Carne de sol, cebola e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Frango: Frango desfiado, milho e orégano. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
- Frango c/ Catupiry: Frango desfiado, catupiry e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- A moda da Casa: Carne de sol, bacon, cebola e orégano. R$ 40,00 / R$ 45,00 / R$ 50,00
|
||||||
|
- Presunto: Presunto, queijo mussarela e orégano. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
- Quatro Estações: Presunto, queijo mussarela, ervilha, milho, palmito e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Mista: Presunto, queijo mussarela, calabresa, cebola e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Toscana: Calabresa, bacon, cebola e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Portuguesa: Presunto, queijo mussarela, calabresa, ovo, cebola e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Dois Queijos: Queijo mussarela, catupiry e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Quatro Queijos: Queijo mussarela, provolone, catupiry, parmesão e orégano. R$ 40,00 / R$ 45,00 / R$ 50,00
|
||||||
|
- Salame: Salame, queijo mussarela e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
- Atum: Atum, cebola e orégano. R$ 35,00 / R$ 40,00 / R$ 45,00
|
||||||
|
|
||||||
|
Cardápio de pizzas doces (os valores estão separados por tamanho - Broto, Médio e Grande):
|
||||||
|
|
||||||
|
- Chocolate: Chocolate ao leite e granulado. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
- Romeu e Julieta: Goiabada e queijo mussarela. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
- California: Banana, canela e açúcar. R$ 30,00 / R$ 35,00 / R$ 40,00
|
||||||
|
|
||||||
|
Extras/Adicionais (os valores estão separados por tamanho - Broto, Médio e Grande):
|
||||||
|
|
||||||
|
- Catupiry: R$ 5,00 / R$ 7,00 / R$ 9,00
|
||||||
|
|
||||||
|
Bordas (os valores estão separados por tamanho - Broto, Médio e Grande):
|
||||||
|
|
||||||
|
- Chocolate: R$ 5,00 / R$ 7,00 / R$ 9,00
|
||||||
|
- Cheddar: R$ 5,00 / R$ 7,00 / R$ 9,00
|
||||||
|
- Catupiry: R$ 5,00 / R$ 7,00 / R$ 9,00
|
||||||
|
|
||||||
|
Bebidas:
|
||||||
|
|
||||||
|
- Coca-Cola 2L: R$ 10,00
|
||||||
|
- Coca-Cola Lata: R$ 8,00
|
||||||
|
- Guaraná 2L: R$ 10,00
|
||||||
|
- Guaraná Lata: R$ 7,00
|
||||||
|
- Água com Gás 500 ml: R$ 5,00
|
||||||
|
- Água sem Gás 500 ml: R$ 4,00
|
||||||
|
`
|
13
src/utils/initPrompt.ts
Normal file
13
src/utils/initPrompt.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { promptPizza } from "../prompts/pizzaAgent"
|
||||||
|
|
||||||
|
export function initPrompt(storeName: string, orderCode: string, prompt?: string ): string {
|
||||||
|
if(prompt){
|
||||||
|
return prompt
|
||||||
|
.replace(/{{[\s]?storeName[\s]?}}/g, storeName)
|
||||||
|
.replace(/{{[\s]?orderCode[\s]?}}/g, orderCode)
|
||||||
|
}else{
|
||||||
|
return promptPizza
|
||||||
|
.replace(/{{[\s]?storeName[\s]?}}/g, storeName)
|
||||||
|
.replace(/{{[\s]?orderCode[\s]?}}/g, orderCode)
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,10 @@ export async function useMultiFileAuthStateDb(
|
|||||||
const client = dbserver.getClient();
|
const client = dbserver.getClient();
|
||||||
|
|
||||||
const collection = client
|
const collection = client
|
||||||
.db(configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME + '-instances')
|
.db(
|
||||||
|
configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME +
|
||||||
|
configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_FINAL_NAME
|
||||||
|
)
|
||||||
.collection(coll);
|
.collection(coll);
|
||||||
|
|
||||||
const writeData = async (data: any, key: string): Promise<any> => {
|
const writeData = async (data: any, key: string): Promise<any> => {
|
||||||
@ -33,6 +36,7 @@ export async function useMultiFileAuthStateDb(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return await collection.replaceOne({ _id: key }, msgParsed, {
|
return await collection.replaceOne({ _id: key }, msgParsed, {
|
||||||
|
//return await collection.replaceOne({ _id: key }, JSON.parse(JSON.stringify(data, BufferJSON.replacer)), {
|
||||||
upsert: true,
|
upsert: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -47,6 +51,7 @@ export async function useMultiFileAuthStateDb(
|
|||||||
if (data?.content_array) {
|
if (data?.content_array) {
|
||||||
data = data.content_array;
|
data = data.content_array;
|
||||||
}
|
}
|
||||||
|
//const data = await collection.findOne({ _id: key });
|
||||||
const creds = JSON.stringify(data);
|
const creds = JSON.stringify(data);
|
||||||
return JSON.parse(creds, BufferJSON.reviver);
|
return JSON.parse(creds, BufferJSON.reviver);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -987,6 +987,51 @@ export const rabbitmqSchema: JSONSchema7 = {
|
|||||||
...isNotEmpty('enabled'),
|
...isNotEmpty('enabled'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const openaiSchema: JSONSchema7 = {
|
||||||
|
$id: v4(),
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
chave: { type: 'string' },
|
||||||
|
enabled: { type: 'boolean', enum: [true, false] },
|
||||||
|
events: {
|
||||||
|
type: 'array',
|
||||||
|
minItems: 0,
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
enum: [
|
||||||
|
'APPLICATION_STARTUP',
|
||||||
|
'QRCODE_UPDATED',
|
||||||
|
'MESSAGES_SET',
|
||||||
|
'MESSAGES_UPSERT',
|
||||||
|
'MESSAGES_UPDATE',
|
||||||
|
'MESSAGES_DELETE',
|
||||||
|
'SEND_MESSAGE',
|
||||||
|
'CONTACTS_SET',
|
||||||
|
'CONTACTS_UPSERT',
|
||||||
|
'CONTACTS_UPDATE',
|
||||||
|
'PRESENCE_UPDATE',
|
||||||
|
'CHATS_SET',
|
||||||
|
'CHATS_UPSERT',
|
||||||
|
'CHATS_UPDATE',
|
||||||
|
'CHATS_DELETE',
|
||||||
|
'GROUPS_UPSERT',
|
||||||
|
'GROUP_UPDATE',
|
||||||
|
'GROUP_PARTICIPANTS_UPDATE',
|
||||||
|
'CONNECTION_UPDATE',
|
||||||
|
'CALL',
|
||||||
|
'NEW_JWT_TOKEN',
|
||||||
|
'TYPEBOT_START',
|
||||||
|
'TYPEBOT_CHANGE_STATUS',
|
||||||
|
'CHAMA_AI_ACTION',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['enabled'],
|
||||||
|
...isNotEmpty('enabled'),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export const sqsSchema: JSONSchema7 = {
|
export const sqsSchema: JSONSchema7 = {
|
||||||
$id: v4(),
|
$id: v4(),
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@ -72,6 +72,7 @@ export class ChatwootController {
|
|||||||
token: '',
|
token: '',
|
||||||
sign_msg: false,
|
sign_msg: false,
|
||||||
name_inbox: '',
|
name_inbox: '',
|
||||||
|
id_inbox: '',
|
||||||
webhook_url: '',
|
webhook_url: '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -86,6 +87,7 @@ export class ChatwootController {
|
|||||||
|
|
||||||
public async receiveWebhook(instance: InstanceDto, data: any) {
|
public async receiveWebhook(instance: InstanceDto, data: any) {
|
||||||
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
|
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
|
||||||
|
|
||||||
const chatwootService = new ChatwootService(waMonitor, this.configService);
|
const chatwootService = new ChatwootService(waMonitor, this.configService);
|
||||||
|
|
||||||
return chatwootService.receiveWebhook(instance, data);
|
return chatwootService.receiveWebhook(instance, data);
|
||||||
|
@ -13,6 +13,7 @@ import { ChatwootService } from '../services/chatwoot.service';
|
|||||||
import { WAMonitoringService } from '../services/monitor.service';
|
import { WAMonitoringService } from '../services/monitor.service';
|
||||||
import { ProxyService } from '../services/proxy.service';
|
import { ProxyService } from '../services/proxy.service';
|
||||||
import { RabbitmqService } from '../services/rabbitmq.service';
|
import { RabbitmqService } from '../services/rabbitmq.service';
|
||||||
|
import { OpenaiService } from '../services/openai.service';
|
||||||
import { SettingsService } from '../services/settings.service';
|
import { SettingsService } from '../services/settings.service';
|
||||||
import { SqsService } from '../services/sqs.service';
|
import { SqsService } from '../services/sqs.service';
|
||||||
import { TypebotService } from '../services/typebot.service';
|
import { TypebotService } from '../services/typebot.service';
|
||||||
@ -33,6 +34,7 @@ export class InstanceController {
|
|||||||
private readonly settingsService: SettingsService,
|
private readonly settingsService: SettingsService,
|
||||||
private readonly websocketService: WebsocketService,
|
private readonly websocketService: WebsocketService,
|
||||||
private readonly rabbitmqService: RabbitmqService,
|
private readonly rabbitmqService: RabbitmqService,
|
||||||
|
private readonly openaiService: OpenaiService,
|
||||||
private readonly proxyService: ProxyService,
|
private readonly proxyService: ProxyService,
|
||||||
private readonly sqsService: SqsService,
|
private readonly sqsService: SqsService,
|
||||||
private readonly typebotService: TypebotService,
|
private readonly typebotService: TypebotService,
|
||||||
@ -66,8 +68,14 @@ export class InstanceController {
|
|||||||
websocket_events,
|
websocket_events,
|
||||||
rabbitmq_enabled,
|
rabbitmq_enabled,
|
||||||
rabbitmq_events,
|
rabbitmq_events,
|
||||||
|
|
||||||
|
openai_chave,
|
||||||
|
openai_enabled,
|
||||||
|
openai_events,
|
||||||
|
|
||||||
sqs_enabled,
|
sqs_enabled,
|
||||||
sqs_events,
|
sqs_events,
|
||||||
|
|
||||||
typebot_url,
|
typebot_url,
|
||||||
typebot,
|
typebot,
|
||||||
typebot_expire,
|
typebot_expire,
|
||||||
@ -81,6 +89,7 @@ export class InstanceController {
|
|||||||
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
|
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
|
||||||
|
|
||||||
this.logger.verbose('checking duplicate token');
|
this.logger.verbose('checking duplicate token');
|
||||||
|
|
||||||
await this.authService.checkDuplicateToken(token);
|
await this.authService.checkDuplicateToken(token);
|
||||||
|
|
||||||
this.logger.verbose('creating instance');
|
this.logger.verbose('creating instance');
|
||||||
@ -250,6 +259,56 @@ export class InstanceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let openaiEvents: string[];
|
||||||
|
|
||||||
|
if (openai_enabled) {
|
||||||
|
this.logger.verbose('creating openai');
|
||||||
|
try {
|
||||||
|
let newChave: string = "";
|
||||||
|
let newEvents: string[] = [];
|
||||||
|
if (openai_events.length === 0) {
|
||||||
|
newEvents = [
|
||||||
|
'APPLICATION_STARTUP',
|
||||||
|
'QRCODE_UPDATED',
|
||||||
|
'MESSAGES_SET',
|
||||||
|
'MESSAGES_UPSERT',
|
||||||
|
'MESSAGES_UPDATE',
|
||||||
|
'MESSAGES_DELETE',
|
||||||
|
'SEND_MESSAGE',
|
||||||
|
'CONTACTS_SET',
|
||||||
|
'CONTACTS_UPSERT',
|
||||||
|
'CONTACTS_UPDATE',
|
||||||
|
'PRESENCE_UPDATE',
|
||||||
|
'CHATS_SET',
|
||||||
|
'CHATS_UPSERT',
|
||||||
|
'CHATS_UPDATE',
|
||||||
|
'CHATS_DELETE',
|
||||||
|
'GROUPS_UPSERT',
|
||||||
|
'GROUP_UPDATE',
|
||||||
|
'GROUP_PARTICIPANTS_UPDATE',
|
||||||
|
'CONNECTION_UPDATE',
|
||||||
|
'CALL',
|
||||||
|
'NEW_JWT_TOKEN',
|
||||||
|
'TYPEBOT_START',
|
||||||
|
'TYPEBOT_CHANGE_STATUS',
|
||||||
|
'CHAMA_AI_ACTION',
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
newEvents = openai_events;
|
||||||
|
}
|
||||||
|
this.openaiService.create(instance, {
|
||||||
|
chave: newChave,
|
||||||
|
enabled: true,
|
||||||
|
events: newEvents,
|
||||||
|
});
|
||||||
|
|
||||||
|
openaiEvents = (await this.openaiService.find(instance)).events;
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (proxy) {
|
if (proxy) {
|
||||||
this.logger.verbose('creating proxy');
|
this.logger.verbose('creating proxy');
|
||||||
try {
|
try {
|
||||||
@ -266,6 +325,7 @@ export class InstanceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let sqsEvents: string[];
|
let sqsEvents: string[];
|
||||||
|
|
||||||
if (sqs_enabled) {
|
if (sqs_enabled) {
|
||||||
@ -380,6 +440,11 @@ export class InstanceController {
|
|||||||
enabled: rabbitmq_enabled,
|
enabled: rabbitmq_enabled,
|
||||||
events: rabbitmqEvents,
|
events: rabbitmqEvents,
|
||||||
},
|
},
|
||||||
|
openai: {
|
||||||
|
chave: openai_chave,
|
||||||
|
enabled: openai_enabled,
|
||||||
|
events: openaiEvents,
|
||||||
|
},
|
||||||
sqs: {
|
sqs: {
|
||||||
enabled: sqs_enabled,
|
enabled: sqs_enabled,
|
||||||
events: sqsEvents,
|
events: sqsEvents,
|
||||||
@ -396,7 +461,6 @@ export class InstanceController {
|
|||||||
},
|
},
|
||||||
settings,
|
settings,
|
||||||
qrcode: getQrcode,
|
qrcode: getQrcode,
|
||||||
proxy,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.logger.verbose('instance created');
|
this.logger.verbose('instance created');
|
||||||
@ -479,6 +543,11 @@ export class InstanceController {
|
|||||||
enabled: rabbitmq_enabled,
|
enabled: rabbitmq_enabled,
|
||||||
events: rabbitmqEvents,
|
events: rabbitmqEvents,
|
||||||
},
|
},
|
||||||
|
openai: {
|
||||||
|
chave: openai_chave,
|
||||||
|
enabled: openai_enabled,
|
||||||
|
events: openaiEvents,
|
||||||
|
},
|
||||||
sqs: {
|
sqs: {
|
||||||
enabled: sqs_enabled,
|
enabled: sqs_enabled,
|
||||||
events: sqsEvents,
|
events: sqsEvents,
|
||||||
@ -506,7 +575,6 @@ export class InstanceController {
|
|||||||
name_inbox: instance.instanceName,
|
name_inbox: instance.instanceName,
|
||||||
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
|
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
|
||||||
},
|
},
|
||||||
proxy,
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error.message[0]);
|
this.logger.error(error.message[0]);
|
||||||
@ -514,6 +582,23 @@ export class InstanceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async qrInstance({ instanceName }: InstanceDto) {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('requested qrInstance from ' + instanceName + ' instance');
|
||||||
|
|
||||||
|
this.logger.verbose('logging out instance: ' + instanceName);
|
||||||
|
///this.waMonitor.waInstances[instanceName]?.client?.ws?.close();
|
||||||
|
|
||||||
|
const qrcode = await this.waMonitor.waInstances[instanceName]?.instance.qrcode;
|
||||||
|
return qrcode.base64;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(error);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) {
|
public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) {
|
||||||
try {
|
try {
|
||||||
this.logger.verbose('requested connectToWhatsapp from ' + instanceName + ' instance');
|
this.logger.verbose('requested connectToWhatsapp from ' + instanceName + ' instance');
|
||||||
@ -628,18 +713,21 @@ export class InstanceController {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.waMonitor.waInstances[instanceName]?.removeRabbitmqQueues();
|
this.waMonitor.waInstances[instanceName]?.removeRabbitmqQueues();
|
||||||
|
this.waMonitor.waInstances[instanceName]?.removeOpenaiQueues();
|
||||||
|
|
||||||
if (instance.state === 'connecting') {
|
if (instance.state === 'connecting') {
|
||||||
this.logger.verbose('logging out instance: ' + instanceName);
|
this.logger.verbose('logging out instance: ' + instanceName);
|
||||||
|
|
||||||
await this.logout({ instanceName });
|
await this.logout({ instanceName });
|
||||||
|
delete this.waMonitor.waInstances[instanceName];
|
||||||
|
return { status: 'SUCCESS', error: false, response: { message: 'Instance deleted' } };
|
||||||
|
} else {
|
||||||
|
this.logger.verbose('deleting instance: ' + instanceName);
|
||||||
|
|
||||||
|
delete this.waMonitor.waInstances[instanceName];
|
||||||
|
this.eventEmitter.emit('remove.instance', instanceName, 'inner');
|
||||||
|
return { status: 'SUCCESS', error: false, response: { message: 'Instance deleted' } };
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('deleting instance: ' + instanceName);
|
|
||||||
|
|
||||||
delete this.waMonitor.waInstances[instanceName];
|
|
||||||
this.eventEmitter.emit('remove.instance', instanceName, 'inner');
|
|
||||||
return { status: 'SUCCESS', error: false, response: { message: 'Instance deleted' } };
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new BadRequestException(error.toString());
|
throw new BadRequestException(error.toString());
|
||||||
}
|
}
|
||||||
|
85
src/whatsapp/controllers/openai.controller.ts
Normal file
85
src/whatsapp/controllers/openai.controller.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { Logger } from '../../config/logger.config';
|
||||||
|
import { InstanceDto } from '../dto/instance.dto';
|
||||||
|
import { OpenaiDto } from '../dto/openai.dto';
|
||||||
|
import { ContactOpenaiDto } from '../dto/contactopenai.dto';
|
||||||
|
import { OpenaiService } from '../services/openai.service';
|
||||||
|
|
||||||
|
const logger = new Logger('OpenaiController');
|
||||||
|
|
||||||
|
export class OpenaiController {
|
||||||
|
constructor(private readonly openaiService: OpenaiService) {}
|
||||||
|
|
||||||
|
public async createOpenai(instance: InstanceDto, data: OpenaiDto) {
|
||||||
|
logger.verbose('requested createOpenai from ' + instance.instanceName + ' instance');
|
||||||
|
|
||||||
|
if (!data.chave) {
|
||||||
|
logger.verbose('openai sem chave');
|
||||||
|
data.chave = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.enabled) {
|
||||||
|
logger.verbose('openai disabled');
|
||||||
|
data.events = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.events?.length === 0) {
|
||||||
|
logger.verbose('openai events empty');
|
||||||
|
data.events = [
|
||||||
|
'APPLICATION_STARTUP',
|
||||||
|
'QRCODE_UPDATED',
|
||||||
|
'MESSAGES_SET',
|
||||||
|
'MESSAGES_UPSERT',
|
||||||
|
'MESSAGES_UPDATE',
|
||||||
|
'MESSAGES_DELETE',
|
||||||
|
'SEND_MESSAGE',
|
||||||
|
'CONTACTS_SET',
|
||||||
|
'CONTACTS_UPSERT',
|
||||||
|
'CONTACTS_UPDATE',
|
||||||
|
'PRESENCE_UPDATE',
|
||||||
|
'CHATS_SET',
|
||||||
|
'CHATS_UPSERT',
|
||||||
|
'CHATS_UPDATE',
|
||||||
|
'CHATS_DELETE',
|
||||||
|
'GROUPS_UPSERT',
|
||||||
|
'GROUP_UPDATE',
|
||||||
|
'GROUP_PARTICIPANTS_UPDATE',
|
||||||
|
'CONNECTION_UPDATE',
|
||||||
|
'CALL',
|
||||||
|
'NEW_JWT_TOKEN',
|
||||||
|
'TYPEBOT_START',
|
||||||
|
'TYPEBOT_CHANGE_STATUS',
|
||||||
|
'CHAMA_AI_ACTION',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.openaiService.create(instance, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findOpenai(instance: InstanceDto) {
|
||||||
|
logger.verbose('requested findOpenai from ' + instance.instanceName + ' instance');
|
||||||
|
return this.openaiService.find(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async createContactOpenai(instance: InstanceDto, data: ContactOpenaiDto) {
|
||||||
|
logger.verbose('requested createOpenai from ' + instance.instanceName + ' instance');
|
||||||
|
|
||||||
|
if (!data.contact) {
|
||||||
|
logger.verbose('openai sem chave');
|
||||||
|
data.contact = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.enabled) {
|
||||||
|
logger.verbose('openai disabled');
|
||||||
|
data.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.owner = instance.instanceName;
|
||||||
|
|
||||||
|
return this.openaiService.createContact(instance, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findContactOpenai(instance: InstanceDto) {
|
||||||
|
logger.verbose('requested findOpenai from ' + instance.instanceName + ' instance');
|
||||||
|
return this.openaiService.findContact(instance);
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { SqsService } from '../services/sqs.service';
|
|||||||
const logger = new Logger('SqsController');
|
const logger = new Logger('SqsController');
|
||||||
|
|
||||||
export class SqsController {
|
export class SqsController {
|
||||||
constructor(private readonly sqsService: SqsService) {}
|
constructor(private readonly sqsService: SqsService) { }
|
||||||
|
|
||||||
public async createSqs(instance: InstanceDto, data: SqsDto) {
|
public async createSqs(instance: InstanceDto, data: SqsDto) {
|
||||||
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');
|
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');
|
||||||
@ -53,4 +53,4 @@ export class SqsController {
|
|||||||
logger.verbose('requested findSqs from ' + instance.instanceName + ' instance');
|
logger.verbose('requested findSqs from ' + instance.instanceName + ' instance');
|
||||||
return this.sqsService.find(instance);
|
return this.sqsService.find(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ export class ChatwootDto {
|
|||||||
token?: string;
|
token?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
name_inbox?: string;
|
name_inbox?: string;
|
||||||
|
id_inbox?: string;
|
||||||
sign_msg?: boolean;
|
sign_msg?: boolean;
|
||||||
number?: string;
|
number?: string;
|
||||||
reopen_conversation?: boolean;
|
reopen_conversation?: boolean;
|
||||||
|
5
src/whatsapp/dto/contactopenai.dto.ts
Normal file
5
src/whatsapp/dto/contactopenai.dto.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export class ContactOpenaiDto {
|
||||||
|
contact?: string;
|
||||||
|
enabled: boolean;
|
||||||
|
owner: string;
|
||||||
|
}
|
@ -23,8 +23,15 @@ export class InstanceDto {
|
|||||||
websocket_events?: string[];
|
websocket_events?: string[];
|
||||||
rabbitmq_enabled?: boolean;
|
rabbitmq_enabled?: boolean;
|
||||||
rabbitmq_events?: string[];
|
rabbitmq_events?: string[];
|
||||||
|
|
||||||
|
openai_chave?: boolean;
|
||||||
|
openai_prompts?: string;
|
||||||
|
openai_enabled?: boolean;
|
||||||
|
openai_events?: string[];
|
||||||
|
|
||||||
sqs_enabled?: boolean;
|
sqs_enabled?: boolean;
|
||||||
sqs_events?: string[];
|
sqs_events?: string[];
|
||||||
|
|
||||||
typebot_url?: string;
|
typebot_url?: string;
|
||||||
typebot?: string;
|
typebot?: string;
|
||||||
typebot_expire?: number;
|
typebot_expire?: number;
|
||||||
@ -32,5 +39,6 @@ export class InstanceDto {
|
|||||||
typebot_delay_message?: number;
|
typebot_delay_message?: number;
|
||||||
typebot_unknown_message?: string;
|
typebot_unknown_message?: string;
|
||||||
typebot_listening_from_me?: boolean;
|
typebot_listening_from_me?: boolean;
|
||||||
|
proxy_enabled?: boolean;
|
||||||
proxy?: string;
|
proxy?: string;
|
||||||
}
|
}
|
||||||
|
6
src/whatsapp/dto/openai.dto.ts
Normal file
6
src/whatsapp/dto/openai.dto.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export class OpenaiDto {
|
||||||
|
chave?: string;
|
||||||
|
enabled: boolean;
|
||||||
|
prompts?: string;
|
||||||
|
events?: string[];
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export class SqsDto {
|
export class SqsDto {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
events?: string[];
|
events?: string[];
|
||||||
}
|
}
|
@ -29,7 +29,9 @@ async function getInstance(instanceName: string) {
|
|||||||
if (db.ENABLED) {
|
if (db.ENABLED) {
|
||||||
const collection = dbserver
|
const collection = dbserver
|
||||||
.getClient()
|
.getClient()
|
||||||
.db(db.CONNECTION.DB_PREFIX_NAME + '-instances')
|
.db(
|
||||||
|
db.CONNECTION.DB_PREFIX_NAME +
|
||||||
|
db.CONNECTION.DB_PREFIX_FINAL_NAME)
|
||||||
.collection(instanceName);
|
.collection(instanceName);
|
||||||
return exists || (await collection.find({}).toArray()).length > 0;
|
return exists || (await collection.find({}).toArray()).length > 0;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ export class ChatwootRaw {
|
|||||||
token?: string;
|
token?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
name_inbox?: string;
|
name_inbox?: string;
|
||||||
|
id_inbox?: string;
|
||||||
sign_msg?: boolean;
|
sign_msg?: boolean;
|
||||||
number?: string;
|
number?: string;
|
||||||
reopen_conversation?: boolean;
|
reopen_conversation?: boolean;
|
||||||
@ -22,6 +23,7 @@ const chatwootSchema = new Schema<ChatwootRaw>({
|
|||||||
token: { type: String, required: true },
|
token: { type: String, required: true },
|
||||||
url: { type: String, required: true },
|
url: { type: String, required: true },
|
||||||
name_inbox: { type: String, required: true },
|
name_inbox: { type: String, required: true },
|
||||||
|
id_inbox: { type: String, required: true },
|
||||||
sign_msg: { type: Boolean, required: true },
|
sign_msg: { type: Boolean, required: true },
|
||||||
number: { type: String, required: true },
|
number: { type: String, required: true },
|
||||||
reopen_conversation: { type: Boolean, required: true },
|
reopen_conversation: { type: Boolean, required: true },
|
||||||
|
20
src/whatsapp/models/contactOpenai.model.ts
Normal file
20
src/whatsapp/models/contactOpenai.model.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Schema } from 'mongoose';
|
||||||
|
|
||||||
|
import { dbserver } from '../../libs/db.connect';
|
||||||
|
|
||||||
|
export class ContactOpenaiRaw {
|
||||||
|
_id?: string;
|
||||||
|
contact?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
owner: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactOpenaiSchema = new Schema<ContactOpenaiRaw>({
|
||||||
|
_id: { type: String, _id: true },
|
||||||
|
contact: { type: String, required: true, minlength: 1 },
|
||||||
|
enabled: { type: Boolean, required: true },
|
||||||
|
owner: { type: String, required: true, minlength: 1 },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ContactOpenaiModel = dbserver?.model(ContactOpenaiRaw.name, contactOpenaiSchema, 'openai_contacts');
|
||||||
|
export type IContactOpenaiModel = typeof ContactOpenaiModel;
|
@ -11,3 +11,5 @@ export * from './sqs.model';
|
|||||||
export * from './typebot.model';
|
export * from './typebot.model';
|
||||||
export * from './webhook.model';
|
export * from './webhook.model';
|
||||||
export * from './websocket.model';
|
export * from './websocket.model';
|
||||||
|
export * from './openai.model';
|
||||||
|
export * from './contactOpenai.model';
|
||||||
|
22
src/whatsapp/models/openai.model.ts
Normal file
22
src/whatsapp/models/openai.model.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Schema } from 'mongoose';
|
||||||
|
|
||||||
|
import { dbserver } from '../../libs/db.connect';
|
||||||
|
|
||||||
|
export class OpenaiRaw {
|
||||||
|
_id?: string;
|
||||||
|
chave?: string;
|
||||||
|
prompts?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
events?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const openaiSchema = new Schema<OpenaiRaw>({
|
||||||
|
_id: { type: String, _id: true },
|
||||||
|
chave: { type: String, required: true },
|
||||||
|
prompts: { type: String, required: false },
|
||||||
|
enabled: { type: Boolean, required: true },
|
||||||
|
events: { type: [String], required: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const OpenaiModel = dbserver?.model(OpenaiRaw.name, openaiSchema, 'openai');
|
||||||
|
export type IOpenaiModel = typeof OpenaiModel;
|
@ -15,4 +15,4 @@ const sqsSchema = new Schema<SqsRaw>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
|
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
|
||||||
export type ISqsModel = typeof SqsModel;
|
export type ISqsModel = typeof SqsModel;
|
153
src/whatsapp/repository/openai.repository.ts
Normal file
153
src/whatsapp/repository/openai.repository.ts
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { ConfigService } from '../../config/env.config';
|
||||||
|
import { Logger } from '../../config/logger.config';
|
||||||
|
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||||
|
import { IContactOpenaiModel, ContactOpenaiRaw, IOpenaiModel, OpenaiRaw } from '../models';
|
||||||
|
|
||||||
|
export class OpenaiRepository extends Repository {
|
||||||
|
constructor(
|
||||||
|
private readonly openaiModel: IOpenaiModel,
|
||||||
|
private readonly contactopenaiModel: IContactOpenaiModel,
|
||||||
|
private readonly configService: ConfigService
|
||||||
|
) {
|
||||||
|
super(configService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly logger = new Logger('OpenaiRepository');
|
||||||
|
|
||||||
|
public async create(data: OpenaiRaw, instance: string): Promise<IInsert> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('creating openai');
|
||||||
|
if (this.dbSettings.ENABLED) {
|
||||||
|
this.logger.verbose('saving openai to db');
|
||||||
|
const insert = await this.openaiModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
|
||||||
|
|
||||||
|
this.logger.verbose('openai saved to db: ' + insert.modifiedCount + ' openai');
|
||||||
|
return { insertCount: insert.modifiedCount };
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('saving openai to store');
|
||||||
|
|
||||||
|
this.writeStore<OpenaiRaw>({
|
||||||
|
path: join(this.storePath, 'openai'),
|
||||||
|
fileName: instance,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.verbose('openai saved to store in path: ' + join(this.storePath, 'openai') + '/' + instance);
|
||||||
|
|
||||||
|
this.logger.verbose('openai created');
|
||||||
|
return { insertCount: 1 };
|
||||||
|
} catch (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async createContact(data: ContactOpenaiRaw, instance: string): Promise<IInsert> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('creating contact openai');
|
||||||
|
if (this.dbSettings.ENABLED) {
|
||||||
|
this.logger.verbose('saving openai to db');
|
||||||
|
var resultado = await this.openaiModel.findOne({ owner: instance, contact: data.contact });
|
||||||
|
if(!resultado){
|
||||||
|
const insert = await this.contactopenaiModel.insertMany({ ...data });
|
||||||
|
|
||||||
|
this.logger.verbose('openai saved to db: ' + insert.length + ' openai_contacts');
|
||||||
|
return { insertCount: insert.length };
|
||||||
|
|
||||||
|
}else{
|
||||||
|
const contacts = []
|
||||||
|
contacts[0] = {
|
||||||
|
updateOne: {
|
||||||
|
filter: { owner: data.owner, contact: data.contact },
|
||||||
|
update: { ...data },
|
||||||
|
upsert: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { nModified } = await this.contactopenaiModel.bulkWrite(contacts);
|
||||||
|
|
||||||
|
this.logger.verbose('contacts updated in db: ' + nModified + ' contacts');
|
||||||
|
return { insertCount: nModified };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('saving openai to store');
|
||||||
|
|
||||||
|
this.writeStore<OpenaiRaw>({
|
||||||
|
path: join(this.storePath, 'openai_contact'),
|
||||||
|
fileName: instance,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.verbose('openai contact saved to store in path: ' + join(this.storePath, 'openai_contact') + '/' + instance);
|
||||||
|
|
||||||
|
this.logger.verbose('openai contact created');
|
||||||
|
return { insertCount: 1 };
|
||||||
|
} catch (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async find(instance: string): Promise<OpenaiRaw> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('finding openai');
|
||||||
|
if (this.dbSettings.ENABLED) {
|
||||||
|
this.logger.verbose('finding openai in db');
|
||||||
|
return await this.openaiModel.findOne({ _id: instance });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('finding openai in store');
|
||||||
|
return JSON.parse(
|
||||||
|
readFileSync(join(this.storePath, 'openai', instance + '.json'), {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
}),
|
||||||
|
) as OpenaiRaw;
|
||||||
|
} catch (error) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findContact(instance: string, contact: string): Promise<ContactOpenaiRaw> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('finding openai');
|
||||||
|
if (this.dbSettings.ENABLED) {
|
||||||
|
this.logger.verbose('finding openai in db');
|
||||||
|
|
||||||
|
return await this.contactopenaiModel.findOne({ owner: instance,contact: contact});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('finding openai in store');
|
||||||
|
return JSON.parse(
|
||||||
|
readFileSync(join(this.storePath, 'openai_contact', instance + '.json'), {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
}),
|
||||||
|
) as ContactOpenaiRaw;
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findContactAll(instance: string): Promise<any> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('finding openai');
|
||||||
|
if (this.dbSettings.ENABLED) {
|
||||||
|
this.logger.verbose('finding openai in db');
|
||||||
|
return await this.contactopenaiModel.find({ owner: instance });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('finding openai in store');
|
||||||
|
return JSON.parse(
|
||||||
|
readFileSync(join(this.storePath, 'openai_contact', instance + '.json'), {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
}),
|
||||||
|
) as ContactOpenaiRaw;
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import { MessageRepository } from './message.repository';
|
|||||||
import { MessageUpRepository } from './messageUp.repository';
|
import { MessageUpRepository } from './messageUp.repository';
|
||||||
import { ProxyRepository } from './proxy.repository';
|
import { ProxyRepository } from './proxy.repository';
|
||||||
import { RabbitmqRepository } from './rabbitmq.repository';
|
import { RabbitmqRepository } from './rabbitmq.repository';
|
||||||
|
import { OpenaiRepository } from './openai.repository';
|
||||||
import { SettingsRepository } from './settings.repository';
|
import { SettingsRepository } from './settings.repository';
|
||||||
import { SqsRepository } from './sqs.repository';
|
import { SqsRepository } from './sqs.repository';
|
||||||
import { TypebotRepository } from './typebot.repository';
|
import { TypebotRepository } from './typebot.repository';
|
||||||
@ -29,6 +30,8 @@ export class RepositoryBroker {
|
|||||||
public readonly settings: SettingsRepository,
|
public readonly settings: SettingsRepository,
|
||||||
public readonly websocket: WebsocketRepository,
|
public readonly websocket: WebsocketRepository,
|
||||||
public readonly rabbitmq: RabbitmqRepository,
|
public readonly rabbitmq: RabbitmqRepository,
|
||||||
|
public readonly openai: OpenaiRepository,
|
||||||
|
public readonly openai_contact: OpenaiRepository,
|
||||||
public readonly sqs: SqsRepository,
|
public readonly sqs: SqsRepository,
|
||||||
public readonly typebot: TypebotRepository,
|
public readonly typebot: TypebotRepository,
|
||||||
public readonly proxy: ProxyRepository,
|
public readonly proxy: ProxyRepository,
|
||||||
@ -63,9 +66,10 @@ export class RepositoryBroker {
|
|||||||
const webhookDir = join(storePath, 'webhook');
|
const webhookDir = join(storePath, 'webhook');
|
||||||
const chatwootDir = join(storePath, 'chatwoot');
|
const chatwootDir = join(storePath, 'chatwoot');
|
||||||
const settingsDir = join(storePath, 'settings');
|
const settingsDir = join(storePath, 'settings');
|
||||||
|
const sqsDir = join(storePath, 'sqs');
|
||||||
const websocketDir = join(storePath, 'websocket');
|
const websocketDir = join(storePath, 'websocket');
|
||||||
const rabbitmqDir = join(storePath, 'rabbitmq');
|
const rabbitmqDir = join(storePath, 'rabbitmq');
|
||||||
const sqsDir = join(storePath, 'sqs');
|
const openaiDir = join(storePath, 'openai');
|
||||||
const typebotDir = join(storePath, 'typebot');
|
const typebotDir = join(storePath, 'typebot');
|
||||||
const proxyDir = join(storePath, 'proxy');
|
const proxyDir = join(storePath, 'proxy');
|
||||||
const chamaaiDir = join(storePath, 'chamaai');
|
const chamaaiDir = join(storePath, 'chamaai');
|
||||||
@ -103,6 +107,12 @@ export class RepositoryBroker {
|
|||||||
this.logger.verbose('creating settings dir: ' + settingsDir);
|
this.logger.verbose('creating settings dir: ' + settingsDir);
|
||||||
fs.mkdirSync(settingsDir, { recursive: true });
|
fs.mkdirSync(settingsDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(sqsDir)) {
|
||||||
|
this.logger.verbose('creating sqs dir: ' + sqsDir);
|
||||||
|
fs.mkdirSync(sqsDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(websocketDir)) {
|
if (!fs.existsSync(websocketDir)) {
|
||||||
this.logger.verbose('creating websocket dir: ' + websocketDir);
|
this.logger.verbose('creating websocket dir: ' + websocketDir);
|
||||||
fs.mkdirSync(websocketDir, { recursive: true });
|
fs.mkdirSync(websocketDir, { recursive: true });
|
||||||
@ -111,9 +121,9 @@ export class RepositoryBroker {
|
|||||||
this.logger.verbose('creating rabbitmq dir: ' + rabbitmqDir);
|
this.logger.verbose('creating rabbitmq dir: ' + rabbitmqDir);
|
||||||
fs.mkdirSync(rabbitmqDir, { recursive: true });
|
fs.mkdirSync(rabbitmqDir, { recursive: true });
|
||||||
}
|
}
|
||||||
if (!fs.existsSync(sqsDir)) {
|
if (!fs.existsSync(openaiDir)) {
|
||||||
this.logger.verbose('creating sqs dir: ' + sqsDir);
|
this.logger.verbose('creating openai dir: ' + openaiDir);
|
||||||
fs.mkdirSync(sqsDir, { recursive: true });
|
fs.mkdirSync(openaiDir, { recursive: true });
|
||||||
}
|
}
|
||||||
if (!fs.existsSync(typebotDir)) {
|
if (!fs.existsSync(typebotDir)) {
|
||||||
this.logger.verbose('creating typebot dir: ' + typebotDir);
|
this.logger.verbose('creating typebot dir: ' + typebotDir);
|
||||||
|
@ -59,4 +59,4 @@ export class SqsRepository extends Repository {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ import { GroupRouter } from './group.router';
|
|||||||
import { InstanceRouter } from './instance.router';
|
import { InstanceRouter } from './instance.router';
|
||||||
import { ProxyRouter } from './proxy.router';
|
import { ProxyRouter } from './proxy.router';
|
||||||
import { RabbitmqRouter } from './rabbitmq.router';
|
import { RabbitmqRouter } from './rabbitmq.router';
|
||||||
|
import { OpenaiRouter } from './openai.router';
|
||||||
import { MessageRouter } from './sendMessage.router';
|
import { MessageRouter } from './sendMessage.router';
|
||||||
import { SettingsRouter } from './settings.router';
|
import { SettingsRouter } from './settings.router';
|
||||||
import { SqsRouter } from './sqs.router';
|
import { SqsRouter } from './sqs.router';
|
||||||
@ -39,9 +40,9 @@ router
|
|||||||
.get('/', (req, res) => {
|
.get('/', (req, res) => {
|
||||||
res.status(HttpStatus.OK).json({
|
res.status(HttpStatus.OK).json({
|
||||||
status: HttpStatus.OK,
|
status: HttpStatus.OK,
|
||||||
message: 'Welcome to the Evolution API, it is working!',
|
message: 'Api',
|
||||||
version: packageJson.version,
|
// version: packageJson.version,
|
||||||
documentation: `${req.protocol}://${req.get('host')}/docs`,
|
// documentation: `${req.protocol}://${req.get('host')}/docs`,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
||||||
@ -54,7 +55,7 @@ router
|
|||||||
.use('/settings', new SettingsRouter(...guards).router)
|
.use('/settings', new SettingsRouter(...guards).router)
|
||||||
.use('/websocket', new WebsocketRouter(...guards).router)
|
.use('/websocket', new WebsocketRouter(...guards).router)
|
||||||
.use('/rabbitmq', new RabbitmqRouter(...guards).router)
|
.use('/rabbitmq', new RabbitmqRouter(...guards).router)
|
||||||
.use('/sqs', new SqsRouter(...guards).router)
|
.use('/openai', new OpenaiRouter(...guards).router)
|
||||||
.use('/typebot', new TypebotRouter(...guards).router)
|
.use('/typebot', new TypebotRouter(...guards).router)
|
||||||
.use('/proxy', new ProxyRouter(...guards).router)
|
.use('/proxy', new ProxyRouter(...guards).router)
|
||||||
.use('/chamaai', new ChamaaiRouter(...guards).router);
|
.use('/chamaai', new ChamaaiRouter(...guards).router);
|
||||||
|
@ -32,7 +32,15 @@ export class InstanceRouter extends RouterBroker {
|
|||||||
execute: (instance) => instanceController.createInstance(instance),
|
execute: (instance) => instanceController.createInstance(instance),
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
|
||||||
|
if (req.query['qrcode']) {
|
||||||
|
return res.status(HttpStatus.OK).render('qrcode', {
|
||||||
|
qrcode: response.qrcode.base64,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
|
}
|
||||||
|
//return res.status(HttpStatus.CREATED).json(response);
|
||||||
})
|
})
|
||||||
.put(this.routerPath('restart'), ...guards, async (req, res) => {
|
.put(this.routerPath('restart'), ...guards, async (req, res) => {
|
||||||
logger.verbose('request received in restartInstance');
|
logger.verbose('request received in restartInstance');
|
||||||
@ -50,6 +58,22 @@ export class InstanceRouter extends RouterBroker {
|
|||||||
|
|
||||||
return res.status(HttpStatus.OK).json(response);
|
return res.status(HttpStatus.OK).json(response);
|
||||||
})
|
})
|
||||||
|
.get(this.routerPath('qr'), ...guards, async (req, res) => {
|
||||||
|
logger.verbose('request received in get qrCode');
|
||||||
|
|
||||||
|
logger.verbose('request query: ');
|
||||||
|
logger.verbose(req.query);
|
||||||
|
const response = await this.dataValidate<InstanceDto>({
|
||||||
|
request: req,
|
||||||
|
schema: instanceNameSchema,
|
||||||
|
ClassRef: InstanceDto,
|
||||||
|
execute: (instance) => instanceController.qrInstance(instance),
|
||||||
|
});
|
||||||
|
return res.status(HttpStatus.OK).render('qrcode', {
|
||||||
|
qrcode: response,
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
.get(this.routerPath('connect'), ...guards, async (req, res) => {
|
.get(this.routerPath('connect'), ...guards, async (req, res) => {
|
||||||
logger.verbose('request received in connectInstance');
|
logger.verbose('request received in connectInstance');
|
||||||
logger.verbose('request body: ');
|
logger.verbose('request body: ');
|
||||||
|
86
src/whatsapp/routers/openai.router.ts
Normal file
86
src/whatsapp/routers/openai.router.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { RequestHandler, Router } from 'express';
|
||||||
|
|
||||||
|
import { Logger } from '../../config/logger.config';
|
||||||
|
import { instanceNameSchema, openaiSchema } from '../../validate/validate.schema';
|
||||||
|
import { RouterBroker } from '../abstract/abstract.router';
|
||||||
|
import { InstanceDto } from '../dto/instance.dto';
|
||||||
|
import { OpenaiDto } from '../dto/openai.dto';
|
||||||
|
import { ContactOpenaiDto } from '../dto/contactopenai.dto';
|
||||||
|
import { openaiController } from '../whatsapp.module';
|
||||||
|
import { HttpStatus } from './index.router';
|
||||||
|
|
||||||
|
const logger = new Logger('OpenaiRouter');
|
||||||
|
|
||||||
|
export class OpenaiRouter extends RouterBroker {
|
||||||
|
constructor(...guards: RequestHandler[]) {
|
||||||
|
super();
|
||||||
|
this.router
|
||||||
|
.post(this.routerPath('set'), ...guards, async (req, res) => {
|
||||||
|
logger.verbose('request received in setOpenai');
|
||||||
|
logger.verbose('request body: ');
|
||||||
|
logger.verbose(req.body);
|
||||||
|
|
||||||
|
logger.verbose('request query: ');
|
||||||
|
logger.verbose(req.query);
|
||||||
|
const response = await this.dataValidate<OpenaiDto>({
|
||||||
|
request: req,
|
||||||
|
schema: openaiSchema,
|
||||||
|
ClassRef: OpenaiDto,
|
||||||
|
execute: (instance, data) => openaiController.createOpenai(instance, data),
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(HttpStatus.CREATED).json(response);
|
||||||
|
})
|
||||||
|
.get(this.routerPath('find'), ...guards, async (req, res) => {
|
||||||
|
logger.verbose('request received in findOpenai');
|
||||||
|
logger.verbose('request body: ');
|
||||||
|
logger.verbose(req.body);
|
||||||
|
|
||||||
|
logger.verbose('request query: ');
|
||||||
|
logger.verbose(req.query);
|
||||||
|
const response = await this.dataValidate<InstanceDto>({
|
||||||
|
request: req,
|
||||||
|
schema: instanceNameSchema,
|
||||||
|
ClassRef: InstanceDto,
|
||||||
|
execute: (instance) => openaiController.findOpenai(instance),
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(HttpStatus.OK).json(response);
|
||||||
|
})
|
||||||
|
.post(this.routerPath('contact'), ...guards, async (req, res) => {
|
||||||
|
logger.verbose('request received in setOpenai');
|
||||||
|
logger.verbose('request body: ');
|
||||||
|
logger.verbose(req.body);
|
||||||
|
|
||||||
|
logger.verbose('request query: ');
|
||||||
|
logger.verbose(req.query);
|
||||||
|
const response = await this.dataValidate<ContactOpenaiDto>({
|
||||||
|
request: req,
|
||||||
|
schema: openaiSchema,
|
||||||
|
ClassRef: ContactOpenaiDto,
|
||||||
|
execute: (instance, data) => openaiController.createContactOpenai(instance, data),
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(HttpStatus.CREATED).json(response);
|
||||||
|
})
|
||||||
|
|
||||||
|
.get(this.routerPath('findcontact'), ...guards, async (req, res) => {
|
||||||
|
logger.verbose('request received in findOpenai');
|
||||||
|
logger.verbose('request body: ');
|
||||||
|
logger.verbose(req.body);
|
||||||
|
|
||||||
|
logger.verbose('request query: ');
|
||||||
|
logger.verbose(req.query);
|
||||||
|
const response = await this.dataValidate<InstanceDto>({
|
||||||
|
request: req,
|
||||||
|
schema: instanceNameSchema,
|
||||||
|
ClassRef: InstanceDto,
|
||||||
|
execute: (instance) => openaiController.findContactOpenai(instance),
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(HttpStatus.OK).json(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly router = Router();
|
||||||
|
}
|
@ -49,4 +49,4 @@ export class SqsRouter extends RouterBroker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public readonly router = Router();
|
public readonly router = Router();
|
||||||
}
|
}
|
BIN
src/whatsapp/services/._whatsapp.service.ts
Normal file
BIN
src/whatsapp/services/._whatsapp.service.ts
Normal file
Binary file not shown.
@ -211,8 +211,8 @@ export class ChatwootService {
|
|||||||
'123456',
|
'123456',
|
||||||
inboxId,
|
inboxId,
|
||||||
false,
|
false,
|
||||||
'EvolutionAPI',
|
'Nex API',
|
||||||
'https://evolution-api.com/files/evolution-api-favicon.png',
|
'https://nex-api.com.br/shared/themes/site/files/images/logo-purple.pnghttps://evolution-api.com/files/evolution-api-favicon.png',
|
||||||
)) as any);
|
)) as any);
|
||||||
|
|
||||||
if (!contact) {
|
if (!contact) {
|
||||||
@ -345,11 +345,17 @@ export class ChatwootService {
|
|||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// const contact = await client.contacts.update({
|
||||||
|
// accountId: this.provider.account_id,
|
||||||
|
// id,
|
||||||
|
// data,
|
||||||
|
// });
|
||||||
this.logger.verbose('contact updated');
|
this.logger.verbose('contact updated');
|
||||||
return contact;
|
return contact;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findContact(instance: InstanceDto, phoneNumber: string) {
|
public async findContact(instance: InstanceDto, phoneNumber: string) {
|
||||||
@ -415,11 +421,18 @@ export class ChatwootService {
|
|||||||
nameContact = !body.key.fromMe ? body.pushName : chatId;
|
nameContact = !body.key.fromMe ? body.pushName : chatId;
|
||||||
|
|
||||||
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
||||||
const filterInbox = await this.getInbox(instance);
|
|
||||||
|
|
||||||
if (!filterInbox) {
|
var idInboxChat = 0;
|
||||||
this.logger.warn('inbox not found');
|
|
||||||
return null;
|
if(this.provider?.id_inbox){
|
||||||
|
idInboxChat = this.provider?.id_inbox;
|
||||||
|
}else{
|
||||||
|
const filterInbox = await this.getInbox(instance);
|
||||||
|
if (!filterInbox) {
|
||||||
|
this.logger.warn('inbox not found');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
idInboxChat = filterInbox.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
@ -443,11 +456,14 @@ export class ChatwootService {
|
|||||||
avatar_url: picture_url.profilePictureUrl || null,
|
avatar_url: picture_url.profilePictureUrl || null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// if (!contact) {
|
||||||
|
// contact = await this.findContact(instance, chatId);
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
await this.createContact(
|
await this.createContact(
|
||||||
instance,
|
instance,
|
||||||
body.key.participant.split('@')[0],
|
body.key.participant.split('@')[0],
|
||||||
filterInbox.id,
|
idInboxChat,
|
||||||
false,
|
false,
|
||||||
body.pushName,
|
body.pushName,
|
||||||
picture_url.profilePictureUrl || null,
|
picture_url.profilePictureUrl || null,
|
||||||
@ -473,7 +489,7 @@ export class ChatwootService {
|
|||||||
contact = await this.createContact(
|
contact = await this.createContact(
|
||||||
instance,
|
instance,
|
||||||
chatId,
|
chatId,
|
||||||
filterInbox.id,
|
idInboxChat,
|
||||||
isGroup,
|
isGroup,
|
||||||
nameContact,
|
nameContact,
|
||||||
picture_url.profilePictureUrl || null,
|
picture_url.profilePictureUrl || null,
|
||||||
@ -492,15 +508,12 @@ export class ChatwootService {
|
|||||||
avatar_url: picture_url.profilePictureUrl || null,
|
avatar_url: picture_url.profilePictureUrl || null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!contact) {
|
|
||||||
contact = await this.findContact(instance, chatId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const jid = isGroup ? null : body.key.remoteJid;
|
const jid = isGroup ? null : body.key.remoteJid;
|
||||||
contact = await this.createContact(
|
contact = await this.createContact(
|
||||||
instance,
|
instance,
|
||||||
chatId,
|
chatId,
|
||||||
filterInbox.id,
|
idInboxChat,
|
||||||
isGroup,
|
isGroup,
|
||||||
nameContact,
|
nameContact,
|
||||||
picture_url.profilePictureUrl || null,
|
picture_url.profilePictureUrl || null,
|
||||||
@ -532,7 +545,7 @@ export class ChatwootService {
|
|||||||
if (contactConversations) {
|
if (contactConversations) {
|
||||||
let conversation: any;
|
let conversation: any;
|
||||||
if (this.provider.reopen_conversation) {
|
if (this.provider.reopen_conversation) {
|
||||||
conversation = contactConversations.payload.find((conversation) => conversation.inbox_id == filterInbox.id);
|
conversation = contactConversations.payload.find((conversation) => conversation.inbox_id == idInboxChat);
|
||||||
|
|
||||||
if (this.provider.conversation_pending) {
|
if (this.provider.conversation_pending) {
|
||||||
await client.conversations.toggleStatus({
|
await client.conversations.toggleStatus({
|
||||||
@ -545,7 +558,7 @@ export class ChatwootService {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
conversation = contactConversations.payload.find(
|
conversation = contactConversations.payload.find(
|
||||||
(conversation) => conversation.status !== 'resolved' && conversation.inbox_id == filterInbox.id,
|
(conversation) => conversation.status !== 'resolved' && conversation.inbox_id == idInboxChat,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.logger.verbose('return conversation if exists');
|
this.logger.verbose('return conversation if exists');
|
||||||
@ -559,7 +572,7 @@ export class ChatwootService {
|
|||||||
this.logger.verbose('create conversation in chatwoot');
|
this.logger.verbose('create conversation in chatwoot');
|
||||||
const data = {
|
const data = {
|
||||||
contact_id: contactId.toString(),
|
contact_id: contactId.toString(),
|
||||||
inbox_id: filterInbox.id.toString(),
|
inbox_id: idInboxChat.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.provider.conversation_pending) {
|
if (this.provider.conversation_pending) {
|
||||||
@ -685,20 +698,31 @@ export class ChatwootService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
if(this.provider?.id_inbox){
|
||||||
const filterInbox = await this.getInbox(instance);
|
|
||||||
|
|
||||||
if (!filterInbox) {
|
this.logger.verbose('find conversation in chatwoot');
|
||||||
this.logger.warn('inbox not found');
|
var findConversation = await client.conversations.list({
|
||||||
return null;
|
accountId: this.provider.account_id,
|
||||||
|
inboxId: this.provider?.id_inbox,
|
||||||
|
});
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
||||||
|
const filterInbox = await this.getInbox(instance);
|
||||||
|
|
||||||
|
if (!filterInbox) {
|
||||||
|
this.logger.warn('inbox not found');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('find conversation in chatwoot');
|
||||||
|
var findConversation = await client.conversations.list({
|
||||||
|
accountId: this.provider.account_id,
|
||||||
|
inboxId: filterInbox.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('find conversation in chatwoot');
|
|
||||||
const findConversation = await client.conversations.list({
|
|
||||||
accountId: this.provider.account_id,
|
|
||||||
inboxId: filterInbox.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!findConversation) {
|
if (!findConversation) {
|
||||||
this.logger.warn('conversation not found');
|
this.logger.warn('conversation not found');
|
||||||
return null;
|
return null;
|
||||||
@ -805,20 +829,32 @@ export class ChatwootService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
|
||||||
const filterInbox = await this.getInbox(instance);
|
|
||||||
|
|
||||||
if (!filterInbox) {
|
if (this.provider?.id_inbox) {
|
||||||
this.logger.warn('inbox not found');
|
|
||||||
return null;
|
this.logger.verbose('find conversation in chatwoot');
|
||||||
|
var findConversation = await client.conversations.list({
|
||||||
|
accountId: this.provider.account_id,
|
||||||
|
inboxId: this.provider?.id_inbox,
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.logger.verbose('get inbox to instance: ' + instance.instanceName);
|
||||||
|
const filterInbox = await this.getInbox(instance);
|
||||||
|
|
||||||
|
if (!filterInbox) {
|
||||||
|
this.logger.warn('inbox not found');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('find conversation in chatwoot');
|
||||||
|
var findConversation = await client.conversations.list({
|
||||||
|
accountId: this.provider.account_id,
|
||||||
|
inboxId: filterInbox.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('find conversation in chatwoot');
|
|
||||||
const findConversation = await client.conversations.list({
|
|
||||||
accountId: this.provider.account_id,
|
|
||||||
inboxId: filterInbox.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!findConversation) {
|
if (!findConversation) {
|
||||||
this.logger.warn('conversation not found');
|
this.logger.warn('conversation not found');
|
||||||
return null;
|
return null;
|
||||||
@ -1053,6 +1089,29 @@ export class ChatwootService {
|
|||||||
formatText = this.provider.sign_msg ? `*${senderName}:*\n${messageReceived}` : messageReceived;
|
formatText = this.provider.sign_msg ? `*${senderName}:*\n${messageReceived}` : messageReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (body.content_attributes.in_reply_to){
|
||||||
|
var idResposta = (body.content_attributes.in_reply_to-1);
|
||||||
|
var conversationId = body.conversation.contact_inbox.inbox_id;
|
||||||
|
let config = {
|
||||||
|
method: 'get',
|
||||||
|
maxBodyLength: Infinity,
|
||||||
|
url: `${this.provider.url}/api/v1/accounts/${this.provider.account_id}/conversations/${conversationId}/messages?after=` + idResposta,
|
||||||
|
headers: {
|
||||||
|
'api_access_token': this.provider.token
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const { data } = await axios.request(config);
|
||||||
|
if (data.payload[0] && data.payload[0].id == body.content_attributes.in_reply_to) {
|
||||||
|
formatText = formatText +`\n\nResposta à: \n` + data.payload[0].content + ``;
|
||||||
|
}
|
||||||
|
this.logger.verbose('data sent');
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (const message of body.conversation.messages) {
|
for (const message of body.conversation.messages) {
|
||||||
this.logger.verbose('check if message is media');
|
this.logger.verbose('check if message is media');
|
||||||
if (message.attachments && message.attachments.length > 0) {
|
if (message.attachments && message.attachments.length > 0) {
|
||||||
@ -1522,14 +1581,20 @@ export class ChatwootService {
|
|||||||
if (event === 'status.instance') {
|
if (event === 'status.instance') {
|
||||||
this.logger.verbose('event status.instance');
|
this.logger.verbose('event status.instance');
|
||||||
const data = body;
|
const data = body;
|
||||||
const inbox = await this.getInbox(instance);
|
|
||||||
|
|
||||||
if (!inbox) {
|
if (this.provider?.id_inbox) {
|
||||||
this.logger.warn('inbox not found');
|
var msgStatus = `⚡️ Instance status ${this.provider?.name_inbox}: ${data.status}`;
|
||||||
return;
|
} else {
|
||||||
|
const inbox = await this.getInbox(instance);
|
||||||
|
|
||||||
|
if (!inbox) {
|
||||||
|
this.logger.warn('inbox not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgStatus = `⚡️ Instance status ${inbox.name}: ${data.status}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const msgStatus = `⚡️ Instance status ${inbox.name}: ${data.status}`;
|
|
||||||
|
|
||||||
this.logger.verbose('send message to chatwoot');
|
this.logger.verbose('send message to chatwoot');
|
||||||
await this.createBotMessage(instance, msgStatus, 'incoming');
|
await this.createBotMessage(instance, msgStatus, 'incoming');
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
TypebotModel,
|
TypebotModel,
|
||||||
WebhookModel,
|
WebhookModel,
|
||||||
WebsocketModel,
|
WebsocketModel,
|
||||||
|
|
||||||
} from '../models';
|
} from '../models';
|
||||||
import { RepositoryBroker } from '../repository/repository.manager';
|
import { RepositoryBroker } from '../repository/repository.manager';
|
||||||
import { WAStartupService } from './whatsapp.service';
|
import { WAStartupService } from './whatsapp.service';
|
||||||
@ -45,7 +46,10 @@ export class WAMonitoringService {
|
|||||||
Object.assign(this.redis, configService.get<Redis>('REDIS'));
|
Object.assign(this.redis, configService.get<Redis>('REDIS'));
|
||||||
|
|
||||||
this.dbInstance = this.db.ENABLED
|
this.dbInstance = this.db.ENABLED
|
||||||
? this.repository.dbServer?.db(this.db.CONNECTION.DB_PREFIX_NAME + '-instances')
|
? this.repository.dbServer?.db(
|
||||||
|
this.db.CONNECTION.DB_PREFIX_NAME +
|
||||||
|
this.db.CONNECTION.DB_PREFIX_FINAL_NAME
|
||||||
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +126,7 @@ export class WAMonitoringService {
|
|||||||
|
|
||||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||||
|
|
||||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
||||||
|
|
||||||
instanceData.instance['chatwoot'] = chatwoot;
|
instanceData.instance['chatwoot'] = chatwoot;
|
||||||
@ -239,21 +243,23 @@ export class WAMonitoringService {
|
|||||||
|
|
||||||
this.logger.verbose('cleaning store database instance: ' + instanceName);
|
this.logger.verbose('cleaning store database instance: ' + instanceName);
|
||||||
|
|
||||||
|
await AuthModel.deleteMany({ owner: instanceName });
|
||||||
await ChatModel.deleteMany({ owner: instanceName });
|
await ChatModel.deleteMany({ owner: instanceName });
|
||||||
await ContactModel.deleteMany({ owner: instanceName });
|
await ContactModel.deleteMany({ owner: instanceName });
|
||||||
await MessageUpModel.deleteMany({ owner: instanceName });
|
|
||||||
await MessageModel.deleteMany({ owner: instanceName });
|
await MessageModel.deleteMany({ owner: instanceName });
|
||||||
|
|
||||||
await AuthModel.deleteMany({ _id: instanceName });
|
await MessageUpModel.deleteMany({ owner: instanceName });
|
||||||
await WebhookModel.deleteMany({ _id: instanceName });
|
await WebhookModel.deleteMany({ _id: instanceName });
|
||||||
await ChatwootModel.deleteMany({ _id: instanceName });
|
await ChatwootModel.deleteMany({ _id: instanceName });
|
||||||
|
|
||||||
await ChamaaiModel.deleteMany({ _id: instanceName });
|
await ChamaaiModel.deleteMany({ _id: instanceName });
|
||||||
await ProxyModel.deleteMany({ _id: instanceName });
|
await ProxyModel.deleteMany({ _id: instanceName });
|
||||||
await RabbitmqModel.deleteMany({ _id: instanceName });
|
await RabbitmqModel.deleteMany({ _id: instanceName });
|
||||||
await TypebotModel.deleteMany({ _id: instanceName });
|
await TypebotModel.deleteMany({ _id: instanceName });
|
||||||
await WebsocketModel.deleteMany({ _id: instanceName });
|
await WebsocketModel.deleteMany({ _id: instanceName });
|
||||||
|
|
||||||
await SettingsModel.deleteMany({ _id: instanceName });
|
await SettingsModel.deleteMany({ _id: instanceName });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +283,7 @@ export class WAMonitoringService {
|
|||||||
const instance = new WAStartupService(this.configService, this.eventEmitter, this.repository, this.cache);
|
const instance = new WAStartupService(this.configService, this.eventEmitter, this.repository, this.cache);
|
||||||
instance.instanceName = name;
|
instance.instanceName = name;
|
||||||
this.logger.verbose('Instance loaded: ' + name);
|
this.logger.verbose('Instance loaded: ' + name);
|
||||||
|
|
||||||
await instance.connectToWhatsapp();
|
await instance.connectToWhatsapp();
|
||||||
this.logger.verbose('connectToWhatsapp: ' + name);
|
this.logger.verbose('connectToWhatsapp: ' + name);
|
||||||
|
|
||||||
|
57
src/whatsapp/services/openai.service.ts
Normal file
57
src/whatsapp/services/openai.service.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Logger } from '../../config/logger.config';
|
||||||
|
import { initQueues } from '../../libs/amqp.server';
|
||||||
|
import { InstanceDto } from '../dto/instance.dto';
|
||||||
|
import { OpenaiDto } from '../dto/openai.dto';
|
||||||
|
import { ContactOpenaiDto } from '../dto/contactopenai.dto';
|
||||||
|
import { OpenaiRaw } from '../models';
|
||||||
|
import { WAMonitoringService } from './monitor.service';
|
||||||
|
|
||||||
|
export class OpenaiService {
|
||||||
|
constructor(private readonly waMonitor: WAMonitoringService) {}
|
||||||
|
|
||||||
|
private readonly logger = new Logger(OpenaiService.name);
|
||||||
|
|
||||||
|
public create(instance: InstanceDto, data: OpenaiDto) {
|
||||||
|
this.logger.verbose('create openai: ' + instance.instanceName);
|
||||||
|
this.waMonitor.waInstances[instance.instanceName].setOpenai(data);
|
||||||
|
return { openai: { ...instance, openai: data } };
|
||||||
|
}
|
||||||
|
|
||||||
|
public async find(instance: InstanceDto): Promise<OpenaiRaw> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('find openai: ' + instance.instanceName);
|
||||||
|
const result = await this.waMonitor.waInstances[instance.instanceName].findOpenai();
|
||||||
|
|
||||||
|
if (Object.keys(result).length === 0) {
|
||||||
|
throw new Error('openai not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
return { chave: '', enabled: false, events: [] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public createContact(instance: InstanceDto, data: ContactOpenaiDto) {
|
||||||
|
this.logger.verbose('create openai: ' + instance.instanceName);
|
||||||
|
this.waMonitor.waInstances[instance.instanceName].setContactOpenai(data);
|
||||||
|
return { openai: { ...instance, openai: data } };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async findContact(instance: InstanceDto): Promise<OpenaiRaw> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('find openai: ' + instance.instanceName);
|
||||||
|
const result = await this.waMonitor.waInstances[instance.instanceName].findContactOpenai();
|
||||||
|
|
||||||
|
if (Object.keys(result).length === 0) {
|
||||||
|
throw new Error('openai not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
return { chave: '', enabled: false, events: [] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { SqsRaw } from '../models';
|
|||||||
import { WAMonitoringService } from './monitor.service';
|
import { WAMonitoringService } from './monitor.service';
|
||||||
|
|
||||||
export class SqsService {
|
export class SqsService {
|
||||||
constructor(private readonly waMonitor: WAMonitoringService) {}
|
constructor(private readonly waMonitor: WAMonitoringService) { }
|
||||||
|
|
||||||
private readonly logger = new Logger(SqsService.name);
|
private readonly logger = new Logger(SqsService.name);
|
||||||
|
|
||||||
@ -32,4 +32,4 @@ export class SqsService {
|
|||||||
return { enabled: false, events: [] };
|
return { enabled: false, events: [] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,8 @@ import { Events } from '../types/wa.types';
|
|||||||
import { WAMonitoringService } from './monitor.service';
|
import { WAMonitoringService } from './monitor.service';
|
||||||
|
|
||||||
export class TypebotService {
|
export class TypebotService {
|
||||||
constructor(private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService) {}
|
//constructor(private readonly waMonitor: WAMonitoringService) {}
|
||||||
|
constructor(private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService) { }
|
||||||
|
|
||||||
private readonly logger = new Logger(TypebotService.name);
|
private readonly logger = new Logger(TypebotService.name);
|
||||||
|
|
||||||
@ -177,6 +178,8 @@ export class TypebotService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//const request = await axios.post(data.url + '/api/v1/sendMessage', reqData);
|
||||||
|
|
||||||
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
||||||
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
||||||
|
|
||||||
@ -267,6 +270,8 @@ export class TypebotService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//const request = await axios.post(data.url + '/api/v1/sendMessage', reqData);
|
||||||
|
|
||||||
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
||||||
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
||||||
|
|
||||||
@ -386,7 +391,7 @@ export class TypebotService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (element.underline) {
|
if (element.underline) {
|
||||||
text = `*${text}*`;
|
text = `~${text}~`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.url) {
|
if (element.url) {
|
||||||
@ -498,7 +503,7 @@ export class TypebotService {
|
|||||||
const listening_from_me = findTypebot.listening_from_me;
|
const listening_from_me = findTypebot.listening_from_me;
|
||||||
|
|
||||||
const session = sessions.find((session) => session.remoteJid === remoteJid);
|
const session = sessions.find((session) => session.remoteJid === remoteJid);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (session && expire && expire > 0) {
|
if (session && expire && expire > 0) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
@ -571,6 +576,7 @@ export class TypebotService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//const request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
||||||
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
const request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
||||||
|
|
||||||
@ -658,9 +664,9 @@ export class TypebotService {
|
|||||||
|
|
||||||
let request: any;
|
let request: any;
|
||||||
try {
|
try {
|
||||||
|
//request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
||||||
request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
request = await axios.post(`${data.url}/api/${version}/sendMessage`, reqData);
|
||||||
|
|
||||||
await this.sendWAMessage(
|
await this.sendWAMessage(
|
||||||
instance,
|
instance,
|
||||||
remoteJid,
|
remoteJid,
|
||||||
@ -739,6 +745,7 @@ export class TypebotService {
|
|||||||
sessionId: session.sessionId.split('-')[1],
|
sessionId: session.sessionId.split('-')[1],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//const request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
const version = this.configService.get<Typebot>('TYPEBOT').API_VERSION;
|
||||||
const request = await axios.post(`${url}/api/${version}/sendMessage`, reqData);
|
const request = await axios.post(`${url}/api/${version}/sendMessage`, reqData);
|
||||||
|
|
||||||
@ -755,5 +762,249 @@ export class TypebotService {
|
|||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (session && expire && expire > 0) {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
const diff = now - session.updateAt;
|
||||||
|
|
||||||
|
const diffInMinutes = Math.floor(diff / 1000 / 60);
|
||||||
|
|
||||||
|
if (diffInMinutes > expire) {
|
||||||
|
//sessions.splice(sessions.indexOf(session), 1);
|
||||||
|
const newSessions = await this.clearSessions(instance, remoteJid);
|
||||||
|
|
||||||
|
const data = await this.createNewSession(instance, {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
//sessions: sessions,
|
||||||
|
sessions: newSessions,
|
||||||
|
remoteJid: remoteJid,
|
||||||
|
pushName: msg.pushName,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions);
|
||||||
|
|
||||||
|
if (data.messages.length === 0) {
|
||||||
|
const content = this.getConversationMessage(msg.message);
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
if (unknown_message) {
|
||||||
|
this.waMonitor.waInstances[instance.instanceName].textMessage({
|
||||||
|
number: remoteJid.split('@')[0],
|
||||||
|
options: {
|
||||||
|
delay: delay_message || 1000,
|
||||||
|
presence: 'composing',
|
||||||
|
},
|
||||||
|
textMessage: {
|
||||||
|
text: unknown_message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
|
||||||
|
sessions.splice(sessions.indexOf(session), 1);
|
||||||
|
|
||||||
|
const typebotData = {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
sessions,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.create(instance, typebotData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqData = {
|
||||||
|
message: content,
|
||||||
|
sessionId: data.sessionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
|
|
||||||
|
await this.sendWAMessage(
|
||||||
|
instance,
|
||||||
|
remoteJid,
|
||||||
|
request.data.messages,
|
||||||
|
request.data.input,
|
||||||
|
request.data.clientSideActions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (session && session.status !== 'opened') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
const data = await this.createNewSession(instance, {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
sessions: sessions,
|
||||||
|
remoteJid: remoteJid,
|
||||||
|
pushName: msg.pushName,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions);
|
||||||
|
|
||||||
|
if (data.messages.length === 0) {
|
||||||
|
const content = this.getConversationMessage(msg.message);
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
if (unknown_message) {
|
||||||
|
this.waMonitor.waInstances[instance.instanceName].textMessage({
|
||||||
|
number: remoteJid.split('@')[0],
|
||||||
|
options: {
|
||||||
|
delay: delay_message || 1000,
|
||||||
|
presence: 'composing',
|
||||||
|
},
|
||||||
|
textMessage: {
|
||||||
|
text: unknown_message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
|
||||||
|
sessions.splice(sessions.indexOf(session), 1);
|
||||||
|
|
||||||
|
const typebotData = {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
sessions,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.create(instance, typebotData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqData = {
|
||||||
|
message: content,
|
||||||
|
sessionId: data.sessionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
|
|
||||||
|
await this.sendWAMessage(
|
||||||
|
instance,
|
||||||
|
remoteJid,
|
||||||
|
request.data.messages,
|
||||||
|
request.data.input,
|
||||||
|
request.data.clientSideActions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions.map((session) => {
|
||||||
|
if (session.remoteJid === remoteJid) {
|
||||||
|
session.updateAt = Date.now();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const typebotData = {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
sessions,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.create(instance, typebotData);
|
||||||
|
|
||||||
|
const content = this.getConversationMessage(msg.message);
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
if (unknown_message) {
|
||||||
|
this.waMonitor.waInstances[instance.instanceName].textMessage({
|
||||||
|
number: remoteJid.split('@')[0],
|
||||||
|
options: {
|
||||||
|
delay: delay_message || 1000,
|
||||||
|
presence: 'composing',
|
||||||
|
},
|
||||||
|
textMessage: {
|
||||||
|
text: unknown_message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
|
||||||
|
sessions.splice(sessions.indexOf(session), 1);
|
||||||
|
|
||||||
|
const typebotData = {
|
||||||
|
enabled: findTypebot.enabled,
|
||||||
|
url: url,
|
||||||
|
typebot: typebot,
|
||||||
|
expire: expire,
|
||||||
|
keyword_finish: keyword_finish,
|
||||||
|
delay_message: delay_message,
|
||||||
|
unknown_message: unknown_message,
|
||||||
|
listening_from_me: listening_from_me,
|
||||||
|
sessions,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.create(instance, typebotData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqData = {
|
||||||
|
message: content,
|
||||||
|
sessionId: session.sessionId.split('-')[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = await axios.post(url + '/api/v1/sendMessage', reqData);
|
||||||
|
|
||||||
|
await this.sendWAMessage(
|
||||||
|
instance,
|
||||||
|
remoteJid,
|
||||||
|
request.data.messages,
|
||||||
|
request.data.input,
|
||||||
|
request.data.clientSideActions,
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,8 @@ import {
|
|||||||
SendTextDto,
|
SendTextDto,
|
||||||
StatusMessage,
|
StatusMessage,
|
||||||
} from '../dto/sendMessage.dto';
|
} from '../dto/sendMessage.dto';
|
||||||
import { ChamaaiRaw, ProxyRaw, RabbitmqRaw, SettingsRaw, SqsRaw, TypebotRaw } from '../models';
|
import { ChamaaiRaw, ProxyRaw, RabbitmqRaw, OpenaiRaw, SettingsRaw, SqsRaw, TypebotRaw, ContactOpenaiRaw } from '../models';
|
||||||
|
|
||||||
import { ChatRaw } from '../models/chat.model';
|
import { ChatRaw } from '../models/chat.model';
|
||||||
import { ChatwootRaw } from '../models/chatwoot.model';
|
import { ChatwootRaw } from '../models/chatwoot.model';
|
||||||
import { ContactRaw } from '../models/contact.model';
|
import { ContactRaw } from '../models/contact.model';
|
||||||
@ -130,7 +131,51 @@ import { Events, MessageSubtype, TypeMediaMessage, wa } from '../types/wa.types'
|
|||||||
import { waMonitor } from '../whatsapp.module';
|
import { waMonitor } from '../whatsapp.module';
|
||||||
import { ChamaaiService } from './chamaai.service';
|
import { ChamaaiService } from './chamaai.service';
|
||||||
import { ChatwootService } from './chatwoot.service';
|
import { ChatwootService } from './chatwoot.service';
|
||||||
|
//import { SocksProxyAgent } from './socks-proxy-agent';
|
||||||
import { TypebotService } from './typebot.service';
|
import { TypebotService } from './typebot.service';
|
||||||
|
|
||||||
|
import { Configuration, OpenAIApi, ChatCompletionRequestMessage } from "openai"
|
||||||
|
|
||||||
|
import { openai, OpenAIService } from "../../libs/openai"
|
||||||
|
import { redis } from "../../libs/redis"
|
||||||
|
|
||||||
|
import { initPrompt } from "../../utils/initPrompt"
|
||||||
|
import { ContactOpenaiDto } from '../dto/contactopenai.dto';
|
||||||
|
|
||||||
|
// https://wa.me/+5512982754592
|
||||||
|
interface CustomerChat {
|
||||||
|
status?: "open" | "closed"
|
||||||
|
orderCode: string
|
||||||
|
chatAt: string
|
||||||
|
customer: {
|
||||||
|
name: string
|
||||||
|
phone: string
|
||||||
|
}
|
||||||
|
messages: ChatCompletionRequestMessage[]
|
||||||
|
orderSummary?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function completion(
|
||||||
|
apiKey: string,
|
||||||
|
messages: ChatCompletionRequestMessage[]
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
|
||||||
|
const configuration = new Configuration({
|
||||||
|
apiKey: apiKey,
|
||||||
|
})
|
||||||
|
|
||||||
|
const openai = new OpenAIApi(configuration)
|
||||||
|
|
||||||
|
const completion = await openai.createChatCompletion({
|
||||||
|
model: "gpt-3.5-turbo",
|
||||||
|
temperature: 0,
|
||||||
|
max_tokens: 256,
|
||||||
|
messages,
|
||||||
|
})
|
||||||
|
|
||||||
|
return completion.data.choices[0].message?.content
|
||||||
|
}
|
||||||
|
|
||||||
export class WAStartupService {
|
export class WAStartupService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
@ -151,6 +196,7 @@ export class WAStartupService {
|
|||||||
private readonly localSettings: wa.LocalSettings = {};
|
private readonly localSettings: wa.LocalSettings = {};
|
||||||
private readonly localWebsocket: wa.LocalWebsocket = {};
|
private readonly localWebsocket: wa.LocalWebsocket = {};
|
||||||
private readonly localRabbitmq: wa.LocalRabbitmq = {};
|
private readonly localRabbitmq: wa.LocalRabbitmq = {};
|
||||||
|
private readonly localOpenai: wa.LocalOpenai = {};
|
||||||
private readonly localSqs: wa.LocalSqs = {};
|
private readonly localSqs: wa.LocalSqs = {};
|
||||||
public readonly localTypebot: wa.LocalTypebot = {};
|
public readonly localTypebot: wa.LocalTypebot = {};
|
||||||
private readonly localProxy: wa.LocalProxy = {};
|
private readonly localProxy: wa.LocalProxy = {};
|
||||||
@ -166,6 +212,7 @@ export class WAStartupService {
|
|||||||
|
|
||||||
private chatwootService = new ChatwootService(waMonitor, this.configService);
|
private chatwootService = new ChatwootService(waMonitor, this.configService);
|
||||||
|
|
||||||
|
//private typebotService = new TypebotService(waMonitor);
|
||||||
private typebotService = new TypebotService(waMonitor, this.configService);
|
private typebotService = new TypebotService(waMonitor, this.configService);
|
||||||
|
|
||||||
private chamaaiService = new ChamaaiService(waMonitor, this.configService);
|
private chamaaiService = new ChamaaiService(waMonitor, this.configService);
|
||||||
@ -216,7 +263,10 @@ export class WAStartupService {
|
|||||||
this.logger.verbose('Database enabled, trying to get from database');
|
this.logger.verbose('Database enabled, trying to get from database');
|
||||||
const collection = dbserver
|
const collection = dbserver
|
||||||
.getClient()
|
.getClient()
|
||||||
.db(this.configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME + '-instances')
|
.db(
|
||||||
|
this.configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME +
|
||||||
|
this.configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_FINAL_NAME
|
||||||
|
)
|
||||||
.collection(this.instanceName);
|
.collection(this.instanceName);
|
||||||
const data = await collection.findOne({ _id: 'creds' });
|
const data = await collection.findOne({ _id: 'creds' });
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -465,6 +515,72 @@ export class WAStartupService {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async loadOpenai() {
|
||||||
|
this.logger.verbose('Loading openai');
|
||||||
|
const data = await this.repository.openai.find(this.instanceName);
|
||||||
|
|
||||||
|
this.localOpenai.chave = data?.chave;
|
||||||
|
this.logger.verbose(`Openai chave: ${this.localOpenai.chave}`);
|
||||||
|
|
||||||
|
this.localOpenai.enabled = data?.enabled;
|
||||||
|
this.logger.verbose(`Openai enabled: ${this.localOpenai.enabled}`);
|
||||||
|
|
||||||
|
this.localOpenai.events = data?.events;
|
||||||
|
this.logger.verbose(`Openai events: ${this.localOpenai.events}`);
|
||||||
|
|
||||||
|
this.logger.verbose('Openai loaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setOpenai(data: OpenaiRaw) {
|
||||||
|
this.logger.verbose('Setting openai');
|
||||||
|
await this.repository.openai.create(data, this.instanceName);
|
||||||
|
this.logger.verbose(`Openai events: ${data.events}`);
|
||||||
|
Object.assign(this.localOpenai, data);
|
||||||
|
this.logger.verbose('Openai set');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setContactOpenai(data: ContactOpenaiRaw) {
|
||||||
|
this.logger.verbose('Setting openai');
|
||||||
|
await this.repository.openai.createContact(data, this.instanceName);
|
||||||
|
|
||||||
|
this.logger.verbose(`Openai events: ${data.enabled}`);
|
||||||
|
Object.assign(this.localOpenai, data);
|
||||||
|
this.logger.verbose('Openai set');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findContactOpenai() {
|
||||||
|
this.logger.verbose('Finding openai');
|
||||||
|
const data = await this.repository.openai.findContactAll(this.instanceName);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
this.logger.verbose('Openai not found');
|
||||||
|
throw new NotFoundException('Openai not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findOpenai() {
|
||||||
|
this.logger.verbose('Finding openai');
|
||||||
|
const data = await this.repository.openai.find(this.instanceName);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
this.logger.verbose('Openai not found');
|
||||||
|
throw new NotFoundException('Openai not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose(`Openai events: ${data.events}`);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async removeOpenaiQueues() {
|
||||||
|
this.logger.verbose('Removing openai');
|
||||||
|
|
||||||
|
if (this.localOpenai.enabled) {
|
||||||
|
removeQueues(this.instanceName, this.localOpenai.events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async loadRabbitmq() {
|
private async loadRabbitmq() {
|
||||||
this.logger.verbose('Loading rabbitmq');
|
this.logger.verbose('Loading rabbitmq');
|
||||||
const data = await this.repository.rabbitmq.find(this.instanceName);
|
const data = await this.repository.rabbitmq.find(this.instanceName);
|
||||||
@ -507,6 +623,7 @@ export class WAStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async loadSqs() {
|
private async loadSqs() {
|
||||||
this.logger.verbose('Loading sqs');
|
this.logger.verbose('Loading sqs');
|
||||||
const data = await this.repository.sqs.find(this.instanceName);
|
const data = await this.repository.sqs.find(this.instanceName);
|
||||||
@ -626,10 +743,11 @@ export class WAStartupService {
|
|||||||
this.logger.verbose(`Proxy proxy: ${data.proxy}`);
|
this.logger.verbose(`Proxy proxy: ${data.proxy}`);
|
||||||
Object.assign(this.localProxy, data);
|
Object.assign(this.localProxy, data);
|
||||||
this.logger.verbose('Proxy set');
|
this.logger.verbose('Proxy set');
|
||||||
|
//this.reloadConnection();
|
||||||
if (reload) {
|
if (reload) {
|
||||||
this.reloadConnection();
|
this.reloadConnection();
|
||||||
}
|
}
|
||||||
|
//this.client?.ws?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findProxy() {
|
public async findProxy() {
|
||||||
@ -768,6 +886,7 @@ export class WAStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this.localSqs.enabled) {
|
if (this.localSqs.enabled) {
|
||||||
const sqs = getSQS();
|
const sqs = getSQS();
|
||||||
|
|
||||||
@ -1299,14 +1418,18 @@ export class WAStartupService {
|
|||||||
let options;
|
let options;
|
||||||
|
|
||||||
if (this.localProxy.enabled) {
|
if (this.localProxy.enabled) {
|
||||||
this.logger.info('Proxy enabled: ' + this.localProxy.proxy);
|
this.logger.verbose('Proxy enabled');
|
||||||
|
// options = {
|
||||||
|
// agent: new ProxyAgent(this.localProxy.proxy as any),
|
||||||
|
// fetchAgent: new ProxyAgent(this.localProxy.proxy as any),
|
||||||
|
// };
|
||||||
if (this.localProxy.proxy.includes('proxyscrape')) {
|
if (this.localProxy.proxy.includes('proxyscrape')) {
|
||||||
const response = await axios.get(this.localProxy.proxy);
|
const response = await axios.get(this.localProxy.proxy);
|
||||||
const text = response.data;
|
const text = response.data;
|
||||||
const proxyUrls = text.split('\r\n');
|
const proxyUrls = text.split('\r\n');
|
||||||
const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length));
|
const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length));
|
||||||
const proxyUrl = 'http://' + proxyUrls[rand];
|
const proxyUrl = 'http://' + proxyUrls[rand];
|
||||||
|
console.log(proxyUrl);
|
||||||
options = {
|
options = {
|
||||||
agent: new ProxyAgent(proxyUrl as any),
|
agent: new ProxyAgent(proxyUrl as any),
|
||||||
};
|
};
|
||||||
@ -1656,9 +1779,132 @@ export class WAStartupService {
|
|||||||
|
|
||||||
let messageRaw: MessageRaw;
|
let messageRaw: MessageRaw;
|
||||||
|
|
||||||
|
if (received.key.remoteJid.includes('@g.us')) {
|
||||||
|
}else{
|
||||||
|
|
||||||
|
if (messages[0].message.conversation){
|
||||||
|
|
||||||
|
const openai = await this.repository.openai_contact.find(this.instance.name);
|
||||||
|
|
||||||
|
if (openai && openai?.chave && openai?.enabled == true && openai?.prompts){
|
||||||
|
|
||||||
|
const customerPhone = `+${received.key.remoteJid.replace("@s.whatsapp.net", "")}`
|
||||||
|
const customerName = messages[0].pushName
|
||||||
|
|
||||||
|
const contactOpenaiC = await this.repository.openai_contact.findContact(this.instance.name, customerPhone);
|
||||||
|
if (!contactOpenaiC){
|
||||||
|
var data = new ContactOpenaiDto;
|
||||||
|
data.contact = customerPhone;
|
||||||
|
data.enabled = true;
|
||||||
|
data.owner = this.instance.name;
|
||||||
|
|
||||||
|
await this.repository.openai_contact.createContact(data, this.instance.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactOpenai = await this.repository.openai_contact.findContact(this.instance.name, customerPhone);
|
||||||
|
|
||||||
|
if(contactOpenai?.enabled == true){
|
||||||
|
|
||||||
|
const customerKey = `instancia:${this.instance.name}customer:${customerPhone}:chat`
|
||||||
|
const orderCode = `#sk-${("00000" + Math.random()).slice(-5)}`
|
||||||
|
|
||||||
|
const lastChat = JSON.parse((await redis.get(customerKey)) || "{}")
|
||||||
|
var storeName = 'Nome';
|
||||||
|
const customerChat: CustomerChat =
|
||||||
|
lastChat?.status === "open"
|
||||||
|
? (lastChat as CustomerChat)
|
||||||
|
: {
|
||||||
|
status: "open",
|
||||||
|
orderCode,
|
||||||
|
chatAt: new Date().toISOString(),
|
||||||
|
customer: {
|
||||||
|
name: customerName,
|
||||||
|
phone: customerPhone,
|
||||||
|
},
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: initPrompt(storeName, orderCode, openai?.prompts),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
orderSummary: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose(customerPhone+" 👤 "+ messages[0].message.conversation)
|
||||||
|
|
||||||
|
customerChat.messages.push({
|
||||||
|
role: "user",
|
||||||
|
content: messages[0].message.conversation,
|
||||||
|
})
|
||||||
|
|
||||||
|
const content =
|
||||||
|
(await completion(openai.chave,
|
||||||
|
customerChat.messages)) || "Não entendi..."
|
||||||
|
|
||||||
|
customerChat.messages.push({
|
||||||
|
role: "assistant",
|
||||||
|
content,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.logger.verbose(customerPhone + " 🤖 "+ content)
|
||||||
|
|
||||||
|
var dadosMessage = {
|
||||||
|
textMessage: received.message.conversation,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mentions: string[];
|
||||||
|
|
||||||
|
const linkPreview = true;
|
||||||
|
|
||||||
|
let quoted: WAMessage;
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
quoted,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client.sendMessage(
|
||||||
|
received.key.remoteJid,
|
||||||
|
{
|
||||||
|
text: content,
|
||||||
|
mentions,
|
||||||
|
linkPreview: linkPreview,
|
||||||
|
} as unknown as AnyMessageContent,
|
||||||
|
option as unknown as MiscMessageGenerationOptions,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
customerChat.status === "open" &&
|
||||||
|
content.match(customerChat.orderCode)
|
||||||
|
) {
|
||||||
|
customerChat.status = "closed"
|
||||||
|
|
||||||
|
customerChat.messages.push({
|
||||||
|
role: "user",
|
||||||
|
content:
|
||||||
|
"Gere um resumo de pedido para registro no sistema da pizzaria, quem está solicitando é um robô.",
|
||||||
|
})
|
||||||
|
|
||||||
|
const content =
|
||||||
|
(await completion(openai.chave,customerChat.messages)) || "Não entendi..."
|
||||||
|
|
||||||
|
this.logger.verbose(customerPhone + " 📦 "+ content)
|
||||||
|
|
||||||
|
customerChat.orderSummary = content
|
||||||
|
}
|
||||||
|
redis.set(customerKey, JSON.stringify(customerChat))
|
||||||
|
|
||||||
|
this.logger.verbose(received);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(this.localWebhook.webhook_base64 === true && received?.message.documentMessage) ||
|
(this.localWebhook.webhook_base64 === true && received?.message.documentMessage) ||
|
||||||
received?.message?.imageMessage
|
received?.message.imageMessage
|
||||||
) {
|
) {
|
||||||
const buffer = await downloadMediaMessage(
|
const buffer = await downloadMediaMessage(
|
||||||
{ key: received.key, message: received?.message },
|
{ key: received.key, message: received?.message },
|
||||||
@ -1714,6 +1960,7 @@ export class WAStartupService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (this.localTypebot.enabled) {
|
||||||
const typebotSessionRemoteJid = this.localTypebot.sessions?.find(
|
const typebotSessionRemoteJid = this.localTypebot.sessions?.find(
|
||||||
(session) => session.remoteJid === received.key.remoteJid,
|
(session) => session.remoteJid === received.key.remoteJid,
|
||||||
);
|
);
|
||||||
@ -2060,7 +2307,9 @@ export class WAStartupService {
|
|||||||
private createJid(number: string): string {
|
private createJid(number: string): string {
|
||||||
this.logger.verbose('Creating jid with number: ' + number);
|
this.logger.verbose('Creating jid with number: ' + number);
|
||||||
|
|
||||||
|
//if (number.includes('@g.us') || number.includes('@s.whatsapp.net')) {
|
||||||
if (number.includes('@g.us') || number.includes('@s.whatsapp.net') || number.includes('@lid')) {
|
if (number.includes('@g.us') || number.includes('@s.whatsapp.net') || number.includes('@lid')) {
|
||||||
|
//this.logger.verbose('Number already contains @g.us or @s.whatsapp.net');
|
||||||
this.logger.verbose('Number already contains @g.us or @s.whatsapp.net or @lid');
|
this.logger.verbose('Number already contains @g.us or @s.whatsapp.net or @lid');
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
@ -2285,6 +2534,7 @@ export class WAStartupService {
|
|||||||
!message['conversation'] &&
|
!message['conversation'] &&
|
||||||
sender !== 'status@broadcast'
|
sender !== 'status@broadcast'
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (message['reactionMessage']) {
|
if (message['reactionMessage']) {
|
||||||
this.logger.verbose('Sending reaction');
|
this.logger.verbose('Sending reaction');
|
||||||
return await this.client.sendMessage(
|
return await this.client.sendMessage(
|
||||||
@ -2314,6 +2564,7 @@ export class WAStartupService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message['conversation']) {
|
if (message['conversation']) {
|
||||||
this.logger.verbose('Sending message');
|
this.logger.verbose('Sending message');
|
||||||
return await this.client.sendMessage(
|
return await this.client.sendMessage(
|
||||||
@ -2573,9 +2824,15 @@ export class WAStartupService {
|
|||||||
|
|
||||||
let mimetype: string;
|
let mimetype: string;
|
||||||
|
|
||||||
|
// if (isURL(mediaMessage.media)) {
|
||||||
|
// mimetype = getMIMEType(mediaMessage.media);
|
||||||
|
// } else {
|
||||||
|
// mimetype = getMIMEType(mediaMessage.fileName);
|
||||||
|
// }
|
||||||
|
|
||||||
if (mediaMessage.mimetype) {
|
if (mediaMessage.mimetype) {
|
||||||
mimetype = mediaMessage.mimetype;
|
mimetype = mediaMessage.mimetype;
|
||||||
} else {
|
}else{
|
||||||
if (isURL(mediaMessage.media)) {
|
if (isURL(mediaMessage.media)) {
|
||||||
mimetype = getMIMEType(mediaMessage.media);
|
mimetype = getMIMEType(mediaMessage.media);
|
||||||
} else {
|
} else {
|
||||||
@ -3229,6 +3486,7 @@ export class WAStartupService {
|
|||||||
await this.client.updateGroupsAddPrivacy(settings.privacySettings.groupadd);
|
await this.client.updateGroupsAddPrivacy(settings.privacySettings.groupadd);
|
||||||
this.logger.verbose('Groups add privacy updated');
|
this.logger.verbose('Groups add privacy updated');
|
||||||
|
|
||||||
|
//this.client?.ws?.close();
|
||||||
this.reloadConnection();
|
this.reloadConnection();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -88,6 +88,12 @@ export declare namespace wa {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
events?: string[];
|
events?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LocalOpenai = {
|
||||||
|
chave?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
events?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
type Session = {
|
type Session = {
|
||||||
remoteJid?: string;
|
remoteJid?: string;
|
||||||
|
@ -10,6 +10,7 @@ import { GroupController } from './controllers/group.controller';
|
|||||||
import { InstanceController } from './controllers/instance.controller';
|
import { InstanceController } from './controllers/instance.controller';
|
||||||
import { ProxyController } from './controllers/proxy.controller';
|
import { ProxyController } from './controllers/proxy.controller';
|
||||||
import { RabbitmqController } from './controllers/rabbitmq.controller';
|
import { RabbitmqController } from './controllers/rabbitmq.controller';
|
||||||
|
import { OpenaiController } from './controllers/openai.controller';
|
||||||
import { SendMessageController } from './controllers/sendMessage.controller';
|
import { SendMessageController } from './controllers/sendMessage.controller';
|
||||||
import { SettingsController } from './controllers/settings.controller';
|
import { SettingsController } from './controllers/settings.controller';
|
||||||
import { SqsController } from './controllers/sqs.controller';
|
import { SqsController } from './controllers/sqs.controller';
|
||||||
@ -27,6 +28,8 @@ import {
|
|||||||
MessageUpModel,
|
MessageUpModel,
|
||||||
ProxyModel,
|
ProxyModel,
|
||||||
RabbitmqModel,
|
RabbitmqModel,
|
||||||
|
OpenaiModel,
|
||||||
|
ContactOpenaiModel,
|
||||||
SettingsModel,
|
SettingsModel,
|
||||||
SqsModel,
|
SqsModel,
|
||||||
TypebotModel,
|
TypebotModel,
|
||||||
@ -42,6 +45,7 @@ import { MessageRepository } from './repository/message.repository';
|
|||||||
import { MessageUpRepository } from './repository/messageUp.repository';
|
import { MessageUpRepository } from './repository/messageUp.repository';
|
||||||
import { ProxyRepository } from './repository/proxy.repository';
|
import { ProxyRepository } from './repository/proxy.repository';
|
||||||
import { RabbitmqRepository } from './repository/rabbitmq.repository';
|
import { RabbitmqRepository } from './repository/rabbitmq.repository';
|
||||||
|
import { OpenaiRepository } from './repository/openai.repository';
|
||||||
import { RepositoryBroker } from './repository/repository.manager';
|
import { RepositoryBroker } from './repository/repository.manager';
|
||||||
import { SettingsRepository } from './repository/settings.repository';
|
import { SettingsRepository } from './repository/settings.repository';
|
||||||
import { SqsRepository } from './repository/sqs.repository';
|
import { SqsRepository } from './repository/sqs.repository';
|
||||||
@ -54,6 +58,7 @@ import { ChatwootService } from './services/chatwoot.service';
|
|||||||
import { WAMonitoringService } from './services/monitor.service';
|
import { WAMonitoringService } from './services/monitor.service';
|
||||||
import { ProxyService } from './services/proxy.service';
|
import { ProxyService } from './services/proxy.service';
|
||||||
import { RabbitmqService } from './services/rabbitmq.service';
|
import { RabbitmqService } from './services/rabbitmq.service';
|
||||||
|
import { OpenaiService } from './services/openai.service';
|
||||||
import { SettingsService } from './services/settings.service';
|
import { SettingsService } from './services/settings.service';
|
||||||
import { SqsService } from './services/sqs.service';
|
import { SqsService } from './services/sqs.service';
|
||||||
import { TypebotService } from './services/typebot.service';
|
import { TypebotService } from './services/typebot.service';
|
||||||
@ -72,9 +77,10 @@ const websocketRepository = new WebsocketRepository(WebsocketModel, configServic
|
|||||||
const proxyRepository = new ProxyRepository(ProxyModel, configService);
|
const proxyRepository = new ProxyRepository(ProxyModel, configService);
|
||||||
const chamaaiRepository = new ChamaaiRepository(ChamaaiModel, configService);
|
const chamaaiRepository = new ChamaaiRepository(ChamaaiModel, configService);
|
||||||
const rabbitmqRepository = new RabbitmqRepository(RabbitmqModel, configService);
|
const rabbitmqRepository = new RabbitmqRepository(RabbitmqModel, configService);
|
||||||
const sqsRepository = new SqsRepository(SqsModel, configService);
|
const openaiRepository = new OpenaiRepository(OpenaiModel,ContactOpenaiModel, configService);
|
||||||
const chatwootRepository = new ChatwootRepository(ChatwootModel, configService);
|
const chatwootRepository = new ChatwootRepository(ChatwootModel, configService);
|
||||||
const settingsRepository = new SettingsRepository(SettingsModel, configService);
|
const settingsRepository = new SettingsRepository(SettingsModel, configService);
|
||||||
|
const sqsRepository = new SqsRepository(SqsModel, configService);
|
||||||
const authRepository = new AuthRepository(AuthModel, configService);
|
const authRepository = new AuthRepository(AuthModel, configService);
|
||||||
|
|
||||||
export const repository = new RepositoryBroker(
|
export const repository = new RepositoryBroker(
|
||||||
@ -87,6 +93,8 @@ export const repository = new RepositoryBroker(
|
|||||||
settingsRepository,
|
settingsRepository,
|
||||||
websocketRepository,
|
websocketRepository,
|
||||||
rabbitmqRepository,
|
rabbitmqRepository,
|
||||||
|
openaiRepository,
|
||||||
|
openaiRepository,
|
||||||
sqsRepository,
|
sqsRepository,
|
||||||
typebotRepository,
|
typebotRepository,
|
||||||
proxyRepository,
|
proxyRepository,
|
||||||
@ -130,6 +138,10 @@ const sqsService = new SqsService(waMonitor);
|
|||||||
|
|
||||||
export const sqsController = new SqsController(sqsService);
|
export const sqsController = new SqsController(sqsService);
|
||||||
|
|
||||||
|
const openaiService = new OpenaiService(waMonitor);
|
||||||
|
|
||||||
|
export const openaiController = new OpenaiController(openaiService);
|
||||||
|
|
||||||
const chatwootService = new ChatwootService(waMonitor, configService);
|
const chatwootService = new ChatwootService(waMonitor, configService);
|
||||||
|
|
||||||
export const chatwootController = new ChatwootController(chatwootService, configService);
|
export const chatwootController = new ChatwootController(chatwootService, configService);
|
||||||
@ -149,6 +161,7 @@ export const instanceController = new InstanceController(
|
|||||||
settingsService,
|
settingsService,
|
||||||
websocketService,
|
websocketService,
|
||||||
rabbitmqService,
|
rabbitmqService,
|
||||||
|
openaiService,
|
||||||
proxyService,
|
proxyService,
|
||||||
sqsService,
|
sqsService,
|
||||||
typebotService,
|
typebotService,
|
||||||
|
Loading…
Reference in New Issue
Block a user