mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-14 01:41:24 -06:00
feat: pusher event integration
This commit is contained in:
parent
f38f3e5ba5
commit
29e2cfaf96
35
.env.example
35
.env.example
@ -88,6 +88,41 @@ SQS_REGION=
|
|||||||
WEBSOCKET_ENABLED=false
|
WEBSOCKET_ENABLED=false
|
||||||
WEBSOCKET_GLOBAL_EVENTS=false
|
WEBSOCKET_GLOBAL_EVENTS=false
|
||||||
|
|
||||||
|
# Pusher - Environment variables
|
||||||
|
PUSHER_ENABLED=false
|
||||||
|
PUSHER_GLOBAL_ENABLED=false
|
||||||
|
PUSHER_GLOBAL_APP_ID=
|
||||||
|
PUSHER_GLOBAL_KEY=
|
||||||
|
PUSHER_GLOBAL_SECRET=
|
||||||
|
PUSHER_GLOBAL_CLUSTER=
|
||||||
|
PUSHER_GLOBAL_USE_TLS=true
|
||||||
|
# Choose the events you want to send to Pusher
|
||||||
|
PUSHER_EVENTS_APPLICATION_STARTUP=true
|
||||||
|
PUSHER_EVENTS_QRCODE_UPDATED=true
|
||||||
|
PUSHER_EVENTS_MESSAGES_SET=true
|
||||||
|
PUSHER_EVENTS_MESSAGES_UPSERT=true
|
||||||
|
PUSHER_EVENTS_MESSAGES_EDITED=true
|
||||||
|
PUSHER_EVENTS_MESSAGES_UPDATE=true
|
||||||
|
PUSHER_EVENTS_MESSAGES_DELETE=true
|
||||||
|
PUSHER_EVENTS_SEND_MESSAGE=true
|
||||||
|
PUSHER_EVENTS_CONTACTS_SET=true
|
||||||
|
PUSHER_EVENTS_CONTACTS_UPSERT=true
|
||||||
|
PUSHER_EVENTS_CONTACTS_UPDATE=true
|
||||||
|
PUSHER_EVENTS_PRESENCE_UPDATE=true
|
||||||
|
PUSHER_EVENTS_CHATS_SET=true
|
||||||
|
PUSHER_EVENTS_CHATS_UPSERT=true
|
||||||
|
PUSHER_EVENTS_CHATS_UPDATE=true
|
||||||
|
PUSHER_EVENTS_CHATS_DELETE=true
|
||||||
|
PUSHER_EVENTS_GROUPS_UPSERT=true
|
||||||
|
PUSHER_EVENTS_GROUPS_UPDATE=true
|
||||||
|
PUSHER_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
|
||||||
|
PUSHER_EVENTS_CONNECTION_UPDATE=true
|
||||||
|
PUSHER_EVENTS_LABELS_EDIT=true
|
||||||
|
PUSHER_EVENTS_LABELS_ASSOCIATION=true
|
||||||
|
PUSHER_EVENTS_CALL=true
|
||||||
|
PUSHER_EVENTS_TYPEBOT_START=false
|
||||||
|
PUSHER_EVENTS_TYPEBOT_CHANGE_STATUS=false
|
||||||
|
|
||||||
# WhatsApp Business API - Environment variables
|
# WhatsApp Business API - Environment variables
|
||||||
# Token used to validate the webhook on the Facebook APP
|
# Token used to validate the webhook on the Facebook APP
|
||||||
WA_BUSINESS_TOKEN_WEBHOOK=evolution
|
WA_BUSINESS_TOKEN_WEBHOOK=evolution
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
* Fake Call function
|
* Fake Call function
|
||||||
* Added unreadMessages to chats
|
* Added unreadMessages to chats
|
||||||
|
* Pusher event integration
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@
|
|||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"pino": "^8.11.0",
|
"pino": "^8.11.0",
|
||||||
"prisma": "^5.15.0",
|
"prisma": "^5.15.0",
|
||||||
|
"pusher": "^5.2.0",
|
||||||
"qrcode": "^1.5.1",
|
"qrcode": "^1.5.1",
|
||||||
"qrcode-terminal": "^0.12.0",
|
"qrcode-terminal": "^0.12.0",
|
||||||
"redis": "^4.6.5",
|
"redis": "^4.6.5",
|
||||||
|
@ -104,6 +104,7 @@ model Instance {
|
|||||||
EvolutionBotSetting EvolutionBotSetting?
|
EvolutionBotSetting EvolutionBotSetting?
|
||||||
Flowise Flowise[]
|
Flowise Flowise[]
|
||||||
FlowiseSetting FlowiseSetting?
|
FlowiseSetting FlowiseSetting?
|
||||||
|
Pusher Pusher?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Session {
|
model Session {
|
||||||
@ -289,6 +290,21 @@ model Websocket {
|
|||||||
instanceId String @unique
|
instanceId String @unique
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Pusher {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
enabled Boolean @default(false)
|
||||||
|
appId String @db.VarChar(100)
|
||||||
|
key String @db.VarChar(100)
|
||||||
|
secret String @db.VarChar(100)
|
||||||
|
cluster String @db.VarChar(100)
|
||||||
|
useTLS Boolean @default(false)
|
||||||
|
events Json @db.Json
|
||||||
|
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
|
||||||
|
updatedAt DateTime @updatedAt @db.Timestamp
|
||||||
|
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||||
|
instanceId String @unique
|
||||||
|
}
|
||||||
|
|
||||||
model Typebot {
|
model Typebot {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
enabled Boolean @default(true)
|
enabled Boolean @default(true)
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Pusher" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"enabled" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"appId" VARCHAR(100) NOT NULL,
|
||||||
|
"key" VARCHAR(100) NOT NULL,
|
||||||
|
"secret" VARCHAR(100) NOT NULL,
|
||||||
|
"cluster" VARCHAR(100) NOT NULL,
|
||||||
|
"useTLS" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"events" JSONB NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL,
|
||||||
|
"instanceId" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Pusher_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Pusher_instanceId_key" ON "Pusher"("instanceId");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Pusher" ADD CONSTRAINT "Pusher_instanceId_fkey" FOREIGN KEY ("instanceId") REFERENCES "Instance"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
@ -104,6 +104,7 @@ model Instance {
|
|||||||
EvolutionBotSetting EvolutionBotSetting?
|
EvolutionBotSetting EvolutionBotSetting?
|
||||||
Flowise Flowise[]
|
Flowise Flowise[]
|
||||||
FlowiseSetting FlowiseSetting?
|
FlowiseSetting FlowiseSetting?
|
||||||
|
Pusher Pusher?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Session {
|
model Session {
|
||||||
@ -115,15 +116,15 @@ model Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Chat {
|
model Chat {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
remoteJid String @db.VarChar(100)
|
remoteJid String @db.VarChar(100)
|
||||||
name String? @db.VarChar(100)
|
name String? @db.VarChar(100)
|
||||||
labels Json? @db.JsonB
|
labels Json? @db.JsonB
|
||||||
createdAt DateTime? @default(now()) @db.Timestamp
|
createdAt DateTime? @default(now()) @db.Timestamp
|
||||||
updatedAt DateTime? @updatedAt @db.Timestamp
|
updatedAt DateTime? @updatedAt @db.Timestamp
|
||||||
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||||
instanceId String
|
instanceId String
|
||||||
unreadMessages Int @default(0)
|
unreadMessages Int @default(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
model Contact {
|
model Contact {
|
||||||
@ -291,6 +292,21 @@ model Websocket {
|
|||||||
instanceId String @unique
|
instanceId String @unique
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Pusher {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
enabled Boolean @default(false) @db.Boolean
|
||||||
|
appId String @db.VarChar(100)
|
||||||
|
key String @db.VarChar(100)
|
||||||
|
secret String @db.VarChar(100)
|
||||||
|
cluster String @db.VarChar(100)
|
||||||
|
useTLS Boolean @default(false) @db.Boolean
|
||||||
|
events Json @db.JsonB
|
||||||
|
createdAt DateTime? @default(now()) @db.Timestamp
|
||||||
|
updatedAt DateTime @updatedAt @db.Timestamp
|
||||||
|
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||||
|
instanceId String @unique
|
||||||
|
}
|
||||||
|
|
||||||
model Typebot {
|
model Typebot {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
enabled Boolean @default(true) @db.Boolean
|
enabled Boolean @default(true) @db.Boolean
|
||||||
|
@ -7,7 +7,7 @@ export type EmitData = {
|
|||||||
instanceName: string;
|
instanceName: string;
|
||||||
origin: string;
|
origin: string;
|
||||||
event: string;
|
event: string;
|
||||||
data: Object;
|
data: any;
|
||||||
serverUrl: string;
|
serverUrl: string;
|
||||||
dateTime: string;
|
dateTime: string;
|
||||||
sender: string;
|
sender: string;
|
||||||
@ -22,7 +22,7 @@ export interface EventControllerInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EventController {
|
export class EventController {
|
||||||
private prismaRepository: PrismaRepository;
|
public prismaRepository: PrismaRepository;
|
||||||
private waMonitor: WAMonitoringService;
|
private waMonitor: WAMonitoringService;
|
||||||
private integrationStatus: boolean;
|
private integrationStatus: boolean;
|
||||||
private integrationName: string;
|
private integrationName: string;
|
||||||
|
@ -25,6 +25,16 @@ export class EventDto {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
events?: string[];
|
events?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pusher?: {
|
||||||
|
enabled?: boolean;
|
||||||
|
appId?: string;
|
||||||
|
key?: string;
|
||||||
|
secret?: string;
|
||||||
|
cluster?: string;
|
||||||
|
useTLS?: boolean;
|
||||||
|
events?: string[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EventInstanceMixin<TBase extends Constructor>(Base: TBase) {
|
export function EventInstanceMixin<TBase extends Constructor>(Base: TBase) {
|
||||||
@ -52,5 +62,15 @@ export function EventInstanceMixin<TBase extends Constructor>(Base: TBase) {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
events?: string[];
|
events?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pusher?: {
|
||||||
|
enabled?: boolean;
|
||||||
|
appId?: string;
|
||||||
|
key?: string;
|
||||||
|
secret?: string;
|
||||||
|
cluster?: string;
|
||||||
|
useTLS?: boolean;
|
||||||
|
events?: string[];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { PusherController } from '@api/integrations/event/pusher/pusher.controller';
|
||||||
import { RabbitmqController } from '@api/integrations/event/rabbitmq/rabbitmq.controller';
|
import { RabbitmqController } from '@api/integrations/event/rabbitmq/rabbitmq.controller';
|
||||||
import { SqsController } from '@api/integrations/event/sqs/sqs.controller';
|
import { SqsController } from '@api/integrations/event/sqs/sqs.controller';
|
||||||
import { WebhookController } from '@api/integrations/event/webhook/webhook.controller';
|
import { WebhookController } from '@api/integrations/event/webhook/webhook.controller';
|
||||||
@ -13,6 +14,7 @@ export class EventManager {
|
|||||||
private webhookController: WebhookController;
|
private webhookController: WebhookController;
|
||||||
private rabbitmqController: RabbitmqController;
|
private rabbitmqController: RabbitmqController;
|
||||||
private sqsController: SqsController;
|
private sqsController: SqsController;
|
||||||
|
private pusherController: PusherController;
|
||||||
|
|
||||||
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
|
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
|
||||||
this.prisma = prismaRepository;
|
this.prisma = prismaRepository;
|
||||||
@ -22,6 +24,7 @@ export class EventManager {
|
|||||||
this.webhook = new WebhookController(prismaRepository, waMonitor);
|
this.webhook = new WebhookController(prismaRepository, waMonitor);
|
||||||
this.rabbitmq = new RabbitmqController(prismaRepository, waMonitor);
|
this.rabbitmq = new RabbitmqController(prismaRepository, waMonitor);
|
||||||
this.sqs = new SqsController(prismaRepository, waMonitor);
|
this.sqs = new SqsController(prismaRepository, waMonitor);
|
||||||
|
this.pusher = new PusherController(prismaRepository, waMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public set prisma(prisma: PrismaRepository) {
|
public set prisma(prisma: PrismaRepository) {
|
||||||
@ -72,10 +75,18 @@ export class EventManager {
|
|||||||
return this.sqsController;
|
return this.sqsController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set pusher(pusher: PusherController) {
|
||||||
|
this.pusherController = pusher;
|
||||||
|
}
|
||||||
|
public get pusher() {
|
||||||
|
return this.pusherController;
|
||||||
|
}
|
||||||
|
|
||||||
public init(httpServer: Server): void {
|
public init(httpServer: Server): void {
|
||||||
this.websocket.init(httpServer);
|
this.websocket.init(httpServer);
|
||||||
this.rabbitmq.init();
|
this.rabbitmq.init();
|
||||||
this.sqs.init();
|
this.sqs.init();
|
||||||
|
this.pusher.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async emit(eventData: {
|
public async emit(eventData: {
|
||||||
@ -93,6 +104,7 @@ export class EventManager {
|
|||||||
await this.rabbitmq.emit(eventData);
|
await this.rabbitmq.emit(eventData);
|
||||||
await this.sqs.emit(eventData);
|
await this.sqs.emit(eventData);
|
||||||
await this.webhook.emit(eventData);
|
await this.webhook.emit(eventData);
|
||||||
|
await this.pusher.emit(eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setInstance(instanceName: string, data: any): Promise<any> {
|
public async setInstance(instanceName: string, data: any): Promise<any> {
|
||||||
@ -131,5 +143,18 @@ export class EventManager {
|
|||||||
byEvents: data.webhook?.byEvents,
|
byEvents: data.webhook?.byEvents,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (data.pusher)
|
||||||
|
await this.pusher.set(instanceName, {
|
||||||
|
pusher: {
|
||||||
|
enabled: true,
|
||||||
|
events: data.pusher?.events,
|
||||||
|
appId: data.pusher?.appId,
|
||||||
|
key: data.pusher?.key,
|
||||||
|
secret: data.pusher?.secret,
|
||||||
|
cluster: data.pusher?.cluster,
|
||||||
|
useTLS: data.pusher?.useTLS,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { PusherRouter } from '@api/integrations/event/pusher/pusher.router';
|
||||||
import { RabbitmqRouter } from '@api/integrations/event/rabbitmq/rabbitmq.router';
|
import { RabbitmqRouter } from '@api/integrations/event/rabbitmq/rabbitmq.router';
|
||||||
import { SqsRouter } from '@api/integrations/event/sqs/sqs.router';
|
import { SqsRouter } from '@api/integrations/event/sqs/sqs.router';
|
||||||
import { WebhookRouter } from '@api/integrations/event/webhook/webhook.router';
|
import { WebhookRouter } from '@api/integrations/event/webhook/webhook.router';
|
||||||
@ -13,6 +14,7 @@ export class EventRouter {
|
|||||||
this.router.use('/webhook', new WebhookRouter(configService, ...guards).router);
|
this.router.use('/webhook', new WebhookRouter(configService, ...guards).router);
|
||||||
this.router.use('/websocket', new WebsocketRouter(...guards).router);
|
this.router.use('/websocket', new WebsocketRouter(...guards).router);
|
||||||
this.router.use('/rabbitmq', new RabbitmqRouter(...guards).router);
|
this.router.use('/rabbitmq', new RabbitmqRouter(...guards).router);
|
||||||
|
this.router.use('/pusher', new PusherRouter(...guards).router);
|
||||||
this.router.use('/sqs', new SqsRouter(...guards).router);
|
this.router.use('/sqs', new SqsRouter(...guards).router);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { v4 } from 'uuid';
|
|||||||
|
|
||||||
import { EventController } from './event.controller';
|
import { EventController } from './event.controller';
|
||||||
|
|
||||||
|
export * from '@api/integrations/event/pusher/pusher.schema';
|
||||||
export * from '@api/integrations/event/webhook/webhook.schema';
|
export * from '@api/integrations/event/webhook/webhook.schema';
|
||||||
|
|
||||||
export const eventSchema: JSONSchema7 = {
|
export const eventSchema: JSONSchema7 = {
|
||||||
|
209
src/api/integrations/event/pusher/pusher.controller.ts
Normal file
209
src/api/integrations/event/pusher/pusher.controller.ts
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
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, Pusher as ConfigPusher } from '@config/env.config';
|
||||||
|
import { Logger } from '@config/logger.config';
|
||||||
|
import Pusher from 'pusher';
|
||||||
|
|
||||||
|
import { EmitData, EventController, EventControllerInterface } from '../event.controller';
|
||||||
|
export class PusherController extends EventController implements EventControllerInterface {
|
||||||
|
private readonly logger = new Logger('PusherController');
|
||||||
|
private pusherClients: { [instanceName: string]: Pusher } = {};
|
||||||
|
private globalPusherClient: Pusher | null = null;
|
||||||
|
private pusherConfig: ConfigPusher = configService.get<ConfigPusher>('PUSHER');
|
||||||
|
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
|
||||||
|
super(prismaRepository, waMonitor, configService.get<ConfigPusher>('PUSHER')?.ENABLED, 'pusher');
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
public async init(): Promise<void> {
|
||||||
|
if (!this.status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.pusherConfig.GLOBAL?.ENABLED) {
|
||||||
|
const { APP_ID, KEY, SECRET, CLUSTER, USE_TLS } = this.pusherConfig.GLOBAL;
|
||||||
|
if (APP_ID && KEY && SECRET && CLUSTER) {
|
||||||
|
this.globalPusherClient = new Pusher({
|
||||||
|
appId: APP_ID,
|
||||||
|
key: KEY,
|
||||||
|
secret: SECRET,
|
||||||
|
cluster: CLUSTER,
|
||||||
|
useTLS: USE_TLS,
|
||||||
|
});
|
||||||
|
this.logger.info('Pusher global client initialized');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const instances = await this.prismaRepository.instance.findMany({
|
||||||
|
where: {
|
||||||
|
Pusher: {
|
||||||
|
isNot: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
Pusher: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
instances.forEach((instance) => {
|
||||||
|
if (
|
||||||
|
instance.Pusher.enabled &&
|
||||||
|
instance.Pusher.appId &&
|
||||||
|
instance.Pusher.key &&
|
||||||
|
instance.Pusher.secret &&
|
||||||
|
instance.Pusher.cluster
|
||||||
|
) {
|
||||||
|
this.pusherClients[instance.name] = new Pusher({
|
||||||
|
appId: instance.Pusher.appId,
|
||||||
|
key: instance.Pusher.key,
|
||||||
|
secret: instance.Pusher.secret,
|
||||||
|
cluster: instance.Pusher.cluster,
|
||||||
|
useTLS: instance.Pusher.useTLS,
|
||||||
|
});
|
||||||
|
this.logger.info(`Pusher client initialized for instance ${instance.name}`);
|
||||||
|
} else {
|
||||||
|
delete this.pusherClients[instance.name];
|
||||||
|
this.logger.warn(`Pusher client disabled or misconfigured for instance ${instance.name}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
override async set(instanceName: string, data: EventDto): Promise<wa.LocalPusher> {
|
||||||
|
if (!data.pusher?.enabled) {
|
||||||
|
data.pusher.events = [];
|
||||||
|
} else if (data.pusher.events.length === 0) {
|
||||||
|
data.pusher.events = EventController.events;
|
||||||
|
}
|
||||||
|
const instance = await this.prisma.pusher.upsert({
|
||||||
|
where: {
|
||||||
|
instanceId: this.monitor.waInstances[instanceName].instanceId,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
enabled: data.pusher.enabled,
|
||||||
|
events: data.pusher.events,
|
||||||
|
appId: data.pusher.appId,
|
||||||
|
key: data.pusher.key,
|
||||||
|
secret: data.pusher.secret,
|
||||||
|
cluster: data.pusher.cluster,
|
||||||
|
useTLS: data.pusher.useTLS,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
enabled: data.pusher.enabled,
|
||||||
|
events: data.pusher.events,
|
||||||
|
instanceId: this.monitor.waInstances[instanceName].instanceId,
|
||||||
|
appId: data.pusher.appId,
|
||||||
|
key: data.pusher.key,
|
||||||
|
secret: data.pusher.secret,
|
||||||
|
cluster: data.pusher.cluster,
|
||||||
|
useTLS: data.pusher.useTLS,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (instance.enabled && instance.appId && instance.key && instance.secret && instance.cluster) {
|
||||||
|
this.pusherClients[instanceName] = new Pusher({
|
||||||
|
appId: instance.appId,
|
||||||
|
key: instance.key,
|
||||||
|
secret: instance.secret,
|
||||||
|
cluster: instance.cluster,
|
||||||
|
useTLS: instance.useTLS,
|
||||||
|
});
|
||||||
|
this.logger.info(`Pusher client initialized for instance ${instanceName}`);
|
||||||
|
} else {
|
||||||
|
delete this.pusherClients[instanceName];
|
||||||
|
this.logger.warn(`Pusher client disabled or misconfigured for instance ${instanceName}`);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
public async emit({
|
||||||
|
instanceName,
|
||||||
|
origin,
|
||||||
|
event,
|
||||||
|
data,
|
||||||
|
serverUrl,
|
||||||
|
dateTime,
|
||||||
|
sender,
|
||||||
|
apiKey,
|
||||||
|
local,
|
||||||
|
}: EmitData): Promise<void> {
|
||||||
|
if (!this.status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const instance = (await this.get(instanceName)) as wa.LocalPusher;
|
||||||
|
const we = event.replace(/[.-]/gm, '_').toUpperCase();
|
||||||
|
const enabledLog = configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS');
|
||||||
|
const eventName = event.replace(/_/g, '.').toLowerCase();
|
||||||
|
const pusherData = {
|
||||||
|
event,
|
||||||
|
instance: instanceName,
|
||||||
|
data,
|
||||||
|
destination: instance?.appId || this.pusherConfig.GLOBAL?.APP_ID,
|
||||||
|
date_time: dateTime,
|
||||||
|
sender,
|
||||||
|
server_url: serverUrl,
|
||||||
|
apikey: apiKey,
|
||||||
|
};
|
||||||
|
if (event == 'qrcode.updated') {
|
||||||
|
delete pusherData.data.qrcode.base64;
|
||||||
|
}
|
||||||
|
const payload = JSON.stringify(pusherData);
|
||||||
|
const payloadSize = Buffer.byteLength(payload, 'utf8');
|
||||||
|
const MAX_SIZE = 10240;
|
||||||
|
if (payloadSize > MAX_SIZE) {
|
||||||
|
this.logger.error({
|
||||||
|
local: `${origin}.sendData-Pusher`,
|
||||||
|
message: 'Payload size exceeds Pusher limit',
|
||||||
|
event,
|
||||||
|
instanceName,
|
||||||
|
payloadSize,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (local && instance && instance.enabled) {
|
||||||
|
const pusherLocalEvents = instance.events;
|
||||||
|
if (Array.isArray(pusherLocalEvents) && pusherLocalEvents.includes(we)) {
|
||||||
|
if (enabledLog) {
|
||||||
|
this.logger.log({
|
||||||
|
local: `${origin}.sendData-Pusher`,
|
||||||
|
appId: instance.appId,
|
||||||
|
...pusherData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const pusher = this.pusherClients[instanceName];
|
||||||
|
if (pusher) {
|
||||||
|
pusher.trigger(instanceName, eventName, pusherData);
|
||||||
|
} else {
|
||||||
|
this.logger.error(`Pusher client not found for instance ${instanceName}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error({
|
||||||
|
local: `${origin}.sendData-Pusher`,
|
||||||
|
message: error?.message,
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.pusherConfig.GLOBAL?.ENABLED) {
|
||||||
|
const globalEvents = this.pusherConfig.EVENTS;
|
||||||
|
if (globalEvents[we]) {
|
||||||
|
if (enabledLog) {
|
||||||
|
this.logger.log({
|
||||||
|
local: `${origin}.sendData-Pusher-Global`,
|
||||||
|
appId: this.pusherConfig.GLOBAL?.APP_ID,
|
||||||
|
...pusherData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (this.globalPusherClient) {
|
||||||
|
this.globalPusherClient.trigger(instanceName, eventName, pusherData);
|
||||||
|
} else {
|
||||||
|
this.logger.error('Global Pusher client not initialized');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error({
|
||||||
|
local: `${origin}.sendData-Pusher-Global`,
|
||||||
|
message: error?.message,
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/api/integrations/event/pusher/pusher.router.ts
Normal file
32
src/api/integrations/event/pusher/pusher.router.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { RouterBroker } from '@api/abstract/abstract.router';
|
||||||
|
import { InstanceDto } from '@api/dto/instance.dto';
|
||||||
|
import { EventDto } from '@api/integrations/event/event.dto';
|
||||||
|
import { HttpStatus } from '@api/routes/index.router';
|
||||||
|
import { eventManager } from '@api/server.module';
|
||||||
|
import { instanceSchema, pusherSchema } from '@validate/validate.schema';
|
||||||
|
import { RequestHandler, Router } from 'express';
|
||||||
|
export class PusherRouter extends RouterBroker {
|
||||||
|
constructor(...guards: RequestHandler[]) {
|
||||||
|
super();
|
||||||
|
this.router
|
||||||
|
.post(this.routerPath('set'), ...guards, async (req, res) => {
|
||||||
|
const response = await this.dataValidate<EventDto>({
|
||||||
|
request: req,
|
||||||
|
schema: pusherSchema,
|
||||||
|
ClassRef: EventDto,
|
||||||
|
execute: (instance, data) => eventManager.pusher.set(instance.instanceName, data),
|
||||||
|
});
|
||||||
|
res.status(HttpStatus.CREATED).json(response);
|
||||||
|
})
|
||||||
|
.get(this.routerPath('find'), ...guards, async (req, res) => {
|
||||||
|
const response = await this.dataValidate<InstanceDto>({
|
||||||
|
request: req,
|
||||||
|
schema: instanceSchema,
|
||||||
|
ClassRef: InstanceDto,
|
||||||
|
execute: (instance) => eventManager.pusher.get(instance.instanceName),
|
||||||
|
});
|
||||||
|
res.status(HttpStatus.OK).json(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public readonly router: Router = Router();
|
||||||
|
}
|
50
src/api/integrations/event/pusher/pusher.schema.ts
Normal file
50
src/api/integrations/event/pusher/pusher.schema.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { JSONSchema7 } from 'json-schema';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { EventController } from '../event.controller';
|
||||||
|
const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => {
|
||||||
|
const properties = {};
|
||||||
|
propertyNames.forEach(
|
||||||
|
(property) =>
|
||||||
|
(properties[property] = {
|
||||||
|
minLength: 1,
|
||||||
|
description: `The "${property}" cannot be empty`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
if: {
|
||||||
|
propertyNames: {
|
||||||
|
enum: [...propertyNames],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
then: { properties },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export const pusherSchema: JSONSchema7 = {
|
||||||
|
$id: v4(),
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
pusher: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
enabled: { type: 'boolean' },
|
||||||
|
appId: { type: 'string' },
|
||||||
|
key: { type: 'string' },
|
||||||
|
secret: { type: 'string' },
|
||||||
|
cluster: { type: 'string' },
|
||||||
|
useTLS: { type: 'boolean' },
|
||||||
|
events: {
|
||||||
|
type: 'array',
|
||||||
|
minItems: 0,
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
enum: EventController.events,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['enabled', 'appId', 'key', 'secret', 'cluster', 'useTLS'],
|
||||||
|
...isNotEmpty('enabled', 'appId', 'key', 'secret', 'cluster', 'useTLS'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['pusher'],
|
||||||
|
};
|
@ -99,6 +99,14 @@ export declare namespace wa {
|
|||||||
webhookBase64?: boolean;
|
webhookBase64?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LocalPusher = LocalEvent & {
|
||||||
|
appId?: string;
|
||||||
|
key?: string;
|
||||||
|
secret?: string;
|
||||||
|
cluster?: string;
|
||||||
|
useTLS?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
type Session = {
|
type Session = {
|
||||||
remoteJid?: string;
|
remoteJid?: string;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
|
2
src/cache/cacheengine.ts
vendored
2
src/cache/cacheengine.ts
vendored
@ -20,8 +20,6 @@ export class CacheEngine {
|
|||||||
logger.verbose(`LocalCache initialized for ${module}`);
|
logger.verbose(`LocalCache initialized for ${module}`);
|
||||||
this.engine = new LocalCache(configService, module);
|
this.engine = new LocalCache(configService, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEngine() {
|
public getEngine() {
|
||||||
|
5
src/cache/localcache.ts
vendored
5
src/cache/localcache.ts
vendored
@ -1,8 +1,8 @@
|
|||||||
import { ICache } from '@api/abstract/abstract.cache';
|
import { ICache } from '@api/abstract/abstract.cache';
|
||||||
import { CacheConf, CacheConfLocal, ConfigService } from '@config/env.config';
|
import { CacheConf, CacheConfLocal, ConfigService } from '@config/env.config';
|
||||||
import NodeCache from 'node-cache';
|
|
||||||
import { BufferJSON } from 'baileys';
|
|
||||||
import { Logger } from '@config/logger.config';
|
import { Logger } from '@config/logger.config';
|
||||||
|
import { BufferJSON } from 'baileys';
|
||||||
|
import NodeCache from 'node-cache';
|
||||||
|
|
||||||
export class LocalCache implements ICache {
|
export class LocalCache implements ICache {
|
||||||
private readonly logger = new Logger('LocalCache');
|
private readonly logger = new Logger('LocalCache');
|
||||||
@ -74,7 +74,6 @@ export class LocalCache implements ICache {
|
|||||||
|
|
||||||
hash[field] = json;
|
hash[field] = json;
|
||||||
LocalCache.localCache.set(this.buildKey(key), hash);
|
LocalCache.localCache.set(this.buildKey(key), hash);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,36 @@ export type EventsWebhook = {
|
|||||||
ERRORS_WEBHOOK: string;
|
ERRORS_WEBHOOK: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EventsPusher = {
|
||||||
|
APPLICATION_STARTUP: boolean;
|
||||||
|
INSTANCE_CREATE: boolean;
|
||||||
|
INSTANCE_DELETE: boolean;
|
||||||
|
QRCODE_UPDATED: boolean;
|
||||||
|
MESSAGES_SET: boolean;
|
||||||
|
MESSAGES_UPSERT: boolean;
|
||||||
|
MESSAGES_EDITED: boolean;
|
||||||
|
MESSAGES_UPDATE: boolean;
|
||||||
|
MESSAGES_DELETE: boolean;
|
||||||
|
SEND_MESSAGE: boolean;
|
||||||
|
CONTACTS_SET: boolean;
|
||||||
|
CONTACTS_UPDATE: boolean;
|
||||||
|
CONTACTS_UPSERT: boolean;
|
||||||
|
PRESENCE_UPDATE: boolean;
|
||||||
|
CHATS_SET: boolean;
|
||||||
|
CHATS_UPDATE: boolean;
|
||||||
|
CHATS_DELETE: boolean;
|
||||||
|
CHATS_UPSERT: boolean;
|
||||||
|
CONNECTION_UPDATE: boolean;
|
||||||
|
LABELS_EDIT: boolean;
|
||||||
|
LABELS_ASSOCIATION: boolean;
|
||||||
|
GROUPS_UPSERT: boolean;
|
||||||
|
GROUP_UPDATE: boolean;
|
||||||
|
GROUP_PARTICIPANTS_UPDATE: boolean;
|
||||||
|
CALL: boolean;
|
||||||
|
TYPEBOT_START: boolean;
|
||||||
|
TYPEBOT_CHANGE_STATUS: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type ApiKey = { KEY: string };
|
export type ApiKey = { KEY: string };
|
||||||
|
|
||||||
export type Auth = {
|
export type Auth = {
|
||||||
@ -163,6 +193,16 @@ export type GlobalWebhook = {
|
|||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
WEBHOOK_BY_EVENTS: boolean;
|
WEBHOOK_BY_EVENTS: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GlobalPusher = {
|
||||||
|
ENABLED: boolean;
|
||||||
|
APP_ID: string;
|
||||||
|
KEY: string;
|
||||||
|
SECRET: string;
|
||||||
|
CLUSTER: string;
|
||||||
|
USE_TLS: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type CacheConfRedis = {
|
export type CacheConfRedis = {
|
||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
URI: string;
|
URI: string;
|
||||||
@ -176,6 +216,7 @@ export type CacheConfLocal = {
|
|||||||
};
|
};
|
||||||
export type SslConf = { PRIVKEY: string; FULLCHAIN: string };
|
export type SslConf = { PRIVKEY: string; FULLCHAIN: string };
|
||||||
export type Webhook = { GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook };
|
export type Webhook = { GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook };
|
||||||
|
export type Pusher = { ENABLED: boolean; GLOBAL?: GlobalPusher; EVENTS: EventsPusher };
|
||||||
export type ConfigSessionPhone = { CLIENT: string; NAME: string; VERSION: string };
|
export type ConfigSessionPhone = { CLIENT: string; NAME: string; VERSION: string };
|
||||||
export type QrCode = { LIMIT: number; COLOR: string };
|
export type QrCode = { LIMIT: number; COLOR: string };
|
||||||
export type Typebot = { ENABLED: boolean; API_VERSION: string; SEND_MEDIA_BASE64: boolean };
|
export type Typebot = { ENABLED: boolean; API_VERSION: string; SEND_MEDIA_BASE64: boolean };
|
||||||
@ -225,6 +266,7 @@ export interface Env {
|
|||||||
DEL_TEMP_INSTANCES: boolean;
|
DEL_TEMP_INSTANCES: boolean;
|
||||||
LANGUAGE: Language;
|
LANGUAGE: Language;
|
||||||
WEBHOOK: Webhook;
|
WEBHOOK: Webhook;
|
||||||
|
PUSHER: Pusher;
|
||||||
CONFIG_SESSION_PHONE: ConfigSessionPhone;
|
CONFIG_SESSION_PHONE: ConfigSessionPhone;
|
||||||
QRCODE: QrCode;
|
QRCODE: QrCode;
|
||||||
TYPEBOT: Typebot;
|
TYPEBOT: Typebot;
|
||||||
@ -270,7 +312,9 @@ export class ConfigService {
|
|||||||
},
|
},
|
||||||
CORS: {
|
CORS: {
|
||||||
ORIGIN: process.env.CORS_ORIGIN?.split(',') || ['*'],
|
ORIGIN: process.env.CORS_ORIGIN?.split(',') || ['*'],
|
||||||
METHODS: (process.env.CORS_METHODS?.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'] as HttpMethods[],
|
METHODS:
|
||||||
|
(process.env.CORS_METHODS?.split(',') as HttpMethods[]) ||
|
||||||
|
(['POST', 'GET', 'PUT', 'DELETE'] as HttpMethods[]),
|
||||||
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
|
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
|
||||||
},
|
},
|
||||||
SSL_CONF: {
|
SSL_CONF: {
|
||||||
@ -347,6 +391,46 @@ export class ConfigService {
|
|||||||
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
|
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
|
||||||
GLOBAL_EVENTS: process.env?.WEBSOCKET_GLOBAL_EVENTS === 'true',
|
GLOBAL_EVENTS: process.env?.WEBSOCKET_GLOBAL_EVENTS === 'true',
|
||||||
},
|
},
|
||||||
|
PUSHER: {
|
||||||
|
ENABLED: process.env?.PUSHER_ENABLED === 'true',
|
||||||
|
GLOBAL: {
|
||||||
|
ENABLED: process.env?.PUSHER_GLOBAL_ENABLED === 'true',
|
||||||
|
APP_ID: process.env?.PUSHER_GLOBAL_APP_ID || '',
|
||||||
|
KEY: process.env?.PUSHER_GLOBAL_KEY || '',
|
||||||
|
SECRET: process.env?.PUSHER_GLOBAL_SECRET || '',
|
||||||
|
CLUSTER: process.env?.PUSHER_GLOBAL_CLUSTER || '',
|
||||||
|
USE_TLS: process.env?.PUSHER_GLOBAL_USE_TLS === 'true',
|
||||||
|
},
|
||||||
|
EVENTS: {
|
||||||
|
APPLICATION_STARTUP: process.env?.PUSHER_EVENTS_APPLICATION_STARTUP === 'true',
|
||||||
|
INSTANCE_CREATE: process.env?.PUSHER_EVENTS_INSTANCE_CREATE === 'true',
|
||||||
|
INSTANCE_DELETE: process.env?.PUSHER_EVENTS_INSTANCE_DELETE === 'true',
|
||||||
|
QRCODE_UPDATED: process.env?.PUSHER_EVENTS_QRCODE_UPDATED === 'true',
|
||||||
|
MESSAGES_SET: process.env?.PUSHER_EVENTS_MESSAGES_SET === 'true',
|
||||||
|
MESSAGES_UPSERT: process.env?.PUSHER_EVENTS_MESSAGES_UPSERT === 'true',
|
||||||
|
MESSAGES_EDITED: process.env?.PUSHER_EVENTS_MESSAGES_EDITED === 'true',
|
||||||
|
MESSAGES_UPDATE: process.env?.PUSHER_EVENTS_MESSAGES_UPDATE === 'true',
|
||||||
|
MESSAGES_DELETE: process.env?.PUSHER_EVENTS_MESSAGES_DELETE === 'true',
|
||||||
|
SEND_MESSAGE: process.env?.PUSHER_EVENTS_SEND_MESSAGE === 'true',
|
||||||
|
CONTACTS_SET: process.env?.PUSHER_EVENTS_CONTACTS_SET === 'true',
|
||||||
|
CONTACTS_UPDATE: process.env?.PUSHER_EVENTS_CONTACTS_UPDATE === 'true',
|
||||||
|
CONTACTS_UPSERT: process.env?.PUSHER_EVENTS_CONTACTS_UPSERT === 'true',
|
||||||
|
PRESENCE_UPDATE: process.env?.PUSHER_EVENTS_PRESENCE_UPDATE === 'true',
|
||||||
|
CHATS_SET: process.env?.PUSHER_EVENTS_CHATS_SET === 'true',
|
||||||
|
CHATS_UPDATE: process.env?.PUSHER_EVENTS_CHATS_UPDATE === 'true',
|
||||||
|
CHATS_UPSERT: process.env?.PUSHER_EVENTS_CHATS_UPSERT === 'true',
|
||||||
|
CHATS_DELETE: process.env?.PUSHER_EVENTS_CHATS_DELETE === 'true',
|
||||||
|
CONNECTION_UPDATE: process.env?.PUSHER_EVENTS_CONNECTION_UPDATE === 'true',
|
||||||
|
LABELS_EDIT: process.env?.PUSHER_EVENTS_LABELS_EDIT === 'true',
|
||||||
|
LABELS_ASSOCIATION: process.env?.PUSHER_EVENTS_LABELS_ASSOCIATION === 'true',
|
||||||
|
GROUPS_UPSERT: process.env?.PUSHER_EVENTS_GROUPS_UPSERT === 'true',
|
||||||
|
GROUP_UPDATE: process.env?.PUSHER_EVENTS_GROUPS_UPDATE === 'true',
|
||||||
|
GROUP_PARTICIPANTS_UPDATE: process.env?.PUSHER_EVENTS_GROUP_PARTICIPANTS_UPDATE === 'true',
|
||||||
|
CALL: process.env?.PUSHER_EVENTS_CALL === 'true',
|
||||||
|
TYPEBOT_START: process.env?.PUSHER_EVENTS_TYPEBOT_START === 'true',
|
||||||
|
TYPEBOT_CHANGE_STATUS: process.env?.PUSHER_EVENTS_TYPEBOT_CHANGE_STATUS === 'true',
|
||||||
|
},
|
||||||
|
},
|
||||||
WA_BUSINESS: {
|
WA_BUSINESS: {
|
||||||
TOKEN_WEBHOOK: process.env.WA_BUSINESS_TOKEN_WEBHOOK || 'evolution',
|
TOKEN_WEBHOOK: process.env.WA_BUSINESS_TOKEN_WEBHOOK || 'evolution',
|
||||||
URL: process.env.WA_BUSINESS_URL || 'https://graph.facebook.com',
|
URL: process.env.WA_BUSINESS_URL || 'https://graph.facebook.com',
|
||||||
@ -354,17 +438,9 @@ export class ConfigService {
|
|||||||
LANGUAGE: process.env.WA_BUSINESS_LANGUAGE || 'en',
|
LANGUAGE: process.env.WA_BUSINESS_LANGUAGE || 'en',
|
||||||
},
|
},
|
||||||
LOG: {
|
LOG: {
|
||||||
LEVEL: (process.env?.LOG_LEVEL?.split(',') as LogLevel[]) || [
|
LEVEL:
|
||||||
'ERROR',
|
(process.env?.LOG_LEVEL?.split(',') as LogLevel[]) ||
|
||||||
'WARN',
|
(['ERROR', 'WARN', 'DEBUG', 'INFO', 'LOG', 'VERBOSE', 'DARK', 'WEBHOOKS', 'WEBSOCKET'] as LogLevel[]),
|
||||||
'DEBUG',
|
|
||||||
'INFO',
|
|
||||||
'LOG',
|
|
||||||
'VERBOSE',
|
|
||||||
'DARK',
|
|
||||||
'WEBHOOKS',
|
|
||||||
'WEBSOCKET',
|
|
||||||
] as LogLevel[],
|
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,7 @@ const getMessageContent = (types: any) => {
|
|||||||
let result = typeKey ? types[typeKey] : undefined;
|
let result = typeKey ? types[typeKey] : undefined;
|
||||||
|
|
||||||
if (types.externalAdReplyBody) {
|
if (types.externalAdReplyBody) {
|
||||||
result = result ? `${result}\n${types.externalAdReplyBody}` : types.externalAdReplyBody;
|
result = result ? `${result}\n${types.externalAdReplyBody}` : types.externalAdReplyBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
Reference in New Issue
Block a user