mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-10 18:39:38 -06:00
refactor: remove EvolutionBot chatbot integration
Remove the EvolutionBot chatbot integration as it is no longer needed. The project now supports only external chatbot integrations: Chatwoot, Typebot, OpenAI, Dify, Flowise, N8N, and EvoAI. Changes: - Deleted EvolutionBot directory with all files (controller, service, router, dto, schema) - Removed EvolutionBot models from Prisma schemas (postgresql and mysql) - Updated ChatbotController to remove evolutionBotController.emit() call - Updated ChatbotRouter to remove EvolutionBot route - Cleaned up imports and exports in server.module.ts - Updated documentation (CLAUDE.md, AGENTS.md) Note: Prisma migrations will be created separately to drop EvolutionBot and EvolutionBotSetting tables from the database.
This commit is contained in:
parent
f7f8bf1182
commit
8884ef42d0
@ -236,7 +236,7 @@ const result = await this.prismaRepository.instance.findUnique({
|
||||
- **Base classes**: Extend `BaseChatbotService` and `BaseChatbotController`
|
||||
- **Trigger system**: Support keyword, regex, and advanced triggers
|
||||
- **Session management**: Handle conversation state per user
|
||||
- **Available integrations**: EvolutionBot, OpenAI, Dify, Typebot, Chatwoot, Flowise, N8N, EvoAI
|
||||
- **Available integrations**: OpenAI, Dify, Typebot, Chatwoot, Flowise, N8N, EvoAI
|
||||
|
||||
### Event Integration
|
||||
- **Internal events**: EventEmitter2 for application events
|
||||
|
||||
@ -101,7 +101,6 @@ src/
|
||||
- Connection lifecycle management per instance with automatic reconnection
|
||||
|
||||
**Chatbot Integrations** (`src/api/integrations/chatbot/`):
|
||||
- **EvolutionBot**: Native chatbot with trigger system
|
||||
- **Chatwoot**: Customer service platform integration
|
||||
- **Typebot**: Visual chatbot flow builder
|
||||
- **OpenAI**: AI capabilities including GPT and Whisper (audio transcription)
|
||||
|
||||
@ -102,8 +102,6 @@ model Instance {
|
||||
Dify Dify[]
|
||||
DifySetting DifySetting?
|
||||
IntegrationSession IntegrationSession[]
|
||||
EvolutionBot EvolutionBot[]
|
||||
EvolutionBotSetting EvolutionBotSetting?
|
||||
Flowise Flowise[]
|
||||
FlowiseSetting FlowiseSetting?
|
||||
N8n N8n[]
|
||||
@ -555,54 +553,6 @@ model DifySetting {
|
||||
instanceId String @unique
|
||||
}
|
||||
|
||||
model EvolutionBot {
|
||||
id String @id @default(cuid())
|
||||
enabled Boolean @default(true)
|
||||
description String? @db.VarChar(255)
|
||||
apiUrl String? @db.VarChar(255)
|
||||
apiKey String? @db.VarChar(255)
|
||||
expire Int? @default(0) @db.Int
|
||||
keywordFinish String? @db.VarChar(100)
|
||||
delayMessage Int? @db.Int
|
||||
unknownMessage String? @db.VarChar(100)
|
||||
listeningFromMe Boolean? @default(false)
|
||||
stopBotFromMe Boolean? @default(false)
|
||||
keepOpen Boolean? @default(false)
|
||||
debounceTime Int? @db.Int
|
||||
ignoreJids Json?
|
||||
splitMessages Boolean? @default(false)
|
||||
timePerChar Int? @default(50) @db.Int
|
||||
triggerType TriggerType?
|
||||
triggerOperator TriggerOperator?
|
||||
triggerValue String?
|
||||
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
instanceId String
|
||||
EvolutionBotSetting EvolutionBotSetting[]
|
||||
}
|
||||
|
||||
model EvolutionBotSetting {
|
||||
id String @id @default(cuid())
|
||||
expire Int? @default(0) @db.Int
|
||||
keywordFinish String? @db.VarChar(100)
|
||||
delayMessage Int? @db.Int
|
||||
unknownMessage String? @db.VarChar(100)
|
||||
listeningFromMe Boolean? @default(false)
|
||||
stopBotFromMe Boolean? @default(false)
|
||||
keepOpen Boolean? @default(false)
|
||||
debounceTime Int? @db.Int
|
||||
ignoreJids Json?
|
||||
splitMessages Boolean? @default(false)
|
||||
timePerChar Int? @default(50) @db.Int
|
||||
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
Fallback EvolutionBot? @relation(fields: [botIdFallback], references: [id])
|
||||
botIdFallback String? @db.VarChar(100)
|
||||
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
instanceId String @unique
|
||||
}
|
||||
|
||||
model Flowise {
|
||||
id String @id @default(cuid())
|
||||
enabled Boolean @default(true)
|
||||
|
||||
@ -102,8 +102,6 @@ model Instance {
|
||||
Dify Dify[]
|
||||
DifySetting DifySetting?
|
||||
IntegrationSession IntegrationSession[]
|
||||
EvolutionBot EvolutionBot[]
|
||||
EvolutionBotSetting EvolutionBotSetting?
|
||||
Flowise Flowise[]
|
||||
FlowiseSetting FlowiseSetting?
|
||||
Pusher Pusher?
|
||||
@ -559,54 +557,6 @@ model DifySetting {
|
||||
instanceId String @unique
|
||||
}
|
||||
|
||||
model EvolutionBot {
|
||||
id String @id @default(cuid())
|
||||
enabled Boolean @default(true) @db.Boolean
|
||||
description String? @db.VarChar(255)
|
||||
apiUrl String? @db.VarChar(255)
|
||||
apiKey String? @db.VarChar(255)
|
||||
expire Int? @default(0) @db.Integer
|
||||
keywordFinish String? @db.VarChar(100)
|
||||
delayMessage Int? @db.Integer
|
||||
unknownMessage String? @db.VarChar(100)
|
||||
listeningFromMe Boolean? @default(false) @db.Boolean
|
||||
stopBotFromMe Boolean? @default(false) @db.Boolean
|
||||
keepOpen Boolean? @default(false) @db.Boolean
|
||||
debounceTime Int? @db.Integer
|
||||
ignoreJids Json?
|
||||
splitMessages Boolean? @default(false) @db.Boolean
|
||||
timePerChar Int? @default(50) @db.Integer
|
||||
triggerType TriggerType?
|
||||
triggerOperator TriggerOperator?
|
||||
triggerValue String?
|
||||
createdAt DateTime? @default(now()) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
instanceId String
|
||||
EvolutionBotSetting EvolutionBotSetting[]
|
||||
}
|
||||
|
||||
model EvolutionBotSetting {
|
||||
id String @id @default(cuid())
|
||||
expire Int? @default(0) @db.Integer
|
||||
keywordFinish String? @db.VarChar(100)
|
||||
delayMessage Int? @db.Integer
|
||||
unknownMessage String? @db.VarChar(100)
|
||||
listeningFromMe Boolean? @default(false) @db.Boolean
|
||||
stopBotFromMe Boolean? @default(false) @db.Boolean
|
||||
keepOpen Boolean? @default(false) @db.Boolean
|
||||
debounceTime Int? @db.Integer
|
||||
ignoreJids Json?
|
||||
splitMessages Boolean? @default(false) @db.Boolean
|
||||
timePerChar Int? @default(50) @db.Integer
|
||||
createdAt DateTime? @default(now()) @db.Timestamp
|
||||
updatedAt DateTime @updatedAt @db.Timestamp
|
||||
Fallback EvolutionBot? @relation(fields: [botIdFallback], references: [id])
|
||||
botIdFallback String? @db.VarChar(100)
|
||||
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
instanceId String @unique
|
||||
}
|
||||
|
||||
model Flowise {
|
||||
id String @id @default(cuid())
|
||||
enabled Boolean @default(true) @db.Boolean
|
||||
|
||||
@ -3,7 +3,6 @@ import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import {
|
||||
difyController,
|
||||
evoaiController,
|
||||
evolutionBotController,
|
||||
flowiseController,
|
||||
n8nController,
|
||||
openaiController,
|
||||
@ -91,7 +90,6 @@ export class ChatbotController {
|
||||
pushName,
|
||||
isIntegration,
|
||||
};
|
||||
evolutionBotController.emit(emitData);
|
||||
|
||||
typebotController.emit(emitData);
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import { TypebotRouter } from '@api/integrations/chatbot/typebot/routes/typebot.
|
||||
import { Router } from 'express';
|
||||
|
||||
import { EvoaiRouter } from './evoai/routes/evoai.router';
|
||||
import { EvolutionBotRouter } from './evolutionBot/routes/evolutionBot.router';
|
||||
import { FlowiseRouter } from './flowise/routes/flowise.router';
|
||||
import { N8nRouter } from './n8n/routes/n8n.router';
|
||||
|
||||
@ -15,7 +14,6 @@ export class ChatbotRouter {
|
||||
constructor(...guards: any[]) {
|
||||
this.router = Router();
|
||||
|
||||
this.router.use('/evolutionBot', new EvolutionBotRouter(...guards).router);
|
||||
this.router.use('/chatwoot', new ChatwootRouter(...guards).router);
|
||||
this.router.use('/typebot', new TypebotRouter(...guards).router);
|
||||
this.router.use('/openai', new OpenaiRouter(...guards).router);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
export * from '@api/integrations/chatbot/chatwoot/validate/chatwoot.schema';
|
||||
export * from '@api/integrations/chatbot/dify/validate/dify.schema';
|
||||
export * from '@api/integrations/chatbot/evoai/validate/evoai.schema';
|
||||
export * from '@api/integrations/chatbot/evolutionBot/validate/evolutionBot.schema';
|
||||
export * from '@api/integrations/chatbot/flowise/validate/flowise.schema';
|
||||
export * from '@api/integrations/chatbot/n8n/validate/n8n.schema';
|
||||
export * from '@api/integrations/chatbot/openai/validate/openai.schema';
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { EvolutionBot, IntegrationSession } from '@prisma/client';
|
||||
|
||||
import { BaseChatbotController } from '../../base-chatbot.controller';
|
||||
import { EvolutionBotDto } from '../dto/evolutionBot.dto';
|
||||
import { EvolutionBotService } from '../services/evolutionBot.service';
|
||||
|
||||
export class EvolutionBotController extends BaseChatbotController<EvolutionBot, EvolutionBotDto> {
|
||||
constructor(
|
||||
private readonly evolutionBotService: EvolutionBotService,
|
||||
prismaRepository: PrismaRepository,
|
||||
waMonitor: WAMonitoringService,
|
||||
) {
|
||||
super(prismaRepository, waMonitor);
|
||||
|
||||
this.botRepository = this.prismaRepository.evolutionBot;
|
||||
this.settingsRepository = this.prismaRepository.evolutionBotSetting;
|
||||
this.sessionRepository = this.prismaRepository.integrationSession;
|
||||
}
|
||||
|
||||
public readonly logger = new Logger('EvolutionBotController');
|
||||
protected readonly integrationName = 'EvolutionBot';
|
||||
|
||||
integrationEnabled = true; // Set to true by default or use config value if available
|
||||
botRepository: any;
|
||||
settingsRepository: any;
|
||||
sessionRepository: any;
|
||||
userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } } = {};
|
||||
|
||||
// Implementation of abstract methods required by BaseChatbotController
|
||||
|
||||
protected getFallbackBotId(settings: any): string | undefined {
|
||||
return settings?.botIdFallback;
|
||||
}
|
||||
|
||||
protected getFallbackFieldName(): string {
|
||||
return 'botIdFallback';
|
||||
}
|
||||
|
||||
protected getIntegrationType(): string {
|
||||
return 'evolution';
|
||||
}
|
||||
|
||||
protected getAdditionalBotData(data: EvolutionBotDto): Record<string, any> {
|
||||
return {
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
};
|
||||
}
|
||||
|
||||
// Implementation for bot-specific updates
|
||||
protected getAdditionalUpdateFields(data: EvolutionBotDto): Record<string, any> {
|
||||
return {
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
};
|
||||
}
|
||||
|
||||
// Implementation for bot-specific duplicate validation on update
|
||||
protected async validateNoDuplicatesOnUpdate(
|
||||
botId: string,
|
||||
instanceId: string,
|
||||
data: EvolutionBotDto,
|
||||
): Promise<void> {
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: {
|
||||
not: botId,
|
||||
},
|
||||
instanceId: instanceId,
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Evolution Bot already exists');
|
||||
}
|
||||
}
|
||||
|
||||
// Process bot-specific logic
|
||||
protected async processBot(
|
||||
instance: any,
|
||||
remoteJid: string,
|
||||
bot: EvolutionBot,
|
||||
session: IntegrationSession,
|
||||
settings: any,
|
||||
content: string,
|
||||
pushName?: string,
|
||||
msg?: any,
|
||||
) {
|
||||
await this.evolutionBotService.process(instance, remoteJid, bot, session, settings, content, pushName, msg);
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
import { BaseChatbotDto, BaseChatbotSettingDto } from '../../base-chatbot.dto';
|
||||
|
||||
export class EvolutionBotDto extends BaseChatbotDto {
|
||||
apiUrl: string;
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
export class EvolutionBotSettingDto extends BaseChatbotSettingDto {
|
||||
botIdFallback?: string;
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
import { RouterBroker } from '@api/abstract/abstract.router';
|
||||
import { IgnoreJidDto } from '@api/dto/chatbot.dto';
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { HttpStatus } from '@api/routes/index.router';
|
||||
import { evolutionBotController } from '@api/server.module';
|
||||
import { instanceSchema } from '@validate/instance.schema';
|
||||
import { RequestHandler, Router } from 'express';
|
||||
|
||||
import { EvolutionBotDto, EvolutionBotSettingDto } from '../dto/evolutionBot.dto';
|
||||
import {
|
||||
evolutionBotIgnoreJidSchema,
|
||||
evolutionBotSchema,
|
||||
evolutionBotSettingSchema,
|
||||
evolutionBotStatusSchema,
|
||||
} from '../validate/evolutionBot.schema';
|
||||
|
||||
export class EvolutionBotRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('create'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<EvolutionBotDto>({
|
||||
request: req,
|
||||
schema: evolutionBotSchema,
|
||||
ClassRef: EvolutionBotDto,
|
||||
execute: (instance, data) => evolutionBotController.createBot(instance, 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) => evolutionBotController.findBot(instance),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetch/:evolutionBotId'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceSchema,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => evolutionBotController.fetchBot(instance, req.params.evolutionBotId),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.put(this.routerPath('update/:evolutionBotId'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<EvolutionBotDto>({
|
||||
request: req,
|
||||
schema: evolutionBotSchema,
|
||||
ClassRef: EvolutionBotDto,
|
||||
execute: (instance, data) => evolutionBotController.updateBot(instance, req.params.evolutionBotId, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('delete/:evolutionBotId'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceSchema,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => evolutionBotController.deleteBot(instance, req.params.evolutionBotId),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('settings'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<EvolutionBotSettingDto>({
|
||||
request: req,
|
||||
schema: evolutionBotSettingSchema,
|
||||
ClassRef: EvolutionBotSettingDto,
|
||||
execute: (instance, data) => evolutionBotController.settings(instance, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchSettings'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceSchema,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => evolutionBotController.fetchSettings(instance),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('changeStatus'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: evolutionBotStatusSchema,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance, data) => evolutionBotController.changeStatus(instance, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchSessions/:evolutionBotId'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceSchema,
|
||||
ClassRef: InstanceDto,
|
||||
execute: (instance) => evolutionBotController.fetchSessions(instance, req.params.evolutionBotId),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('ignoreJid'), ...guards, async (req, res) => {
|
||||
const response = await this.dataValidate<IgnoreJidDto>({
|
||||
request: req,
|
||||
schema: evolutionBotIgnoreJidSchema,
|
||||
ClassRef: IgnoreJidDto,
|
||||
execute: (instance, data) => evolutionBotController.ignoreJid(instance, data),
|
||||
});
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
});
|
||||
}
|
||||
|
||||
public readonly router: Router = Router();
|
||||
}
|
||||
@ -1,164 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { ConfigService, HttpServer } from '@config/env.config';
|
||||
import { EvolutionBot, EvolutionBotSetting, IntegrationSession } from '@prisma/client';
|
||||
import { sendTelemetry } from '@utils/sendTelemetry';
|
||||
import axios from 'axios';
|
||||
import { isURL } from 'class-validator';
|
||||
|
||||
import { BaseChatbotService } from '../../base-chatbot.service';
|
||||
import { OpenaiService } from '../../openai/services/openai.service';
|
||||
|
||||
export class EvolutionBotService extends BaseChatbotService<EvolutionBot, EvolutionBotSetting> {
|
||||
private openaiService: OpenaiService;
|
||||
|
||||
constructor(
|
||||
waMonitor: WAMonitoringService,
|
||||
prismaRepository: PrismaRepository,
|
||||
configService: ConfigService,
|
||||
openaiService: OpenaiService,
|
||||
) {
|
||||
super(waMonitor, prismaRepository, 'EvolutionBotService', configService);
|
||||
this.openaiService = openaiService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bot type identifier
|
||||
*/
|
||||
protected getBotType(): string {
|
||||
return 'evolution';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the Evolution Bot API
|
||||
*/
|
||||
protected async sendMessageToBot(
|
||||
instance: any,
|
||||
session: IntegrationSession,
|
||||
settings: EvolutionBotSetting,
|
||||
bot: EvolutionBot,
|
||||
remoteJid: string,
|
||||
pushName: string,
|
||||
content: string,
|
||||
msg?: any,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const payload: any = {
|
||||
inputs: {
|
||||
sessionId: session.id,
|
||||
remoteJid: remoteJid,
|
||||
pushName: pushName,
|
||||
fromMe: msg?.key?.fromMe,
|
||||
instanceName: instance.instanceName,
|
||||
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
|
||||
apiKey: instance.token,
|
||||
},
|
||||
query: content,
|
||||
conversation_id: session.sessionId === remoteJid ? undefined : session.sessionId,
|
||||
user: remoteJid,
|
||||
};
|
||||
|
||||
if (this.isAudioMessage(content) && msg) {
|
||||
try {
|
||||
this.logger.debug(`[EvolutionBot] Downloading audio for Whisper transcription`);
|
||||
const transcription = await this.openaiService.speechToText(msg, instance);
|
||||
if (transcription) {
|
||||
payload.query = `[audio] ${transcription}`;
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.error(`[EvolutionBot] Failed to transcribe audio: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isImageMessage(content) && msg) {
|
||||
const media = content.split('|');
|
||||
|
||||
if (msg.message.mediaUrl || msg.message.base64) {
|
||||
payload.files = [
|
||||
{
|
||||
type: 'image',
|
||||
url: msg.message.base64 || msg.message.mediaUrl,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
payload.files = [
|
||||
{
|
||||
type: 'image',
|
||||
url: media[1].split('?')[0],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
payload.query = media[2] || content;
|
||||
}
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const endpoint = bot.apiUrl;
|
||||
|
||||
if (!endpoint) {
|
||||
this.logger.error('No Evolution Bot endpoint defined');
|
||||
return;
|
||||
}
|
||||
|
||||
let headers: any = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
if (bot.apiKey) {
|
||||
headers = {
|
||||
...headers,
|
||||
Authorization: `Bearer ${bot.apiKey}`,
|
||||
};
|
||||
}
|
||||
|
||||
// Sanitize payload for logging (remove sensitive data)
|
||||
const sanitizedPayload = {
|
||||
...payload,
|
||||
inputs: {
|
||||
...payload.inputs,
|
||||
apiKey: payload.inputs.apiKey ? '[REDACTED]' : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers,
|
||||
});
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
}
|
||||
|
||||
let message = response?.data?.message;
|
||||
const rawLinkPreview = response?.data?.linkPreview;
|
||||
|
||||
// Validate linkPreview is boolean and default to true for backward compatibility
|
||||
const linkPreview = typeof rawLinkPreview === 'boolean' ? rawLinkPreview : true;
|
||||
|
||||
if (message && typeof message === 'string' && message.startsWith("'") && message.endsWith("'")) {
|
||||
const innerContent = message.slice(1, -1);
|
||||
if (!innerContent.includes("'")) {
|
||||
message = innerContent;
|
||||
}
|
||||
}
|
||||
|
||||
if (message) {
|
||||
// Use the base class method that handles splitMessages functionality
|
||||
await this.sendMessageWhatsApp(instance, remoteJid, message, settings, linkPreview);
|
||||
} else {
|
||||
this.logger.warn(`[EvolutionBot] No message content received from bot response`);
|
||||
}
|
||||
|
||||
// Send telemetry
|
||||
sendTelemetry('/message/sendText');
|
||||
} catch (error) {
|
||||
this.logger.error(`Error in sendMessageToBot: ${error.message || JSON.stringify(error)}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
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 evolutionBotSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
properties: {
|
||||
enabled: { type: 'boolean' },
|
||||
description: { type: 'string' },
|
||||
apiUrl: { type: 'string' },
|
||||
apiKey: { type: 'string' },
|
||||
triggerType: { type: 'string', enum: ['all', 'keyword', 'none', 'advanced'] },
|
||||
triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] },
|
||||
triggerValue: { type: 'string' },
|
||||
expire: { type: 'integer' },
|
||||
keywordFinish: { type: 'string' },
|
||||
delayMessage: { type: 'integer' },
|
||||
unknownMessage: { type: 'string' },
|
||||
listeningFromMe: { type: 'boolean' },
|
||||
stopBotFromMe: { type: 'boolean' },
|
||||
keepOpen: { type: 'boolean' },
|
||||
debounceTime: { type: 'integer' },
|
||||
ignoreJids: { type: 'array', items: { type: 'string' } },
|
||||
splitMessages: { type: 'boolean' },
|
||||
timePerChar: { type: 'integer' },
|
||||
},
|
||||
required: ['enabled', 'apiUrl', 'triggerType'],
|
||||
...isNotEmpty('enabled', 'apiUrl', 'triggerType'),
|
||||
};
|
||||
|
||||
export const evolutionBotStatusSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
properties: {
|
||||
remoteJid: { type: 'string' },
|
||||
status: { type: 'string', enum: ['opened', 'closed', 'paused', 'delete'] },
|
||||
},
|
||||
required: ['remoteJid', 'status'],
|
||||
...isNotEmpty('remoteJid', 'status'),
|
||||
};
|
||||
|
||||
export const evolutionBotSettingSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
properties: {
|
||||
expire: { type: 'integer' },
|
||||
keywordFinish: { type: 'string' },
|
||||
delayMessage: { type: 'integer' },
|
||||
unknownMessage: { type: 'string' },
|
||||
listeningFromMe: { type: 'boolean' },
|
||||
stopBotFromMe: { type: 'boolean' },
|
||||
keepOpen: { type: 'boolean' },
|
||||
debounceTime: { type: 'integer' },
|
||||
ignoreJids: { type: 'array', items: { type: 'string' } },
|
||||
botIdFallback: { type: 'string' },
|
||||
splitMessages: { type: 'boolean' },
|
||||
timePerChar: { type: 'integer' },
|
||||
},
|
||||
required: [
|
||||
'expire',
|
||||
'keywordFinish',
|
||||
'delayMessage',
|
||||
'unknownMessage',
|
||||
'listeningFromMe',
|
||||
'stopBotFromMe',
|
||||
'keepOpen',
|
||||
'debounceTime',
|
||||
'ignoreJids',
|
||||
'splitMessages',
|
||||
'timePerChar',
|
||||
],
|
||||
...isNotEmpty(
|
||||
'expire',
|
||||
'keywordFinish',
|
||||
'delayMessage',
|
||||
'unknownMessage',
|
||||
'listeningFromMe',
|
||||
'stopBotFromMe',
|
||||
'keepOpen',
|
||||
'debounceTime',
|
||||
'ignoreJids',
|
||||
'splitMessages',
|
||||
'timePerChar',
|
||||
),
|
||||
};
|
||||
|
||||
export const evolutionBotIgnoreJidSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
properties: {
|
||||
remoteJid: { type: 'string' },
|
||||
action: { type: 'string', enum: ['add', 'remove'] },
|
||||
},
|
||||
required: ['remoteJid', 'action'],
|
||||
...isNotEmpty('remoteJid', 'action'),
|
||||
};
|
||||
@ -23,8 +23,6 @@ import { DifyController } from './integrations/chatbot/dify/controllers/dify.con
|
||||
import { DifyService } from './integrations/chatbot/dify/services/dify.service';
|
||||
import { EvoaiController } from './integrations/chatbot/evoai/controllers/evoai.controller';
|
||||
import { EvoaiService } from './integrations/chatbot/evoai/services/evoai.service';
|
||||
import { EvolutionBotController } from './integrations/chatbot/evolutionBot/controllers/evolutionBot.controller';
|
||||
import { EvolutionBotService } from './integrations/chatbot/evolutionBot/services/evolutionBot.service';
|
||||
import { FlowiseController } from './integrations/chatbot/flowise/controllers/flowise.controller';
|
||||
import { FlowiseService } from './integrations/chatbot/flowise/services/flowise.service';
|
||||
import { N8nController } from './integrations/chatbot/n8n/controllers/n8n.controller';
|
||||
@ -124,9 +122,6 @@ export const typebotController = new TypebotController(typebotService, prismaRep
|
||||
const difyService = new DifyService(waMonitor, prismaRepository, configService, openaiService);
|
||||
export const difyController = new DifyController(difyService, prismaRepository, waMonitor);
|
||||
|
||||
const evolutionBotService = new EvolutionBotService(waMonitor, prismaRepository, configService, openaiService);
|
||||
export const evolutionBotController = new EvolutionBotController(evolutionBotService, prismaRepository, waMonitor);
|
||||
|
||||
const flowiseService = new FlowiseService(waMonitor, prismaRepository, configService, openaiService);
|
||||
export const flowiseController = new FlowiseController(flowiseService, prismaRepository, waMonitor);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user