Merge pull request #538 from codigoencasa/dev

Dev
This commit is contained in:
Leifer Mendez
2023-01-23 12:05:49 +01:00
committed by GitHub
9 changed files with 78 additions and 32 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
/node_modules /node_modules
/packages/repl
/packages/*/starters /packages/*/starters
/packages/*/node_modules /packages/*/node_modules
/packages/*/dist /packages/*/dist

View File

@@ -21,10 +21,12 @@ class CoreClass {
flowClass flowClass
databaseClass databaseClass
providerClass providerClass
constructor(_flow, _database, _provider) { generalArgs = { blackList: [] }
constructor(_flow, _database, _provider, _args) {
this.flowClass = _flow this.flowClass = _flow
this.databaseClass = _database this.databaseClass = _database
this.providerClass = _provider this.providerClass = _provider
this.generalArgs = { ...this.generalArgs, ..._args }
for (const { event, func } of this.listenerBusEvents()) { for (const { event, func } of this.listenerBusEvents()) {
this.providerClass.on(event, func) this.providerClass.on(event, func)
@@ -70,6 +72,7 @@ class CoreClass {
const { body, from } = messageCtxInComming const { body, from } = messageCtxInComming
let msgToSend = [] let msgToSend = []
let fallBackFlag = false let fallBackFlag = false
if (this.generalArgs.blackList.includes(from)) return
if (!body) return if (!body) return
if (!body.length) return if (!body.length) return
@@ -89,14 +92,18 @@ class CoreClass {
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx // 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
const sendFlow = async (messageToSend, numberOrId) => { const sendFlow = async (messageToSend, numberOrId) => {
// [1 Paso] esto esta bien!
if (prevMsg?.options?.capture) await cbEveryCtx(prevMsg?.ref)
const queue = [] const queue = []
for (const ctxMessage of messageToSend) { for (const ctxMessage of messageToSend) {
const delayMs = ctxMessage?.options?.delay || 0 const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs) if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() => QueuePrincipal.enqueue(() =>
Promise.all([ Promise.all([
this.sendProviderAndSave(numberOrId, ctxMessage), this.sendProviderAndSave(numberOrId, ctxMessage).then(
resolveCbEveryCtx(ctxMessage), () => resolveCbEveryCtx(ctxMessage)
),
]) ])
) )
} }
@@ -113,6 +120,7 @@ class CoreClass {
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes // 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
// para evitar bloque de whatsapp // para evitar bloque de whatsapp
const flowDynamic = async ( const flowDynamic = async (
listMsg = [], listMsg = [],
optListMsg = { limit: 5, fallback: false } optListMsg = { limit: 5, fallback: false }
@@ -122,15 +130,21 @@ class CoreClass {
fallBackFlag = optListMsg.fallback fallBackFlag = optListMsg.fallback
const parseListMsg = listMsg const parseListMsg = listMsg
.map(({ body }, index) => .map((opt, index) => {
toCtx({ const body = typeof opt === 'string' ? opt : opt.body
const media = opt?.media ?? null
const buttons = opt?.buttons ?? []
return toCtx({
body, body,
from, from,
keyword: null, keyword: null,
index, index,
options: { media, buttons },
}) })
) })
.slice(0, optListMsg.limit) .slice(0, optListMsg.limit)
for (const msg of parseListMsg) { for (const msg of parseListMsg) {
await this.sendProviderAndSave(from, msg) await this.sendProviderAndSave(from, msg)
} }
@@ -139,7 +153,6 @@ class CoreClass {
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback // 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
const resolveCbEveryCtx = async (ctxMessage) => { const resolveCbEveryCtx = async (ctxMessage) => {
if (prevMsg?.options?.capture) return cbEveryCtx(prevMsg?.ref)
if (!ctxMessage?.options?.capture) if (!ctxMessage?.options?.capture)
return await cbEveryCtx(ctxMessage?.ref) return await cbEveryCtx(ctxMessage?.ref)
} }
@@ -153,17 +166,6 @@ class CoreClass {
}) })
} }
if (prevMsg?.ref) resolveCbEveryCtx(prevMsg)
// 📄 [options: callback]: Si se tiene un callback se ejecuta
//TODO AQUI
// if (!fallBackFlag) {
// if (prevMsg?.options?.capture) cbEveryCtx(prevMsg?.ref)
// for (const ite of this.flowClass.find(body)) {
// if (!ite?.options?.capture) cbEveryCtx(ite?.ref)
// }
// }
// 📄🤘(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa // 📄🤘(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa
if (!fallBackFlag && prevMsg?.options?.nested?.length) { if (!fallBackFlag && prevMsg?.options?.nested?.length) {
const nestedRef = prevMsg.options.nested const nestedRef = prevMsg.options.nested
@@ -173,11 +175,6 @@ class CoreClass {
msgToSend = this.flowClass.find(body, false, flowStandalone) || [] msgToSend = this.flowClass.find(body, false, flowStandalone) || []
// //TODO AQUI
// for (const ite of msgToSend) {
// cbEveryCtx(ite?.ref)
// }
sendFlow(msgToSend, from) sendFlow(msgToSend, from)
return return
} }
@@ -225,5 +222,24 @@ class CoreClass {
this.continue(null, responde.ref) this.continue(null, responde.ref)
} }
} }
/**
* Funcion dedicada a enviar el mensaje sin pasar por el flow
* (dialogflow)
* @param {*} messageToSend
* @param {*} numberOrId
* @returns
*/
sendFlowSimple = async (messageToSend, numberOrId) => {
const queue = []
for (const ctxMessage of messageToSend) {
const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() =>
this.sendProviderAndSave(numberOrId, ctxMessage)
)
}
return Promise.all(queue)
}
} }
module.exports = CoreClass module.exports = CoreClass

View File

@@ -8,8 +8,8 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
* @param {*} args * @param {*} args
* @returns * @returns
*/ */
const createBot = async ({ flow, database, provider }) => const createBot = async ({ flow, database, provider }, args = {}) =>
new CoreClass(flow, database, provider) new CoreClass(flow, database, provider, args)
/** /**
* Crear instancia de clase Io (Flow) * Crear instancia de clase Io (Flow)

View File

@@ -5,12 +5,12 @@ const { generateRef, generateRefSerialize } = require('../../utils/hash')
* @param options {media:string, buttons:[], capture:true default false} * @param options {media:string, buttons:[], capture:true default false}
* @returns * @returns
*/ */
const toCtx = ({ body, from, prevRef, index }) => { const toCtx = ({ body, from, prevRef, options = {}, index }) => {
return { return {
ref: generateRef(), ref: generateRef(),
keyword: prevRef, keyword: prevRef,
answer: body, answer: body,
options: {}, options: options ?? {},
from, from,
refSerialize: generateRefSerialize({ index, answer: body }), refSerialize: generateRefSerialize({ index, answer: body }),
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@bot-whatsapp/bot", "name": "@bot-whatsapp/bot",
"version": "0.0.66-alpha.0", "version": "0.0.73-alpha.0",
"description": "", "description": "",
"main": "./lib/bundle.bot.cjs", "main": "./lib/bundle.bot.cjs",
"scripts": { "scripts": {

View File

@@ -0,0 +1,29 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const FlowClass = require('../io/flow.class')
const MockProvider = require('../../../__mocks__/mock.provider')
const { addKeyword } = require('../index')
test(`[FlowClass] Probando instanciamiento de clase`, async () => {
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
const flowClass = new FlowClass([MOCK_FLOW])
assert.is(flowClass instanceof FlowClass, true)
})
test(`[FlowClass] Probando find`, async () => {
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
const flowClass = new FlowClass([MOCK_FLOW])
flowClass.find('hola')
assert.is(flowClass instanceof FlowClass, true)
})
test(`[FlowClass] Probando findBySerialize`, async () => {
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
const flowClass = new FlowClass([MOCK_FLOW])
flowClass.findBySerialize('')
assert.is(flowClass instanceof FlowClass, true)
})
test.run()

View File

@@ -117,7 +117,7 @@ class DialogFlowCXContext extends CoreClass {
} }
}) })
this.sendFlow(listMessages, from) this.sendFlowSimple(listMessages, from)
} }
} }

View File

@@ -107,7 +107,7 @@ class DialogFlowContext extends CoreClass {
...customPayload, ...customPayload,
answer: fields?.answer?.stringValue, answer: fields?.answer?.stringValue,
} }
this.sendFlow([ctxFromDX], from) this.sendFlowSimple([ctxFromDX], from)
return return
} }
@@ -115,7 +115,7 @@ class DialogFlowContext extends CoreClass {
answer: queryResult?.fulfillmentText, answer: queryResult?.fulfillmentText,
} }
this.sendFlow([ctxFromDX], from) this.sendFlowSimple([ctxFromDX], from)
} }
} }

View File

@@ -55,7 +55,7 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
- delay: 0 (milisegundos) - delay: 0 (milisegundos)
- media: url de imagen - media: url de imagen
- buttons: array `[{body:'Boton1'}, {body:'Boton2'}, {body:'Boton3'}]` - buttons: array `[{body:'Boton1'}, {body:'Boton2'}, {body:'Boton3'}]`
- capture: false (para esperar respuesta) - capture: true (para esperar respuesta)
- child: Objecto tipo flujo o arra de flujos hijos - child: Objecto tipo flujo o arra de flujos hijos
```js ```js