refactor: chatbot integration

This commit is contained in:
Davidson Gomes 2024-08-21 13:37:22 -03:00
parent 8876797172
commit edeb1efd2a
13 changed files with 1957 additions and 2627 deletions

View File

@ -60,13 +60,11 @@ import {
configService,
ConfigSessionPhone,
Database,
Dify,
Log,
Openai,
ProviderSession,
QrCode,
S3,
Typebot,
} from '@config/env.config';
import { BadRequestException, InternalServerErrorException, NotFoundException } from '@exceptions';
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
@ -2012,35 +2010,12 @@ export class BaileysStartupService extends ChannelStartupService {
);
}
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled && isIntegration) {
if (this.configService.get<Typebot>('TYPEBOT').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.typebotService.sendTypebot(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw,
);
}
if (this.configService.get<Openai>('OPENAI').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw.pushName,
messageRaw,
);
}
if (this.configService.get<Dify>('DIFY').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.difyService.sendDify(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw,
);
}
}
await chatbotController.emit({
instance: { instanceName: this.instance.name, instanceId: this.instanceId },
remoteJid: messageRaw.key.remoteJid,
msg: messageRaw,
pushName: messageRaw.pushName,
});
if (this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE)
await this.prismaRepository.message.create({

View File

@ -20,7 +20,7 @@ import { chatbotController } from '@api/server.module';
import { CacheService } from '@api/services/cache.service';
import { ChannelStartupService } from '@api/services/channel.service';
import { Events, wa } from '@api/types/wa.types';
import { Chatwoot, ConfigService, Database, Dify, Openai, S3, Typebot, WaBusiness } from '@config/env.config';
import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@config/env.config';
import { BadRequestException, InternalServerErrorException } from '@exceptions';
import axios from 'axios';
import { arrayUnique, isURL } from 'class-validator';
@ -923,35 +923,12 @@ export class BusinessStartupService extends ChannelStartupService {
);
}
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled && isIntegration) {
if (this.configService.get<Typebot>('TYPEBOT').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.typebotService.sendTypebot(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw,
);
}
if (this.configService.get<Openai>('OPENAI').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.openaiService.sendOpenai(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw.pushName,
messageRaw,
);
}
if (this.configService.get<Dify>('DIFY').ENABLED) {
if (messageRaw.messageType !== 'reactionMessage')
await this.difyService.sendDify(
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw,
);
}
}
await chatbotController.emit({
instance: { instanceName: this.instance.name, instanceId: this.instanceId },
remoteJid: messageRaw.key.remoteJid,
msg: messageRaw,
pushName: messageRaw.pushName,
});
await this.prismaRepository.message.create({
data: messageRaw,

View File

@ -6,6 +6,36 @@ import { Logger } from '@config/logger.config';
import { IntegrationSession } from '@prisma/client';
import { findBotByTrigger } from '@utils/findBotByTrigger';
export type EmitData = {
instance: InstanceDto;
remoteJid: string;
msg: any;
pushName?: string;
};
export interface ChatbotControllerInterface {
integrationEnabled: boolean;
botRepository: any;
settingsRepository: any;
sessionRepository: any;
userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } };
createBot(instance: InstanceDto, data: any): Promise<any>;
findBot(instance: InstanceDto): Promise<any>;
fetchBot(instance: InstanceDto, botId: string): Promise<any>;
updateBot(instance: InstanceDto, botId: string, data: any): Promise<any>;
deleteBot(instance: InstanceDto, botId: string): Promise<any>;
settings(instance: InstanceDto, data: any): Promise<any>;
fetchSettings(instance: InstanceDto): Promise<any>;
changeStatus(instance: InstanceDto, botId: string, status: string): Promise<any>;
fetchSessions(instance: InstanceDto, botId: string, remoteJid?: string): Promise<any>;
ignoreJid(instance: InstanceDto, data: any): Promise<any>;
emit(data: EmitData): Promise<void>;
}
export class ChatbotController {
public prismaRepository: PrismaRepository;
public waMonitor: WAMonitoringService;

View File

@ -1,84 +1,825 @@
import { IgnoreJidDto } from '@api/dto/chatbot.dto';
import { InstanceDto } from '@api/dto/instance.dto';
import { DifyDto, DifyIgnoreJidDto } from '@api/integrations/chatbot/dify/dto/dify.dto';
import { DifyDto } from '@api/integrations/chatbot/dify/dto/dify.dto';
import { DifyService } from '@api/integrations/chatbot/dify/services/dify.service';
import { PrismaRepository } from '@api/repository/repository.service';
import { WAMonitoringService } from '@api/services/monitor.service';
import { configService, Dify } from '@config/env.config';
import { Logger } from '@config/logger.config';
import { BadRequestException } from '@exceptions';
import { getConversationMessage } from '@utils/getConversationMessage';
export class DifyController {
constructor(private readonly difyService: DifyService) {}
import { ChatbotController, ChatbotControllerInterface, EmitData } from '../../chatbot.controller';
public async createDify(instance: InstanceDto, data: DifyDto) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
export class DifyController extends ChatbotController implements ChatbotControllerInterface {
constructor(
private readonly difyService: DifyService,
prismaRepository: PrismaRepository,
waMonitor: WAMonitoringService,
) {
super(prismaRepository, waMonitor);
return this.difyService.create(instance, data);
this.botRepository = this.prismaRepository.dify;
this.settingsRepository = this.prismaRepository.difySetting;
this.sessionRepository = this.prismaRepository.integrationSession;
}
public async findDify(instance: InstanceDto) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public readonly logger = new Logger(DifyController.name);
return this.difyService.find(instance);
integrationEnabled = configService.get<Dify>('DIFY').ENABLED;
botRepository: any;
settingsRepository: any;
sessionRepository: any;
userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } } = {};
// Bots
public async createBot(instance: InstanceDto, data: DifyDto) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
const instanceId = await this.prismaRepository.instance
.findFirst({
where: {
name: instance.instanceName,
},
})
.then((instance) => instance.id);
if (
!data.expire ||
!data.keywordFinish ||
!data.delayMessage ||
!data.unknownMessage ||
!data.listeningFromMe ||
!data.stopBotFromMe ||
!data.keepOpen ||
!data.debounceTime ||
!data.ignoreJids
) {
const defaultSettingCheck = await this.settingsRepository.findFirst({
where: {
instanceId: instanceId,
},
});
if (!data.expire) data.expire = defaultSettingCheck?.expire || 0;
if (!data.keywordFinish) data.keywordFinish = defaultSettingCheck?.keywordFinish || '';
if (!data.delayMessage) data.delayMessage = defaultSettingCheck?.delayMessage || 1000;
if (!data.unknownMessage) data.unknownMessage = defaultSettingCheck?.unknownMessage || '';
if (!data.listeningFromMe) data.listeningFromMe = defaultSettingCheck?.listeningFromMe || false;
if (!data.stopBotFromMe) data.stopBotFromMe = defaultSettingCheck?.stopBotFromMe || false;
if (!data.keepOpen) data.keepOpen = defaultSettingCheck?.keepOpen || false;
if (!data.debounceTime) data.debounceTime = defaultSettingCheck?.debounceTime || 0;
if (!data.ignoreJids) data.ignoreJids = defaultSettingCheck?.ignoreJids || [];
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,
});
}
}
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 dify with an "All" trigger, you cannot have more bots while it is active');
}
const checkDuplicate = await this.botRepository.findFirst({
where: {
instanceId: instanceId,
botType: data.botType,
apiUrl: data.apiUrl,
apiKey: data.apiKey,
},
});
if (checkDuplicate) {
throw new Error('Dify 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,
botType: data.botType,
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,
},
});
return bot;
} catch (error) {
this.logger.error(error);
throw new Error('Error creating dify');
}
}
public async fetchDify(instance: InstanceDto, difyId: string) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public async findBot(instance: InstanceDto) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.fetch(instance, difyId);
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;
}
public async updateDify(instance: InstanceDto, difyId: string, data: DifyDto) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public async fetchBot(instance: InstanceDto, botId: string) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.update(instance, difyId, data);
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('Dify not found');
}
if (bot.instanceId !== instanceId) {
throw new Error('Dify not found');
}
return bot;
}
public async deleteDify(instance: InstanceDto, difyId: string) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public async updateBot(instance: InstanceDto, botId: string, data: DifyDto) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.delete(instance, difyId);
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('Dify not found');
}
if (bot.instanceId !== instanceId) {
throw new Error('Dify 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 dify with an "All" trigger, you cannot have more bots while it is active');
}
}
const checkDuplicate = await this.botRepository.findFirst({
where: {
id: {
not: botId,
},
instanceId: instanceId,
botType: data.botType,
apiUrl: data.apiUrl,
apiKey: data.apiKey,
},
});
if (checkDuplicate) {
throw new Error('Dify 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,
botType: data.botType,
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,
},
});
return bot;
} catch (error) {
this.logger.error(error);
throw new Error('Error updating dify');
}
}
public async deleteBot(instance: InstanceDto, botId: string) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
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('Dify not found');
}
if (bot.instanceId !== instanceId) {
throw new Error('Dify 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 dify bot');
}
}
// Settings
public async settings(instance: InstanceDto, data: any) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.setDefaultSettings(instance, data);
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,
difyIdFallback: data.difyIdFallback,
ignoreJids: data.ignoreJids,
},
});
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,
difyIdFallback: updateSettings.difyIdFallback,
ignoreJids: updateSettings.ignoreJids,
};
}
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,
difyIdFallback: data.difyIdFallback,
ignoreJids: data.ignoreJids,
instanceId: instanceId,
},
});
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,
difyIdFallback: newSetttings.difyIdFallback,
ignoreJids: newSetttings.ignoreJids,
};
} catch (error) {
this.logger.error(error);
throw new Error('Error setting default settings');
}
}
public async fetchSettings(instance: InstanceDto) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.fetchDefaultSettings(instance);
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: [],
difyIdFallback: '',
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,
difyIdFallback: settings.difyIdFallback,
fallback: settings.Fallback,
};
} catch (error) {
this.logger.error(error);
throw new Error('Error fetching default settings');
}
}
// Sessions
public async changeStatus(instance: InstanceDto, data: any) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.changeStatus(instance, data);
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, difyId: string) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public async fetchSessions(instance: InstanceDto, botId: string, remoteJid?: string) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.fetchSessions(instance, difyId);
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 },
},
});
} catch (error) {
this.logger.error(error);
throw new Error('Error fetching sessions');
}
}
public async ignoreJid(instance: InstanceDto, data: DifyIgnoreJidDto) {
if (!configService.get<Dify>('DIFY').ENABLED) throw new BadRequestException('Dify is disabled');
public async ignoreJid(instance: InstanceDto, data: IgnoreJidDto) {
if (!this.integrationEnabled) throw new BadRequestException('Dify is disabled');
return this.difyService.ignoreJid(instance, data);
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');
}
}
public async emit({
instance,
remoteJid,
msg,
}: {
instance: InstanceDto;
remoteJid: string;
msg: any;
pushName?: string;
}) {
if (!configService.get<Dify>('DIFY').ENABLED) return;
// Emit
public async emit({ instance, remoteJid, msg }: EmitData) {
if (!this.integrationEnabled) return;
await this.difyService.sendDify(instance, remoteJid, msg);
try {
const settings = await this.prismaRepository.difySetting.findFirst({
where: {
instanceId: instance.instanceId,
},
});
if (this.checkIgnoreJids(settings?.ignoreJids, remoteJid)) return;
const session = await this.getSession(remoteJid, instance);
const content = getConversationMessage(msg);
const findBot = await this.findBotTrigger(
this.botRepository,
this.settingsRepository,
content,
instance,
session,
);
if (!findBot) 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;
if (
!expire ||
!keywordFinish ||
!delayMessage ||
!unknownMessage ||
!listeningFromMe ||
!stopBotFromMe ||
!keepOpen ||
!debounceTime
) {
if (!expire) expire = settings.expire;
if (!keywordFinish) keywordFinish = settings.keywordFinish;
if (!delayMessage) delayMessage = settings.delayMessage;
if (!unknownMessage) unknownMessage = settings.unknownMessage;
if (!listeningFromMe) listeningFromMe = settings.listeningFromMe;
if (!stopBotFromMe) stopBotFromMe = settings.stopBotFromMe;
if (!keepOpen) keepOpen = settings.keepOpen;
if (!debounceTime) debounceTime = settings.debounceTime;
}
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 (debounceTime && debounceTime > 0) {
this.processDebounce(this.userMessageDebounce, content, remoteJid, debounceTime, async (debouncedContent) => {
await this.difyService.processDify(
this.waMonitor.waInstances[instance.instanceName],
remoteJid,
findBot,
session,
settings,
debouncedContent,
msg?.pushName,
);
});
} else {
await this.difyService.processDify(
this.waMonitor.waInstances[instance.instanceName],
remoteJid,
findBot,
session,
settings,
content,
msg?.pushName,
);
}
return;
} catch (error) {
this.logger.error(error);
return;
}
}
}

