From a83a358620253f1cbfb30ae3356afa554bb30f12 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 23 Aug 2024 07:55:26 -0300 Subject: [PATCH] refactor: channel integration folders --- .../channel/channel.controller.ts | 33 ++++++++- .../integrations/channel/channel.router.ts | 15 ++++ .../channel/evolution/evolution.controller.ts | 39 ++++++++++ .../channel/evolution/evolution.router.ts | 18 +++++ .../channel/meta/meta.controller.ts | 72 +++++++++++++++++++ .../integrations/channel/meta/meta.router.ts | 24 +++++++ .../whatsapp.business.service.ts | 0 .../{baileys => }/whatsapp.baileys.service.ts | 0 .../webhook/controllers/webhook.controller.ts | 72 ------------------- .../event/webhook/routes/webhook.router.ts | 19 +---- src/api/routes/index.router.ts | 2 + src/api/server.module.ts | 8 ++- 12 files changed, 209 insertions(+), 93 deletions(-) create mode 100644 src/api/integrations/channel/channel.router.ts create mode 100644 src/api/integrations/channel/evolution/evolution.controller.ts create mode 100644 src/api/integrations/channel/evolution/evolution.router.ts create mode 100644 src/api/integrations/channel/meta/meta.controller.ts create mode 100644 src/api/integrations/channel/meta/meta.router.ts rename src/api/integrations/channel/{whatsapp/business => meta}/whatsapp.business.service.ts (100%) rename src/api/integrations/channel/whatsapp/{baileys => }/whatsapp.baileys.service.ts (100%) diff --git a/src/api/integrations/channel/channel.controller.ts b/src/api/integrations/channel/channel.controller.ts index 0dde7c00..a371cc82 100644 --- a/src/api/integrations/channel/channel.controller.ts +++ b/src/api/integrations/channel/channel.controller.ts @@ -2,14 +2,15 @@ import { InstanceDto } from '@api/dto/instance.dto'; import { ProviderFiles } from '@api/provider/sessions'; import { PrismaRepository } from '@api/repository/repository.service'; import { CacheService } from '@api/services/cache.service'; +import { WAMonitoringService } from '@api/services/monitor.service'; import { Integration } from '@api/types/wa.types'; import { ConfigService } from '@config/env.config'; import { BadRequestException } from '@exceptions'; import EventEmitter2 from 'eventemitter2'; import { EvolutionStartupService } from './evolution/evolution.channel.service'; -import { BaileysStartupService } from './whatsapp/baileys/whatsapp.baileys.service'; -import { BusinessStartupService } from './whatsapp/business/whatsapp.business.service'; +import { BusinessStartupService } from './meta/whatsapp.business.service'; +import { BaileysStartupService } from './whatsapp/whatsapp.baileys.service'; type ChannelDataType = { configService: ConfigService; @@ -21,7 +22,35 @@ type ChannelDataType = { providerFiles: ProviderFiles; }; +export interface ChannelControllerInterface { + receiveWebhook(data: any): Promise; +} + export class ChannelController { + public prismaRepository: PrismaRepository; + public waMonitor: WAMonitoringService; + + constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) { + this.prisma = prismaRepository; + this.monitor = waMonitor; + } + + public set prisma(prisma: PrismaRepository) { + this.prismaRepository = prisma; + } + + public get prisma() { + return this.prismaRepository; + } + + public set monitor(waMonitor: WAMonitoringService) { + this.waMonitor = waMonitor; + } + + public get monitor() { + return this.waMonitor; + } + public init(instanceData: InstanceDto, data: ChannelDataType) { if (!instanceData.token && instanceData.integration === Integration.WHATSAPP_BUSINESS) { throw new BadRequestException('token is required'); diff --git a/src/api/integrations/channel/channel.router.ts b/src/api/integrations/channel/channel.router.ts new file mode 100644 index 00000000..c5bce859 --- /dev/null +++ b/src/api/integrations/channel/channel.router.ts @@ -0,0 +1,15 @@ +import { Router } from 'express'; + +import { EvolutionRouter } from './evolution/evolution.router'; +import { MetaRouter } from './meta/meta.router'; + +export class ChannelRouter { + public readonly router: Router; + + constructor(configService: any) { + this.router = Router(); + + this.router.use('/', new EvolutionRouter(configService).router); + this.router.use('/', new MetaRouter(configService).router); + } +} diff --git a/src/api/integrations/channel/evolution/evolution.controller.ts b/src/api/integrations/channel/evolution/evolution.controller.ts new file mode 100644 index 00000000..1dac51a9 --- /dev/null +++ b/src/api/integrations/channel/evolution/evolution.controller.ts @@ -0,0 +1,39 @@ +import { PrismaRepository } from '@api/repository/repository.service'; +import { WAMonitoringService } from '@api/services/monitor.service'; +import { Logger } from '@config/logger.config'; + +import { ChannelController, ChannelControllerInterface } from '../channel.controller'; + +export class EvolutionController extends ChannelController implements ChannelControllerInterface { + private readonly logger = new Logger(EvolutionController.name); + + constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) { + super(prismaRepository, waMonitor); + } + + integrationEnabled: boolean; + + public async receiveWebhook(data: any) { + const numberId = data.numberId; + + if (!numberId) { + this.logger.error('WebhookService -> receiveWebhookEvolution -> numberId not found'); + return; + } + + const instance = await this.prismaRepository.instance.findFirst({ + where: { number: numberId }, + }); + + if (!instance) { + this.logger.error('WebhookService -> receiveWebhook -> instance not found'); + return; + } + + await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data); + + return { + status: 'success', + }; + } +} diff --git a/src/api/integrations/channel/evolution/evolution.router.ts b/src/api/integrations/channel/evolution/evolution.router.ts new file mode 100644 index 00000000..1ab0ec00 --- /dev/null +++ b/src/api/integrations/channel/evolution/evolution.router.ts @@ -0,0 +1,18 @@ +import { RouterBroker } from '@api/abstract/abstract.router'; +import { evolutionController } from '@api/server.module'; +import { ConfigService } from '@config/env.config'; +import { Router } from 'express'; + +export class EvolutionRouter extends RouterBroker { + constructor(readonly configService: ConfigService) { + super(); + this.router.post(this.routerPath('webhook/evolution', false), async (req, res) => { + const { body } = req; + const response = await evolutionController.receiveWebhook(body); + + return res.status(200).json(response); + }); + } + + public readonly router: Router = Router(); +} diff --git a/src/api/integrations/channel/meta/meta.controller.ts b/src/api/integrations/channel/meta/meta.controller.ts new file mode 100644 index 00000000..0fe0a003 --- /dev/null +++ b/src/api/integrations/channel/meta/meta.controller.ts @@ -0,0 +1,72 @@ +import { PrismaRepository } from '@api/repository/repository.service'; +import { WAMonitoringService } from '@api/services/monitor.service'; +import { Logger } from '@config/logger.config'; +import axios from 'axios'; + +import { ChannelController, ChannelControllerInterface } from '../channel.controller'; + +export class MetaController extends ChannelController implements ChannelControllerInterface { + private readonly logger = new Logger(MetaController.name); + + constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) { + super(prismaRepository, waMonitor); + } + + integrationEnabled: boolean; + + public async receiveWebhook(data: any) { + if (data.object === 'whatsapp_business_account') { + if (data.entry[0]?.changes[0]?.field === 'message_template_status_update') { + const template = await this.prismaRepository.template.findFirst({ + where: { templateId: `${data.entry[0].changes[0].value.message_template_id}` }, + }); + + if (!template) { + console.log('template not found'); + return; + } + + const { webhookUrl } = template; + + await axios.post(webhookUrl, data.entry[0].changes[0].value, { + headers: { + 'Content-Type': 'application/json', + }, + }); + return; + } + + data.entry?.forEach(async (entry: any) => { + const numberId = entry.changes[0].value.metadata.phone_number_id; + + if (!numberId) { + this.logger.error('WebhookService -> receiveWebhookMeta -> numberId not found'); + return { + status: 'success', + }; + } + + const instance = await this.prismaRepository.instance.findFirst({ + where: { number: numberId }, + }); + + if (!instance) { + this.logger.error('WebhookService -> receiveWebhookMeta -> instance not found'); + return { + status: 'success', + }; + } + + await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data); + + return { + status: 'success', + }; + }); + } + + return { + status: 'success', + }; + } +} diff --git a/src/api/integrations/channel/meta/meta.router.ts b/src/api/integrations/channel/meta/meta.router.ts new file mode 100644 index 00000000..b0fc43ce --- /dev/null +++ b/src/api/integrations/channel/meta/meta.router.ts @@ -0,0 +1,24 @@ +import { RouterBroker } from '@api/abstract/abstract.router'; +import { metaController } from '@api/server.module'; +import { ConfigService, WaBusiness } from '@config/env.config'; +import { Router } from 'express'; + +export class MetaRouter extends RouterBroker { + constructor(readonly configService: ConfigService) { + super(); + this.router + .get(this.routerPath('webhook/meta', false), async (req, res) => { + if (req.query['hub.verify_token'] === configService.get('WA_BUSINESS').TOKEN_WEBHOOK) + res.send(req.query['hub.challenge']); + else res.send('Error, wrong validation token'); + }) + .post(this.routerPath('webhook/meta', false), async (req, res) => { + const { body } = req; + const response = await metaController.receiveWebhook(body); + + return res.status(200).json(response); + }); + } + + public readonly router: Router = Router(); +} diff --git a/src/api/integrations/channel/whatsapp/business/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts similarity index 100% rename from src/api/integrations/channel/whatsapp/business/whatsapp.business.service.ts rename to src/api/integrations/channel/meta/whatsapp.business.service.ts diff --git a/src/api/integrations/channel/whatsapp/baileys/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts similarity index 100% rename from src/api/integrations/channel/whatsapp/baileys/whatsapp.baileys.service.ts rename to src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts diff --git a/src/api/integrations/event/webhook/controllers/webhook.controller.ts b/src/api/integrations/event/webhook/controllers/webhook.controller.ts index 15f3577f..8fbc41f7 100644 --- a/src/api/integrations/event/webhook/controllers/webhook.controller.ts +++ b/src/api/integrations/event/webhook/controllers/webhook.controller.ts @@ -186,76 +186,4 @@ export class WebhookController extends EventController implements EventControlle } } } - - public async receiveWebhookMeta(data: any) { - if (data.object === 'whatsapp_business_account') { - if (data.entry[0]?.changes[0]?.field === 'message_template_status_update') { - const template = await this.prismaRepository.template.findFirst({ - where: { templateId: `${data.entry[0].changes[0].value.message_template_id}` }, - }); - - if (!template) { - console.log('template not found'); - return; - } - - const { webhookUrl } = template; - - await axios.post(webhookUrl, data.entry[0].changes[0].value, { - headers: { - 'Content-Type': 'application/json', - }, - }); - return; - } - - data.entry?.forEach(async (entry: any) => { - const numberId = entry.changes[0].value.metadata.phone_number_id; - - if (!numberId) { - this.logger.error('WebhookService -> receiveWebhookMeta -> numberId not found'); - return; - } - - const instance = await this.prismaRepository.instance.findFirst({ - where: { number: numberId }, - }); - - if (!instance) { - this.logger.error('WebhookService -> receiveWebhookMeta -> instance not found'); - return; - } - - await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data); - - return; - }); - } - - return; - } - - public async receiveWebhookEvolution(data: any) { - const numberId = data.numberId; - - if (!numberId) { - this.logger.error('WebhookService -> receiveWebhookEvolution -> numberId not found'); - return; - } - - const instance = await this.prismaRepository.instance.findFirst({ - where: { number: numberId }, - }); - - if (!instance) { - this.logger.error('WebhookService -> receiveWebhook -> instance not found'); - return; - } - - await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data); - - return { - status: 'success', - }; - } } diff --git a/src/api/integrations/event/webhook/routes/webhook.router.ts b/src/api/integrations/event/webhook/routes/webhook.router.ts index 6a3bcdae..ca9a90bb 100644 --- a/src/api/integrations/event/webhook/routes/webhook.router.ts +++ b/src/api/integrations/event/webhook/routes/webhook.router.ts @@ -2,7 +2,7 @@ import { RouterBroker } from '@api/abstract/abstract.router'; import { InstanceDto } from '@api/dto/instance.dto'; import { HttpStatus } from '@api/routes/index.router'; import { webhookController } from '@api/server.module'; -import { ConfigService, WaBusiness } from '@config/env.config'; +import { ConfigService } from '@config/env.config'; import { instanceSchema, webhookSchema } from '@validate/validate.schema'; import { RequestHandler, Router } from 'express'; @@ -31,23 +31,6 @@ export class WebhookRouter extends RouterBroker { }); res.status(HttpStatus.OK).json(response); - }) - .get(this.routerPath('meta', false), async (req, res) => { - if (req.query['hub.verify_token'] === configService.get('WA_BUSINESS').TOKEN_WEBHOOK) - res.send(req.query['hub.challenge']); - else res.send('Error, wrong validation token'); - }) - .post(this.routerPath('meta', false), async (req, res) => { - const { body } = req; - const response = await webhookController.receiveWebhookMeta(body); - - return res.status(200).json(response); - }) - .post(this.routerPath('evolution', false), async (req, res) => { - const { body } = req; - const response = await webhookController.receiveWebhookEvolution(body); - - return res.status(200).json(response); }); } diff --git a/src/api/routes/index.router.ts b/src/api/routes/index.router.ts index 9ce3f033..43401725 100644 --- a/src/api/routes/index.router.ts +++ b/src/api/routes/index.router.ts @@ -1,6 +1,7 @@ import { authGuard } from '@api/guards/auth.guard'; import { instanceExistsGuard, instanceLoggedGuard } from '@api/guards/instance.guard'; import Telemetry from '@api/guards/telemetry.guard'; +import { ChannelRouter } from '@api/integrations/channel/channel.router'; import { ChatbotRouter } from '@api/integrations/chatbot/chatbot.router'; import { EventRouter } from '@api/integrations/event/event.router'; import { StorageRouter } from '@api/integrations/storage/storage.router'; @@ -84,6 +85,7 @@ router .use('/settings', new SettingsRouter(...guards).router) .use('/proxy', new ProxyRouter(...guards).router) .use('/label', new LabelRouter(...guards).router) + .use('', new ChannelRouter(configService).router) .use('', new EventRouter(configService, ...guards).router) .use('', new ChatbotRouter(...guards).router) .use('', new StorageRouter(...guards).router); diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 274780f4..6263f012 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -12,6 +12,8 @@ import { SendMessageController } from './controllers/sendMessage.controller'; import { SettingsController } from './controllers/settings.controller'; import { TemplateController } from './controllers/template.controller'; import { ChannelController } from './integrations/channel/channel.controller'; +import { EvolutionController } from './integrations/channel/evolution/evolution.controller'; +import { MetaController } from './integrations/channel/meta/meta.controller'; import { ChatbotController } from './integrations/chatbot/chatbot.controller'; import { ChatwootController } from './integrations/chatbot/chatwoot/controllers/chatwoot.controller'; import { ChatwootService } from './integrations/chatbot/chatwoot/services/chatwoot.service'; @@ -102,7 +104,11 @@ export const labelController = new LabelController(waMonitor); export const eventController = new EventController(prismaRepository, waMonitor); export const chatbotController = new ChatbotController(prismaRepository, waMonitor); -export const channelController = new ChannelController(); +export const channelController = new ChannelController(prismaRepository, waMonitor); + +// channels +export const evolutionController = new EvolutionController(prismaRepository, waMonitor); +export const metaController = new MetaController(prismaRepository, waMonitor); // events export const websocketController = new WebsocketController(prismaRepository, waMonitor);