Last active
September 4, 2022 20:12
-
-
Save alexchristianqr/9d90f9eba3b2eb5e25d6bcf583a72fa8 to your computer and use it in GitHub Desktop.
Clase js para la logica de chatbots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const Chatbot = require('app/SaaS/Chat/Models/Chatbots/Chatbot') | |
const NodeChatbot = require('app/SaaS/Chat/Models/Chatbots/NodeChatbot') | |
const ChatbotService = require('app/SaaS/Chat/Services/Chatbots/ChatbotService') | |
const Ticket = require('app/SaaS/Chat/Models/Conversations/Ticket') | |
const Message = require('app/SaaS/Chat/Models/Messages/Message') | |
const User = require('app/Http/Models/Users/User') | |
class ChatbotChatService { | |
/** | |
* Encontrar chatbot | |
* @param companyId | |
* @param userId | |
* @param ticketId | |
* @param validateContactId | |
* @return {Promise<{chatbot: null, validateChatbot: boolean}>} | |
*/ | |
static async findChatbot({ validateContactId, companyId, userId, ticketId }) { | |
console.log('ChatbotChatService.findChatbot', { companyId, userId, ticketId }) | |
// Set | |
const result = { | |
validateChatbot: false, | |
chatbot: null, | |
} | |
// Obtener chatbots | |
const chatbotsFiltered = await Chatbot.find({ | |
companyId: companyId, // Empresa ID | |
status: true, // Activo | |
'deleted.status': false, // Eliminado | |
}) | |
// Obtener horarios válidos | |
for (const mychatbot of chatbotsFiltered) { | |
mychatbot.schedules = mychatbot.schedules.map((item) => { | |
item.schedule = item.schedule.filter((subitem) => subitem.start.time != null && subitem.end.time != null) | |
return item | |
}) | |
} | |
// No tienes chatbots activos | |
if (!chatbotsFiltered) { | |
return result | |
} | |
// Validar horario de todos los chatbots activos | |
const responseSchedule = ChatbotService.validateScheduleChatbotWebhook({ | |
chatbotsFiltered, | |
}) | |
// Validar chatbot | |
if (!responseSchedule.validateChatbot) { | |
return result | |
} | |
// console.info({ validateContactId }) | |
if (!validateContactId) { | |
// Obtener nodo chatbot | |
const nodeChatbot = await NodeChatbot.findOne( | |
{ | |
companyId: companyId, | |
chatbotId: responseSchedule.chatbot._id, | |
root: true, // Obtener el primer nodo que debe ejecutarse | |
'deleted.status': false, // Obtener nodos no eliminados | |
}, | |
['_id'], | |
) | |
// Actualizar ticket | |
await Ticket.updateOne( | |
{ | |
companyId: companyId, // Empresa ID | |
_id: ticketId, // Ticket ID | |
}, | |
{ | |
'tree.chatbotId': responseSchedule.chatbot._id, | |
'tree.nodeChatbotId': nodeChatbot._id, | |
}, | |
) | |
} else { | |
// Actualizar ticket | |
await Ticket.updateOne( | |
{ | |
companyId: companyId, // Empresa ID | |
_id: ticketId, // Ticket ID | |
}, | |
{ | |
'tree.chatbotId': responseSchedule.chatbot._id, | |
}, | |
) | |
} | |
// Set | |
result.validateChatbot = responseSchedule.validateChatbot | |
result.chatbot = responseSchedule.chatbot | |
// Response | |
return result | |
} | |
/** | |
* Encontrar nodo chatbot | |
* @param companyId | |
* @param chatbotId | |
* @param ticketId | |
* @param messagePayload | |
* @param validateContactId | |
* @param ticketFounded | |
* @return {Promise<*>} | |
*/ | |
static async findNodeChatbot({ validateContactId, companyId, chatbotId, ticketId, messagePayload, ticketFounded }) { | |
console.log('ChatbotChatService.findNodeChatbot', { companyId, chatbotId, ticketId, messagePayload }) | |
// Set | |
let nodeChatbots = null | |
let nodeChatbot | |
const result = { | |
validateNodeChatbot: false, | |
nodeChatbot: null, | |
messageNodechatbot: null, | |
} | |
// Obtener nodo | |
console.info({ messagePayload }) | |
if (validateContactId) { | |
let parentNodeChatbotId = ticketFounded?.tree?.nodeChatbotId | |
let beforeNodeChatbot = await NodeChatbot.findOne({ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
root: false, // Obtener el siguiente nodo que debe ejecutarse | |
parent: parentNodeChatbotId, | |
'item.value': messagePayload, | |
'deleted.status': false, // Obtener nodos no eliminados | |
}) | |
console.info({ beforeNodeChatbot }) | |
nodeChatbot = await NodeChatbot.findOne({ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
_id: beforeNodeChatbot.action.nodeChatbotId, | |
root: false, // Obtener el siguiente nodo que debe ejecutarse | |
'deleted.status': false, // Obtener nodos no eliminados | |
}) | |
} else { | |
nodeChatbot = await NodeChatbot.findOne({ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
root: true, // Obtener el primer nodo que debe ejecutarse | |
'deleted.status': false, // Obtener nodos no eliminados | |
}) | |
} | |
if (!nodeChatbot) { | |
throw { | |
message: 'nodo chatbot not found', | |
status: 400, | |
} | |
} | |
// Set | |
let message = `${nodeChatbot.item.text}\n` | |
// Validar tipo nodo | |
switch (nodeChatbot.type) { | |
case 'multiple': | |
// Obtener nodos chatbots | |
nodeChatbots = await NodeChatbot.find( | |
{ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
_id: { $in: nodeChatbot.nodeChatbotIds }, | |
'deleted.status': false, // Obtener nodos no eliminados | |
}, | |
['item'], | |
) | |
if (!nodeChatbots) { | |
return result | |
} | |
// Iterar nodos | |
for (let field of nodeChatbots) { | |
message += `${field.item.value}. ${field.item.text}\n` | |
} | |
// Set | |
result.validateNodeChatbot = true | |
result.nodeChatbot = nodeChatbot | |
result.messageNodechatbot = message | |
break | |
case 'options': | |
switch (nodeChatbot.action.type) { | |
case 'transfer': | |
case 'archive': | |
case 'back': | |
case 'continue': | |
// Set | |
result.nodeChatbot = nodeChatbot | |
result.messageNodechatbot = message | |
break | |
case 'finish': | |
console.info('nodo chatbot finish') | |
break | |
default: | |
} | |
break | |
case 'single': | |
// Obtener nodos chatbots | |
nodeChatbots = await NodeChatbot.find( | |
{ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
_id: { $in: nodeChatbot.nodeChatbotIds }, | |
'deleted.status': false, // Obtener nodos no eliminados | |
}, | |
['item'], | |
) | |
if (!nodeChatbots) { | |
return result | |
} | |
// Set | |
result.validateNodeChatbot = true | |
// Iterar nodos | |
for (let field of nodeChatbots) { | |
message += `${field.item.value}. ${field.item.text}\n` | |
} | |
// console.info({ message }) | |
// Actualizar ticket} | |
// console.info('alex #2') | |
// await Ticket.updateOne( | |
// { | |
// companyId: companyId, // Empresa ID | |
// _id: ticketId, // Ticket ID | |
// }, | |
// { | |
// 'tree.chatbotId': chatbotId, | |
// // 'tree.nodeChatbotId': nodeChatbotId, | |
// }, | |
// ) | |
// Set | |
result.nodeChatbot = nodeChatbot | |
result.messageNodechatbot = message | |
break | |
default: | |
throw { | |
message: 'type nodo chatbot not support', | |
status: 400, | |
} | |
} | |
// Response | |
return result | |
} | |
/** | |
* Responder como nodo chatbot o chatbot | |
* @param contactId | |
* @param userId | |
* @param companyId | |
* @param channel | |
* @param conversationId | |
* @param ticket | |
* @param ticketId | |
* @param payload | |
* @param message | |
* @param provider | |
* @param messageType | |
* @param url | |
* @return {Promise<*>} | |
*/ | |
static async setMessageForChatbot({ validateContactId, contactId, userId, companyId, channel, conversationId, ticket, ticketId, payload, messagePayload, provider, messageType, url }) { | |
console.log('ChatbotChatService.setMessageForChatbot', { messagePayload, validateContactId }) | |
// Set | |
let chatbotId = null | |
let messageString = '' | |
let responseChatbot = null | |
let result = { | |
lastMessage: null, | |
message: null, | |
} | |
// Contacto existe | |
if (validateContactId) { | |
// Obtener chatbot | |
const { validateChatbot, chatbot } = await this.findChatbot({ | |
companyId, | |
userId, | |
ticketId, | |
validateContactId, | |
}) | |
if (!validateChatbot) { | |
// Preparar mensaje | |
const responseChatbot = await this.dispatchWebhookMessage({ | |
validateContactId, | |
provider, | |
companyId, | |
channel, | |
conversationId, | |
userId, | |
ticket, | |
chatbotId, | |
messagePayload, | |
payload, | |
contactId, | |
messageString, | |
messageType, | |
url, | |
}) | |
// Set | |
result.lastMessage = responseChatbot.lastMessage | |
result.message = responseChatbot.message | |
// Response | |
return result | |
} | |
// Set | |
chatbotId = chatbot._id | |
// Obtener ticket | |
const ticketFounded = await Ticket.findOne({ | |
companyId: companyId, // Empresa ID | |
channel: channel, // Canal | |
conversationId: conversationId, // Conversación ID | |
ticket: ticket, // Numero de ticket | |
'tree.chatbotId': chatbotId, // Chatbot ID | |
}) | |
if (!ticketFounded) { | |
throw new Error('not found ticket') | |
} | |
// Obtener nodo chatbot | |
const { validateNodeChatbot, nodeChatbot, messageNodechatbot } = await ChatbotChatService.findNodeChatbot({ | |
companyId, | |
chatbotId, | |
messagePayload, | |
validateContactId, | |
ticketFounded, | |
}) | |
if (!validateNodeChatbot) { | |
throw new Error('not found node chatbot') | |
} | |
// Obtener usuario chatbot | |
let userChatbotId = await this.getUserChatbot(companyId) | |
// console.info({ userChatbotId }) | |
// Preparar mensaje | |
responseChatbot = await this.dispatchWebhookMessage({ | |
validateContactId, | |
provider, | |
companyId, | |
channel, | |
conversationId, | |
userId, | |
ticket, | |
chatbotId, | |
nodeChatbot, | |
payload, | |
messagePayload, | |
contactId, | |
messageString, | |
messageType, | |
url, | |
userChatbotId, | |
}) | |
// Set | |
result.lastMessage = responseChatbot.lastMessage | |
result.message = responseChatbot.message | |
// TODO | |
// Set | |
messageString = `${messageNodechatbot}` | |
// Crear ultimo mensaje | |
await Message.create({ | |
channel: channel, // Canal | |
provider: provider, // Proveedor | |
sender: payload.sender, | |
recipient: payload.recipient, | |
guid: payload.guid, | |
ticket: ticket, | |
conversationId: conversationId, // ObjectId() | |
userId: userChatbotId, // ObjectId() | |
message: messageString, // Mensaje | |
messageType: messageType, // Tipo de mensaje | |
messageStatus: 'delivered', // Entregado | |
mediafileUrl: url, | |
status: true, // Activo | |
}) | |
// TODO | |
} | |
// Contacto no existe | |
else { | |
// Obtener chatbot | |
const { validateChatbot, chatbot } = await this.findChatbot({ | |
companyId, | |
userId, | |
validateContactId, | |
}) | |
if (!validateChatbot) { | |
// Preparar mensaje | |
const responseChatbot = await this.dispatchWebhookMessage({ | |
validateContactId, | |
provider, | |
companyId, | |
channel, | |
conversationId, | |
userId, | |
ticket, | |
chatbotId, | |
messagePayload, | |
payload, | |
contactId, | |
messageString, | |
messageType, | |
url, | |
}) | |
// Set | |
result.lastMessage = responseChatbot.lastMessage | |
result.message = responseChatbot.message | |
// Response | |
return result | |
} | |
// Set | |
chatbotId = chatbot._id | |
// Obtener nodo chatbot | |
const { validateNodeChatbot, nodeChatbot, messageNodechatbot } = await ChatbotChatService.findNodeChatbot({ | |
companyId, | |
chatbotId, | |
validateContactId, | |
}) | |
if (!validateNodeChatbot) { | |
throw new Error('not found node chatbot') | |
} | |
// Obtener usuario chatbot | |
let userChatbotId = await this.getUserChatbot(companyId) | |
console.log({ userChatbotId }) | |
// Preparar mensaje | |
const responseChatbot = await this.dispatchWebhookMessage({ | |
validateContactId, | |
provider, | |
companyId, | |
channel, | |
conversationId, | |
userId, | |
ticket, | |
chatbotId, | |
nodeChatbot, | |
messagePayload, | |
messageNodechatbot, | |
payload, | |
contactId, | |
messageString, | |
messageType, | |
url, | |
userChatbotId, | |
}) | |
// Set | |
result.lastMessage = responseChatbot.lastMessage | |
result.message = responseChatbot.message | |
// Set | |
messagePayload = `${messageNodechatbot}` | |
// Crear ultimo mensaje | |
await Message.create({ | |
channel: channel, // Canal | |
provider: provider, // Proveedor | |
sender: payload.sender, | |
recipient: payload.recipient, | |
guid: payload.guid, | |
ticket: ticket, | |
conversationId: conversationId, // ObjectId() | |
userId: userChatbotId, // ObjectId() | |
message: messagePayload, // Mensaje | |
messageType: messageType, // Tipo de mensaje | |
messageStatus: 'delivered', // Entregado | |
mediafileUrl: url, | |
status: true, // Activo | |
}) | |
} | |
// Response | |
return result | |
} | |
/** | |
* Preparar mensaje | |
* @param validateContactId | |
* @param provider | |
* @param companyId | |
* @param channel | |
* @param conversationId | |
* @param userId | |
* @param ticket | |
* @param chatbotId | |
* @param nodeChatbot | |
* @param messagePayload | |
* @param messageNodechatbot | |
* @param payload | |
* @param contactId | |
* @param messageString | |
* @param messageType | |
* @param url | |
* @param userChatbotId | |
* @return {Promise<void>} | |
*/ | |
static async dispatchWebhookMessage({ | |
validateContactId, | |
provider, | |
companyId, | |
channel, | |
conversationId, | |
userId, | |
ticket, | |
chatbotId, | |
nodeChatbot, | |
messagePayload, | |
messageNodechatbot, | |
payload, | |
contactId, | |
messageString, | |
messageType, | |
url, | |
userChatbotId, | |
}) { | |
console.log('Chatbot.dispatchWebhookMessage', { messagePayload, messageNodechatbot, messageString }) | |
// Set | |
let nodeChatbotId | |
if (validateContactId && nodeChatbot) { | |
// Set | |
nodeChatbotId = nodeChatbot._id | |
// Actualizar ticket | |
await Ticket.updateOne( | |
{ | |
companyId: companyId, // Empresa ID | |
channel: channel, // Canal | |
conversationId: conversationId, // Conversacion ID | |
userId: userId, // Usuario Id | |
ticket: ticket, // Numero de ticket | |
'tree.chatbotId': chatbotId, // Chatbot ID | |
}, | |
{ | |
'tree.nodeChatbotId': nodeChatbotId, // Nodo chatbot ID | |
}, | |
) | |
} else { | |
if (chatbotId) { | |
// Obtener nodo chatbot | |
const tmpnodeChatbot = await NodeChatbot.findOne( | |
{ | |
companyId: companyId, | |
chatbotId: chatbotId, | |
root: true, // Obtener el primer nodo que debe ejecutarse | |
'deleted.status': false, // Obtener nodos no eliminados | |
}, | |
['_id'], | |
) | |
// Actualizar ticket | |
await Ticket.updateOne( | |
{ | |
companyId: companyId, // Empresa ID | |
channel: channel, // Canal | |
conversationId: conversationId, // Conversacion ID | |
userId: userId, // Usuario Id | |
ticket: ticket, // Numero de ticket | |
}, | |
{ | |
'tree.chatbotId': chatbotId, // Chatbot ID | |
'tree.nodeChatbotId': tmpnodeChatbot._id, // Nodo chatbot ID | |
}, | |
) | |
} | |
} | |
// Crear ultimo mensaje | |
const lastMessage = await Message.create({ | |
channel: channel, // Canal | |
provider: provider, // Proveedor | |
sender: payload.sender, | |
recipient: payload.recipient, | |
guid: payload.guid, | |
ticket: ticket, | |
conversationId: conversationId, // ObjectId() | |
contactId: contactId, // ObjectId() | |
message: messagePayload, // Mensaje | |
messageType: messageType, // Tipo de mensaje | |
messageStatus: 'delivered', // Entregado | |
mediafileUrl: url, | |
status: true, // Activo | |
}) | |
// Obtener ultimo mensaje | |
const message = await Message.findOne({ | |
_id: lastMessage._id, // ObjectId() | |
}).populate('contactId') | |
// Set RelationsShip | |
message.contact = message.contactId | |
message.contactId = message.contact._id | |
// Response | |
return { | |
message, | |
lastMessage, | |
} | |
} | |
/** | |
* Obtener usuario chatbot por empresa ID | |
* @param companyId | |
* @returns {Promise<*>} | |
*/ | |
static async getUserChatbot(companyId) { | |
// Obtener usuario chatbot | |
const user = await User.findOne( | |
{ | |
companyId: companyId, | |
isBot: true, | |
}, | |
['_id'], | |
) | |
// Response | |
return user._id | |
} | |
} | |
module.exports = ChatbotChatService |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment