From 1c66f178a56d284bb8cb9df5ca17685c7e5d1ddd Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sat, 28 Jan 2023 18:41:58 +0100 Subject: [PATCH 1/3] fix(cli): :zap: endflow --- __test__/06-case.test.js | 111 ++++++++++++++++++++++++++++++++ packages/bot/core/core.class.js | 11 +++- packages/bot/package.json | 2 +- 3 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 __test__/06-case.test.js diff --git a/__test__/06-case.test.js b/__test__/06-case.test.js new file mode 100644 index 0000000..c68679e --- /dev/null +++ b/__test__/06-case.test.js @@ -0,0 +1,111 @@ +const { test } = require('uvu') +const assert = require('uvu/assert') +const MOCK_DB = require('../packages/database/src/mock') +const PROVIDER_DB = require('../packages/provider/src/mock') +const { + addKeyword, + createBot, + createFlow, + createProvider, +} = require('../packages/bot/index') + +/** + * Falsear peticion async + * @param {*} fakeData + * @returns + */ +const fakeHTTP = async (fakeData = []) => { + await delay(5) + const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` })) + return Promise.resolve(data) +} + +test(`[Caso - 06] Finalizar Flujo (endFlow)`, async () => { + const MOCK_VALUES = [ + 'ΒΏCUal es tu email?', + 'Continuamos....', + 'ΒΏCual es tu edad?', + ] + const provider = createProvider(PROVIDER_DB) + const database = new MOCK_DB() + + const flujoPrincipal = addKeyword(['hola']) + .addAnswer( + MOCK_VALUES[0], + { + capture: true, + }, + async (ctx, { flowDynamic, fallBack }) => { + const validation = ctx.body.includes('@') + + if (validation) { + const getDataFromApi = await fakeHTTP([ + 'Gracias por tu email se ha validado de manera correcta', + ]) + return flowDynamic(getDataFromApi) + } + return fallBack(validation) + } + ) + .addAnswer(MOCK_VALUES[1], null, async (_, { endFlow }) => { + return endFlow() + }) + .addAnswer( + MOCK_VALUES[2], + { capture: true }, + async (ctx, { flowDynamic, fallBack }) => { + if (ctx.body !== '18') { + await delay(50) + return fallBack(false, 'Ups creo que no eres mayor de edad') + } + return flowDynamic('Bien tu edad es correcta!') + } + ) + .addAnswer('Puedes pasar') + + createBot({ + database, + flow: createFlow([flujoPrincipal]), + provider, + }) + + provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + provider.delaySendMessage(10, 'message', { + from: '000', + body: 'this is not email value', + }) + + provider.delaySendMessage(20, 'message', { + from: '000', + body: 'test@test.com', + }) + + provider.delaySendMessage(90, 'message', { + from: '000', + body: '20', + }) + + await delay(1200) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + assert.is('this is not email value', getHistory[1]) + assert.is(MOCK_VALUES[0], getHistory[2]) + assert.is('test@test.com', getHistory[3]) + assert.is( + '1 Gracias por tu email se ha validado de manera correcta', + getHistory[4] + ) + assert.is(MOCK_VALUES[1], getHistory[5]) + assert.is('20', getHistory[6]) + assert.is(undefined, getHistory[7]) +}) + +test.run() + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index b3bc15b..90340e6 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -98,10 +98,15 @@ class CoreClass { } // πŸ“„ Finalizar flujo - const endFlow = async () => { + const endFlow = async (message = null) => { prevMsg = null endFlowFlag = true clearQueue() + if (message) + this.sendProviderAndSave(from, { + ...prevMsg, + answer: message ?? prevMsg.answer, + }) return } @@ -199,7 +204,7 @@ class CoreClass { } // πŸ“„πŸ€˜(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa - if (prevMsg?.options?.nested?.length) { + if (!endFlowFlag && prevMsg?.options?.nested?.length) { const nestedRef = prevMsg.options.nested const flowStandalone = nestedRef.map((f) => ({ ...nestedRef.find((r) => r.refSerialize === f.refSerialize), @@ -212,7 +217,7 @@ class CoreClass { } // πŸ“„πŸ€˜(tiene return) Si el mensaje previo implementa capture - if (!prevMsg?.options?.nested?.length) { + if (!endFlowFlag && !prevMsg?.options?.nested?.length) { const typeCapture = typeof prevMsg?.options?.capture if (typeCapture === 'boolean' && fallBackFlag) { diff --git a/packages/bot/package.json b/packages/bot/package.json index 30211e4..827194b 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.84-alpha.0", + "version": "0.0.86-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { From b655ae449e7958ea940d8cc3c678fd66f60b6385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leifer=20Jes=C3=BAs=20Mendez?= Date: Sun, 29 Jan 2023 12:46:31 +0100 Subject: [PATCH 2/3] fix(bot): :fire: endFlow with ctx --- packages/bot/core/core.class.js | 48 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index b3bc15b..9ddf444 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -91,6 +91,25 @@ class CoreClass { this.databaseClass.save(ctxByNumber) } + // πŸ“„ Crar CTX de mensaje (uso private) + const createCtxMessage = (payload = {}, index = 0) => { + const body = + typeof payload === 'string' + ? payload + : payload?.body ?? payload?.answer + const media = payload?.media ?? null + const buttons = payload?.buttons ?? [] + const capture = payload?.capture ?? false + + return toCtx({ + body, + from, + keyword: null, + index, + options: { media, buttons, capture }, + }) + } + // πŸ“„ Limpiar cola de procesos const clearQueue = () => { QueuePrincipal.pendingPromise = false @@ -98,9 +117,12 @@ class CoreClass { } // πŸ“„ Finalizar flujo - const endFlow = async () => { + const endFlow = async (message = null) => { prevMsg = null endFlowFlag = true + if (message) + this.sendProviderAndSave(from, createCtxMessage(message)) + clearQueue() return } @@ -151,28 +173,12 @@ class CoreClass { // πŸ“„ [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes // para evitar bloque de whatsapp - const flowDynamic = async ( - listMsg = [], - optListMsg = { limit: 5, fallback: false } - ) => { + const flowDynamic = async (listMsg = []) => { if (!Array.isArray(listMsg)) listMsg = [listMsg] - fallBackFlag = optListMsg.fallback - const parseListMsg = listMsg - .map((opt, index) => { - const body = typeof opt === 'string' ? opt : opt.body - const media = opt?.media ?? null - const buttons = opt?.buttons ?? [] - - return toCtx({ - body, - from, - keyword: null, - index, - options: { media, buttons }, - }) - }) - .slice(0, optListMsg.limit) + const parseListMsg = listMsg.map((opt, index) => + createCtxMessage(opt, index) + ) if (endFlowFlag) return for (const msg of parseListMsg) { From f6114affadfbc324536a86167d1fdfe8da3c8de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leifer=20Jes=C3=BAs=20Mendez?= Date: Sun, 29 Jan 2023 13:39:09 +0100 Subject: [PATCH 3/3] fix(bot): :fire: endFlow with ctx --- packages/bot/core/core.class.js | 9 ++++++++- packages/bot/package.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 9ddf444..60644a5 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -166,7 +166,14 @@ class CoreClass { if (next) return continueFlow() return this.sendProviderAndSave(from, { ...prevMsg, - answer: message ?? prevMsg.answer, + answer: + typeof message === 'string' + ? message + : message?.body ?? prevMsg.answer, + options: { + ...prevMsg.options, + buttons: message?.buttons ?? prevMsg.options?.buttons, + }, }) } diff --git a/packages/bot/package.json b/packages/bot/package.json index 30211e4..5d2dc0c 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.84-alpha.0", + "version": "0.0.89-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": {