Integração com ChatGPT e id inbox chatwoot

This commit is contained in:
CodePhix 2023-12-06 20:16:20 -03:00
parent 41b2946cdc
commit eadbba8ca6
129 changed files with 19275 additions and 17806 deletions

BIN
.DS_Store vendored

Binary file not shown.

5
env Normal file
View File

@ -0,0 +1,5 @@
OPENAI_API_KEY=""
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASS=0

14
src/config.ts Executable file
View 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,
},
}

15
src/config/env.config.ts Normal file → Executable file
View File

@ -48,6 +48,7 @@ export type CleanStoreConf = {
export type DBConnection = {
URI: string;
DB_PREFIX_NAME: string;
DB_PREFIX_FINAL_NAME: string;
};
export type Database = {
CONNECTION: DBConnection;
@ -74,6 +75,12 @@ export type Sqs = {
REGION: string;
};
export type Openai = {
CHAVE: string;
ENABLED: boolean;
URI: string;
};
export type Websocket = {
ENABLED: boolean;
};
@ -145,6 +152,7 @@ export interface Env {
REDIS: Redis;
RABBITMQ: Rabbitmq;
SQS: Sqs;
OPENAI: Openai;
WEBSOCKET: Websocket;
LOG: Log;
DEL_INSTANCE: DelInstance;
@ -218,6 +226,7 @@ export class ConfigService {
CONNECTION: {
URI: process.env.DATABASE_CONNECTION_URI || '',
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',
SAVE_DATA: {
@ -244,6 +253,12 @@ export class ConfigService {
ACCOUNT_ID: process.env.SQS_ACCOUNT_ID || '',
REGION: process.env.SQS_REGION || '',
},
OPENAI: {
CHAVE: process.env?.OPENAI_ENABLED || '',
ENABLED: process.env?.OPENAI_ENABLED === 'true',
URI: process.env.OPENAI_URI || '',
},
WEBSOCKET: {
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
},

4
src/config/error.config.ts Normal file → Executable file
View File

@ -8,7 +8,7 @@ export function onUnexpectedError() {
stderr: process.stderr.fd,
error,
});
// process.exit(1);
process.exit(1);
});
process.on('unhandledRejection', (error, origin) => {
@ -18,6 +18,6 @@ export function onUnexpectedError() {
stderr: process.stderr.fd,
error,
});
// process.exit(1);
process.exit(1);
});
}

0
src/config/event.config.ts Normal file → Executable file
View File

0
src/config/logger.config.ts Normal file → Executable file
View File

0
src/config/path.config.ts Normal file → Executable file
View File

39
src/dev-env.yml Normal file → Executable file
View File

@ -7,8 +7,8 @@
# Choose the server type for the application
SERVER:
TYPE: http # https
PORT: 8080 # 443
URL: localhost
PORT: 3333 # 443
URL: 127.0.0.1
CORS:
ORIGIN:
@ -48,8 +48,8 @@ DEL_INSTANCE: false # or false
# Temporary data storage
STORE:
MESSAGES: true
MESSAGE_UP: true
MESSAGES: false
MESSAGE_UP: false
CONTACTS: true
CHATS: true
@ -62,17 +62,20 @@ CLEAN_STORE:
# Permanent data storage
DATABASE:
ENABLED: false
ENABLED: true
CONNECTION:
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
SAVE_DATA:
INSTANCE: false
INSTANCE: true
NEW_MESSAGE: false
MESSAGE_UPDATE: false
CONTACTS: false
CHATS: false
CONTACTS: true
CHATS: true
REDIS:
ENABLED: false
@ -83,8 +86,14 @@ RABBITMQ:
ENABLED: false
URI: "amqp://guest:guest@localhost:5672"
OPENAI:
CHAVE: ""
ENABLED: false
PROMPTS: false
URI: ""
SQS:
ENABLED: true
ENABLED: false
ACCESS_KEY_ID: ""
SECRET_ACCESS_KEY: ""
ACCOUNT_ID: ""
@ -93,12 +102,15 @@ SQS:
WEBSOCKET:
ENABLED: false
TYPEBOT:
API_VERSION: 'v1' # v1 | v2
# Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created
WEBHOOK:
# Define a global webhook that will listen for enabled events from all instances
GLOBAL:
URL: <url>
URL: ""
ENABLED: false
# 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
@ -134,7 +146,7 @@ WEBHOOK:
CHAMA_AI_ACTION: false
# This event is used to send errors to the webhook
ERRORS: false
ERRORS_WEBHOOK: <url>
ERRORS_WEBHOOK: ""
CONFIG_SESSION_PHONE:
# Name that will be displayed on smartphone connection
@ -146,9 +158,6 @@ QRCODE:
LIMIT: 30
COLOR: "#198754"
TYPEBOT:
API_VERSION: 'v1' # v1 | v2
# Defines an authentication type for the api
# 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

0
src/docs/swagger.conf.ts Normal file → Executable file
View File

2
src/docs/swagger.yaml Normal file → Executable file
View File

@ -25,7 +25,7 @@ info:
</font>
[![Run in Postman](https://run.pstmn.io/button.svg)](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:
name: DavidsonGomes
email: contato@agenciadgcode.com

0
src/exceptions/400.exception.ts Normal file → Executable file
View File

0
src/exceptions/401.exception.ts Normal file → Executable file
View File

0
src/exceptions/403.exception.ts Normal file → Executable file
View File

0
src/exceptions/404.exception.ts Normal file → Executable file
View File

0
src/exceptions/500.exception.ts Normal file → Executable file
View File

0
src/exceptions/index.ts Normal file → Executable file
View File

2
src/libs/amqp.server.ts Normal file → Executable file
View File

@ -1,6 +1,6 @@
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';
const logger = new Logger('AMQP');

3
src/libs/db.connect.ts Normal file → Executable file
View File

@ -10,7 +10,8 @@ export const dbserver = (() => {
if (db.ENABLED) {
logger.verbose('connecting');
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.info('ON - dbName: ' + dbs['$dbName']);

34
src/libs/openai.ts Executable file
View 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;
}
}

29
src/libs/redis.client.ts Normal file → Executable file
View File

@ -5,11 +5,6 @@ import { Redis } from '../config/env.config';
import { Logger } from '../config/logger.config';
export class RedisCache {
private readonly logger = new Logger(RedisCache.name);
private client: RedisClientType;
private statusConnection = false;
private instanceName: string;
private redisEnv: Redis;
constructor() {
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) {
this.logger.verbose('set reference: ' + reference);
this.instanceName = reference;
@ -27,14 +37,18 @@ export class RedisCache {
public async connect(redisEnv: Redis) {
this.logger.verbose('Connecting to Redis...');
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));
await this.client.connect();
this.statusConnection = true;
this.redisEnv = redisEnv;
this.logger.verbose(`Connected to ${redisEnv.URI}`);
}
private readonly logger = new Logger(RedisCache.name);
private client: RedisClientType;
public async disconnect() {
if (this.statusConnection) {
await this.client.disconnect();
@ -46,11 +60,14 @@ export class RedisCache {
public async instanceKeys(): Promise<string[]> {
const keys: string[] = [];
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');
for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) {
keys.push(key);
}
} catch (error) {
this.logger.error(error);
this.logger.error('Error fetching instance keys ' + error);
}
return keys;

9
src/libs/redis.ts Executable file
View 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,
})

0
src/libs/socket.server.ts Normal file → Executable file
View File

0
src/libs/sqs.server.ts Normal file → Executable file
View File

0
src/main.ts Normal file → Executable file
View File

49
src/prompts/contabilAgent.ts Executable file
View 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ê 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 Executable file
View 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 Executable file
View 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)
}
}

0
src/utils/server-up.ts Normal file → Executable file
View File

9
src/utils/use-multi-file-auth-state-db.ts Normal file → Executable file
View File

@ -19,7 +19,10 @@ export async function useMultiFileAuthStateDb(
const client = dbserver.getClient();
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);
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 }, JSON.parse(JSON.stringify(data, BufferJSON.replacer)), {
upsert: true,
});
} catch (error) {
@ -47,6 +51,7 @@ export async function useMultiFileAuthStateDb(
if (data?.content_array) {
data = data.content_array;
}
//const data = await collection.findOne({ _id: key });
const creds = JSON.stringify(data);
return JSON.parse(creds, BufferJSON.reviver);
} catch (error) {
@ -101,7 +106,7 @@ export async function useMultiFileAuthStateDb(
},
},
saveCreds: async () => {
return await writeData(creds, 'creds');
return writeData(creds, 'creds');
},
};
}

