import { EventDto } from '@api/integrations/event/event.dto'; import { PrismaRepository } from '@api/repository/repository.service'; import { WAMonitoringService } from '@api/services/monitor.service'; import { wa } from '@api/types/wa.types'; import { configService, Log, Webhook } from '@config/env.config'; import { Logger } from '@config/logger.config'; import { BadRequestException } from '@exceptions'; import axios from 'axios'; import { isURL } from 'class-validator'; import { EmitData, EventController, EventControllerInterface } from '../event.controller'; export class WebhookController extends EventController implements EventControllerInterface { private readonly logger = new Logger('WebhookController'); constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) { super(prismaRepository, waMonitor, true, 'webhook'); } override async set(instanceName: string, data: EventDto): Promise { if (!isURL(data.webhook.url, { require_tld: false })) { throw new BadRequestException('Invalid "url" property'); } if (!data.webhook?.enabled) { data.webhook.events = []; } else { if (0 === data.webhook.events.length) { data.webhook.events = EventController.events; } } return this.prisma.webhook.upsert({ where: { instanceId: this.monitor.waInstances[instanceName].instanceId, }, update: { enabled: data.webhook?.enabled, events: data.webhook?.events, url: data.webhook?.url, webhookBase64: data.webhook.base64, webhookByEvents: data.webhook.byEvents, }, create: { enabled: data.webhook?.enabled, events: data.webhook?.events, instanceId: this.monitor.waInstances[instanceName].instanceId, url: data.webhook?.url, webhookBase64: data.webhook.base64, webhookByEvents: data.webhook.byEvents, }, }); } public async emit({ instanceName, origin, event, data, serverUrl, dateTime, sender, apiKey, local, }: EmitData): Promise { const instance = (await this.get(instanceName)) as wa.LocalWebHook; if (!instance || !instance?.enabled) { return; } const webhookConfig = configService.get('WEBHOOK'); const webhookLocal = instance?.events; const we = event.replace(/[.-]/gm, '_').toUpperCase(); const transformedWe = we.replace(/_/gm, '-').toLowerCase(); const enabledLog = configService.get('LOG').LEVEL.includes('WEBHOOKS'); const webhookData = { event, instance: instanceName, data, destination: instance?.url, date_time: dateTime, sender, server_url: serverUrl, apikey: apiKey, }; if (local) { if (Array.isArray(webhookLocal) && webhookLocal.includes(we)) { let baseURL: string; if (instance?.webhookByEvents) { baseURL = `${instance?.url}/${transformedWe}`; } else { baseURL = instance?.url; } if (enabledLog) { const logData = { local: `${origin}.sendData-Webhook`, url: baseURL, ...webhookData, }; this.logger.log(logData); } try { if (instance?.enabled && isURL(instance.url, { require_tld: false })) { const httpService = axios.create({ baseURL }); await httpService.post('', webhookData); } } catch (error) { this.logger.error({ local: `${origin}.sendData-Webhook`, message: error?.message, hostName: error?.hostname, syscall: error?.syscall, code: error?.code, error: error?.errno, stack: error?.stack, name: error?.name, url: baseURL, server_url: serverUrl, }); } } } if (webhookConfig.GLOBAL?.ENABLED) { if (webhookConfig.EVENTS[we]) { let globalURL = webhookConfig.GLOBAL.URL; if (webhookConfig.GLOBAL.WEBHOOK_BY_EVENTS) { globalURL = `${globalURL}/${transformedWe}`; } if (enabledLog) { const logData = { local: `${origin}.sendData-Webhook-Global`, url: globalURL, ...webhookData, }; this.logger.log(logData); } try { if (isURL(globalURL)) { const httpService = axios.create({ baseURL: globalURL }); await httpService.post('', webhookData); } } catch (error) { this.logger.error({ local: `${origin}.sendData-Webhook-Global`, message: error?.message, hostName: error?.hostname, syscall: error?.syscall, code: error?.code, error: error?.errno, stack: error?.stack, name: error?.name, url: globalURL, server_url: serverUrl, }); } } } } }