oex2003/evolution-api
0
1import { PrismaRepository } from '@api/repository/repository.service';2import { WAMonitoringService } from '@api/services/monitor.service';3import { Auth, configService, Cors, Log, Websocket } from '@config/env.config';4import { Logger } from '@config/logger.config';5import { Server } from 'http';6import { Server as SocketIO } from 'socket.io';7 8import { EmitData, EventController, EventControllerInterface } from '../event.controller';9 10export class WebsocketController extends EventController implements EventControllerInterface {11 private io: SocketIO;12 private corsConfig: Array<any>;13 private readonly logger = new Logger('WebsocketController');14 15 constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {16 super(prismaRepository, waMonitor, configService.get<Websocket>('WEBSOCKET')?.ENABLED, 'websocket');17 18 this.cors = configService.get<Cors>('CORS').ORIGIN;19 }20 21 public init(httpServer: Server): void {22 if (!this.status) {23 return;24 }25 26 this.socket = new SocketIO(httpServer, {27 cors: { origin: this.cors },28 allowRequest: async (req, callback) => {29 try {30 const url = new URL(req.url || '', 'http://localhost');31 const params = new URLSearchParams(url.search);32 33 // Permite conexões internas do Socket.IO (EIO=4 é o Engine.IO v4)34 if (params.has('EIO')) {35 return callback(null, true);36 }37 38 const apiKey = params.get('apikey') || (req.headers.apikey as string);39 40 if (!apiKey) {41 this.logger.error('Connection rejected: apiKey not provided');42 return callback('apiKey is required', false);43 }44 45 const instance = await this.prismaRepository.instance.findFirst({ where: { token: apiKey } });46 47 if (!instance) {48 const globalToken = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;49 if (apiKey !== globalToken) {50 this.logger.error('Connection rejected: invalid global token');51 return callback('Invalid global token', false);52 }53 }54 55 callback(null, true);56 } catch (error) {57 this.logger.error('Authentication error:');58 this.logger.error(error);59 callback('Authentication error', false);60 }61 },62 });63 64 this.socket.on('connection', (socket) => {65 this.logger.info('User connected');66 67 socket.on('disconnect', () => {68 this.logger.info('User disconnected');69 });70 71 socket.on('sendNode', async (data) => {72 try {73 await this.waMonitor.waInstances[data.instanceId].baileysSendNode(data.stanza);74 this.logger.info('Node sent successfully');75 } catch (error) {76 this.logger.error('Error sending node:');77 this.logger.error(error);78 }79 });80 });81 82 this.logger.info('Socket.io initialized');83 }84 85 private set cors(cors: Array<any>) {86 this.corsConfig = cors;87 }88 89 private get cors(): string | Array<any> {90 return this.corsConfig?.includes('*') ? '*' : this.corsConfig;91 }92 93 private set socket(socket: SocketIO) {94 this.io = socket;95 }96 97 public get socket(): SocketIO {98 return this.io;99 }100 101 public async emit({102 instanceName,103 origin,104 event,105 data,106 serverUrl,107 dateTime,108 sender,109 apiKey,110 integration,111 }: EmitData): Promise<void> {112 if (integration && !integration.includes('websocket')) {113 return;114 }115 116 if (!this.status) {117 return;118 }119 120 const configEv = event.replace(/[.-]/gm, '_').toUpperCase();121 const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBSOCKET');122 const message = {123 event,124 instance: instanceName,125 data,126 server_url: serverUrl,127 date_time: dateTime,128 sender,129 apikey: apiKey,130 };131 132 if (configService.get<Websocket>('WEBSOCKET')?.GLOBAL_EVENTS) {133 this.socket.emit(event, message);134 135 if (logEnabled) {136 this.logger.log({ local: `${origin}.sendData-WebsocketGlobal`, ...message });137 }138 }139 140 try {141 const instance = await this.get(instanceName);142 143 if (!instance?.enabled) {144 return;145 }146 147 if (Array.isArray(instance?.events) && instance?.events.includes(configEv)) {148 this.socket.of(`/${instanceName}`).emit(event, message);149 150 if (logEnabled) {151 this.logger.log({ local: `${origin}.sendData-Websocket`, ...message });152 }153 }154 } catch (err) {155 if (logEnabled) {156 this.logger.log(err);157 }158 }159 }160}161 