mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 12:12:55 -06:00
Refactor websocket structure
This commit is contained in:
parent
000d8fd436
commit
dc04eb16fc
@ -12,7 +12,7 @@ CORS_METHODS=GET,POST,PUT,DELETE
|
|||||||
CORS_CREDENTIALS=true
|
CORS_CREDENTIALS=true
|
||||||
|
|
||||||
# Determine the logs to be displayed
|
# Determine the logs to be displayed
|
||||||
LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS
|
LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS,WEBSOCKET
|
||||||
LOG_COLOR=true
|
LOG_COLOR=true
|
||||||
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
|
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
|
||||||
LOG_BAILEYS=error
|
LOG_BAILEYS=error
|
||||||
|
@ -2,7 +2,7 @@ import { InstanceDto, SetPresenceDto } from '@api/dto/instance.dto';
|
|||||||
import { ChatwootService } from '@api/integrations/chatwoot/services/chatwoot.service';
|
import { ChatwootService } from '@api/integrations/chatwoot/services/chatwoot.service';
|
||||||
import { RabbitmqService } from '@api/integrations/rabbitmq/services/rabbitmq.service';
|
import { RabbitmqService } from '@api/integrations/rabbitmq/services/rabbitmq.service';
|
||||||
import { SqsService } from '@api/integrations/sqs/services/sqs.service';
|
import { SqsService } from '@api/integrations/sqs/services/sqs.service';
|
||||||
import { WebsocketService } from '@api/integrations/websocket/services/websocket.service';
|
import { WebsocketController } from '@api/integrations/websocket/controllers/websocket.controller';
|
||||||
import { ProviderFiles } from '@api/provider/sessions';
|
import { ProviderFiles } from '@api/provider/sessions';
|
||||||
import { PrismaRepository } from '@api/repository/repository.service';
|
import { PrismaRepository } from '@api/repository/repository.service';
|
||||||
import { AuthService } from '@api/services/auth.service';
|
import { AuthService } from '@api/services/auth.service';
|
||||||
@ -34,7 +34,7 @@ export class InstanceController {
|
|||||||
private readonly webhookService: WebhookService,
|
private readonly webhookService: WebhookService,
|
||||||
private readonly chatwootService: ChatwootService,
|
private readonly chatwootService: ChatwootService,
|
||||||
private readonly settingsService: SettingsService,
|
private readonly settingsService: SettingsService,
|
||||||
private readonly websocketService: WebsocketService,
|
private readonly websocketController: WebsocketController,
|
||||||
private readonly rabbitmqService: RabbitmqService,
|
private readonly rabbitmqService: RabbitmqService,
|
||||||
private readonly sqsService: SqsService,
|
private readonly sqsService: SqsService,
|
||||||
private readonly proxyService: ProxyController,
|
private readonly proxyService: ProxyController,
|
||||||
@ -205,44 +205,12 @@ export class InstanceController {
|
|||||||
|
|
||||||
if (websocketEnabled) {
|
if (websocketEnabled) {
|
||||||
try {
|
try {
|
||||||
let newEvents: string[] = [];
|
await this.websocketController.set(instance.instanceName, {
|
||||||
if (websocketEvents.length === 0) {
|
|
||||||
newEvents = [
|
|
||||||
'APPLICATION_STARTUP',
|
|
||||||
'QRCODE_UPDATED',
|
|
||||||
'MESSAGES_SET',
|
|
||||||
'MESSAGES_UPSERT',
|
|
||||||
'MESSAGES_EDITED',
|
|
||||||
'MESSAGES_UPDATE',
|
|
||||||
'MESSAGES_DELETE',
|
|
||||||
'SEND_MESSAGE',
|
|
||||||
'CONTACTS_SET',
|
|
||||||
'CONTACTS_UPSERT',
|
|
||||||
'CONTACTS_UPDATE',
|
|
||||||
'PRESENCE_UPDATE',
|
|
||||||
'CHATS_SET',
|
|
||||||
'CHATS_UPSERT',
|
|
||||||
'CHATS_UPDATE',
|
|
||||||
'CHATS_DELETE',
|
|
||||||
'GROUPS_UPSERT',
|
|
||||||
'GROUP_UPDATE',
|
|
||||||
'GROUP_PARTICIPANTS_UPDATE',
|
|
||||||
'CONNECTION_UPDATE',
|
|
||||||
'LABELS_EDIT',
|
|
||||||
'LABELS_ASSOCIATION',
|
|
||||||
'CALL',
|
|
||||||
'TYPEBOT_START',
|
|
||||||
'TYPEBOT_CHANGE_STATUS',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
newEvents = websocketEvents;
|
|
||||||
}
|
|
||||||
this.websocketService.create(instance, {
|
|
||||||
enabled: true,
|
enabled: true,
|
||||||
events: newEvents,
|
events: websocketEvents,
|
||||||
});
|
});
|
||||||
|
|
||||||
const websocketEventsJson: JsonValue = (await this.websocketService.find(instance)).events;
|
const websocketEventsJson: JsonValue = (await this.websocketController.get(instance.instanceName)).events;
|
||||||
|
|
||||||
getWebsocketEvents = Array.isArray(websocketEventsJson)
|
getWebsocketEvents = Array.isArray(websocketEventsJson)
|
||||||
? websocketEventsJson.map((event) => String(event))
|
? websocketEventsJson.map((event) => String(event))
|
||||||
|
@ -1,49 +1,217 @@
|
|||||||
import { InstanceDto } from '@api/dto/instance.dto';
|
|
||||||
import { WebsocketDto } from '@api/integrations/websocket/dto/websocket.dto';
|
import { WebsocketDto } from '@api/integrations/websocket/dto/websocket.dto';
|
||||||
import { WebsocketService } from '@api/integrations/websocket/services/websocket.service';
|
import { PrismaRepository } from '@api/repository/repository.service';
|
||||||
|
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||||
|
import { wa } from '@api/types/wa.types';
|
||||||
|
import { Auth, configService, Cors, HttpServer, Log, Websocket } from '@config/env.config';
|
||||||
|
import { Logger } from '@config/logger.config';
|
||||||
|
import { NotFoundException } from '@exceptions';
|
||||||
|
import { Server } from 'http';
|
||||||
|
import { Server as SocketIO } from 'socket.io';
|
||||||
|
|
||||||
export class WebsocketController {
|
export class WebsocketController {
|
||||||
constructor(private readonly websocketService: WebsocketService) {}
|
private io: SocketIO;
|
||||||
|
private prismaRepository: PrismaRepository;
|
||||||
|
private waMonitor: WAMonitoringService;
|
||||||
|
private corsConfig: Array<any>;
|
||||||
|
private readonly logger = new Logger('SocketStartupService');
|
||||||
|
public readonly monitorEvents = ['REMOVE_INSTANCE', 'LOGOUT_INSTANCE', 'NO_CONNECTION'];
|
||||||
|
public readonly events = [
|
||||||
|
'APPLICATION_STARTUP',
|
||||||
|
'QRCODE_UPDATED',
|
||||||
|
'MESSAGES_SET',
|
||||||
|
'MESSAGES_UPSERT',
|
||||||
|
'MESSAGES_EDITED',
|
||||||
|
'MESSAGES_UPDATE',
|
||||||
|
'MESSAGES_DELETE',
|
||||||
|
'SEND_MESSAGE',
|
||||||
|
'CONTACTS_SET',
|
||||||
|
'CONTACTS_UPSERT',
|
||||||
|
'CONTACTS_UPDATE',
|
||||||
|
'PRESENCE_UPDATE',
|
||||||
|
'CHATS_SET',
|
||||||
|
'CHATS_UPSERT',
|
||||||
|
'CHATS_UPDATE',
|
||||||
|
'CHATS_DELETE',
|
||||||
|
'GROUPS_UPSERT',
|
||||||
|
'GROUP_UPDATE',
|
||||||
|
'GROUP_PARTICIPANTS_UPDATE',
|
||||||
|
'CONNECTION_UPDATE',
|
||||||
|
'LABELS_EDIT',
|
||||||
|
'LABELS_ASSOCIATION',
|
||||||
|
'CALL',
|
||||||
|
'TYPEBOT_START',
|
||||||
|
'TYPEBOT_CHANGE_STATUS',
|
||||||
|
];
|
||||||
|
|
||||||
public async createWebsocket(instance: InstanceDto, data: WebsocketDto) {
|
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
|
||||||
|
this.prisma = prismaRepository;
|
||||||
|
this.monitor = waMonitor;
|
||||||
|
this.cors = configService.get<Cors>('CORS').ORIGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(httpServer: Server): void {
|
||||||
|
if (!configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.socket = new SocketIO(httpServer, {
|
||||||
|
cors: {
|
||||||
|
origin: this.cors,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('connection', (socket) => {
|
||||||
|
this.logger.info('User connected');
|
||||||
|
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
this.logger.info('User disconnected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.info('Socket.io initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
private set prisma(prisma: PrismaRepository) {
|
||||||
|
this.prismaRepository = prisma;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get prisma() {
|
||||||
|
return this.prismaRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
private set monitor(waMonitor: WAMonitoringService) {
|
||||||
|
this.waMonitor = waMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get monitor() {
|
||||||
|
return this.waMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private set cors(cors: Array<any>) {
|
||||||
|
this.corsConfig = cors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get cors(): string | Array<any> {
|
||||||
|
return this.corsConfig?.includes('*') ? '*' : this.corsConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private set socket(socket: SocketIO) {
|
||||||
|
this.io = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get socket(): SocketIO {
|
||||||
|
return this.io;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async set(instanceName: string, data: WebsocketDto): Promise<wa.LocalWebsocket> {
|
||||||
if (!data.enabled) {
|
if (!data.enabled) {
|
||||||
data.events = [];
|
data.events = [];
|
||||||
|
} else {
|
||||||
|
if (0 === data.events.length) {
|
||||||
|
data.events = this.events;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.events.length === 0) {
|
try {
|
||||||
data.events = [
|
await this.get(instanceName);
|
||||||
'APPLICATION_STARTUP',
|
|
||||||
'QRCODE_UPDATED',
|
|
||||||
'MESSAGES_SET',
|
|
||||||
'MESSAGES_UPSERT',
|
|
||||||
'MESSAGES_EDITED',
|
|
||||||
'MESSAGES_UPDATE',
|
|
||||||
'MESSAGES_DELETE',
|
|
||||||
'SEND_MESSAGE',
|
|
||||||
'CONTACTS_SET',
|
|
||||||
'CONTACTS_UPSERT',
|
|
||||||
'CONTACTS_UPDATE',
|
|
||||||
'PRESENCE_UPDATE',
|
|
||||||
'CHATS_SET',
|
|
||||||
'CHATS_UPSERT',
|
|
||||||
'CHATS_UPDATE',
|
|
||||||
'CHATS_DELETE',
|
|
||||||
'GROUPS_UPSERT',
|
|
||||||
'GROUP_UPDATE',
|
|
||||||
'GROUP_PARTICIPANTS_UPDATE',
|
|
||||||
'CONNECTION_UPDATE',
|
|
||||||
'LABELS_EDIT',
|
|
||||||
'LABELS_ASSOCIATION',
|
|
||||||
'CALL',
|
|
||||||
'TYPEBOT_START',
|
|
||||||
'TYPEBOT_CHANGE_STATUS',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.websocketService.create(instance, data);
|
return this.prisma.websocket.update({
|
||||||
|
where: {
|
||||||
|
instanceId: this.monitor.waInstances[instanceName].instanceId,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
return this.prisma.websocket.create({
|
||||||
|
data: {
|
||||||
|
enabled: data.enabled,
|
||||||
|
events: data.events,
|
||||||
|
instanceId: this.monitor.waInstances[instanceName].instanceId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findWebsocket(instance: InstanceDto) {
|
public async get(instanceName: string): Promise<wa.LocalWebsocket> {
|
||||||
return this.websocketService.find(instance);
|
if (undefined === this.monitor.waInstances[instanceName]) {
|
||||||
|
throw new NotFoundException('Instance not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await this.prisma.websocket.findUnique({
|
||||||
|
where: {
|
||||||
|
instanceId: this.monitor.waInstances[instanceName].instanceId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
throw new NotFoundException('Websocket not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async emit({
|
||||||
|
instanceName,
|
||||||
|
origin,
|
||||||
|
event,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
instanceName: string;
|
||||||
|
origin: string;
|
||||||
|
event: string;
|
||||||
|
data: Object;
|
||||||
|
}): Promise<void> {
|
||||||
|
if (!configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configEv = event.replace(/[.-]/gm, '_').toUpperCase();
|
||||||
|
const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBSOCKET');
|
||||||
|
const serverUrl = configService.get<HttpServer>('SERVER').URL;
|
||||||
|
const date = new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString();
|
||||||
|
const message = {
|
||||||
|
event,
|
||||||
|
instanceName,
|
||||||
|
data,
|
||||||
|
serverUrl,
|
||||||
|
date,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (configService.get<Websocket>('WEBSOCKET')?.GLOBAL_EVENTS) {
|
||||||
|
this.socket.emit(event, message);
|
||||||
|
|
||||||
|
if (logEnabled) {
|
||||||
|
this.logger.log({
|
||||||
|
local: `${origin}.sendData-WebsocketGlobal`,
|
||||||
|
...message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const instanceSocket = await this.get(instanceName);
|
||||||
|
|
||||||
|
if (!instanceSocket.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.monitorEvents.includes(configEv) ||
|
||||||
|
(Array.isArray(instanceSocket.events) && instanceSocket.events.includes(configEv))
|
||||||
|
) {
|
||||||
|
this.socket.of(`/${instanceName}`).emit(event, message);
|
||||||
|
|
||||||
|
if (logEnabled) {
|
||||||
|
this.logger.log({
|
||||||
|
local: `${origin}.sendData-Websocket`,
|
||||||
|
...message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (logEnabled) {
|
||||||
|
this.logger.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { configService, Cors, Websocket } from '@config/env.config';
|
|
||||||
import { Logger } from '@config/logger.config';
|
|
||||||
import { Server } from 'http';
|
|
||||||
import { Server as SocketIO } from 'socket.io';
|
|
||||||
|
|
||||||
const logger = new Logger('Socket');
|
|
||||||
|
|
||||||
let io: SocketIO;
|
|
||||||
|
|
||||||
const cors = configService.get<Cors>('CORS').ORIGIN;
|
|
||||||
|
|
||||||
export const initIO = (httpServer: Server) => {
|
|
||||||
if (configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
|
|
||||||
io = new SocketIO(httpServer, {
|
|
||||||
cors: {
|
|
||||||
origin: cors.includes('*') ? '*' : cors,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
|
||||||
logger.info('User connected');
|
|
||||||
|
|
||||||
socket.on('disconnect', () => {
|
|
||||||
logger.info('User disconnected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
logger.info('Socket.io initialized');
|
|
||||||
return io;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getIO = (): SocketIO => {
|
|
||||||
if (!io) {
|
|
||||||
logger.error('Socket.io not initialized');
|
|
||||||
throw new Error('Socket.io not initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
return io;
|
|
||||||
};
|
|
@ -15,7 +15,7 @@ export class WebsocketRouter extends RouterBroker {
|
|||||||
request: req,
|
request: req,
|
||||||
schema: websocketSchema,
|
schema: websocketSchema,
|
||||||
ClassRef: WebsocketDto,
|
ClassRef: WebsocketDto,
|
||||||
execute: (instance, data) => websocketController.createWebsocket(instance, data),
|
execute: (instance, data) => websocketController.set(instance.instanceName, data),
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(HttpStatus.CREATED).json(response);
|
res.status(HttpStatus.CREATED).json(response);
|
||||||
@ -25,7 +25,7 @@ export class WebsocketRouter extends RouterBroker {
|
|||||||
request: req,
|
request: req,
|
||||||
schema: instanceSchema,
|
schema: instanceSchema,
|
||||||
ClassRef: InstanceDto,
|
ClassRef: InstanceDto,
|
||||||
execute: (instance) => websocketController.findWebsocket(instance),
|
execute: (instance) => websocketController.get(instance.instanceName),
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(HttpStatus.OK).json(response);
|
res.status(HttpStatus.OK).json(response);
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import { InstanceDto } from '@api/dto/instance.dto';
|
|
||||||
import { WebsocketDto } from '@api/integrations/websocket/dto/websocket.dto';
|
|
||||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
|
||||||
import { Logger } from '@config/logger.config';
|
|
||||||
import { Websocket } from '@prisma/client';
|
|
||||||
|
|
||||||
export class WebsocketService {
|
|
||||||
constructor(private readonly waMonitor: WAMonitoringService) {}
|
|
||||||
|
|
||||||
private readonly logger = new Logger('WebsocketService');
|
|
||||||
|
|
||||||
public create(instance: InstanceDto, data: WebsocketDto) {
|
|
||||||
this.waMonitor.waInstances[instance.instanceName].setWebsocket(data);
|
|
||||||
|
|
||||||
return { websocket: { ...instance, websocket: data } };
|
|
||||||
}
|
|
||||||
|
|
||||||
public async find(instance: InstanceDto): Promise<Websocket> {
|
|
||||||
try {
|
|
||||||
const result = await this.waMonitor.waInstances[instance.instanceName].findWebsocket();
|
|
||||||
|
|
||||||
if (Object.keys(result).length === 0) {
|
|
||||||
throw new Error('Websocket not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,6 @@ import { SqsService } from './integrations/sqs/services/sqs.service';
|
|||||||
import { TypebotController } from './integrations/typebot/controllers/typebot.controller';
|
import { TypebotController } from './integrations/typebot/controllers/typebot.controller';
|
||||||
import { TypebotService } from './integrations/typebot/services/typebot.service';
|
import { TypebotService } from './integrations/typebot/services/typebot.service';
|
||||||
import { WebsocketController } from './integrations/websocket/controllers/websocket.controller';
|
import { WebsocketController } from './integrations/websocket/controllers/websocket.controller';
|
||||||
import { WebsocketService } from './integrations/websocket/services/websocket.service';
|
|
||||||
import { ProviderFiles } from './provider/sessions';
|
import { ProviderFiles } from './provider/sessions';
|
||||||
import { PrismaRepository } from './repository/repository.service';
|
import { PrismaRepository } from './repository/repository.service';
|
||||||
import { AuthService } from './services/auth.service';
|
import { AuthService } from './services/auth.service';
|
||||||
@ -85,8 +84,7 @@ export const webhookController = new WebhookController(webhookService, waMonitor
|
|||||||
const templateService = new TemplateService(waMonitor, prismaRepository, configService);
|
const templateService = new TemplateService(waMonitor, prismaRepository, configService);
|
||||||
export const templateController = new TemplateController(templateService);
|
export const templateController = new TemplateController(templateService);
|
||||||
|
|
||||||
const websocketService = new WebsocketService(waMonitor);
|
export const websocketController = new WebsocketController(prismaRepository, waMonitor);
|
||||||
export const websocketController = new WebsocketController(websocketService);
|
|
||||||
|
|
||||||
const proxyService = new ProxyService(waMonitor);
|
const proxyService = new ProxyService(waMonitor);
|
||||||
export const proxyController = new ProxyController(proxyService, waMonitor);
|
export const proxyController = new ProxyController(proxyService, waMonitor);
|
||||||
@ -112,7 +110,7 @@ export const instanceController = new InstanceController(
|
|||||||
webhookService,
|
webhookService,
|
||||||
chatwootService,
|
chatwootService,
|
||||||
settingsService,
|
settingsService,
|
||||||
websocketService,
|
websocketController,
|
||||||
rabbitmqService,
|
rabbitmqService,
|
||||||
sqsService,
|
sqsService,
|
||||||
proxyController,
|
proxyController,
|
||||||
|
@ -11,12 +11,10 @@ import { getAMQP, removeQueues } from '@api/integrations/rabbitmq/libs/amqp.serv
|
|||||||
import { SqsDto } from '@api/integrations/sqs/dto/sqs.dto';
|
import { SqsDto } from '@api/integrations/sqs/dto/sqs.dto';
|
||||||
import { getSQS, removeQueues as removeQueuesSQS } from '@api/integrations/sqs/libs/sqs.server';
|
import { getSQS, removeQueues as removeQueuesSQS } from '@api/integrations/sqs/libs/sqs.server';
|
||||||
import { TypebotService } from '@api/integrations/typebot/services/typebot.service';
|
import { TypebotService } from '@api/integrations/typebot/services/typebot.service';
|
||||||
import { WebsocketDto } from '@api/integrations/websocket/dto/websocket.dto';
|
|
||||||
import { getIO } from '@api/integrations/websocket/libs/socket.server';
|
|
||||||
import { PrismaRepository, Query } from '@api/repository/repository.service';
|
import { PrismaRepository, Query } from '@api/repository/repository.service';
|
||||||
import { waMonitor } from '@api/server.module';
|
import { waMonitor, websocketController } from '@api/server.module';
|
||||||
import { Events, wa } from '@api/types/wa.types';
|
import { Events, wa } from '@api/types/wa.types';
|
||||||
import { Auth, Chatwoot, ConfigService, HttpServer, Log, Rabbitmq, Sqs, Webhook, Websocket } from '@config/env.config';
|
import { Auth, Chatwoot, ConfigService, HttpServer, Log, Rabbitmq, Sqs, Webhook } from '@config/env.config';
|
||||||
import { Logger } from '@config/logger.config';
|
import { Logger } from '@config/logger.config';
|
||||||
import { ROOT_DIR } from '@config/path.config';
|
import { ROOT_DIR } from '@config/path.config';
|
||||||
import { NotFoundException } from '@exceptions';
|
import { NotFoundException } from '@exceptions';
|
||||||
@ -44,7 +42,6 @@ export class ChannelStartupService {
|
|||||||
public readonly instance: wa.Instance = {};
|
public readonly instance: wa.Instance = {};
|
||||||
public readonly localWebhook: wa.LocalWebHook = {};
|
public readonly localWebhook: wa.LocalWebHook = {};
|
||||||
public readonly localChatwoot: wa.LocalChatwoot = {};
|
public readonly localChatwoot: wa.LocalChatwoot = {};
|
||||||
public readonly localWebsocket: wa.LocalWebsocket = {};
|
|
||||||
public readonly localRabbitmq: wa.LocalRabbitmq = {};
|
public readonly localRabbitmq: wa.LocalRabbitmq = {};
|
||||||
public readonly localSqs: wa.LocalSqs = {};
|
public readonly localSqs: wa.LocalSqs = {};
|
||||||
public readonly localProxy: wa.LocalProxy = {};
|
public readonly localProxy: wa.LocalProxy = {};
|
||||||
@ -425,43 +422,6 @@ export class ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadWebsocket() {
|
|
||||||
const data = await this.prismaRepository.websocket.findUnique({
|
|
||||||
where: {
|
|
||||||
instanceId: this.instanceId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.localWebsocket.enabled = data?.enabled;
|
|
||||||
this.localWebsocket.events = data?.events;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async setWebsocket(data: WebsocketDto) {
|
|
||||||
await this.prismaRepository.websocket.create({
|
|
||||||
data: {
|
|
||||||
enabled: data.enabled,
|
|
||||||
events: data.events,
|
|
||||||
instanceId: this.instanceId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.assign(this.localWebsocket, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async findWebsocket() {
|
|
||||||
const data = await this.prismaRepository.websocket.findUnique({
|
|
||||||
where: {
|
|
||||||
instanceId: this.instanceId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
throw new NotFoundException('Websocket not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async loadRabbitmq() {
|
public async loadRabbitmq() {
|
||||||
const data = await this.prismaRepository.rabbitmq.findUnique({
|
const data = await this.prismaRepository.rabbitmq.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@ -640,7 +600,6 @@ export class ChannelStartupService {
|
|||||||
public async sendDataWebhook<T = any>(event: Events, data: T, local = true) {
|
public async sendDataWebhook<T = any>(event: Events, data: T, local = true) {
|
||||||
const webhookGlobal = this.configService.get<Webhook>('WEBHOOK');
|
const webhookGlobal = this.configService.get<Webhook>('WEBHOOK');
|
||||||
const webhookLocal = this.localWebhook.events;
|
const webhookLocal = this.localWebhook.events;
|
||||||
const websocketLocal = this.localWebsocket.events;
|
|
||||||
const rabbitmqLocal = this.localRabbitmq.events;
|
const rabbitmqLocal = this.localRabbitmq.events;
|
||||||
const sqsLocal = this.localSqs.events;
|
const sqsLocal = this.localSqs.events;
|
||||||
const serverUrl = this.configService.get<HttpServer>('SERVER').URL;
|
const serverUrl = this.configService.get<HttpServer>('SERVER').URL;
|
||||||
@ -862,72 +821,16 @@ export class ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
|
await websocketController.emit({
|
||||||
const io = getIO();
|
instanceName: this.instance.name,
|
||||||
|
origin: ChannelStartupService.name,
|
||||||
const message = {
|
event,
|
||||||
event,
|
data: {
|
||||||
instance: this.instance.name,
|
...data,
|
||||||
data,
|
|
||||||
server_url: serverUrl,
|
|
||||||
date_time: now,
|
|
||||||
sender: this.wuid,
|
sender: this.wuid,
|
||||||
};
|
apikey: (expose && instanceApikey) || null,
|
||||||
|
},
|
||||||
if (expose && instanceApikey) {
|
});
|
||||||
message['apikey'] = instanceApikey;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.configService.get<Websocket>('WEBSOCKET')?.GLOBAL_EVENTS) {
|
|
||||||
io.emit(event, message);
|
|
||||||
|
|
||||||
if (this.configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS')) {
|
|
||||||
const logData = {
|
|
||||||
local: ChannelStartupService.name + '.sendData-WebsocketGlobal',
|
|
||||||
event,
|
|
||||||
instance: this.instance.name,
|
|
||||||
data,
|
|
||||||
server_url: serverUrl,
|
|
||||||
apikey: (expose && instanceApikey) || null,
|
|
||||||
date_time: now,
|
|
||||||
sender: this.wuid,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (expose && instanceApikey) {
|
|
||||||
logData['apikey'] = instanceApikey;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.log(logData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.localWebsocket.enabled && Array.isArray(websocketLocal) && websocketLocal.includes(we)) {
|
|
||||||
io.of(`/${this.instance.name}`).emit(event, message);
|
|
||||||
|
|
||||||
if (this.configService.get<Websocket>('WEBSOCKET')?.GLOBAL_EVENTS) {
|
|
||||||
io.emit(event, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS')) {
|
|
||||||
const logData = {
|
|
||||||
local: ChannelStartupService.name + '.sendData-Websocket',
|
|
||||||
event,
|
|
||||||
instance: this.instance.name,
|
|
||||||
data,
|
|
||||||
server_url: serverUrl,
|
|
||||||
apikey: (expose && instanceApikey) || null,
|
|
||||||
date_time: now,
|
|
||||||
sender: this.wuid,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (expose && instanceApikey) {
|
|
||||||
logData['apikey'] = instanceApikey;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.log(logData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const globalApiKey = this.configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
|
const globalApiKey = this.configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
|
||||||
|
|
||||||
|
@ -687,7 +687,6 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
this.loadWebhook();
|
this.loadWebhook();
|
||||||
this.loadChatwoot();
|
this.loadChatwoot();
|
||||||
this.loadSettings();
|
this.loadSettings();
|
||||||
this.loadWebsocket();
|
|
||||||
this.loadRabbitmq();
|
this.loadRabbitmq();
|
||||||
this.loadSqs();
|
this.loadSqs();
|
||||||
this.loadProxy();
|
this.loadProxy();
|
||||||
|
@ -131,7 +131,6 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
try {
|
try {
|
||||||
this.loadWebhook();
|
this.loadWebhook();
|
||||||
this.loadChatwoot();
|
this.loadChatwoot();
|
||||||
this.loadWebsocket();
|
|
||||||
this.loadRabbitmq();
|
this.loadRabbitmq();
|
||||||
this.loadSqs();
|
this.loadSqs();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { InstanceDto } from '@api/dto/instance.dto';
|
import { InstanceDto } from '@api/dto/instance.dto';
|
||||||
import { ProviderFiles } from '@api/provider/sessions';
|
import { ProviderFiles } from '@api/provider/sessions';
|
||||||
import { PrismaRepository } from '@api/repository/repository.service';
|
import { PrismaRepository } from '@api/repository/repository.service';
|
||||||
|
import { websocketController } from '@api/server.module';
|
||||||
import { Integration } from '@api/types/wa.types';
|
import { Integration } from '@api/types/wa.types';
|
||||||
import { CacheConf, Chatwoot, ConfigService, Database, DelInstance, ProviderSession } from '@config/env.config';
|
import { CacheConf, Chatwoot, ConfigService, Database, DelInstance, ProviderSession } from '@config/env.config';
|
||||||
import { Logger } from '@config/logger.config';
|
import { Logger } from '@config/logger.config';
|
||||||
@ -52,10 +53,9 @@ export class WAMonitoringService {
|
|||||||
this.waInstances[instance]?.client?.end(undefined);
|
this.waInstances[instance]?.client?.end(undefined);
|
||||||
}
|
}
|
||||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||||
delete this.waInstances[instance];
|
this.eventEmitter.emit('remove.instance', instance, 'inner');
|
||||||
} else {
|
} else {
|
||||||
this.waInstances[instance]?.removeRabbitmqQueues();
|
this.waInstances[instance]?.removeRabbitmqQueues();
|
||||||
delete this.waInstances[instance];
|
|
||||||
this.eventEmitter.emit('remove.instance', instance, 'inner');
|
this.eventEmitter.emit('remove.instance', instance, 'inner');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,6 +342,13 @@ export class WAMonitoringService {
|
|||||||
private removeInstance() {
|
private removeInstance() {
|
||||||
this.eventEmitter.on('remove.instance', async (instanceName: string) => {
|
this.eventEmitter.on('remove.instance', async (instanceName: string) => {
|
||||||
try {
|
try {
|
||||||
|
await websocketController.emit({
|
||||||
|
instanceName,
|
||||||
|
origin: WAMonitoringService.name,
|
||||||
|
event: 'remove.instance',
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
|
||||||
this.cleaningUp(instanceName);
|
this.cleaningUp(instanceName);
|
||||||
this.cleaningStoreData(instanceName);
|
this.cleaningStoreData(instanceName);
|
||||||
} finally {
|
} finally {
|
||||||
@ -356,7 +363,17 @@ export class WAMonitoringService {
|
|||||||
});
|
});
|
||||||
this.eventEmitter.on('logout.instance', async (instanceName: string) => {
|
this.eventEmitter.on('logout.instance', async (instanceName: string) => {
|
||||||
try {
|
try {
|
||||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED) this.waInstances[instanceName]?.clearCacheChatwoot();
|
await websocketController.emit({
|
||||||
|
instanceName,
|
||||||
|
origin: WAMonitoringService.name,
|
||||||
|
event: 'logout.instance',
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED) {
|
||||||
|
this.waInstances[instanceName]?.clearCacheChatwoot();
|
||||||
|
}
|
||||||
|
|
||||||
this.cleaningUp(instanceName);
|
this.cleaningUp(instanceName);
|
||||||
} finally {
|
} finally {
|
||||||
this.logger.warn(`Instance "${instanceName}" - LOGOUT`);
|
this.logger.warn(`Instance "${instanceName}" - LOGOUT`);
|
||||||
@ -367,6 +384,13 @@ export class WAMonitoringService {
|
|||||||
private noConnection() {
|
private noConnection() {
|
||||||
this.eventEmitter.on('no.connection', async (instanceName) => {
|
this.eventEmitter.on('no.connection', async (instanceName) => {
|
||||||
try {
|
try {
|
||||||
|
await websocketController.emit({
|
||||||
|
instanceName,
|
||||||
|
origin: WAMonitoringService.name,
|
||||||
|
event: 'no.connection',
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
|
||||||
await this.waInstances[instanceName]?.client?.logout('Log out instance: ' + instanceName);
|
await this.waInstances[instanceName]?.client?.logout('Log out instance: ' + instanceName);
|
||||||
|
|
||||||
this.waInstances[instanceName]?.client?.ws?.close();
|
this.waInstances[instanceName]?.client?.ws?.close();
|
||||||
|
@ -20,7 +20,7 @@ export type Cors = {
|
|||||||
|
|
||||||
export type LogBaileys = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
export type LogBaileys = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
||||||
|
|
||||||
export type LogLevel = 'ERROR' | 'WARN' | 'DEBUG' | 'INFO' | 'LOG' | 'VERBOSE' | 'DARK' | 'WEBHOOKS';
|
export type LogLevel = 'ERROR' | 'WARN' | 'DEBUG' | 'INFO' | 'LOG' | 'VERBOSE' | 'DARK' | 'WEBHOOKS' | 'WEBSOCKET';
|
||||||
|
|
||||||
export type Log = {
|
export type Log = {
|
||||||
LEVEL: LogLevel[];
|
LEVEL: LogLevel[];
|
||||||
@ -359,6 +359,7 @@ export class ConfigService {
|
|||||||
'VERBOSE',
|
'VERBOSE',
|
||||||
'DARK',
|
'DARK',
|
||||||
'WEBHOOKS',
|
'WEBHOOKS',
|
||||||
|
'WEBSOCKET',
|
||||||
],
|
],
|
||||||
COLOR: process.env?.LOG_COLOR === 'true',
|
COLOR: process.env?.LOG_COLOR === 'true',
|
||||||
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
|
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
|
||||||
|
@ -2,11 +2,10 @@ import 'express-async-errors';
|
|||||||
|
|
||||||
import { initAMQP, initGlobalQueues } from '@api/integrations/rabbitmq/libs/amqp.server';
|
import { initAMQP, initGlobalQueues } from '@api/integrations/rabbitmq/libs/amqp.server';
|
||||||
import { initSQS } from '@api/integrations/sqs/libs/sqs.server';
|
import { initSQS } from '@api/integrations/sqs/libs/sqs.server';
|
||||||
import { initIO } from '@api/integrations/websocket/libs/socket.server';
|
|
||||||
import { ProviderFiles } from '@api/provider/sessions';
|
import { ProviderFiles } from '@api/provider/sessions';
|
||||||
import { PrismaRepository } from '@api/repository/repository.service';
|
import { PrismaRepository } from '@api/repository/repository.service';
|
||||||
import { HttpStatus, router } from '@api/routes/index.router';
|
import { HttpStatus, router } from '@api/routes/index.router';
|
||||||
import { waMonitor } from '@api/server.module';
|
import { waMonitor, websocketController } from '@api/server.module';
|
||||||
import { Auth, configService, Cors, HttpServer, ProviderSession, Rabbitmq, Sqs, Webhook } from '@config/env.config';
|
import { Auth, configService, Cors, HttpServer, ProviderSession, Rabbitmq, Sqs, Webhook } from '@config/env.config';
|
||||||
import { onUnexpectedError } from '@config/error.config';
|
import { onUnexpectedError } from '@config/error.config';
|
||||||
import { Logger } from '@config/logger.config';
|
import { Logger } from '@config/logger.config';
|
||||||
@ -130,12 +129,12 @@ async function bootstrap() {
|
|||||||
ServerUP.app = app;
|
ServerUP.app = app;
|
||||||
const server = ServerUP[httpServer.TYPE];
|
const server = ServerUP[httpServer.TYPE];
|
||||||
|
|
||||||
|
websocketController.init(server);
|
||||||
|
|
||||||
server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT));
|
server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT));
|
||||||
|
|
||||||
initWA();
|
initWA();
|
||||||
|
|
||||||
initIO(server);
|
|
||||||
|
|
||||||
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) {
|
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) {
|
||||||
initAMQP().then(() => {
|
initAMQP().then(() => {
|
||||||
if (configService.get<Rabbitmq>('RABBITMQ')?.GLOBAL_ENABLED) initGlobalQueues();
|
if (configService.get<Rabbitmq>('RABBITMQ')?.GLOBAL_ENABLED) initGlobalQueues();
|
||||||
|
Loading…
Reference in New Issue
Block a user