0
src/utils/use-multi-file-auth-state-redis-db.ts Normal file → Executable file
View File

45
src/validate/validate.schema.ts Normal file → Executable file
View File

@ -987,6 +987,51 @@ export const rabbitmqSchema: JSONSchema7 = {
...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 = {
$id: v4(),
type: 'object',

0
src/whatsapp/abstract/abstract.repository.ts Normal file → Executable file
View File

0
src/whatsapp/abstract/abstract.router.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/chamaai.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/chat.controller.ts Normal file → Executable file
View File

2
src/whatsapp/controllers/chatwoot.controller.ts Normal file → Executable file
View File

@ -72,6 +72,7 @@ export class ChatwootController {
token: '',
sign_msg: false,
name_inbox: '',
id_inbox: '',
webhook_url: '',
};
}
@ -86,6 +87,7 @@ export class ChatwootController {
public async receiveWebhook(instance: InstanceDto, data: any) {
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
const chatwootService = new ChatwootService(waMonitor, this.configService);
return chatwootService.receiveWebhook(instance, data);

0
src/whatsapp/controllers/group.controller.ts Normal file → Executable file
View File

96
src/whatsapp/controllers/instance.controller.ts Normal file → Executable file
View File

@ -13,6 +13,7 @@ import { ChatwootService } from '../services/chatwoot.service';
import { WAMonitoringService } from '../services/monitor.service';
import { ProxyService } from '../services/proxy.service';
import { RabbitmqService } from '../services/rabbitmq.service';
import { OpenaiService } from '../services/openai.service';
import { SettingsService } from '../services/settings.service';
import { SqsService } from '../services/sqs.service';
import { TypebotService } from '../services/typebot.service';
@ -33,6 +34,7 @@ export class InstanceController {
private readonly settingsService: SettingsService,
private readonly websocketService: WebsocketService,
private readonly rabbitmqService: RabbitmqService,
private readonly openaiService: OpenaiService,
private readonly proxyService: ProxyService,
private readonly sqsService: SqsService,
private readonly typebotService: TypebotService,
@ -66,8 +68,14 @@ export class InstanceController {
websocket_events,
rabbitmq_enabled,
rabbitmq_events,
openai_chave,
openai_enabled,
openai_events,
sqs_enabled,
sqs_events,
typebot_url,
typebot,
typebot_expire,
@ -81,6 +89,7 @@ export class InstanceController {
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
this.logger.verbose('checking duplicate token');
await this.authService.checkDuplicateToken(token);
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) {
this.logger.verbose('creating proxy');
try {
@ -266,6 +325,7 @@ export class InstanceController {
}
}
let sqsEvents: string[];
if (sqs_enabled) {
@ -380,6 +440,11 @@ export class InstanceController {
enabled: rabbitmq_enabled,
events: rabbitmqEvents,
},
openai: {
chave: openai_chave,
enabled: openai_enabled,
events: openaiEvents,
},
sqs: {
enabled: sqs_enabled,
events: sqsEvents,
@ -396,7 +461,6 @@ export class InstanceController {
},
settings,
qrcode: getQrcode,
proxy,
};
this.logger.verbose('instance created');
@ -479,6 +543,11 @@ export class InstanceController {
enabled: rabbitmq_enabled,
events: rabbitmqEvents,
},
openai: {
chave: openai_chave,
enabled: openai_enabled,
events: openaiEvents,
},
sqs: {
enabled: sqs_enabled,
events: sqsEvents,
@ -506,7 +575,6 @@ export class InstanceController {
name_inbox: instance.instanceName,
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
},
proxy,
};
} catch (error) {
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) {
try {
this.logger.verbose('requested connectToWhatsapp from ' + instanceName + ' instance');
@ -628,18 +713,21 @@ export class InstanceController {
}
try {
this.waMonitor.waInstances[instanceName]?.removeRabbitmqQueues();
this.waMonitor.waInstances[instanceName]?.removeOpenaiQueues();
if (instance.state === 'connecting') {
this.logger.verbose('logging out instance: ' + 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' } };
}
} catch (error) {
throw new BadRequestException(error.toString());
}

View 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);
}
}

0
src/whatsapp/controllers/proxy.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/rabbitmq.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/sendMessage.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/settings.controller.ts Normal file → Executable file
View File

2
src/whatsapp/controllers/sqs.controller.ts Normal file → Executable file
View File

@ -6,7 +6,7 @@ import { SqsService } from '../services/sqs.service';
const logger = new Logger('SqsController');
export class SqsController {
constructor(private readonly sqsService: SqsService) {}
constructor(private readonly sqsService: SqsService) { }
public async createSqs(instance: InstanceDto, data: SqsDto) {
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');

0
src/whatsapp/controllers/typebot.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/views.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/webhook.controller.ts Normal file → Executable file
View File

0
src/whatsapp/controllers/websocket.controller.ts Normal file → Executable file
View File

0
src/whatsapp/dto/chamaai.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/chat.dto.ts Normal file → Executable file
View File

1
src/whatsapp/dto/chatwoot.dto.ts Normal file → Executable file
View File

@ -4,6 +4,7 @@ export class ChatwootDto {
token?: string;
url?: string;
name_inbox?: string;
id_inbox?: string;
sign_msg?: boolean;
number?: string;
reopen_conversation?: boolean;

View File

@ -0,0 +1,5 @@
export class ContactOpenaiDto {
contact?: string;
enabled: boolean;
owner: string;
}

0
src/whatsapp/dto/group.dto.ts Normal file → Executable file
View File

8
src/whatsapp/dto/instance.dto.ts Normal file → Executable file
View File

@ -23,8 +23,15 @@ export class InstanceDto {
websocket_events?: string[];
rabbitmq_enabled?: boolean;
rabbitmq_events?: string[];
openai_chave?: boolean;
openai_prompts?: string;
openai_enabled?: boolean;
openai_events?: string[];
sqs_enabled?: boolean;
sqs_events?: string[];
typebot_url?: string;
typebot?: string;
typebot_expire?: number;
@ -32,5 +39,6 @@ export class InstanceDto {
typebot_delay_message?: number;
typebot_unknown_message?: string;
typebot_listening_from_me?: boolean;
proxy_enabled?: boolean;
proxy?: string;
}

6
src/whatsapp/dto/openai.dto.ts Executable file
View File

@ -0,0 +1,6 @@
export class OpenaiDto {
chave?: string;
enabled: boolean;
prompts?: string;
events?: string[];
}

0
src/whatsapp/dto/proxy.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/rabbitmq.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/sendMessage.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/settings.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/sqs.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/typebot.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/webhook.dto.ts Normal file → Executable file
View File

0
src/whatsapp/dto/websocket.dto.ts Normal file → Executable file
View File

0
src/whatsapp/guards/auth.guard.ts Normal file → Executable file
View File

4
src/whatsapp/guards/instance.guard.ts Normal file → Executable file
View File

@ -29,7 +29,9 @@ async function getInstance(instanceName: string) {
if (db.ENABLED) {
const collection = dbserver
.getClient()
.db(db.CONNECTION.DB_PREFIX_NAME + '-instances')
.db(
db.CONNECTION.DB_PREFIX_NAME +
db.CONNECTION.DB_PREFIX_FINAL_NAME)
.collection(instanceName);
return exists || (await collection.find({}).toArray()).length > 0;
}

0
src/whatsapp/models/auth.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/chamaai.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/chat.model.ts Normal file → Executable file
View File

2
src/whatsapp/models/chatwoot.model.ts Normal file → Executable file
View File

@ -9,6 +9,7 @@ export class ChatwootRaw {
token?: string;
url?: string;
name_inbox?: string;
id_inbox?: string;
sign_msg?: boolean;
number?: string;
reopen_conversation?: boolean;
@ -22,6 +23,7 @@ const chatwootSchema = new Schema<ChatwootRaw>({
token: { type: String, required: true },
url: { type: String, required: true },
name_inbox: { type: String, required: true },
id_inbox: { type: String, required: true },
sign_msg: { type: Boolean, required: true },
number: { type: String, required: true },
reopen_conversation: { type: Boolean, required: true },

0
src/whatsapp/models/contact.model.ts Normal file → Executable file
View File

View 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;

2
src/whatsapp/models/index.ts Normal file → Executable file
View File

@ -11,3 +11,5 @@ export * from './sqs.model';
export * from './typebot.model';
export * from './webhook.model';
export * from './websocket.model';
export * from './openai.model';
export * from './contactOpenai.model';

0
src/whatsapp/models/message.model.ts Normal file → Executable file
View File

View 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;

0
src/whatsapp/models/proxy.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/rabbitmq.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/settings.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/sqs.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/typebot.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/webhook.model.ts Normal file → Executable file
View File

0
src/whatsapp/models/websocket.model.ts Normal file → Executable file
View File

0
src/whatsapp/repository/auth.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/chamaai.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/chat.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/chatwoot.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/contact.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/message.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/messageUp.repository.ts Normal file → Executable file
View File

View 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;
}
}
}

0
src/whatsapp/repository/proxy.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/rabbitmq.repository.ts Normal file → Executable file
View File

18
src/whatsapp/repository/repository.manager.ts Normal file → Executable file
View File

@ -13,6 +13,7 @@ import { MessageRepository } from './message.repository';
import { MessageUpRepository } from './messageUp.repository';
import { ProxyRepository } from './proxy.repository';
import { RabbitmqRepository } from './rabbitmq.repository';
import { OpenaiRepository } from './openai.repository';
import { SettingsRepository } from './settings.repository';
import { SqsRepository } from './sqs.repository';
import { TypebotRepository } from './typebot.repository';
@ -29,6 +30,8 @@ export class RepositoryBroker {
public readonly settings: SettingsRepository,
public readonly websocket: WebsocketRepository,
public readonly rabbitmq: RabbitmqRepository,
public readonly openai: OpenaiRepository,
public readonly openai_contact: OpenaiRepository,
public readonly sqs: SqsRepository,
public readonly typebot: TypebotRepository,
public readonly proxy: ProxyRepository,
@ -63,9 +66,10 @@ export class RepositoryBroker {
const webhookDir = join(storePath, 'webhook');
const chatwootDir = join(storePath, 'chatwoot');
const settingsDir = join(storePath, 'settings');
const sqsDir = join(storePath, 'sqs');
const websocketDir = join(storePath, 'websocket');
const rabbitmqDir = join(storePath, 'rabbitmq');
const sqsDir = join(storePath, 'sqs');
const openaiDir = join(storePath, 'openai');
const typebotDir = join(storePath, 'typebot');
const proxyDir = join(storePath, 'proxy');
const chamaaiDir = join(storePath, 'chamaai');
@ -103,6 +107,12 @@ export class RepositoryBroker {
this.logger.verbose('creating settings dir: ' + settingsDir);
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)) {
this.logger.verbose('creating websocket dir: ' + websocketDir);
fs.mkdirSync(websocketDir, { recursive: true });
@ -111,9 +121,9 @@ export class RepositoryBroker {
this.logger.verbose('creating rabbitmq dir: ' + rabbitmqDir);
fs.mkdirSync(rabbitmqDir, { recursive: true });
}
if (!fs.existsSync(sqsDir)) {
this.logger.verbose('creating sqs dir: ' + sqsDir);
fs.mkdirSync(sqsDir, { recursive: true });
if (!fs.existsSync(openaiDir)) {
this.logger.verbose('creating openai dir: ' + openaiDir);
fs.mkdirSync(openaiDir, { recursive: true });
}
if (!fs.existsSync(typebotDir)) {
this.logger.verbose('creating typebot dir: ' + typebotDir);

0
src/whatsapp/repository/settings.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/sqs.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/typebot.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/webhook.repository.ts Normal file → Executable file
View File

0
src/whatsapp/repository/websocket.repository.ts Normal file → Executable file
View File

0
src/whatsapp/routers/chamaai.router.ts Normal file → Executable file
View File

0
src/whatsapp/routers/chat.router.ts Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More