diff --git a/.gitignore b/.gitignore
index 1cc3038..9f6dbbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/node_modules
+/packages/repl
/packages/*/starters
/packages/*/node_modules
/packages/*/dist
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d3865b..9b39939 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,47 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+### [0.1.18](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.17...v0.1.18) (2023-01-24)
+
+
+### Features
+
+* **bot:** :zap: add blacklist ([7078dc4](https://github.com/leifermendez/bot-whatsapp/commit/7078dc4c93d01bf90ef08ecb34e89a1abbe16fd2))
+* **bot:** :zap: flowDynamic buttons, media ([3c4b1c0](https://github.com/leifermendez/bot-whatsapp/commit/3c4b1c0fc4b6d98d67c67806d918d3604bb2209b))
+
+
+### Bug Fixes
+
+* **bot:** :bug: body undefined ([bb6ed4a](https://github.com/leifermendez/bot-whatsapp/commit/bb6ed4a084ae98070dfdf0c4ba1eca574c4092cc))
+* **bot:** :bug: body undefined ([9234cf1](https://github.com/leifermendez/bot-whatsapp/commit/9234cf1c5d00abdd35e62a826b3c450ab056987a))
+* **bot:** :bug: body undefined ([a118bbb](https://github.com/leifermendez/bot-whatsapp/commit/a118bbbf7f0a7023cb7f33c23f37db72adad151f))
+* **bot:** :bug: body undefined ([f54dea5](https://github.com/leifermendez/bot-whatsapp/commit/f54dea52b01063acd6122eeba1fbbe324aa7805d))
+* **bot:** :bug: body undefined ([72e0a91](https://github.com/leifermendez/bot-whatsapp/commit/72e0a910503e9643db7dfbc6e09c41c96934e1f7))
+* **bot:** :bug: body undefined ([70dd4d7](https://github.com/leifermendez/bot-whatsapp/commit/70dd4d73e814fc5636d19a887f3621c483b837c1))
+* **bot:** :bug: body undefined ([ecf0eef](https://github.com/leifermendez/bot-whatsapp/commit/ecf0eef928917d76c59bd23886cb7a4108b421f1))
+* **bot:** :bug: flowDynamic stranger behaviour ([877252b](https://github.com/leifermendez/bot-whatsapp/commit/877252bd4a8a7bbbbf083c3ceaeaeb952b0a1828))
+* **bot:** :bug: flowDynamic stranger behaviour ([f5a7de3](https://github.com/leifermendez/bot-whatsapp/commit/f5a7de3a003c012e2164e51fff26892cfc3144be))
+* **bot:** :memo: more docs ([98793d0](https://github.com/leifermendez/bot-whatsapp/commit/98793d0cfc1674830beaa3707f933c5a791eec14))
+* **cli:** :zap: refactor ([a29b9d4](https://github.com/leifermendez/bot-whatsapp/commit/a29b9d4e1f85fc163cf1d633c0857f0c8b7f03e1))
+* **cli:** :zap: refactor ([18ef4e9](https://github.com/leifermendez/bot-whatsapp/commit/18ef4e9d726575ca390ca24354825860328d3347))
+* **cli:** :zap: refactor ([3648757](https://github.com/leifermendez/bot-whatsapp/commit/3648757fa083bdb88a16bf6c2e90c828c233bdb1))
+* **cli:** :zap: refactor ([32f6a70](https://github.com/leifermendez/bot-whatsapp/commit/32f6a70f8f6fb26d8ea2a0f1a4aec4827b9d6a93))
+* **cli:** :zap: refactor ([8c825e7](https://github.com/leifermendez/bot-whatsapp/commit/8c825e7f6b7133f7cc7f3041ce331b80a9fe60e0))
+* **cli:** :zap: refactor ([0c0f437](https://github.com/leifermendez/bot-whatsapp/commit/0c0f4375b84549bee809340a85f9ce038ee2739e))
+* **cli:** :zap: refactor ([039ce5d](https://github.com/leifermendez/bot-whatsapp/commit/039ce5dd7cac8115b335ad5de05f7bd871e24140))
+* **cli:** :zap: refactor ([5e87918](https://github.com/leifermendez/bot-whatsapp/commit/5e879188b8bf9d486399b308a9a9c2612607d465))
+* **cli:** :zap: refactor ([21a7270](https://github.com/leifermendez/bot-whatsapp/commit/21a72702817bc6b344223b34ca4513a7ff45fc93))
+* **cli:** :zap: refactor ([82a99b2](https://github.com/leifermendez/bot-whatsapp/commit/82a99b2c80e6738566042ea738bbab8208a17758))
+* **cli:** :zap: refactor ([cc19974](https://github.com/leifermendez/bot-whatsapp/commit/cc19974579379777b05cb69c38cec0fce6740471))
+* **cli:** :zap: refactor ([56fcb8f](https://github.com/leifermendez/bot-whatsapp/commit/56fcb8fb72169bc21fce7c4fcdceccf2acd39c73))
+* **cli:** :zap: refactor ([f36cff1](https://github.com/leifermendez/bot-whatsapp/commit/f36cff1eefdd96be4ab531e1cb2d3b630b1a81c3))
+* **cli:** :zap: refactor ([b393c11](https://github.com/leifermendez/bot-whatsapp/commit/b393c11af6c0ebccb0a690be8b90b9df8877dad1))
+* **cli:** :zap: refactor ([6683715](https://github.com/leifermendez/bot-whatsapp/commit/6683715ad617ea1075654a475a1c62ea607c733f))
+* **contexts:** :bug: fixed [#524](https://github.com/leifermendez/bot-whatsapp/issues/524) issue ([79cc31a](https://github.com/leifermendez/bot-whatsapp/commit/79cc31a96f6a9836447cc4e6bb1e1521c54183fe))
+* **contexts:** :bug: fixed [#524](https://github.com/leifermendez/bot-whatsapp/issues/524) issue ([7067b4a](https://github.com/leifermendez/bot-whatsapp/commit/7067b4a80b7938ccfaf1ed141a37d645a1a3a062))
+* **provider:** wwebjs upgrade ([345f256](https://github.com/leifermendez/bot-whatsapp/commit/345f256a1b4a238519dafc15c9a31bc5e6bad4fe))
+* se agrego @bot-whatsapp/portal a package.json ([46a9fa6](https://github.com/leifermendez/bot-whatsapp/commit/46a9fa6793e06600335de998d2bd9d0691b02ca4))
+
### [0.1.17](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.16...v0.1.17) (2023-01-13)
diff --git a/__test__/01-case.test.js b/__test__/01-case.test.js
new file mode 100644
index 0000000..bce4a42
--- /dev/null
+++ b/__test__/01-case.test.js
@@ -0,0 +1,41 @@
+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')
+
+test(`[Caso - 01] Flow Basico`, async () => {
+ const [VALUE_A, VALUE_B] = ['hola', 'buenas']
+
+ const flow = addKeyword(VALUE_A).addAnswer(VALUE_B)
+ const provider = createProvider(PROVIDER_DB)
+ const database = new MOCK_DB()
+
+ createBot({
+ database,
+ flow: createFlow([flow]),
+ provider,
+ })
+
+ provider.delaySendMessage(100, 'message', {
+ from: '000',
+ body: VALUE_A,
+ })
+
+ await delay(100)
+
+ const prevMsg = database.getPrevByNumber('000')
+
+ assert.is(prevMsg.answer, VALUE_B)
+})
+
+test.run()
+
+function delay(ms) {
+ return new Promise((res) => setTimeout(res, ms))
+}
diff --git a/__test__/02-case.test.js b/__test__/02-case.test.js
new file mode 100644
index 0000000..a2a93ec
--- /dev/null
+++ b/__test__/02-case.test.js
@@ -0,0 +1,99 @@
+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 = []) => {
+ console.log('⚡ Server request!')
+ await delay(50)
+ console.log('⚡ Server return!')
+ const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
+ console.log(data)
+ return Promise.resolve(data)
+}
+
+test(`[Caso - 02] Flow (flowDynamic)`, async () => {
+ const MOCK_VALUES = [
+ 'Bienvenido te envio muchas marcas (5510)',
+ 'Seleccione marca del auto a cotizar, con el *número* correspondiente',
+ 'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:',
+ 'Los precios rondan:',
+ ]
+ const provider = createProvider(PROVIDER_DB)
+ const database = new MOCK_DB()
+
+ const flujoPrincipal = addKeyword(['hola'])
+ .addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => {
+ console.log('execute...')
+ const data = await fakeHTTP(['Ford', 'GM', 'BMW'])
+ return flowDynamic(data)
+ })
+ .addAnswer(MOCK_VALUES[1], null, async (ctx, { flowDynamic }) => {
+ const data = await fakeHTTP(['Ranger', 'Explorer'])
+ return flowDynamic(data)
+ })
+ .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
+ const data = await fakeHTTP(['Usado', 'Nuevos'])
+ return flowDynamic(data)
+ })
+ .addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => {
+ const data = await fakeHTTP(['1000', '2000', '3000'])
+ return flowDynamic(data)
+ })
+
+ createBot({
+ database,
+ flow: createFlow([flujoPrincipal]),
+ provider,
+ })
+
+ provider.delaySendMessage(0, 'message', {
+ from: '000',
+ body: 'hola',
+ })
+
+ await delay(1200)
+ const getHistory = database.listHistory.map((i) => i.answer)
+ assert.is(MOCK_VALUES[0], getHistory[0])
+
+ //FlowDynamic
+ assert.is('1 Ford', getHistory[1])
+ assert.is('2 GM', getHistory[2])
+ assert.is('3 BMW', getHistory[3])
+
+ assert.is(MOCK_VALUES[1], getHistory[4])
+
+ //FlowDynamic
+ assert.is('1 Ranger', getHistory[5])
+ assert.is('2 Explorer', getHistory[6])
+
+ assert.is(MOCK_VALUES[2], getHistory[7])
+
+ //FlowDynamic
+ assert.is('1 Usado', getHistory[8])
+ assert.is('2 Nuevos', getHistory[9])
+
+ assert.is(MOCK_VALUES[3], getHistory[10])
+
+ //FlowDynamic
+ assert.is('1 1000', getHistory[11])
+ assert.is('2 2000', getHistory[12])
+ assert.is('3 3000', getHistory[13])
+})
+
+test.run()
+
+function delay(ms) {
+ return new Promise((res) => setTimeout(res, ms))
+}
diff --git a/__test__/03-case.test.js b/__test__/03-case.test.js
new file mode 100644
index 0000000..45c399a
--- /dev/null
+++ b/__test__/03-case.test.js
@@ -0,0 +1,44 @@
+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')
+
+test(`[Caso - 03] Flow puro`, async () => {
+ const MOCK_VALUES = ['Bienvenido a mi tienda', 'Como estas?']
+
+ const provider = createProvider(PROVIDER_DB)
+ const database = new MOCK_DB()
+
+ const flujoPrincipal = addKeyword(['hola'])
+ .addAnswer(MOCK_VALUES[0])
+ .addAnswer(MOCK_VALUES[1])
+
+ createBot({
+ database,
+ flow: createFlow([flujoPrincipal]),
+ provider,
+ })
+
+ provider.delaySendMessage(0, 'message', {
+ from: '000',
+ body: 'hola',
+ })
+
+ await delay(10)
+ const getHistory = database.listHistory.map((i) => i.answer)
+
+ assert.is(MOCK_VALUES[0], getHistory[0])
+ assert.is(MOCK_VALUES[1], getHistory[1])
+})
+
+test.run()
+
+function delay(ms) {
+ return new Promise((res) => setTimeout(res, ms))
+}
diff --git a/__test__/04-case.test.js b/__test__/04-case.test.js
new file mode 100644
index 0000000..2291a0c
--- /dev/null
+++ b/__test__/04-case.test.js
@@ -0,0 +1,82 @@
+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 = []) => {
+ console.log('⚡ Server request!')
+ await delay(50)
+ console.log('⚡ Server return!')
+ const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
+ console.log(data)
+ return Promise.resolve(data)
+}
+
+test(`[Caso - 04] Romper flujo (endFlow)`, async () => {
+ const MOCK_VALUES = [
+ 'Bienvenido te envio muchas marcas (5510)',
+ 'Seleccione marca del auto a cotizar, con el *número* correspondiente',
+ 'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:',
+ 'Los precios rondan:',
+ ]
+ const provider = createProvider(PROVIDER_DB)
+ const database = new MOCK_DB()
+
+ const flujoPrincipal = addKeyword(['hola'])
+ .addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => {
+ console.log('execute...')
+ const data = await fakeHTTP(['Ford', 'GM', 'BMW'])
+ return flowDynamic(data)
+ })
+ .addAnswer(MOCK_VALUES[1], null, async (ctx, { endFlow }) => {
+ return endFlow()
+ })
+ .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
+ const data = await fakeHTTP(['Usado', 'Nuevos'])
+ return flowDynamic(data)
+ })
+ .addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => {
+ const data = await fakeHTTP(['1000', '2000', '3000'])
+ return flowDynamic(data)
+ })
+
+ createBot({
+ database,
+ flow: createFlow([flujoPrincipal]),
+ provider,
+ })
+
+ provider.delaySendMessage(0, 'message', {
+ from: '000',
+ body: 'hola',
+ })
+
+ await delay(1200)
+ const getHistory = database.listHistory.map((i) => i.answer)
+ assert.is(MOCK_VALUES[0], getHistory[0])
+
+ //FlowDynamic
+ assert.is('1 Ford', getHistory[1])
+ assert.is('2 GM', getHistory[2])
+ assert.is('3 BMW', getHistory[3])
+
+ assert.is(MOCK_VALUES[1], getHistory[4])
+ assert.is(undefined, getHistory[5])
+})
+
+test.run()
+
+function delay(ms) {
+ return new Promise((res) => setTimeout(res, ms))
+}
diff --git a/package.json b/package.json
index 354bc44..fda898a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@bot-whatsapp/root",
- "version": "0.1.17",
+ "version": "0.1.18",
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
"main": "app.js",
"private": true,
@@ -24,7 +24,8 @@
"build": "yarn run cli:rollup && yarn run bot:rollup && yarn run provider:rollup && yarn run database:rollup && yarn run contexts:rollup && yarn run create-bot-whatsapp:rollup && yarn run portal:rollup",
"copy.lib": "node ./scripts/move.js",
"test.unit": "node ./node_modules/uvu/bin.js packages test",
- "test.coverage": "node ./node_modules/c8/bin/c8.js npm run test.unit",
+ "test.e2e": "node ./node_modules/uvu/bin.js __test__",
+ "test.coverage": "node ./node_modules/c8/bin/c8.js npm run test.unit && npm run test.e2e",
"test": "npm run test.coverage",
"cli": "node ./packages/cli/bin/cli.js",
"create": "node ./packages/create-bot-whatsapp/bin/create.js",
diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js
index e3efc04..f7051b3 100644
--- a/packages/bot/core/core.class.js
+++ b/packages/bot/core/core.class.js
@@ -21,10 +21,12 @@ class CoreClass {
flowClass
databaseClass
providerClass
- constructor(_flow, _database, _provider) {
+ generalArgs = { blackList: [] }
+ constructor(_flow, _database, _provider, _args) {
this.flowClass = _flow
this.databaseClass = _database
this.providerClass = _provider
+ this.generalArgs = { ...this.generalArgs, ..._args }
for (const { event, func } of this.listenerBusEvents()) {
this.providerClass.on(event, func)
@@ -70,10 +72,12 @@ class CoreClass {
const { body, from } = messageCtxInComming
let msgToSend = []
let fallBackFlag = false
+ let endFlowFlag = false
+ if (this.generalArgs.blackList.includes(from)) return
if (!body) return
if (!body.length) return
- const prevMsg = await this.databaseClass.getPrevByNumber(from)
+ let prevMsg = await this.databaseClass.getPrevByNumber(from)
const refToContinue = this.flowClass.findBySerialize(
prevMsg?.refSerialize
)
@@ -87,16 +91,35 @@ class CoreClass {
this.databaseClass.save(ctxByNumber)
}
+ // 📄 Limpiar cola de procesos
+ const clearQueue = () => {
+ QueuePrincipal.pendingPromise = false
+ QueuePrincipal.queue = []
+ }
+
+ // 📄 Finalizar flujo
+ const endFlow = async () => {
+ prevMsg = null
+ endFlowFlag = true
+ clearQueue()
+ return
+ }
+
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
const sendFlow = async (messageToSend, numberOrId) => {
+ // [1 Paso] esto esta bien!
+
+ if (prevMsg?.options?.capture) await cbEveryCtx(prevMsg?.ref)
const queue = []
for (const ctxMessage of messageToSend) {
+ if (endFlowFlag) return
const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() =>
Promise.all([
- this.sendProviderAndSave(numberOrId, ctxMessage),
- resolveCbEveryCtx(ctxMessage),
+ this.sendProviderAndSave(numberOrId, ctxMessage).then(
+ () => resolveCbEveryCtx(ctxMessage)
+ ),
])
)
}
@@ -113,6 +136,7 @@ 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 }
@@ -122,15 +146,22 @@ class CoreClass {
fallBackFlag = optListMsg.fallback
const parseListMsg = listMsg
- .map(({ body }, index) =>
- toCtx({
+ .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)
+
+ if (endFlowFlag) return
for (const msg of parseListMsg) {
await this.sendProviderAndSave(from, msg)
}
@@ -139,7 +170,6 @@ class CoreClass {
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
const resolveCbEveryCtx = async (ctxMessage) => {
- if (prevMsg?.options?.capture) return cbEveryCtx(prevMsg?.ref)
if (!ctxMessage?.options?.capture)
return await cbEveryCtx(ctxMessage?.ref)
}
@@ -150,20 +180,10 @@ class CoreClass {
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
fallBack,
flowDynamic,
+ endFlow,
})
}
- 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
if (!fallBackFlag && prevMsg?.options?.nested?.length) {
const nestedRef = prevMsg.options.nested
@@ -173,11 +193,6 @@ class CoreClass {
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
- // //TODO AQUI
- // for (const ite of msgToSend) {
- // cbEveryCtx(ite?.ref)
- // }
-
sendFlow(msgToSend, from)
return
}
@@ -225,5 +240,24 @@ class CoreClass {
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
diff --git a/packages/bot/index.js b/packages/bot/index.js
index eb9df24..ac96063 100644
--- a/packages/bot/index.js
+++ b/packages/bot/index.js
@@ -8,8 +8,8 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
* @param {*} args
* @returns
*/
-const createBot = async ({ flow, database, provider }) =>
- new CoreClass(flow, database, provider)
+const createBot = async ({ flow, database, provider }, args = {}) =>
+ new CoreClass(flow, database, provider, args)
/**
* Crear instancia de clase Io (Flow)
diff --git a/packages/bot/io/methods/toCtx.js b/packages/bot/io/methods/toCtx.js
index d29295e..980cbfb 100644
--- a/packages/bot/io/methods/toCtx.js
+++ b/packages/bot/io/methods/toCtx.js
@@ -5,12 +5,12 @@ const { generateRef, generateRefSerialize } = require('../../utils/hash')
* @param options {media:string, buttons:[], capture:true default false}
* @returns
*/
-const toCtx = ({ body, from, prevRef, index }) => {
+const toCtx = ({ body, from, prevRef, options = {}, index }) => {
return {
ref: generateRef(),
keyword: prevRef,
answer: body,
- options: {},
+ options: options ?? {},
from,
refSerialize: generateRefSerialize({ index, answer: body }),
}
diff --git a/packages/bot/package.json b/packages/bot/package.json
index d3f004e..fe542c1 100644
--- a/packages/bot/package.json
+++ b/packages/bot/package.json
@@ -1,6 +1,6 @@
{
"name": "@bot-whatsapp/bot",
- "version": "0.0.66-alpha.0",
+ "version": "0.0.73-alpha.0",
"description": "",
"main": "./lib/bundle.bot.cjs",
"scripts": {
diff --git a/packages/bot/tests/flow.class.test.js b/packages/bot/tests/flow.class.test.js
new file mode 100644
index 0000000..e1c93d7
--- /dev/null
+++ b/packages/bot/tests/flow.class.test.js
@@ -0,0 +1,28 @@
+const { test } = require('uvu')
+const assert = require('uvu/assert')
+const FlowClass = require('../io/flow.class')
+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()
diff --git a/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js
index 25bd2a6..2d0ebd2 100644
--- a/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js
+++ b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js
@@ -117,7 +117,7 @@ class DialogFlowCXContext extends CoreClass {
}
})
- this.sendFlow(listMessages, from)
+ this.sendFlowSimple(listMessages, from)
}
}
diff --git a/packages/contexts/src/dialogflow/dialogflow.class.js b/packages/contexts/src/dialogflow/dialogflow.class.js
index ebd92bc..6a7cda0 100644
--- a/packages/contexts/src/dialogflow/dialogflow.class.js
+++ b/packages/contexts/src/dialogflow/dialogflow.class.js
@@ -107,7 +107,7 @@ class DialogFlowContext extends CoreClass {
...customPayload,
answer: fields?.answer?.stringValue,
}
- this.sendFlow([ctxFromDX], from)
+ this.sendFlowSimple([ctxFromDX], from)
return
}
@@ -115,7 +115,7 @@ class DialogFlowContext extends CoreClass {
answer: queryResult?.fulfillmentText,
}
- this.sendFlow([ctxFromDX], from)
+ this.sendFlowSimple([ctxFromDX], from)
}
}
diff --git a/packages/docs/src/components/widgets/SearchModal.tsx b/packages/docs/src/components/widgets/SearchModal.tsx
new file mode 100644
index 0000000..287a28b
--- /dev/null
+++ b/packages/docs/src/components/widgets/SearchModal.tsx
@@ -0,0 +1,20 @@
+import { component$ } from '@builder.io/qwik'
+
+export const SearchModal = component$(() => {
+ // const state = useStore({
+ // open: false,
+ // src: '',
+ // })
+
+ return (
+
+ )
+})
+
+export const SingleModal = component$(() => {
+ return Modal singlke
+})
diff --git a/packages/docs/src/routes/docs/flows/index.mdx b/packages/docs/src/routes/docs/flows/index.mdx
index 7a2171c..0cb1222 100644
--- a/packages/docs/src/routes/docs/flows/index.mdx
+++ b/packages/docs/src/routes/docs/flows/index.mdx
@@ -23,6 +23,23 @@ const flowPrincipal = addKeyword(['hola', 'alo'])
---
+## blackList
+
+Éste argumento se utiliza para **evitar que el bot se active** cuando los números de la lista activen el bot.
+Es importante que el número **vaya acompañado de su prefijo**, en el caso de España "34".
+
+```js
+createBot({
+ flow: adapterFlow,
+ provider: adapterProvider,
+ database: adapterDB,
+ },{
+ blackList:['34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX']
+ })
+```
+
+---
+
## addKeyword()
Esta funcion se utliza para iniciar un flujo de conversion.
Recibe un `string` o un `array`
@@ -55,7 +72,7 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
- delay: 0 (milisegundos)
- media: url de imagen
- 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
```js
@@ -158,6 +175,64 @@ const flowString = addKeyword('hola')
```
---
+## endFlow()
+
+Esta funcion se utliza para finalizar un flujo con dos o más addAnswer. Un ejemplo de uso sería registrar 3 datos de un usuario en 3 preguntas distinas y
+que el usuario pueda finalizar por él mismo el flujo.
+Como podrás comprobar en el ejemplo siguiente, se puede vincular flowDynamic y todas sus funciones; como por ejemplo botones.
+
+
+
+```js
+const flowFormulario = addKeyword(['Hola'])
+
+.addAnswer(['Hola!','Escriba su *Nombre* para generar su solicitud'],
+{capture: true,buttons:[{body:'❌ Cancelar solicitud'}]},
+async (ctx,{flowDynamic, endFlow})=>{
+ if(ctx.body == '❌ Cancelar solicitud'){
+ await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}])
+ return endFlow()
+ }
+ })
+ .addAnswer(['También necesito tus dos apellidos'],
+ {capture: true,buttons:[{body:'❌ Cancelar solicitud'}]},
+ async (ctx,{flowDynamic, endFlow})=>{
+ if(ctx.body == '❌ Cancelar solicitud'){
+ await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}])
+ return endFlow()
+ }
+ })
+ .addAnswer(['Dejeme su número de teléfono y le llamaré lo antes posible.'],
+{capture: true,buttons:[{body:'❌ Cancelar solicitud'}]},
+async (ctx,{flowDynamic, endFlow})=>{
+ if(ctx.body == '❌ Cancelar solicitud'){
+ await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}])
+ return endFlow()
+ }
+ })
+
+
+
+```
+
+---
+
+
+
+
+
+# QRPortalWeb
+
+Argumento para asignar nombre y puerto al BOT
+
+```js
+QRPortalWeb({name:BOTNAME, port:3005 });
+
+```
+
+---
+
+
{
return (
<>
+
diff --git a/packages/docs/src/routes/index.tsx b/packages/docs/src/routes/index.tsx
index 8ad3b75..9b0f04a 100644
--- a/packages/docs/src/routes/index.tsx
+++ b/packages/docs/src/routes/index.tsx
@@ -10,11 +10,11 @@ import { fetchGithub } from '~/services/github'
import { fetchOpenCollective } from '~/services/opencollective'
import { RequestHandlerNetlify } from '@builder.io/qwik-city/middleware/netlify-edge'
import { GITHUB_TOKEN } from './docs/constant'
+// import { SearchModal } from '~/components/widgets/SearchModal'
export const onGet: RequestHandlerNetlify = async ({ platform }) => {
const CHECK_GITHUB_TOKEN =
(platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
- console.log(`[🚩 platform]: `, GITHUB_TOKEN)
const dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN)
const dataOpenCollective = await fetchOpenCollective()
return {
diff --git a/packages/docs/src/services/opencollective.ts b/packages/docs/src/services/opencollective.ts
index 2eb60c8..9a89f25 100644
--- a/packages/docs/src/services/opencollective.ts
+++ b/packages/docs/src/services/opencollective.ts
@@ -4,7 +4,7 @@
*/
export const fetchOpenCollective = async () => {
const data = await fetch(
- `https://opencollective.com/bot-whatsapp/members/users.json?limit=10&offset=0`,
+ `https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`,
{
method: 'GET',
}
diff --git a/packages/portal/server/@qwik-city-not-found-paths.js b/packages/portal/server/@qwik-city-not-found-paths.js
index f5f657d..473076c 100644
--- a/packages/portal/server/@qwik-city-not-found-paths.js
+++ b/packages/portal/server/@qwik-city-not-found-paths.js
@@ -1,7 +1,7 @@
const notFounds = [
[
'/',
- '\n\n\n
\n
\n
404 Resource Not Found\n
\n \n\n\n
404 Resource Not Found
\n\n',
+ '\n\n \n
\n
\n
404 Resource Not Found\n
\n \n \n \n
404 Resource Not Found
\n \n\n',
],
]
function getNotFound(p) {
diff --git a/packages/portal/server/@qwik-city-static-paths.js b/packages/portal/server/@qwik-city-static-paths.js
index 1afa65f..1835f6b 100644
--- a/packages/portal/server/@qwik-city-static-paths.js
+++ b/packages/portal/server/@qwik-city-static-paths.js
@@ -1,5 +1,4 @@
const staticPaths = new Set([
- '/',
'/favicon.svg',
'/manifest.json',
'/q-manifest.json',