feat: prisma

This commit is contained in:
Davidson Gomes
2024-06-06 01:08:24 -03:00
parent 8eced6c575
commit 272bed1351
74 changed files with 1140 additions and 4148 deletions

View File

@@ -16,9 +16,9 @@ import {
WhatsAppNumberDto,
} from '../dto/chat.dto';
import { InstanceDto } from '../dto/instance.dto';
import { ContactQuery } from '../repository/contact.repository';
import { MessageQuery } from '../repository/message.repository';
import { MessageUpQuery } from '../repository/messageUp.repository';
import { ContactQuery } from '../repository/mongodb/contact.repository';
import { MessageQuery } from '../repository/mongodb/message.repository';
import { MessageUpQuery } from '../repository/mongodb/messageUp.repository';
import { WAMonitoringService } from '../services/monitor.service';
const logger = new Logger('ChatController');

View File

@@ -13,8 +13,9 @@ import { SqsService } from '../integrations/sqs/services/sqs.service';
import { TypebotService } from '../integrations/typebot/services/typebot.service';
import { WebsocketService } from '../integrations/websocket/services/websocket.service';
import { ProviderFiles } from '../provider/sessions';
import { RepositoryBroker } from '../repository/repository.manager';
import { AuthService, OldToken } from '../services/auth.service';
import { MongodbRepository } from '../repository/mongodb/repository.manager';
import { PrismaRepository } from '../repository/prisma/repository.service';
import { AuthService } from '../services/auth.service';
import { CacheService } from '../services/cache.service';
import { BaileysStartupService } from '../services/channels/whatsapp.baileys.service';
import { BusinessStartupService } from '../services/channels/whatsapp.business.service';
@@ -29,7 +30,8 @@ export class InstanceController {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly configService: ConfigService,
private readonly repository: RepositoryBroker,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
private readonly eventEmitter: EventEmitter2,
private readonly authService: AuthService,
private readonly webhookService: WebhookService,
@@ -109,7 +111,8 @@ export class InstanceController {
instance = new BusinessStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.mongodbRepository,
this.prismaRepository,
this.cache,
this.chatwootCache,
this.baileysCache,
@@ -119,7 +122,8 @@ export class InstanceController {
instance = new BaileysStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.mongodbRepository,
this.prismaRepository,
this.cache,
this.chatwootCache,
this.baileysCache,
@@ -188,10 +192,8 @@ export class InstanceController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = events;
@@ -240,10 +242,8 @@ export class InstanceController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = websocket_events;
@@ -289,10 +289,8 @@ export class InstanceController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = rabbitmq_events;
@@ -338,10 +336,8 @@ export class InstanceController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = sqs_events;
@@ -690,7 +686,7 @@ export class InstanceController {
let arrayReturn = false;
if (env.KEY !== key) {
const instanceByKey = await this.repository.auth.findByKey(key);
const instanceByKey = await this.mongodbRepository.auth.findByKey(key);
if (instanceByKey) {
name = instanceByKey._id;
arrayReturn = true;
@@ -755,7 +751,7 @@ export class InstanceController {
try {
this.waMonitor.waInstances[instanceName]?.sendDataWebhook(Events.INSTANCE_DELETE, {
instanceName,
instanceId: (await this.repository.auth.find(instanceName))?.instanceId,
instanceId: (await this.mongodbRepository.auth.find(instanceName))?.instanceId,
});
} catch (error) {
this.logger.error(error);
@@ -768,9 +764,4 @@ export class InstanceController {
throw new BadRequestException(error.toString());
}
}
public async refreshToken(_: InstanceDto, oldToken: OldToken) {
this.logger.verbose('requested refreshToken');
return await this.authService.refreshToken(oldToken);
}
}

View File

@@ -50,10 +50,8 @@ export class WebhookController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}

View File

@@ -1,60 +1,13 @@
import { isJWT } from 'class-validator';
import { NextFunction, Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import { name } from '../../../package.json';
import { Auth, configService, Database } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { ForbiddenException, UnauthorizedException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { repository } from '../server.module';
import { JwtPayload } from '../services/auth.service';
import { mongodbRepository } from '../server.module';
const logger = new Logger('GUARD');
async function jwtGuard(req: Request, res: Response, next: NextFunction) {
const key = req.get('apikey');
if (key && configService.get<Auth>('AUTHENTICATION').API_KEY.KEY !== key) {
throw new UnauthorizedException();
}
if (configService.get<Auth>('AUTHENTICATION').API_KEY.KEY === key) {
return next();
}
if ((req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) && !key) {
throw new ForbiddenException('Missing global api key', 'The global api key must be set');
}
const jwtOpts = configService.get<Auth>('AUTHENTICATION').JWT;
try {
const [bearer, token] = req.get('authorization').split(' ');
if (bearer.toLowerCase() !== 'bearer') {
throw new UnauthorizedException();
}
if (!isJWT(token)) {
throw new UnauthorizedException();
}
const param = req.params as unknown as InstanceDto;
const decode = jwt.verify(token, jwtOpts.SECRET, {
ignoreExpiration: jwtOpts.EXPIRIN_IN === 0,
}) as JwtPayload;
if (param.instanceName !== decode.instanceName || name !== decode.apiName) {
throw new UnauthorizedException();
}
return next();
} catch (error) {
logger.error(error);
throw new UnauthorizedException();
}
}
async function apikey(req: Request, _: Response, next: NextFunction) {
const env = configService.get<Auth>('AUTHENTICATION').API_KEY;
const key = req.get('apikey');
@@ -75,13 +28,13 @@ async function apikey(req: Request, _: Response, next: NextFunction) {
try {
if (param?.instanceName) {
const instanceKey = await repository.auth.find(param.instanceName);
const instanceKey = await mongodbRepository.auth.find(param.instanceName);
if (instanceKey?.apikey === key) {
return next();
}
} else {
if (req.originalUrl.includes('/instance/fetchInstances') && db.ENABLED) {
const instanceByKey = await repository.auth.findByKey(key);
const instanceByKey = await mongodbRepository.auth.findByKey(key);
if (instanceByKey) {
return next();
}
@@ -94,4 +47,4 @@ async function apikey(req: Request, _: Response, next: NextFunction) {
throw new UnauthorizedException();
}
export const authGuard = { jwt: jwtGuard, apikey };
export const authGuard = { apikey };

View File

@@ -10,7 +10,7 @@ import {
InternalServerErrorException,
NotFoundException,
} from '../../exceptions';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
import { InstanceDto } from '../dto/instance.dto';
import { cache, waMonitor } from '../server.module';
@@ -28,7 +28,7 @@ async function getInstance(instanceName: string) {
}
if (db.ENABLED) {
const collection = dbserver
const collection = mongodbServer
.getClient()
.db(db.CONNECTION.DB_PREFIX_NAME + '-instances')
.collection(instanceName);

View File

@@ -1,29 +0,0 @@
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { ChamaaiDto } from '../dto/chamaai.dto';
import { ChamaaiService } from '../services/chamaai.service';
const logger = new Logger('ChamaaiController');
export class ChamaaiController {
constructor(private readonly chamaaiService: ChamaaiService) {}
public async createChamaai(instance: InstanceDto, data: ChamaaiDto) {
logger.verbose('requested createChamaai from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('chamaai disabled');
data.url = '';
data.token = '';
data.waNumber = '';
data.answerByAudio = false;
}
return this.chamaaiService.create(instance, data);
}
public async findChamaai(instance: InstanceDto) {
logger.verbose('requested findChamaai from ' + instance.instanceName + ' instance');
return this.chamaaiService.find(instance);
}
}

View File

@@ -1,7 +0,0 @@
export class ChamaaiDto {
enabled: boolean;
url: string;
token: string;
waNumber: string;
answerByAudio: boolean;
}

View File

@@ -1,24 +0,0 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
export class ChamaaiRaw {
_id?: string;
enabled?: boolean;
url?: string;
token?: string;
waNumber?: string;
answerByAudio?: boolean;
}
const chamaaiSchema = new Schema<ChamaaiRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
url: { type: String, required: true },
token: { type: String, required: true },
waNumber: { type: String, required: true },
answerByAudio: { type: Boolean, required: true },
});
export const ChamaaiModel = dbserver?.model(ChamaaiRaw.name, chamaaiSchema, 'chamaai');
export type IChamaaiModel = typeof ChamaaiModel;

View File

@@ -1,62 +0,0 @@
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 { ChamaaiRaw, IChamaaiModel } from '../../../models';
export class ChamaaiRepository extends Repository {
constructor(private readonly chamaaiModel: IChamaaiModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('ChamaaiRepository');
public async create(data: ChamaaiRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating chamaai');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving chamaai to db');
const insert = await this.chamaaiModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('chamaai saved to db: ' + insert.modifiedCount + ' chamaai');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving chamaai to store');
this.writeStore<ChamaaiRaw>({
path: join(this.storePath, 'chamaai'),
fileName: instance,
data,
});
this.logger.verbose('chamaai saved to store in path: ' + join(this.storePath, 'chamaai') + '/' + instance);
this.logger.verbose('chamaai created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<ChamaaiRaw> {
try {
this.logger.verbose('finding chamaai');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding chamaai in db');
return await this.chamaaiModel.findOne({ _id: instance });
}
this.logger.verbose('finding chamaai in store');
return JSON.parse(
readFileSync(join(this.storePath, 'chamaai', instance + '.json'), {
encoding: 'utf-8',
}),
) as ChamaaiRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -1,52 +0,0 @@
import { RequestHandler, Router } from 'express';
import { Logger } from '../../../../config/logger.config';
import { chamaaiSchema, instanceNameSchema } from '../../../../validate/validate.schema';
import { RouterBroker } from '../../../abstract/abstract.router';
import { InstanceDto } from '../../../dto/instance.dto';
import { HttpStatus } from '../../../routes/index.router';
import { chamaaiController } from '../../../server.module';
import { ChamaaiDto } from '../dto/chamaai.dto';
const logger = new Logger('ChamaaiRouter');
export class ChamaaiRouter extends RouterBroker {
constructor(...guards: RequestHandler[]) {
super();
this.router
.post(this.routerPath('set'), ...guards, async (req, res) => {
logger.verbose('request received in setChamaai');
logger.verbose('request body: ');
logger.verbose(req.body);
logger.verbose('request query: ');
logger.verbose(req.query);
const response = await this.dataValidate<ChamaaiDto>({
request: req,
schema: chamaaiSchema,
ClassRef: ChamaaiDto,
execute: (instance, data) => chamaaiController.createChamaai(instance, data),
});
res.status(HttpStatus.CREATED).json(response);
})
.get(this.routerPath('find'), ...guards, async (req, res) => {
logger.verbose('request received in findChamaai');
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) => chamaaiController.findChamaai(instance),
});
res.status(HttpStatus.OK).json(response);
});
}
public readonly router = Router();
}

View File

@@ -1,230 +0,0 @@
import axios from 'axios';
import { writeFileSync } from 'fs';
import path from 'path';
import { ConfigService, HttpServer } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { ChamaaiRaw } from '../../../models';
import { WAMonitoringService } from '../../../services/monitor.service';
import { Events } from '../../../types/wa.types';
import { ChamaaiDto } from '../dto/chamaai.dto';
export class ChamaaiService {
constructor(private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService) {}
private readonly logger = new Logger(ChamaaiService.name);
public create(instance: InstanceDto, data: ChamaaiDto) {
this.logger.verbose('create chamaai: ' + instance.instanceName);
this.waMonitor.waInstances[instance.instanceName].setChamaai(data);
return { chamaai: { ...instance, chamaai: data } };
}
public async find(instance: InstanceDto): Promise<ChamaaiRaw> {
try {
this.logger.verbose('find chamaai: ' + instance.instanceName);
const result = await this.waMonitor.waInstances[instance.instanceName].findChamaai();
if (Object.keys(result).length === 0) {
throw new Error('Chamaai not found');
}
return result;
} catch (error) {
return { enabled: false, url: '', token: '', waNumber: '', answerByAudio: false };
}
}
private getTypeMessage(msg: any) {
this.logger.verbose('get type message');
const types = {
conversation: msg.conversation,
extendedTextMessage: msg.extendedTextMessage?.text,
};
this.logger.verbose('type message: ' + types);
return types;
}
private getMessageContent(types: any) {
this.logger.verbose('get message content');
const typeKey = Object.keys(types).find((key) => types[key] !== undefined);
const result = typeKey ? types[typeKey] : undefined;
this.logger.verbose('message content: ' + result);
return result;
}
private getConversationMessage(msg: any) {
this.logger.verbose('get conversation message');
const types = this.getTypeMessage(msg);
const messageContent = this.getMessageContent(types);
this.logger.verbose('conversation message: ' + messageContent);
return messageContent;
}
private calculateTypingTime(text: string) {
const wordsPerMinute = 100;
const wordCount = text.split(' ').length;
const typingTimeInMinutes = wordCount / wordsPerMinute;
const typingTimeInMilliseconds = typingTimeInMinutes * 60;
return typingTimeInMilliseconds;
}
private convertToMilliseconds(count: number) {
const averageCharactersPerSecond = 15;
const characterCount = count;
const speakingTimeInSeconds = characterCount / averageCharactersPerSecond;
return speakingTimeInSeconds;
}
private getRegexPatterns() {
const patternsToCheck = [
'.*atend.*humano.*',
'.*falar.*com.*um.*humano.*',
'.*fala.*humano.*',
'.*atend.*humano.*',
'.*fala.*atend.*',
'.*preciso.*ajuda.*',
'.*quero.*suporte.*',
'.*preciso.*assiste.*',
'.*ajuda.*atend.*',
'.*chama.*atendente.*',
'.*suporte.*urgente.*',
'.*atend.*por.*favor.*',
'.*quero.*falar.*com.*alguém.*',
'.*falar.*com.*um.*humano.*',
'.*transfer.*humano.*',
'.*transfer.*atend.*',
'.*equipe.*humano.*',
'.*suporte.*humano.*',
];
const regexPatterns = patternsToCheck.map((pattern) => new RegExp(pattern, 'iu'));
return regexPatterns;
}
public async sendChamaai(instance: InstanceDto, remoteJid: string, msg: any) {
const content = this.getConversationMessage(msg.message);
const msgType = msg.messageType;
const find = await this.find(instance);
const url = find.url;
const token = find.token;
const waNumber = find.waNumber;
const answerByAudio = find.answerByAudio;
if (!content && msgType !== 'audioMessage') {
return;
}
let data;
let endpoint;
if (msgType === 'audioMessage') {
const downloadBase64 = await this.waMonitor.waInstances[instance.instanceName].getBase64FromMediaMessage({
message: {
...msg,
},
});
const random = Math.random().toString(36).substring(7);
const nameFile = `${random}.ogg`;
const fileData = Buffer.from(downloadBase64.base64, 'base64');
const fileName = `${path.join(
this.waMonitor.waInstances[instance.instanceName].storePath,
'temp',
`${nameFile}`,
)}`;
writeFileSync(fileName, fileData, 'utf8');
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
const url = `${urlServer}/store/temp/${nameFile}`;
data = {
waNumber: waNumber,
audioUrl: url,
queryNumber: remoteJid.split('@')[0],
answerByAudio: answerByAudio,
};
endpoint = 'processMessageAudio';
} else {
data = {
waNumber: waNumber,
question: content,
queryNumber: remoteJid.split('@')[0],
answerByAudio: answerByAudio,
};
endpoint = 'processMessageText';
}
const request = await axios.post(`${url}/${endpoint}`, data, {
headers: {
Authorization: `${token}`,
},
});
const answer = request.data?.answer;
const type = request.data?.type;
const characterCount = request.data?.characterCount;
if (answer) {
if (type === 'text') {
this.waMonitor.waInstances[instance.instanceName].textMessage({
number: remoteJid.split('@')[0],
options: {
delay: this.calculateTypingTime(answer) * 1000 || 1000,
presence: 'composing',
linkPreview: false,
quoted: {
key: msg.key,
message: msg.message,
},
},
textMessage: {
text: answer,
},
});
}
if (type === 'audio') {
this.waMonitor.waInstances[instance.instanceName].audioWhatsapp({
number: remoteJid.split('@')[0],
options: {
delay: characterCount ? this.convertToMilliseconds(characterCount) * 1000 || 1000 : 1000,
presence: 'recording',
encoding: true,
},
audioMessage: {
audio: answer,
},
});
}
if (this.getRegexPatterns().some((pattern) => pattern.test(answer))) {
this.waMonitor.waInstances[instance.instanceName].sendDataWebhook(Events.CHAMA_AI_ACTION, {
remoteJid: remoteJid,
message: msg,
answer: answer,
action: 'transfer',
});
}
}
}
}

View File

@@ -1,35 +0,0 @@
import { JSONSchema7 } from 'json-schema';
import { v4 } from 'uuid';
const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => {
const properties = {};
propertyNames.forEach(
(property) =>
(properties[property] = {
minLength: 1,
description: `The "${property}" cannot be empty`,
}),
);
return {
if: {
propertyNames: {
enum: [...propertyNames],
},
},
then: { properties },
};
};
export const chamaaiSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
url: { type: 'string' },
token: { type: 'string' },
waNumber: { type: 'string' },
answerByAudio: { type: 'boolean', enum: [true, false] },
},
required: ['enabled', 'url', 'token', 'waNumber', 'answerByAudio'],
...isNotEmpty('enabled', 'url', 'token', 'waNumber', 'answerByAudio'),
};

View File

@@ -5,7 +5,8 @@ import { ConfigService, HttpServer } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { BadRequestException } from '../../../../exceptions';
import { InstanceDto } from '../../../dto/instance.dto';
import { RepositoryBroker } from '../../../repository/repository.manager';
import { MongodbRepository } from '../../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../../repository/prisma/repository.service';
import { waMonitor } from '../../../server.module';
import { CacheService } from '../../../services/cache.service';
import { ChatwootDto } from '../dto/chatwoot.dto';
@@ -17,7 +18,8 @@ export class ChatwootController {
constructor(
private readonly chatwootService: ChatwootService,
private readonly configService: ConfigService,
private readonly repository: RepositoryBroker,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
) {}
public async createChatwoot(instance: InstanceDto, data: ChatwootDto) {
@@ -105,7 +107,13 @@ export class ChatwootController {
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
const chatwootCache = new CacheService(new CacheEngine(this.configService, ChatwootService.name).getEngine());
const chatwootService = new ChatwootService(waMonitor, this.configService, this.repository, chatwootCache);
const chatwootService = new ChatwootService(
waMonitor,
this.configService,
this.mongodbRepository,
this.prismaRepository,
chatwootCache,
);
return chatwootService.receiveWebhook(instance, data);
}

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class ChatwootRaw {
_id?: string;
@@ -38,5 +38,5 @@ const chatwootSchema = new Schema<ChatwootRaw>({
days_limit_import_messages: { type: Number, required: true },
});
export const ChatwootModel = dbserver?.model(ChatwootRaw.name, chatwootSchema, 'chatwoot');
export const ChatwootModel = mongodbServer?.model(ChatwootRaw.name, chatwootSchema, 'chatwoot');
export type IChatwootModel = typeof ChatwootModel;

View File

@@ -23,7 +23,8 @@ import { ICache } from '../../../abstract/abstract.cache';
import { InstanceDto } from '../../../dto/instance.dto';
import { Options, Quoted, SendAudioDto, SendMediaDto, SendTextDto } from '../../../dto/sendMessage.dto';
import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../models';
import { RepositoryBroker } from '../../../repository/repository.manager';
import { MongodbRepository } from '../../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../../repository/prisma/repository.service';
import { WAMonitoringService } from '../../../services/monitor.service';
import { Events } from '../../../types/wa.types';
import { ChatwootDto } from '../dto/chatwoot.dto';
@@ -37,7 +38,8 @@ export class ChatwootService {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly configService: ConfigService,
private readonly repository: RepositoryBroker,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
private readonly cache: ICache,
) {}
@@ -444,8 +446,7 @@ export class ChatwootService {
const searchableFields = this.getSearchableFields();
// eslint-disable-next-line prettier/prettier
if(contacts.length === 2 && this.getClientCwConfig().merge_brazil_contacts && query.startsWith('+55')){
if (contacts.length === 2 && this.getClientCwConfig().merge_brazil_contacts && query.startsWith('+55')) {
const contact = this.mergeBrazilianContacts(contacts);
if (contact) {
return contact;
@@ -1194,7 +1195,7 @@ export class ChatwootService {
this.logger.verbose('check if is a message deletion');
if (body.event === 'message_updated' && body.content_attributes?.deleted) {
const message = await this.repository.message.find({
const message = await this.mongodbRepository.message.find({
where: {
owner: instance.instanceName,
chatwoot: {
@@ -1208,7 +1209,7 @@ export class ChatwootService {
await waInstance?.client.sendMessage(message[0].key.remoteJid, { delete: message[0].key });
this.logger.verbose('deleting message in repository. Message id: ' + message[0].key.id);
this.repository.message.delete({
this.mongodbRepository.message.delete({
where: {
owner: instance.instanceName,
chatwoot: {
@@ -1423,7 +1424,7 @@ export class ChatwootService {
const chatwootRead = this.configService.get<Chatwoot>('CHATWOOT').MESSAGE_READ;
if (chatwootRead) {
const lastMessage = await this.repository.message.find({
const lastMessage = await this.mongodbRepository.message.find({
where: {
key: {
fromMe: false,
@@ -1448,7 +1449,7 @@ export class ChatwootService {
isRead: true,
},
}));
this.repository.message.update(updateMessage, instance.instanceName, true);
this.mongodbRepository.message.update(updateMessage, instance.instanceName, true);
}
}
}
@@ -1490,11 +1491,11 @@ export class ChatwootService {
}
message.chatwoot = chatwootMessageIds;
this.repository.message.update([message], instance.instanceName, true);
this.mongodbRepository.message.update([message], instance.instanceName, true);
}
private async getMessageByKeyId(instance: InstanceDto, keyId: string): Promise<MessageRaw> {
const messages = await this.repository.message.find({
const messages = await this.mongodbRepository.message.find({
where: {
key: {
id: keyId,
@@ -1532,7 +1533,7 @@ export class ChatwootService {
private async getQuotedMessage(msg: any, instance: InstanceDto): Promise<Quoted> {
if (msg?.content_attributes?.in_reply_to) {
const message = await this.repository.message.find({
const message = await this.mongodbRepository.message.find({
where: {
chatwoot: {
messageId: msg?.content_attributes?.in_reply_to,
@@ -2132,7 +2133,7 @@ export class ChatwootService {
const message = await this.getMessageByKeyId(instance, body.key.id);
if (message?.chatwoot?.messageId && message?.chatwoot?.conversationId) {
this.logger.verbose('deleting message in repository. Message id: ' + body.key.id);
this.repository.message.delete({
this.mongodbRepository.message.delete({
where: {
key: {
id: body.key.id,
@@ -2381,7 +2382,7 @@ export class ChatwootService {
);
const contactsWithProfilePicture = (
await this.repository.contact.find({
await this.mongodbRepository.contact.find({
where: {
owner: instance.instanceName,
id: {

View File

@@ -41,10 +41,8 @@ export class RabbitmqController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class RabbitmqRaw {
_id?: string;
@@ -14,5 +14,5 @@ const rabbitmqSchema = new Schema<RabbitmqRaw>({
events: { type: [String], required: true },
});
export const RabbitmqModel = dbserver?.model(RabbitmqRaw.name, rabbitmqSchema, 'rabbitmq');
export const RabbitmqModel = mongodbServer?.model(RabbitmqRaw.name, rabbitmqSchema, 'rabbitmq');
export type IRabbitmqModel = typeof RabbitmqModel;

View File

@@ -53,10 +53,8 @@ export const rabbitmqSchema: JSONSchema7 = {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},

View File

@@ -41,10 +41,8 @@ export class SqsController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class SqsRaw {
_id?: string;
@@ -14,5 +14,5 @@ const sqsSchema = new Schema<SqsRaw>({
events: { type: [String], required: true },
});
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
export const SqsModel = mongodbServer?.model(SqsRaw.name, sqsSchema, 'sqs');
export type ISqsModel = typeof SqsModel;

View File

@@ -53,10 +53,8 @@ export const sqsSchema: JSONSchema7 = {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
import { mongodbServer } from '../../../../libs/mongodb.connect';
class Session {
remoteJid?: string;
@@ -54,5 +54,5 @@ const typebotSchema = new Schema<TypebotRaw>({
],
});
export const TypebotModel = dbserver?.model(TypebotRaw.name, typebotSchema, 'typebot');
export const TypebotModel = mongodbServer?.model(TypebotRaw.name, typebotSchema, 'typebot');
export type ITypebotModel = typeof TypebotModel;

View File

@@ -41,10 +41,8 @@ export class WebsocketController {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../../../libs/db.connect';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class WebsocketRaw {
_id?: string;
@@ -14,5 +14,5 @@ const websocketSchema = new Schema<WebsocketRaw>({
events: { type: [String], required: true },
});
export const WebsocketModel = dbserver?.model(WebsocketRaw.name, websocketSchema, 'websocket');
export const WebsocketModel = mongodbServer?.model(WebsocketRaw.name, websocketSchema, 'websocket');
export type IWebsocketModel = typeof WebsocketModel;

View File

@@ -53,10 +53,8 @@ export const websocketSchema: JSONSchema7 = {
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},

View File

@@ -1,20 +1,18 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class AuthRaw {
_id?: string;
jwt?: string;
apikey?: string;
instanceId?: string;
}
const authSchema = new Schema<AuthRaw>({
_id: { type: String, _id: true },
jwt: { type: String, minlength: 1 },
apikey: { type: String, minlength: 1 },
instanceId: { type: String, minlength: 1 },
});
export const AuthModel = dbserver?.model(AuthRaw.name, authSchema, 'authentication');
export const AuthModel = mongodbServer?.model(AuthRaw.name, authSchema, 'authentication');
export type IAuthModel = typeof AuthModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class ChatRaw {
_id?: string;
@@ -22,5 +22,5 @@ const chatSchema = new Schema<ChatRaw>({
labels: { type: [String], default: [] },
});
export const ChatModel = dbserver?.model(ChatRaw.name, chatSchema, 'chats');
export const ChatModel = mongodbServer?.model(ChatRaw.name, chatSchema, 'chats');
export type IChatModel = typeof ChatModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class ContactRaw {
_id?: string;
@@ -23,5 +23,5 @@ const contactSchema = new Schema<ContactRaw>({
owner: { type: String, required: true, minlength: 1 },
});
export const ContactModel = dbserver?.model(ContactRaw.name, contactSchema, 'contacts');
export const ContactModel = mongodbServer?.model(ContactRaw.name, contactSchema, 'contacts');
export type IContactModel = typeof ContactModel;

View File

@@ -1,4 +1,3 @@
export * from '../integrations/chamaai/models/chamaai.model';
export * from '../integrations/chatwoot/models/chatwoot.model';
export * from '../integrations/rabbitmq/models/rabbitmq.model';
export * from '../integrations/sqs/models/sqs.model';

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class IntegrationRaw {
_id?: string;
@@ -16,5 +16,5 @@ const integrationSchema = new Schema<IntegrationRaw>({
token: { type: String, required: true },
});
export const IntegrationModel = dbserver?.model(IntegrationRaw.name, integrationSchema, 'integration');
export const IntegrationModel = mongodbServer?.model(IntegrationRaw.name, integrationSchema, 'integration');
export type IntegrationModel = typeof IntegrationModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class LabelRaw {
_id?: string;
@@ -25,5 +25,5 @@ const labelSchema = new Schema<LabelRaw>({
predefinedId: { type: String },
});
export const LabelModel = dbserver?.model(LabelRaw.name, labelSchema, 'labels');
export const LabelModel = mongodbServer?.model(LabelRaw.name, labelSchema, 'labels');
export type ILabelModel = typeof LabelModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
import { wa } from '../types/wa.types';
class Key {
@@ -72,7 +72,7 @@ messageSchema.index({ 'key.id': 1 });
messageSchema.index({ 'key.id': 1, owner: 1 });
messageSchema.index({ owner: 1 });
export const MessageModel = dbserver?.model(MessageRaw.name, messageSchema, 'messages');
export const MessageModel = mongodbServer?.model(MessageRaw.name, messageSchema, 'messages');
export type IMessageModel = typeof MessageModel;
export class MessageUpdateRaw {
@@ -98,5 +98,5 @@ const messageUpdateSchema = new Schema<MessageUpdateRaw>({
owner: { type: String, required: true, min: 1 },
});
export const MessageUpModel = dbserver?.model(MessageUpdateRaw.name, messageUpdateSchema, 'messageUpdate');
export const MessageUpModel = mongodbServer?.model(MessageUpdateRaw.name, messageUpdateSchema, 'messageUpdate');
export type IMessageUpModel = typeof MessageUpModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
class Proxy {
host?: string;
@@ -28,5 +28,5 @@ const proxySchema = new Schema<ProxyRaw>({
},
});
export const ProxyModel = dbserver?.model(ProxyRaw.name, proxySchema, 'proxy');
export const ProxyModel = mongodbServer?.model(ProxyRaw.name, proxySchema, 'proxy');
export type IProxyModel = typeof ProxyModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class SettingsRaw {
_id?: string;
@@ -24,5 +24,5 @@ const settingsSchema = new Schema<SettingsRaw>({
sync_full_history: { type: Boolean, required: true },
});
export const SettingsModel = dbserver?.model(SettingsRaw.name, settingsSchema, 'settings');
export const SettingsModel = mongodbServer?.model(SettingsRaw.name, settingsSchema, 'settings');
export type ISettingsModel = typeof SettingsModel;

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
import { mongodbServer } from '../../libs/mongodb.connect';
export class WebhookRaw {
_id?: string;
@@ -20,5 +20,5 @@ const webhookSchema = new Schema<WebhookRaw>({
webhook_base64: { type: Boolean, required: true },
});
export const WebhookModel = dbserver?.model(WebhookRaw.name, webhookSchema, 'webhook');
export const WebhookModel = mongodbServer?.model(WebhookRaw.name, webhookSchema, 'webhook');
export type IWebhookModel = typeof WebhookModel;

View File

@@ -1,11 +1,11 @@
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { Auth, ConfigService } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { AUTH_DIR } from '../../config/path.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { AuthRaw, IAuthModel, IntegrationModel } from '../models';
import { Auth, ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { AUTH_DIR } from '../../../config/path.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { AuthRaw, IAuthModel, IntegrationModel } from '../../models';
export class AuthRepository extends Repository {
constructor(
@@ -35,11 +35,11 @@ export class AuthRepository extends Repository {
this.logger.verbose('saving auth to store');
this.writeStore<AuthRaw>({
path: join(AUTH_DIR, this.auth.TYPE),
path: join(AUTH_DIR, 'apikey'),
fileName: instance,
data,
});
this.logger.verbose('auth saved to store in path: ' + join(AUTH_DIR, this.auth.TYPE) + '/' + instance);
this.logger.verbose('auth saved to store in path: ' + join(AUTH_DIR, 'apikey') + '/' + instance);
this.logger.verbose('auth created');
return { insertCount: 1 };
@@ -59,7 +59,7 @@ export class AuthRepository extends Repository {
this.logger.verbose('finding auth in store');
return JSON.parse(
readFileSync(join(AUTH_DIR, this.auth.TYPE, instance + '.json'), {
readFileSync(join(AUTH_DIR, 'apikey', instance + '.json'), {
encoding: 'utf-8',
}),
) as AuthRaw;
@@ -92,14 +92,14 @@ export class AuthRepository extends Repository {
this.logger.verbose('listing auth in store');
const auths: AuthRaw[] = [];
const openDir = opendirSync(join(AUTH_DIR, this.auth.TYPE), {
const openDir = opendirSync(join(AUTH_DIR, 'apikey'), {
encoding: 'utf-8',
});
for await (const dirent of openDir) {
if (dirent.isFile()) {
auths.push(
JSON.parse(
readFileSync(join(AUTH_DIR, this.auth.TYPE, dirent.name), {
readFileSync(join(AUTH_DIR, 'apikey', dirent.name), {
encoding: 'utf-8',
}),
),

View File

@@ -1,10 +1,10 @@
import { opendirSync, readFileSync, rmSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ChatRaw, ChatRawSelect, IChatModel } from '../models';
import { ConfigService, StoreConf } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { ChatRaw, ChatRawSelect, IChatModel } from '../../models';
export class ChatQuery {
select?: ChatRawSelect;

View File

@@ -1,10 +1,10 @@
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ContactRaw, ContactRawSelect, IContactModel } from '../models';
import { ConfigService, StoreConf } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { ContactRaw, ContactRawSelect, IContactModel } from '../../models';
export class ContactQuery {
select?: ContactRawSelect;

View File

@@ -0,0 +1,149 @@
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { Auth, ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { AUTH_DIR } from '../../../config/path.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { AuthRaw, IAuthModel, IntegrationModel } from '../../models';
export class AuthRepository extends Repository {
constructor(
private readonly authModel: IAuthModel,
private readonly integrationModel: IntegrationModel,
readonly configService: ConfigService,
) {
super(configService);
this.auth = configService.get<Auth>('AUTHENTICATION');
}
private readonly auth: Auth;
private readonly logger = new Logger('AuthRepository');
public async create(data: AuthRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating auth');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving auth to db');
const insert = await this.authModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('auth saved to db: ' + insert.modifiedCount + ' auth');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving auth to store');
this.writeStore<AuthRaw>({
path: join(AUTH_DIR, 'apikey'),
fileName: instance,
data,
});
this.logger.verbose('auth saved to store in path: ' + join(AUTH_DIR, 'apikey') + '/' + instance);
this.logger.verbose('auth created');
return { insertCount: 1 };
} catch (error) {
return { error } as any;
}
}
public async find(instance: string): Promise<AuthRaw> {
try {
this.logger.verbose('finding auth');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding auth in db');
return await this.authModel.findOne({ _id: instance });
}
this.logger.verbose('finding auth in store');
return JSON.parse(
readFileSync(join(AUTH_DIR, 'apikey', instance + '.json'), {
encoding: 'utf-8',
}),
) as AuthRaw;
} catch (error) {
return {};
}
}
public async findByKey(key: string): Promise<AuthRaw> {
try {
this.logger.verbose('finding auth');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding auth in db');
return await this.authModel.findOne({ apikey: key });
}
return {};
} catch (error) {
return {};
}
}
public async list(): Promise<AuthRaw[]> {
try {
if (this.dbSettings.ENABLED) {
this.logger.verbose('listing auth in db');
return await this.authModel.find();
}
this.logger.verbose('listing auth in store');
const auths: AuthRaw[] = [];
const openDir = opendirSync(join(AUTH_DIR, 'apikey'), {
encoding: 'utf-8',
});
for await (const dirent of openDir) {
if (dirent.isFile()) {
auths.push(
JSON.parse(
readFileSync(join(AUTH_DIR, 'apikey', dirent.name), {
encoding: 'utf-8',
}),
),
);
}
}
return auths;
} catch (error) {
return [];
}
}
public async findInstanceNameById(instanceId: string): Promise<string | null> {
try {
this.logger.verbose('finding auth by instanceId');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding auth in db');
const response = await this.authModel.findOne({ instanceId });
return response._id;
}
this.logger.verbose('finding auth in store is not supported');
} catch (error) {
return null;
}
}
public async findInstanceNameByNumber(number: string): Promise<string | null> {
try {
this.logger.verbose('finding auth by number');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding auth in db');
const instance = await this.integrationModel.findOne({ number });
const response = await this.authModel.findOne({ _id: instance._id });
return response._id;
}
this.logger.verbose('finding auth in store is not supported');
} catch (error) {
return null;
}
}
}

View File

@@ -1,10 +1,10 @@
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 { IntegrationModel, IntegrationRaw } from '../models';
import { ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { IntegrationModel, IntegrationRaw } from '../../models';
export class IntegrationRepository extends Repository {
constructor(private readonly integrationModel: IntegrationModel, private readonly configService: ConfigService) {

View File

@@ -1,10 +1,10 @@
import { opendirSync, readFileSync, rmSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ILabelModel, LabelRaw, LabelRawSelect } from '../models';
import { ConfigService, StoreConf } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { ILabelModel, LabelRaw, LabelRawSelect } from '../../models';
export class LabelQuery {
select?: LabelRawSelect;

View File

@@ -1,10 +1,10 @@
import { opendirSync, readFileSync, rmSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { IMessageModel, MessageRaw, MessageRawSelect } from '../models';
import { ConfigService, StoreConf } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { IMessageModel, MessageRaw, MessageRawSelect } from '../../models';
export class MessageQuery {
select?: MessageRawSelect;

View File

@@ -1,10 +1,10 @@
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { IMessageUpModel, MessageUpdateRaw } from '../models';
import { ConfigService, StoreConf } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { IMessageUpModel, MessageUpdateRaw } from '../../models';
export class MessageUpQuery {
where: MessageUpdateRaw;

View File

@@ -1,10 +1,10 @@
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 { IProxyModel, ProxyRaw } from '../models';
import { ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { IProxyModel, ProxyRaw } from '../../models';
export class ProxyRepository extends Repository {
constructor(private readonly proxyModel: IProxyModel, private readonly configService: ConfigService) {

View File

@@ -1,15 +1,15 @@
import { PrismaClient } from '@prisma/client';
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 { ChamaaiRepository } from '../integrations/chamaai/repository/chamaai.repository';
import { ChatwootRepository } from '../integrations/chatwoot/repository/chatwoot.repository';
import { RabbitmqRepository } from '../integrations/rabbitmq/repository/rabbitmq.repository';
import { SqsRepository } from '../integrations/sqs/repository/sqs.repository';
import { TypebotRepository } from '../integrations/typebot/repository/typebot.repository';
import { WebsocketRepository } from '../integrations/websocket/repository/websocket.repository';
import { ConfigService, Database } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { ChatwootRepository } from '../../integrations/chatwoot/repository/chatwoot.repository';
import { RabbitmqRepository } from '../../integrations/rabbitmq/repository/rabbitmq.repository';
import { SqsRepository } from '../../integrations/sqs/repository/sqs.repository';
import { TypebotRepository } from '../../integrations/typebot/repository/typebot.repository';
import { WebsocketRepository } from '../../integrations/websocket/repository/websocket.repository';
import { AuthRepository } from './auth.repository';
import { ChatRepository } from './chat.repository';
import { ContactRepository } from './contact.repository';
@@ -20,7 +20,7 @@ import { MessageUpRepository } from './messageUp.repository';
import { ProxyRepository } from './proxy.repository';
import { SettingsRepository } from './settings.repository';
import { WebhookRepository } from './webhook.repository';
export class RepositoryBroker {
export class MongodbRepository {
constructor(
public readonly message: MessageRepository,
public readonly chat: ChatRepository,
@@ -34,22 +34,28 @@ export class RepositoryBroker {
public readonly sqs: SqsRepository,
public readonly typebot: TypebotRepository,
public readonly proxy: ProxyRepository,
public readonly chamaai: ChamaaiRepository,
public readonly integration: IntegrationRepository,
public readonly auth: AuthRepository,
public readonly labels: LabelRepository,
private configService: ConfigService,
dbServer?: MongoClient,
mongodbServer?: MongoClient,
prismaServer?: PrismaClient,
) {
this.dbClient = dbServer;
this.mongodbClient = mongodbServer;
this.prismaClient = prismaServer;
this.__init_repo_without_db__();
}
private dbClient?: MongoClient;
private mongodbClient?: MongoClient;
private prismaClient?: PrismaClient;
private readonly logger = new Logger('RepositoryBroker');
public get dbServer() {
return this.dbClient;
public get mongodbServer() {
return this.mongodbClient;
}
public get prismaServer() {
return this.prismaClient;
}
private __init_repo_without_db__() {
@@ -59,7 +65,7 @@ export class RepositoryBroker {
this.logger.verbose('creating store path: ' + storePath);
try {
const authDir = join(storePath, 'auth', this.configService.get<Auth>('AUTHENTICATION').TYPE);
const authDir = join(storePath, 'auth', 'apikey');
const chatsDir = join(storePath, 'chats');
const contactsDir = join(storePath, 'contacts');
const messagesDir = join(storePath, 'messages');
@@ -72,7 +78,6 @@ export class RepositoryBroker {
const sqsDir = join(storePath, 'sqs');
const typebotDir = join(storePath, 'typebot');
const proxyDir = join(storePath, 'proxy');
const chamaaiDir = join(storePath, 'chamaai');
const integrationDir = join(storePath, 'integration');
const tempDir = join(storePath, 'temp');
@@ -128,10 +133,6 @@ export class RepositoryBroker {
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(integrationDir)) {
this.logger.verbose('creating integration dir: ' + integrationDir);
fs.mkdirSync(integrationDir, { recursive: true });

View File

@@ -1,10 +1,10 @@
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 { ISettingsModel, SettingsRaw } from '../models';
import { ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { ISettingsModel, SettingsRaw } from '../../models';
export class SettingsRepository extends Repository {
constructor(private readonly settingsModel: ISettingsModel, private readonly configService: ConfigService) {

View File

@@ -1,10 +1,10 @@
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 { IWebhookModel, WebhookRaw } from '../models';
import { ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
import { IInsert, Repository } from '../../abstract/abstract.repository';
import { IWebhookModel, WebhookRaw } from '../../models';
export class WebhookRepository extends Repository {
constructor(private readonly webhookModel: IWebhookModel, private readonly configService: ConfigService) {

View File

@@ -0,0 +1,29 @@
import { PrismaClient } from '@prisma/client';
import { ConfigService } from '../../../config/env.config';
import { Logger } from '../../../config/logger.config';
export class Query<T> {
where?: T;
sort?: 'asc' | 'desc';
page?: number;
offset?: number;
}
export class PrismaRepository extends PrismaClient {
constructor(private readonly configService: ConfigService) {
super();
}
private readonly logger = new Logger(PrismaRepository.name);
public async onModuleInit() {
await this.$connect();
this.logger.info('Repository:Prisma - ON');
}
public async onModuleDestroy() {
await this.$disconnect();
this.logger.warn('Repository:Prisma - OFF');
}
}

View File

@@ -37,9 +37,9 @@ import {
WhatsAppNumberDto,
} from '../dto/chat.dto';
import { InstanceDto } from '../dto/instance.dto';
import { ContactQuery } from '../repository/contact.repository';
import { MessageQuery } from '../repository/message.repository';
import { MessageUpQuery } from '../repository/messageUp.repository';
import { ContactQuery } from '../repository/mongodb/contact.repository';
import { MessageQuery } from '../repository/mongodb/message.repository';
import { MessageUpQuery } from '../repository/mongodb/messageUp.repository';
import { chatController } from '../server.module';
import { HttpStatus } from './index.router';

View File

@@ -1,10 +1,9 @@
import { Router } from 'express';
import fs from 'fs';
import { Auth, configService } from '../../config/env.config';
import { configService } from '../../config/env.config';
import { authGuard } from '../guards/auth.guard';
import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard';
import { ChamaaiRouter } from '../integrations/chamaai/routes/chamaai.router';
import { ChatwootRouter } from '../integrations/chatwoot/routes/chatwoot.router';
import { RabbitmqRouter } from '../integrations/rabbitmq/routes/rabbitmq.router';
import { SqsRouter } from '../integrations/sqs/routes/sqs.router';
@@ -31,9 +30,8 @@ enum HttpStatus {
}
const router = Router();
const authType = configService.get<Auth>('AUTHENTICATION').TYPE;
const serverConfig = configService.get('SERVER');
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard[authType]];
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard['apikey']];
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
@@ -45,7 +43,6 @@ router
status: HttpStatus.OK,
message: 'Welcome to the Evolution API, it is working!',
version: packageJson.version,
swagger: !serverConfig.DISABLE_DOCS ? `${req.protocol}://${req.get('host')}/docs` : undefined,
manager: !serverConfig.DISABLE_MANAGER ? `${req.protocol}://${req.get('host')}/manager` : undefined,
documentation: `https://doc.evolution-api.com`,
});
@@ -62,7 +59,6 @@ router
.use('/sqs', new SqsRouter(...guards).router)
.use('/typebot', new TypebotRouter(...guards).router)
.use('/proxy', new ProxyRouter(...guards).router)
.use('/chamaai', new ChamaaiRouter(...guards).router)
.use('/label', new LabelRouter(...guards).router);
export { HttpStatus, router };

View File

@@ -1,13 +1,12 @@
import { RequestHandler, Router } from 'express';
import { Auth, ConfigService, Database } from '../../config/env.config';
import { ConfigService, Database } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { dbserver } from '../../libs/db.connect';
import { instanceNameSchema, oldTokenSchema, presenceOnlySchema } from '../../validate/validate.schema';
import { mongodbServer } from '../../libs/mongodb.connect';
import { instanceNameSchema, presenceOnlySchema } from '../../validate/validate.schema';
import { RouterBroker } from '../abstract/abstract.router';
import { InstanceDto, SetPresenceDto } from '../dto/instance.dto';
import { instanceController } from '../server.module';
import { OldToken } from '../services/auth.service';
import { HttpStatus } from './index.router';
const logger = new Logger('InstanceRouter');
@@ -15,7 +14,6 @@ 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');
@@ -165,25 +163,6 @@ export class InstanceRouter extends RouterBroker {
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: ');
@@ -194,7 +173,7 @@ export class InstanceRouter extends RouterBroker {
const db = this.configService.get<Database>('DATABASE');
if (db.ENABLED) {
try {
await dbserver.dropDatabase();
await mongodbServer.dropDatabase();
return res
.status(HttpStatus.CREATED)
.json({ status: 'SUCCESS', error: false, response: { message: 'database deleted' } });

View File

@@ -2,7 +2,8 @@ import { CacheEngine } from '../cache/cacheengine';
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 { mongodbServer } from '../libs/mongodb.connect';
import { prismaServer } from '../libs/prisma.connect';
import { ChatController } from './controllers/chat.controller';
import { GroupController } from './controllers/group.controller';
import { InstanceController } from './controllers/instance.controller';
@@ -11,9 +12,6 @@ import { ProxyController } from './controllers/proxy.controller';
import { SendMessageController } from './controllers/sendMessage.controller';
import { SettingsController } from './controllers/settings.controller';
import { WebhookController } from './controllers/webhook.controller';
import { ChamaaiController } from './integrations/chamaai/controllers/chamaai.controller';
import { ChamaaiRepository } from './integrations/chamaai/repository/chamaai.repository';
import { ChamaaiService } from './integrations/chamaai/services/chamaai.service';
import { ChatwootController } from './integrations/chatwoot/controllers/chatwoot.controller';
import { ChatwootRepository } from './integrations/chatwoot/repository/chatwoot.repository';
import { ChatwootService } from './integrations/chatwoot/services/chatwoot.service';
@@ -31,7 +29,6 @@ import { WebsocketRepository } from './integrations/websocket/repository/websock
import { WebsocketService } from './integrations/websocket/services/websocket.service';
import {
AuthModel,
ChamaaiModel,
ChatModel,
ChatwootModel,
ContactModel,
@@ -48,17 +45,18 @@ import {
} from './models';
import { LabelModel } from './models/label.model';
import { ProviderFiles } from './provider/sessions';
import { AuthRepository } from './repository/auth.repository';
import { ChatRepository } from './repository/chat.repository';
import { ContactRepository } from './repository/contact.repository';
import { IntegrationRepository } from './repository/integration.repository';
import { LabelRepository } from './repository/label.repository';
import { MessageRepository } from './repository/message.repository';
import { MessageUpRepository } from './repository/messageUp.repository';
import { ProxyRepository } from './repository/proxy.repository';
import { RepositoryBroker } from './repository/repository.manager';
import { SettingsRepository } from './repository/settings.repository';
import { WebhookRepository } from './repository/webhook.repository';
import { AuthRepository } from './repository/mongodb/auth.repository';
import { ChatRepository } from './repository/mongodb/chat.repository';
import { ContactRepository } from './repository/mongodb/contact.repository';
import { IntegrationRepository } from './repository/mongodb/integration.repository';
import { LabelRepository } from './repository/mongodb/label.repository';
import { MessageRepository } from './repository/mongodb/message.repository';
import { MessageUpRepository } from './repository/mongodb/messageUp.repository';
import { ProxyRepository } from './repository/mongodb/proxy.repository';
import { MongodbRepository } from './repository/mongodb/repository.manager';
import { SettingsRepository } from './repository/mongodb/settings.repository';
import { WebhookRepository } from './repository/mongodb/webhook.repository';
import { PrismaRepository } from './repository/prisma/repository.service';
import { AuthService } from './services/auth.service';
import { CacheService } from './services/cache.service';
import { IntegrationService } from './services/integration.service';
@@ -77,7 +75,6 @@ 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 sqsRepository = new SqsRepository(SqsModel, configService);
const integrationRepository = new IntegrationRepository(IntegrationModel, configService);
@@ -86,7 +83,7 @@ const settingsRepository = new SettingsRepository(SettingsModel, configService);
const authRepository = new AuthRepository(AuthModel, IntegrationModel, configService);
const labelRepository = new LabelRepository(LabelModel, configService);
export const repository = new RepositoryBroker(
export const mongodbRepository = new MongodbRepository(
messageRepository,
chatRepository,
contactRepository,
@@ -99,14 +96,16 @@ export const repository = new RepositoryBroker(
sqsRepository,
typebotRepository,
proxyRepository,
chamaaiRepository,
integrationRepository,
authRepository,
labelRepository,
configService,
dbserver?.getClient(),
mongodbServer.getClient(),
prismaServer,
);
export const prismaRepository = new PrismaRepository(configService);
export const cache = new CacheService(new CacheEngine(configService, 'instance').getEngine());
const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine());
const baileysCache = new CacheService(new CacheEngine(configService, 'baileys').getEngine());
@@ -115,14 +114,15 @@ const providerFiles = new ProviderFiles(configService);
export const waMonitor = new WAMonitoringService(
eventEmitter,
configService,
repository,
mongodbRepository,
prismaRepository,
cache,
chatwootCache,
baileysCache,
providerFiles,
);
const authService = new AuthService(configService, waMonitor, repository);
const authService = new AuthService(waMonitor, mongodbRepository, prismaRepository);
const typebotService = new TypebotService(waMonitor, configService, eventEmitter);
export const typebotController = new TypebotController(typebotService);
@@ -136,9 +136,6 @@ export const websocketController = new WebsocketController(websocketService);
const proxyService = new ProxyService(waMonitor);
export const proxyController = new ProxyController(proxyService, waMonitor);
const chamaaiService = new ChamaaiService(waMonitor, configService);
export const chamaaiController = new ChamaaiController(chamaaiService);
const rabbitmqService = new RabbitmqService(waMonitor);
export const rabbitmqController = new RabbitmqController(rabbitmqService);
@@ -147,8 +144,19 @@ export const sqsController = new SqsController(sqsService);
const integrationService = new IntegrationService(waMonitor);
const chatwootService = new ChatwootService(waMonitor, configService, repository, chatwootCache);
export const chatwootController = new ChatwootController(chatwootService, configService, repository);
const chatwootService = new ChatwootService(
waMonitor,
configService,
mongodbRepository,
prismaRepository,
chatwootCache,
);
export const chatwootController = new ChatwootController(
chatwootService,
configService,
mongodbRepository,
prismaRepository,
);
const settingsService = new SettingsService(waMonitor);
export const settingsController = new SettingsController(settingsService);
@@ -156,7 +164,8 @@ export const settingsController = new SettingsController(settingsService);
export const instanceController = new InstanceController(
waMonitor,
configService,
repository,
mongodbRepository,
prismaRepository,
eventEmitter,
authService,
webhookService,

View File

@@ -1,75 +1,30 @@
import axios from 'axios';
import { isJWT } from 'class-validator';
import { sign, verify } from 'jsonwebtoken';
import { v4 } from 'uuid';
import { name as apiName } from '../../../package.json';
import { Auth, ConfigService, Webhook } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { RepositoryBroker } from '../repository/repository.manager';
import { MongodbRepository } from '../repository/mongodb/repository.manager';
import { PrismaRepository } from '../repository/prisma/repository.service';
import { WAMonitoringService } from './monitor.service';
export type JwtPayload = {
instanceName: string;
apiName: string;
jwt?: string;
apikey?: string;
tokenId: string;
};
export class OldToken {
oldToken: string;
}
export class AuthService {
constructor(
private readonly configService: ConfigService,
private readonly waMonitor: WAMonitoringService,
private readonly repository: RepositoryBroker,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
) {}
private readonly logger = new Logger(AuthService.name);
private async jwt(instance: InstanceDto) {
const jwtOpts = this.configService.get<Auth>('AUTHENTICATION').JWT;
const token = sign(
{
instanceName: instance.instanceName,
apiName,
tokenId: v4(),
},
jwtOpts.SECRET,
{ expiresIn: jwtOpts.EXPIRIN_IN, encoding: 'utf8', subject: 'g-t' },
);
this.logger.verbose('JWT token created: ' + token);
const auth = await this.repository.auth.create(
{ jwt: token, instanceId: instance.instanceId },
instance.instanceName,
);
this.logger.verbose('JWT token saved in database');
if (auth['error']) {
this.logger.error({
localError: AuthService.name + '.jwt',
error: auth['error'],
});
throw new BadRequestException('Authentication error', auth['error']?.toString());
}
return { jwt: token };
}
private async apikey(instance: InstanceDto, token?: string) {
const apikey = token ? token : v4().toUpperCase();
this.logger.verbose(token ? 'APIKEY defined: ' + apikey : 'APIKEY created: ' + apikey);
const auth = await this.repository.auth.create({ apikey, instanceId: instance.instanceId }, instance.instanceName);
const auth = await this.mongodbRepository.auth.create(
{ apikey, instanceId: instance.instanceId },
instance.instanceName,
);
this.logger.verbose('APIKEY saved in database');
@@ -101,80 +56,8 @@ export class AuthService {
}
public async generateHash(instance: InstanceDto, token?: string) {
const options = this.configService.get<Auth>('AUTHENTICATION');
this.logger.verbose('generating hash apiKey to instance: ' + instance.instanceName);
this.logger.verbose('generating hash ' + options.TYPE + ' to instance: ' + instance.instanceName);
return (await this[options.TYPE](instance, token)) as { jwt: string } | { apikey: string };
}
public async refreshToken({ oldToken }: OldToken) {
this.logger.verbose('refreshing token');
if (!isJWT(oldToken)) {
throw new BadRequestException('Invalid "oldToken"');
}
try {
const jwtOpts = this.configService.get<Auth>('AUTHENTICATION').JWT;
this.logger.verbose('checking oldToken');
const decode = verify(oldToken, jwtOpts.SECRET, {
ignoreExpiration: true,
}) as Pick<JwtPayload, 'apiName' | 'instanceName' | 'tokenId'>;
this.logger.verbose('checking token in database');
const tokenStore = await this.repository.auth.find(decode.instanceName);
const decodeTokenStore = verify(tokenStore.jwt, jwtOpts.SECRET, {
ignoreExpiration: true,
}) as Pick<JwtPayload, 'apiName' | 'instanceName' | 'tokenId'>;
this.logger.verbose('checking tokenId');
if (decode.tokenId !== decodeTokenStore.tokenId) {
throw new BadRequestException('Invalid "oldToken"');
}
this.logger.verbose('generating new token');
const token = {
jwt: (await this.jwt({ instanceName: decode.instanceName })).jwt,
instanceName: decode.instanceName,
};
try {
this.logger.verbose('checking webhook');
const webhook = await this.repository.webhook.find(decode.instanceName);
if (webhook?.enabled && this.configService.get<Webhook>('WEBHOOK').EVENTS.NEW_JWT_TOKEN) {
this.logger.verbose('sending webhook');
const httpService = axios.create({ baseURL: webhook.url });
await httpService.post(
'',
{
event: 'new.jwt',
instance: decode.instanceName,
data: token,
},
{ params: { owner: this.waMonitor.waInstances[decode.instanceName].wuid } },
);
}
} catch (error) {
this.logger.error(error);
}
this.logger.verbose('token refreshed');
return token;
} catch (error) {
this.logger.error({
localError: AuthService.name + '.refreshToken',
error,
});
throw new BadRequestException('Invalid "oldToken"');
}
return (await this.apikey(instance, token)) as { apikey: string };
}
}

View File

@@ -21,7 +21,6 @@ import {
import { Logger } from '../../config/logger.config';
import { ROOT_DIR } from '../../config/path.config';
import { NotFoundException } from '../../exceptions';
import { ChamaaiService } from '../integrations/chamaai/services/chamaai.service';
import { ChatwootRaw } from '../integrations/chatwoot/models/chatwoot.model';
import { ChatwootService } from '../integrations/chatwoot/services/chatwoot.service';
import { getAMQP, removeQueues } from '../integrations/rabbitmq/libs/amqp.server';
@@ -29,12 +28,13 @@ import { getSQS, removeQueues as removeQueuesSQS } from '../integrations/sqs/lib
import { TypebotService } from '../integrations/typebot/services/typebot.service';
import { getIO } from '../integrations/websocket/libs/socket.server';
import { WebsocketRaw } from '../integrations/websocket/models/websocket.model';
import { ChamaaiRaw, IntegrationRaw, ProxyRaw, RabbitmqRaw, SettingsRaw, SqsRaw, TypebotRaw } from '../models';
import { IntegrationRaw, ProxyRaw, RabbitmqRaw, SettingsRaw, SqsRaw, TypebotRaw } from '../models';
import { WebhookRaw } from '../models/webhook.model';
import { ContactQuery } from '../repository/contact.repository';
import { MessageQuery } from '../repository/message.repository';
import { MessageUpQuery } from '../repository/messageUp.repository';
import { RepositoryBroker } from '../repository/repository.manager';
import { ContactQuery } from '../repository/mongodb/contact.repository';
import { MessageQuery } from '../repository/mongodb/message.repository';
import { MessageUpQuery } from '../repository/mongodb/messageUp.repository';
import { MongodbRepository } from '../repository/mongodb/repository.manager';
import { PrismaRepository } from '../repository/prisma/repository.service';
import { waMonitor } from '../server.module';
import { Events, wa } from '../types/wa.types';
import { CacheService } from './cache.service';
@@ -43,7 +43,8 @@ export class ChannelStartupService {
constructor(
public readonly configService: ConfigService,
public readonly eventEmitter: EventEmitter2,
public readonly repository: RepositoryBroker,
public readonly mongodbRepository: MongodbRepository,
public readonly prismaRepository: PrismaRepository,
public readonly chatwootCache: CacheService,
) {
this.logger.verbose('ChannelStartupService initialized');
@@ -60,17 +61,20 @@ export class ChannelStartupService {
public readonly localSqs: wa.LocalSqs = {};
public readonly localTypebot: wa.LocalTypebot = {};
public readonly localProxy: wa.LocalProxy = {};
public readonly localChamaai: wa.LocalChamaai = {};
public readonly localIntegration: wa.LocalIntegration = {};
public readonly localSettings: wa.LocalSettings = {};
public readonly storePath = join(ROOT_DIR, 'store');
public chatwootService = new ChatwootService(waMonitor, this.configService, this.repository, this.chatwootCache);
public chatwootService = new ChatwootService(
waMonitor,
this.configService,
this.mongodbRepository,
this.prismaRepository,
this.chatwootCache,
);
public typebotService = new TypebotService(waMonitor, this.configService, this.eventEmitter);
public chamaaiService = new ChamaaiService(waMonitor, this.configService);
public set instanceName(name: string) {
this.logger.setInstance(name);
@@ -112,7 +116,7 @@ export class ChannelStartupService {
public async loadIntegration() {
this.logger.verbose('Loading webhook');
const data = await this.repository.integration.find(this.instanceName);
const data = await this.mongodbRepository.integration.find(this.instanceName);
this.localIntegration.integration = data?.integration;
this.logger.verbose(`Integration: ${this.localIntegration.integration}`);
@@ -127,7 +131,7 @@ export class ChannelStartupService {
public async setIntegration(data: IntegrationRaw) {
this.logger.verbose('Setting integration');
await this.repository.integration.create(data, this.instanceName);
await this.mongodbRepository.integration.create(data, this.instanceName);
this.logger.verbose(`Integration: ${data.integration}`);
this.logger.verbose(`Integration number: ${data.number}`);
this.logger.verbose(`Integration token: ${data.token}`);
@@ -139,10 +143,13 @@ export class ChannelStartupService {
this.logger.verbose('Finding integration');
let data: any;
data = await this.repository.integration.find(this.instanceName);
data = await this.mongodbRepository.integration.find(this.instanceName);
if (!data) {
this.repository.integration.create({ integration: 'WHATSAPP-BAILEYS', number: '', token: '' }, this.instanceName);
this.mongodbRepository.integration.create(
{ integration: 'WHATSAPP-BAILEYS', number: '', token: '' },
this.instanceName,
);
data = { integration: 'WHATSAPP-BAILEYS', number: '', token: '' };
}
@@ -159,7 +166,7 @@ export class ChannelStartupService {
public async loadSettings() {
this.logger.verbose('Loading settings');
const data = await this.repository.settings.find(this.instanceName);
const data = await this.mongodbRepository.settings.find(this.instanceName);
this.localSettings.reject_call = data?.reject_call;
this.logger.verbose(`Settings reject_call: ${this.localSettings.reject_call}`);
@@ -186,7 +193,7 @@ export class ChannelStartupService {
public async setSettings(data: SettingsRaw) {
this.logger.verbose('Setting settings');
await this.repository.settings.create(data, this.instanceName);
await this.mongodbRepository.settings.create(data, this.instanceName);
this.logger.verbose(`Settings reject_call: ${data.reject_call}`);
this.logger.verbose(`Settings msg_call: ${data.msg_call}`);
this.logger.verbose(`Settings groups_ignore: ${data.groups_ignore}`);
@@ -200,7 +207,7 @@ export class ChannelStartupService {
public async findSettings() {
this.logger.verbose('Finding settings');
const data = await this.repository.settings.find(this.instanceName);
const data = await this.mongodbRepository.settings.find(this.instanceName);
if (!data) {
this.logger.verbose('Settings not found');
@@ -227,7 +234,7 @@ export class ChannelStartupService {
public async loadWebhook() {
this.logger.verbose('Loading webhook');
const data = await this.repository.webhook.find(this.instanceName);
const data = await this.mongodbRepository.webhook.find(this.instanceName);
this.localWebhook.url = data?.url;
this.logger.verbose(`Webhook url: ${this.localWebhook.url}`);
@@ -248,7 +255,7 @@ export class ChannelStartupService {
public async setWebhook(data: WebhookRaw) {
this.logger.verbose('Setting webhook');
await this.repository.webhook.create(data, this.instanceName);
await this.mongodbRepository.webhook.create(data, this.instanceName);
this.logger.verbose(`Webhook url: ${data.url}`);
this.logger.verbose(`Webhook events: ${data.events}`);
Object.assign(this.localWebhook, data);
@@ -257,7 +264,7 @@ export class ChannelStartupService {
public async findWebhook() {
this.logger.verbose('Finding webhook');
const data = await this.repository.webhook.find(this.instanceName);
const data = await this.mongodbRepository.webhook.find(this.instanceName);
if (!data) {
this.logger.verbose('Webhook not found');
@@ -278,7 +285,7 @@ export class ChannelStartupService {
public async loadChatwoot() {
this.logger.verbose('Loading chatwoot');
const data = await this.repository.chatwoot.find(this.instanceName);
const data = await this.mongodbRepository.chatwoot.find(this.instanceName);
this.localChatwoot.enabled = data?.enabled;
this.logger.verbose(`Chatwoot enabled: ${this.localChatwoot.enabled}`);
@@ -323,7 +330,7 @@ export class ChannelStartupService {
public async setChatwoot(data: ChatwootRaw) {
this.logger.verbose('Setting chatwoot');
await this.repository.chatwoot.create(data, this.instanceName);
await this.mongodbRepository.chatwoot.create(data, this.instanceName);
this.logger.verbose(`Chatwoot account id: ${data.account_id}`);
this.logger.verbose(`Chatwoot token: ${data.token}`);
this.logger.verbose(`Chatwoot url: ${data.url}`);
@@ -346,7 +353,7 @@ export class ChannelStartupService {
public async findChatwoot() {
this.logger.verbose('Finding chatwoot');
const data = await this.repository.chatwoot.find(this.instanceName);
const data = await this.mongodbRepository.chatwoot.find(this.instanceName);
if (!data) {
this.logger.verbose('Chatwoot not found');
@@ -393,7 +400,7 @@ export class ChannelStartupService {
public async loadWebsocket() {
this.logger.verbose('Loading websocket');
const data = await this.repository.websocket.find(this.instanceName);
const data = await this.mongodbRepository.websocket.find(this.instanceName);
this.localWebsocket.enabled = data?.enabled;
this.logger.verbose(`Websocket enabled: ${this.localWebsocket.enabled}`);
@@ -406,7 +413,7 @@ export class ChannelStartupService {
public async setWebsocket(data: WebsocketRaw) {
this.logger.verbose('Setting websocket');
await this.repository.websocket.create(data, this.instanceName);
await this.mongodbRepository.websocket.create(data, this.instanceName);
this.logger.verbose(`Websocket events: ${data.events}`);
Object.assign(this.localWebsocket, data);
this.logger.verbose('Websocket set');
@@ -414,7 +421,7 @@ export class ChannelStartupService {
public async findWebsocket() {
this.logger.verbose('Finding websocket');
const data = await this.repository.websocket.find(this.instanceName);
const data = await this.mongodbRepository.websocket.find(this.instanceName);
if (!data) {
this.logger.verbose('Websocket not found');
@@ -430,7 +437,7 @@ export class ChannelStartupService {
public async loadRabbitmq() {
this.logger.verbose('Loading rabbitmq');
const data = await this.repository.rabbitmq.find(this.instanceName);
const data = await this.mongodbRepository.rabbitmq.find(this.instanceName);
this.localRabbitmq.enabled = data?.enabled;
this.logger.verbose(`Rabbitmq enabled: ${this.localRabbitmq.enabled}`);
@@ -443,7 +450,7 @@ export class ChannelStartupService {
public async setRabbitmq(data: RabbitmqRaw) {
this.logger.verbose('Setting rabbitmq');
await this.repository.rabbitmq.create(data, this.instanceName);
await this.mongodbRepository.rabbitmq.create(data, this.instanceName);
this.logger.verbose(`Rabbitmq events: ${data.events}`);
Object.assign(this.localRabbitmq, data);
this.logger.verbose('Rabbitmq set');
@@ -451,7 +458,7 @@ export class ChannelStartupService {
public async findRabbitmq() {
this.logger.verbose('Finding rabbitmq');
const data = await this.repository.rabbitmq.find(this.instanceName);
const data = await this.mongodbRepository.rabbitmq.find(this.instanceName);
if (!data) {
this.logger.verbose('Rabbitmq not found');
@@ -475,7 +482,7 @@ export class ChannelStartupService {
public async loadSqs() {
this.logger.verbose('Loading sqs');
const data = await this.repository.sqs.find(this.instanceName);
const data = await this.mongodbRepository.sqs.find(this.instanceName);
this.localSqs.enabled = data?.enabled;
this.logger.verbose(`Sqs enabled: ${this.localSqs.enabled}`);
@@ -488,7 +495,7 @@ export class ChannelStartupService {
public async setSqs(data: SqsRaw) {
this.logger.verbose('Setting sqs');
await this.repository.sqs.create(data, this.instanceName);
await this.mongodbRepository.sqs.create(data, this.instanceName);
this.logger.verbose(`Sqs events: ${data.events}`);
Object.assign(this.localSqs, data);
this.logger.verbose('Sqs set');
@@ -496,7 +503,7 @@ export class ChannelStartupService {
public async findSqs() {
this.logger.verbose('Finding sqs');
const data = await this.repository.sqs.find(this.instanceName);
const data = await this.mongodbRepository.sqs.find(this.instanceName);
if (!data) {
this.logger.verbose('Sqs not found');
@@ -520,7 +527,7 @@ export class ChannelStartupService {
public async loadTypebot() {
this.logger.verbose('Loading typebot');
const data = await this.repository.typebot.find(this.instanceName);
const data = await this.mongodbRepository.typebot.find(this.instanceName);
this.localTypebot.enabled = data?.enabled;
this.logger.verbose(`Typebot enabled: ${this.localTypebot.enabled}`);
@@ -553,7 +560,7 @@ export class ChannelStartupService {
public async setTypebot(data: TypebotRaw) {
this.logger.verbose('Setting typebot');
await this.repository.typebot.create(data, this.instanceName);
await this.mongodbRepository.typebot.create(data, this.instanceName);
this.logger.verbose(`Typebot typebot: ${data.typebot}`);
this.logger.verbose(`Typebot expire: ${data.expire}`);
this.logger.verbose(`Typebot keyword_finish: ${data.keyword_finish}`);
@@ -566,7 +573,7 @@ export class ChannelStartupService {
public async findTypebot() {
this.logger.verbose('Finding typebot');
const data = await this.repository.typebot.find(this.instanceName);
const data = await this.mongodbRepository.typebot.find(this.instanceName);
if (!data) {
this.logger.verbose('Typebot not found');
@@ -588,7 +595,7 @@ export class ChannelStartupService {
public async loadProxy() {
this.logger.verbose('Loading proxy');
const data = await this.repository.proxy.find(this.instanceName);
const data = await this.mongodbRepository.proxy.find(this.instanceName);
this.localProxy.enabled = data?.enabled;
this.logger.verbose(`Proxy enabled: ${this.localProxy.enabled}`);
@@ -601,7 +608,7 @@ export class ChannelStartupService {
public async setProxy(data: ProxyRaw) {
this.logger.verbose('Setting proxy');
await this.repository.proxy.create(data, this.instanceName);
await this.mongodbRepository.proxy.create(data, this.instanceName);
this.logger.verbose(`Proxy proxy: ${data.proxy}`);
Object.assign(this.localProxy, data);
this.logger.verbose('Proxy set');
@@ -609,7 +616,7 @@ export class ChannelStartupService {
public async findProxy() {
this.logger.verbose('Finding proxy');
const data = await this.repository.proxy.find(this.instanceName);
const data = await this.mongodbRepository.proxy.find(this.instanceName);
if (!data) {
this.logger.verbose('Proxy not found');
@@ -622,70 +629,6 @@ export class ChannelStartupService {
};
}
public async loadChamaai() {
this.logger.verbose('Loading chamaai');
const data = await this.repository.chamaai.find(this.instanceName);
this.localChamaai.enabled = data?.enabled;
this.logger.verbose(`Chamaai enabled: ${this.localChamaai.enabled}`);
this.localChamaai.url = data?.url;
this.logger.verbose(`Chamaai url: ${this.localChamaai.url}`);
this.localChamaai.token = data?.token;
this.logger.verbose(`Chamaai token: ${this.localChamaai.token}`);
this.localChamaai.waNumber = data?.waNumber;
this.logger.verbose(`Chamaai waNumber: ${this.localChamaai.waNumber}`);
this.localChamaai.answerByAudio = data?.answerByAudio;
this.logger.verbose(`Chamaai answerByAudio: ${this.localChamaai.answerByAudio}`);
this.logger.verbose('Chamaai loaded');
}
public async setChamaai(data: ChamaaiRaw) {
this.logger.verbose('Setting chamaai');
await this.repository.chamaai.create(data, this.instanceName);
this.logger.verbose(`Chamaai url: ${data.url}`);
this.logger.verbose(`Chamaai token: ${data.token}`);
this.logger.verbose(`Chamaai waNumber: ${data.waNumber}`);
this.logger.verbose(`Chamaai answerByAudio: ${data.answerByAudio}`);
Object.assign(this.localChamaai, data);
this.logger.verbose('Chamaai set');
}
public async findChamaai() {
this.logger.verbose('Finding chamaai');
const data = await this.repository.chamaai.find(this.instanceName);
if (!data) {
this.logger.verbose('Chamaai not found');
throw new NotFoundException('Chamaai not found');
}
return {
enabled: data.enabled,
url: data.url,
token: data.token,
waNumber: data.waNumber,
answerByAudio: data.answerByAudio,
};
}
private assertExchangeAsync = (channel, exchangeName, exchangeType, options) => {
return new Promise((resolve, reject) => {
channel.assertExchange(exchangeName, exchangeType, options, (error, ok) => {
if (error) {
reject(error);
} else {
resolve(ok);
}
});
});
};
public async sendDataWebhook<T = any>(event: Events, data: T, local = true) {
const webhookGlobal = this.configService.get<Webhook>('WEBHOOK');
const webhookLocal = this.localWebhook.events;
@@ -703,7 +646,7 @@ export class ChannelStartupService {
const now = localISOTime;
const expose = this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES;
const tokenStore = await this.repository.auth.find(this.instanceName);
const tokenStore = await this.mongodbRepository.auth.find(this.instanceName);
const instanceApikey = tokenStore?.apikey || 'Apikey not found';
if (rabbitmqEnabled) {
@@ -1238,7 +1181,7 @@ export class ChannelStartupService {
},
};
}
return await this.repository.contact.find(query);
return await this.mongodbRepository.contact.find(query);
}
public async fetchMessages(query: MessageQuery) {
@@ -1256,7 +1199,7 @@ export class ChannelStartupService {
limit: query?.limit,
};
}
return await this.repository.message.find(query);
return await this.mongodbRepository.message.find(query);
}
public async fetchStatusMessage(query: MessageUpQuery) {
@@ -1274,11 +1217,11 @@ export class ChannelStartupService {
limit: query?.limit,
};
}
return await this.repository.messageUpdate.find(query);
return await this.mongodbRepository.messageUpdate.find(query);
}
public async fetchChats() {
this.logger.verbose('Fetching chats');
return await this.repository.chat.find({ where: { owner: this.instance.name } });
return await this.mongodbRepository.chat.find({ where: { owner: this.instance.name } });
}
}

View File

@@ -68,9 +68,10 @@ import {
} from '../../../config/env.config';
import { INSTANCE_DIR } from '../../../config/path.config';
import { BadRequestException, InternalServerErrorException, NotFoundException } from '../../../exceptions';
import { dbserver } from '../../../libs/db.connect';
import { mongodbServer } from '../../../libs/mongodb.connect';
import { makeProxyAgent } from '../../../utils/makeProxyAgent';
import { useMultiFileAuthStateDb } from '../../../utils/use-multi-file-auth-state-db';
import { useMultiFileAuthStateMongoDb } from '../../../utils/use-multi-file-auth-state-mongodb';
import useMultiFileAuthStatePrisma from '../../../utils/use-multi-file-auth-state-prisma';
import { AuthStateProvider } from '../../../utils/use-multi-file-auth-state-provider-files';
import { useMultiFileAuthStateRedisDb } from '../../../utils/use-multi-file-auth-state-redis-db';
import {
@@ -126,7 +127,8 @@ import { ChatRaw } from '../../models/chat.model';
import { ContactRaw } from '../../models/contact.model';
import { MessageRaw, MessageUpdateRaw } from '../../models/message.model';
import { ProviderFiles } from '../../provider/sessions';
import { RepositoryBroker } from '../../repository/repository.manager';
import { MongodbRepository } from '../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../repository/prisma/repository.service';
import { waMonitor } from '../../server.module';
import { Events, MessageSubtype, TypeMediaMessage, wa } from '../../types/wa.types';
import { CacheService } from './../cache.service';
@@ -138,13 +140,14 @@ export class BaileysStartupService extends ChannelStartupService {
constructor(
public readonly configService: ConfigService,
public readonly eventEmitter: EventEmitter2,
public readonly repository: RepositoryBroker,
public readonly mongoRepository: MongodbRepository,
public readonly prismaRepository: PrismaRepository,
public readonly cache: CacheService,
public readonly chatwootCache: CacheService,
public readonly baileysCache: CacheService,
private readonly providerFiles: ProviderFiles,
) {
super(configService, eventEmitter, repository, chatwootCache);
super(configService, eventEmitter, mongoRepository, prismaRepository, chatwootCache);
this.logger.verbose('BaileysStartupService initialized');
this.cleanStore();
this.instance.qrcode = { count: 0 };
@@ -224,7 +227,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('Profile name not found, trying to get from database');
if (this.configService.get<Database>('DATABASE').ENABLED) {
this.logger.verbose('Database enabled, trying to get from database');
const collection = dbserver
const collection = mongodbServer
.getClient()
.db(this.configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME + '-instances')
.collection(this.instanceName);
@@ -460,7 +463,7 @@ export class BaileysStartupService extends ChannelStartupService {
private async getMessage(key: proto.IMessageKey, full = false) {
this.logger.verbose('Getting message with key: ' + JSON.stringify(key));
try {
const webMessageInfo = (await this.repository.message.find({
const webMessageInfo = (await this.mongodbRepository.message.find({
where: { owner: this.instance.name, key: { id: key.id } },
})) as unknown as proto.IWebMessageInfo[];
if (full) {
@@ -510,7 +513,8 @@ export class BaileysStartupService extends ChannelStartupService {
if (db.SAVE_DATA.INSTANCE && db.ENABLED) {
this.logger.verbose('Database enabled');
return await useMultiFileAuthStateDb(this.instance.name);
if (db.PROVIDER === 'mongodb') return await useMultiFileAuthStateMongoDb(this.instance.name);
else return await useMultiFileAuthStatePrisma(this.instance.name);
}
this.logger.verbose('Store file enabled');
@@ -528,7 +532,6 @@ export class BaileysStartupService extends ChannelStartupService {
this.loadSqs();
this.loadTypebot();
this.loadProxy();
this.loadChamaai();
this.instance.authState = await this.defineAuthState();
@@ -827,7 +830,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('Event received: chats.upsert');
this.logger.verbose('Finding chats in database');
const chatsRepository = await this.repository.chat.find({
const chatsRepository = await this.mongodbRepository.chat.find({
where: { owner: this.instance.name },
});
@@ -845,7 +848,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CHATS_UPSERT, chatsRaw);
this.logger.verbose('Inserting chats in database');
this.repository.chat.insert(chatsRaw, this.instance.name, database.SAVE_DATA.CHATS);
this.mongodbRepository.chat.insert(chatsRaw, this.instance.name, database.SAVE_DATA.CHATS);
},
'chats.update': async (
@@ -872,7 +875,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('Deleting chats in database');
chats.forEach(
async (chat) =>
await this.repository.chat.delete({
await this.mongodbRepository.chat.delete({
where: { owner: this.instance.name, id: chat },
}),
);
@@ -890,7 +893,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('Finding contacts in database');
const contactsRepository = new Set(
(
await this.repository.contact.find({
await this.mongodbRepository.contact.find({
select: { id: 1, _id: 0 },
where: { owner: this.instance.name },
})
@@ -917,7 +920,7 @@ export class BaileysStartupService extends ChannelStartupService {
if (contactsRaw.length > 0) this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw);
this.logger.verbose('Inserting contacts in database');
this.repository.contact.insert(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
this.mongodbRepository.contact.insert(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
if (this.localChatwoot.enabled && this.localChatwoot.import_contacts && contactsRaw.length) {
this.chatwootService.addHistoryContacts({ instanceName: this.instance.name }, contactsRaw);
@@ -939,7 +942,7 @@ export class BaileysStartupService extends ChannelStartupService {
if (contactsRaw.length > 0) this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw);
this.logger.verbose('Updating contacts in database');
this.repository.contact.update(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
this.mongodbRepository.contact.update(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
} catch (error) {
this.logger.error(error);
}
@@ -963,7 +966,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CONTACTS_UPDATE, contactsRaw);
this.logger.verbose('Updating contacts in database');
this.repository.contact.update(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
this.mongodbRepository.contact.update(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS);
},
};
@@ -1004,7 +1007,7 @@ export class BaileysStartupService extends ChannelStartupService {
const chatsRaw: ChatRaw[] = [];
const chatsRepository = new Set(
(
await this.repository.chat.find({
await this.mongodbRepository.chat.find({
select: { id: 1, _id: 0 },
where: { owner: this.instance.name },
})
@@ -1027,13 +1030,13 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CHATS_SET, chatsRaw);
this.logger.verbose('Inserting chats in database');
this.repository.chat.insert(chatsRaw, this.instance.name, database.SAVE_DATA.CHATS);
this.mongodbRepository.chat.insert(chatsRaw, this.instance.name, database.SAVE_DATA.CHATS);
const messagesRaw: MessageRaw[] = [];
const messagesRepository = new Set(
chatwootImport.getRepositoryMessagesCache(instance) ??
(
await this.repository.message.find({
await this.mongodbRepository.message.find({
select: { key: { id: 1 }, _id: 0 },
where: { owner: this.instance.name },
})
@@ -1086,7 +1089,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.MESSAGES_SET, [...messagesRaw]);
this.logger.verbose('Inserting messages in database');
await this.repository.message.insert(messagesRaw, this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
await this.mongodbRepository.message.insert(messagesRaw, this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
if (this.localChatwoot.enabled && this.localChatwoot.import_messages && messagesRaw.length > 0) {
this.chatwootService.addHistoryMessages(
@@ -1262,19 +1265,11 @@ export class BaileysStartupService extends ChannelStartupService {
}
}
if (this.localChamaai.enabled && messageRaw.key.fromMe === false && type === 'notify') {
await this.chamaaiService.sendChamaai(
{ instanceName: this.instance.name },
messageRaw.key.remoteJid,
messageRaw,
);
}
this.logger.verbose('Inserting message in database');
await this.repository.message.insert([messageRaw], this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
await this.mongodbRepository.message.insert([messageRaw], this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
this.logger.verbose('Verifying contact from message');
const contact = await this.repository.contact.find({
const contact = await this.mongodbRepository.contact.find({
where: { owner: this.instance.name, id: received.key.remoteJid },
});
@@ -1311,7 +1306,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
this.logger.verbose('Updating contact in database');
await this.repository.contact.update([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
await this.mongodbRepository.contact.update([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
return;
}
@@ -1321,7 +1316,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
this.logger.verbose('Inserting contact in database');
this.repository.contact.insert([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
this.mongodbRepository.contact.insert([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
}
} catch (error) {
this.logger.error(error);
@@ -1388,7 +1383,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose(message);
this.logger.verbose('Inserting message in database');
await this.repository.messageUpdate.insert(
await this.mongodbRepository.messageUpdate.insert(
[message],
this.instance.name,
database.SAVE_DATA.MESSAGE_UPDATE,
@@ -1419,7 +1414,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.MESSAGES_UPDATE, message);
this.logger.verbose('Inserting message in database');
this.repository.messageUpdate.insert([message], this.instance.name, database.SAVE_DATA.MESSAGE_UPDATE);
this.mongodbRepository.messageUpdate.insert([message], this.instance.name, database.SAVE_DATA.MESSAGE_UPDATE);
}
}
},
@@ -1462,14 +1457,14 @@ export class BaileysStartupService extends ChannelStartupService {
[Events.LABELS_EDIT]: async (label: Label, database: Database) => {
this.logger.verbose('Event received: labels.edit');
this.logger.verbose('Finding labels in database');
const labelsRepository = await this.repository.labels.find({
const labelsRepository = await this.mongodbRepository.labels.find({
where: { owner: this.instance.name },
});
const savedLabel = labelsRepository.find((l) => l.id === label.id);
if (label.deleted && savedLabel) {
this.logger.verbose('Sending data to webhook in event LABELS_EDIT');
await this.repository.labels.delete({
await this.mongodbRepository.labels.delete({
where: { owner: this.instance.name, id: label.id },
});
this.sendDataWebhook(Events.LABELS_EDIT, { ...label, instance: this.instance.name });
@@ -1479,7 +1474,7 @@ export class BaileysStartupService extends ChannelStartupService {
const labelName = label.name.replace(/[^\x20-\x7E]/g, '');
if (!savedLabel || savedLabel.color !== label.color || savedLabel.name !== labelName) {
this.logger.verbose('Sending data to webhook in event LABELS_EDIT');
await this.repository.labels.insert(
await this.mongodbRepository.labels.insert(
{
color: label.color,
name: labelName,
@@ -1502,7 +1497,7 @@ export class BaileysStartupService extends ChannelStartupService {
// Atualiza labels nos chats
if (database.ENABLED && database.SAVE_DATA.CHATS) {
const chats = await this.repository.chat.find({
const chats = await this.mongodbRepository.chat.find({
where: {
owner: this.instance.name,
},
@@ -1515,7 +1510,7 @@ export class BaileysStartupService extends ChannelStartupService {
} else if (data.type === 'add') {
labels = [...labels, data.association.labelId];
}
await this.repository.chat.update(
await this.mongodbRepository.chat.update(
[{ id: chat.id, owner: this.instance.name, labels }],
this.instance.name,
database.SAVE_DATA.CHATS,
@@ -2041,7 +2036,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
this.logger.verbose('Inserting message in database');
await this.repository.message.insert(
await this.mongodbRepository.message.insert(
[messageRaw],
this.instance.name,
this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE,
@@ -2160,7 +2155,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('All contacts defined as true');
this.logger.verbose('Getting contacts from database');
const contacts = await this.repository.contact.find({
const contacts = await this.mongodbRepository.contact.find({
where: { owner: this.instance.name },
});
@@ -2686,7 +2681,7 @@ export class BaileysStartupService extends ChannelStartupService {
onWhatsapp.push(...groups);
// USERS
const contacts: ContactRaw[] = await this.repository.contact.findManyById({
const contacts: ContactRaw[] = await this.mongodbRepository.contact.findManyById({
owner: this.instance.name,
ids: jids.users.map(({ jid }) => (jid.startsWith('+') ? jid.substring(1) : jid)),
});
@@ -3177,7 +3172,7 @@ export class BaileysStartupService extends ChannelStartupService {
public async fetchLabels(): Promise<LabelDto[]> {
this.logger.verbose('Fetching labels');
const labels = await this.repository.labels.find({
const labels = await this.mongodbRepository.labels.find({
where: {
owner: this.instance.name,
},
@@ -3485,7 +3480,7 @@ export class BaileysStartupService extends ChannelStartupService {
this.logger.verbose('Fetching participants for group: ' + id.groupJid);
try {
const participants = (await this.client.groupMetadata(id.groupJid)).participants;
const contacts = await this.repository.contact.findManyById({
const contacts = await this.mongodbRepository.contact.findManyById({
owner: this.instance.name,
ids: participants.map((p) => p.id),
});

View File

@@ -24,7 +24,8 @@ import {
} from '../../dto/sendMessage.dto';
import { ContactRaw, MessageRaw, MessageUpdateRaw, SettingsRaw } from '../../models';
import { ProviderFiles } from '../../provider/sessions';
import { RepositoryBroker } from '../../repository/repository.manager';
import { MongodbRepository } from '../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../repository/prisma/repository.service';
import { Events, wa } from '../../types/wa.types';
import { CacheService } from './../cache.service';
import { ChannelStartupService } from './../channel.service';
@@ -33,13 +34,14 @@ export class BusinessStartupService extends ChannelStartupService {
constructor(
public readonly configService: ConfigService,
public readonly eventEmitter: EventEmitter2,
public readonly repository: RepositoryBroker,
public readonly mongodbRepository: MongodbRepository,
public readonly prismaRepository: PrismaRepository,
public readonly cache: CacheService,
public readonly chatwootCache: CacheService,
public readonly baileysCache: CacheService,
private readonly providerFiles: ProviderFiles,
) {
super(configService, eventEmitter, repository, chatwootCache);
super(configService, eventEmitter, mongodbRepository, prismaRepository, chatwootCache);
this.logger.verbose('BusinessStartupService initialized');
this.cleanStore();
}
@@ -146,7 +148,6 @@ export class BusinessStartupService extends ChannelStartupService {
this.loadRabbitmq();
this.loadSqs();
this.loadTypebot();
this.loadChamaai();
this.logger.verbose('Creating socket');
@@ -442,19 +443,11 @@ export class BusinessStartupService extends ChannelStartupService {
}
}
if (this.localChamaai.enabled && messageRaw.key.fromMe === false && received?.message.type === 'notify') {
await this.chamaaiService.sendChamaai(
{ instanceName: this.instance.name },
messageRaw.key.remoteJid,
messageRaw,
);
}
this.logger.verbose('Inserting message in database');
await this.repository.message.insert([messageRaw], this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
await this.mongodbRepository.message.insert([messageRaw], this.instance.name, database.SAVE_DATA.NEW_MESSAGE);
this.logger.verbose('Verifying contact from message');
const contact = await this.repository.contact.find({
const contact = await this.mongodbRepository.contact.find({
where: { owner: this.instance.name, id: key.remoteJid },
});
@@ -491,7 +484,7 @@ export class BusinessStartupService extends ChannelStartupService {
}
this.logger.verbose('Updating contact in database');
await this.repository.contact.update([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
await this.mongodbRepository.contact.update([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
return;
}
@@ -501,7 +494,7 @@ export class BusinessStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
this.logger.verbose('Inserting contact in database');
this.repository.contact.insert([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
this.mongodbRepository.contact.insert([contactRaw], this.instance.name, database.SAVE_DATA.CONTACTS);
}
this.logger.verbose('Event received: messages.update');
if (received.statuses) {
@@ -536,7 +529,7 @@ export class BusinessStartupService extends ChannelStartupService {
this.logger.verbose(message);
this.logger.verbose('Inserting message in database');
await this.repository.messageUpdate.insert(
await this.mongodbRepository.messageUpdate.insert(
[message],
this.instance.name,
database.SAVE_DATA.MESSAGE_UPDATE,
@@ -566,7 +559,11 @@ export class BusinessStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.MESSAGES_UPDATE, message);
this.logger.verbose('Inserting message in database');
this.repository.messageUpdate.insert([message], this.instance.name, database.SAVE_DATA.MESSAGE_UPDATE);
this.mongodbRepository.messageUpdate.insert(
[message],
this.instance.name,
database.SAVE_DATA.MESSAGE_UPDATE,
);
}
}
}
@@ -871,7 +868,7 @@ export class BusinessStartupService extends ChannelStartupService {
}
this.logger.verbose('Inserting message in database');
await this.repository.message.insert(
await this.mongodbRepository.message.insert(
[messageRaw],
this.instance.name,
this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE,

View File

@@ -19,7 +19,6 @@ import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config';
import { NotFoundException } from '../../exceptions';
import {
AuthModel,
ChamaaiModel,
ChatwootModel,
ContactModel,
LabelModel,
@@ -31,7 +30,8 @@ import {
WebsocketModel,
} from '../models';
import { ProviderFiles } from '../provider/sessions';
import { RepositoryBroker } from '../repository/repository.manager';
import { MongodbRepository } from '../repository/mongodb/repository.manager';
import { PrismaRepository } from '../repository/prisma/repository.service';
import { Integration } from '../types/wa.types';
import { CacheService } from './cache.service';
import { BaileysStartupService } from './channels/whatsapp.baileys.service';
@@ -41,7 +41,8 @@ export class WAMonitoringService {
constructor(
private readonly eventEmitter: EventEmitter2,
private readonly configService: ConfigService,
private readonly repository: RepositoryBroker,
private readonly monogodbRepository: MongodbRepository,
private readonly primaRepository: PrismaRepository,
private readonly cache: CacheService,
private readonly chatwootCache: CacheService,
private readonly baileysCache: CacheService,
@@ -56,7 +57,7 @@ export class WAMonitoringService {
Object.assign(this.redis, configService.get<CacheConf>('CACHE'));
this.dbInstance = this.db.ENABLED
? this.repository.dbServer?.db(this.db.CONNECTION.DB_PREFIX_NAME + '-instances')
? this.monogodbRepository.mongodbServer?.db(this.db.CONNECTION.DB_PREFIX_NAME + '-instances')
: undefined;
}
@@ -135,7 +136,7 @@ export class WAMonitoringService {
const instanceData = {
instance: {
instanceName: key,
instanceId: (await this.repository.auth.find(key))?.instanceId,
instanceId: (await this.monogodbRepository.auth.find(key))?.instanceId,
owner: value.wuid,
profileName: (await value.getProfileName()) || 'not loaded',
profilePictureUrl: value.profilePictureUrl,
@@ -147,7 +148,7 @@ export class WAMonitoringService {
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['apikey'] = (await this.monogodbRepository.auth.find(key))?.apikey;
instanceData.instance['chatwoot'] = chatwoot;
@@ -161,7 +162,7 @@ export class WAMonitoringService {
const instanceData = {
instance: {
instanceName: key,
instanceId: (await this.repository.auth.find(key))?.instanceId,
instanceId: (await this.monogodbRepository.auth.find(key))?.instanceId,
status: value.connectionStatus.state,
},
};
@@ -169,7 +170,7 @@ export class WAMonitoringService {
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['apikey'] = (await this.monogodbRepository.auth.find(key))?.apikey;
instanceData.instance['chatwoot'] = chatwoot;
@@ -193,12 +194,12 @@ export class WAMonitoringService {
this.logger.verbose('get instance info');
let instanceName: string;
if (instanceId) {
instanceName = await this.repository.auth.findInstanceNameById(instanceId);
instanceName = await this.monogodbRepository.auth.findInstanceNameById(instanceId);
if (!instanceName) {
throw new NotFoundException(`Instance "${instanceId}" not found`);
}
} else if (number) {
instanceName = await this.repository.auth.findInstanceNameByNumber(number);
instanceName = await this.monogodbRepository.auth.findInstanceNameByNumber(number);
if (!instanceName) {
throw new NotFoundException(`Instance "${number}" not found`);
}
@@ -254,7 +255,7 @@ export class WAMonitoringService {
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
this.logger.verbose('cleaning up instance in database: ' + instanceName);
await this.repository.dbServer.connect();
await this.monogodbRepository.mongodbServer.connect();
const collections: any[] = await this.dbInstance.collections();
if (collections.length > 0) {
await this.dbInstance.dropCollection(instanceName);
@@ -291,7 +292,6 @@ export class WAMonitoringService {
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 + '*')}`);
@@ -307,7 +307,6 @@ export class WAMonitoringService {
await AuthModel.deleteMany({ _id: 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 });
@@ -328,7 +327,8 @@ export class WAMonitoringService {
} else if (this.redis.REDIS.ENABLED && this.redis.REDIS.SAVE_INSTANCES) {
await this.loadInstancesFromRedis();
} else if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
await this.loadInstancesFromDatabase();
if (this.db.PROVIDER === 'mongodb') await this.loadInstancesFromDatabaseMongoDB();
else if (this.db.PROVIDER === 'postgresql') await this.loadInstancesFromDatabasePostgres();
} else {
await this.loadInstancesFromFiles();
}
@@ -343,7 +343,7 @@ export class WAMonitoringService {
try {
const msgParsed = JSON.parse(JSON.stringify(data));
if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) {
await this.repository.dbServer.connect();
await this.monogodbRepository.mongodbServer.connect();
await this.dbInstance.collection(data.instanceName).replaceOne({ _id: 'integration' }, msgParsed, {
upsert: true,
});
@@ -358,14 +358,15 @@ export class WAMonitoringService {
}
private async setInstance(name: string) {
const integration = await this.repository.integration.find(name);
const integration = await this.monogodbRepository.integration.find(name);
let instance: BaileysStartupService | BusinessStartupService;
if (integration && integration.integration === Integration.WHATSAPP_BUSINESS) {
instance = new BusinessStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.monogodbRepository,
this.primaRepository,
this.cache,
this.chatwootCache,
this.baileysCache,
@@ -377,7 +378,8 @@ export class WAMonitoringService {
instance = new BaileysStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.monogodbRepository,
this.primaRepository,
this.cache,
this.chatwootCache,
this.baileysCache,
@@ -410,9 +412,9 @@ export class WAMonitoringService {
}
}
private async loadInstancesFromDatabase() {
private async loadInstancesFromDatabaseMongoDB() {
this.logger.verbose('Database enabled');
await this.repository.dbServer.connect();
await this.monogodbRepository.mongodbServer.connect();
const collections: any[] = await this.dbInstance.collections();
await this.deleteTempInstances(collections);
if (collections.length > 0) {
@@ -423,6 +425,20 @@ export class WAMonitoringService {
}
}
private async loadInstancesFromDatabasePostgres() {
this.logger.verbose('Database enabled');
await this.primaRepository.onModuleInit();
const instances = await this.primaRepository.instance.findMany();
if (instances.length === 0) {
this.logger.verbose('No instances found');
return;
}
await Promise.all(instances.map(async (instance) => this.setInstance(instance.name)));
}
private async loadInstancesFromProvider() {
this.logger.verbose('Provider in files enabled');
const [instances] = await this.providerFiles.allInstances();
@@ -523,7 +539,7 @@ export class WAMonitoringService {
return;
}
this.logger.verbose('Cleaning up temp instances');
const auths = await this.repository.auth.list();
const auths = await this.monogodbRepository.auth.list();
if (auths.length === 0) {
this.logger.verbose('No temp instances found');
return;

View File

@@ -27,7 +27,6 @@ export enum Events {
CALL = 'call',
TYPEBOT_START = 'typebot.start',
TYPEBOT_CHANGE_STATUS = 'typebot.change-status',
CHAMA_AI_ACTION = 'chama-ai.action',
LABELS_EDIT = 'labels.edit',
LABELS_ASSOCIATION = 'labels.association',
CREDS_UPDATE = 'creds.update',
@@ -131,14 +130,6 @@ export declare namespace wa {
proxy?: Proxy;
};
export type LocalChamaai = {
enabled?: boolean;
url?: string;
token?: string;
waNumber?: string;
answerByAudio?: boolean;
};
export type LocalIntegration = {
integration?: string;
number?: string;