integrations

This commit is contained in:
Davidson Gomes 2024-06-08 10:31:52 -03:00
parent cbb5d1d048
commit de89f03f13
7 changed files with 145 additions and 287 deletions

View File

@ -72,7 +72,6 @@ model Session {
model Chat {
id Int @id @default(autoincrement())
remoteJid String @db.VarChar(100)
lastMsgTimestamp String? @db.VarChar(100)
labels Json? @db.JsonB
createdAt DateTime? @default(now()) @db.Date
updatedAt DateTime? @updatedAt @db.Date
@ -100,7 +99,7 @@ model Message {
message Json @db.JsonB
contextInfo Json? @db.JsonB
source DeviceMessage
messageTimestamp String @db.VarChar(100)
messageTimestamp Int @db.Integer
chatwootMessageId Int? @db.Integer
chatwootInboxId Int? @db.Integer
chatwootConversationId Int? @db.Integer
@ -119,7 +118,7 @@ model MessageUpdate {
remoteJid String @db.VarChar(100)
fromMe Boolean @db.Boolean
participant String? @db.VarChar(100)
dateTime DateTime @db.Date
dateTime Int @db.Integer
pollUpdates Json? @db.JsonB
status String @db.VarChar(30)
Message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)

View File

@ -18,8 +18,8 @@ export class TypebotController {
} else {
const saveData = await this.typebotService.find(instance);
if (saveData.enabled) {
data.sessions = saveData.sessions;
if (saveData?.typebot?.enabled) {
data.sessions = saveData?.sessions;
}
}

View File

@ -2,9 +2,10 @@ import { Message } from '@prisma/client';
import axios from 'axios';
import EventEmitter2 from 'eventemitter2';
import { ConfigService, Typebot } from '../../../../config/env.config';
import { Auth, ConfigService, Typebot } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { PrismaRepository } from '../../../repository/repository.service';
import { WAMonitoringService } from '../../../services/monitor.service';
import { Events } from '../../../types/wa.types';
import { TypebotDto } from '../dto/typebot.dto';
@ -13,6 +14,7 @@ export class TypebotService {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly configService: ConfigService,
private readonly prismaRepository: PrismaRepository,
private readonly eventEmitter: EventEmitter2,
) {
this.eventEmitter.on('typebot:end', async (data) => {
@ -31,17 +33,26 @@ export class TypebotService {
return { typebot: { ...instance, typebot: data } };
}
public async find(instance: InstanceDto): Promise<TypebotDto> {
public async find(instance: InstanceDto): Promise<any> {
try {
const result = await this.waMonitor.waInstances[instance.instanceName].findTypebot();
const typebot = await this.waMonitor.waInstances[instance.instanceName].findTypebot();
if (Object.keys(result).length === 0) {
if (Object.keys(typebot).length === 0) {
throw new Error('Typebot not found');
}
return result;
const sessions = await this.prismaRepository.typebotSession.findMany({
where: {
typebotId: typebot.id,
},
});
return {
typebot,
sessions,
};
} catch (error) {
return { enabled: false, url: '', typebot: '', expire: 0, sessions: [] };
return null;
}
}
@ -51,96 +62,55 @@ export class TypebotService {
const findData = await this.find(instance);
const session = findData.sessions.find((session) => session.remoteJid === remoteJid);
if (session) {
if (status === 'closed') {
findData.sessions.splice(findData.sessions.indexOf(session), 1);
const typebotData = {
enabled: findData.enabled,
url: findData.url,
typebot: findData.typebot,
expire: findData.expire,
keywordFinish: findData.keywordFinish,
delayMessage: findData.delayMessage,
unknownMessage: findData.unknownMessage,
listeningFromMe: findData.listeningFromMe,
sessions: findData.sessions,
};
this.create(instance, typebotData);
return { typebot: { ...instance, typebot: typebotData } };
}
findData.sessions.map((session) => {
if (session.remoteJid === remoteJid) {
session.status = status;
}
});
} else if (status === 'paused') {
// const session: Session = {
// remoteJid: remoteJid,
// sessionId: Math.floor(Math.random() * 10000000000).toString(),
// status: status,
// createdAt: Date.now(),
// updateAt: Date.now(),
// prefilledVariables: {
// remoteJid: remoteJid,
// pushName: '',
// additionalData: {},
// },
// };
// findData.sessions.push(session);
}
const session = await this.prismaRepository.typebotSession.updateMany({
where: {
typebotId: findData?.typebot?.id,
remoteJid: remoteJid,
},
data: {
status: status,
},
});
const typebotData = {
enabled: findData.enabled,
url: findData.url,
typebot: findData.typebot,
expire: findData.expire,
keywordFinish: findData.keywordFinish,
delayMessage: findData.delayMessage,
unknownMessage: findData.unknownMessage,
listeningFromMe: findData.listeningFromMe,
sessions: findData.sessions,
};
this.create(instance, typebotData);
this.waMonitor.waInstances[instance.instanceName].sendDataWebhook(Events.TYPEBOT_CHANGE_STATUS, {
remoteJid: remoteJid,
status: status,
url: findData.url,
typebot: findData.typebot,
url: findData?.typebot?.url,
typebot: findData?.typebot?.typebot,
session,
});
};
this.waMonitor.waInstances[instance.instanceName].sendDataWebhook(Events.TYPEBOT_CHANGE_STATUS, typebotData);
return { typebot: { ...instance, typebot: typebotData } };
}
public async clearSessions(instance: InstanceDto, remoteJid: string) {
const findTypebot = await this.find(instance);
const sessions = [];
// const sessions = (findTypebot.sessions as Session[]) ?? [];
const sessions = await this.prismaRepository.typebotSession.findMany({
where: {
typebotId: findTypebot?.typebot?.id,
remoteJid: remoteJid,
},
});
const sessionWithRemoteJid = sessions.filter((session) => session.remoteJid === remoteJid);
if (sessionWithRemoteJid.length > 0) {
sessionWithRemoteJid.forEach((session) => {
sessions.splice(sessions.indexOf(session), 1);
if (sessions.length > 0) {
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot?.typebot?.id,
remoteJid: remoteJid,
},
});
const typebotData = {
enabled: findTypebot.enabled,
url: findTypebot.url,
typebot: findTypebot.typebot,
expire: findTypebot.expire,
keywordFinish: findTypebot.keywordFinish,
delayMessage: findTypebot.delayMessage,
unknownMessage: findTypebot.unknownMessage,
listeningFromMe: findTypebot.listeningFromMe,
enabled: findTypebot?.typebot?.enabled,
url: findTypebot?.typebot?.url,
typebot: findTypebot?.typebot?.typebot,
expire: findTypebot?.typebot?.expire,
keywordFinish: findTypebot?.typebot?.keywordFinish,
delayMessage: findTypebot?.typebot?.delayMessage,
unknownMessage: findTypebot?.typebot?.unknownMessage,
listeningFromMe: findTypebot?.typebot?.listeningFromMe,
sessions,
};
@ -161,17 +131,20 @@ export class TypebotService {
const startSession = data.startSession;
const variables = data.variables;
const findTypebot = await this.find(instance);
const expire = findTypebot.expire;
const keywordFinish = findTypebot.keywordFinish;
const delayMessage = findTypebot.delayMessage;
const unknownMessage = findTypebot.unknownMessage;
const listeningFromMe = findTypebot.listeningFromMe;
const expire = findTypebot?.typebot?.expire;
const keywordFinish = findTypebot?.typebot?.keywordFinish;
const delayMessage = findTypebot?.typebot?.delayMessage;
const unknownMessage = findTypebot?.typebot?.unknownMessage;
const listeningFromMe = findTypebot?.typebot?.listeningFromMe;
const prefilledVariables = {
remoteJid: remoteJid,
instanceName: instance.instanceName,
};
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES)
prefilledVariables['token'] = instance.token;
if (variables?.length) {
variables.forEach((variable: { name: string | number; value: string }) => {
prefilledVariables[variable.name] = variable.value;
@ -179,10 +152,15 @@ export class TypebotService {
}
if (startSession) {
const newSessions = await this.clearSessions(instance, remoteJid);
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot.typebot.id,
remoteJid: remoteJid,
},
});
const response = await this.createNewSession(instance, {
enabled: findTypebot.enabled,
enabled: findTypebot?.typebot?.enabled,
url: url,
typebot: typebot,
remoteJid: remoteJid,
@ -191,8 +169,8 @@ export class TypebotService {
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
prefilledVariables: prefilledVariables,
typebotId: findTypebot.typebot.id,
});
if (response.sessionId) {
@ -306,70 +284,6 @@ export class TypebotService {
return messageContent;
}
private getAudioMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const audioContent = types.audioMessage;
return audioContent;
}
private getImageMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const imageContent = types.imageMessage;
return imageContent;
}
private getVideoMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const videoContent = types.videoMessage;
return videoContent;
}
private getDocumentMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const documentContent = types.documentMessage;
return documentContent;
}
private getContactMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const contactContent = types.contactMessage;
return contactContent;
}
private getLocationMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const locationContent = types.locationMessage;
return locationContent;
}
private getViewOnceMessageV2Content(msg: any) {
const types = this.getTypeMessage(msg);
const viewOnceContent = types.viewOnceMessageV2;
return viewOnceContent;
}
private getListResponseMessageContent(msg: any) {
const types = this.getTypeMessage(msg);
const listResponseContent = types.listResponseMessage || types.responseRowId;
return listResponseContent;
}
public async createNewSession(instance: InstanceDto, data: any) {
if (data.remoteJid === 'status@broadcast') return;
const id = Math.floor(Math.random() * 10000000000).toString();
@ -407,33 +321,22 @@ export class TypebotService {
const request = await axios.post(url, reqData);
if (request?.data?.sessionId) {
data.sessions.push({
remoteJid: data.remoteJid,
sessionId: `${id}-${request.data.sessionId}`,
status: 'opened',
createdAt: Date.now(),
updateAt: Date.now(),
prefilledVariables: {
...data.prefilledVariables,
await this.prismaRepository.typebotSession.create({
data: {
remoteJid: data.remoteJid,
pushName: data.pushName || '',
instanceName: instance.instanceName,
sessionId: `${id}-${request.data.sessionId}`,
status: 'opened',
prefilledVariables: {
...data.prefilledVariables,
remoteJid: data.remoteJid,
pushName: data.pushName || '',
instanceName: instance.instanceName,
},
typebotId: data.typebotId,
instanceId: instance.instanceId,
},
});
const typebotData = {
enabled: data.enabled,
url: data.url,
typebot: data.typebot,
expire: data.expire,
keywordFinish: data.keywordFinish,
delayMessage: data.delayMessage,
unknownMessage: data.unknownMessage,
listeningFromMe: data.listeningFromMe,
sessions: data.sessions,
};
this.create(instance, typebotData);
}
return request.data;
} catch (error) {
@ -636,16 +539,14 @@ export class TypebotService {
public async sendTypebot(instance: InstanceDto, remoteJid: string, msg: Message) {
const findTypebot = await this.find(instance);
const url = findTypebot.url;
const typebot = findTypebot.typebot;
// const sessions = (findTypebot.sessions as Session[]) ?? [];
const sessions = [];
const expire = findTypebot.expire;
const keywordFinish = findTypebot.keywordFinish;
const delayMessage = findTypebot.delayMessage;
const unknownMessage = findTypebot.unknownMessage;
const listeningFromMe = findTypebot.listeningFromMe;
const messageType = this.getTypeMessage(msg.message).messageType;
const url = findTypebot.typebot?.url;
const typebot = findTypebot.typebot?.typebot;
const sessions = findTypebot.sessions;
const expire = findTypebot.typebot?.expire;
const keywordFinish = findTypebot.typebot?.keywordFinish;
const delayMessage = findTypebot.typebot?.delayMessage;
const unknownMessage = findTypebot.typebot?.unknownMessage;
const listeningFromMe = findTypebot.typebot?.listeningFromMe;
const session = sessions.find((session) => session.remoteJid === remoteJid);
@ -653,15 +554,22 @@ export class TypebotService {
if (session && expire && expire > 0) {
const now = Date.now();
const diff = now - session.updateAt;
const sessionUpdatedAt = new Date(session.updatedAt).getTime();
const diff = now - sessionUpdatedAt;
const diffInMinutes = Math.floor(diff / 1000 / 60);
if (diffInMinutes > expire) {
const newSessions = await this.clearSessions(instance, remoteJid);
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot.typebot.id,
remoteJid: remoteJid,
},
});
const data = await this.createNewSession(instance, {
enabled: findTypebot.enabled,
enabled: findTypebot.typebot.enabled,
url: url,
typebot: typebot,
expire: expire,
@ -669,9 +577,9 @@ export class TypebotService {
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
remoteJid: remoteJid,
pushName: msg.pushName,
typebotId: findTypebot.typebot.id,
});
await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions);
@ -691,22 +599,12 @@ export class TypebotService {
}
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
enabled: findTypebot.enabled,
url: url,
typebot: typebot,
expire: expire,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};
this.create(instance, typebotData);
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot.typebot.id,
remoteJid: remoteJid,
},
});
return;
}
@ -752,7 +650,7 @@ export class TypebotService {
if (!session) {
const data = await this.createNewSession(instance, {
enabled: findTypebot.enabled,
enabled: findTypebot.typebot?.enabled,
url: url,
typebot: typebot,
expire: expire,
@ -760,15 +658,12 @@ export class TypebotService {
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: sessions,
remoteJid: remoteJid,
pushName: msg.pushName,
prefilledVariables: {
messageType: messageType,
},
typebotId: findTypebot.typebot.id,
});
await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions);
await this.sendWAMessage(instance, remoteJid, data?.messages, data?.input, data?.clientSideActions);
if (data.messages.length === 0) {
const content = this.getConversationMessage(msg.message);
@ -785,21 +680,12 @@ export class TypebotService {
}
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
enabled: findTypebot.enabled,
url: url,
typebot: typebot,
expire: expire,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};
this.create(instance, typebotData);
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot.typebot.id,
remoteJid: remoteJid,
},
});
return;
}
@ -838,26 +724,15 @@ export class TypebotService {
return;
}
sessions.map((session) => {
if (session.remoteJid === remoteJid) {
session.updateAt = Date.now();
}
await this.prismaRepository.typebotSession.update({
where: {
id: session.id,
},
data: {
status: 'opened',
},
});
const typebotData = {
enabled: findTypebot.enabled,
url: url,
typebot: typebot,
expire: expire,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions,
};
this.create(instance, typebotData);
const content = this.getConversationMessage(msg.message);
if (!content) {
@ -872,22 +747,12 @@ export class TypebotService {
}
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
enabled: findTypebot.enabled,
url: url,
typebot: typebot,
expire: expire,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};
this.create(instance, typebotData);
await this.prismaRepository.typebotSession.deleteMany({
where: {
typebotId: findTypebot.typebot.id,
remoteJid: remoteJid,
},
});
return;
}

View File

@ -24,13 +24,13 @@ export const typebotSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
enabled: { type: 'boolean' },
url: { type: 'string' },
typebot: { type: 'string' },
expire: { type: 'integer' },
delayMessage: { type: 'integer' },
unknownMessage: { type: 'string' },
listeningFromMe: { type: 'boolean', enum: [true, false] },
listeningFromMe: { type: 'boolean' },
},
required: ['enabled', 'url', 'typebot', 'expire', 'delayMessage', 'unknownMessage', 'listeningFromMe'],
...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delayMessage', 'unknownMessage', 'listeningFromMe'),

View File

@ -54,7 +54,7 @@ export const waMonitor = new WAMonitoringService(
const authService = new AuthService(prismaRepository);
const typebotService = new TypebotService(waMonitor, configService, eventEmitter);
const typebotService = new TypebotService(waMonitor, configService, prismaRepository, eventEmitter);
export const typebotController = new TypebotController(typebotService);
const webhookService = new WebhookService(waMonitor);

View File

@ -71,7 +71,7 @@ export class ChannelStartupService {
this.chatwootCache,
);
public typebotService = new TypebotService(waMonitor, this.configService, this.eventEmitter);
public typebotService = new TypebotService(waMonitor, this.configService, this.prismaRepository, this.eventEmitter);
public setInstance(instance: InstanceDto) {
this.instance.name = instance.instanceName;
@ -547,17 +547,7 @@ export class ChannelStartupService {
throw new NotFoundException('Typebot not found');
}
return {
enabled: data.enabled,
url: data.url,
typebot: data.typebot,
expire: data.expire,
keywordFinish: data.keywordFinish,
delayMessage: data.delayMessage,
unknownMessage: data.unknownMessage,
listeningFromMe: data.listeningFromMe,
sessions: data.sessions,
};
return data;
}
public async loadProxy() {

View File

@ -794,7 +794,7 @@ export class BaileysStartupService extends ChannelStartupService {
remoteJid: chat.id,
},
data: {
lastMsgTimestamp: Long.fromValue(chat.lastMessageRecvTimestamp).toString(),
remoteJid: chat.id,
},
});
}
@ -936,7 +936,7 @@ export class BaileysStartupService extends ChannelStartupService {
chatsRaw.push({
remoteJid: chat.id,
instanceId: this.instanceId,
lastMsgTimestamp: chat.lastMessageRecvTimestamp,
lastMsgTimestamp: parseInt(chat.lastMessageRecvTimestamp?.toString()).toString(),
});
}
@ -1190,7 +1190,7 @@ export class BaileysStartupService extends ChannelStartupService {
if (!(this.localTypebot.listeningFromMe === false && messageRaw.key.fromMe === true)) {
if (messageRaw.messageType !== 'reactionMessage')
await this.typebotService.sendTypebot(
{ instanceName: this.instance.name },
{ instanceName: this.instance.name, instanceId: this.instanceId },
messageRaw.key.remoteJid,
messageRaw,
);
@ -1312,7 +1312,7 @@ export class BaileysStartupService extends ChannelStartupService {
fromMe: key.fromMe,
participant: key?.remoteJid,
status: 'DELETED',
dateTime: Date.now(),
dateTime: parseInt(new Date().getTime().toString()).toString(),
instanceId: this.instanceId,
};
@ -1338,7 +1338,7 @@ export class BaileysStartupService extends ChannelStartupService {
fromMe: key.fromMe,
participant: key?.remoteJid,
status: status[update.status],
dateTime: Date.now(),
dateTime: parseInt(new Date().getTime().toString()).toString(),
pollUpdates,
instanceId: this.instanceId,
};
@ -1878,13 +1878,17 @@ export class BaileysStartupService extends ChannelStartupService {
const contentMsg = messageSent.message[getContentType(messageSent.message)] as any;
if (Long.isLong(messageSent?.messageTimestamp)) {
messageSent.messageTimestamp = messageSent.messageTimestamp?.toNumber();
}
const messageRaw: any = {
key: messageSent.key,
pushName: messageSent.pushName,
message: { ...messageSent.message },
contextInfo: contentMsg?.contextInfo,
messageType: getContentType(messageSent.message),
messageTimestamp: Long.fromValue(messageSent.messageTimestamp).toString(),
messageTimestamp: messageSent.messageTimestamp as number,
instanceId: this.instanceId,
source: getDevice(messageSent.key.id),
};