mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-26 15:17:44 -06:00
refactor(chatbot): unify keywordFinish type and enhance session handling
- Changed the type of `keywordFinish` from an array to a string in multiple DTOs and controller interfaces to simplify data handling. - Updated the `BaseChatbotService` to include logic for updating session status to 'opened' and managing user responses more effectively. - Refactored the media message handling in the `BaseChatbotService` to streamline the process and improve readability. - Enhanced error logging across various services to ensure better traceability during operations. This commit focuses on improving the structure and consistency of chatbot integrations while ensuring that session management is robust and user-friendly.
This commit is contained in:
@@ -1,16 +1,13 @@
|
||||
import { IgnoreJidDto } from '@api/dto/chatbot.dto';
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { Flowise } from '@prisma/client';
|
||||
import { getConversationMessage } from '@utils/getConversationMessage';
|
||||
import { Flowise, IntegrationSession } from '@prisma/client';
|
||||
|
||||
import { ChatbotController, ChatbotControllerInterface, EmitData } from '../../chatbot.controller';
|
||||
import { BaseChatbotController } from '../../base-chatbot.controller';
|
||||
import { FlowiseDto } from '../dto/flowise.dto';
|
||||
import { FlowiseService } from '../services/flowise.service';
|
||||
|
||||
export class FlowiseController extends ChatbotController implements ChatbotControllerInterface {
|
||||
export class FlowiseController extends BaseChatbotController<Flowise, FlowiseDto> {
|
||||
constructor(
|
||||
private readonly flowiseService: FlowiseService,
|
||||
prismaRepository: PrismaRepository,
|
||||
@@ -24,258 +21,45 @@ export class FlowiseController extends ChatbotController implements ChatbotContr
|
||||
}
|
||||
|
||||
public readonly logger = new Logger('FlowiseController');
|
||||
protected readonly integrationName = 'Flowise';
|
||||
|
||||
integrationEnabled: boolean;
|
||||
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 } } = {};
|
||||
|
||||
// Bots
|
||||
public async createBot(instance: InstanceDto, data: FlowiseDto) {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
// Implementation of abstract methods required by BaseChatbotController
|
||||
|
||||
if (
|
||||
!data.expire ||
|
||||
!data.keywordFinish ||
|
||||
!data.delayMessage ||
|
||||
!data.unknownMessage ||
|
||||
!data.listeningFromMe ||
|
||||
!data.stopBotFromMe ||
|
||||
!data.keepOpen ||
|
||||
!data.debounceTime ||
|
||||
!data.ignoreJids ||
|
||||
!data.splitMessages ||
|
||||
!data.timePerChar
|
||||
) {
|
||||
const defaultSettingCheck = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (data.expire === undefined || data.expire === null) data.expire = defaultSettingCheck.expire;
|
||||
if (data.keywordFinish === undefined || data.keywordFinish === null)
|
||||
data.keywordFinish = defaultSettingCheck.keywordFinish;
|
||||
if (data.delayMessage === undefined || data.delayMessage === null)
|
||||
data.delayMessage = defaultSettingCheck.delayMessage;
|
||||
if (data.unknownMessage === undefined || data.unknownMessage === null)
|
||||
data.unknownMessage = defaultSettingCheck.unknownMessage;
|
||||
if (data.listeningFromMe === undefined || data.listeningFromMe === null)
|
||||
data.listeningFromMe = defaultSettingCheck.listeningFromMe;
|
||||
if (data.stopBotFromMe === undefined || data.stopBotFromMe === null)
|
||||
data.stopBotFromMe = defaultSettingCheck.stopBotFromMe;
|
||||
if (data.keepOpen === undefined || data.keepOpen === null) data.keepOpen = defaultSettingCheck.keepOpen;
|
||||
if (data.debounceTime === undefined || data.debounceTime === null)
|
||||
data.debounceTime = defaultSettingCheck.debounceTime;
|
||||
if (data.ignoreJids === undefined || data.ignoreJids === null) data.ignoreJids = defaultSettingCheck.ignoreJids;
|
||||
if (data.splitMessages === undefined || data.splitMessages === null)
|
||||
data.splitMessages = defaultSettingCheck?.splitMessages ?? false;
|
||||
if (data.timePerChar === undefined || data.timePerChar === null)
|
||||
data.timePerChar = defaultSettingCheck?.timePerChar ?? 0;
|
||||
|
||||
if (!defaultSettingCheck) {
|
||||
await this.settings(instance, {
|
||||
expire: data.expire,
|
||||
keywordFinish: data.keywordFinish,
|
||||
delayMessage: data.delayMessage,
|
||||
unknownMessage: data.unknownMessage,
|
||||
listeningFromMe: data.listeningFromMe,
|
||||
stopBotFromMe: data.stopBotFromMe,
|
||||
keepOpen: data.keepOpen,
|
||||
debounceTime: data.debounceTime,
|
||||
ignoreJids: data.ignoreJids,
|
||||
splitMessages: data.splitMessages,
|
||||
timePerChar: data.timePerChar,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const checkTriggerAll = await this.botRepository.findFirst({
|
||||
where: {
|
||||
enabled: true,
|
||||
triggerType: 'all',
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkTriggerAll && data.triggerType === 'all') {
|
||||
throw new Error('You already have a Flowise with an "All" trigger, you cannot have more bots while it is active');
|
||||
}
|
||||
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Flowise already exists');
|
||||
}
|
||||
|
||||
if (data.triggerType === 'keyword') {
|
||||
if (!data.triggerOperator || !data.triggerValue) {
|
||||
throw new Error('Trigger operator and value are required');
|
||||
}
|
||||
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
triggerOperator: data.triggerOperator,
|
||||
triggerValue: data.triggerValue,
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Trigger already exists');
|
||||
}
|
||||
}
|
||||
|
||||
if (data.triggerType === 'advanced') {
|
||||
if (!data.triggerValue) {
|
||||
throw new Error('Trigger value is required');
|
||||
}
|
||||
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
triggerValue: data.triggerValue,
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Trigger already exists');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const bot = await this.botRepository.create({
|
||||
data: {
|
||||
enabled: data?.enabled,
|
||||
description: data.description,
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
expire: data.expire,
|
||||
keywordFinish: data.keywordFinish,
|
||||
delayMessage: data.delayMessage,
|
||||
unknownMessage: data.unknownMessage,
|
||||
listeningFromMe: data.listeningFromMe,
|
||||
stopBotFromMe: data.stopBotFromMe,
|
||||
keepOpen: data.keepOpen,
|
||||
debounceTime: data.debounceTime,
|
||||
instanceId: instanceId,
|
||||
triggerType: data.triggerType,
|
||||
triggerOperator: data.triggerOperator,
|
||||
triggerValue: data.triggerValue,
|
||||
ignoreJids: data.ignoreJids,
|
||||
splitMessages: data.splitMessages,
|
||||
timePerChar: data.timePerChar,
|
||||
},
|
||||
});
|
||||
|
||||
return bot;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error creating bot');
|
||||
}
|
||||
protected getFallbackBotId(settings: any): string | undefined {
|
||||
return settings?.flowiseIdFallback;
|
||||
}
|
||||
|
||||
public async findBot(instance: InstanceDto) {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const bots = await this.botRepository.findMany({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!bots.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return bots;
|
||||
protected getFallbackFieldName(): string {
|
||||
return 'flowiseIdFallback';
|
||||
}
|
||||
|
||||
public async fetchBot(instance: InstanceDto, botId: string) {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const bot = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!bot) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
|
||||
if (bot.instanceId !== instanceId) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
|
||||
return bot;
|
||||
protected getIntegrationType(): string {
|
||||
return 'flowise';
|
||||
}
|
||||
|
||||
public async updateBot(instance: InstanceDto, botId: string, data: FlowiseDto) {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
protected getAdditionalBotData(data: FlowiseDto): Record<string, any> {
|
||||
return {
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
};
|
||||
}
|
||||
|
||||
const bot = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!bot) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
|
||||
if (bot.instanceId !== instanceId) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
|
||||
if (data.triggerType === 'all') {
|
||||
const checkTriggerAll = await this.botRepository.findFirst({
|
||||
where: {
|
||||
enabled: true,
|
||||
triggerType: 'all',
|
||||
id: {
|
||||
not: botId,
|
||||
},
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkTriggerAll) {
|
||||
throw new Error('You already have a bot with an "All" trigger, you cannot have more bots while it is active');
|
||||
}
|
||||
}
|
||||
// Implementation for bot-specific updates
|
||||
protected getAdditionalUpdateFields(data: FlowiseDto): 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: FlowiseDto): Promise<void> {
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: {
|
||||
@@ -288,573 +72,20 @@ export class FlowiseController extends ChatbotController implements ChatbotContr
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Bot already exists');
|
||||
}
|
||||
|
||||
if (data.triggerType === 'keyword') {
|
||||
if (!data.triggerOperator || !data.triggerValue) {
|
||||
throw new Error('Trigger operator and value are required');
|
||||
}
|
||||
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
triggerOperator: data.triggerOperator,
|
||||
triggerValue: data.triggerValue,
|
||||
id: { not: botId },
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Trigger already exists');
|
||||
}
|
||||
}
|
||||
|
||||
if (data.triggerType === 'advanced') {
|
||||
if (!data.triggerValue) {
|
||||
throw new Error('Trigger value is required');
|
||||
}
|
||||
|
||||
const checkDuplicate = await this.botRepository.findFirst({
|
||||
where: {
|
||||
triggerValue: data.triggerValue,
|
||||
id: { not: botId },
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (checkDuplicate) {
|
||||
throw new Error('Trigger already exists');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const bot = await this.botRepository.update({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
data: {
|
||||
enabled: data?.enabled,
|
||||
description: data.description,
|
||||
apiUrl: data.apiUrl,
|
||||
apiKey: data.apiKey,
|
||||
expire: data.expire,
|
||||
keywordFinish: data.keywordFinish,
|
||||
delayMessage: data.delayMessage,
|
||||
unknownMessage: data.unknownMessage,
|
||||
listeningFromMe: data.listeningFromMe,
|
||||
stopBotFromMe: data.stopBotFromMe,
|
||||
keepOpen: data.keepOpen,
|
||||
debounceTime: data.debounceTime,
|
||||
instanceId: instanceId,
|
||||
triggerType: data.triggerType,
|
||||
triggerOperator: data.triggerOperator,
|
||||
triggerValue: data.triggerValue,
|
||||
ignoreJids: data.ignoreJids,
|
||||
splitMessages: data.splitMessages,
|
||||
timePerChar: data.timePerChar,
|
||||
},
|
||||
});
|
||||
|
||||
return bot;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error updating bot');
|
||||
throw new Error('Flowise already exists');
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteBot(instance: InstanceDto, botId: string) {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const bot = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!bot) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
|
||||
if (bot.instanceId !== instanceId) {
|
||||
throw new Error('Bot not found');
|
||||
}
|
||||
try {
|
||||
await this.prismaRepository.integrationSession.deleteMany({
|
||||
where: {
|
||||
botId: botId,
|
||||
},
|
||||
});
|
||||
|
||||
await this.botRepository.delete({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
});
|
||||
|
||||
return { bot: { id: botId } };
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error deleting bot');
|
||||
}
|
||||
}
|
||||
|
||||
// Settings
|
||||
public async settings(instance: InstanceDto, data: any) {
|
||||
try {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const settings = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (settings) {
|
||||
const updateSettings = await this.settingsRepository.update({
|
||||
where: {
|
||||
id: settings.id,
|
||||
},
|
||||
data: {
|
||||
expire: data.expire,
|
||||
keywordFinish: data.keywordFinish,
|
||||
delayMessage: data.delayMessage,
|
||||
unknownMessage: data.unknownMessage,
|
||||
listeningFromMe: data.listeningFromMe,
|
||||
stopBotFromMe: data.stopBotFromMe,
|
||||
keepOpen: data.keepOpen,
|
||||
debounceTime: data.debounceTime,
|
||||
flowiseIdFallback: data.flowiseIdFallback,
|
||||
ignoreJids: data.ignoreJids,
|
||||
splitMessages: data.splitMessages,
|
||||
timePerChar: data.timePerChar,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
expire: updateSettings.expire,
|
||||
keywordFinish: updateSettings.keywordFinish,
|
||||
delayMessage: updateSettings.delayMessage,
|
||||
unknownMessage: updateSettings.unknownMessage,
|
||||
listeningFromMe: updateSettings.listeningFromMe,
|
||||
stopBotFromMe: updateSettings.stopBotFromMe,
|
||||
keepOpen: updateSettings.keepOpen,
|
||||
debounceTime: updateSettings.debounceTime,
|
||||
flowiseIdFallback: updateSettings.flowiseIdFallback,
|
||||
ignoreJids: updateSettings.ignoreJids,
|
||||
splitMessages: updateSettings.splitMessages,
|
||||
timePerChar: updateSettings.timePerChar,
|
||||
};
|
||||
}
|
||||
|
||||
const newSetttings = await this.settingsRepository.create({
|
||||
data: {
|
||||
expire: data.expire,
|
||||
keywordFinish: data.keywordFinish,
|
||||
delayMessage: data.delayMessage,
|
||||
unknownMessage: data.unknownMessage,
|
||||
listeningFromMe: data.listeningFromMe,
|
||||
stopBotFromMe: data.stopBotFromMe,
|
||||
keepOpen: data.keepOpen,
|
||||
debounceTime: data.debounceTime,
|
||||
flowiseIdFallback: data.flowiseIdFallback,
|
||||
ignoreJids: data.ignoreJids,
|
||||
instanceId: instanceId,
|
||||
splitMessages: data.splitMessages,
|
||||
timePerChar: data.timePerChar,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
expire: newSetttings.expire,
|
||||
keywordFinish: newSetttings.keywordFinish,
|
||||
delayMessage: newSetttings.delayMessage,
|
||||
unknownMessage: newSetttings.unknownMessage,
|
||||
listeningFromMe: newSetttings.listeningFromMe,
|
||||
stopBotFromMe: newSetttings.stopBotFromMe,
|
||||
keepOpen: newSetttings.keepOpen,
|
||||
debounceTime: newSetttings.debounceTime,
|
||||
flowiseIdFallback: newSetttings.flowiseIdFallback,
|
||||
ignoreJids: newSetttings.ignoreJids,
|
||||
splitMessages: newSetttings.splitMessages,
|
||||
timePerChar: newSetttings.timePerChar,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error setting default settings');
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchSettings(instance: InstanceDto) {
|
||||
try {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const settings = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
},
|
||||
include: {
|
||||
Fallback: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!settings) {
|
||||
return {
|
||||
expire: 0,
|
||||
keywordFinish: '',
|
||||
delayMessage: 0,
|
||||
unknownMessage: '',
|
||||
listeningFromMe: false,
|
||||
stopBotFromMe: false,
|
||||
keepOpen: false,
|
||||
ignoreJids: [],
|
||||
splitMessages: false,
|
||||
timePerChar: 0,
|
||||
flowiseIdFallback: '',
|
||||
fallback: null,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
expire: settings.expire,
|
||||
keywordFinish: settings.keywordFinish,
|
||||
delayMessage: settings.delayMessage,
|
||||
unknownMessage: settings.unknownMessage,
|
||||
listeningFromMe: settings.listeningFromMe,
|
||||
stopBotFromMe: settings.stopBotFromMe,
|
||||
keepOpen: settings.keepOpen,
|
||||
ignoreJids: settings.ignoreJids,
|
||||
splitMessages: settings.splitMessages,
|
||||
timePerChar: settings.timePerChar,
|
||||
flowiseIdFallback: settings.flowiseIdFallback,
|
||||
fallback: settings.Fallback,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error fetching default settings');
|
||||
}
|
||||
}
|
||||
|
||||
// Sessions
|
||||
public async changeStatus(instance: InstanceDto, data: any) {
|
||||
try {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const defaultSettingCheck = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
const remoteJid = data.remoteJid;
|
||||
const status = data.status;
|
||||
|
||||
if (status === 'delete') {
|
||||
await this.sessionRepository.deleteMany({
|
||||
where: {
|
||||
remoteJid: remoteJid,
|
||||
botId: { not: null },
|
||||
},
|
||||
});
|
||||
|
||||
return { bot: { remoteJid: remoteJid, status: status } };
|
||||
}
|
||||
|
||||
if (status === 'closed') {
|
||||
if (defaultSettingCheck?.keepOpen) {
|
||||
await this.sessionRepository.updateMany({
|
||||
where: {
|
||||
remoteJid: remoteJid,
|
||||
botId: { not: null },
|
||||
},
|
||||
data: {
|
||||
status: 'closed',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await this.sessionRepository.deleteMany({
|
||||
where: {
|
||||
remoteJid: remoteJid,
|
||||
botId: { not: null },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return { bot: { ...instance, bot: { remoteJid: remoteJid, status: status } } };
|
||||
} else {
|
||||
const session = await this.sessionRepository.updateMany({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
remoteJid: remoteJid,
|
||||
botId: { not: null },
|
||||
},
|
||||
data: {
|
||||
status: status,
|
||||
},
|
||||
});
|
||||
|
||||
const botData = {
|
||||
remoteJid: remoteJid,
|
||||
status: status,
|
||||
session,
|
||||
};
|
||||
|
||||
return { bot: { ...instance, bot: botData } };
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error changing status');
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchSessions(instance: InstanceDto, botId: string, remoteJid?: string) {
|
||||
try {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const bot = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: botId,
|
||||
},
|
||||
});
|
||||
|
||||
if (bot && bot.instanceId !== instanceId) {
|
||||
throw new Error('Dify not found');
|
||||
}
|
||||
|
||||
return await this.sessionRepository.findMany({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
remoteJid,
|
||||
botId: bot ? botId : { not: null },
|
||||
type: 'flowise',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error fetching sessions');
|
||||
}
|
||||
}
|
||||
|
||||
public async ignoreJid(instance: InstanceDto, data: IgnoreJidDto) {
|
||||
try {
|
||||
const instanceId = await this.prismaRepository.instance
|
||||
.findFirst({
|
||||
where: {
|
||||
name: instance.instanceName,
|
||||
},
|
||||
})
|
||||
.then((instance) => instance.id);
|
||||
|
||||
const settings = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!settings) {
|
||||
throw new Error('Settings not found');
|
||||
}
|
||||
|
||||
let ignoreJids: any = settings?.ignoreJids || [];
|
||||
|
||||
if (data.action === 'add') {
|
||||
if (ignoreJids.includes(data.remoteJid)) return { ignoreJids: ignoreJids };
|
||||
|
||||
ignoreJids.push(data.remoteJid);
|
||||
} else {
|
||||
ignoreJids = ignoreJids.filter((jid) => jid !== data.remoteJid);
|
||||
}
|
||||
|
||||
const updateSettings = await this.settingsRepository.update({
|
||||
where: {
|
||||
id: settings.id,
|
||||
},
|
||||
data: {
|
||||
ignoreJids: ignoreJids,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
ignoreJids: updateSettings.ignoreJids,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new Error('Error setting default settings');
|
||||
}
|
||||
}
|
||||
|
||||
// Emit
|
||||
public async emit({ instance, remoteJid, msg }: EmitData) {
|
||||
try {
|
||||
const settings = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instance.instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (this.checkIgnoreJids(settings?.ignoreJids, remoteJid)) return;
|
||||
|
||||
const session = await this.getSession(remoteJid, instance);
|
||||
|
||||
const content = getConversationMessage(msg);
|
||||
|
||||
let findBot = (await this.findBotTrigger(this.botRepository, content, instance, session)) as Flowise;
|
||||
|
||||
if (!findBot) {
|
||||
const fallback = await this.settingsRepository.findFirst({
|
||||
where: {
|
||||
instanceId: instance.instanceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (fallback?.flowiseIdFallback) {
|
||||
const findFallback = await this.botRepository.findFirst({
|
||||
where: {
|
||||
id: fallback.flowiseIdFallback,
|
||||
},
|
||||
});
|
||||
|
||||
findBot = findFallback;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let expire = findBot?.expire;
|
||||
let keywordFinish = findBot?.keywordFinish;
|
||||
let delayMessage = findBot?.delayMessage;
|
||||
let unknownMessage = findBot?.unknownMessage;
|
||||
let listeningFromMe = findBot?.listeningFromMe;
|
||||
let stopBotFromMe = findBot?.stopBotFromMe;
|
||||
let keepOpen = findBot?.keepOpen;
|
||||
let debounceTime = findBot?.debounceTime;
|
||||
let ignoreJids = findBot?.ignoreJids;
|
||||
let splitMessages = findBot?.splitMessages;
|
||||
let timePerChar = findBot?.timePerChar;
|
||||
|
||||
if (expire === undefined || expire === null) expire = settings.expire;
|
||||
if (keywordFinish === undefined || keywordFinish === null) keywordFinish = settings.keywordFinish;
|
||||
if (delayMessage === undefined || delayMessage === null) delayMessage = settings.delayMessage;
|
||||
if (unknownMessage === undefined || unknownMessage === null) unknownMessage = settings.unknownMessage;
|
||||
if (listeningFromMe === undefined || listeningFromMe === null) listeningFromMe = settings.listeningFromMe;
|
||||
if (stopBotFromMe === undefined || stopBotFromMe === null) stopBotFromMe = settings.stopBotFromMe;
|
||||
if (keepOpen === undefined || keepOpen === null) keepOpen = settings.keepOpen;
|
||||
if (debounceTime === undefined || debounceTime === null) debounceTime = settings.debounceTime;
|
||||
if (ignoreJids === undefined || ignoreJids === null) ignoreJids = settings.ignoreJids;
|
||||
if (splitMessages === undefined || splitMessages === null) splitMessages = settings?.splitMessages ?? false;
|
||||
if (timePerChar === undefined || timePerChar === null) timePerChar = settings?.timePerChar ?? 0;
|
||||
|
||||
const key = msg.key as {
|
||||
id: string;
|
||||
remoteJid: string;
|
||||
fromMe: boolean;
|
||||
participant: string;
|
||||
};
|
||||
|
||||
if (stopBotFromMe && key.fromMe && session) {
|
||||
await this.prismaRepository.integrationSession.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
status: 'paused',
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!listeningFromMe && key.fromMe) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session && !session.awaitUser) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (debounceTime && debounceTime > 0) {
|
||||
this.processDebounce(this.userMessageDebounce, content, remoteJid, debounceTime, async (debouncedContent) => {
|
||||
await this.flowiseService.processBot(
|
||||
this.waMonitor.waInstances[instance.instanceName],
|
||||
remoteJid,
|
||||
findBot,
|
||||
session,
|
||||
{
|
||||
...settings,
|
||||
expire,
|
||||
keywordFinish,
|
||||
delayMessage,
|
||||
unknownMessage,
|
||||
listeningFromMe,
|
||||
stopBotFromMe,
|
||||
keepOpen,
|
||||
debounceTime,
|
||||
ignoreJids,
|
||||
splitMessages,
|
||||
timePerChar,
|
||||
},
|
||||
debouncedContent,
|
||||
msg?.pushName,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
await this.flowiseService.processBot(
|
||||
this.waMonitor.waInstances[instance.instanceName],
|
||||
remoteJid,
|
||||
findBot,
|
||||
session,
|
||||
{
|
||||
...settings,
|
||||
expire,
|
||||
keywordFinish,
|
||||
delayMessage,
|
||||
unknownMessage,
|
||||
listeningFromMe,
|
||||
stopBotFromMe,
|
||||
keepOpen,
|
||||
debounceTime,
|
||||
ignoreJids,
|
||||
splitMessages,
|
||||
timePerChar,
|
||||
},
|
||||
content,
|
||||
msg?.pushName,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
return;
|
||||
}
|
||||
// Process bot-specific logic
|
||||
protected async processBot(
|
||||
instance: any,
|
||||
remoteJid: string,
|
||||
bot: Flowise,
|
||||
session: IntegrationSession,
|
||||
settings: any,
|
||||
content: string,
|
||||
pushName?: string,
|
||||
) {
|
||||
await this.flowiseService.process(instance, remoteJid, bot, session, settings, content, pushName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { TriggerOperator, TriggerType } from '@prisma/client';
|
||||
|
||||
export class FlowiseDto {
|
||||
import { BaseChatbotDto, BaseChatbotSettingDto } from '../../base-chatbot.dto';
|
||||
|
||||
export class FlowiseDto extends BaseChatbotDto {
|
||||
apiUrl: string;
|
||||
apiKey: string;
|
||||
description: string;
|
||||
keywordFinish?: string | null;
|
||||
triggerType: TriggerType;
|
||||
enabled?: boolean;
|
||||
description?: string;
|
||||
apiUrl?: string;
|
||||
apiKey?: string;
|
||||
expire?: number;
|
||||
keywordFinish?: string;
|
||||
delayMessage?: number;
|
||||
unknownMessage?: string;
|
||||
listeningFromMe?: boolean;
|
||||
stopBotFromMe?: boolean;
|
||||
keepOpen?: boolean;
|
||||
debounceTime?: number;
|
||||
triggerType?: TriggerType;
|
||||
triggerOperator?: TriggerOperator;
|
||||
triggerValue?: string;
|
||||
ignoreJids?: any;
|
||||
@@ -21,9 +23,9 @@ export class FlowiseDto {
|
||||
timePerChar?: number;
|
||||
}
|
||||
|
||||
export class FlowiseSettingDto {
|
||||
export class FlowiseSettingDto extends BaseChatbotSettingDto {
|
||||
expire?: number;
|
||||
keywordFinish?: string;
|
||||
keywordFinish?: string | null;
|
||||
delayMessage?: number;
|
||||
unknownMessage?: string;
|
||||
listeningFromMe?: boolean;
|
||||
|
||||
@@ -1,425 +1,111 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { Auth, ConfigService, HttpServer } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { Flowise, FlowiseSetting, IntegrationSession } from '@prisma/client';
|
||||
import { sendTelemetry } from '@utils/sendTelemetry';
|
||||
import axios from 'axios';
|
||||
|
||||
export class FlowiseService {
|
||||
constructor(
|
||||
private readonly waMonitor: WAMonitoringService,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly prismaRepository: PrismaRepository,
|
||||
) {}
|
||||
import { BaseChatbotService } from '../../base-chatbot.service';
|
||||
|
||||
private readonly logger = new Logger('FlowiseService');
|
||||
export class FlowiseService extends BaseChatbotService<Flowise, FlowiseSetting> {
|
||||
constructor(waMonitor: WAMonitoringService, configService: ConfigService, prismaRepository: PrismaRepository) {
|
||||
super(waMonitor, prismaRepository, 'FlowiseService', configService);
|
||||
}
|
||||
|
||||
public async createNewSession(instance: InstanceDto, data: any) {
|
||||
/**
|
||||
* Get the bot type identifier
|
||||
*/
|
||||
protected getBotType(): string {
|
||||
return 'flowise';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the Flowise API
|
||||
*/
|
||||
protected async sendMessageToBot(
|
||||
instance: any,
|
||||
session: IntegrationSession,
|
||||
settings: FlowiseSetting,
|
||||
bot: Flowise,
|
||||
remoteJid: string,
|
||||
pushName: string,
|
||||
content: string,
|
||||
msg?: any,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const session = await this.prismaRepository.integrationSession.create({
|
||||
data: {
|
||||
remoteJid: data.remoteJid,
|
||||
pushName: data.pushName,
|
||||
sessionId: data.remoteJid,
|
||||
status: 'opened',
|
||||
awaitUser: false,
|
||||
botId: data.botId,
|
||||
instanceId: instance.instanceId,
|
||||
type: 'flowise',
|
||||
},
|
||||
});
|
||||
|
||||
return { session };
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private isImageMessage(content: string) {
|
||||
return content.includes('imageMessage');
|
||||
}
|
||||
|
||||
private async sendMessageToBot(instance: any, bot: Flowise, remoteJid: string, pushName: string, content: string) {
|
||||
const payload: any = {
|
||||
question: content,
|
||||
overrideConfig: {
|
||||
sessionId: remoteJid,
|
||||
vars: {
|
||||
remoteJid: remoteJid,
|
||||
pushName: pushName,
|
||||
instanceName: instance.instanceName,
|
||||
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
|
||||
apiKey: this.configService.get<Auth>('AUTHENTICATION').API_KEY.KEY,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (this.isImageMessage(content)) {
|
||||
const contentSplit = content.split('|');
|
||||
|
||||
payload.uploads = [
|
||||
{
|
||||
data: contentSplit[1].split('?')[0],
|
||||
type: 'url',
|
||||
name: 'Flowise.png',
|
||||
mime: 'image/png',
|
||||
},
|
||||
];
|
||||
payload.question = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
let headers: any = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
if (bot.apiKey) {
|
||||
headers = {
|
||||
...headers,
|
||||
Authorization: `Bearer ${bot.apiKey}`,
|
||||
};
|
||||
}
|
||||
|
||||
const endpoint = bot.apiUrl;
|
||||
|
||||
if (!endpoint) return null;
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers,
|
||||
});
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.text;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private async sendMessageWhatsApp(
|
||||
instance: any,
|
||||
remoteJid: string,
|
||||
session: IntegrationSession,
|
||||
settings: FlowiseSetting,
|
||||
message: string,
|
||||
) {
|
||||
const linkRegex = /(!?)\[(.*?)\]\((.*?)\)/g;
|
||||
|
||||
let textBuffer = '';
|
||||
let lastIndex = 0;
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
const getMediaType = (url: string): string | null => {
|
||||
const extension = url.split('.').pop()?.toLowerCase();
|
||||
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
|
||||
const audioExtensions = ['mp3', 'wav', 'aac', 'ogg'];
|
||||
const videoExtensions = ['mp4', 'avi', 'mkv', 'mov'];
|
||||
const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'];
|
||||
|
||||
if (imageExtensions.includes(extension || '')) return 'image';
|
||||
if (audioExtensions.includes(extension || '')) return 'audio';
|
||||
if (videoExtensions.includes(extension || '')) return 'video';
|
||||
if (documentExtensions.includes(extension || '')) return 'document';
|
||||
return null;
|
||||
};
|
||||
|
||||
while ((match = linkRegex.exec(message)) !== null) {
|
||||
const [fullMatch, exclMark, altText, url] = match;
|
||||
const mediaType = getMediaType(url);
|
||||
|
||||
const beforeText = message.slice(lastIndex, match.index);
|
||||
if (beforeText) {
|
||||
textBuffer += beforeText;
|
||||
}
|
||||
|
||||
if (mediaType) {
|
||||
const splitMessages = settings.splitMessages ?? false;
|
||||
const timePerChar = settings.timePerChar ?? 0;
|
||||
const minDelay = 1000;
|
||||
const maxDelay = 20000;
|
||||
|
||||
if (textBuffer.trim()) {
|
||||
if (splitMessages) {
|
||||
const multipleMessages = textBuffer.trim().split('\n\n');
|
||||
|
||||
for (let index = 0; index < multipleMessages.length; index++) {
|
||||
const message = multipleMessages[index];
|
||||
|
||||
const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay);
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(async () => {
|
||||
await instance.textMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
text: message,
|
||||
},
|
||||
false,
|
||||
);
|
||||
resolve();
|
||||
}, delay);
|
||||
});
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await instance.textMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
text: textBuffer.trim(),
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
textBuffer = '';
|
||||
}
|
||||
|
||||
if (mediaType === 'audio') {
|
||||
await instance.audioWhatsapp({
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
audio: url,
|
||||
caption: altText,
|
||||
});
|
||||
} else {
|
||||
await instance.mediaMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
mediatype: mediaType,
|
||||
media: url,
|
||||
caption: altText,
|
||||
},
|
||||
null,
|
||||
false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
textBuffer += `[${altText}](${url})`;
|
||||
}
|
||||
|
||||
lastIndex = linkRegex.lastIndex;
|
||||
}
|
||||
|
||||
if (lastIndex < message.length) {
|
||||
const remainingText = message.slice(lastIndex);
|
||||
if (remainingText.trim()) {
|
||||
textBuffer += remainingText;
|
||||
}
|
||||
}
|
||||
|
||||
const splitMessages = settings.splitMessages ?? false;
|
||||
const timePerChar = settings.timePerChar ?? 0;
|
||||
const minDelay = 1000;
|
||||
const maxDelay = 20000;
|
||||
|
||||
if (textBuffer.trim()) {
|
||||
if (splitMessages) {
|
||||
const multipleMessages = textBuffer.trim().split('\n\n');
|
||||
|
||||
for (let index = 0; index < multipleMessages.length; index++) {
|
||||
const message = multipleMessages[index];
|
||||
|
||||
const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay);
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(async () => {
|
||||
await instance.textMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
text: message,
|
||||
},
|
||||
false,
|
||||
);
|
||||
resolve();
|
||||
}, delay);
|
||||
});
|
||||
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await instance.textMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings?.delayMessage || 1000,
|
||||
text: textBuffer.trim(),
|
||||
const payload: any = {
|
||||
question: content,
|
||||
overrideConfig: {
|
||||
sessionId: remoteJid,
|
||||
vars: {
|
||||
remoteJid: remoteJid,
|
||||
pushName: pushName,
|
||||
instanceName: instance.instanceName,
|
||||
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
|
||||
apiKey: this.configService.get<Auth>('AUTHENTICATION').API_KEY.KEY,
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
if (this.isImageMessage(content)) {
|
||||
const contentSplit = content.split('|');
|
||||
|
||||
payload.uploads = [
|
||||
{
|
||||
data: contentSplit[1].split('?')[0],
|
||||
type: 'url',
|
||||
name: 'Flowise.png',
|
||||
mime: 'image/png',
|
||||
},
|
||||
];
|
||||
payload.question = contentSplit[2] || content;
|
||||
}
|
||||
textBuffer = '';
|
||||
}
|
||||
|
||||
sendTelemetry('/message/sendText');
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
await this.prismaRepository.integrationSession.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
status: 'opened',
|
||||
awaitUser: true,
|
||||
},
|
||||
});
|
||||
let headers: any = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
if (bot.apiKey) {
|
||||
headers = {
|
||||
...headers,
|
||||
Authorization: `Bearer ${bot.apiKey}`,
|
||||
};
|
||||
}
|
||||
|
||||
private async initNewSession(
|
||||
instance: any,
|
||||
remoteJid: string,
|
||||
bot: Flowise,
|
||||
settings: FlowiseSetting,
|
||||
session: IntegrationSession,
|
||||
content: string,
|
||||
pushName?: string,
|
||||
) {
|
||||
const data = await this.createNewSession(instance, {
|
||||
remoteJid,
|
||||
pushName,
|
||||
botId: bot.id,
|
||||
});
|
||||
const endpoint = bot.apiUrl;
|
||||
|
||||
if (data.session) {
|
||||
session = data.session;
|
||||
}
|
||||
|
||||
const message = await this.sendMessageToBot(instance, bot, remoteJid, pushName, content);
|
||||
|
||||
await this.sendMessageWhatsApp(instance, remoteJid, session, settings, message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public async processBot(
|
||||
instance: any,
|
||||
remoteJid: string,
|
||||
bot: Flowise,
|
||||
session: IntegrationSession,
|
||||
settings: FlowiseSetting,
|
||||
content: string,
|
||||
pushName?: string,
|
||||
) {
|
||||
if (session && session.status !== 'opened') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session && settings.expire && settings.expire > 0) {
|
||||
const now = Date.now();
|
||||
|
||||
const sessionUpdatedAt = new Date(session.updatedAt).getTime();
|
||||
|
||||
const diff = now - sessionUpdatedAt;
|
||||
|
||||
const diffInMinutes = Math.floor(diff / 1000 / 60);
|
||||
|
||||
if (diffInMinutes > settings.expire) {
|
||||
if (settings.keepOpen) {
|
||||
await this.prismaRepository.integrationSession.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
status: 'closed',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await this.prismaRepository.integrationSession.deleteMany({
|
||||
where: {
|
||||
botId: bot.id,
|
||||
remoteJid: remoteJid,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await this.initNewSession(instance, remoteJid, bot, settings, session, content, pushName);
|
||||
if (!endpoint) {
|
||||
this.logger.error('No Flowise endpoint defined');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
await this.initNewSession(instance, remoteJid, bot, settings, session, content, pushName);
|
||||
return;
|
||||
}
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers,
|
||||
});
|
||||
|
||||
await this.prismaRepository.integrationSession.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
status: 'opened',
|
||||
awaitUser: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (!content) {
|
||||
if (settings.unknownMessage) {
|
||||
this.waMonitor.waInstances[instance.instanceName].textMessage(
|
||||
{
|
||||
number: remoteJid.split('@')[0],
|
||||
delay: settings.delayMessage || 1000,
|
||||
text: settings.unknownMessage,
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
||||
sendTelemetry('/message/sendText');
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.keywordFinish && content.toLowerCase() === settings.keywordFinish.toLowerCase()) {
|
||||
if (settings.keepOpen) {
|
||||
await this.prismaRepository.integrationSession.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
status: 'closed',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await this.prismaRepository.integrationSession.deleteMany({
|
||||
where: {
|
||||
botId: bot.id,
|
||||
remoteJid: remoteJid,
|
||||
},
|
||||
});
|
||||
const message = response?.data?.text;
|
||||
|
||||
if (message) {
|
||||
// Use the base class method to send the message to WhatsApp
|
||||
await this.sendMessageWhatsApp(instance, remoteJid, message, settings);
|
||||
}
|
||||
|
||||
// Send telemetry
|
||||
sendTelemetry('/message/sendText');
|
||||
} catch (error) {
|
||||
this.logger.error(`Error in sendMessageToBot: ${error.message || JSON.stringify(error)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const message = await this.sendMessageToBot(instance, bot, remoteJid, pushName, content);
|
||||
|
||||
await this.sendMessageWhatsApp(instance, remoteJid, session, settings, message);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user