mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-26 18:38:39 -06:00
Merge branch 'develop' of https://github.com/codephix/evolution-api into develop
This commit is contained in:
commit
760b3f5fc5
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
|
28
src/config.ts
Executable file → Normal file
28
src/config.ts
Executable file → Normal file
@ -1,14 +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,
|
||||
},
|
||||
}
|
||||
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,
|
||||
},
|
||||
}
|
||||
|
696
src/config/env.config.ts
Executable file → Normal file
696
src/config/env.config.ts
Executable file → Normal file
@ -1,348 +1,348 @@
|
||||
import { isBooleanString } from 'class-validator';
|
||||
import { readFileSync } from 'fs';
|
||||
import { load } from 'js-yaml';
|
||||
import { join } from 'path';
|
||||
|
||||
export type HttpServer = { TYPE: 'http' | 'https'; PORT: number; URL: string };
|
||||
|
||||
export type HttpMethods = 'POST' | 'GET' | 'PUT' | 'DELETE';
|
||||
export type Cors = {
|
||||
ORIGIN: string[];
|
||||
METHODS: HttpMethods[];
|
||||
CREDENTIALS: boolean;
|
||||
};
|
||||
|
||||
export type LogBaileys = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
||||
|
||||
export type LogLevel = 'ERROR' | 'WARN' | 'DEBUG' | 'INFO' | 'LOG' | 'VERBOSE' | 'DARK' | 'WEBHOOKS';
|
||||
|
||||
export type Log = {
|
||||
LEVEL: LogLevel[];
|
||||
COLOR: boolean;
|
||||
BAILEYS: LogBaileys;
|
||||
};
|
||||
|
||||
export type SaveData = {
|
||||
INSTANCE: boolean;
|
||||
NEW_MESSAGE: boolean;
|
||||
MESSAGE_UPDATE: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type StoreConf = {
|
||||
MESSAGES: boolean;
|
||||
MESSAGE_UP: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type CleanStoreConf = {
|
||||
CLEANING_INTERVAL: number;
|
||||
MESSAGES: boolean;
|
||||
MESSAGE_UP: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type DBConnection = {
|
||||
URI: string;
|
||||
DB_PREFIX_NAME: string;
|
||||
DB_PREFIX_FINAL_NAME: string;
|
||||
};
|
||||
export type Database = {
|
||||
CONNECTION: DBConnection;
|
||||
ENABLED: boolean;
|
||||
SAVE_DATA: SaveData;
|
||||
};
|
||||
|
||||
export type Redis = {
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
PREFIX_KEY: string;
|
||||
};
|
||||
|
||||
export type Rabbitmq = {
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
};
|
||||
|
||||
export type Sqs = {
|
||||
ENABLED: boolean;
|
||||
ACCESS_KEY_ID: string;
|
||||
SECRET_ACCESS_KEY: string;
|
||||
ACCOUNT_ID: string;
|
||||
REGION: string;
|
||||
};
|
||||
|
||||
export type Openai = {
|
||||
CHAVE: string;
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
};
|
||||
|
||||
export type Websocket = {
|
||||
ENABLED: boolean;
|
||||
};
|
||||
|
||||
export type Chatwoot = {
|
||||
USE_REPLY_ID: boolean;
|
||||
};
|
||||
|
||||
export type EventsWebhook = {
|
||||
APPLICATION_STARTUP: boolean;
|
||||
QRCODE_UPDATED: boolean;
|
||||
MESSAGES_SET: boolean;
|
||||
MESSAGES_UPSERT: boolean;
|
||||
MESSAGES_UPDATE: boolean;
|
||||
MESSAGES_DELETE: boolean;
|
||||
SEND_MESSAGE: boolean;
|
||||
CONTACTS_SET: boolean;
|
||||
CONTACTS_UPDATE: boolean;
|
||||
CONTACTS_UPSERT: boolean;
|
||||
PRESENCE_UPDATE: boolean;
|
||||
CHATS_SET: boolean;
|
||||
CHATS_UPDATE: boolean;
|
||||
CHATS_DELETE: boolean;
|
||||
CHATS_UPSERT: boolean;
|
||||
CONNECTION_UPDATE: boolean;
|
||||
GROUPS_UPSERT: boolean;
|
||||
GROUP_UPDATE: boolean;
|
||||
GROUP_PARTICIPANTS_UPDATE: boolean;
|
||||
CALL: boolean;
|
||||
NEW_JWT_TOKEN: boolean;
|
||||
TYPEBOT_START: boolean;
|
||||
TYPEBOT_CHANGE_STATUS: boolean;
|
||||
CHAMA_AI_ACTION: boolean;
|
||||
ERRORS: boolean;
|
||||
ERRORS_WEBHOOK: string;
|
||||
};
|
||||
|
||||
export type ApiKey = { KEY: string };
|
||||
export type Jwt = { EXPIRIN_IN: number; SECRET: string };
|
||||
|
||||
export type Auth = {
|
||||
API_KEY: ApiKey;
|
||||
EXPOSE_IN_FETCH_INSTANCES: boolean;
|
||||
JWT: Jwt;
|
||||
TYPE: 'jwt' | 'apikey';
|
||||
};
|
||||
|
||||
export type DelInstance = number | boolean;
|
||||
|
||||
export type GlobalWebhook = {
|
||||
URL: string;
|
||||
ENABLED: boolean;
|
||||
WEBHOOK_BY_EVENTS: boolean;
|
||||
};
|
||||
export type SslConf = { PRIVKEY: string; FULLCHAIN: string };
|
||||
export type Webhook = { GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook };
|
||||
export type ConfigSessionPhone = { CLIENT: string; NAME: string };
|
||||
export type QrCode = { LIMIT: number; COLOR: string };
|
||||
export type Typebot = { API_VERSION: string };
|
||||
export type Production = boolean;
|
||||
|
||||
export interface Env {
|
||||
SERVER: HttpServer;
|
||||
CORS: Cors;
|
||||
SSL_CONF: SslConf;
|
||||
STORE: StoreConf;
|
||||
CLEAN_STORE: CleanStoreConf;
|
||||
DATABASE: Database;
|
||||
REDIS: Redis;
|
||||
RABBITMQ: Rabbitmq;
|
||||
SQS: Sqs;
|
||||
OPENAI: Openai;
|
||||
WEBSOCKET: Websocket;
|
||||
LOG: Log;
|
||||
DEL_INSTANCE: DelInstance;
|
||||
WEBHOOK: Webhook;
|
||||
CONFIG_SESSION_PHONE: ConfigSessionPhone;
|
||||
QRCODE: QrCode;
|
||||
TYPEBOT: Typebot;
|
||||
AUTHENTICATION: Auth;
|
||||
PRODUCTION?: Production;
|
||||
CHATWOOT?: Chatwoot;
|
||||
}
|
||||
|
||||
export type Key = keyof Env;
|
||||
|
||||
export class ConfigService {
|
||||
constructor() {
|
||||
this.loadEnv();
|
||||
}
|
||||
|
||||
private env: Env;
|
||||
|
||||
public get<T = any>(key: Key) {
|
||||
return this.env[key] as T;
|
||||
}
|
||||
|
||||
private loadEnv() {
|
||||
this.env = !(process.env?.DOCKER_ENV === 'true') ? this.envYaml() : this.envProcess();
|
||||
this.env.PRODUCTION = process.env?.NODE_ENV === 'PROD';
|
||||
if (process.env?.DOCKER_ENV === 'true') {
|
||||
this.env.SERVER.TYPE = 'http';
|
||||
this.env.SERVER.PORT = 8080;
|
||||
}
|
||||
}
|
||||
|
||||
private envYaml(): Env {
|
||||
return load(readFileSync(join(process.cwd(), 'src', 'env.yml'), { encoding: 'utf-8' })) as Env;
|
||||
}
|
||||
|
||||
private envProcess(): Env {
|
||||
return {
|
||||
SERVER: {
|
||||
TYPE: process.env.SERVER_TYPE as 'http' | 'https',
|
||||
PORT: Number.parseInt(process.env.SERVER_PORT) || 8080,
|
||||
URL: process.env.SERVER_URL,
|
||||
},
|
||||
CORS: {
|
||||
ORIGIN: process.env.CORS_ORIGIN.split(',') || ['*'],
|
||||
METHODS: (process.env.CORS_METHODS.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'],
|
||||
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
|
||||
},
|
||||
SSL_CONF: {
|
||||
PRIVKEY: process.env?.SSL_CONF_PRIVKEY || '',
|
||||
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN || '',
|
||||
},
|
||||
STORE: {
|
||||
MESSAGES: process.env?.STORE_MESSAGES === 'true',
|
||||
MESSAGE_UP: process.env?.STORE_MESSAGE_UP === 'true',
|
||||
CONTACTS: process.env?.STORE_CONTACTS === 'true',
|
||||
CHATS: process.env?.STORE_CHATS === 'true',
|
||||
},
|
||||
CLEAN_STORE: {
|
||||
CLEANING_INTERVAL: Number.isInteger(process.env?.CLEAN_STORE_CLEANING_TERMINAL)
|
||||
? Number.parseInt(process.env.CLEAN_STORE_CLEANING_TERMINAL)
|
||||
: 7200,
|
||||
MESSAGES: process.env?.CLEAN_STORE_MESSAGES === 'true',
|
||||
MESSAGE_UP: process.env?.CLEAN_STORE_MESSAGE_UP === 'true',
|
||||
CONTACTS: process.env?.CLEAN_STORE_CONTACTS === 'true',
|
||||
CHATS: process.env?.CLEAN_STORE_CHATS === 'true',
|
||||
},
|
||||
DATABASE: {
|
||||
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: {
|
||||
INSTANCE: process.env?.DATABASE_SAVE_DATA_INSTANCE === 'true',
|
||||
NEW_MESSAGE: process.env?.DATABASE_SAVE_DATA_NEW_MESSAGE === 'true',
|
||||
MESSAGE_UPDATE: process.env?.DATABASE_SAVE_MESSAGE_UPDATE === 'true',
|
||||
CONTACTS: process.env?.DATABASE_SAVE_DATA_CONTACTS === 'true',
|
||||
CHATS: process.env?.DATABASE_SAVE_DATA_CHATS === 'true',
|
||||
},
|
||||
},
|
||||
REDIS: {
|
||||
ENABLED: process.env?.REDIS_ENABLED === 'true',
|
||||
URI: process.env.REDIS_URI || '',
|
||||
PREFIX_KEY: process.env.REDIS_PREFIX_KEY || 'evolution',
|
||||
},
|
||||
RABBITMQ: {
|
||||
ENABLED: process.env?.RABBITMQ_ENABLED === 'true',
|
||||
URI: process.env.RABBITMQ_URI || '',
|
||||
},
|
||||
SQS: {
|
||||
ENABLED: process.env?.SQS_ENABLED === 'true',
|
||||
ACCESS_KEY_ID: process.env.SQS_ACCESS_KEY_ID || '',
|
||||
SECRET_ACCESS_KEY: process.env.SQS_SECRET_ACCESS_KEY || '',
|
||||
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',
|
||||
},
|
||||
LOG: {
|
||||
LEVEL: (process.env?.LOG_LEVEL.split(',') as LogLevel[]) || [
|
||||
'ERROR',
|
||||
'WARN',
|
||||
'DEBUG',
|
||||
'INFO',
|
||||
'LOG',
|
||||
'VERBOSE',
|
||||
'DARK',
|
||||
'WEBHOOKS',
|
||||
],
|
||||
COLOR: process.env?.LOG_COLOR === 'true',
|
||||
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
|
||||
},
|
||||
DEL_INSTANCE: isBooleanString(process.env?.DEL_INSTANCE)
|
||||
? process.env.DEL_INSTANCE === 'true'
|
||||
: Number.parseInt(process.env.DEL_INSTANCE) || false,
|
||||
WEBHOOK: {
|
||||
GLOBAL: {
|
||||
URL: process.env?.WEBHOOK_GLOBAL_URL || '',
|
||||
ENABLED: process.env?.WEBHOOK_GLOBAL_ENABLED === 'true',
|
||||
WEBHOOK_BY_EVENTS: process.env?.WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS === 'true',
|
||||
},
|
||||
EVENTS: {
|
||||
APPLICATION_STARTUP: process.env?.WEBHOOK_EVENTS_APPLICATION_STARTUP === 'true',
|
||||
QRCODE_UPDATED: process.env?.WEBHOOK_EVENTS_QRCODE_UPDATED === 'true',
|
||||
MESSAGES_SET: process.env?.WEBHOOK_EVENTS_MESSAGES_SET === 'true',
|
||||
MESSAGES_UPSERT: process.env?.WEBHOOK_EVENTS_MESSAGES_UPSERT === 'true',
|
||||
MESSAGES_UPDATE: process.env?.WEBHOOK_EVENTS_MESSAGES_UPDATE === 'true',
|
||||
MESSAGES_DELETE: process.env?.WEBHOOK_EVENTS_MESSAGES_DELETE === 'true',
|
||||
SEND_MESSAGE: process.env?.WEBHOOK_EVENTS_SEND_MESSAGE === 'true',
|
||||
CONTACTS_SET: process.env?.WEBHOOK_EVENTS_CONTACTS_SET === 'true',
|
||||
CONTACTS_UPDATE: process.env?.WEBHOOK_EVENTS_CONTACTS_UPDATE === 'true',
|
||||
CONTACTS_UPSERT: process.env?.WEBHOOK_EVENTS_CONTACTS_UPSERT === 'true',
|
||||
PRESENCE_UPDATE: process.env?.WEBHOOK_EVENTS_PRESENCE_UPDATE === 'true',
|
||||
CHATS_SET: process.env?.WEBHOOK_EVENTS_CHATS_SET === 'true',
|
||||
CHATS_UPDATE: process.env?.WEBHOOK_EVENTS_CHATS_UPDATE === 'true',
|
||||
CHATS_UPSERT: process.env?.WEBHOOK_EVENTS_CHATS_UPSERT === 'true',
|
||||
CHATS_DELETE: process.env?.WEBHOOK_EVENTS_CHATS_DELETE === 'true',
|
||||
CONNECTION_UPDATE: process.env?.WEBHOOK_EVENTS_CONNECTION_UPDATE === 'true',
|
||||
GROUPS_UPSERT: process.env?.WEBHOOK_EVENTS_GROUPS_UPSERT === 'true',
|
||||
GROUP_UPDATE: process.env?.WEBHOOK_EVENTS_GROUPS_UPDATE === 'true',
|
||||
GROUP_PARTICIPANTS_UPDATE: process.env?.WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE === 'true',
|
||||
CALL: process.env?.WEBHOOK_EVENTS_CALL === 'true',
|
||||
NEW_JWT_TOKEN: process.env?.WEBHOOK_EVENTS_NEW_JWT_TOKEN === 'true',
|
||||
TYPEBOT_START: process.env?.WEBHOOK_EVENTS_TYPEBOT_START === 'true',
|
||||
TYPEBOT_CHANGE_STATUS: process.env?.WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS === 'true',
|
||||
CHAMA_AI_ACTION: process.env?.WEBHOOK_EVENTS_CHAMA_AI_ACTION === 'true',
|
||||
ERRORS: process.env?.WEBHOOK_EVENTS_ERRORS === 'true',
|
||||
ERRORS_WEBHOOK: process.env?.WEBHOOK_EVENTS_ERRORS_WEBHOOK || '',
|
||||
},
|
||||
},
|
||||
CONFIG_SESSION_PHONE: {
|
||||
CLIENT: process.env?.CONFIG_SESSION_PHONE_CLIENT || 'Evolution API',
|
||||
NAME: process.env?.CONFIG_SESSION_PHONE_NAME || 'Chrome',
|
||||
},
|
||||
QRCODE: {
|
||||
LIMIT: Number.parseInt(process.env.QRCODE_LIMIT) || 30,
|
||||
COLOR: process.env.QRCODE_COLOR || '#198754',
|
||||
},
|
||||
TYPEBOT: {
|
||||
API_VERSION: process.env?.TYPEBOT_API_VERSION || 'v1',
|
||||
},
|
||||
AUTHENTICATION: {
|
||||
TYPE: process.env.AUTHENTICATION_TYPE as 'apikey',
|
||||
API_KEY: {
|
||||
KEY: process.env.AUTHENTICATION_API_KEY || 'BQYHJGJHJ',
|
||||
},
|
||||
EXPOSE_IN_FETCH_INSTANCES: process.env?.AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES === 'true',
|
||||
JWT: {
|
||||
EXPIRIN_IN: Number.isInteger(process.env?.AUTHENTICATION_JWT_EXPIRIN_IN)
|
||||
? Number.parseInt(process.env.AUTHENTICATION_JWT_EXPIRIN_IN)
|
||||
: 3600,
|
||||
SECRET: process.env.AUTHENTICATION_JWT_SECRET || 'L=0YWt]b2w[WF>#>:&E`',
|
||||
},
|
||||
},
|
||||
CHATWOOT: {
|
||||
USE_REPLY_ID: process.env?.USE_REPLY_ID === 'true',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const configService = new ConfigService();
|
||||
import { isBooleanString } from 'class-validator';
|
||||
import { readFileSync } from 'fs';
|
||||
import { load } from 'js-yaml';
|
||||
import { join } from 'path';
|
||||
|
||||
export type HttpServer = { TYPE: 'http' | 'https'; PORT: number; URL: string };
|
||||
|
||||
export type HttpMethods = 'POST' | 'GET' | 'PUT' | 'DELETE';
|
||||
export type Cors = {
|
||||
ORIGIN: string[];
|
||||
METHODS: HttpMethods[];
|
||||
CREDENTIALS: boolean;
|
||||
};
|
||||
|
||||
export type LogBaileys = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
||||
|
||||
export type LogLevel = 'ERROR' | 'WARN' | 'DEBUG' | 'INFO' | 'LOG' | 'VERBOSE' | 'DARK' | 'WEBHOOKS';
|
||||
|
||||
export type Log = {
|
||||
LEVEL: LogLevel[];
|
||||
COLOR: boolean;
|
||||
BAILEYS: LogBaileys;
|
||||
};
|
||||
|
||||
export type SaveData = {
|
||||
INSTANCE: boolean;
|
||||
NEW_MESSAGE: boolean;
|
||||
MESSAGE_UPDATE: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type StoreConf = {
|
||||
MESSAGES: boolean;
|
||||
MESSAGE_UP: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type CleanStoreConf = {
|
||||
CLEANING_INTERVAL: number;
|
||||
MESSAGES: boolean;
|
||||
MESSAGE_UP: boolean;
|
||||
CONTACTS: boolean;
|
||||
CHATS: boolean;
|
||||
};
|
||||
|
||||
export type DBConnection = {
|
||||
URI: string;
|
||||
DB_PREFIX_NAME: string;
|
||||
DB_PREFIX_FINAL_NAME: string;
|
||||
};
|
||||
export type Database = {
|
||||
CONNECTION: DBConnection;
|
||||
ENABLED: boolean;
|
||||
SAVE_DATA: SaveData;
|
||||
};
|
||||
|
||||
export type Redis = {
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
PREFIX_KEY: string;
|
||||
};
|
||||
|
||||
export type Rabbitmq = {
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
};
|
||||
|
||||
export type Sqs = {
|
||||
ENABLED: boolean;
|
||||
ACCESS_KEY_ID: string;
|
||||
SECRET_ACCESS_KEY: string;
|
||||
ACCOUNT_ID: string;
|
||||
REGION: string;
|
||||
};
|
||||
|
||||
export type Openai = {
|
||||
CHAVE: string;
|
||||
ENABLED: boolean;
|
||||
URI: string;
|
||||
};
|
||||
|
||||
export type Websocket = {
|
||||
ENABLED: boolean;
|
||||
};
|
||||
|
||||
export type Chatwoot = {
|
||||
USE_REPLY_ID: boolean;
|
||||
};
|
||||
|
||||
export type EventsWebhook = {
|
||||
APPLICATION_STARTUP: boolean;
|
||||
QRCODE_UPDATED: boolean;
|
||||
MESSAGES_SET: boolean;
|
||||
MESSAGES_UPSERT: boolean;
|
||||
MESSAGES_UPDATE: boolean;
|
||||
MESSAGES_DELETE: boolean;
|
||||
SEND_MESSAGE: boolean;
|
||||
CONTACTS_SET: boolean;
|
||||
CONTACTS_UPDATE: boolean;
|
||||
CONTACTS_UPSERT: boolean;
|
||||
PRESENCE_UPDATE: boolean;
|
||||
CHATS_SET: boolean;
|
||||
CHATS_UPDATE: boolean;
|
||||
CHATS_DELETE: boolean;
|
||||
CHATS_UPSERT: boolean;
|
||||
CONNECTION_UPDATE: boolean;
|
||||
GROUPS_UPSERT: boolean;
|
||||
GROUP_UPDATE: boolean;
|
||||
GROUP_PARTICIPANTS_UPDATE: boolean;
|
||||
CALL: boolean;
|
||||
NEW_JWT_TOKEN: boolean;
|
||||
TYPEBOT_START: boolean;
|
||||
TYPEBOT_CHANGE_STATUS: boolean;
|
||||
CHAMA_AI_ACTION: boolean;
|
||||
ERRORS: boolean;
|
||||
ERRORS_WEBHOOK: string;
|
||||
};
|
||||
|
||||
export type ApiKey = { KEY: string };
|
||||
export type Jwt = { EXPIRIN_IN: number; SECRET: string };
|
||||
|
||||
export type Auth = {
|
||||
API_KEY: ApiKey;
|
||||
EXPOSE_IN_FETCH_INSTANCES: boolean;
|
||||
JWT: Jwt;
|
||||
TYPE: 'jwt' | 'apikey';
|
||||
};
|
||||
|
||||
export type DelInstance = number | boolean;
|
||||
|
||||
export type GlobalWebhook = {
|
||||
URL: string;
|
||||
ENABLED: boolean;
|
||||
WEBHOOK_BY_EVENTS: boolean;
|
||||
};
|
||||
export type SslConf = { PRIVKEY: string; FULLCHAIN: string };
|
||||
export type Webhook = { GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook };
|
||||
export type ConfigSessionPhone = { CLIENT: string; NAME: string };
|
||||
export type QrCode = { LIMIT: number; COLOR: string };
|
||||
export type Typebot = { API_VERSION: string };
|
||||
export type Production = boolean;
|
||||
|
||||
export interface Env {
|
||||
SERVER: HttpServer;
|
||||
CORS: Cors;
|
||||
SSL_CONF: SslConf;
|
||||
STORE: StoreConf;
|
||||
CLEAN_STORE: CleanStoreConf;
|
||||
DATABASE: Database;
|
||||
REDIS: Redis;
|
||||
RABBITMQ: Rabbitmq;
|
||||
SQS: Sqs;
|
||||
OPENAI: Openai;
|
||||
WEBSOCKET: Websocket;
|
||||
LOG: Log;
|
||||
DEL_INSTANCE: DelInstance;
|
||||
WEBHOOK: Webhook;
|
||||
CONFIG_SESSION_PHONE: ConfigSessionPhone;
|
||||
QRCODE: QrCode;
|
||||
TYPEBOT: Typebot;
|
||||
AUTHENTICATION: Auth;
|
||||
PRODUCTION?: Production;
|
||||
CHATWOOT?: Chatwoot;
|
||||
}
|
||||
|
||||
export type Key = keyof Env;
|
||||
|
||||
export class ConfigService {
|
||||
constructor() {
|
||||
this.loadEnv();
|
||||
}
|
||||
|
||||
private env: Env;
|
||||
|
||||
public get<T = any>(key: Key) {
|
||||
return this.env[key] as T;
|
||||
}
|
||||
|
||||
private loadEnv() {
|
||||
this.env = !(process.env?.DOCKER_ENV === 'true') ? this.envYaml() : this.envProcess();
|
||||
this.env.PRODUCTION = process.env?.NODE_ENV === 'PROD';
|
||||
if (process.env?.DOCKER_ENV === 'true') {
|
||||
this.env.SERVER.TYPE = 'http';
|
||||
this.env.SERVER.PORT = 8080;
|
||||
}
|
||||
}
|
||||
|
||||
private envYaml(): Env {
|
||||
return load(readFileSync(join(process.cwd(), 'src', 'env.yml'), { encoding: 'utf-8' })) as Env;
|
||||
}
|
||||
|
||||
private envProcess(): Env {
|
||||
return {
|
||||
SERVER: {
|
||||
TYPE: process.env.SERVER_TYPE as 'http' | 'https',
|
||||
PORT: Number.parseInt(process.env.SERVER_PORT) || 8080,
|
||||
URL: process.env.SERVER_URL,
|
||||
},
|
||||
CORS: {
|
||||
ORIGIN: process.env.CORS_ORIGIN.split(',') || ['*'],
|
||||
METHODS: (process.env.CORS_METHODS.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'],
|
||||
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
|
||||
},
|
||||
SSL_CONF: {
|
||||
PRIVKEY: process.env?.SSL_CONF_PRIVKEY || '',
|
||||
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN || '',
|
||||
},
|
||||
STORE: {
|
||||
MESSAGES: process.env?.STORE_MESSAGES === 'true',
|
||||
MESSAGE_UP: process.env?.STORE_MESSAGE_UP === 'true',
|
||||
CONTACTS: process.env?.STORE_CONTACTS === 'true',
|
||||
CHATS: process.env?.STORE_CHATS === 'true',
|
||||
},
|
||||
CLEAN_STORE: {
|
||||
CLEANING_INTERVAL: Number.isInteger(process.env?.CLEAN_STORE_CLEANING_TERMINAL)
|
||||
? Number.parseInt(process.env.CLEAN_STORE_CLEANING_TERMINAL)
|
||||
: 7200,
|
||||
MESSAGES: process.env?.CLEAN_STORE_MESSAGES === 'true',
|
||||
MESSAGE_UP: process.env?.CLEAN_STORE_MESSAGE_UP === 'true',
|
||||
CONTACTS: process.env?.CLEAN_STORE_CONTACTS === 'true',
|
||||
CHATS: process.env?.CLEAN_STORE_CHATS === 'true',
|
||||
},
|
||||
DATABASE: {
|
||||
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: {
|
||||
INSTANCE: process.env?.DATABASE_SAVE_DATA_INSTANCE === 'true',
|
||||
NEW_MESSAGE: process.env?.DATABASE_SAVE_DATA_NEW_MESSAGE === 'true',
|
||||
MESSAGE_UPDATE: process.env?.DATABASE_SAVE_MESSAGE_UPDATE === 'true',
|
||||
CONTACTS: process.env?.DATABASE_SAVE_DATA_CONTACTS === 'true',
|
||||
CHATS: process.env?.DATABASE_SAVE_DATA_CHATS === 'true',
|
||||
},
|
||||
},
|
||||
REDIS: {
|
||||
ENABLED: process.env?.REDIS_ENABLED === 'true',
|
||||
URI: process.env.REDIS_URI || '',
|
||||
PREFIX_KEY: process.env.REDIS_PREFIX_KEY || 'evolution',
|
||||
},
|
||||
RABBITMQ: {
|
||||
ENABLED: process.env?.RABBITMQ_ENABLED === 'true',
|
||||
URI: process.env.RABBITMQ_URI || '',
|
||||
},
|
||||
SQS: {
|
||||
ENABLED: process.env?.SQS_ENABLED === 'true',
|
||||
ACCESS_KEY_ID: process.env.SQS_ACCESS_KEY_ID || '',
|
||||
SECRET_ACCESS_KEY: process.env.SQS_SECRET_ACCESS_KEY || '',
|
||||
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',
|
||||
},
|
||||
LOG: {
|
||||
LEVEL: (process.env?.LOG_LEVEL.split(',') as LogLevel[]) || [
|
||||
'ERROR',
|
||||
'WARN',
|
||||
'DEBUG',
|
||||
'INFO',
|
||||
'LOG',
|
||||
'VERBOSE',
|
||||
'DARK',
|
||||
'WEBHOOKS',
|
||||
],
|
||||
COLOR: process.env?.LOG_COLOR === 'true',
|
||||
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
|
||||
},
|
||||
DEL_INSTANCE: isBooleanString(process.env?.DEL_INSTANCE)
|
||||
? process.env.DEL_INSTANCE === 'true'
|
||||
: Number.parseInt(process.env.DEL_INSTANCE) || false,
|
||||
WEBHOOK: {
|
||||
GLOBAL: {
|
||||
URL: process.env?.WEBHOOK_GLOBAL_URL || '',
|
||||
ENABLED: process.env?.WEBHOOK_GLOBAL_ENABLED === 'true',
|
||||
WEBHOOK_BY_EVENTS: process.env?.WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS === 'true',
|
||||
},
|
||||
EVENTS: {
|
||||
APPLICATION_STARTUP: process.env?.WEBHOOK_EVENTS_APPLICATION_STARTUP === 'true',
|
||||
QRCODE_UPDATED: process.env?.WEBHOOK_EVENTS_QRCODE_UPDATED === 'true',
|
||||
MESSAGES_SET: process.env?.WEBHOOK_EVENTS_MESSAGES_SET === 'true',
|
||||
MESSAGES_UPSERT: process.env?.WEBHOOK_EVENTS_MESSAGES_UPSERT === 'true',
|
||||
MESSAGES_UPDATE: process.env?.WEBHOOK_EVENTS_MESSAGES_UPDATE === 'true',
|
||||
MESSAGES_DELETE: process.env?.WEBHOOK_EVENTS_MESSAGES_DELETE === 'true',
|
||||
SEND_MESSAGE: process.env?.WEBHOOK_EVENTS_SEND_MESSAGE === 'true',
|
||||
CONTACTS_SET: process.env?.WEBHOOK_EVENTS_CONTACTS_SET === 'true',
|
||||
CONTACTS_UPDATE: process.env?.WEBHOOK_EVENTS_CONTACTS_UPDATE === 'true',
|
||||
CONTACTS_UPSERT: process.env?.WEBHOOK_EVENTS_CONTACTS_UPSERT === 'true',
|
||||
PRESENCE_UPDATE: process.env?.WEBHOOK_EVENTS_PRESENCE_UPDATE === 'true',
|
||||
CHATS_SET: process.env?.WEBHOOK_EVENTS_CHATS_SET === 'true',
|
||||
CHATS_UPDATE: process.env?.WEBHOOK_EVENTS_CHATS_UPDATE === 'true',
|
||||
CHATS_UPSERT: process.env?.WEBHOOK_EVENTS_CHATS_UPSERT === 'true',
|
||||
CHATS_DELETE: process.env?.WEBHOOK_EVENTS_CHATS_DELETE === 'true',
|
||||
CONNECTION_UPDATE: process.env?.WEBHOOK_EVENTS_CONNECTION_UPDATE === 'true',
|
||||
GROUPS_UPSERT: process.env?.WEBHOOK_EVENTS_GROUPS_UPSERT === 'true',
|
||||
GROUP_UPDATE: process.env?.WEBHOOK_EVENTS_GROUPS_UPDATE === 'true',
|
||||
GROUP_PARTICIPANTS_UPDATE: process.env?.WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE === 'true',
|
||||
CALL: process.env?.WEBHOOK_EVENTS_CALL === 'true',
|
||||
NEW_JWT_TOKEN: process.env?.WEBHOOK_EVENTS_NEW_JWT_TOKEN === 'true',
|
||||
TYPEBOT_START: process.env?.WEBHOOK_EVENTS_TYPEBOT_START === 'true',
|
||||
TYPEBOT_CHANGE_STATUS: process.env?.WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS === 'true',
|
||||
CHAMA_AI_ACTION: process.env?.WEBHOOK_EVENTS_CHAMA_AI_ACTION === 'true',
|
||||
ERRORS: process.env?.WEBHOOK_EVENTS_ERRORS === 'true',
|
||||
ERRORS_WEBHOOK: process.env?.WEBHOOK_EVENTS_ERRORS_WEBHOOK || '',
|
||||
},
|
||||
},
|
||||
CONFIG_SESSION_PHONE: {
|
||||
CLIENT: process.env?.CONFIG_SESSION_PHONE_CLIENT || 'Evolution API',
|
||||
NAME: process.env?.CONFIG_SESSION_PHONE_NAME || 'Chrome',
|
||||
},
|
||||
QRCODE: {
|
||||
LIMIT: Number.parseInt(process.env.QRCODE_LIMIT) || 30,
|
||||
COLOR: process.env.QRCODE_COLOR || '#198754',
|
||||
},
|
||||
TYPEBOT: {
|
||||
API_VERSION: process.env?.TYPEBOT_API_VERSION || 'v1',
|
||||
},
|
||||
AUTHENTICATION: {
|
||||
TYPE: process.env.AUTHENTICATION_TYPE as 'apikey',
|
||||
API_KEY: {
|
||||
KEY: process.env.AUTHENTICATION_API_KEY || 'BQYHJGJHJ',
|
||||
},
|
||||
EXPOSE_IN_FETCH_INSTANCES: process.env?.AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES === 'true',
|
||||
JWT: {
|
||||
EXPIRIN_IN: Number.isInteger(process.env?.AUTHENTICATION_JWT_EXPIRIN_IN)
|
||||
? Number.parseInt(process.env.AUTHENTICATION_JWT_EXPIRIN_IN)
|
||||
: 3600,
|
||||
SECRET: process.env.AUTHENTICATION_JWT_SECRET || 'L=0YWt]b2w[WF>#>:&E`',
|
||||
},
|
||||
},
|
||||
CHATWOOT: {
|
||||
USE_REPLY_ID: process.env?.USE_REPLY_ID === 'true',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const configService = new ConfigService();
|
||||
|
358
src/dev-env.yml
Executable file → Normal file
358
src/dev-env.yml
Executable file → Normal file
@ -1,179 +1,179 @@
|
||||
# ⚠️
|
||||
# ⚠️ ALL SETTINGS DEFINED IN THIS FILE ARE APPLIED TO ALL INSTANCES.
|
||||
# ⚠️
|
||||
|
||||
# ⚠️ RENAME THIS FILE TO env.yml
|
||||
|
||||
# Choose the server type for the application
|
||||
SERVER:
|
||||
TYPE: http # https
|
||||
PORT: 3333 # 443
|
||||
URL: 127.0.0.1
|
||||
|
||||
CORS:
|
||||
ORIGIN:
|
||||
- "*"
|
||||
# - yourdomain.com
|
||||
METHODS:
|
||||
- POST
|
||||
- GET
|
||||
- PUT
|
||||
- DELETE
|
||||
CREDENTIALS: true
|
||||
|
||||
# Install ssl certificate and replace string <domain> with domain name
|
||||
# Access: https://certbot.eff.org/instructions?ws=other&os=ubuntufocal
|
||||
SSL_CONF:
|
||||
PRIVKEY: /etc/letsencrypt/live/<domain>/privkey.pem
|
||||
FULLCHAIN: /etc/letsencrypt/live/<domain>/fullchain.pem
|
||||
|
||||
# Determine the logs to be displayed
|
||||
LOG:
|
||||
LEVEL:
|
||||
- ERROR
|
||||
- WARN
|
||||
- DEBUG
|
||||
- INFO
|
||||
- LOG
|
||||
- VERBOSE
|
||||
- DARK
|
||||
- WEBHOOKS
|
||||
COLOR: true
|
||||
BAILEYS: error # fatal | error | warn | info | debug | trace
|
||||
|
||||
# Determine how long the instance should be deleted from memory in case of no connection.
|
||||
# Default time: 5 minutes
|
||||
# If you don't even want an expiration, enter the value false
|
||||
DEL_INSTANCE: false # or false
|
||||
|
||||
# Temporary data storage
|
||||
STORE:
|
||||
MESSAGES: false
|
||||
MESSAGE_UP: false
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
CLEAN_STORE:
|
||||
CLEANING_INTERVAL: 7200 # 7200 seconds === 2h
|
||||
MESSAGES: true
|
||||
MESSAGE_UP: true
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
# Permanent data storage
|
||||
DATABASE:
|
||||
ENABLED: true
|
||||
CONNECTION:
|
||||
URI: "mongodb://root:root@localhost:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true"
|
||||
|
||||
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: true
|
||||
NEW_MESSAGE: false
|
||||
MESSAGE_UPDATE: false
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
REDIS:
|
||||
ENABLED: false
|
||||
URI: "redis://localhost:6379"
|
||||
PREFIX_KEY: "evolution"
|
||||
|
||||
RABBITMQ:
|
||||
ENABLED: false
|
||||
URI: "amqp://guest:guest@localhost:5672"
|
||||
|
||||
OPENAI:
|
||||
CHAVE: ""
|
||||
ENABLED: false
|
||||
PROMPTS: false
|
||||
URI: ""
|
||||
|
||||
SQS:
|
||||
ENABLED: false
|
||||
ACCESS_KEY_ID: ""
|
||||
SECRET_ACCESS_KEY: ""
|
||||
ACCOUNT_ID: ""
|
||||
REGION: "us-east-1"
|
||||
|
||||
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: ""
|
||||
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
|
||||
# Automatically maps webhook paths
|
||||
# Set the events you want to hear
|
||||
EVENTS:
|
||||
APPLICATION_STARTUP: false
|
||||
QRCODE_UPDATED: true
|
||||
MESSAGES_SET: true
|
||||
MESSAGES_UPSERT: true
|
||||
MESSAGES_UPDATE: true
|
||||
MESSAGES_DELETE: true
|
||||
SEND_MESSAGE: true
|
||||
CONTACTS_SET: true
|
||||
CONTACTS_UPSERT: true
|
||||
CONTACTS_UPDATE: true
|
||||
PRESENCE_UPDATE: true
|
||||
CHATS_SET: true
|
||||
CHATS_UPSERT: true
|
||||
CHATS_UPDATE: true
|
||||
CHATS_DELETE: true
|
||||
GROUPS_UPSERT: true
|
||||
GROUP_UPDATE: true
|
||||
GROUP_PARTICIPANTS_UPDATE: true
|
||||
CONNECTION_UPDATE: true
|
||||
CALL: true
|
||||
# This event fires every time a new token is requested via the refresh route
|
||||
NEW_JWT_TOKEN: false
|
||||
# This events is used with Typebot
|
||||
TYPEBOT_START: false
|
||||
TYPEBOT_CHANGE_STATUS: false
|
||||
# This event is used with Chama AI
|
||||
CHAMA_AI_ACTION: false
|
||||
# This event is used to send errors to the webhook
|
||||
ERRORS: false
|
||||
ERRORS_WEBHOOK: ""
|
||||
|
||||
CONFIG_SESSION_PHONE:
|
||||
# Name that will be displayed on smartphone connection
|
||||
CLIENT: "Evolution API"
|
||||
NAME: Chrome # Chrome | Firefox | Edge | Opera | Safari
|
||||
|
||||
# Set qrcode display limit
|
||||
QRCODE:
|
||||
LIMIT: 30
|
||||
COLOR: "#198754"
|
||||
|
||||
# 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
|
||||
AUTHENTICATION:
|
||||
TYPE: apikey # jwt or apikey
|
||||
# Define a global apikey to access all instances
|
||||
API_KEY:
|
||||
# OBS: This key must be inserted in the request header to create an instance.
|
||||
KEY: B6D711FCDE4D4FD5936544120E713976
|
||||
# Expose the api key on return from fetch instances
|
||||
EXPOSE_IN_FETCH_INSTANCES: true
|
||||
# Set the secret key to encrypt and decrypt your token and its expiration time.
|
||||
JWT:
|
||||
EXPIRIN_IN: 0 # seconds - 3600s === 1h | zero (0) - never expires
|
||||
SECRET: L=0YWt]b2w[WF>#>:&E`
|
||||
|
||||
# Configure to chatwoot
|
||||
CHATWOOT:
|
||||
USE_REPLY_ID: false
|
||||
# ⚠️
|
||||
# ⚠️ ALL SETTINGS DEFINED IN THIS FILE ARE APPLIED TO ALL INSTANCES.
|
||||
# ⚠️
|
||||
|
||||
# ⚠️ RENAME THIS FILE TO env.yml
|
||||
|
||||
# Choose the server type for the application
|
||||
SERVER:
|
||||
TYPE: http # https
|
||||
PORT: 3333 # 443
|
||||
URL: 127.0.0.1
|
||||
|
||||
CORS:
|
||||
ORIGIN:
|
||||
- "*"
|
||||
# - yourdomain.com
|
||||
METHODS:
|
||||
- POST
|
||||
- GET
|
||||
- PUT
|
||||
- DELETE
|
||||
CREDENTIALS: true
|
||||
|
||||
# Install ssl certificate and replace string <domain> with domain name
|
||||
# Access: https://certbot.eff.org/instructions?ws=other&os=ubuntufocal
|
||||
SSL_CONF:
|
||||
PRIVKEY: /etc/letsencrypt/live/<domain>/privkey.pem
|
||||
FULLCHAIN: /etc/letsencrypt/live/<domain>/fullchain.pem
|
||||
|
||||
# Determine the logs to be displayed
|
||||
LOG:
|
||||
LEVEL:
|
||||
- ERROR
|
||||
- WARN
|
||||
- DEBUG
|
||||
- INFO
|
||||
- LOG
|
||||
- VERBOSE
|
||||
- DARK
|
||||
- WEBHOOKS
|
||||
COLOR: true
|
||||
BAILEYS: error # fatal | error | warn | info | debug | trace
|
||||
|
||||
# Determine how long the instance should be deleted from memory in case of no connection.
|
||||
# Default time: 5 minutes
|
||||
# If you don't even want an expiration, enter the value false
|
||||
DEL_INSTANCE: false # or false
|
||||
|
||||
# Temporary data storage
|
||||
STORE:
|
||||
MESSAGES: false
|
||||
MESSAGE_UP: false
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
CLEAN_STORE:
|
||||
CLEANING_INTERVAL: 7200 # 7200 seconds === 2h
|
||||
MESSAGES: true
|
||||
MESSAGE_UP: true
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
# Permanent data storage
|
||||
DATABASE:
|
||||
ENABLED: true
|
||||
CONNECTION:
|
||||
URI: "mongodb://root:root@localhost:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true"
|
||||
|
||||
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: true
|
||||
NEW_MESSAGE: false
|
||||
MESSAGE_UPDATE: false
|
||||
CONTACTS: true
|
||||
CHATS: true
|
||||
|
||||
REDIS:
|
||||
ENABLED: false
|
||||
URI: "redis://localhost:6379"
|
||||
PREFIX_KEY: "evolution"
|
||||
|
||||
RABBITMQ:
|
||||
ENABLED: false
|
||||
URI: "amqp://guest:guest@localhost:5672"
|
||||
|
||||
OPENAI:
|
||||
CHAVE: ""
|
||||
ENABLED: false
|
||||
PROMPTS: false
|
||||
URI: ""
|
||||
|
||||
SQS:
|
||||
ENABLED: false
|
||||
ACCESS_KEY_ID: ""
|
||||
SECRET_ACCESS_KEY: ""
|
||||
ACCOUNT_ID: ""
|
||||
REGION: "us-east-1"
|
||||
|
||||
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: ""
|
||||
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
|
||||
# Automatically maps webhook paths
|
||||
# Set the events you want to hear
|
||||
EVENTS:
|
||||
APPLICATION_STARTUP: false
|
||||
QRCODE_UPDATED: true
|
||||
MESSAGES_SET: true
|
||||
MESSAGES_UPSERT: true
|
||||
MESSAGES_UPDATE: true
|
||||
MESSAGES_DELETE: true
|
||||
SEND_MESSAGE: true
|
||||
CONTACTS_SET: true
|
||||
CONTACTS_UPSERT: true
|
||||
CONTACTS_UPDATE: true
|
||||
PRESENCE_UPDATE: true
|
||||
CHATS_SET: true
|
||||
CHATS_UPSERT: true
|
||||
CHATS_UPDATE: true
|
||||
CHATS_DELETE: true
|
||||
GROUPS_UPSERT: true
|
||||
GROUP_UPDATE: true
|
||||
GROUP_PARTICIPANTS_UPDATE: true
|
||||
CONNECTION_UPDATE: true
|
||||
CALL: true
|
||||
# This event fires every time a new token is requested via the refresh route
|
||||
NEW_JWT_TOKEN: false
|
||||
# This events is used with Typebot
|
||||
TYPEBOT_START: false
|
||||
TYPEBOT_CHANGE_STATUS: false
|
||||
# This event is used with Chama AI
|
||||
CHAMA_AI_ACTION: false
|
||||
# This event is used to send errors to the webhook
|
||||
ERRORS: false
|
||||
ERRORS_WEBHOOK: ""
|
||||
|
||||
CONFIG_SESSION_PHONE:
|
||||
# Name that will be displayed on smartphone connection
|
||||
CLIENT: "Chat API"
|
||||
NAME: Chrome # Chrome | Firefox | Edge | Opera | Safari
|
||||
|
||||
# Set qrcode display limit
|
||||
QRCODE:
|
||||
LIMIT: 30
|
||||
COLOR: "#198754"
|
||||
|
||||
# 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
|
||||
AUTHENTICATION:
|
||||
TYPE: apikey # jwt or apikey
|
||||
# Define a global apikey to access all instances
|
||||
API_KEY:
|
||||
# OBS: This key must be inserted in the request header to create an instance.
|
||||
KEY: B6D711FCDE4D4FD5936544120E713976
|
||||
# Expose the api key on return from fetch instances
|
||||
EXPOSE_IN_FETCH_INSTANCES: true
|
||||
# Set the secret key to encrypt and decrypt your token and its expiration time.
|
||||
JWT:
|
||||
EXPIRIN_IN: 0 # seconds - 3600s === 1h | zero (0) - never expires
|
||||
SECRET: L=0YWt]b2w[WF>#>:&E`
|
||||
|
||||
# Configure to chatwoot
|
||||
CHATWOOT:
|
||||
USE_REPLY_ID: false
|
||||
|
5194
src/docs/swagger.yaml
Executable file → Normal file
5194
src/docs/swagger.yaml
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
200
src/libs/amqp.server.ts
Executable file → Normal file
200
src/libs/amqp.server.ts
Executable file → Normal file
@ -1,100 +1,100 @@
|
||||
import * as amqp from 'amqplib/callback_api';
|
||||
|
||||
import { configService, Rabbitmq, Openai } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('AMQP');
|
||||
|
||||
let amqpChannel: amqp.Channel | null = null;
|
||||
|
||||
export const initAMQP = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const uri = configService.get<Rabbitmq>('RABBITMQ').URI;
|
||||
amqp.connect(uri, (error, connection) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
connection.createChannel((channelError, channel) => {
|
||||
if (channelError) {
|
||||
reject(channelError);
|
||||
return;
|
||||
}
|
||||
|
||||
const exchangeName = 'evolution_exchange';
|
||||
|
||||
channel.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
amqpChannel = channel;
|
||||
|
||||
logger.info('AMQP initialized');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const getAMQP = (): amqp.Channel | null => {
|
||||
return amqpChannel;
|
||||
};
|
||||
|
||||
export const initQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '.').toLowerCase()}`;
|
||||
});
|
||||
|
||||
queues.forEach((event) => {
|
||||
const amqp = getAMQP();
|
||||
const exchangeName = instanceName ?? 'evolution_exchange';
|
||||
|
||||
amqp.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
const queueName = `${instanceName}.${event}`;
|
||||
|
||||
amqp.assertQueue(queueName, {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
arguments: {
|
||||
'x-queue-type': 'quorum',
|
||||
},
|
||||
});
|
||||
|
||||
amqp.bindQueue(queueName, exchangeName, event);
|
||||
});
|
||||
};
|
||||
|
||||
export const removeQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const channel = getAMQP();
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '.').toLowerCase()}`;
|
||||
});
|
||||
|
||||
const exchangeName = instanceName ?? 'evolution_exchange';
|
||||
|
||||
queues.forEach((event) => {
|
||||
const amqp = getAMQP();
|
||||
|
||||
amqp.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
const queueName = `${instanceName}.${event}`;
|
||||
|
||||
amqp.deleteQueue(queueName);
|
||||
});
|
||||
|
||||
channel.deleteExchange(exchangeName);
|
||||
};
|
||||
import * as amqp from 'amqplib/callback_api';
|
||||
|
||||
import { configService, Rabbitmq, Openai } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('AMQP');
|
||||
|
||||
let amqpChannel: amqp.Channel | null = null;
|
||||
|
||||
export const initAMQP = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const uri = configService.get<Rabbitmq>('RABBITMQ').URI;
|
||||
amqp.connect(uri, (error, connection) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
connection.createChannel((channelError, channel) => {
|
||||
if (channelError) {
|
||||
reject(channelError);
|
||||
return;
|
||||
}
|
||||
|
||||
const exchangeName = 'evolution_exchange';
|
||||
|
||||
channel.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
amqpChannel = channel;
|
||||
|
||||
logger.info('AMQP initialized');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const getAMQP = (): amqp.Channel | null => {
|
||||
return amqpChannel;
|
||||
};
|
||||
|
||||
export const initQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '.').toLowerCase()}`;
|
||||
});
|
||||
|
||||
queues.forEach((event) => {
|
||||
const amqp = getAMQP();
|
||||
const exchangeName = instanceName ?? 'evolution_exchange';
|
||||
|
||||
amqp.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
const queueName = `${instanceName}.${event}`;
|
||||
|
||||
amqp.assertQueue(queueName, {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
arguments: {
|
||||
'x-queue-type': 'quorum',
|
||||
},
|
||||
});
|
||||
|
||||
amqp.bindQueue(queueName, exchangeName, event);
|
||||
});
|
||||
};
|
||||
|
||||
export const removeQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const channel = getAMQP();
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '.').toLowerCase()}`;
|
||||
});
|
||||
|
||||
const exchangeName = instanceName ?? 'evolution_exchange';
|
||||
|
||||
queues.forEach((event) => {
|
||||
const amqp = getAMQP();
|
||||
|
||||
amqp.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
const queueName = `${instanceName}.${event}`;
|
||||
|
||||
amqp.deleteQueue(queueName);
|
||||
});
|
||||
|
||||
channel.deleteExchange(exchangeName);
|
||||
};
|
||||
|
52
src/libs/db.connect.ts
Executable file → Normal file
52
src/libs/db.connect.ts
Executable file → Normal file
@ -1,26 +1,26 @@
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { configService, Database } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('MongoDB');
|
||||
|
||||
const db = configService.get<Database>('DATABASE');
|
||||
export const dbserver = (() => {
|
||||
if (db.ENABLED) {
|
||||
logger.verbose('connecting');
|
||||
const dbs = mongoose.createConnection(db.CONNECTION.URI, {
|
||||
|
||||
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']);
|
||||
|
||||
process.on('beforeExit', () => {
|
||||
logger.verbose('instance destroyed');
|
||||
dbserver.destroy(true, (error) => logger.error(error));
|
||||
});
|
||||
|
||||
return dbs;
|
||||
}
|
||||
})();
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { configService, Database } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('MongoDB');
|
||||
|
||||
const db = configService.get<Database>('DATABASE');
|
||||
export const dbserver = (() => {
|
||||
if (db.ENABLED) {
|
||||
logger.verbose('connecting');
|
||||
const dbs = mongoose.createConnection(db.CONNECTION.URI, {
|
||||
|
||||
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']);
|
||||
|
||||
process.on('beforeExit', () => {
|
||||
logger.verbose('instance destroyed');
|
||||
dbserver.destroy(true, (error) => logger.error(error));
|
||||
});
|
||||
|
||||
return dbs;
|
||||
}
|
||||
})();
|
||||
|
68
src/libs/openai.ts
Executable file → Normal file
68
src/libs/openai.ts
Executable file → Normal file
@ -1,34 +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;
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
264
src/libs/redis.client.ts
Executable file → Normal file
264
src/libs/redis.client.ts
Executable file → Normal file
@ -1,132 +1,132 @@
|
||||
import { createClient, RedisClientType } from '@redis/client';
|
||||
import { BufferJSON } from '@whiskeysockets/baileys';
|
||||
|
||||
import { Redis } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
export class RedisCache {
|
||||
|
||||
constructor() {
|
||||
this.logger.verbose('RedisCache instance created');
|
||||
process.on('beforeExit', () => {
|
||||
this.logger.verbose('RedisCache instance destroyed');
|
||||
this.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
this.statusConnection = false;
|
||||
this.logger.verbose('Redis client disconnected');
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public async keyExists(key?: string) {
|
||||
if (key) {
|
||||
this.logger.verbose('keyExists: ' + key);
|
||||
return !!(await this.instanceKeys()).find((i) => i === key);
|
||||
}
|
||||
this.logger.verbose('keyExists: ' + this.instanceName);
|
||||
return !!(await this.instanceKeys()).find((i) => i === this.instanceName);
|
||||
}
|
||||
|
||||
public async writeData(field: string, data: any) {
|
||||
try {
|
||||
this.logger.verbose('writeData: ' + field);
|
||||
const json = JSON.stringify(data, BufferJSON.replacer);
|
||||
|
||||
return await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async readData(field: string) {
|
||||
try {
|
||||
this.logger.verbose('readData: ' + field);
|
||||
const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
|
||||
|
||||
if (data) {
|
||||
this.logger.verbose('readData: ' + field + ' success');
|
||||
return JSON.parse(data, BufferJSON.reviver);
|
||||
}
|
||||
|
||||
this.logger.verbose('readData: ' + field + ' not found');
|
||||
return null;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async removeData(field: string) {
|
||||
try {
|
||||
this.logger.verbose('removeData: ' + field);
|
||||
return await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async delAll(hash?: string) {
|
||||
try {
|
||||
this.logger.verbose('instance delAll: ' + hash);
|
||||
const result = await this.client.del(hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
import { createClient, RedisClientType } from '@redis/client';
|
||||
import { BufferJSON } from '@whiskeysockets/baileys';
|
||||
|
||||
import { Redis } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
export class RedisCache {
|
||||
|
||||
constructor() {
|
||||
this.logger.verbose('RedisCache instance created');
|
||||
process.on('beforeExit', () => {
|
||||
this.logger.verbose('RedisCache instance destroyed');
|
||||
this.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
this.statusConnection = false;
|
||||
this.logger.verbose('Redis client disconnected');
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public async keyExists(key?: string) {
|
||||
if (key) {
|
||||
this.logger.verbose('keyExists: ' + key);
|
||||
return !!(await this.instanceKeys()).find((i) => i === key);
|
||||
}
|
||||
this.logger.verbose('keyExists: ' + this.instanceName);
|
||||
return !!(await this.instanceKeys()).find((i) => i === this.instanceName);
|
||||
}
|
||||
|
||||
public async writeData(field: string, data: any) {
|
||||
try {
|
||||
this.logger.verbose('writeData: ' + field);
|
||||
const json = JSON.stringify(data, BufferJSON.replacer);
|
||||
|
||||
return await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async readData(field: string) {
|
||||
try {
|
||||
this.logger.verbose('readData: ' + field);
|
||||
const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
|
||||
|
||||
if (data) {
|
||||
this.logger.verbose('readData: ' + field + ' success');
|
||||
return JSON.parse(data, BufferJSON.reviver);
|
||||
}
|
||||
|
||||
this.logger.verbose('readData: ' + field + ' not found');
|
||||
return null;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async removeData(field: string) {
|
||||
try {
|
||||
this.logger.verbose('removeData: ' + field);
|
||||
return await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async delAll(hash?: string) {
|
||||
try {
|
||||
this.logger.verbose('instance delAll: ' + hash);
|
||||
const result = await this.client.del(hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
src/libs/redis.ts
Executable file → Normal file
18
src/libs/redis.ts
Executable file → Normal file
@ -1,9 +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,
|
||||
})
|
||||
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,
|
||||
})
|
||||
|
192
src/libs/sqs.server.ts
Executable file → Normal file
192
src/libs/sqs.server.ts
Executable file → Normal file
@ -1,97 +1,97 @@
|
||||
import { SQS } from 'aws-sdk';
|
||||
|
||||
import { configService, Sqs } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('SQS');
|
||||
|
||||
let sqs: SQS;
|
||||
|
||||
export const initSQS = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const awsConfig = configService.get<Sqs>('SQS');
|
||||
sqs = new SQS({
|
||||
accessKeyId: awsConfig.ACCESS_KEY_ID,
|
||||
secretAccessKey: awsConfig.SECRET_ACCESS_KEY,
|
||||
region: awsConfig.REGION,
|
||||
});
|
||||
|
||||
logger.info('SQS initialized');
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
export const getSQS = (): SQS => {
|
||||
return sqs;
|
||||
};
|
||||
|
||||
export const initQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '_').toLowerCase()}`;
|
||||
});
|
||||
|
||||
const sqs = getSQS();
|
||||
|
||||
queues.forEach((event) => {
|
||||
const queueName = `${instanceName}_${event}.fifo`;
|
||||
|
||||
sqs.createQueue(
|
||||
{
|
||||
QueueName: queueName,
|
||||
Attributes: {
|
||||
FifoQueue: 'true',
|
||||
},
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
logger.error(`Error creating queue ${queueName}: ${err.message}`);
|
||||
} else {
|
||||
logger.info(`Queue ${queueName} created: ${data.QueueUrl}`);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const removeQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const sqs = getSQS();
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '_').toLowerCase()}`;
|
||||
});
|
||||
|
||||
queues.forEach((event) => {
|
||||
const queueName = `${instanceName}_${event}.fifo`;
|
||||
|
||||
sqs.getQueueUrl(
|
||||
{
|
||||
QueueName: queueName,
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
logger.error(`Error getting queue URL for ${queueName}: ${err.message}`);
|
||||
} else {
|
||||
const queueUrl = data.QueueUrl;
|
||||
|
||||
sqs.deleteQueue(
|
||||
{
|
||||
QueueUrl: queueUrl,
|
||||
},
|
||||
(deleteErr) => {
|
||||
if (deleteErr) {
|
||||
logger.error(`Error deleting queue ${queueName}: ${deleteErr.message}`);
|
||||
} else {
|
||||
logger.info(`Queue ${queueName} deleted`);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
import { SQS } from 'aws-sdk';
|
||||
|
||||
import { configService, Sqs } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
|
||||
const logger = new Logger('SQS');
|
||||
|
||||
let sqs: SQS;
|
||||
|
||||
export const initSQS = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const awsConfig = configService.get<Sqs>('SQS');
|
||||
sqs = new SQS({
|
||||
accessKeyId: awsConfig.ACCESS_KEY_ID,
|
||||
secretAccessKey: awsConfig.SECRET_ACCESS_KEY,
|
||||
region: awsConfig.REGION,
|
||||
});
|
||||
|
||||
logger.info('SQS initialized');
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
export const getSQS = (): SQS => {
|
||||
return sqs;
|
||||
};
|
||||
|
||||
export const initQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '_').toLowerCase()}`;
|
||||
});
|
||||
|
||||
const sqs = getSQS();
|
||||
|
||||
queues.forEach((event) => {
|
||||
const queueName = `${instanceName}_${event}.fifo`;
|
||||
|
||||
sqs.createQueue(
|
||||
{
|
||||
QueueName: queueName,
|
||||
Attributes: {
|
||||
FifoQueue: 'true',
|
||||
},
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
logger.error(`Error creating queue ${queueName}: ${err.message}`);
|
||||
} else {
|
||||
logger.info(`Queue ${queueName} created: ${data.QueueUrl}`);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const removeQueues = (instanceName: string, events: string[]) => {
|
||||
if (!events || !events.length) return;
|
||||
|
||||
const sqs = getSQS();
|
||||
|
||||
const queues = events.map((event) => {
|
||||
return `${event.replace(/_/g, '_').toLowerCase()}`;
|
||||
});
|
||||
|
||||
queues.forEach((event) => {
|
||||
const queueName = `${instanceName}_${event}.fifo`;
|
||||
|
||||
sqs.getQueueUrl(
|
||||
{
|
||||
QueueName: queueName,
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
logger.error(`Error getting queue URL for ${queueName}: ${err.message}`);
|
||||
} else {
|
||||
const queueUrl = data.QueueUrl;
|
||||
|
||||
sqs.deleteQueue(
|
||||
{
|
||||
QueueUrl: queueUrl,
|
||||
},
|
||||
(deleteErr) => {
|
||||
if (deleteErr) {
|
||||
logger.error(`Error deleting queue ${queueName}: ${deleteErr.message}`);
|
||||
} else {
|
||||
logger.info(`Queue ${queueName} deleted`);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
274
src/main.ts
Executable file → Normal file
274
src/main.ts
Executable file → Normal file
@ -1,137 +1,137 @@
|
||||
import 'express-async-errors';
|
||||
|
||||
import axios from 'axios';
|
||||
import compression from 'compression';
|
||||
import cors from 'cors';
|
||||
import express, { json, NextFunction, Request, Response, urlencoded } from 'express';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config';
|
||||
import { onUnexpectedError } from './config/error.config';
|
||||
import { Logger } from './config/logger.config';
|
||||
import { ROOT_DIR } from './config/path.config';
|
||||
import { swaggerRouter } from './docs/swagger.conf';
|
||||
import { initAMQP } from './libs/amqp.server';
|
||||
import { initIO } from './libs/socket.server';
|
||||
import { initSQS } from './libs/sqs.server';
|
||||
import { ServerUP } from './utils/server-up';
|
||||
import { HttpStatus, router } from './whatsapp/routers/index.router';
|
||||
import { waMonitor } from './whatsapp/whatsapp.module';
|
||||
|
||||
function initWA() {
|
||||
waMonitor.loadInstance();
|
||||
}
|
||||
|
||||
function bootstrap() {
|
||||
const logger = new Logger('SERVER');
|
||||
const app = express();
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin(requestOrigin, callback) {
|
||||
const { ORIGIN } = configService.get<Cors>('CORS');
|
||||
if (ORIGIN.includes('*')) {
|
||||
return callback(null, true);
|
||||
}
|
||||
if (ORIGIN.indexOf(requestOrigin) !== -1) {
|
||||
return callback(null, true);
|
||||
}
|
||||
return callback(new Error('Not allowed by CORS'));
|
||||
},
|
||||
methods: [...configService.get<Cors>('CORS').METHODS],
|
||||
credentials: configService.get<Cors>('CORS').CREDENTIALS,
|
||||
}),
|
||||
urlencoded({ extended: true, limit: '136mb' }),
|
||||
json({ limit: '136mb' }),
|
||||
compression(),
|
||||
);
|
||||
|
||||
app.set('view engine', 'hbs');
|
||||
app.set('views', join(ROOT_DIR, 'views'));
|
||||
app.use(express.static(join(ROOT_DIR, 'public')));
|
||||
|
||||
app.use('/store', express.static(join(ROOT_DIR, 'store')));
|
||||
|
||||
app.use('/', router);
|
||||
app.use(swaggerRouter);
|
||||
|
||||
app.use(
|
||||
(err: Error, req: Request, res: Response, next: NextFunction) => {
|
||||
if (err) {
|
||||
const webhook = configService.get<Webhook>('WEBHOOK');
|
||||
|
||||
if (webhook.EVENTS.ERRORS_WEBHOOK && webhook.EVENTS.ERRORS_WEBHOOK != '' && webhook.EVENTS.ERRORS) {
|
||||
const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
|
||||
const localISOTime = new Date(Date.now() - tzoffset).toISOString();
|
||||
const now = localISOTime;
|
||||
const globalApiKey = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
|
||||
const serverUrl = configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const errorData = {
|
||||
event: 'error',
|
||||
data: {
|
||||
error: err['error'] || 'Internal Server Error',
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
status: err['status'] || 500,
|
||||
response: {
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
date_time: now,
|
||||
api_key: globalApiKey,
|
||||
server_url: serverUrl,
|
||||
};
|
||||
|
||||
logger.error(errorData);
|
||||
|
||||
const baseURL = webhook.EVENTS.ERRORS_WEBHOOK;
|
||||
const httpService = axios.create({ baseURL });
|
||||
|
||||
httpService.post('', errorData);
|
||||
}
|
||||
|
||||
return res.status(err['status'] || 500).json({
|
||||
status: err['status'] || 500,
|
||||
error: err['error'] || 'Internal Server Error',
|
||||
response: {
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const { method, url } = req;
|
||||
|
||||
res.status(HttpStatus.NOT_FOUND).json({
|
||||
status: HttpStatus.NOT_FOUND,
|
||||
error: 'Not Found',
|
||||
response: {
|
||||
message: [`Cannot ${method.toUpperCase()} ${url}`],
|
||||
},
|
||||
});
|
||||
|
||||
next();
|
||||
},
|
||||
);
|
||||
|
||||
const httpServer = configService.get<HttpServer>('SERVER');
|
||||
|
||||
ServerUP.app = app;
|
||||
const server = ServerUP[httpServer.TYPE];
|
||||
|
||||
server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT));
|
||||
|
||||
initWA();
|
||||
|
||||
initIO(server);
|
||||
|
||||
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
|
||||
|
||||
if (configService.get<Sqs>('SQS')?.ENABLED) initSQS();
|
||||
|
||||
onUnexpectedError();
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
import 'express-async-errors';
|
||||
|
||||
import axios from 'axios';
|
||||
import compression from 'compression';
|
||||
import cors from 'cors';
|
||||
import express, { json, NextFunction, Request, Response, urlencoded } from 'express';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config';
|
||||
import { onUnexpectedError } from './config/error.config';
|
||||
import { Logger } from './config/logger.config';
|
||||
import { ROOT_DIR } from './config/path.config';
|
||||
import { swaggerRouter } from './docs/swagger.conf';
|
||||
import { initAMQP } from './libs/amqp.server';
|
||||
import { initIO } from './libs/socket.server';
|
||||
import { initSQS } from './libs/sqs.server';
|
||||
import { ServerUP } from './utils/server-up';
|
||||
import { HttpStatus, router } from './whatsapp/routers/index.router';
|
||||
import { waMonitor } from './whatsapp/whatsapp.module';
|
||||
|
||||
function initWA() {
|
||||
waMonitor.loadInstance();
|
||||
}
|
||||
|
||||
function bootstrap() {
|
||||
const logger = new Logger('SERVER');
|
||||
const app = express();
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin(requestOrigin, callback) {
|
||||
const { ORIGIN } = configService.get<Cors>('CORS');
|
||||
if (ORIGIN.includes('*')) {
|
||||
return callback(null, true);
|
||||
}
|
||||
if (ORIGIN.indexOf(requestOrigin) !== -1) {
|
||||
return callback(null, true);
|
||||
}
|
||||
return callback(new Error('Not allowed by CORS'));
|
||||
},
|
||||
methods: [...configService.get<Cors>('CORS').METHODS],
|
||||
credentials: configService.get<Cors>('CORS').CREDENTIALS,
|
||||
}),
|
||||
urlencoded({ extended: true, limit: '136mb' }),
|
||||
json({ limit: '136mb' }),
|
||||
compression(),
|
||||
);
|
||||
|
||||
app.set('view engine', 'hbs');
|
||||
app.set('views', join(ROOT_DIR, 'views'));
|
||||
app.use(express.static(join(ROOT_DIR, 'public')));
|
||||
|
||||
app.use('/store', express.static(join(ROOT_DIR, 'store')));
|
||||
|
||||
app.use('/', router);
|
||||
app.use(swaggerRouter);
|
||||
|
||||
app.use(
|
||||
(err: Error, req: Request, res: Response, next: NextFunction) => {
|
||||
if (err) {
|
||||
const webhook = configService.get<Webhook>('WEBHOOK');
|
||||
|
||||
if (webhook.EVENTS.ERRORS_WEBHOOK && webhook.EVENTS.ERRORS_WEBHOOK != '' && webhook.EVENTS.ERRORS) {
|
||||
const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
|
||||
const localISOTime = new Date(Date.now() - tzoffset).toISOString();
|
||||
const now = localISOTime;
|
||||
const globalApiKey = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
|
||||
const serverUrl = configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const errorData = {
|
||||
event: 'error',
|
||||
data: {
|
||||
error: err['error'] || 'Internal Server Error',
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
status: err['status'] || 500,
|
||||
response: {
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
},
|
||||
},
|
||||
date_time: now,
|
||||
api_key: globalApiKey,
|
||||
server_url: serverUrl,
|
||||
};
|
||||
|
||||
logger.error(errorData);
|
||||
|
||||
const baseURL = webhook.EVENTS.ERRORS_WEBHOOK;
|
||||
const httpService = axios.create({ baseURL });
|
||||
|
||||
httpService.post('', errorData);
|
||||
}
|
||||
|
||||
return res.status(err['status'] || 500).json({
|
||||
status: err['status'] || 500,
|
||||
error: err['error'] || 'Internal Server Error',
|
||||
response: {
|
||||
message: err['message'] || 'Internal Server Error',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const { method, url } = req;
|
||||
|
||||
res.status(HttpStatus.NOT_FOUND).json({
|
||||
status: HttpStatus.NOT_FOUND,
|
||||
error: 'Not Found',
|
||||
response: {
|
||||
message: [`Cannot ${method.toUpperCase()} ${url}`],
|
||||
},
|
||||
});
|
||||
|
||||
next();
|
||||
},
|
||||
);
|
||||
|
||||
const httpServer = configService.get<HttpServer>('SERVER');
|
||||
|
||||
ServerUP.app = app;
|
||||
const server = ServerUP[httpServer.TYPE];
|
||||
|
||||
server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT));
|
||||
|
||||
initWA();
|
||||
|
||||
initIO(server);
|
||||
|
||||
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
|
||||
|
||||
if (configService.get<Sqs>('SQS')?.ENABLED) initSQS();
|
||||
|
||||
onUnexpectedError();
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
98
src/prompts/contabilAgent.ts
Executable file → Normal file
98
src/prompts/contabilAgent.ts
Executable file → Normal file
@ -1,49 +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?
|
||||
|
||||
`
|
||||
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?
|
||||
|
||||
`
|
||||
|
188
src/prompts/pizzaAgent.ts
Executable file → Normal file
188
src/prompts/pizzaAgent.ts
Executable file → Normal file
@ -1,94 +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
|
||||
`
|
||||
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
|
||||
`
|
||||
|
26
src/utils/initPrompt.ts
Executable file → Normal file
26
src/utils/initPrompt.ts
Executable file → Normal file
@ -1,13 +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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
224
src/utils/use-multi-file-auth-state-db.ts
Executable file → Normal file
224
src/utils/use-multi-file-auth-state-db.ts
Executable file → Normal file
@ -1,112 +1,112 @@
|
||||
import {
|
||||
AuthenticationCreds,
|
||||
AuthenticationState,
|
||||
BufferJSON,
|
||||
initAuthCreds,
|
||||
proto,
|
||||
SignalDataTypeMap,
|
||||
} from '@whiskeysockets/baileys';
|
||||
|
||||
import { configService, Database } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
import { dbserver } from '../libs/db.connect';
|
||||
|
||||
export async function useMultiFileAuthStateDb(
|
||||
coll: string,
|
||||
): Promise<{ state: AuthenticationState; saveCreds: () => Promise<void> }> {
|
||||
const logger = new Logger(useMultiFileAuthStateDb.name);
|
||||
|
||||
const client = dbserver.getClient();
|
||||
|
||||
const collection = client
|
||||
.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> => {
|
||||
try {
|
||||
await client.connect();
|
||||
let msgParsed = JSON.parse(JSON.stringify(data, BufferJSON.replacer));
|
||||
if (Array.isArray(msgParsed)) {
|
||||
msgParsed = {
|
||||
_id: key,
|
||||
content_array: msgParsed,
|
||||
};
|
||||
}
|
||||
return await collection.replaceOne({ _id: key }, msgParsed, {
|
||||
//return await collection.replaceOne({ _id: key }, JSON.parse(JSON.stringify(data, BufferJSON.replacer)), {
|
||||
upsert: true,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const readData = async (key: string): Promise<any> => {
|
||||
try {
|
||||
await client.connect();
|
||||
let data = (await collection.findOne({ _id: key })) as any;
|
||||
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) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const removeData = async (key: string) => {
|
||||
try {
|
||||
await client.connect();
|
||||
return await collection.deleteOne({ _id: key });
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const creds: AuthenticationCreds = (await readData('creds')) || initAuthCreds();
|
||||
|
||||
return {
|
||||
state: {
|
||||
creds,
|
||||
keys: {
|
||||
get: async (type, ids: string[]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const data: { [_: string]: SignalDataTypeMap[type] } = {};
|
||||
await Promise.all(
|
||||
ids.map(async (id) => {
|
||||
let value = await readData(`${type}-${id}`);
|
||||
if (type === 'app-state-sync-key' && value) {
|
||||
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
||||
}
|
||||
|
||||
data[id] = value;
|
||||
}),
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
set: async (data: any) => {
|
||||
const tasks: Promise<void>[] = [];
|
||||
for (const category in data) {
|
||||
for (const id in data[category]) {
|
||||
const value = data[category][id];
|
||||
const key = `${category}-${id}`;
|
||||
tasks.push(value ? writeData(value, key) : removeData(key));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(tasks);
|
||||
},
|
||||
},
|
||||
},
|
||||
saveCreds: async () => {
|
||||
return writeData(creds, 'creds');
|
||||
},
|
||||
};
|
||||
}
|
||||
import {
|
||||
AuthenticationCreds,
|
||||
AuthenticationState,
|
||||
BufferJSON,
|
||||
initAuthCreds,
|
||||
proto,
|
||||
SignalDataTypeMap,
|
||||
} from '@whiskeysockets/baileys';
|
||||
|
||||
import { configService, Database } from '../config/env.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
import { dbserver } from '../libs/db.connect';
|
||||
|
||||
export async function useMultiFileAuthStateDb(
|
||||
coll: string,
|
||||
): Promise<{ state: AuthenticationState; saveCreds: () => Promise<void> }> {
|
||||
const logger = new Logger(useMultiFileAuthStateDb.name);
|
||||
|
||||
const client = dbserver.getClient();
|
||||
|
||||
const collection = client
|
||||
.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> => {
|
||||
try {
|
||||
await client.connect();
|
||||
let msgParsed = JSON.parse(JSON.stringify(data, BufferJSON.replacer));
|
||||
if (Array.isArray(msgParsed)) {
|
||||
msgParsed = {
|
||||
_id: key,
|
||||
content_array: msgParsed,
|
||||
};
|
||||
}
|
||||
return await collection.replaceOne({ _id: key }, msgParsed, {
|
||||
//return await collection.replaceOne({ _id: key }, JSON.parse(JSON.stringify(data, BufferJSON.replacer)), {
|
||||
upsert: true,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const readData = async (key: string): Promise<any> => {
|
||||
try {
|
||||
await client.connect();
|
||||
let data = (await collection.findOne({ _id: key })) as any;
|
||||
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) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const removeData = async (key: string) => {
|
||||
try {
|
||||
await client.connect();
|
||||
return await collection.deleteOne({ _id: key });
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const creds: AuthenticationCreds = (await readData('creds')) || initAuthCreds();
|
||||
|
||||
return {
|
||||
state: {
|
||||
creds,
|
||||
keys: {
|
||||
get: async (type, ids: string[]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const data: { [_: string]: SignalDataTypeMap[type] } = {};
|
||||
await Promise.all(
|
||||
ids.map(async (id) => {
|
||||
let value = await readData(`${type}-${id}`);
|
||||
if (type === 'app-state-sync-key' && value) {
|
||||
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
||||
}
|
||||
|
||||
data[id] = value;
|
||||
}),
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
set: async (data: any) => {
|
||||
const tasks: Promise<void>[] = [];
|
||||
for (const category in data) {
|
||||
for (const id in data[category]) {
|
||||
const value = data[category][id];
|
||||
const key = `${category}-${id}`;
|
||||
tasks.push(value ? writeData(value, key) : removeData(key));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(tasks);
|
||||
},
|
||||
},
|
||||
},
|
||||
saveCreds: async () => {
|
||||
return await writeData(creds, 'creds');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
2280
src/validate/validate.schema.ts
Executable file → Normal file
2280
src/validate/validate.schema.ts
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
1480
src/whatsapp/controllers/instance.controller.ts
Executable file → Normal file
1480
src/whatsapp/controllers/instance.controller.ts
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
170
src/whatsapp/controllers/openai.controller.ts
Executable file → Normal file
170
src/whatsapp/controllers/openai.controller.ts
Executable file → Normal file
@ -1,85 +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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
110
src/whatsapp/controllers/sqs.controller.ts
Executable file → Normal file
110
src/whatsapp/controllers/sqs.controller.ts
Executable file → Normal file
@ -1,56 +1,56 @@
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { SqsService } from '../services/sqs.service';
|
||||
|
||||
const logger = new Logger('SqsController');
|
||||
|
||||
export class SqsController {
|
||||
constructor(private readonly sqsService: SqsService) { }
|
||||
|
||||
public async createSqs(instance: InstanceDto, data: SqsDto) {
|
||||
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');
|
||||
|
||||
if (!data.enabled) {
|
||||
logger.verbose('sqs disabled');
|
||||
data.events = [];
|
||||
}
|
||||
|
||||
if (data.events.length === 0) {
|
||||
logger.verbose('sqs 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.sqsService.create(instance, data);
|
||||
}
|
||||
|
||||
public async findSqs(instance: InstanceDto) {
|
||||
logger.verbose('requested findSqs from ' + instance.instanceName + ' instance');
|
||||
return this.sqsService.find(instance);
|
||||
}
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { SqsService } from '../services/sqs.service';
|
||||
|
||||
const logger = new Logger('SqsController');
|
||||
|
||||
export class SqsController {
|
||||
constructor(private readonly sqsService: SqsService) { }
|
||||
|
||||
public async createSqs(instance: InstanceDto, data: SqsDto) {
|
||||
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');
|
||||
|
||||
if (!data.enabled) {
|
||||
logger.verbose('sqs disabled');
|
||||
data.events = [];
|
||||
}
|
||||
|
||||
if (data.events.length === 0) {
|
||||
logger.verbose('sqs 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.sqsService.create(instance, data);
|
||||
}
|
||||
|
||||
public async findSqs(instance: InstanceDto) {
|
||||
logger.verbose('requested findSqs from ' + instance.instanceName + ' instance');
|
||||
return this.sqsService.find(instance);
|
||||
}
|
||||
}
|
10
src/whatsapp/dto/contactopenai.dto.ts
Executable file → Normal file
10
src/whatsapp/dto/contactopenai.dto.ts
Executable file → Normal file
@ -1,5 +1,5 @@
|
||||
export class ContactOpenaiDto {
|
||||
contact?: string;
|
||||
enabled: boolean;
|
||||
owner: string;
|
||||
}
|
||||
export class ContactOpenaiDto {
|
||||
contact?: string;
|
||||
enabled: boolean;
|
||||
owner: string;
|
||||
}
|
||||
|
88
src/whatsapp/dto/instance.dto.ts
Executable file → Normal file
88
src/whatsapp/dto/instance.dto.ts
Executable file → Normal file
@ -1,44 +1,44 @@
|
||||
export class InstanceDto {
|
||||
instanceName: string;
|
||||
qrcode?: boolean;
|
||||
number?: string;
|
||||
token?: string;
|
||||
webhook?: string;
|
||||
webhook_by_events?: boolean;
|
||||
webhook_base64?: boolean;
|
||||
events?: string[];
|
||||
reject_call?: boolean;
|
||||
msg_call?: string;
|
||||
groups_ignore?: boolean;
|
||||
always_online?: boolean;
|
||||
read_messages?: boolean;
|
||||
read_status?: boolean;
|
||||
chatwoot_account_id?: string;
|
||||
chatwoot_token?: string;
|
||||
chatwoot_url?: string;
|
||||
chatwoot_sign_msg?: boolean;
|
||||
chatwoot_reopen_conversation?: boolean;
|
||||
chatwoot_conversation_pending?: boolean;
|
||||
websocket_enabled?: boolean;
|
||||
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;
|
||||
typebot_keyword_finish?: string;
|
||||
typebot_delay_message?: number;
|
||||
typebot_unknown_message?: string;
|
||||
typebot_listening_from_me?: boolean;
|
||||
proxy_enabled?: boolean;
|
||||
proxy?: string;
|
||||
}
|
||||
export class InstanceDto {
|
||||
instanceName: string;
|
||||
qrcode?: boolean;
|
||||
number?: string;
|
||||
token?: string;
|
||||
webhook?: string;
|
||||
webhook_by_events?: boolean;
|
||||
webhook_base64?: boolean;
|
||||
events?: string[];
|
||||
reject_call?: boolean;
|
||||
msg_call?: string;
|
||||
groups_ignore?: boolean;
|
||||
always_online?: boolean;
|
||||
read_messages?: boolean;
|
||||
read_status?: boolean;
|
||||
chatwoot_account_id?: string;
|
||||
chatwoot_token?: string;
|
||||
chatwoot_url?: string;
|
||||
chatwoot_sign_msg?: boolean;
|
||||
chatwoot_reopen_conversation?: boolean;
|
||||
chatwoot_conversation_pending?: boolean;
|
||||
websocket_enabled?: boolean;
|
||||
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;
|
||||
typebot_keyword_finish?: string;
|
||||
typebot_delay_message?: number;
|
||||
typebot_unknown_message?: string;
|
||||
typebot_listening_from_me?: boolean;
|
||||
proxy_enabled?: boolean;
|
||||
proxy?: string;
|
||||
}
|
||||
|
12
src/whatsapp/dto/openai.dto.ts
Executable file → Normal file
12
src/whatsapp/dto/openai.dto.ts
Executable file → Normal file
@ -1,6 +1,6 @@
|
||||
export class OpenaiDto {
|
||||
chave?: string;
|
||||
enabled: boolean;
|
||||
prompts?: string;
|
||||
events?: string[];
|
||||
}
|
||||
export class OpenaiDto {
|
||||
chave?: string;
|
||||
enabled: boolean;
|
||||
prompts?: string;
|
||||
events?: string[];
|
||||
}
|
||||
|
6
src/whatsapp/dto/sqs.dto.ts
Executable file → Normal file
6
src/whatsapp/dto/sqs.dto.ts
Executable file → Normal file
@ -1,4 +1,4 @@
|
||||
export class SqsDto {
|
||||
enabled: boolean;
|
||||
events?: string[];
|
||||
export class SqsDto {
|
||||
enabled: boolean;
|
||||
events?: string[];
|
||||
}
|
152
src/whatsapp/guards/instance.guard.ts
Executable file → Normal file
152
src/whatsapp/guards/instance.guard.ts
Executable file → Normal file
@ -1,76 +1,76 @@
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { configService, Database, Redis } from '../../config/env.config';
|
||||
import { INSTANCE_DIR } from '../../config/path.config';
|
||||
import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
InternalServerErrorException,
|
||||
NotFoundException,
|
||||
} from '../../exceptions';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { cache, waMonitor } from '../whatsapp.module';
|
||||
|
||||
async function getInstance(instanceName: string) {
|
||||
try {
|
||||
const db = configService.get<Database>('DATABASE');
|
||||
const redisConf = configService.get<Redis>('REDIS');
|
||||
|
||||
const exists = !!waMonitor.waInstances[instanceName];
|
||||
|
||||
if (redisConf.ENABLED) {
|
||||
const keyExists = await cache.keyExists();
|
||||
return exists || keyExists;
|
||||
}
|
||||
|
||||
if (db.ENABLED) {
|
||||
const collection = dbserver
|
||||
.getClient()
|
||||
.db(
|
||||
db.CONNECTION.DB_PREFIX_NAME +
|
||||
db.CONNECTION.DB_PREFIX_FINAL_NAME)
|
||||
.collection(instanceName);
|
||||
return exists || (await collection.find({}).toArray()).length > 0;
|
||||
}
|
||||
|
||||
return exists || existsSync(join(INSTANCE_DIR, instanceName));
|
||||
} catch (error) {
|
||||
throw new InternalServerErrorException(error?.toString());
|
||||
}
|
||||
}
|
||||
|
||||
export async function instanceExistsGuard(req: Request, _: Response, next: NextFunction) {
|
||||
if (req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const param = req.params as unknown as InstanceDto;
|
||||
if (!param?.instanceName) {
|
||||
throw new BadRequestException('"instanceName" not provided.');
|
||||
}
|
||||
|
||||
if (!(await getInstance(param.instanceName))) {
|
||||
throw new NotFoundException(`The "${param.instanceName}" instance does not exist`);
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
export async function instanceLoggedGuard(req: Request, _: Response, next: NextFunction) {
|
||||
if (req.originalUrl.includes('/instance/create')) {
|
||||
const instance = req.body as InstanceDto;
|
||||
if (await getInstance(instance.instanceName)) {
|
||||
throw new ForbiddenException(`This name "${instance.instanceName}" is already in use.`);
|
||||
}
|
||||
|
||||
if (waMonitor.waInstances[instance.instanceName]) {
|
||||
waMonitor.waInstances[instance.instanceName]?.removeRabbitmqQueues();
|
||||
delete waMonitor.waInstances[instance.instanceName];
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { configService, Database, Redis } from '../../config/env.config';
|
||||
import { INSTANCE_DIR } from '../../config/path.config';
|
||||
import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
InternalServerErrorException,
|
||||
NotFoundException,
|
||||
} from '../../exceptions';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { cache, waMonitor } from '../whatsapp.module';
|
||||
|
||||
async function getInstance(instanceName: string) {
|
||||
try {
|
||||
const db = configService.get<Database>('DATABASE');
|
||||
const redisConf = configService.get<Redis>('REDIS');
|
||||
|
||||
const exists = !!waMonitor.waInstances[instanceName];
|
||||
|
||||
if (redisConf.ENABLED) {
|
||||
const keyExists = await cache.keyExists();
|
||||
return exists || keyExists;
|
||||
}
|
||||
|
||||
if (db.ENABLED) {
|
||||
const collection = dbserver
|
||||
.getClient()
|
||||
.db(
|
||||
db.CONNECTION.DB_PREFIX_NAME +
|
||||
db.CONNECTION.DB_PREFIX_FINAL_NAME)
|
||||
.collection(instanceName);
|
||||
return exists || (await collection.find({}).toArray()).length > 0;
|
||||
}
|
||||
|
||||
return exists || existsSync(join(INSTANCE_DIR, instanceName));
|
||||
} catch (error) {
|
||||
throw new InternalServerErrorException(error?.toString());
|
||||
}
|
||||
}
|
||||
|
||||
export async function instanceExistsGuard(req: Request, _: Response, next: NextFunction) {
|
||||
if (req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const param = req.params as unknown as InstanceDto;
|
||||
if (!param?.instanceName) {
|
||||
throw new BadRequestException('"instanceName" not provided.');
|
||||
}
|
||||
|
||||
if (!(await getInstance(param.instanceName))) {
|
||||
throw new NotFoundException(`The "${param.instanceName}" instance does not exist`);
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
export async function instanceLoggedGuard(req: Request, _: Response, next: NextFunction) {
|
||||
if (req.originalUrl.includes('/instance/create')) {
|
||||
const instance = req.body as InstanceDto;
|
||||
if (await getInstance(instance.instanceName)) {
|
||||
throw new ForbiddenException(`This name "${instance.instanceName}" is already in use.`);
|
||||
}
|
||||
|
||||
if (waMonitor.waInstances[instance.instanceName]) {
|
||||
waMonitor.waInstances[instance.instanceName]?.removeRabbitmqQueues();
|
||||
delete waMonitor.waInstances[instance.instanceName];
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
40
src/whatsapp/models/contactOpenai.model.ts
Executable file → Normal file
40
src/whatsapp/models/contactOpenai.model.ts
Executable file → Normal file
@ -1,20 +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;
|
||||
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;
|
||||
|
30
src/whatsapp/models/index.ts
Executable file → Normal file
30
src/whatsapp/models/index.ts
Executable file → Normal file
@ -1,15 +1,15 @@
|
||||
export * from './auth.model';
|
||||
export * from './chamaai.model';
|
||||
export * from './chat.model';
|
||||
export * from './chatwoot.model';
|
||||
export * from './contact.model';
|
||||
export * from './message.model';
|
||||
export * from './proxy.model';
|
||||
export * from './rabbitmq.model';
|
||||
export * from './settings.model';
|
||||
export * from './sqs.model';
|
||||
export * from './typebot.model';
|
||||
export * from './webhook.model';
|
||||
export * from './websocket.model';
|
||||
export * from './openai.model';
|
||||
export * from './contactOpenai.model';
|
||||
export * from './auth.model';
|
||||
export * from './chamaai.model';
|
||||
export * from './chat.model';
|
||||
export * from './chatwoot.model';
|
||||
export * from './contact.model';
|
||||
export * from './message.model';
|
||||
export * from './proxy.model';
|
||||
export * from './rabbitmq.model';
|
||||
export * from './settings.model';
|
||||
export * from './sqs.model';
|
||||
export * from './typebot.model';
|
||||
export * from './webhook.model';
|
||||
export * from './websocket.model';
|
||||
export * from './openai.model';
|
||||
export * from './contactOpenai.model';
|
||||
|
44
src/whatsapp/models/openai.model.ts
Executable file → Normal file
44
src/whatsapp/models/openai.model.ts
Executable file → Normal file
@ -1,22 +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;
|
||||
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;
|
||||
|
34
src/whatsapp/models/sqs.model.ts
Executable file → Normal file
34
src/whatsapp/models/sqs.model.ts
Executable file → Normal file
@ -1,18 +1,18 @@
|
||||
import { Schema } from 'mongoose';
|
||||
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
|
||||
export class SqsRaw {
|
||||
_id?: string;
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
}
|
||||
|
||||
const sqsSchema = new Schema<SqsRaw>({
|
||||
_id: { type: String, _id: true },
|
||||
enabled: { type: Boolean, required: true },
|
||||
events: { type: [String], required: true },
|
||||
});
|
||||
|
||||
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
|
||||
import { Schema } from 'mongoose';
|
||||
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
|
||||
export class SqsRaw {
|
||||
_id?: string;
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
}
|
||||
|
||||
const sqsSchema = new Schema<SqsRaw>({
|
||||
_id: { type: String, _id: true },
|
||||
enabled: { type: Boolean, required: true },
|
||||
events: { type: [String], required: true },
|
||||
});
|
||||
|
||||
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
|
||||
export type ISqsModel = typeof SqsModel;
|
306
src/whatsapp/repository/openai.repository.ts
Executable file → Normal file
306
src/whatsapp/repository/openai.repository.ts
Executable file → Normal file
@ -1,153 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
338
src/whatsapp/repository/repository.manager.ts
Executable file → Normal file
338
src/whatsapp/repository/repository.manager.ts
Executable file → Normal file
@ -1,169 +1,169 @@
|
||||
import fs from 'fs';
|
||||
import { MongoClient } from 'mongodb';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { AuthRepository } from './auth.repository';
|
||||
import { ChamaaiRepository } from './chamaai.repository';
|
||||
import { ChatRepository } from './chat.repository';
|
||||
import { ChatwootRepository } from './chatwoot.repository';
|
||||
import { ContactRepository } from './contact.repository';
|
||||
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';
|
||||
import { WebhookRepository } from './webhook.repository';
|
||||
import { WebsocketRepository } from './websocket.repository';
|
||||
export class RepositoryBroker {
|
||||
constructor(
|
||||
public readonly message: MessageRepository,
|
||||
public readonly chat: ChatRepository,
|
||||
public readonly contact: ContactRepository,
|
||||
public readonly messageUpdate: MessageUpRepository,
|
||||
public readonly webhook: WebhookRepository,
|
||||
public readonly chatwoot: ChatwootRepository,
|
||||
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,
|
||||
public readonly chamaai: ChamaaiRepository,
|
||||
public readonly auth: AuthRepository,
|
||||
private configService: ConfigService,
|
||||
dbServer?: MongoClient,
|
||||
) {
|
||||
this.dbClient = dbServer;
|
||||
this.__init_repo_without_db__();
|
||||
}
|
||||
|
||||
private dbClient?: MongoClient;
|
||||
private readonly logger = new Logger('RepositoryBroker');
|
||||
|
||||
public get dbServer() {
|
||||
return this.dbClient;
|
||||
}
|
||||
|
||||
private __init_repo_without_db__() {
|
||||
this.logger.verbose('initializing repository without db');
|
||||
if (!this.configService.get<Database>('DATABASE').ENABLED) {
|
||||
const storePath = join(process.cwd(), 'store');
|
||||
|
||||
this.logger.verbose('creating store path: ' + storePath);
|
||||
try {
|
||||
const authDir = join(storePath, 'auth', this.configService.get<Auth>('AUTHENTICATION').TYPE);
|
||||
const chatsDir = join(storePath, 'chats');
|
||||
const contactsDir = join(storePath, 'contacts');
|
||||
const messagesDir = join(storePath, 'messages');
|
||||
const messageUpDir = join(storePath, 'message-up');
|
||||
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 openaiDir = join(storePath, 'openai');
|
||||
const typebotDir = join(storePath, 'typebot');
|
||||
const proxyDir = join(storePath, 'proxy');
|
||||
const chamaaiDir = join(storePath, 'chamaai');
|
||||
const tempDir = join(storePath, 'temp');
|
||||
|
||||
if (!fs.existsSync(authDir)) {
|
||||
this.logger.verbose('creating auth dir: ' + authDir);
|
||||
fs.mkdirSync(authDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chatsDir)) {
|
||||
this.logger.verbose('creating chats dir: ' + chatsDir);
|
||||
fs.mkdirSync(chatsDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(contactsDir)) {
|
||||
this.logger.verbose('creating contacts dir: ' + contactsDir);
|
||||
fs.mkdirSync(contactsDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(messagesDir)) {
|
||||
this.logger.verbose('creating messages dir: ' + messagesDir);
|
||||
fs.mkdirSync(messagesDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(messageUpDir)) {
|
||||
this.logger.verbose('creating message-up dir: ' + messageUpDir);
|
||||
fs.mkdirSync(messageUpDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(webhookDir)) {
|
||||
this.logger.verbose('creating webhook dir: ' + webhookDir);
|
||||
fs.mkdirSync(webhookDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chatwootDir)) {
|
||||
this.logger.verbose('creating chatwoot dir: ' + chatwootDir);
|
||||
fs.mkdirSync(chatwootDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(settingsDir)) {
|
||||
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 });
|
||||
}
|
||||
if (!fs.existsSync(rabbitmqDir)) {
|
||||
this.logger.verbose('creating rabbitmq dir: ' + rabbitmqDir);
|
||||
fs.mkdirSync(rabbitmqDir, { 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);
|
||||
fs.mkdirSync(typebotDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(proxyDir)) {
|
||||
this.logger.verbose('creating proxy dir: ' + proxyDir);
|
||||
fs.mkdirSync(proxyDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chamaaiDir)) {
|
||||
this.logger.verbose('creating chamaai dir: ' + chamaaiDir);
|
||||
fs.mkdirSync(chamaaiDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(tempDir)) {
|
||||
this.logger.verbose('creating temp dir: ' + tempDir);
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const storePath = join(process.cwd(), 'store');
|
||||
|
||||
this.logger.verbose('creating store path: ' + storePath);
|
||||
|
||||
const tempDir = join(storePath, 'temp');
|
||||
const chatwootDir = join(storePath, 'chatwoot');
|
||||
|
||||
if (!fs.existsSync(chatwootDir)) {
|
||||
this.logger.verbose('creating chatwoot dir: ' + chatwootDir);
|
||||
fs.mkdirSync(chatwootDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(tempDir)) {
|
||||
this.logger.verbose('creating temp dir: ' + tempDir);
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import fs from 'fs';
|
||||
import { MongoClient } from 'mongodb';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { AuthRepository } from './auth.repository';
|
||||
import { ChamaaiRepository } from './chamaai.repository';
|
||||
import { ChatRepository } from './chat.repository';
|
||||
import { ChatwootRepository } from './chatwoot.repository';
|
||||
import { ContactRepository } from './contact.repository';
|
||||
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';
|
||||
import { WebhookRepository } from './webhook.repository';
|
||||
import { WebsocketRepository } from './websocket.repository';
|
||||
export class RepositoryBroker {
|
||||
constructor(
|
||||
public readonly message: MessageRepository,
|
||||
public readonly chat: ChatRepository,
|
||||
public readonly contact: ContactRepository,
|
||||
public readonly messageUpdate: MessageUpRepository,
|
||||
public readonly webhook: WebhookRepository,
|
||||
public readonly chatwoot: ChatwootRepository,
|
||||
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,
|
||||
public readonly chamaai: ChamaaiRepository,
|
||||
public readonly auth: AuthRepository,
|
||||
private configService: ConfigService,
|
||||
dbServer?: MongoClient,
|
||||
) {
|
||||
this.dbClient = dbServer;
|
||||
this.__init_repo_without_db__();
|
||||
}
|
||||
|
||||
private dbClient?: MongoClient;
|
||||
private readonly logger = new Logger('RepositoryBroker');
|
||||
|
||||
public get dbServer() {
|
||||
return this.dbClient;
|
||||
}
|
||||
|
||||
private __init_repo_without_db__() {
|
||||
this.logger.verbose('initializing repository without db');
|
||||
if (!this.configService.get<Database>('DATABASE').ENABLED) {
|
||||
const storePath = join(process.cwd(), 'store');
|
||||
|
||||
this.logger.verbose('creating store path: ' + storePath);
|
||||
try {
|
||||
const authDir = join(storePath, 'auth', this.configService.get<Auth>('AUTHENTICATION').TYPE);
|
||||
const chatsDir = join(storePath, 'chats');
|
||||
const contactsDir = join(storePath, 'contacts');
|
||||
const messagesDir = join(storePath, 'messages');
|
||||
const messageUpDir = join(storePath, 'message-up');
|
||||
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 openaiDir = join(storePath, 'openai');
|
||||
const typebotDir = join(storePath, 'typebot');
|
||||
const proxyDir = join(storePath, 'proxy');
|
||||
const chamaaiDir = join(storePath, 'chamaai');
|
||||
const tempDir = join(storePath, 'temp');
|
||||
|
||||
if (!fs.existsSync(authDir)) {
|
||||
this.logger.verbose('creating auth dir: ' + authDir);
|
||||
fs.mkdirSync(authDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chatsDir)) {
|
||||
this.logger.verbose('creating chats dir: ' + chatsDir);
|
||||
fs.mkdirSync(chatsDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(contactsDir)) {
|
||||
this.logger.verbose('creating contacts dir: ' + contactsDir);
|
||||
fs.mkdirSync(contactsDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(messagesDir)) {
|
||||
this.logger.verbose('creating messages dir: ' + messagesDir);
|
||||
fs.mkdirSync(messagesDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(messageUpDir)) {
|
||||
this.logger.verbose('creating message-up dir: ' + messageUpDir);
|
||||
fs.mkdirSync(messageUpDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(webhookDir)) {
|
||||
this.logger.verbose('creating webhook dir: ' + webhookDir);
|
||||
fs.mkdirSync(webhookDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chatwootDir)) {
|
||||
this.logger.verbose('creating chatwoot dir: ' + chatwootDir);
|
||||
fs.mkdirSync(chatwootDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(settingsDir)) {
|
||||
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 });
|
||||
}
|
||||
if (!fs.existsSync(rabbitmqDir)) {
|
||||
this.logger.verbose('creating rabbitmq dir: ' + rabbitmqDir);
|
||||
fs.mkdirSync(rabbitmqDir, { 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);
|
||||
fs.mkdirSync(typebotDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(proxyDir)) {
|
||||
this.logger.verbose('creating proxy dir: ' + proxyDir);
|
||||
fs.mkdirSync(proxyDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(chamaaiDir)) {
|
||||
this.logger.verbose('creating chamaai dir: ' + chamaaiDir);
|
||||
fs.mkdirSync(chamaaiDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(tempDir)) {
|
||||
this.logger.verbose('creating temp dir: ' + tempDir);
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const storePath = join(process.cwd(), 'store');
|
||||
|
||||
this.logger.verbose('creating store path: ' + storePath);
|
||||
|
||||
const tempDir = join(storePath, 'temp');
|
||||
const chatwootDir = join(storePath, 'chatwoot');
|
||||
|
||||
if (!fs.existsSync(chatwootDir)) {
|
||||
this.logger.verbose('creating chatwoot dir: ' + chatwootDir);
|
||||
fs.mkdirSync(chatwootDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(tempDir)) {
|
||||
this.logger.verbose('creating temp dir: ' + tempDir);
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
122
src/whatsapp/repository/sqs.repository.ts
Executable file → Normal file
122
src/whatsapp/repository/sqs.repository.ts
Executable file → Normal file
@ -1,62 +1,62 @@
|
||||
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 { ISqsModel, SqsRaw } from '../models';
|
||||
|
||||
export class SqsRepository extends Repository {
|
||||
constructor(private readonly sqsModel: ISqsModel, private readonly configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
private readonly logger = new Logger('SqsRepository');
|
||||
|
||||
public async create(data: SqsRaw, instance: string): Promise<IInsert> {
|
||||
try {
|
||||
this.logger.verbose('creating sqs');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('saving sqs to db');
|
||||
const insert = await this.sqsModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
|
||||
|
||||
this.logger.verbose('sqs saved to db: ' + insert.modifiedCount + ' sqs');
|
||||
return { insertCount: insert.modifiedCount };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving sqs to store');
|
||||
|
||||
this.writeStore<SqsRaw>({
|
||||
path: join(this.storePath, 'sqs'),
|
||||
fileName: instance,
|
||||
data,
|
||||
});
|
||||
|
||||
this.logger.verbose('sqs saved to store in path: ' + join(this.storePath, 'sqs') + '/' + instance);
|
||||
|
||||
this.logger.verbose('sqs created');
|
||||
return { insertCount: 1 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
public async find(instance: string): Promise<SqsRaw> {
|
||||
try {
|
||||
this.logger.verbose('finding sqs');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding sqs in db');
|
||||
return await this.sqsModel.findOne({ _id: instance });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding sqs in store');
|
||||
return JSON.parse(
|
||||
readFileSync(join(this.storePath, 'sqs', instance + '.json'), {
|
||||
encoding: 'utf-8',
|
||||
}),
|
||||
) as SqsRaw;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
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 { ISqsModel, SqsRaw } from '../models';
|
||||
|
||||
export class SqsRepository extends Repository {
|
||||
constructor(private readonly sqsModel: ISqsModel, private readonly configService: ConfigService) {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
private readonly logger = new Logger('SqsRepository');
|
||||
|
||||
public async create(data: SqsRaw, instance: string): Promise<IInsert> {
|
||||
try {
|
||||
this.logger.verbose('creating sqs');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('saving sqs to db');
|
||||
const insert = await this.sqsModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
|
||||
|
||||
this.logger.verbose('sqs saved to db: ' + insert.modifiedCount + ' sqs');
|
||||
return { insertCount: insert.modifiedCount };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving sqs to store');
|
||||
|
||||
this.writeStore<SqsRaw>({
|
||||
path: join(this.storePath, 'sqs'),
|
||||
fileName: instance,
|
||||
data,
|
||||
});
|
||||
|
||||
this.logger.verbose('sqs saved to store in path: ' + join(this.storePath, 'sqs') + '/' + instance);
|
||||
|
||||
this.logger.verbose('sqs created');
|
||||
return { insertCount: 1 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
public async find(instance: string): Promise<SqsRaw> {
|
||||
try {
|
||||
this.logger.verbose('finding sqs');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding sqs in db');
|
||||
return await this.sqsModel.findOne({ _id: instance });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding sqs in store');
|
||||
return JSON.parse(
|
||||
readFileSync(join(this.storePath, 'sqs', instance + '.json'), {
|
||||
encoding: 'utf-8',
|
||||
}),
|
||||
) as SqsRaw;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
126
src/whatsapp/routers/index.router.ts
Executable file → Normal file
126
src/whatsapp/routers/index.router.ts
Executable file → Normal file
@ -1,63 +1,63 @@
|
||||
import { Router } from 'express';
|
||||
import fs from 'fs';
|
||||
|
||||
import { Auth, configService } from '../../config/env.config';
|
||||
import { authGuard } from '../guards/auth.guard';
|
||||
import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard';
|
||||
import { ChamaaiRouter } from './chamaai.router';
|
||||
import { ChatRouter } from './chat.router';
|
||||
import { ChatwootRouter } from './chatwoot.router';
|
||||
import { GroupRouter } from './group.router';
|
||||
import { InstanceRouter } from './instance.router';
|
||||
import { ProxyRouter } from './proxy.router';
|
||||
import { RabbitmqRouter } from './rabbitmq.router';
|
||||
import { OpenaiRouter } from './openai.router';
|
||||
import { MessageRouter } from './sendMessage.router';
|
||||
import { SettingsRouter } from './settings.router';
|
||||
import { SqsRouter } from './sqs.router';
|
||||
import { TypebotRouter } from './typebot.router';
|
||||
import { ViewsRouter } from './view.router';
|
||||
import { WebhookRouter } from './webhook.router';
|
||||
import { WebsocketRouter } from './websocket.router';
|
||||
|
||||
enum HttpStatus {
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
NOT_FOUND = 404,
|
||||
FORBIDDEN = 403,
|
||||
BAD_REQUEST = 400,
|
||||
UNAUTHORIZED = 401,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
const authType = configService.get<Auth>('AUTHENTICATION').TYPE;
|
||||
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard[authType]];
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
|
||||
router
|
||||
.get('/', (req, res) => {
|
||||
res.status(HttpStatus.OK).json({
|
||||
status: HttpStatus.OK,
|
||||
message: 'Api',
|
||||
// version: packageJson.version,
|
||||
// documentation: `${req.protocol}://${req.get('host')}/docs`,
|
||||
});
|
||||
})
|
||||
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
||||
.use('/manager', new ViewsRouter().router)
|
||||
.use('/message', new MessageRouter(...guards).router)
|
||||
.use('/chat', new ChatRouter(...guards).router)
|
||||
.use('/group', new GroupRouter(...guards).router)
|
||||
.use('/webhook', new WebhookRouter(...guards).router)
|
||||
.use('/chatwoot', new ChatwootRouter(...guards).router)
|
||||
.use('/settings', new SettingsRouter(...guards).router)
|
||||
.use('/websocket', new WebsocketRouter(...guards).router)
|
||||
.use('/rabbitmq', new RabbitmqRouter(...guards).router)
|
||||
.use('/openai', new OpenaiRouter(...guards).router)
|
||||
.use('/typebot', new TypebotRouter(...guards).router)
|
||||
.use('/proxy', new ProxyRouter(...guards).router)
|
||||
.use('/chamaai', new ChamaaiRouter(...guards).router);
|
||||
|
||||
export { HttpStatus, router };
|
||||
import { Router } from 'express';
|
||||
import fs from 'fs';
|
||||
|
||||
import { Auth, configService } from '../../config/env.config';
|
||||
import { authGuard } from '../guards/auth.guard';
|
||||
import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard';
|
||||
import { ChamaaiRouter } from './chamaai.router';
|
||||
import { ChatRouter } from './chat.router';
|
||||
import { ChatwootRouter } from './chatwoot.router';
|
||||
import { GroupRouter } from './group.router';
|
||||
import { InstanceRouter } from './instance.router';
|
||||
import { ProxyRouter } from './proxy.router';
|
||||
import { RabbitmqRouter } from './rabbitmq.router';
|
||||
import { OpenaiRouter } from './openai.router';
|
||||
import { MessageRouter } from './sendMessage.router';
|
||||
import { SettingsRouter } from './settings.router';
|
||||
import { SqsRouter } from './sqs.router';
|
||||
import { TypebotRouter } from './typebot.router';
|
||||
import { ViewsRouter } from './view.router';
|
||||
import { WebhookRouter } from './webhook.router';
|
||||
import { WebsocketRouter } from './websocket.router';
|
||||
|
||||
enum HttpStatus {
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
NOT_FOUND = 404,
|
||||
FORBIDDEN = 403,
|
||||
BAD_REQUEST = 400,
|
||||
UNAUTHORIZED = 401,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
const authType = configService.get<Auth>('AUTHENTICATION').TYPE;
|
||||
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard[authType]];
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
|
||||
router
|
||||
.get('/', (req, res) => {
|
||||
res.status(HttpStatus.OK).json({
|
||||
status: HttpStatus.OK,
|
||||
message: 'Api',
|
||||
// version: packageJson.version,
|
||||
// documentation: `${req.protocol}://${req.get('host')}/docs`,
|
||||
});
|
||||
})
|
||||
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
||||
.use('/manager', new ViewsRouter().router)
|
||||
.use('/message', new MessageRouter(...guards).router)
|
||||
.use('/chat', new ChatRouter(...guards).router)
|
||||
.use('/group', new GroupRouter(...guards).router)
|
||||
.use('/webhook', new WebhookRouter(...guards).router)
|
||||
.use('/chatwoot', new ChatwootRouter(...guards).router)
|
||||
.use('/settings', new SettingsRouter(...guards).router)
|
||||
.use('/websocket', new WebsocketRouter(...guards).router)
|
||||
.use('/rabbitmq', new RabbitmqRouter(...guards).router)
|
||||
.use('/openai', new OpenaiRouter(...guards).router)
|
||||
.use('/typebot', new TypebotRouter(...guards).router)
|
||||
.use('/proxy', new ProxyRouter(...guards).router)
|
||||
.use('/chamaai', new ChamaaiRouter(...guards).router);
|
||||
|
||||
export { HttpStatus, router };
|
||||
|
402
src/whatsapp/routers/instance.router.ts
Executable file → Normal file
402
src/whatsapp/routers/instance.router.ts
Executable file → Normal file
@ -1,201 +1,201 @@
|
||||
import { RequestHandler, Router } from 'express';
|
||||
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { instanceNameSchema, oldTokenSchema } from '../../validate/validate.schema';
|
||||
import { RouterBroker } from '../abstract/abstract.router';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { OldToken } from '../services/auth.service';
|
||||
import { instanceController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
|
||||
const logger = new Logger('InstanceRouter');
|
||||
|
||||
export class InstanceRouter extends RouterBroker {
|
||||
constructor(readonly configService: ConfigService, ...guards: RequestHandler[]) {
|
||||
super();
|
||||
const auth = configService.get<Auth>('AUTHENTICATION');
|
||||
this.router
|
||||
.post('/create', ...guards, async (req, res) => {
|
||||
logger.verbose('request received in createInstance');
|
||||
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) => instanceController.createInstance(instance),
|
||||
});
|
||||
|
||||
|
||||
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) => {
|
||||
logger.verbose('request received in restartInstance');
|
||||
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) => instanceController.restartInstance(instance),
|
||||
});
|
||||
|
||||
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) => {
|
||||
logger.verbose('request received in connectInstance');
|
||||
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) => instanceController.connectToWhatsapp(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('connectionState'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in connectionState');
|
||||
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) => instanceController.connectionState(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchInstances', false), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchInstances');
|
||||
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: null,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => instanceController.fetchInstances(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('logout'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in logoutInstances');
|
||||
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) => instanceController.logout(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('delete'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in deleteInstances');
|
||||
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) => instanceController.deleteInstance(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
});
|
||||
|
||||
if (auth.TYPE === 'jwt') {
|
||||
this.router.put('/refreshToken', async (req, res) => {
|
||||
logger.verbose('request received in refreshToken');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<OldToken>({
|
||||
request: req,
|
||||
schema: oldTokenSchema,
|
||||
ClassRef: OldToken,
|
||||
execute: (_, data) => instanceController.refreshToken(_, data),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
});
|
||||
}
|
||||
|
||||
this.router.delete('/deleteDatabase', async (req, res) => {
|
||||
logger.verbose('request received in deleteDatabase');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const db = this.configService.get<Database>('DATABASE');
|
||||
if (db.ENABLED) {
|
||||
try {
|
||||
await dbserver.dropDatabase();
|
||||
return res
|
||||
.status(HttpStatus.CREATED)
|
||||
.json({ status: 'SUCCESS', error: false, response: { message: 'database deleted' } });
|
||||
} catch (error) {
|
||||
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ error: true, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ error: true, message: 'Database is not enabled' });
|
||||
});
|
||||
}
|
||||
|
||||
public readonly router = Router();
|
||||
}
|
||||
import { RequestHandler, Router } from 'express';
|
||||
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { instanceNameSchema, oldTokenSchema } from '../../validate/validate.schema';
|
||||
import { RouterBroker } from '../abstract/abstract.router';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { OldToken } from '../services/auth.service';
|
||||
import { instanceController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
|
||||
const logger = new Logger('InstanceRouter');
|
||||
|
||||
export class InstanceRouter extends RouterBroker {
|
||||
constructor(readonly configService: ConfigService, ...guards: RequestHandler[]) {
|
||||
super();
|
||||
const auth = configService.get<Auth>('AUTHENTICATION');
|
||||
this.router
|
||||
.post('/create', ...guards, async (req, res) => {
|
||||
logger.verbose('request received in createInstance');
|
||||
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) => instanceController.createInstance(instance),
|
||||
});
|
||||
|
||||
|
||||
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) => {
|
||||
logger.verbose('request received in restartInstance');
|
||||
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) => instanceController.restartInstance(instance),
|
||||
});
|
||||
|
||||
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) => {
|
||||
logger.verbose('request received in connectInstance');
|
||||
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) => instanceController.connectToWhatsapp(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('connectionState'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in connectionState');
|
||||
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) => instanceController.connectionState(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchInstances', false), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchInstances');
|
||||
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: null,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => instanceController.fetchInstances(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('logout'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in logoutInstances');
|
||||
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) => instanceController.logout(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('delete'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in deleteInstances');
|
||||
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) => instanceController.deleteInstance(instance),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
});
|
||||
|
||||
if (auth.TYPE === 'jwt') {
|
||||
this.router.put('/refreshToken', async (req, res) => {
|
||||
logger.verbose('request received in refreshToken');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<OldToken>({
|
||||
request: req,
|
||||
schema: oldTokenSchema,
|
||||
ClassRef: OldToken,
|
||||
execute: (_, data) => instanceController.refreshToken(_, data),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
});
|
||||
}
|
||||
|
||||
this.router.delete('/deleteDatabase', async (req, res) => {
|
||||
logger.verbose('request received in deleteDatabase');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const db = this.configService.get<Database>('DATABASE');
|
||||
if (db.ENABLED) {
|
||||
try {
|
||||
await dbserver.dropDatabase();
|
||||
return res
|
||||
.status(HttpStatus.CREATED)
|
||||
.json({ status: 'SUCCESS', error: false, response: { message: 'database deleted' } });
|
||||
} catch (error) {
|
||||
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ error: true, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ error: true, message: 'Database is not enabled' });
|
||||
});
|
||||
}
|
||||
|
||||
public readonly router = Router();
|
||||
}
|
||||
|
172
src/whatsapp/routers/openai.router.ts
Executable file → Normal file
172
src/whatsapp/routers/openai.router.ts
Executable file → Normal file
@ -1,86 +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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
102
src/whatsapp/routers/sqs.router.ts
Executable file → Normal file
102
src/whatsapp/routers/sqs.router.ts
Executable file → Normal file
@ -1,52 +1,52 @@
|
||||
import { RequestHandler, Router } from 'express';
|
||||
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { instanceNameSchema, sqsSchema } from '../../validate/validate.schema';
|
||||
import { RouterBroker } from '../abstract/abstract.router';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { sqsController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
|
||||
const logger = new Logger('SqsRouter');
|
||||
|
||||
export class SqsRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('set'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in setSqs');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SqsDto>({
|
||||
request: req,
|
||||
schema: sqsSchema,
|
||||
ClassRef: SqsDto,
|
||||
execute: (instance, data) => sqsController.createSqs(instance, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.get(this.routerPath('find'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findSqs');
|
||||
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) => sqsController.findSqs(instance),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
});
|
||||
}
|
||||
|
||||
public readonly router = Router();
|
||||
import { RequestHandler, Router } from 'express';
|
||||
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { instanceNameSchema, sqsSchema } from '../../validate/validate.schema';
|
||||
import { RouterBroker } from '../abstract/abstract.router';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { sqsController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
|
||||
const logger = new Logger('SqsRouter');
|
||||
|
||||
export class SqsRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('set'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in setSqs');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SqsDto>({
|
||||
request: req,
|
||||
schema: sqsSchema,
|
||||
ClassRef: SqsDto,
|
||||
execute: (instance, data) => sqsController.createSqs(instance, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.get(this.routerPath('find'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findSqs');
|
||||
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) => sqsController.findSqs(instance),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
});
|
||||
}
|
||||
|
||||
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.
3316
src/whatsapp/services/chatwoot.service.ts
Executable file → Normal file
3316
src/whatsapp/services/chatwoot.service.ts
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
796
src/whatsapp/services/monitor.service.ts
Executable file → Normal file
796
src/whatsapp/services/monitor.service.ts
Executable file → Normal file
@ -1,398 +1,398 @@
|
||||
import { execSync } from 'child_process';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
import { opendirSync, readdirSync, rmSync } from 'fs';
|
||||
import { Db } from 'mongodb';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, ConfigService, Database, DelInstance, HttpServer, Redis } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config';
|
||||
import { NotFoundException } from '../../exceptions';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { RedisCache } from '../../libs/redis.client';
|
||||
import {
|
||||
AuthModel,
|
||||
ChamaaiModel,
|
||||
ChatModel,
|
||||
ChatwootModel,
|
||||
ContactModel,
|
||||
MessageModel,
|
||||
MessageUpModel,
|
||||
ProxyModel,
|
||||
RabbitmqModel,
|
||||
SettingsModel,
|
||||
TypebotModel,
|
||||
WebhookModel,
|
||||
WebsocketModel,
|
||||
|
||||
} from '../models';
|
||||
import { RepositoryBroker } from '../repository/repository.manager';
|
||||
import { WAStartupService } from './whatsapp.service';
|
||||
|
||||
export class WAMonitoringService {
|
||||
constructor(
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly repository: RepositoryBroker,
|
||||
private readonly cache: RedisCache,
|
||||
) {
|
||||
this.logger.verbose('instance created');
|
||||
|
||||
this.removeInstance();
|
||||
this.noConnection();
|
||||
this.delInstanceFiles();
|
||||
|
||||
Object.assign(this.db, configService.get<Database>('DATABASE'));
|
||||
Object.assign(this.redis, configService.get<Redis>('REDIS'));
|
||||
|
||||
this.dbInstance = this.db.ENABLED
|
||||
? this.repository.dbServer?.db(
|
||||
this.db.CONNECTION.DB_PREFIX_NAME +
|
||||
this.db.CONNECTION.DB_PREFIX_FINAL_NAME
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
private readonly db: Partial<Database> = {};
|
||||
private readonly redis: Partial<Redis> = {};
|
||||
|
||||
private dbInstance: Db;
|
||||
|
||||
private dbStore = dbserver;
|
||||
|
||||
private readonly logger = new Logger(WAMonitoringService.name);
|
||||
public readonly waInstances: Record<string, WAStartupService> = {};
|
||||
|
||||
public delInstanceTime(instance: string) {
|
||||
const time = this.configService.get<DelInstance>('DEL_INSTANCE');
|
||||
if (typeof time === 'number' && time > 0) {
|
||||
this.logger.verbose(`Instance "${instance}" don't have connection, will be removed in ${time} minutes`);
|
||||
|
||||
setTimeout(async () => {
|
||||
if (this.waInstances[instance]?.connectionStatus?.state !== 'open') {
|
||||
if (this.waInstances[instance]?.connectionStatus?.state === 'connecting') {
|
||||
await this.waInstances[instance]?.client?.logout('Log out instance: ' + instance);
|
||||
this.waInstances[instance]?.client?.ws?.close();
|
||||
this.waInstances[instance]?.client?.end(undefined);
|
||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||
delete this.waInstances[instance];
|
||||
} else {
|
||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||
delete this.waInstances[instance];
|
||||
this.eventEmitter.emit('remove.instance', instance, 'inner');
|
||||
}
|
||||
}
|
||||
}, 1000 * 60 * time);
|
||||
}
|
||||
}
|
||||
|
||||
public async instanceInfo(instanceName?: string) {
|
||||
this.logger.verbose('get instance info');
|
||||
if (instanceName && !this.waInstances[instanceName]) {
|
||||
throw new NotFoundException(`Instance "${instanceName}" not found`);
|
||||
}
|
||||
|
||||
const instances: any[] = [];
|
||||
|
||||
for await (const [key, value] of Object.entries(this.waInstances)) {
|
||||
if (value) {
|
||||
this.logger.verbose('get instance info: ' + key);
|
||||
let chatwoot: any;
|
||||
|
||||
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const findChatwoot = await this.waInstances[key].findChatwoot();
|
||||
|
||||
if (findChatwoot && findChatwoot.enabled) {
|
||||
chatwoot = {
|
||||
...findChatwoot,
|
||||
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(key)}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (value.connectionStatus.state === 'open') {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: open');
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
owner: value.wuid,
|
||||
profileName: (await value.getProfileName()) || 'not loaded',
|
||||
profilePictureUrl: value.profilePictureUrl,
|
||||
profileStatus: (await value.getProfileStatus()) || '',
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
} else {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: ' + value.connectionStatus.state);
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('return instance info: ' + instances.length);
|
||||
|
||||
return instances.find((i) => i.instance.instanceName === instanceName) ?? instances;
|
||||
}
|
||||
|
||||
private delInstanceFiles() {
|
||||
this.logger.verbose('cron to delete instance files started');
|
||||
setInterval(async () => {
|
||||
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
const collections = await this.dbInstance.collections();
|
||||
collections.forEach(async (collection) => {
|
||||
const name = collection.namespace.replace(/^[\w-]+./, '');
|
||||
await this.dbInstance.collection(name).deleteMany({
|
||||
$or: [{ _id: { $regex: /^app.state.*/ } }, { _id: { $regex: /^session-.*/ } }],
|
||||
});
|
||||
this.logger.verbose('instance files deleted: ' + name);
|
||||
});
|
||||
} else if (!this.redis.ENABLED) {
|
||||
const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' });
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isDirectory()) {
|
||||
const files = readdirSync(join(INSTANCE_DIR, dirent.name), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
files.forEach(async (file) => {
|
||||
if (file.match(/^app.state.*/) || file.match(/^session-.*/)) {
|
||||
rmSync(join(INSTANCE_DIR, dirent.name, file), {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.logger.verbose('instance files deleted: ' + dirent.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3600 * 1000 * 2);
|
||||
}
|
||||
|
||||
public async cleaningUp(instanceName: string) {
|
||||
this.logger.verbose('cleaning up instance: ' + instanceName);
|
||||
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
this.logger.verbose('cleaning up instance in database: ' + instanceName);
|
||||
await this.repository.dbServer.connect();
|
||||
const collections: any[] = await this.dbInstance.collections();
|
||||
if (collections.length > 0) {
|
||||
await this.dbInstance.dropCollection(instanceName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.redis.ENABLED) {
|
||||
this.logger.verbose('cleaning up instance in redis: ' + instanceName);
|
||||
this.cache.reference = instanceName;
|
||||
await this.cache.delAll();
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('cleaning up instance in files: ' + instanceName);
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
}
|
||||
|
||||
public async cleaningStoreFiles(instanceName: string) {
|
||||
if (!this.db.ENABLED) {
|
||||
this.logger.verbose('cleaning store files instance: ' + instanceName);
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chats', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'contacts', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'message-up', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'messages', instanceName)}`);
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'auth', 'apikey', instanceName + '.json')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'webhook', instanceName + '.json')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chatwoot', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chamaai', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'proxy', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'rabbitmq', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'typebot', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'websocket', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'settings', instanceName + '*')}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('cleaning store database instance: ' + instanceName);
|
||||
|
||||
await AuthModel.deleteMany({ owner: instanceName });
|
||||
await ChatModel.deleteMany({ owner: instanceName });
|
||||
await ContactModel.deleteMany({ owner: instanceName });
|
||||
await MessageModel.deleteMany({ owner: instanceName });
|
||||
|
||||
await MessageUpModel.deleteMany({ owner: instanceName });
|
||||
await WebhookModel.deleteMany({ _id: instanceName });
|
||||
await ChatwootModel.deleteMany({ _id: instanceName });
|
||||
|
||||
await ChamaaiModel.deleteMany({ _id: instanceName });
|
||||
await ProxyModel.deleteMany({ _id: instanceName });
|
||||
await RabbitmqModel.deleteMany({ _id: instanceName });
|
||||
await TypebotModel.deleteMany({ _id: instanceName });
|
||||
await WebsocketModel.deleteMany({ _id: instanceName });
|
||||
|
||||
await SettingsModel.deleteMany({ _id: instanceName });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public async loadInstance() {
|
||||
this.logger.verbose('Loading instances');
|
||||
|
||||
try {
|
||||
if (this.redis.ENABLED) {
|
||||
await this.loadInstancesFromRedis();
|
||||
} else if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
await this.loadInstancesFromDatabase();
|
||||
} else {
|
||||
await this.loadInstancesFromFiles();
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async setInstance(name: string) {
|
||||
const instance = new WAStartupService(this.configService, this.eventEmitter, this.repository, this.cache);
|
||||
instance.instanceName = name;
|
||||
this.logger.verbose('Instance loaded: ' + name);
|
||||
|
||||
await instance.connectToWhatsapp();
|
||||
this.logger.verbose('connectToWhatsapp: ' + name);
|
||||
|
||||
this.waInstances[name] = instance;
|
||||
}
|
||||
|
||||
private async loadInstancesFromRedis() {
|
||||
this.logger.verbose('Redis enabled');
|
||||
await this.cache.connect(this.redis as Redis);
|
||||
const keys = await this.cache.instanceKeys();
|
||||
|
||||
if (keys?.length > 0) {
|
||||
this.logger.verbose('Reading instance keys and setting instances');
|
||||
await Promise.all(keys.map((k) => this.setInstance(k.split(':')[1])));
|
||||
} else {
|
||||
this.logger.verbose('No instance keys found');
|
||||
}
|
||||
}
|
||||
|
||||
private async loadInstancesFromDatabase() {
|
||||
this.logger.verbose('Database enabled');
|
||||
await this.repository.dbServer.connect();
|
||||
const collections: any[] = await this.dbInstance.collections();
|
||||
|
||||
if (collections.length > 0) {
|
||||
this.logger.verbose('Reading collections and setting instances');
|
||||
await Promise.all(collections.map((coll) => this.setInstance(coll.namespace.replace(/^[\w-]+\./, ''))));
|
||||
} else {
|
||||
this.logger.verbose('No collections found');
|
||||
}
|
||||
}
|
||||
|
||||
private async loadInstancesFromFiles() {
|
||||
this.logger.verbose('Store in files enabled');
|
||||
const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' });
|
||||
const instanceDirs = [];
|
||||
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isDirectory()) {
|
||||
instanceDirs.push(dirent.name);
|
||||
} else {
|
||||
this.logger.verbose('No instance files found');
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
instanceDirs.map(async (instanceName) => {
|
||||
this.logger.verbose('Reading instance files and setting instances: ' + instanceName);
|
||||
const files = readdirSync(join(INSTANCE_DIR, instanceName), { encoding: 'utf-8' });
|
||||
|
||||
if (files.length === 0) {
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
} else {
|
||||
await this.setInstance(instanceName);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private removeInstance() {
|
||||
this.eventEmitter.on('remove.instance', async (instanceName: string) => {
|
||||
this.logger.verbose('remove instance: ' + instanceName);
|
||||
try {
|
||||
this.logger.verbose('instance: ' + instanceName + ' - removing from memory');
|
||||
this.waInstances[instanceName] = undefined;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
|
||||
try {
|
||||
this.logger.verbose('request cleaning up instance: ' + instanceName);
|
||||
this.cleaningUp(instanceName);
|
||||
this.cleaningStoreFiles(instanceName);
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - REMOVED`);
|
||||
}
|
||||
});
|
||||
this.eventEmitter.on('logout.instance', async (instanceName: string) => {
|
||||
this.logger.verbose('logout instance: ' + instanceName);
|
||||
try {
|
||||
this.logger.verbose('request cleaning up instance: ' + instanceName);
|
||||
this.cleaningUp(instanceName);
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - LOGOUT`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private noConnection() {
|
||||
this.logger.verbose('checking instances without connection');
|
||||
this.eventEmitter.on('no.connection', async (instanceName) => {
|
||||
try {
|
||||
this.logger.verbose('logging out instance: ' + instanceName);
|
||||
await this.waInstances[instanceName]?.client?.logout('Log out instance: ' + instanceName);
|
||||
|
||||
this.logger.verbose('close connection instance: ' + instanceName);
|
||||
this.waInstances[instanceName]?.client?.ws?.close();
|
||||
|
||||
this.waInstances[instanceName].instance.qrcode = { count: 0 };
|
||||
this.waInstances[instanceName].stateConnection.state = 'close';
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
localError: 'noConnection',
|
||||
warn: 'Error deleting instance from memory.',
|
||||
error,
|
||||
});
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - NOT CONNECTION`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
import { execSync } from 'child_process';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
import { opendirSync, readdirSync, rmSync } from 'fs';
|
||||
import { Db } from 'mongodb';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Auth, ConfigService, Database, DelInstance, HttpServer, Redis } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config';
|
||||
import { NotFoundException } from '../../exceptions';
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { RedisCache } from '../../libs/redis.client';
|
||||
import {
|
||||
AuthModel,
|
||||
ChamaaiModel,
|
||||
ChatModel,
|
||||
ChatwootModel,
|
||||
ContactModel,
|
||||
MessageModel,
|
||||
MessageUpModel,
|
||||
ProxyModel,
|
||||
RabbitmqModel,
|
||||
SettingsModel,
|
||||
TypebotModel,
|
||||
WebhookModel,
|
||||
WebsocketModel,
|
||||
|
||||
} from '../models';
|
||||
import { RepositoryBroker } from '../repository/repository.manager';
|
||||
import { WAStartupService } from './whatsapp.service';
|
||||
|
||||
export class WAMonitoringService {
|
||||
constructor(
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly repository: RepositoryBroker,
|
||||
private readonly cache: RedisCache,
|
||||
) {
|
||||
this.logger.verbose('instance created');
|
||||
|
||||
this.removeInstance();
|
||||
this.noConnection();
|
||||
this.delInstanceFiles();
|
||||
|
||||
Object.assign(this.db, configService.get<Database>('DATABASE'));
|
||||
Object.assign(this.redis, configService.get<Redis>('REDIS'));
|
||||
|
||||
this.dbInstance = this.db.ENABLED
|
||||
? this.repository.dbServer?.db(
|
||||
this.db.CONNECTION.DB_PREFIX_NAME +
|
||||
this.db.CONNECTION.DB_PREFIX_FINAL_NAME
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
private readonly db: Partial<Database> = {};
|
||||
private readonly redis: Partial<Redis> = {};
|
||||
|
||||
private dbInstance: Db;
|
||||
|
||||
private dbStore = dbserver;
|
||||
|
||||
private readonly logger = new Logger(WAMonitoringService.name);
|
||||
public readonly waInstances: Record<string, WAStartupService> = {};
|
||||
|
||||
public delInstanceTime(instance: string) {
|
||||
const time = this.configService.get<DelInstance>('DEL_INSTANCE');
|
||||
if (typeof time === 'number' && time > 0) {
|
||||
this.logger.verbose(`Instance "${instance}" don't have connection, will be removed in ${time} minutes`);
|
||||
|
||||
setTimeout(async () => {
|
||||
if (this.waInstances[instance]?.connectionStatus?.state !== 'open') {
|
||||
if (this.waInstances[instance]?.connectionStatus?.state === 'connecting') {
|
||||
await this.waInstances[instance]?.client?.logout('Log out instance: ' + instance);
|
||||
this.waInstances[instance]?.client?.ws?.close();
|
||||
this.waInstances[instance]?.client?.end(undefined);
|
||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||
delete this.waInstances[instance];
|
||||
} else {
|
||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||
delete this.waInstances[instance];
|
||||
this.eventEmitter.emit('remove.instance', instance, 'inner');
|
||||
}
|
||||
}
|
||||
}, 1000 * 60 * time);
|
||||
}
|
||||
}
|
||||
|
||||
public async instanceInfo(instanceName?: string) {
|
||||
this.logger.verbose('get instance info');
|
||||
if (instanceName && !this.waInstances[instanceName]) {
|
||||
throw new NotFoundException(`Instance "${instanceName}" not found`);
|
||||
}
|
||||
|
||||
const instances: any[] = [];
|
||||
|
||||
for await (const [key, value] of Object.entries(this.waInstances)) {
|
||||
if (value) {
|
||||
this.logger.verbose('get instance info: ' + key);
|
||||
let chatwoot: any;
|
||||
|
||||
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const findChatwoot = await this.waInstances[key].findChatwoot();
|
||||
|
||||
if (findChatwoot && findChatwoot.enabled) {
|
||||
chatwoot = {
|
||||
...findChatwoot,
|
||||
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(key)}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (value.connectionStatus.state === 'open') {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: open');
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
owner: value.wuid,
|
||||
profileName: (await value.getProfileName()) || 'not loaded',
|
||||
profilePictureUrl: value.profilePictureUrl,
|
||||
profileStatus: (await value.getProfileStatus()) || '',
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
} else {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: ' + value.connectionStatus.state);
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key))?.apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('return instance info: ' + instances.length);
|
||||
|
||||
return instances.find((i) => i.instance.instanceName === instanceName) ?? instances;
|
||||
}
|
||||
|
||||
private delInstanceFiles() {
|
||||
this.logger.verbose('cron to delete instance files started');
|
||||
setInterval(async () => {
|
||||
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
const collections = await this.dbInstance.collections();
|
||||
collections.forEach(async (collection) => {
|
||||
const name = collection.namespace.replace(/^[\w-]+./, '');
|
||||
await this.dbInstance.collection(name).deleteMany({
|
||||
$or: [{ _id: { $regex: /^app.state.*/ } }, { _id: { $regex: /^session-.*/ } }],
|
||||
});
|
||||
this.logger.verbose('instance files deleted: ' + name);
|
||||
});
|
||||
} else if (!this.redis.ENABLED) {
|
||||
const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' });
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isDirectory()) {
|
||||
const files = readdirSync(join(INSTANCE_DIR, dirent.name), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
files.forEach(async (file) => {
|
||||
if (file.match(/^app.state.*/) || file.match(/^session-.*/)) {
|
||||
rmSync(join(INSTANCE_DIR, dirent.name, file), {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.logger.verbose('instance files deleted: ' + dirent.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3600 * 1000 * 2);
|
||||
}
|
||||
|
||||
public async cleaningUp(instanceName: string) {
|
||||
this.logger.verbose('cleaning up instance: ' + instanceName);
|
||||
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
this.logger.verbose('cleaning up instance in database: ' + instanceName);
|
||||
await this.repository.dbServer.connect();
|
||||
const collections: any[] = await this.dbInstance.collections();
|
||||
if (collections.length > 0) {
|
||||
await this.dbInstance.dropCollection(instanceName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.redis.ENABLED) {
|
||||
this.logger.verbose('cleaning up instance in redis: ' + instanceName);
|
||||
this.cache.reference = instanceName;
|
||||
await this.cache.delAll();
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('cleaning up instance in files: ' + instanceName);
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
}
|
||||
|
||||
public async cleaningStoreFiles(instanceName: string) {
|
||||
if (!this.db.ENABLED) {
|
||||
this.logger.verbose('cleaning store files instance: ' + instanceName);
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chats', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'contacts', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'message-up', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'messages', instanceName)}`);
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'auth', 'apikey', instanceName + '.json')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'webhook', instanceName + '.json')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chatwoot', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chamaai', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'proxy', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'rabbitmq', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'typebot', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'websocket', instanceName + '*')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'settings', instanceName + '*')}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('cleaning store database instance: ' + instanceName);
|
||||
|
||||
await AuthModel.deleteMany({ owner: instanceName });
|
||||
await ChatModel.deleteMany({ owner: instanceName });
|
||||
await ContactModel.deleteMany({ owner: instanceName });
|
||||
await MessageModel.deleteMany({ owner: instanceName });
|
||||
|
||||
await MessageUpModel.deleteMany({ owner: instanceName });
|
||||
await WebhookModel.deleteMany({ _id: instanceName });
|
||||
await ChatwootModel.deleteMany({ _id: instanceName });
|
||||
|
||||
await ChamaaiModel.deleteMany({ _id: instanceName });
|
||||
await ProxyModel.deleteMany({ _id: instanceName });
|
||||
await RabbitmqModel.deleteMany({ _id: instanceName });
|
||||
await TypebotModel.deleteMany({ _id: instanceName });
|
||||
await WebsocketModel.deleteMany({ _id: instanceName });
|
||||
|
||||
await SettingsModel.deleteMany({ _id: instanceName });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public async loadInstance() {
|
||||
this.logger.verbose('Loading instances');
|
||||
|
||||
try {
|
||||
if (this.redis.ENABLED) {
|
||||
await this.loadInstancesFromRedis();
|
||||
} else if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
|
||||
await this.loadInstancesFromDatabase();
|
||||
} else {
|
||||
await this.loadInstancesFromFiles();
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async setInstance(name: string) {
|
||||
const instance = new WAStartupService(this.configService, this.eventEmitter, this.repository, this.cache);
|
||||
instance.instanceName = name;
|
||||
this.logger.verbose('Instance loaded: ' + name);
|
||||
|
||||
await instance.connectToWhatsapp();
|
||||
this.logger.verbose('connectToWhatsapp: ' + name);
|
||||
|
||||
this.waInstances[name] = instance;
|
||||
}
|
||||
|
||||
private async loadInstancesFromRedis() {
|
||||
this.logger.verbose('Redis enabled');
|
||||
await this.cache.connect(this.redis as Redis);
|
||||
const keys = await this.cache.instanceKeys();
|
||||
|
||||
if (keys?.length > 0) {
|
||||
this.logger.verbose('Reading instance keys and setting instances');
|
||||
await Promise.all(keys.map((k) => this.setInstance(k.split(':')[1])));
|
||||
} else {
|
||||
this.logger.verbose('No instance keys found');
|
||||
}
|
||||
}
|
||||
|
||||
private async loadInstancesFromDatabase() {
|
||||
this.logger.verbose('Database enabled');
|
||||
await this.repository.dbServer.connect();
|
||||
const collections: any[] = await this.dbInstance.collections();
|
||||
|
||||
if (collections.length > 0) {
|
||||
this.logger.verbose('Reading collections and setting instances');
|
||||
await Promise.all(collections.map((coll) => this.setInstance(coll.namespace.replace(/^[\w-]+\./, ''))));
|
||||
} else {
|
||||
this.logger.verbose('No collections found');
|
||||
}
|
||||
}
|
||||
|
||||
private async loadInstancesFromFiles() {
|
||||
this.logger.verbose('Store in files enabled');
|
||||
const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' });
|
||||
const instanceDirs = [];
|
||||
|
||||
for await (const dirent of dir) {
|
||||
if (dirent.isDirectory()) {
|
||||
instanceDirs.push(dirent.name);
|
||||
} else {
|
||||
this.logger.verbose('No instance files found');
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
instanceDirs.map(async (instanceName) => {
|
||||
this.logger.verbose('Reading instance files and setting instances: ' + instanceName);
|
||||
const files = readdirSync(join(INSTANCE_DIR, instanceName), { encoding: 'utf-8' });
|
||||
|
||||
if (files.length === 0) {
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
} else {
|
||||
await this.setInstance(instanceName);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private removeInstance() {
|
||||
this.eventEmitter.on('remove.instance', async (instanceName: string) => {
|
||||
this.logger.verbose('remove instance: ' + instanceName);
|
||||
try {
|
||||
this.logger.verbose('instance: ' + instanceName + ' - removing from memory');
|
||||
this.waInstances[instanceName] = undefined;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
|
||||
try {
|
||||
this.logger.verbose('request cleaning up instance: ' + instanceName);
|
||||
this.cleaningUp(instanceName);
|
||||
this.cleaningStoreFiles(instanceName);
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - REMOVED`);
|
||||
}
|
||||
});
|
||||
this.eventEmitter.on('logout.instance', async (instanceName: string) => {
|
||||
this.logger.verbose('logout instance: ' + instanceName);
|
||||
try {
|
||||
this.logger.verbose('request cleaning up instance: ' + instanceName);
|
||||
this.cleaningUp(instanceName);
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - LOGOUT`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private noConnection() {
|
||||
this.logger.verbose('checking instances without connection');
|
||||
this.eventEmitter.on('no.connection', async (instanceName) => {
|
||||
try {
|
||||
this.logger.verbose('logging out instance: ' + instanceName);
|
||||
await this.waInstances[instanceName]?.client?.logout('Log out instance: ' + instanceName);
|
||||
|
||||
this.logger.verbose('close connection instance: ' + instanceName);
|
||||
this.waInstances[instanceName]?.client?.ws?.close();
|
||||
|
||||
this.waInstances[instanceName].instance.qrcode = { count: 0 };
|
||||
this.waInstances[instanceName].stateConnection.state = 'close';
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
localError: 'noConnection',
|
||||
warn: 'Error deleting instance from memory.',
|
||||
error,
|
||||
});
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - NOT CONNECTION`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
114
src/whatsapp/services/openai.service.ts
Executable file → Normal file
114
src/whatsapp/services/openai.service.ts
Executable file → Normal file
@ -1,57 +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: [] };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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: [] };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
68
src/whatsapp/services/sqs.service.ts
Executable file → Normal file
68
src/whatsapp/services/sqs.service.ts
Executable file → Normal file
@ -1,35 +1,35 @@
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { initQueues } from '../../libs/sqs.server';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { SqsRaw } from '../models';
|
||||
import { WAMonitoringService } from './monitor.service';
|
||||
|
||||
export class SqsService {
|
||||
constructor(private readonly waMonitor: WAMonitoringService) { }
|
||||
|
||||
private readonly logger = new Logger(SqsService.name);
|
||||
|
||||
public create(instance: InstanceDto, data: SqsDto) {
|
||||
this.logger.verbose('create sqs: ' + instance.instanceName);
|
||||
this.waMonitor.waInstances[instance.instanceName].setSqs(data);
|
||||
|
||||
initQueues(instance.instanceName, data.events);
|
||||
return { sqs: { ...instance, sqs: data } };
|
||||
}
|
||||
|
||||
public async find(instance: InstanceDto): Promise<SqsRaw> {
|
||||
try {
|
||||
this.logger.verbose('find sqs: ' + instance.instanceName);
|
||||
const result = await this.waMonitor.waInstances[instance.instanceName].findSqs();
|
||||
|
||||
if (Object.keys(result).length === 0) {
|
||||
throw new Error('Sqs not found');
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
return { enabled: false, events: [] };
|
||||
}
|
||||
}
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { initQueues } from '../../libs/sqs.server';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { SqsDto } from '../dto/sqs.dto';
|
||||
import { SqsRaw } from '../models';
|
||||
import { WAMonitoringService } from './monitor.service';
|
||||
|
||||
export class SqsService {
|
||||
constructor(private readonly waMonitor: WAMonitoringService) { }
|
||||
|
||||
private readonly logger = new Logger(SqsService.name);
|
||||
|
||||
public create(instance: InstanceDto, data: SqsDto) {
|
||||
this.logger.verbose('create sqs: ' + instance.instanceName);
|
||||
this.waMonitor.waInstances[instance.instanceName].setSqs(data);
|
||||
|
||||
initQueues(instance.instanceName, data.events);
|
||||
return { sqs: { ...instance, sqs: data } };
|
||||
}
|
||||
|
||||
public async find(instance: InstanceDto): Promise<SqsRaw> {
|
||||
try {
|
||||
this.logger.verbose('find sqs: ' + instance.instanceName);
|
||||
const result = await this.waMonitor.waInstances[instance.instanceName].findSqs();
|
||||
|
||||
if (Object.keys(result).length === 0) {
|
||||
throw new Error('Sqs not found');
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
return { enabled: false, events: [] };
|
||||
}
|
||||
}
|
||||
}
|
2020
src/whatsapp/services/typebot.service.ts
Executable file → Normal file
2020
src/whatsapp/services/typebot.service.ts
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
7682
src/whatsapp/services/whatsapp.service.ts
Executable file → Normal file
7682
src/whatsapp/services/whatsapp.service.ts
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
290
src/whatsapp/types/wa.types.ts
Executable file → Normal file
290
src/whatsapp/types/wa.types.ts
Executable file → Normal file
@ -1,145 +1,145 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { AuthenticationState, WAConnectionState } from '@whiskeysockets/baileys';
|
||||
|
||||
export enum Events {
|
||||
APPLICATION_STARTUP = 'application.startup',
|
||||
QRCODE_UPDATED = 'qrcode.updated',
|
||||
CONNECTION_UPDATE = 'connection.update',
|
||||
STATUS_INSTANCE = 'status.instance',
|
||||
MESSAGES_SET = 'messages.set',
|
||||
MESSAGES_UPSERT = 'messages.upsert',
|
||||
MESSAGES_UPDATE = 'messages.update',
|
||||
MESSAGES_DELETE = 'messages.delete',
|
||||
SEND_MESSAGE = 'send.message',
|
||||
CONTACTS_SET = 'contacts.set',
|
||||
CONTACTS_UPSERT = 'contacts.upsert',
|
||||
CONTACTS_UPDATE = 'contacts.update',
|
||||
PRESENCE_UPDATE = 'presence.update',
|
||||
CHATS_SET = 'chats.set',
|
||||
CHATS_UPDATE = 'chats.update',
|
||||
CHATS_UPSERT = 'chats.upsert',
|
||||
CHATS_DELETE = 'chats.delete',
|
||||
GROUPS_UPSERT = 'groups.upsert',
|
||||
GROUPS_UPDATE = 'groups.update',
|
||||
GROUP_PARTICIPANTS_UPDATE = 'group-participants.update',
|
||||
CALL = 'call',
|
||||
TYPEBOT_START = 'typebot.start',
|
||||
TYPEBOT_CHANGE_STATUS = 'typebot.change-status',
|
||||
CHAMA_AI_ACTION = 'chama-ai.action',
|
||||
}
|
||||
|
||||
export declare namespace wa {
|
||||
export type QrCode = {
|
||||
count?: number;
|
||||
pairingCode?: string;
|
||||
base64?: string;
|
||||
code?: string;
|
||||
};
|
||||
export type Instance = {
|
||||
qrcode?: QrCode;
|
||||
pairingCode?: string;
|
||||
authState?: { state: AuthenticationState; saveCreds: () => void };
|
||||
name?: string;
|
||||
wuid?: string;
|
||||
profileName?: string;
|
||||
profilePictureUrl?: string;
|
||||
};
|
||||
|
||||
export type LocalWebHook = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
events?: string[];
|
||||
webhook_by_events?: boolean;
|
||||
webhook_base64?: boolean;
|
||||
};
|
||||
|
||||
export type LocalChatwoot = {
|
||||
enabled?: boolean;
|
||||
account_id?: string;
|
||||
token?: string;
|
||||
url?: string;
|
||||
name_inbox?: string;
|
||||
sign_msg?: boolean;
|
||||
number?: string;
|
||||
reopen_conversation?: boolean;
|
||||
conversation_pending?: boolean;
|
||||
};
|
||||
|
||||
export type LocalSettings = {
|
||||
reject_call?: boolean;
|
||||
msg_call?: string;
|
||||
groups_ignore?: boolean;
|
||||
always_online?: boolean;
|
||||
read_messages?: boolean;
|
||||
read_status?: boolean;
|
||||
};
|
||||
|
||||
export type LocalWebsocket = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalRabbitmq = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalSqs = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalOpenai = {
|
||||
chave?: string;
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
type Session = {
|
||||
remoteJid?: string;
|
||||
sessionId?: string;
|
||||
createdAt?: number;
|
||||
};
|
||||
|
||||
export type LocalTypebot = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
typebot?: string;
|
||||
expire?: number;
|
||||
keyword_finish?: string;
|
||||
delay_message?: number;
|
||||
unknown_message?: string;
|
||||
listening_from_me?: boolean;
|
||||
sessions?: Session[];
|
||||
};
|
||||
|
||||
export type LocalProxy = {
|
||||
enabled?: boolean;
|
||||
proxy?: string;
|
||||
};
|
||||
|
||||
export type LocalChamaai = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
token?: string;
|
||||
waNumber?: string;
|
||||
answerByAudio?: boolean;
|
||||
};
|
||||
|
||||
export type StateConnection = {
|
||||
instance?: string;
|
||||
state?: WAConnectionState | 'refused';
|
||||
statusReason?: number;
|
||||
};
|
||||
|
||||
export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED';
|
||||
}
|
||||
|
||||
export const TypeMediaMessage = ['imageMessage', 'documentMessage', 'audioMessage', 'videoMessage', 'stickerMessage'];
|
||||
|
||||
export const MessageSubtype = [
|
||||
'ephemeralMessage',
|
||||
'documentWithCaptionMessage',
|
||||
'viewOnceMessage',
|
||||
'viewOnceMessageV2',
|
||||
];
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { AuthenticationState, WAConnectionState } from '@whiskeysockets/baileys';
|
||||
|
||||
export enum Events {
|
||||
APPLICATION_STARTUP = 'application.startup',
|
||||
QRCODE_UPDATED = 'qrcode.updated',
|
||||
CONNECTION_UPDATE = 'connection.update',
|
||||
STATUS_INSTANCE = 'status.instance',
|
||||
MESSAGES_SET = 'messages.set',
|
||||
MESSAGES_UPSERT = 'messages.upsert',
|
||||
MESSAGES_UPDATE = 'messages.update',
|
||||
MESSAGES_DELETE = 'messages.delete',
|
||||
SEND_MESSAGE = 'send.message',
|
||||
CONTACTS_SET = 'contacts.set',
|
||||
CONTACTS_UPSERT = 'contacts.upsert',
|
||||
CONTACTS_UPDATE = 'contacts.update',
|
||||
PRESENCE_UPDATE = 'presence.update',
|
||||
CHATS_SET = 'chats.set',
|
||||
CHATS_UPDATE = 'chats.update',
|
||||
CHATS_UPSERT = 'chats.upsert',
|
||||
CHATS_DELETE = 'chats.delete',
|
||||
GROUPS_UPSERT = 'groups.upsert',
|
||||
GROUPS_UPDATE = 'groups.update',
|
||||
GROUP_PARTICIPANTS_UPDATE = 'group-participants.update',
|
||||
CALL = 'call',
|
||||
TYPEBOT_START = 'typebot.start',
|
||||
TYPEBOT_CHANGE_STATUS = 'typebot.change-status',
|
||||
CHAMA_AI_ACTION = 'chama-ai.action',
|
||||
}
|
||||
|
||||
export declare namespace wa {
|
||||
export type QrCode = {
|
||||
count?: number;
|
||||
pairingCode?: string;
|
||||
base64?: string;
|
||||
code?: string;
|
||||
};
|
||||
export type Instance = {
|
||||
qrcode?: QrCode;
|
||||
pairingCode?: string;
|
||||
authState?: { state: AuthenticationState; saveCreds: () => void };
|
||||
name?: string;
|
||||
wuid?: string;
|
||||
profileName?: string;
|
||||
profilePictureUrl?: string;
|
||||
};
|
||||
|
||||
export type LocalWebHook = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
events?: string[];
|
||||
webhook_by_events?: boolean;
|
||||
webhook_base64?: boolean;
|
||||
};
|
||||
|
||||
export type LocalChatwoot = {
|
||||
enabled?: boolean;
|
||||
account_id?: string;
|
||||
token?: string;
|
||||
url?: string;
|
||||
name_inbox?: string;
|
||||
sign_msg?: boolean;
|
||||
number?: string;
|
||||
reopen_conversation?: boolean;
|
||||
conversation_pending?: boolean;
|
||||
};
|
||||
|
||||
export type LocalSettings = {
|
||||
reject_call?: boolean;
|
||||
msg_call?: string;
|
||||
groups_ignore?: boolean;
|
||||
always_online?: boolean;
|
||||
read_messages?: boolean;
|
||||
read_status?: boolean;
|
||||
};
|
||||
|
||||
export type LocalWebsocket = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalRabbitmq = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalSqs = {
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
export type LocalOpenai = {
|
||||
chave?: string;
|
||||
enabled?: boolean;
|
||||
events?: string[];
|
||||
};
|
||||
|
||||
type Session = {
|
||||
remoteJid?: string;
|
||||
sessionId?: string;
|
||||
createdAt?: number;
|
||||
};
|
||||
|
||||
export type LocalTypebot = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
typebot?: string;
|
||||
expire?: number;
|
||||
keyword_finish?: string;
|
||||
delay_message?: number;
|
||||
unknown_message?: string;
|
||||
listening_from_me?: boolean;
|
||||
sessions?: Session[];
|
||||
};
|
||||
|
||||
export type LocalProxy = {
|
||||
enabled?: boolean;
|
||||
proxy?: string;
|
||||
};
|
||||
|
||||
export type LocalChamaai = {
|
||||
enabled?: boolean;
|
||||
url?: string;
|
||||
token?: string;
|
||||
waNumber?: string;
|
||||
answerByAudio?: boolean;
|
||||
};
|
||||
|
||||
export type StateConnection = {
|
||||
instance?: string;
|
||||
state?: WAConnectionState | 'refused';
|
||||
statusReason?: number;
|
||||
};
|
||||
|
||||
export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED';
|
||||
}
|
||||
|
||||
export const TypeMediaMessage = ['imageMessage', 'documentMessage', 'audioMessage', 'videoMessage', 'stickerMessage'];
|
||||
|
||||
export const MessageSubtype = [
|
||||
'ephemeralMessage',
|
||||
'documentWithCaptionMessage',
|
||||
'viewOnceMessage',
|
||||
'viewOnceMessageV2',
|
||||
];
|
||||
|
350
src/whatsapp/whatsapp.module.ts
Executable file → Normal file
350
src/whatsapp/whatsapp.module.ts
Executable file → Normal file
@ -1,175 +1,175 @@
|
||||
import { configService } from '../config/env.config';
|
||||
import { eventEmitter } from '../config/event.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
import { dbserver } from '../libs/db.connect';
|
||||
import { RedisCache } from '../libs/redis.client';
|
||||
import { ChamaaiController } from './controllers/chamaai.controller';
|
||||
import { ChatController } from './controllers/chat.controller';
|
||||
import { ChatwootController } from './controllers/chatwoot.controller';
|
||||
import { GroupController } from './controllers/group.controller';
|
||||
import { InstanceController } from './controllers/instance.controller';
|
||||
import { ProxyController } from './controllers/proxy.controller';
|
||||
import { RabbitmqController } from './controllers/rabbitmq.controller';
|
||||
import { OpenaiController } from './controllers/openai.controller';
|
||||
import { SendMessageController } from './controllers/sendMessage.controller';
|
||||
import { SettingsController } from './controllers/settings.controller';
|
||||
import { SqsController } from './controllers/sqs.controller';
|
||||
import { TypebotController } from './controllers/typebot.controller';
|
||||
import { ViewsController } from './controllers/views.controller';
|
||||
import { WebhookController } from './controllers/webhook.controller';
|
||||
import { WebsocketController } from './controllers/websocket.controller';
|
||||
import {
|
||||
AuthModel,
|
||||
ChamaaiModel,
|
||||
ChatModel,
|
||||
ChatwootModel,
|
||||
ContactModel,
|
||||
MessageModel,
|
||||
MessageUpModel,
|
||||
ProxyModel,
|
||||
RabbitmqModel,
|
||||
OpenaiModel,
|
||||
ContactOpenaiModel,
|
||||
SettingsModel,
|
||||
SqsModel,
|
||||
TypebotModel,
|
||||
WebhookModel,
|
||||
WebsocketModel,
|
||||
} from './models';
|
||||
import { AuthRepository } from './repository/auth.repository';
|
||||
import { ChamaaiRepository } from './repository/chamaai.repository';
|
||||
import { ChatRepository } from './repository/chat.repository';
|
||||
import { ChatwootRepository } from './repository/chatwoot.repository';
|
||||
import { ContactRepository } from './repository/contact.repository';
|
||||
import { MessageRepository } from './repository/message.repository';
|
||||
import { MessageUpRepository } from './repository/messageUp.repository';
|
||||
import { ProxyRepository } from './repository/proxy.repository';
|
||||
import { RabbitmqRepository } from './repository/rabbitmq.repository';
|
||||
import { OpenaiRepository } from './repository/openai.repository';
|
||||
import { RepositoryBroker } from './repository/repository.manager';
|
||||
import { SettingsRepository } from './repository/settings.repository';
|
||||
import { SqsRepository } from './repository/sqs.repository';
|
||||
import { TypebotRepository } from './repository/typebot.repository';
|
||||
import { WebhookRepository } from './repository/webhook.repository';
|
||||
import { WebsocketRepository } from './repository/websocket.repository';
|
||||
import { AuthService } from './services/auth.service';
|
||||
import { ChamaaiService } from './services/chamaai.service';
|
||||
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';
|
||||
import { WebhookService } from './services/webhook.service';
|
||||
import { WebsocketService } from './services/websocket.service';
|
||||
|
||||
const logger = new Logger('WA MODULE');
|
||||
|
||||
const messageRepository = new MessageRepository(MessageModel, configService);
|
||||
const chatRepository = new ChatRepository(ChatModel, configService);
|
||||
const contactRepository = new ContactRepository(ContactModel, configService);
|
||||
const messageUpdateRepository = new MessageUpRepository(MessageUpModel, configService);
|
||||
const typebotRepository = new TypebotRepository(TypebotModel, configService);
|
||||
const webhookRepository = new WebhookRepository(WebhookModel, configService);
|
||||
const websocketRepository = new WebsocketRepository(WebsocketModel, configService);
|
||||
const proxyRepository = new ProxyRepository(ProxyModel, configService);
|
||||
const chamaaiRepository = new ChamaaiRepository(ChamaaiModel, configService);
|
||||
const rabbitmqRepository = new RabbitmqRepository(RabbitmqModel, configService);
|
||||
const openaiRepository = new OpenaiRepository(OpenaiModel,ContactOpenaiModel, configService);
|
||||
const chatwootRepository = new ChatwootRepository(ChatwootModel, configService);
|
||||
const settingsRepository = new SettingsRepository(SettingsModel, configService);
|
||||
const sqsRepository = new SqsRepository(SqsModel, configService);
|
||||
const authRepository = new AuthRepository(AuthModel, configService);
|
||||
|
||||
export const repository = new RepositoryBroker(
|
||||
messageRepository,
|
||||
chatRepository,
|
||||
contactRepository,
|
||||
messageUpdateRepository,
|
||||
webhookRepository,
|
||||
chatwootRepository,
|
||||
settingsRepository,
|
||||
websocketRepository,
|
||||
rabbitmqRepository,
|
||||
openaiRepository,
|
||||
openaiRepository,
|
||||
sqsRepository,
|
||||
typebotRepository,
|
||||
proxyRepository,
|
||||
chamaaiRepository,
|
||||
authRepository,
|
||||
configService,
|
||||
dbserver?.getClient(),
|
||||
);
|
||||
|
||||
export const cache = new RedisCache();
|
||||
|
||||
export const waMonitor = new WAMonitoringService(eventEmitter, configService, repository, cache);
|
||||
|
||||
const authService = new AuthService(configService, waMonitor, repository);
|
||||
|
||||
const typebotService = new TypebotService(waMonitor, configService);
|
||||
|
||||
export const typebotController = new TypebotController(typebotService);
|
||||
|
||||
const webhookService = new WebhookService(waMonitor);
|
||||
|
||||
export const webhookController = new WebhookController(webhookService);
|
||||
|
||||
const websocketService = new WebsocketService(waMonitor);
|
||||
|
||||
export const websocketController = new WebsocketController(websocketService);
|
||||
|
||||
const proxyService = new ProxyService(waMonitor);
|
||||
|
||||
export const proxyController = new ProxyController(proxyService);
|
||||
|
||||
const chamaaiService = new ChamaaiService(waMonitor, configService);
|
||||
|
||||
export const chamaaiController = new ChamaaiController(chamaaiService);
|
||||
|
||||
const rabbitmqService = new RabbitmqService(waMonitor);
|
||||
|
||||
export const rabbitmqController = new RabbitmqController(rabbitmqService);
|
||||
|
||||
const sqsService = new SqsService(waMonitor);
|
||||
|
||||
export const sqsController = new SqsController(sqsService);
|
||||
|
||||
const openaiService = new OpenaiService(waMonitor);
|
||||
|
||||
export const openaiController = new OpenaiController(openaiService);
|
||||
|
||||
const chatwootService = new ChatwootService(waMonitor, configService);
|
||||
|
||||
export const chatwootController = new ChatwootController(chatwootService, configService);
|
||||
|
||||
const settingsService = new SettingsService(waMonitor);
|
||||
|
||||
export const settingsController = new SettingsController(settingsService);
|
||||
|
||||
export const instanceController = new InstanceController(
|
||||
waMonitor,
|
||||
configService,
|
||||
repository,
|
||||
eventEmitter,
|
||||
authService,
|
||||
webhookService,
|
||||
chatwootService,
|
||||
settingsService,
|
||||
websocketService,
|
||||
rabbitmqService,
|
||||
openaiService,
|
||||
proxyService,
|
||||
sqsService,
|
||||
typebotService,
|
||||
cache,
|
||||
);
|
||||
export const viewsController = new ViewsController(waMonitor, configService);
|
||||
export const sendMessageController = new SendMessageController(waMonitor);
|
||||
export const chatController = new ChatController(waMonitor);
|
||||
export const groupController = new GroupController(waMonitor);
|
||||
|
||||
logger.info('Module - ON');
|
||||
import { configService } from '../config/env.config';
|
||||
import { eventEmitter } from '../config/event.config';
|
||||
import { Logger } from '../config/logger.config';
|
||||
import { dbserver } from '../libs/db.connect';
|
||||
import { RedisCache } from '../libs/redis.client';
|
||||
import { ChamaaiController } from './controllers/chamaai.controller';
|
||||
import { ChatController } from './controllers/chat.controller';
|
||||
import { ChatwootController } from './controllers/chatwoot.controller';
|
||||
import { GroupController } from './controllers/group.controller';
|
||||
import { InstanceController } from './controllers/instance.controller';
|
||||
import { ProxyController } from './controllers/proxy.controller';
|
||||
import { RabbitmqController } from './controllers/rabbitmq.controller';
|
||||
import { OpenaiController } from './controllers/openai.controller';
|
||||
import { SendMessageController } from './controllers/sendMessage.controller';
|
||||
import { SettingsController } from './controllers/settings.controller';
|
||||
import { SqsController } from './controllers/sqs.controller';
|
||||
import { TypebotController } from './controllers/typebot.controller';
|
||||
import { ViewsController } from './controllers/views.controller';
|
||||
import { WebhookController } from './controllers/webhook.controller';
|
||||
import { WebsocketController } from './controllers/websocket.controller';
|
||||
import {
|
||||
AuthModel,
|
||||
ChamaaiModel,
|
||||
ChatModel,
|
||||
ChatwootModel,
|
||||
ContactModel,
|
||||
MessageModel,
|
||||
MessageUpModel,
|
||||
ProxyModel,
|
||||
RabbitmqModel,
|
||||
OpenaiModel,
|
||||
ContactOpenaiModel,
|
||||
SettingsModel,
|
||||
SqsModel,
|
||||
TypebotModel,
|
||||
WebhookModel,
|
||||
WebsocketModel,
|
||||
} from './models';
|
||||
import { AuthRepository } from './repository/auth.repository';
|
||||
import { ChamaaiRepository } from './repository/chamaai.repository';
|
||||
import { ChatRepository } from './repository/chat.repository';
|
||||
import { ChatwootRepository } from './repository/chatwoot.repository';
|
||||
import { ContactRepository } from './repository/contact.repository';
|
||||
import { MessageRepository } from './repository/message.repository';
|
||||
import { MessageUpRepository } from './repository/messageUp.repository';
|
||||
import { ProxyRepository } from './repository/proxy.repository';
|
||||
import { RabbitmqRepository } from './repository/rabbitmq.repository';
|
||||
import { OpenaiRepository } from './repository/openai.repository';
|
||||
import { RepositoryBroker } from './repository/repository.manager';
|
||||
import { SettingsRepository } from './repository/settings.repository';
|
||||
import { SqsRepository } from './repository/sqs.repository';
|
||||
import { TypebotRepository } from './repository/typebot.repository';
|
||||
import { WebhookRepository } from './repository/webhook.repository';
|
||||
import { WebsocketRepository } from './repository/websocket.repository';
|
||||
import { AuthService } from './services/auth.service';
|
||||
import { ChamaaiService } from './services/chamaai.service';
|
||||
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';
|
||||
import { WebhookService } from './services/webhook.service';
|
||||
import { WebsocketService } from './services/websocket.service';
|
||||
|
||||
const logger = new Logger('WA MODULE');
|
||||
|
||||
const messageRepository = new MessageRepository(MessageModel, configService);
|
||||
const chatRepository = new ChatRepository(ChatModel, configService);
|
||||
const contactRepository = new ContactRepository(ContactModel, configService);
|
||||
const messageUpdateRepository = new MessageUpRepository(MessageUpModel, configService);
|
||||
const typebotRepository = new TypebotRepository(TypebotModel, configService);
|
||||
const webhookRepository = new WebhookRepository(WebhookModel, configService);
|
||||
const websocketRepository = new WebsocketRepository(WebsocketModel, configService);
|
||||
const proxyRepository = new ProxyRepository(ProxyModel, configService);
|
||||
const chamaaiRepository = new ChamaaiRepository(ChamaaiModel, configService);
|
||||
const rabbitmqRepository = new RabbitmqRepository(RabbitmqModel, configService);
|
||||
const openaiRepository = new OpenaiRepository(OpenaiModel,ContactOpenaiModel, configService);
|
||||
const chatwootRepository = new ChatwootRepository(ChatwootModel, configService);
|
||||
const settingsRepository = new SettingsRepository(SettingsModel, configService);
|
||||
const sqsRepository = new SqsRepository(SqsModel, configService);
|
||||
const authRepository = new AuthRepository(AuthModel, configService);
|
||||
|
||||
export const repository = new RepositoryBroker(
|
||||
messageRepository,
|
||||
chatRepository,
|
||||
contactRepository,
|
||||
messageUpdateRepository,
|
||||
webhookRepository,
|
||||
chatwootRepository,
|
||||
settingsRepository,
|
||||
websocketRepository,
|
||||
rabbitmqRepository,
|
||||
openaiRepository,
|
||||
openaiRepository,
|
||||
sqsRepository,
|
||||
typebotRepository,
|
||||
proxyRepository,
|
||||
chamaaiRepository,
|
||||
authRepository,
|
||||
configService,
|
||||
dbserver?.getClient(),
|
||||
);
|
||||
|
||||
export const cache = new RedisCache();
|
||||
|
||||
export const waMonitor = new WAMonitoringService(eventEmitter, configService, repository, cache);
|
||||
|
||||
const authService = new AuthService(configService, waMonitor, repository);
|
||||
|
||||
const typebotService = new TypebotService(waMonitor, configService);
|
||||
|
||||
export const typebotController = new TypebotController(typebotService);
|
||||
|
||||
const webhookService = new WebhookService(waMonitor);
|
||||
|
||||
export const webhookController = new WebhookController(webhookService);
|
||||
|
||||
const websocketService = new WebsocketService(waMonitor);
|
||||
|
||||
export const websocketController = new WebsocketController(websocketService);
|
||||
|
||||
const proxyService = new ProxyService(waMonitor);
|
||||
|
||||
export const proxyController = new ProxyController(proxyService);
|
||||
|
||||
const chamaaiService = new ChamaaiService(waMonitor, configService);
|
||||
|
||||
export const chamaaiController = new ChamaaiController(chamaaiService);
|
||||
|
||||
const rabbitmqService = new RabbitmqService(waMonitor);
|
||||
|
||||
export const rabbitmqController = new RabbitmqController(rabbitmqService);
|
||||
|
||||
const sqsService = new SqsService(waMonitor);
|
||||
|
||||
export const sqsController = new SqsController(sqsService);
|
||||
|
||||
const openaiService = new OpenaiService(waMonitor);
|
||||
|
||||
export const openaiController = new OpenaiController(openaiService);
|
||||
|
||||
const chatwootService = new ChatwootService(waMonitor, configService);
|
||||
|
||||
export const chatwootController = new ChatwootController(chatwootService, configService);
|
||||
|
||||
const settingsService = new SettingsService(waMonitor);
|
||||
|
||||
export const settingsController = new SettingsController(settingsService);
|
||||
|
||||
export const instanceController = new InstanceController(
|
||||
waMonitor,
|
||||
configService,
|
||||
repository,
|
||||
eventEmitter,
|
||||
authService,
|
||||
webhookService,
|
||||
chatwootService,
|
||||
settingsService,
|
||||
websocketService,
|
||||
rabbitmqService,
|
||||
openaiService,
|
||||
proxyService,
|
||||
sqsService,
|
||||
typebotService,
|
||||
cache,
|
||||
);
|
||||
export const viewsController = new ViewsController(waMonitor, configService);
|
||||
export const sendMessageController = new SendMessageController(waMonitor);
|
||||
export const chatController = new ChatController(waMonitor);
|
||||
export const groupController = new GroupController(waMonitor);
|
||||
|
||||
logger.info('Module - ON');
|
||||
|
Loading…
Reference in New Issue
Block a user