refactor: event folder

This commit is contained in:
Davidson Gomes
2024-08-20 15:27:32 -03:00
parent 64ed0faa83
commit 7b79591e42
35 changed files with 1100 additions and 1539 deletions

View File

@@ -1,5 +1,5 @@
import { PrismaRepository } from '@api/repository/repository.service';
import { websocketController } from '@api/server.module';
import { rabbitmqController, sqsController, webhookController, websocketController } from '@api/server.module';
import { WAMonitoringService } from '@api/services/monitor.service';
import { Server } from 'http';
@@ -61,6 +61,12 @@ export class EventController {
public init(httpServer: Server): void {
// websocket
websocketController.init(httpServer);
// rabbitmq
rabbitmqController.init();
// sqs
sqsController.init();
}
public async emit({
@@ -68,28 +74,76 @@ export class EventController {
origin,
event,
data,
serverUrl,
dateTime,
sender,
apiKey,
local,
}: {
instanceName: string;
origin: string;
event: string;
data: Object;
serverUrl: string;
dateTime: string;
sender: string;
apiKey?: string;
local?: boolean;
}): Promise<void> {
// websocket
await websocketController.emit({
const emitData = {
instanceName,
origin,
event,
data,
});
serverUrl,
dateTime,
sender,
apiKey,
local,
};
// websocket
await websocketController.emit(emitData);
// rabbitmq
await rabbitmqController.emit(emitData);
// sqs
await sqsController.emit(emitData);
// webhook
await webhookController.emit(emitData);
}
public async set(instanceName: string, data: any): Promise<any> {
public async setInstance(instanceName: string, data: any): Promise<any> {
// websocket
await websocketController.set(instanceName, data);
}
if (data.websocketEnabled)
await websocketController.set(instanceName, {
enabled: true,
events: data.websocketEvents,
});
public async get(instanceName: string): Promise<any> {
// websocket
await websocketController.get(instanceName);
// rabbitmq
if (data.rabbitmqEnabled)
await rabbitmqController.set(instanceName, {
enabled: true,
events: data.rabbitmqEvents,
});
// sqs
if (data.sqsEnabled)
await sqsController.set(instanceName, {
enabled: true,
events: data.sqsEvents,
});
// webhook
if (data.webhookEnabled)
await webhookController.set(instanceName, {
enabled: true,
events: data.webhookEvents,
url: data.webhookUrl,
webhookBase64: data.webhookBase64,
webhookByEvents: data.webhookByEvents,
});
}
}

View File

@@ -1,22 +1,17 @@
import { InstanceDto, SetPresenceDto } from '@api/dto/instance.dto';
import { ChatwootService } from '@api/integrations/chatbot/chatwoot/services/chatwoot.service';
import { RabbitmqService } from '@api/integrations/event/rabbitmq/services/rabbitmq.service';
import { SqsService } from '@api/integrations/event/sqs/services/sqs.service';
import { WebsocketController } from '@api/integrations/event/websocket/controllers/websocket.controller';
import { ProviderFiles } from '@api/provider/sessions';
import { PrismaRepository } from '@api/repository/repository.service';
import { AuthService } from '@api/services/auth.service';
import { eventController } from '@api/server.module';
import { CacheService } from '@api/services/cache.service';
import { BaileysStartupService } from '@api/services/channels/whatsapp.baileys.service';
import { BusinessStartupService } from '@api/services/channels/whatsapp.business.service';
import { WAMonitoringService } from '@api/services/monitor.service';
import { SettingsService } from '@api/services/settings.service';
import { WebhookService } from '@api/services/webhook.service';
import { Events, Integration, wa } from '@api/types/wa.types';
import { Auth, Chatwoot, ConfigService, HttpServer, WaBusiness } from '@config/env.config';
import { Logger } from '@config/logger.config';
import { BadRequestException, InternalServerErrorException, UnauthorizedException } from '@exceptions';
import { JsonValue } from '@prisma/client/runtime/library';
import { delay } from 'baileys';
import { isArray, isURL } from 'class-validator';
import EventEmitter2 from 'eventemitter2';
@@ -30,13 +25,8 @@ export class InstanceController {
private readonly configService: ConfigService,
private readonly prismaRepository: PrismaRepository,
private readonly eventEmitter: EventEmitter2,
private readonly authService: AuthService,
private readonly webhookService: WebhookService,
private readonly chatwootService: ChatwootService,
private readonly settingsService: SettingsService,
private readonly websocketController: WebsocketController,
private readonly rabbitmqService: RabbitmqService,
private readonly sqsService: SqsService,
private readonly proxyService: ProxyController,
private readonly cache: CacheService,
private readonly chatwootCache: CacheService,
@@ -46,58 +36,14 @@ export class InstanceController {
private readonly logger = new Logger('InstanceController');
public async createInstance({
instanceName,
qrcode,
number,
integration,
token,
rejectCall,
msgCall,
groupsIgnore,
alwaysOnline,
readMessages,
readStatus,
syncFullHistory,
proxyHost,
proxyPort,
proxyProtocol,
proxyUsername,
proxyPassword,
webhookUrl,
webhookByEvents,
webhookBase64,
webhookEvents,
websocketEnabled,
websocketEvents,
rabbitmqEnabled,
rabbitmqEvents,
sqsEnabled,
sqsEvents,
chatwootAccountId,
chatwootToken,
chatwootUrl,
chatwootSignMsg,
chatwootReopenConversation,
chatwootConversationPending,
chatwootImportContacts,
chatwootNameInbox,
chatwootMergeBrazilContacts,
chatwootImportMessages,
chatwootDaysLimitImportMessages,
chatwootOrganization,
chatwootLogo,
businessId,
}: InstanceDto) {
public async createInstance(instanceData: InstanceDto) {
try {
// if (token) await this.authService.checkDuplicateToken(token);
if (!token && integration === Integration.WHATSAPP_BUSINESS) {
if (!instanceData.token && instanceData.integration === Integration.WHATSAPP_BUSINESS) {
throw new BadRequestException('token is required');
}
let instance: BaileysStartupService | BusinessStartupService;
if (integration === Integration.WHATSAPP_BUSINESS) {
if (instanceData.integration === Integration.WHATSAPP_BUSINESS) {
instance = new BusinessStartupService(
this.configService,
this.eventEmitter,
@@ -123,210 +69,45 @@ export class InstanceController {
let hash: string;
if (!token) hash = v4().toUpperCase();
else hash = token;
if (!instanceData.token) hash = v4().toUpperCase();
else hash = instanceData.token;
await this.waMonitor.saveInstance({ instanceId, integration, instanceName, hash, number, businessId });
await this.waMonitor.saveInstance({
instanceId,
integration: instanceData.integration,
instanceName: instanceData.instanceName,
hash,
number: instanceData.number,
businessId: instanceData.businessId,
});
instance.setInstance({
instanceName,
instanceName: instanceData.instanceName,
instanceId,
integration,
integration: instanceData.integration,
token: hash,
number,
businessId,
number: instanceData.number,
businessId: instanceData.businessId,
});
instance.sendDataWebhook(Events.INSTANCE_CREATE, {
instanceName,
instanceName: instanceData.instanceName,
instanceId: instanceId,
});
this.waMonitor.waInstances[instance.instanceName] = instance;
this.waMonitor.delInstanceTime(instance.instanceName);
let getWebhookEvents: string[];
// set events
eventController.setInstance(instance.instanceName, instanceData);
if (webhookUrl) {
if (!isURL(webhookUrl, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property in webhook');
}
try {
let newEvents: string[] = [];
if (webhookEvents.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 = webhookEvents;
}
this.webhookService.create(instance, {
enabled: true,
url: webhookUrl,
events: newEvents,
webhookByEvents,
webhookBase64,
});
const webhookEventsJson: JsonValue = (await this.webhookService.find(instance)).events;
getWebhookEvents = Array.isArray(webhookEventsJson) ? webhookEventsJson.map((event) => String(event)) : [];
} catch (error) {
this.logger.log(error);
}
}
let getWebsocketEvents: string[];
if (websocketEnabled) {
try {
await this.websocketController.set(instance.instanceName, {
enabled: true,
events: websocketEvents,
});
const websocketEventsJson: JsonValue = (await this.websocketController.get(instance.instanceName)).events;
getWebsocketEvents = Array.isArray(websocketEventsJson)
? websocketEventsJson.map((event) => String(event))
: [];
} catch (error) {
this.logger.log(error);
}
}
let getRabbitmqEvents: string[];
if (rabbitmqEnabled) {
try {
let newEvents: string[] = [];
if (rabbitmqEvents.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 = rabbitmqEvents;
}
this.rabbitmqService.create(instance, {
enabled: true,
events: newEvents,
});
const rabbitmqEventsJson: JsonValue = (await this.rabbitmqService.find(instance)).events;
getRabbitmqEvents = Array.isArray(rabbitmqEventsJson) ? rabbitmqEventsJson.map((event) => String(event)) : [];
} catch (error) {
this.logger.log(error);
}
}
let getSqsEvents: string[];
if (sqsEnabled) {
try {
let newEvents: string[] = [];
if (sqsEvents.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 = sqsEvents;
}
this.sqsService.create(instance, {
enabled: true,
events: newEvents,
});
const sqsEventsJson: JsonValue = (await this.sqsService.find(instance)).events;
getSqsEvents = Array.isArray(sqsEventsJson) ? sqsEventsJson.map((event) => String(event)) : [];
// sqsEvents = (await this.sqsService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
if (proxyHost && proxyPort && proxyProtocol) {
if (instanceData.proxyHost && instanceData.proxyPort && instanceData.proxyProtocol) {
const testProxy = await this.proxyService.testProxy({
host: proxyHost,
port: proxyPort,
protocol: proxyProtocol,
username: proxyUsername,
password: proxyPassword,
host: instanceData.proxyHost,
port: instanceData.proxyPort,
protocol: instanceData.proxyProtocol,
username: instanceData.proxyUsername,
password: instanceData.proxyPassword,
});
if (!testProxy) {
throw new BadRequestException('Invalid proxy');
@@ -334,22 +115,22 @@ export class InstanceController {
await this.proxyService.createProxy(instance, {
enabled: true,
host: proxyHost,
port: proxyPort,
protocol: proxyProtocol,
username: proxyUsername,
password: proxyPassword,
host: instanceData.proxyHost,
port: instanceData.proxyPort,
protocol: instanceData.proxyProtocol,
username: instanceData.proxyUsername,
password: instanceData.proxyPassword,
});
}
const settings: wa.LocalSettings = {
rejectCall: rejectCall === true,
msgCall: msgCall || '',
groupsIgnore: groupsIgnore === true,
alwaysOnline: alwaysOnline === true,
readMessages: readMessages === true,
readStatus: readStatus === true,
syncFullHistory: syncFullHistory === true,
rejectCall: instanceData.rejectCall === true,
msgCall: instanceData.msgCall || '',
groupsIgnore: instanceData.groupsIgnore === true,
alwaysOnline: instanceData.alwaysOnline === true,
readMessages: instanceData.readMessages === true,
readStatus: instanceData.readStatus === true,
syncFullHistory: instanceData.syncFullHistory === true,
};
await this.settingsService.create(instance, settings);
@@ -357,8 +138,8 @@ export class InstanceController {
let webhookWaBusiness = null,
accessTokenWaBusiness = '';
if (integration === Integration.WHATSAPP_BUSINESS) {
if (!number) {
if (instanceData.integration === Integration.WHATSAPP_BUSINESS) {
if (!instanceData.number) {
throw new BadRequestException('number is required');
}
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
@@ -366,11 +147,11 @@ export class InstanceController {
accessTokenWaBusiness = this.configService.get<WaBusiness>('WA_BUSINESS').TOKEN_WEBHOOK;
}
if (!chatwootAccountId || !chatwootToken || !chatwootUrl) {
if (!instanceData.chatwootAccountId || !instanceData.chatwootToken || !instanceData.chatwootUrl) {
let getQrcode: wa.QrCode;
if (qrcode && integration === Integration.WHATSAPP_BAILEYS) {
await instance.connectToWhatsapp(number);
if (instanceData.qrcode && instanceData.integration === Integration.WHATSAPP_BAILEYS) {
await instance.connectToWhatsapp(instanceData.number);
await delay(5000);
getQrcode = instance.qrCode;
}
@@ -379,29 +160,29 @@ export class InstanceController {
instance: {
instanceName: instance.instanceName,
instanceId: instanceId,
integration: integration,
integration: instanceData.integration,
webhookWaBusiness,
accessTokenWaBusiness,
status: 'created',
},
hash,
webhook: {
webhookUrl,
webhookByEvents,
webhookBase64,
events: getWebhookEvents,
webhookUrl: instanceData.webhookUrl,
webhookByEvents: instanceData.webhookByEvents,
webhookBase64: instanceData.webhookBase64,
// events: getWebhookEvents,
},
websocket: {
enabled: websocketEnabled,
events: getWebsocketEvents,
enabled: instanceData.websocketEnabled,
// events: getWebsocketEvents,
},
rabbitmq: {
enabled: rabbitmqEnabled,
events: getRabbitmqEvents,
enabled: instanceData.rabbitmqEnabled,
// events: getRabbitmqEvents,
},
sqs: {
enabled: sqsEnabled,
events: getSqsEvents,
enabled: instanceData.sqsEnabled,
// events: getSqsEvents,
},
settings,
qrcode: getQrcode,
@@ -413,31 +194,31 @@ export class InstanceController {
if (!this.configService.get<Chatwoot>('CHATWOOT').ENABLED)
throw new BadRequestException('Chatwoot is not enabled');
if (!chatwootAccountId) {
if (!instanceData.chatwootAccountId) {
throw new BadRequestException('accountId is required');
}
if (!chatwootToken) {
if (!instanceData.chatwootToken) {
throw new BadRequestException('token is required');
}
if (!chatwootUrl) {
if (!instanceData.chatwootUrl) {
throw new BadRequestException('url is required');
}
if (!isURL(chatwootUrl, { require_tld: false })) {
if (!isURL(instanceData.chatwootUrl, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property in chatwoot');
}
if (chatwootSignMsg !== true && chatwootSignMsg !== false) {
if (instanceData.chatwootSignMsg !== true && instanceData.chatwootSignMsg !== false) {
throw new BadRequestException('signMsg is required');
}
if (chatwootReopenConversation !== true && chatwootReopenConversation !== false) {
if (instanceData.chatwootReopenConversation !== true && instanceData.chatwootReopenConversation !== false) {
throw new BadRequestException('reopenConversation is required');
}
if (chatwootConversationPending !== true && chatwootConversationPending !== false) {
if (instanceData.chatwootConversationPending !== true && instanceData.chatwootConversationPending !== false) {
throw new BadRequestException('conversationPending is required');
}
@@ -446,20 +227,20 @@ export class InstanceController {
try {
this.chatwootService.create(instance, {
enabled: true,
accountId: chatwootAccountId,
token: chatwootToken,
url: chatwootUrl,
signMsg: chatwootSignMsg || false,
nameInbox: chatwootNameInbox ?? instance.instanceName.split('-cwId-')[0],
number,
reopenConversation: chatwootReopenConversation || false,
conversationPending: chatwootConversationPending || false,
importContacts: chatwootImportContacts ?? true,
mergeBrazilContacts: chatwootMergeBrazilContacts ?? false,
importMessages: chatwootImportMessages ?? true,
daysLimitImportMessages: chatwootDaysLimitImportMessages ?? 60,
organization: chatwootOrganization,
logo: chatwootLogo,
accountId: instanceData.chatwootAccountId,
token: instanceData.chatwootToken,
url: instanceData.chatwootUrl,
signMsg: instanceData.chatwootSignMsg || false,
nameInbox: instanceData.chatwootNameInbox ?? instance.instanceName.split('-cwId-')[0],
number: instanceData.number,
reopenConversation: instanceData.chatwootReopenConversation || false,
conversationPending: instanceData.chatwootConversationPending || false,
importContacts: instanceData.chatwootImportContacts ?? true,
mergeBrazilContacts: instanceData.chatwootMergeBrazilContacts ?? false,
importMessages: instanceData.chatwootImportMessages ?? true,
daysLimitImportMessages: instanceData.chatwootDaysLimitImportMessages ?? 60,
organization: instanceData.chatwootOrganization,
logo: instanceData.chatwootLogo,
autoCreate: true,
});
} catch (error) {
@@ -470,45 +251,45 @@ export class InstanceController {
instance: {
instanceName: instance.instanceName,
instanceId: instanceId,
integration: integration,
integration: instanceData.integration,
webhookWaBusiness,
accessTokenWaBusiness,
status: 'created',
},
hash,
webhook: {
webhookUrl,
webhookByEvents,
webhookBase64,
events: getWebhookEvents,
webhookUrl: instanceData.webhookUrl,
webhookByEvents: instanceData.webhookByEvents,
webhookBase64: instanceData.webhookBase64,
// events: getWebhookEvents,
},
websocket: {
enabled: websocketEnabled,
events: getWebsocketEvents,
enabled: instanceData.websocketEnabled,
// events: getWebsocketEvents,
},
rabbitmq: {
enabled: rabbitmqEnabled,
events: getRabbitmqEvents,
enabled: instanceData.rabbitmqEnabled,
// events: getRabbitmqEvents,
},
sqs: {
enabled: sqsEnabled,
events: getSqsEvents,
enabled: instanceData.sqsEnabled,
// events: getSqsEvents,
},
settings,
chatwoot: {
enabled: true,
accountId: chatwootAccountId,
token: chatwootToken,
url: chatwootUrl,
signMsg: chatwootSignMsg || false,
reopenConversation: chatwootReopenConversation || false,
conversationPending: chatwootConversationPending || false,
mergeBrazilContacts: chatwootMergeBrazilContacts ?? false,
importContacts: chatwootImportContacts ?? true,
importMessages: chatwootImportMessages ?? true,
daysLimitImportMessages: chatwootDaysLimitImportMessages || 60,
number,
nameInbox: chatwootNameInbox ?? instance.instanceName,
accountId: instanceData.chatwootAccountId,
token: instanceData.chatwootToken,
url: instanceData.chatwootUrl,
signMsg: instanceData.chatwootSignMsg || false,
reopenConversation: instanceData.chatwootReopenConversation || false,
conversationPending: instanceData.chatwootConversationPending || false,
mergeBrazilContacts: instanceData.chatwootMergeBrazilContacts ?? false,
importContacts: instanceData.chatwootImportContacts ?? true,
importMessages: instanceData.chatwootImportMessages ?? true,
daysLimitImportMessages: instanceData.chatwootDaysLimitImportMessages || 60,
number: instanceData.number,
nameInbox: instanceData.chatwootNameInbox ?? instance.instanceName,
webhookUrl: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
},
};
@@ -650,7 +431,6 @@ export class InstanceController {
}
try {
const waInstances = this.waMonitor.waInstances[instanceName];
waInstances?.removeRabbitmqQueues();
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED) waInstances?.clearCacheChatwoot();
if (instance.state === 'connecting') {

View File

@@ -1,65 +0,0 @@
import { InstanceDto } from '@api/dto/instance.dto';
import { WebhookDto } from '@api/dto/webhook.dto';
import { WAMonitoringService } from '@api/services/monitor.service';
import { WebhookService } from '@api/services/webhook.service';
import { BadRequestException } from '@exceptions';
import { isURL } from 'class-validator';
export class WebhookController {
constructor(private readonly webhookService: WebhookService, private readonly waMonitor: WAMonitoringService) {}
public async createWebhook(instance: InstanceDto, data: WebhookDto) {
if (!isURL(data.url, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property');
}
data.enabled = data.enabled ?? true;
if (!data.enabled) {
data.url = '';
data.events = [];
} else if (data.events.length === 0) {
data.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',
];
}
return this.webhookService.create(instance, data);
}
public async findWebhook(instance: InstanceDto) {
return this.webhookService.find(instance);
}
public async receiveWebhook(data: any) {
this.webhookService.receiveWebhook(data);
return {
message: 'Webhook received',
};
}
}