View File

@ -1,13 +1,5 @@
import { $Enums, TriggerOperator, TriggerType } from '@prisma/client';
export class Session {
remoteJid?: string;
sessionId?: string;
status?: string;
createdAt?: number;
updateAt?: number;
}
export class DifyDto {
enabled?: boolean;
description?: string;
@ -40,8 +32,3 @@ export class DifySettingDto {
difyIdFallback?: string;
ignoreJids?: any;
}
export class DifyIgnoreJidDto {
remoteJid?: string;
action?: string;
}

View File

@ -1,6 +1,7 @@
import { RouterBroker } from '@api/abstract/abstract.router';
import { IgnoreJidDto } from '@api/dto/chatbot.dto';
import { InstanceDto } from '@api/dto/instance.dto';
import { DifyDto, DifyIgnoreJidDto, DifySettingDto } from '@api/integrations/chatbot/dify/dto/dify.dto';
import { DifyDto, DifySettingDto } from '@api/integrations/chatbot/dify/dto/dify.dto';
import { HttpStatus } from '@api/routes/index.router';
import { difyController } from '@api/server.module';
import {
@ -21,7 +22,7 @@ export class DifyRouter extends RouterBroker {
request: req,
schema: difySchema,
ClassRef: DifyDto,
execute: (instance, data) => difyController.createDify(instance, data),
execute: (instance, data) => difyController.createBot(instance, data),
});
res.status(HttpStatus.CREATED).json(response);
@ -31,7 +32,7 @@ export class DifyRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => difyController.findDify(instance),
execute: (instance) => difyController.findBot(instance),
});
res.status(HttpStatus.OK).json(response);
@ -41,7 +42,7 @@ export class DifyRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => difyController.fetchDify(instance, req.params.difyId),
execute: (instance) => difyController.fetchBot(instance, req.params.difyId),
});
res.status(HttpStatus.OK).json(response);
@ -51,7 +52,7 @@ export class DifyRouter extends RouterBroker {
request: req,
schema: difySchema,
ClassRef: DifyDto,
execute: (instance, data) => difyController.updateDify(instance, req.params.difyId, data),
execute: (instance, data) => difyController.updateBot(instance, req.params.difyId, data),
});
res.status(HttpStatus.OK).json(response);
@ -61,7 +62,7 @@ export class DifyRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => difyController.deleteDify(instance, req.params.difyId),
execute: (instance) => difyController.deleteBot(instance, req.params.difyId),
});
res.status(HttpStatus.OK).json(response);
@ -107,10 +108,10 @@ export class DifyRouter extends RouterBroker {
res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('ignoreJid'), ...guards, async (req, res) => {
const response = await this.dataValidate<DifyIgnoreJidDto>({
const response = await this.dataValidate<IgnoreJidDto>({
request: req,
schema: difyIgnoreJidSchema,
ClassRef: DifyIgnoreJidDto,
ClassRef: IgnoreJidDto,
execute: (instance, data) => difyController.ignoreJid(instance, data),
});

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,9 @@ import { BadRequestException } from '@exceptions';
import { getConversationMessage } from '@utils/getConversationMessage';
import OpenAI from 'openai';
import { ChatbotController } from '../../chatbot.controller';
import { ChatbotController, ChatbotControllerInterface, EmitData } from '../../chatbot.controller';
export class OpenaiController extends ChatbotController {
export class OpenaiController extends ChatbotController implements ChatbotControllerInterface {
constructor(
private readonly openaiService: OpenaiService,
prismaRepository: PrismaRepository,
@ -28,13 +28,13 @@ export class OpenaiController extends ChatbotController {
public readonly logger = new Logger(OpenaiController.name);
private integrationEnabled = configService.get<Openai>('OPENAI').ENABLED;
integrationEnabled = configService.get<Openai>('OPENAI').ENABLED;
botRepository: any;
settingsRepository: any;
sessionRepository: any;
userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } } = {};
private client: OpenAI;
private botRepository: any;
private settingsRepository: any;
private sessionRepository: any;
private credsRepository: any;
private userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } } = {};
// Credentials
public async createOpenaiCreds(instance: InstanceDto, data: OpenaiCredsDto) {
@ -311,7 +311,7 @@ export class OpenaiController extends ChatbotController {
}
try {
const openaiBot = await this.botRepository.create({
const bot = await this.botRepository.create({
data: {
enabled: data.enabled,
description: data.description,
@ -340,7 +340,7 @@ export class OpenaiController extends ChatbotController {
},
});
return openaiBot;
return bot;
} catch (error) {
this.logger.error(error);
throw new Error('Error creating openai bot');
@ -358,7 +358,7 @@ export class OpenaiController extends ChatbotController {
})
.then((instance) => instance.id);
const openaiBots = await this.botRepository.findMany({
const bots = await this.botRepository.findMany({
where: {
instanceId,
},
@ -367,11 +367,11 @@ export class OpenaiController extends ChatbotController {
},
});
if (!openaiBots.length) {
if (!bots.length) {
return null;
}
return openaiBots;
return bots;
}
public async fetchBot(instance: InstanceDto, botId: string) {
@ -385,7 +385,7 @@ export class OpenaiController extends ChatbotController {
})
.then((instance) => instance.id);
const openaiBot = await this.botRepository.findFirst({
const bot = await this.botRepository.findFirst({
where: {
id: botId,
},
@ -394,15 +394,15 @@ export class OpenaiController extends ChatbotController {
},
});
if (!openaiBot) {
if (!bot) {
throw new Error('Openai Bot not found');
}
if (openaiBot.instanceId !== instanceId) {
if (bot.instanceId !== instanceId) {
throw new Error('Openai Bot not found');
}
return openaiBot;
return bot;
}
public async updateBot(instance: InstanceDto, botId: string, data: OpenaiDto) {
@ -416,17 +416,17 @@ export class OpenaiController extends ChatbotController {
})
.then((instance) => instance.id);
const openaiBot = await this.botRepository.findFirst({
const bot = await this.botRepository.findFirst({
where: {
id: botId,
},
});
if (!openaiBot) {
if (!bot) {
throw new Error('Openai Bot not found');
}
if (openaiBot.instanceId !== instanceId) {
if (bot.instanceId !== instanceId) {
throw new Error('Openai Bot not found');
}
@ -522,7 +522,7 @@ export class OpenaiController extends ChatbotController {
}
try {
const openaiBot = await this.botRepository.update({
const bot = await this.botRepository.update({
where: {
id: botId,
},
@ -553,7 +553,7 @@ export class OpenaiController extends ChatbotController {
},
});
return openaiBot;
return bot;
} catch (error) {
this.logger.error(error);
throw new Error('Error updating openai bot');
@ -571,17 +571,17 @@ export class OpenaiController extends ChatbotController {
})
.then((instance) => instance.id);
const openaiBot = await this.botRepository.findFirst({
const bot = await this.botRepository.findFirst({
where: {
id: botId,
},
});
if (!openaiBot) {
if (!bot) {
throw new Error('Openai bot not found');
}
if (openaiBot.instanceId !== instanceId) {
if (bot.instanceId !== instanceId) {
throw new Error('Openai bot not found');
}
try {
@ -597,7 +597,7 @@ export class OpenaiController extends ChatbotController {
},
});
return { openaiBot: { id: botId } };
return { bot: { id: botId } };
} catch (error) {
this.logger.error(error);
throw new Error('Error deleting openai bot');
@ -925,17 +925,7 @@ export class OpenaiController extends ChatbotController {
}
// Emit
public async emit({
instance,
remoteJid,
msg,
pushName,
}: {
instance: InstanceDto;
remoteJid: string;
msg: any;
pushName?: string;
}) {
public async emit({ instance, remoteJid, msg, pushName }: EmitData) {
if (!this.integrationEnabled) return;
try {

View File

@ -1,14 +1,5 @@
import { TriggerOperator, TriggerType } from '@prisma/client';
export class Session {
remoteJid?: string;
sessionId?: string;
status?: string;
createdAt?: number;
updateAt?: number;
prefilledVariables?: PrefilledVariables;
}
export class PrefilledVariables {
remoteJid?: string;
pushName?: string;
@ -47,8 +38,3 @@ export class TypebotSettingDto {
typebotIdFallback?: string;
ignoreJids?: any;
}
export class TypebotIgnoreJidDto {
remoteJid?: string;
action?: string;
}

View File

@ -1,8 +1,9 @@
import { RouterBroker } from '@api/abstract/abstract.router';
import { IgnoreJidDto } from '@api/dto/chatbot.dto';
import { InstanceDto } from '@api/dto/instance.dto';
import { TypebotDto, TypebotIgnoreJidDto, TypebotSettingDto } from '@api/integrations/chatbot/typebot/dto/typebot.dto';
import { typebotController } from '@api/server.module';
import { TypebotDto, TypebotSettingDto } from '@api/integrations/chatbot/typebot/dto/typebot.dto';
import { HttpStatus } from '@api/routes/index.router';
import { typebotController } from '@api/server.module';
import {
instanceSchema,
typebotIgnoreJidSchema,
@ -22,7 +23,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: typebotSchema,
ClassRef: TypebotDto,
execute: (instance, data) => typebotController.createTypebot(instance, data),
execute: (instance, data) => typebotController.createBot(instance, data),
});
res.status(HttpStatus.CREATED).json(response);
@ -32,7 +33,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => typebotController.findTypebot(instance),
execute: (instance) => typebotController.findBot(instance),
});
res.status(HttpStatus.OK).json(response);
@ -42,7 +43,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => typebotController.fetchTypebot(instance, req.params.typebotId),
execute: (instance) => typebotController.fetchBot(instance, req.params.typebotId),
});
res.status(HttpStatus.OK).json(response);
@ -52,7 +53,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: typebotSchema,
ClassRef: TypebotDto,
execute: (instance, data) => typebotController.updateTypebot(instance, req.params.typebotId, data),
execute: (instance, data) => typebotController.updateBot(instance, req.params.typebotId, data),
});
res.status(HttpStatus.OK).json(response);
@ -62,7 +63,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: instanceSchema,
ClassRef: InstanceDto,
execute: (instance) => typebotController.deleteTypebot(instance, req.params.typebotId),
execute: (instance) => typebotController.deleteBot(instance, req.params.typebotId),
});
res.status(HttpStatus.OK).json(response);
@ -92,7 +93,7 @@ export class TypebotRouter extends RouterBroker {
request: req,
schema: typebotStartSchema,
ClassRef: InstanceDto,
execute: (instance, data) => typebotController.startTypebot(instance, data),
execute: (instance, data) => typebotController.startBot(instance, data),
});
res.status(HttpStatus.OK).json(response);
@ -118,10 +119,10 @@ export class TypebotRouter extends RouterBroker {
res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('ignoreJid'), ...guards, async (req, res) => {
const response = await this.dataValidate<TypebotIgnoreJidDto>({
const response = await this.dataValidate<IgnoreJidDto>({
request: req,
schema: typebotIgnoreJidSchema,
ClassRef: TypebotIgnoreJidDto,
ClassRef: IgnoreJidDto,
execute: (instance, data) => typebotController.ignoreJid(instance, data),
});

View File

@ -108,12 +108,12 @@ export const webhookController = new WebhookController(prismaRepository, waMonit
// chatbots
const typebotService = new TypebotService(waMonitor, configService, prismaRepository);
export const typebotController = new TypebotController(typebotService);
export const typebotController = new TypebotController(typebotService, prismaRepository, waMonitor);
const openaiService = new OpenaiService(waMonitor, configService, prismaRepository);
export const openaiController = new OpenaiController(openaiService);
export const openaiController = new OpenaiController(openaiService, prismaRepository, waMonitor);
const difyService = new DifyService(waMonitor, configService, prismaRepository);
export const difyController = new DifyController(difyService);
export const difyController = new DifyController(difyService, prismaRepository, waMonitor);
logger.info('Module - ON');