diff --git a/TODO.md b/TODO.md index 2d12ed7..e932143 100644 --- a/TODO.md +++ b/TODO.md @@ -1 +1,5 @@ -- [ ] Cuando Envian Sticket devuelve mensaje raro \ No newline at end of file +- [ ] Cuando Envian Sticket devuelve mensaje raro +- [ ] Posibilidad de en el capture meter todo un nuevo CTX de FLOW .addAnswer('Marca la opcion',{capture:true, join:CTX}) +- [ ] .addKeyword('1') no funciona con 1 caracter +- [ ] sensitivy viene activado por defecto +- [ ] colocar mensaje esperando conectando whatsapp (provider) \ No newline at end of file diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 132b6d0..224c3c7 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -47,7 +47,8 @@ class CoreClass { * @private * @param {*} ctxMessage */ - handleMsg = async ({ body, from }) => { + handleMsg = async (messageInComming) => { + const { body, from } = messageInComming let msgToSend = [] const prevMsg = await this.databaseClass.getPrevByNumber(from) @@ -64,6 +65,17 @@ class CoreClass { const refToContinue = this.flowClass.findBySerialize( prevMsg.refSerialize ) + + if (refToContinue && prevMsg?.options?.callback) { + const indexFlow = this.flowClass.findIndexByRef( + refToContinue?.ref + ) + + this.flowClass.allCallbacks[indexFlow].callback( + messageInComming + ) + } + msgToSend = this.flowClass.find(refToContinue?.ref, true) || [] } else { msgToSend = this.flowClass.find(body) || [] diff --git a/packages/bot/index.js b/packages/bot/index.js index 072e0c0..e5b6e1c 100644 --- a/packages/bot/index.js +++ b/packages/bot/index.js @@ -1,7 +1,7 @@ const CoreClass = require('./core/core.class') const ProviderClass = require('./provider/provider.class') const FlowClass = require('./io/flow.class') -const { addKeyword, addAnswer } = require('./io/methods') +const { addKeyword, addAnswer, toSerialize } = require('./io/methods') /** * Crear instancia de clase Bot @@ -38,6 +38,7 @@ module.exports = { createProvider, addKeyword, addAnswer, + toSerialize, ProviderClass, CoreClass, } diff --git a/packages/bot/io/flow.class.js b/packages/bot/io/flow.class.js index 83d413a..a031b57 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -1,19 +1,55 @@ const { toSerialize } = require('./methods') class FlowClass { - flow + allContexts = [] + allCallbacks = [] + flowSerialize = [] + flowRaw = [] constructor(_flow) { - this.flow = toSerialize(_flow) + if (!Array.isArray(_flow)) throw new Error('Esto debe ser un ARRAY') + _flow.forEach((ctxFlow, parentIndex) => { + const callbacks = ctxFlow.ctx?.callbacks || [] + const contexts = ctxFlow.ctx?.contexts || [] + + callbacks.forEach((deepCallbacks) => { + if (deepCallbacks && contexts[parentIndex]) { + const ctxChild = contexts[parentIndex] + deepCallbacks.callback(null, ctxChild) + } + }) + }) + + this.flowRaw = _flow + this.allContexts = _flow + .map((ctxs) => ctxs.ctx.contexts) + .flat(2) + .map((c, i) => ({ getCtx: c?.getCtx, index: i })) + + this.allCallbacks = _flow + .map((cbIn) => cbIn.ctx.callbacks) + .flat(2) + .map((c, i) => ({ callback: c?.callback, index: i })) + + const mergeToJsonSerialize = Object.keys(_flow) + .map((indexObjectFlow) => _flow[indexObjectFlow].toJson()) + .flat(2) + + this.flowSerialize = toSerialize(mergeToJsonSerialize) } find = (keyOrWord, symbol = false) => { let capture = false let messages = [] - let refSymbol + let refSymbol = null - const findIn = (keyOrWord, symbol = false, flow = this.flow) => { + const findIn = ( + keyOrWord, + symbol = false, + flow = this.flowSerialize + ) => { capture = refSymbol?.options?.capture || false if (capture) return messages + if (symbol) { refSymbol = flow.find((c) => c.keyword === keyOrWord) if (refSymbol?.answer) messages.push(refSymbol) @@ -29,7 +65,9 @@ class FlowClass { } findBySerialize = (refSerialize) => - this.flow.find((r) => r.refSerialize === refSerialize) + this.flowSerialize.find((r) => r.refSerialize === refSerialize) + + findIndexByRef = (ref) => this.flowSerialize.findIndex((r) => r.ref === ref) } module.exports = FlowClass diff --git a/packages/bot/io/methods/addAnswer.js b/packages/bot/io/methods/addAnswer.js index ace843e..aa7b8e3 100644 --- a/packages/bot/io/methods/addAnswer.js +++ b/packages/bot/io/methods/addAnswer.js @@ -6,43 +6,78 @@ const { toJson } = require('./toJson') * @param options {media:string, buttons:[], capture:true default false} * @returns */ -const addAnswer = (inCtx) => (answer, options) => { - const getAnswerOptions = () => ({ - media: typeof options?.media === 'string' ? `${options?.media}` : null, - buttons: Array.isArray(options?.buttons) ? options.buttons : [], - capture: - typeof options?.capture === 'boolean' ? options?.capture : false, - }) +const addAnswer = + (inCtx) => + (answer, options, cb = null) => { + const getAnswerOptions = () => ({ + media: + typeof options?.media === 'string' ? `${options?.media}` : null, + buttons: Array.isArray(options?.buttons) ? options.buttons : [], + capture: + typeof options?.capture === 'boolean' + ? options?.capture + : false, + child: + typeof options?.child === 'string' ? `${options?.child}` : null, + }) - const lastCtx = inCtx.hasOwnProperty('ctx') ? inCtx.ctx : inCtx - const ctxAnswer = () => { - const ref = `ans_${generateRef()}` + const lastCtx = inCtx.hasOwnProperty('ctx') ? inCtx.ctx : inCtx + const ctxAnswer = () => { + const ref = `ans_${generateRef()}` - const options = { - ...getAnswerOptions(), - keyword: {}, + const callback = + typeof cb === 'function' + ? cb + : () => console.log('Callback no definida') + + const options = { + ...getAnswerOptions(), + keyword: {}, + callback: !!cb, + } + + const json = [].concat(inCtx.json).concat([ + { + ref, + keyword: lastCtx.ref, + answer, + options, + }, + ]) + + const callbacks = [].concat(inCtx.callbacks).concat([ + { + ref: lastCtx.ref, + callback, + }, + ]) + + const contexts = [].concat(inCtx.contexts).concat([ + { + ref: lastCtx.ref, + getCtx: () => lastCtx, + }, + ]) + + return { + ...lastCtx, + ref, + answer, + json, + options, + callbacks, + contexts, + } } - const json = [].concat(inCtx.json).concat([ - { - ref, - keyword: lastCtx.ref, - answer, - options, - }, - ]) + const ctx = ctxAnswer() - return { ...lastCtx, ref, answer, json, options } + return { + ctx, + ref: ctx.ref, + addAnswer: addAnswer(ctx), + toJson: toJson(ctx), + } } - const ctx = ctxAnswer() - - return { - ctx, - ref: ctx.ref, - addAnswer: addAnswer(ctx), - toJson: toJson(ctx), - } -} - module.exports = { addAnswer } diff --git a/packages/bot/io/methods/addKeyword.js b/packages/bot/io/methods/addKeyword.js index 18bcaa5..e17f9be 100644 --- a/packages/bot/io/methods/addKeyword.js +++ b/packages/bot/io/methods/addKeyword.js @@ -1,10 +1,6 @@ const { generateRef } = require('../../utils/hash') const { addAnswer } = require('./addAnswer') const { toJson } = require('./toJson') -/** - * addKeyword: - * Es necesario que genere id|hash - */ /** * @@ -12,11 +8,6 @@ const { toJson } = require('./toJson') * @param {*} options {sensitive:boolean} default false */ const addKeyword = (keyword, options) => { - /** - * Esta funcion deberia parsear y validar las opciones - * del keyword - * @returns - */ const parseOptions = () => { const defaultProperties = { sensitive: diff --git a/packages/bot/tests/methods.test.js b/packages/bot/tests/methods.test.js index e108e43..5f7e79d 100644 --- a/packages/bot/tests/methods.test.js +++ b/packages/bot/tests/methods.test.js @@ -31,6 +31,8 @@ test('Debere probar toSerialize', () => { .addAnswer('Segundo!') .toJson() + console.log(MAIN_CTX) + const [ANSWER_A] = MAIN_CTX assert.is( diff --git a/packages/bot/utils/hash.js b/packages/bot/utils/hash.js index 888df6b..19e3c30 100644 --- a/packages/bot/utils/hash.js +++ b/packages/bot/utils/hash.js @@ -1,7 +1,13 @@ const crypto = require('crypto') -const generateRef = () => { - return crypto.randomUUID() +/** + * Generamos un UUID unico con posibilidad de tener un prefijo + * @param {*} prefix + * @returns + */ +const generateRef = (prefix = false) => { + const id = crypto.randomUUID() + return prefix ? `${prefix}_${id}` : id } /**