diff --git a/.husky/commit-msg b/.husky/commit-msg index 4002db7..3d3fb52 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npx --no -- commitlint --edit +npm run lint:fix && npx --no -- commitlint --edit diff --git a/.prettierignore b/.prettierignore index 547ec21..7fffea9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,5 @@ packages/**/lib -packages/docs/*.json +packages/docs/ **/.git **/.svn **/.hg diff --git a/.prettierrc.json b/.prettierrc.json index e74ed9f..f0db82f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,5 +2,6 @@ "trailingComma": "es5", "tabWidth": 4, "semi": false, - "singleQuote": true + "singleQuote": true, + "printWidth": 120 } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 0d0e52b..1ace260 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["xyc.vscode-mdx-preview"] + "recommendations": ["xyc.vscode-mdx-preview", "vivaxy.vscode-conventional-commits", "mhutchie.git-graph"] } diff --git a/README.md b/README.md index 777209f..af4b124 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # Chatbot Library ![](https://img.shields.io/npm/v/@bot-whatsapp/bot?color=%2300c200&label=%40bot-whatsapp) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) -[![BotWhatsapp Releases(Prod)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml/badge.svg)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml) - +[![](https://img.shields.io/discord/915193197645402142?logo=discord)](https://link.codigoencasa.com/DISCORD)

@@ -112,14 +111,35 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. Null + + + devrlbusiness +
+ Developer RL Business +
+ + + + + Gregoriotecnico +
+ Null +
+ jlferrete
Jose Luis Ferrete Olarte
- - + + + + lisandroprada +
+ Null +
+ 6rak0 @@ -140,7 +160,8 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
Rodrigo Mendoza Cabrera
- + + yond1994 diff --git a/__test__/01-case.test.js b/__test__/01-case.test.js index bce4a42..57ae08c 100644 --- a/__test__/01-case.test.js +++ b/__test__/01-case.test.js @@ -2,12 +2,7 @@ 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') +const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') test(`[Caso - 01] Flow Basico`, async () => { const [VALUE_A, VALUE_B] = ['hola', 'buenas'] diff --git a/__test__/05-case.test.js b/__test__/05-case.test.js index 6ca65d0..f61d114 100644 --- a/__test__/05-case.test.js +++ b/__test__/05-case.test.js @@ -2,12 +2,7 @@ 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') +const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') /** * Falsear peticion async @@ -21,11 +16,7 @@ const fakeHTTP = async (fakeData = []) => { } test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { - const MOCK_VALUES = [ - '¿CUal es tu email?', - 'Continuamos....', - '¿Cual es tu edad?', - ] + const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?'] const provider = createProvider(PROVIDER_DB) const database = new MOCK_DB() @@ -39,26 +30,20 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { const validation = ctx.body.includes('@') if (validation) { - const getDataFromApi = await fakeHTTP([ - 'Gracias por tu email se ha validado de manera correcta', - ]) + const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta']) return flowDynamic(getDataFromApi) } return fallBack(validation) } ) .addAnswer(MOCK_VALUES[1]) - .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(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({ @@ -98,10 +83,7 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { 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('1 Gracias por tu email se ha validado de manera correcta', getHistory[4]) assert.is(MOCK_VALUES[1], getHistory[5]) assert.is(MOCK_VALUES[2], getHistory[6]) assert.is('20', getHistory[7]) diff --git a/__test__/07-case.test.js b/__test__/07-case.test.js new file mode 100644 index 0000000..6eb8e42 --- /dev/null +++ b/__test__/07-case.test.js @@ -0,0 +1,92 @@ +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) +} + +let STATE_APP = {} + +test(`[Caso - 07] Retornar estado`, async () => { + const MOCK_VALUES = ['¿Cual es tu nombre?', '¿Cual es tu edad?', 'Tu datos son:'] + const provider = createProvider(PROVIDER_DB) + const database = new MOCK_DB() + + const flujoPrincipal = addKeyword(['hola']) + .addAnswer( + MOCK_VALUES[0], + { + capture: true, + }, + async (ctx, { flowDynamic, fallBack }) => { + STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], name: ctx.body } + + flowDynamic('Gracias por tu nombre!') + } + ) + .addAnswer( + MOCK_VALUES[1], + { + capture: true, + }, + async (ctx, { flowDynamic, endFlow }) => { + STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], age: ctx.body } + + await flowDynamic('Gracias por tu edad!') + } + ) + .addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => { + flowDynamic(`Nombre: ${STATE_APP[ctx.from].name} Edad: ${STATE_APP[ctx.from].age}`) + }) + .addAnswer('🤖🤖 Gracias por tu participacion') + + createBot({ + database, + flow: createFlow([flujoPrincipal]), + provider, + }) + + provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + provider.delaySendMessage(20, 'message', { + from: '000', + body: 'Leifer', + }) + + provider.delaySendMessage(40, 'message', { + from: '000', + body: '90', + }) + + await delay(1200) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + assert.is('Leifer', getHistory[1]) + assert.is('Gracias por tu nombre!', getHistory[2]) + assert.is('¿Cual es tu edad?', getHistory[3]) + assert.is('90', getHistory[4]) + assert.is('Gracias por tu edad!', getHistory[5]) + assert.is('Tu datos son:', getHistory[6]) + assert.is('Nombre: Leifer Edad: 90', getHistory[7]) + assert.is('🤖🤖 Gracias por tu participacion', getHistory[8]) + assert.is(undefined, getHistory[9]) +}) + +test.run() + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} diff --git a/__test__/08-case.test.js b/__test__/08-case.test.js new file mode 100644 index 0000000..82fc46a --- /dev/null +++ b/__test__/08-case.test.js @@ -0,0 +1,43 @@ +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 - 08] Regular expression on keyword`, async () => { + const provider = createProvider(PROVIDER_DB) + const database = new MOCK_DB() + + const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm` + const flujoPrincipal = addKeyword(REGEX_CREDIT_NUMBER, { regex: true }) + .addAnswer(`Gracias por proporcionar un numero de tarjeta valido`) + .addAnswer('Fin!') + + createBot({ + database, + flow: createFlow([flujoPrincipal]), + provider, + }) + + provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + provider.delaySendMessage(20, 'message', { + from: '000', + body: '374245455400126', + }) + + await delay(40) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is('Gracias por proporcionar un numero de tarjeta valido', getHistory[0]) + assert.is('Fin!', getHistory[1]) + assert.is(undefined, getHistory[2]) +}) + +test.run() + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} diff --git a/__test__/09-case.test.js b/__test__/09-case.test.js new file mode 100644 index 0000000..417ce31 --- /dev/null +++ b/__test__/09-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_MOCK = require('../packages/provider/src/mock') +const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index') + +let PROVIDER = undefined + +test(`[Caso - 09] Check provider WS`, async () => { + const [VALUE_A, VALUE_B] = ['hola', 'buenas'] + + const flow = addKeyword(VALUE_A).addAnswer(VALUE_B, null, async (_, { provider }) => { + PROVIDER = provider + }) + const provider = createProvider(PROVIDER_MOCK) + 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) + assert.is(typeof PROVIDER.sendMessage, 'function') +}) + +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 9b329cc..29cf5d1 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -43,8 +43,7 @@ class CoreClass { }, { event: 'require_action', - func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) => - printer(instructions, title), + func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) => printer(instructions, title), }, { event: 'ready', @@ -52,8 +51,7 @@ class CoreClass { }, { event: 'auth_failure', - func: ({ instructions }) => - printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'), + func: ({ instructions }) => printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'), }, { @@ -78,9 +76,7 @@ class CoreClass { if (!body.length) return let prevMsg = await this.databaseClass.getPrevByNumber(from) - const refToContinue = this.flowClass.findBySerialize( - prevMsg?.refSerialize - ) + const refToContinue = this.flowClass.findBySerialize(prevMsg?.refSerialize) if (prevMsg?.ref) { const ctxByNumber = toCtx({ @@ -93,10 +89,7 @@ class CoreClass { // 📄 Crar CTX de mensaje (uso private) const createCtxMessage = (payload = {}, index = 0) => { - const body = - typeof payload === 'string' - ? payload - : payload?.body ?? payload?.answer + const body = typeof payload === 'string' ? payload : payload?.body ?? payload?.answer const media = payload?.media ?? null const buttons = payload?.buttons ?? [] const capture = payload?.capture ?? false @@ -118,30 +111,16 @@ class CoreClass { // 📄 Finalizar flujo const endFlow = async (message = null) => { - prevMsg = null endFlowFlag = true - if (message) - this.sendProviderAndSave(from, createCtxMessage(message)) + if (message) this.sendProviderAndSave(from, createCtxMessage(message)) clearQueue() - return - } - - // 📄 Continuar con el siguiente flujo - const continueFlow = async () => { - const cotinueMessage = - this.flowClass.find(refToContinue?.ref, true) || [] - sendFlow(cotinueMessage, from, { continue: true }) + sendFlow([]) return } // 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx - const sendFlow = async ( - messageToSend, - numberOrId, - options = { continue: false } - ) => { - if (!options.continue && prevMsg?.options?.capture) - await cbEveryCtx(prevMsg?.ref) + const sendFlow = async (messageToSend, numberOrId, options = { prev: prevMsg }) => { + if (options.prev?.options?.capture) await cbEveryCtx(options.prev?.ref) const queue = [] for (const ctxMessage of messageToSend) { @@ -150,9 +129,7 @@ class CoreClass { if (delayMs) await delay(delayMs) QueuePrincipal.enqueue(() => Promise.all([ - this.sendProviderAndSave(numberOrId, ctxMessage).then( - () => resolveCbEveryCtx(ctxMessage) - ), + this.sendProviderAndSave(numberOrId, ctxMessage).then(() => resolveCbEveryCtx(ctxMessage)), ]) ) } @@ -160,20 +137,26 @@ class CoreClass { } // 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje - const fallBack = async (next = false, message = null) => { + const fallBack = async (validation = false, message = null) => { QueuePrincipal.queue = [] - if (next) return continueFlow() - return this.sendProviderAndSave(from, { + + if (validation) { + const currentPrev = await this.databaseClass.getPrevByNumber(from) + const nextFlow = await this.flowClass.find(refToContinue?.ref, true) + const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize) + + return sendFlow(filterNextFlow, from, { prev: undefined }) + } + + await this.sendProviderAndSave(from, { ...prevMsg, - answer: - typeof message === 'string' - ? message - : message?.body ?? prevMsg.answer, + answer: typeof message === 'string' ? message : message?.body ?? prevMsg.answer, options: { ...prevMsg.options, - buttons: message?.buttons ?? prevMsg.options?.buttons, + buttons: prevMsg.options?.buttons, }, }) + return } // 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes @@ -182,31 +165,45 @@ class CoreClass { const flowDynamic = async (listMsg = []) => { if (!Array.isArray(listMsg)) listMsg = [listMsg] - const parseListMsg = listMsg.map((opt, index) => - createCtxMessage(opt, index) - ) + const parseListMsg = listMsg.map((opt, index) => createCtxMessage(opt, index)) + const currentPrev = await this.databaseClass.getPrevByNumber(from) + + const skipContinueFlow = async () => { + const nextFlow = await this.flowClass.find(refToContinue?.ref, true) + const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize) + const isContinueFlow = filterNextFlow.map((i) => i.keyword).includes(currentPrev?.ref) + return { + continue: !isContinueFlow, + contexts: filterNextFlow, + } + } if (endFlowFlag) return for (const msg of parseListMsg) { await this.sendProviderAndSave(from, msg) } - return continueFlow() + + const continueFlowData = await skipContinueFlow() + + if (continueFlowData.continue) return sendFlow(continueFlowData.contexts, from, { prev: undefined }) + return } // 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback const resolveCbEveryCtx = async (ctxMessage) => { - if (!ctxMessage?.options?.capture) - return await cbEveryCtx(ctxMessage?.ref) + if (!ctxMessage?.options?.capture) return await cbEveryCtx(ctxMessage?.ref) } // 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo const cbEveryCtx = async (inRef) => { + const provider = this.providerClass + if (!this.flowClass.allCallbacks[inRef]) return Promise.resolve() return this.flowClass.allCallbacks[inRef](messageCtxInComming, { + provider, fallBack, flowDynamic, endFlow, - continueFlow, }) } @@ -246,10 +243,9 @@ class CoreClass { */ sendProviderAndSave = (numberOrId, ctxMessage) => { const { answer } = ctxMessage - return Promise.all([ - this.providerClass.sendMessage(numberOrId, answer, ctxMessage), - this.databaseClass.save({ ...ctxMessage, from: numberOrId }), - ]) + return this.providerClass + .sendMessage(numberOrId, answer, ctxMessage) + .then(() => this.databaseClass.save({ ...ctxMessage, from: numberOrId })) } /** @@ -279,9 +275,7 @@ class CoreClass { for (const ctxMessage of messageToSend) { const delayMs = ctxMessage?.options?.delay || 0 if (delayMs) await delay(delayMs) - QueuePrincipal.enqueue(() => - this.sendProviderAndSave(numberOrId, ctxMessage) - ) + QueuePrincipal.enqueue(() => this.sendProviderAndSave(numberOrId, ctxMessage)) } return Promise.all(queue) } diff --git a/packages/bot/index.js b/packages/bot/index.js index ac96063..fe03d60 100644 --- a/packages/bot/index.js +++ b/packages/bot/index.js @@ -8,8 +8,7 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods') * @param {*} args * @returns */ -const createBot = async ({ flow, database, provider }, args = {}) => - new CoreClass(flow, database, provider, args) +const createBot = async ({ flow, database, provider }, args = {}) => new CoreClass(flow, database, provider, args) /** * Crear instancia de clase Io (Flow) @@ -29,8 +28,7 @@ const createFlow = (args) => { */ const createProvider = (providerClass = class {}, args = null) => { const providerInstance = new providerClass(args) - if (!providerClass.prototype instanceof ProviderClass) - throw new Error('El provider no implementa ProviderClass') + if (!providerClass.prototype instanceof ProviderClass) throw new Error('El provider no implementa ProviderClass') return providerInstance } diff --git a/packages/bot/io/flow.class.js b/packages/bot/io/flow.class.js index 458c423..13de732 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -25,9 +25,17 @@ class FlowClass { let refSymbol = null overFlow = overFlow ?? this.flowSerialize + const customRegex = (str = null) => { + if (typeof str !== 'string') return + const instanceRegex = new RegExp(str) + return instanceRegex.test(str) + } + /** Retornar expresion regular para buscar coincidencia */ - const mapSensitive = (str, flag = false) => { - const regexSensitive = flag ? 'g' : 'i' + const mapSensitive = (str, mapOptions = { sensitive: false, regex: false }) => { + if (mapOptions.regex) return customRegex(str) + + const regexSensitive = mapOptions.sensitive ? 'g' : 'i' if (Array.isArray(str)) { return new RegExp(str.join('|'), regexSensitive) } @@ -36,6 +44,7 @@ class FlowClass { const findIn = (keyOrWord, symbol = false, flow = overFlow) => { const sensitive = refSymbol?.options?.sensitive || false + const regex = refSymbol?.options?.regex || false capture = refSymbol?.options?.capture || false if (capture) return messages @@ -46,7 +55,7 @@ class FlowClass { if (refSymbol?.ref) findIn(refSymbol.ref, true) } else { refSymbol = flow.find((c) => { - return mapSensitive(c.keyword, sensitive).test(keyOrWord) + return mapSensitive(c.keyword, { sensitive, regex }).test(keyOrWord) }) if (refSymbol?.ref) findIn(refSymbol.ref, true) return messages @@ -56,8 +65,7 @@ class FlowClass { return messages } - findBySerialize = (refSerialize) => - this.flowSerialize.find((r) => r.refSerialize === refSerialize) + findBySerialize = (refSerialize) => this.flowSerialize.find((r) => r.refSerialize === refSerialize) findIndexByRef = (ref) => this.flowSerialize.findIndex((r) => r.ref === ref) } diff --git a/packages/bot/io/methods/addAnswer.js b/packages/bot/io/methods/addAnswer.js index f0ccdad..5236c14 100644 --- a/packages/bot/io/methods/addAnswer.js +++ b/packages/bot/io/methods/addAnswer.js @@ -17,15 +17,10 @@ const addAnswer = * @returns */ const getAnswerOptions = () => ({ - media: - typeof options?.media === 'string' ? `${options?.media}` : null, + 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, + capture: typeof options?.capture === 'boolean' ? options?.capture : false, + child: typeof options?.child === 'string' ? `${options?.child}` : null, delay: typeof options?.delay === 'number' ? options?.delay : 0, }) @@ -49,8 +44,7 @@ const addAnswer = * Esta funcion aplana y busca los callback anidados de los hijos * @returns */ - const getCbFromNested = () => - flatObject(Array.isArray(nested) ? nested : [nested]) + const getCbFromNested = () => flatObject(Array.isArray(nested) ? nested : [nested]) const callback = typeof cb === 'function' ? cb : () => null diff --git a/packages/bot/io/methods/addKeyword.js b/packages/bot/io/methods/addKeyword.js index e17f9be..50a5c0c 100644 --- a/packages/bot/io/methods/addKeyword.js +++ b/packages/bot/io/methods/addKeyword.js @@ -8,12 +8,14 @@ const { toJson } = require('./toJson') * @param {*} options {sensitive:boolean} default false */ const addKeyword = (keyword, options) => { + if (typeof keyword !== 'string' && !Array.isArray(keyword)) { + throw new Error('DEBE_SER_STRING_ARRAY_REGEX') + } + const parseOptions = () => { const defaultProperties = { - sensitive: - typeof options?.sensitive === 'boolean' - ? options?.sensitive - : false, + sensitive: typeof options?.sensitive === 'boolean' ? options?.sensitive : false, + regex: typeof options?.regex === 'boolean' ? options?.regex : false, } return defaultProperties diff --git a/packages/bot/package.json b/packages/bot/package.json index 3d4acf3..563cd74 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.91-alpha.0", + "version": "0.0.96-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { diff --git a/packages/bot/provider/provider.class.js b/packages/bot/provider/provider.class.js index 212f042..57d7185 100644 --- a/packages/bot/provider/provider.class.js +++ b/packages/bot/provider/provider.class.js @@ -20,8 +20,7 @@ class ProviderClass extends EventEmitter { */ sendMessage = async (userId, message) => { - if (NODE_ENV !== 'production') - console.log('[sendMessage]', { userId, message }) + if (NODE_ENV !== 'production') console.log('[sendMessage]', { userId, message }) return message } } diff --git a/packages/bot/tests/bot.class.test.js b/packages/bot/tests/bot.class.test.js index d74fdad..4db4ca8 100644 --- a/packages/bot/tests/bot.class.test.js +++ b/packages/bot/tests/bot.class.test.js @@ -2,13 +2,7 @@ const { test } = require('uvu') const assert = require('uvu/assert') const FlowClass = require('../io/flow.class') const MockProvider = require('../../../__mocks__/mock.provider') -const { - createBot, - CoreClass, - createFlow, - createProvider, - ProviderClass, -} = require('../index') +const { createBot, CoreClass, createFlow, createProvider, ProviderClass } = require('../index') class MockFlow { allCallbacks = { ref: () => 1 } @@ -100,20 +94,13 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => { await createBot(setting) /// Escuchamos eventos - mockProvider.on( - 'require_action', - (r) => (responseEvents['require_action'] = r) - ) + mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r)) mockProvider.on('ready', (r) => (responseEvents['ready'] = r)) mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r)) mockProvider.on('message', (r) => (responseEvents['message'] = r)) /// Emitimos eventos - mockProvider.delaySendMessage( - 0, - 'require_action', - MOCK_EVENTS.require_action - ) + mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action) mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready) mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure) mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message) @@ -121,21 +108,12 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => { await delay(0) /// Testeamos eventos - assert.is( - JSON.stringify(responseEvents.require_action), - JSON.stringify(MOCK_EVENTS.require_action) - ) + assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action)) assert.is(responseEvents.ready, MOCK_EVENTS.ready) - assert.is( - JSON.stringify(responseEvents.auth_failure), - JSON.stringify(MOCK_EVENTS.auth_failure) - ) + assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure)) - assert.is( - JSON.stringify(responseEvents.message), - JSON.stringify(MOCK_EVENTS.message) - ) + assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message)) }) test(`[Bot] Probando Flujos Internos`, async () => { @@ -166,20 +144,13 @@ test(`[Bot] Probando Flujos Internos`, async () => { await createBot(setting) /// Escuchamos eventos - mockProvider.on( - 'require_action', - (r) => (responseEvents['require_action'] = r) - ) + mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r)) mockProvider.on('ready', (r) => (responseEvents['ready'] = r)) mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r)) mockProvider.on('message', (r) => (responseEvents['message'] = r)) /// Emitimos eventos - mockProvider.delaySendMessage( - 0, - 'require_action', - MOCK_EVENTS.require_action - ) + mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action) mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready) mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure) mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message) @@ -187,21 +158,12 @@ test(`[Bot] Probando Flujos Internos`, async () => { await delay(0) /// Testeamos eventos - assert.is( - JSON.stringify(responseEvents.require_action), - JSON.stringify(MOCK_EVENTS.require_action) - ) + assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action)) assert.is(responseEvents.ready, MOCK_EVENTS.ready) - assert.is( - JSON.stringify(responseEvents.auth_failure), - JSON.stringify(MOCK_EVENTS.auth_failure) - ) + assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure)) - assert.is( - JSON.stringify(responseEvents.message), - JSON.stringify(MOCK_EVENTS.message) - ) + assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message)) }) test(`[Bot] Probando Flujos Nested`, async () => { @@ -234,20 +196,13 @@ test(`[Bot] Probando Flujos Nested`, async () => { botInstance.sendProviderAndSave('xxxxx', 'xxxxx') botInstance.continue('xxxxx', 'xxxxx') /// Escuchamos eventos - mockProvider.on( - 'require_action', - (r) => (responseEvents['require_action'] = r) - ) + mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r)) mockProvider.on('ready', (r) => (responseEvents['ready'] = r)) mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r)) mockProvider.on('message', (r) => (responseEvents['message'] = r)) /// Emitimos eventos - mockProvider.delaySendMessage( - 0, - 'require_action', - MOCK_EVENTS.require_action - ) + mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action) mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready) mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure) mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message) @@ -255,21 +210,12 @@ test(`[Bot] Probando Flujos Nested`, async () => { await delay(0) /// Testeamos eventos - assert.is( - JSON.stringify(responseEvents.require_action), - JSON.stringify(MOCK_EVENTS.require_action) - ) + assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action)) assert.is(responseEvents.ready, MOCK_EVENTS.ready) - assert.is( - JSON.stringify(responseEvents.auth_failure), - JSON.stringify(MOCK_EVENTS.auth_failure) - ) + assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure)) - assert.is( - JSON.stringify(responseEvents.message), - JSON.stringify(MOCK_EVENTS.message) - ) + assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message)) }) test.run() diff --git a/packages/bot/tests/methods.test.js b/packages/bot/tests/methods.test.js index 10b0977..f030731 100644 --- a/packages/bot/tests/methods.test.js +++ b/packages/bot/tests/methods.test.js @@ -35,10 +35,7 @@ test('Debere probar toSerialize', () => { const ARRANGE = { keyword: ['hola!', 'ole'], } - const MAIN_CTX = addKeyword(ARRANGE.keyword) - .addAnswer('Segundo!') - .addAnswer('Segundo!') - .toJson() + const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer('Segundo!').addAnswer('Segundo!').toJson() const [ANSWER_A] = MAIN_CTX @@ -71,9 +68,7 @@ test('Debere probar la anidación', () => { answer_A: 'Bienvenido', answer_B: 'Continuar', } - const MAIN_CTX = addKeyword(ARRANGE.keyword) - .addAnswer(ARRANGE.answer_A) - .addAnswer(ARRANGE.answer_B) + const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer(ARRANGE.answer_A).addAnswer(ARRANGE.answer_B) assert.is(MAIN_CTX.ctx.answer, ARRANGE.answer_B) }) @@ -107,10 +102,7 @@ test('Debere probar error las addAnswer', () => { }) test('Obtener toJson', () => { - const [ctxA, ctxB, ctxC] = addKeyword('hola') - .addAnswer('pera!') - .addAnswer('chao') - .toJson() + const [ctxA, ctxB, ctxC] = addKeyword('hola').addAnswer('pera!').addAnswer('chao').toJson() assert.is(ctxA.keyword, 'hola') assert.match(ctxA.ref, /^key_/) diff --git a/packages/bot/utils/delay.js b/packages/bot/utils/delay.js index 021fafe..a6534c0 100644 --- a/packages/bot/utils/delay.js +++ b/packages/bot/utils/delay.js @@ -1,4 +1,3 @@ -const delay = (miliseconds) => - new Promise((res) => setTimeout(res, miliseconds)) +const delay = (miliseconds) => new Promise((res) => setTimeout(res, miliseconds)) module.exports = { delay } diff --git a/packages/bot/utils/flattener.js b/packages/bot/utils/flattener.js index 875736d..ddc823f 100644 --- a/packages/bot/utils/flattener.js +++ b/packages/bot/utils/flattener.js @@ -3,9 +3,7 @@ const flatObject = (listArray = []) => { if (!listArray.length) return {} - const cbNestedObj = cbNestedList - .map(({ ctx }) => ctx?.callbacks) - .filter((i) => !!i) + const cbNestedObj = cbNestedList.map(({ ctx }) => ctx?.callbacks).filter((i) => !!i) const queueCb = cbNestedObj.reduce((acc, current) => { const getKeys = Object.keys(current) const parse = getKeys.map((icb, i) => ({ diff --git a/packages/bot/utils/hash.js b/packages/bot/utils/hash.js index 84a25db..6902d58 100644 --- a/packages/bot/utils/hash.js +++ b/packages/bot/utils/hash.js @@ -16,9 +16,6 @@ const generateRef = (prefix = false) => { * @returns */ const generateRefSerialize = ({ index, answer, keyword }) => - crypto - .createHash('md5') - .update(JSON.stringify({ index, answer, keyword })) - .digest('hex') + crypto.createHash('md5').update(JSON.stringify({ index, answer, keyword })).digest('hex') module.exports = { generateRef, generateRefSerialize } diff --git a/packages/bot/utils/interactive.js b/packages/bot/utils/interactive.js index c317a7f..44905cf 100644 --- a/packages/bot/utils/interactive.js +++ b/packages/bot/utils/interactive.js @@ -4,9 +4,7 @@ const printer = (message, title) => { if (NODE_ENV !== 'test') { // console.clear() if (title) console.log(bgRed(`${title}`)) - console.log( - yellow(Array.isArray(message) ? message.join('\n') : message) - ) + console.log(yellow(Array.isArray(message) ? message.join('\n') : message)) console.log(``) } } diff --git a/packages/cli/check/index.js b/packages/cli/check/index.js index 454f67c..5befb8a 100644 --- a/packages/cli/check/index.js +++ b/packages/cli/check/index.js @@ -5,15 +5,9 @@ const checkNodeVersion = () => { return new Promise((resolve, reject) => { console.log(bgCyan('🚀 Revisando tu Node.js')) const version = process.version - const majorVersion = parseInt( - version.replace('v', '').split('.').shift() - ) + const majorVersion = parseInt(version.replace('v', '').split('.').shift()) if (majorVersion < 16) { - console.error( - red( - `🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}` - ) - ) + console.error(red(`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`)) console.log(``) reject('ERROR_NODE') } diff --git a/packages/cli/clean/index.js b/packages/cli/clean/index.js index 6b7f6fd..60b8092 100644 --- a/packages/cli/clean/index.js +++ b/packages/cli/clean/index.js @@ -2,10 +2,7 @@ const rimraf = require('rimraf') const { yellow } = require('kleur') const { join } = require('path') -const PATH_WW = [ - join(process.cwd(), '.wwebjs_auth'), - join(process.cwd(), 'session.json'), -] +const PATH_WW = [join(process.cwd(), '.wwebjs_auth'), join(process.cwd(), 'session.json')] const cleanSession = () => { const queue = [] diff --git a/packages/cli/configuration/index.js b/packages/cli/configuration/index.js index 50565d9..2ce6077 100644 --- a/packages/cli/configuration/index.js +++ b/packages/cli/configuration/index.js @@ -23,11 +23,7 @@ const JSON_TEMPLATE = { const PATH_CONFIG = join(process.cwd(), 'config.json') const jsonConfig = () => { - return writeFile( - PATH_CONFIG, - JSON.stringify(JSON_TEMPLATE, null, 2), - 'utf-8' - ) + return writeFile(PATH_CONFIG, JSON.stringify(JSON_TEMPLATE, null, 2), 'utf-8') } module.exports = { jsonConfig } diff --git a/packages/cli/install/tool.js b/packages/cli/install/tool.js index 8095cd0..a74cec6 100644 --- a/packages/cli/install/tool.js +++ b/packages/cli/install/tool.js @@ -20,13 +20,9 @@ const installDeps = (pkgManager, packageList) => { const installSingle = (pkgInstall) => () => { new Promise((resolve) => { try { - childProcess = spawn( - pkgManager, - [PKG_OPTION[pkgManager], pkgInstall], - { - stdio: 'inherit', - } - ) + childProcess = spawn(pkgManager, [PKG_OPTION[pkgManager], pkgInstall], { + stdio: 'inherit', + }) childProcess.on('error', (e) => { console.error(e) diff --git a/packages/cli/interactive/index.js b/packages/cli/interactive/index.js index 53cc885..d65ca19 100644 --- a/packages/cli/interactive/index.js +++ b/packages/cli/interactive/index.js @@ -30,9 +30,7 @@ const startInteractive = async () => { await nextSteps() } catch (e) { console.error(bgRed(`Ups! 🙄 algo no va bien.`)) - console.error( - bgRed(`Revisa los requerimientos minimos en la documentacion`) - ) + console.error(bgRed(`Revisa los requerimientos minimos en la documentacion`)) } } @@ -82,8 +80,7 @@ const nextSteps = async () => { const { outDir = '', providerDb = [], providerWs = [] } = response const createApp = async (templateName = null) => { - if (!templateName) - throw new Error('TEMPLATE_NAME_INVALID: ', templateName) + if (!templateName) throw new Error('TEMPLATE_NAME_INVALID: ', templateName) const possiblesPath = [ join(__dirname, '..', '..', 'starters', 'apps', templateName), @@ -115,11 +112,7 @@ const nextSteps = async () => { const vendorProvider = async () => { const [answer] = providerWs if (!providerWs.length) { - console.log( - red( - `Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar` - ) - ) + console.log(red(`Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar`)) process.exit(1) } return answer @@ -132,11 +125,7 @@ const nextSteps = async () => { const dbProvider = async () => { const [answer] = providerDb if (!providerDb.length) { - console.log( - red( - `Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar` - ) - ) + console.log(red(`Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar`)) process.exit(1) } return answer diff --git a/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js index 2d0ebd2..6be4f9e 100644 --- a/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js +++ b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js @@ -38,10 +38,8 @@ class DialogFlowCXContext extends CoreClass { * */ } - if (!this.optionsDX.location.length) - throw new Error('LOCATION_NO_ENCONTRADO') - if (!this.optionsDX.agentId.length) - throw new Error('AGENTID_NO_ENCONTRADO') + if (!this.optionsDX.location.length) throw new Error('LOCATION_NO_ENCONTRADO') + if (!this.optionsDX.agentId.length) throw new Error('AGENTID_NO_ENCONTRADO') const rawJson = readFileSync(GOOGLE_ACCOUNT_PATH, 'utf-8') const { project_id, private_key, client_email } = JSON.parse(rawJson) @@ -86,9 +84,7 @@ class DialogFlowCXContext extends CoreClass { }, } - const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [ - null, - ] + const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null] const listMessages = single.queryResult.responseMessages.map((res) => { if (res.message == 'text') { @@ -96,17 +92,11 @@ class DialogFlowCXContext extends CoreClass { } if (res.message == 'payload') { - const { - media = null, - buttons = [], - answer = '', - } = res.payload.fields - const buttonsArray = buttons?.listValue?.values?.map( - (btnValue) => { - const { stringValue } = btnValue.structValue.fields.body - return { body: stringValue } - } - ) + const { media = null, buttons = [], answer = '' } = res.payload.fields + const buttonsArray = buttons?.listValue?.values?.map((btnValue) => { + const { stringValue } = btnValue.structValue.fields.body + return { body: stringValue } + }) return { answer: answer?.stringValue, options: { diff --git a/packages/contexts/src/dialogflow-cx/index.js b/packages/contexts/src/dialogflow-cx/index.js index 2a561c4..13c479e 100644 --- a/packages/contexts/src/dialogflow-cx/index.js +++ b/packages/contexts/src/dialogflow-cx/index.js @@ -5,8 +5,7 @@ const DialogCXFlowClass = require('./dialogflow-cx.class') * @param {*} args * @returns */ -const createBotDialog = async ({ database, provider }, _options) => - new DialogCXFlowClass(database, provider, _options) +const createBotDialog = async ({ database, provider }, _options) => new DialogCXFlowClass(database, provider, _options) module.exports = { createBotDialog, diff --git a/packages/contexts/src/dialogflow/dialogflow.class.js b/packages/contexts/src/dialogflow/dialogflow.class.js index 6a7cda0..33df66b 100644 --- a/packages/contexts/src/dialogflow/dialogflow.class.js +++ b/packages/contexts/src/dialogflow/dialogflow.class.js @@ -65,10 +65,7 @@ class DialogFlowContext extends CoreClass { * para evitar este problema. * https://github.com/codigoencasa/bot-whatsapp/pull/140 */ - const session = this.sessionClient.projectAgentSessionPath( - this.projectId, - from - ) + const session = this.sessionClient.projectAgentSessionPath(this.projectId, from) const reqDialog = { session, queryInput: { @@ -79,15 +76,11 @@ class DialogFlowContext extends CoreClass { }, } - const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [ - null, - ] + const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null] const { queryResult } = single - const msgPayload = queryResult?.fulfillmentMessages?.find( - (a) => a.message === 'payload' - ) + const msgPayload = queryResult?.fulfillmentMessages?.find((a) => a.message === 'payload') // Revisamos si el dialogFlow tiene multimedia if (msgPayload && msgPayload?.payload) { diff --git a/packages/contexts/src/dialogflow/index.js b/packages/contexts/src/dialogflow/index.js index e988f50..377fd88 100644 --- a/packages/contexts/src/dialogflow/index.js +++ b/packages/contexts/src/dialogflow/index.js @@ -5,8 +5,7 @@ const DialogFlowClass = require('./dialogflow.class') * @param {*} args * @returns */ -const createBotDialog = async ({ database, provider }) => - new DialogFlowClass(database, provider) +const createBotDialog = async ({ database, provider }) => new DialogFlowClass(database, provider) module.exports = { createBotDialog, diff --git a/packages/contexts/src/mock/index.js b/packages/contexts/src/mock/index.js index b609be5..4e2e10f 100644 --- a/packages/contexts/src/mock/index.js +++ b/packages/contexts/src/mock/index.js @@ -5,8 +5,7 @@ const MockClass = require('./mock.class') * @param {*} args * @returns */ -const createBotMock = async ({ database, provider }) => - new MockClass(database, provider) +const createBotMock = async ({ database, provider }) => new MockClass(database, provider) module.exports = { createBotMock, diff --git a/packages/database/src/mock/index.js b/packages/database/src/mock/index.js index 4c07c03..2ab91a0 100644 --- a/packages/database/src/mock/index.js +++ b/packages/database/src/mock/index.js @@ -10,7 +10,10 @@ class MockDatabase { constructor() {} getPrevByNumber = (from) => { - const history = this.listHistory.slice().reverse() + const history = this.listHistory + .slice() + .reverse() + .filter((i) => !!i.keyword) return history.find((a) => a.from === from) } diff --git a/packages/database/src/mongo/index.js b/packages/database/src/mongo/index.js index 6af68f0..9ea3fa5 100644 --- a/packages/database/src/mongo/index.js +++ b/packages/database/src/mongo/index.js @@ -24,12 +24,7 @@ class MongoAdapter { } getPrevByNumber = async (from) => { - const result = await this.db - .collection('history') - .find({ from }) - .sort({ _id: -1 }) - .limit(1) - .toArray() + const result = await this.db.collection('history').find({ from }).sort({ _id: -1 }).limit(1).toArray() return result[0] } diff --git a/packages/database/src/mysql/index.js b/packages/database/src/mysql/index.js index e01b55a..0beea56 100644 --- a/packages/database/src/mysql/index.js +++ b/packages/database/src/mysql/index.js @@ -46,18 +46,8 @@ class MyslAdapter { }) save = (ctx) => { - const values = [ - [ - ctx.ref, - ctx.keyword, - ctx.answer, - ctx.refSerialize, - ctx.from, - JSON.stringify(ctx.options), - ], - ] - const sql = - 'INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?' + const values = [[ctx.ref, ctx.keyword, ctx.answer, ctx.refSerialize, ctx.from, JSON.stringify(ctx.options)]] + const sql = 'INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?' this.db.query(sql, [values], (err) => { if (err) throw err @@ -71,14 +61,14 @@ class MyslAdapter { const tableName = 'history' const sql = `CREATE TABLE ${tableName} - (id INT AUTO_INCREMENT PRIMARY KEY, - ref varchar(255) NOT NULL, - keyword varchar(255) NOT NULL, - answer longtext NOT NULL, - refSerialize varchar(255) NOT NULL, - phone varchar(255) NOT NULL, - options longtext NOT NULL - )` + (id INT AUTO_INCREMENT PRIMARY KEY, + ref varchar(255) NOT NULL, + keyword varchar(255) NOT NULL, + answer longtext NOT NULL, + refSerialize varchar(255) NOT NULL, + phone varchar(255) NOT NULL, + options longtext NOT NULL) + CHARACTER SET utf8mb4 COLLATE utf8mb4_General_ci` this.db.query(sql, (err) => { if (err) throw err diff --git a/packages/docs/src/assets/fonts/generated/IBMPlexMono-Regular.module.css b/packages/docs/src/assets/fonts/generated/IBMPlexMono-Regular.module.css index deddf7c..f0ab1c0 100644 --- a/packages/docs/src/assets/fonts/generated/IBMPlexMono-Regular.module.css +++ b/packages/docs/src/assets/fonts/generated/IBMPlexMono-Regular.module.css @@ -8,6 +8,5 @@ font-family: IBMPlexMono-Regular; src: url(IBMPlexMono-Regular-subset.woff2) format('woff2'), url(IBMPlexMono-Regular-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58, - U+61-65, U+67-69, U+6C-76; + unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58, U+61-65, U+67-69, U+6C-76; } diff --git a/packages/docs/src/assets/fonts/generated/IBMPlexMono-SemiBold.module.css b/packages/docs/src/assets/fonts/generated/IBMPlexMono-SemiBold.module.css index e2fdf72..6b47965 100644 --- a/packages/docs/src/assets/fonts/generated/IBMPlexMono-SemiBold.module.css +++ b/packages/docs/src/assets/fonts/generated/IBMPlexMono-SemiBold.module.css @@ -8,6 +8,6 @@ font-family: IBMPlexMono-SemiBold; src: url(IBMPlexMono-SemiBold-subset.woff2) format('woff2'), url(IBMPlexMono-SemiBold-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47, - U+4E, U+4F, U+52-55, U+57, U+59, U+65, U+68, U+6F, U+72, U+74; + unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47, U+4E, U+4F, U+52-55, U+57, U+59, U+65, + U+68, U+6F, U+72, U+74; } diff --git a/packages/docs/src/assets/fonts/generated/Pally-Variable.module.css b/packages/docs/src/assets/fonts/generated/Pally-Variable.module.css index 74aa400..e899bbf 100644 --- a/packages/docs/src/assets/fonts/generated/Pally-Variable.module.css +++ b/packages/docs/src/assets/fonts/generated/Pally-Variable.module.css @@ -6,9 +6,8 @@ @font-face { font-family: Pally-Variable; - src: url(Pally-Variable-subset.woff2) format('woff2'), - url(Pally-Variable-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46, - U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69, U+6B-77, U+79; + src: url(Pally-Variable-subset.woff2) format('woff2'), url(Pally-Variable-subset.zopfli.woff) format('woff'); + unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46, U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69, + U+6B-77, U+79; font-weight: 400 700; } diff --git a/packages/docs/src/assets/fonts/generated/SourceSerifPro-Regular.module.css b/packages/docs/src/assets/fonts/generated/SourceSerifPro-Regular.module.css index b1a323f..a491d8c 100644 --- a/packages/docs/src/assets/fonts/generated/SourceSerifPro-Regular.module.css +++ b/packages/docs/src/assets/fonts/generated/SourceSerifPro-Regular.module.css @@ -8,6 +8,5 @@ font-family: SourceSerifPro-Regular; src: url(SourceSerifPro-Regular-subset.woff2) format('woff2'), url(SourceSerifPro-Regular-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55, - U+61-65, U+67-69, U+6B-76, U+79; + unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55, U+61-65, U+67-69, U+6B-76, U+79; } diff --git a/packages/docs/src/assets/fonts/generated/Synonym-Variable.module.css b/packages/docs/src/assets/fonts/generated/Synonym-Variable.module.css index b834dbb..00cb8df 100644 --- a/packages/docs/src/assets/fonts/generated/Synonym-Variable.module.css +++ b/packages/docs/src/assets/fonts/generated/Synonym-Variable.module.css @@ -6,9 +6,8 @@ @font-face { font-family: Synonym-Variable; - src: url(Synonym-Variable-subset.woff2) format('woff2'), - url(Synonym-Variable-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47, - U+49, U+4B-4F, U+53-55, U+57-59, U+61, U+63-65, U+67-69, U+6C-76; + src: url(Synonym-Variable-subset.woff2) format('woff2'), url(Synonym-Variable-subset.zopfli.woff) format('woff'); + unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47, U+49, U+4B-4F, U+53-55, U+57-59, U+61, + U+63-65, U+67-69, U+6C-76; font-weight: 400 700; } diff --git a/packages/docs/src/assets/fonts/generated/TenorSans-Regular.module.css b/packages/docs/src/assets/fonts/generated/TenorSans-Regular.module.css index 819cfa3..b3dbfc6 100644 --- a/packages/docs/src/assets/fonts/generated/TenorSans-Regular.module.css +++ b/packages/docs/src/assets/fonts/generated/TenorSans-Regular.module.css @@ -6,8 +6,7 @@ @font-face { font-family: TenorSans-Regular; - src: url(TenorSans-Regular-subset.woff2) format('woff2'), - url(TenorSans-Regular-subset.zopfli.woff) format('woff'); - unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54, - U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F, U+72-75, U+79; + src: url(TenorSans-Regular-subset.woff2) format('woff2'), url(TenorSans-Regular-subset.zopfli.woff) format('woff'); + unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54, U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F, + U+72-75, U+79; } diff --git a/packages/docs/src/assets/images/digital-ocean.png b/packages/docs/src/assets/images/digital-ocean.png new file mode 100644 index 0000000..0d0163b Binary files /dev/null and b/packages/docs/src/assets/images/digital-ocean.png differ diff --git a/packages/docs/src/components/atoms/DigitalOcean.tsx b/packages/docs/src/components/atoms/DigitalOcean.tsx new file mode 100644 index 0000000..fc97537 --- /dev/null +++ b/packages/docs/src/components/atoms/DigitalOcean.tsx @@ -0,0 +1,189 @@ +export const DigitalOcean = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/packages/docs/src/components/atoms/Logo.tsx b/packages/docs/src/components/atoms/Logo.tsx index b5e1199..97a7fa1 100644 --- a/packages/docs/src/components/atoms/Logo.tsx +++ b/packages/docs/src/components/atoms/Logo.tsx @@ -5,14 +5,7 @@ import logoSrc from '~/assets/images/chatbot-whatsapp.png?width=64&height=64&png export default component$(() => ( - Qwind Logo + Qwind Logo Chatbot )) diff --git a/packages/docs/src/components/atoms/Netlify.tsx b/packages/docs/src/components/atoms/Netlify.tsx index 9047eab..3090113 100644 --- a/packages/docs/src/components/atoms/Netlify.tsx +++ b/packages/docs/src/components/atoms/Netlify.tsx @@ -1,11 +1,5 @@ export const Netlify = () => ( - + { {head.title} - + {head.meta.map((m) => ( diff --git a/packages/docs/src/components/core/Social.tsx b/packages/docs/src/components/core/Social.tsx index 43d6ac2..f620441 100644 --- a/packages/docs/src/components/core/Social.tsx +++ b/packages/docs/src/components/core/Social.tsx @@ -34,14 +34,8 @@ export const Social = () => { content="https://campaign.codigoencasa.com" /> */} - - + + @@ -52,10 +46,7 @@ export const Social = () => { name="twitter:title" content="💻 Conviértete en un Programador Backend aprendiendo todo de Cloud y Nodejs" /> - + ) } diff --git a/packages/docs/src/components/core/ToggleMenu.tsx b/packages/docs/src/components/core/ToggleMenu.tsx index 51779fc..567fd46 100644 --- a/packages/docs/src/components/core/ToggleMenu.tsx +++ b/packages/docs/src/components/core/ToggleMenu.tsx @@ -27,9 +27,7 @@ export default component$((props: ItemProps) => { // TODO: document.body.classList.toggle('overflow-hidden') document.getElementById('header')?.classList.toggle('h-screen') - document - .querySelector('#header nav') - ?.classList.toggle('hidden') + document.querySelector('#header nav')?.classList.toggle('hidden') }} > diff --git a/packages/docs/src/components/core/ToggleTheme.tsx b/packages/docs/src/components/core/ToggleTheme.tsx index 00de98e..6ef1196 100644 --- a/packages/docs/src/components/core/ToggleTheme.tsx +++ b/packages/docs/src/components/core/ToggleTheme.tsx @@ -10,16 +10,13 @@ interface ItemProps { export default component$((props: ItemProps) => { const { iconClass } = props const store = useStore({ - theme: - (typeof window !== 'undefined' && window?.localStorage?.theme) || - undefined, + theme: (typeof window !== 'undefined' && window?.localStorage?.theme) || undefined, }) useClientEffect$(() => { store.theme = window.localStorage.theme === 'dark' || - (!('theme' in window.localStorage) && - window.matchMedia('(prefers-color-scheme: dark)').matches) + (!('theme' in window.localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light' }) @@ -42,11 +39,7 @@ export default component$((props: ItemProps) => { } }} > - {store.theme == 'dark' ? ( - - ) : ( - - )} + {store.theme == 'dark' ? : } ) }) diff --git a/packages/docs/src/components/icons/IconArrowDownRight.tsx b/packages/docs/src/components/icons/IconArrowDownRight.tsx index 8adfab2..5fd5087 100644 --- a/packages/docs/src/components/icons/IconArrowDownRight.tsx +++ b/packages/docs/src/components/icons/IconArrowDownRight.tsx @@ -7,9 +7,7 @@ export const IconArrowDownRight = (props: ItemProps) => { return ( { diff --git a/packages/docs/src/components/icons/IconMoon.tsx b/packages/docs/src/components/icons/IconMoon.tsx index fa65ec0..296951f 100644 --- a/packages/docs/src/components/icons/IconMoon.tsx +++ b/packages/docs/src/components/icons/IconMoon.tsx @@ -7,9 +7,7 @@ export const IconMoon = (props: ItemProps) => { return (
-

- {props.user.login} -
+
{props.user.login}
diff --git a/packages/docs/src/components/widgets/Collaborators.tsx b/packages/docs/src/components/widgets/Collaborators.tsx index 23f2844..cfd2d24 100644 --- a/packages/docs/src/components/widgets/Collaborators.tsx +++ b/packages/docs/src/components/widgets/Collaborators.tsx @@ -32,8 +32,7 @@ export default component$((props: { users: User[] }) => { Super estrellas

- Todo es posible gracias a el mayor recursos de todos, el - recurso humano. Tu tambien puedes{' '} + Todo es posible gracias a el mayor recursos de todos, el recurso humano. Tu tambien puedes{' '} formar parte diff --git a/packages/docs/src/components/widgets/ExtraBar.tsx b/packages/docs/src/components/widgets/ExtraBar.tsx index fda47b2..0d9ae34 100644 --- a/packages/docs/src/components/widgets/ExtraBar.tsx +++ b/packages/docs/src/components/widgets/ExtraBar.tsx @@ -15,8 +15,8 @@ export default component$(() => { 📄 Editar esta pagina

- Forma parte de esta comunidad mejorando la documentación - siente libre de poder agregar o editar lo que quieras + Forma parte de esta comunidad mejorando la documentación siente libre de poder agregar o editar + lo que quieras

diff --git a/packages/docs/src/components/widgets/FAQs.tsx b/packages/docs/src/components/widgets/FAQs.tsx index 28aa2c1..5834e24 100644 --- a/packages/docs/src/components/widgets/FAQs.tsx +++ b/packages/docs/src/components/widgets/FAQs.tsx @@ -56,13 +56,9 @@ export default component$(() => { {question} - {answer - .split('\n\n') - .map((paragraph) => ( -

- {paragraph} -

- ))} + {answer.split('\n\n').map((paragraph) => ( +

{paragraph}

+ ))} ))} diff --git a/packages/docs/src/components/widgets/Features.tsx b/packages/docs/src/components/widgets/Features.tsx index 4888086..ddd3dc8 100644 --- a/packages/docs/src/components/widgets/Features.tsx +++ b/packages/docs/src/components/widgets/Features.tsx @@ -50,13 +50,11 @@ export default component$(() => { Caracteristicas

- Nuestras principales{' '} - funciones + Nuestras principales funciones

- El secreto es mantener los procesos repetitivos en - procesos automatizados simples, por eso te mostramos en - que destacamos. + El secreto es mantener los procesos repetitivos en procesos automatizados simples, por eso te + mostramos en que destacamos.

@@ -70,12 +68,8 @@ export default component$(() => {
-

- {title} -

-

- {description} -

+

{title}

+

{description}

))} diff --git a/packages/docs/src/components/widgets/Hero.tsx b/packages/docs/src/components/widgets/Hero.tsx index b3761f8..01ee042 100644 --- a/packages/docs/src/components/widgets/Hero.tsx +++ b/packages/docs/src/components/widgets/Hero.tsx @@ -9,36 +9,24 @@ import { src as placeholder } from '~/assets/images/chatbot-whatsapp.png?width=4 export default component$(() => { return ( -
+

- Crear chatbot{' '} - - WhatsApp - - {' '} - en minutos + Crear chatbot WhatsApp + en minutos

- - Con esta libreria,{' '} - + Con esta libreria, - puedes configurar respuestas - automatizadas para preguntas frecuentes + puedes configurar respuestas automatizadas para preguntas frecuentes {' '} - , recibir y responder mensajes de manera - automatizada, y hacer un seguimiento de las - interacciones con los clientes. Además, - nuestro Chatbot se integra fácilmente con - otros sistemas y herramientas que ya esté - utilizando en su negocio. + , recibir y responder mensajes de manera automatizada, y hacer un seguimiento de las + interacciones con los clientes. Además, nuestro Chatbot se integra fácilmente con + otros sistemas y herramientas que ya esté utilizando en su negocio.

@@ -48,10 +36,7 @@ export default component$(() => {
- + Ver documentación { Miembros

- Conviértete en un miembro destacado y forma parte del - proyecto y disfruta de manera adelantada de las - actualizaciones{' '} - + Conviértete en un miembro destacado y forma parte del proyecto y disfruta de manera adelantada + de las actualizaciones{' '} + Únete

diff --git a/packages/docs/src/components/widgets/NavBar.tsx b/packages/docs/src/components/widgets/NavBar.tsx index 56915c9..5b332bc 100644 --- a/packages/docs/src/components/widgets/NavBar.tsx +++ b/packages/docs/src/components/widgets/NavBar.tsx @@ -5,55 +5,45 @@ import { DocumentationCtx } from '~/contexts' /** * options = [] array con la lista de opciones de la documentacion */ -export default component$( - ({ options = [] }: { options: DocumentationCtx[] }) => { - return ( -
- {options.map((item, i) => ( - - ))} -
- ) - } -) +export default component$(({ options = [] }: { options: DocumentationCtx[] }) => { + return ( +
+ {options.map((item, i) => ( + + ))} +
+ ) +}) -export const UlCompoent = component$( - (porps: { title: string; list: { link: string; name: string }[] }) => { - return ( -
    -
  • -
    - {porps.title} -
    - +export const UlCompoent = component$((porps: { title: string; list: { link: string; name: string }[] }) => { + return ( +
      +
    • +
      {porps.title}
      + +
    • +
    + ) +}) + +export const LiComponent = component$((porps: { list: { link: string; name: string }[] }) => { + const location = useLocation() + const currentPage = location.pathname + return ( +
      + {porps.list.map((opt) => ( +
    • + + {opt.name} +
    • -
    - ) - } -) - -export const LiComponent = component$( - (porps: { list: { link: string; name: string }[] }) => { - const location = useLocation() - const currentPage = location.pathname - return ( -
      - {porps.list.map((opt) => ( -
    • - - {opt.name} - -
    • - ))} -
    - ) - } -) + ))} +
+ ) +}) diff --git a/packages/docs/src/components/widgets/Navigation.tsx b/packages/docs/src/components/widgets/Navigation.tsx index 779a787..092ed93 100644 --- a/packages/docs/src/components/widgets/Navigation.tsx +++ b/packages/docs/src/components/widgets/Navigation.tsx @@ -1,74 +1,63 @@ import { component$ } from '@builder.io/qwik' -export const ButtonLink = component$( - (props: { name: string; link: string; direction: 'left' | 'right' }) => { - const ArrowRight = () => ( - - - - ) +export const ButtonLink = component$((props: { name: string; link: string; direction: 'left' | 'right' }) => { + const ArrowRight = () => ( + + + + ) - const ArrowLeft = () => ( - - - - ) + const ArrowLeft = () => ( + + + + ) - return ( - - {props.direction === 'left' ? ( - <> - - {props.name} - - ) : ( - <> - {props.name} - - - )} - - ) - } -) + return ( + + {props.direction === 'left' ? ( + <> + + {props.name} + + ) : ( + <> + {props.name} + + + )} + + ) +}) -export default component$( - (props: { pages: ({ name: string; link: string } | null)[] }) => { - const { pages } = props - return ( -
-
- {pages[0] ? ( - - ) : null} - {pages[1] ? ( - - ) : null} -
+export default component$((props: { pages: ({ name: string; link: string } | null)[] }) => { + const { pages } = props + return ( +
+
+ {pages[0] ? : null} + {pages[1] ? : null}
- ) - } -) +
+ ) +}) diff --git a/packages/docs/src/components/widgets/SponsorBar.tsx b/packages/docs/src/components/widgets/SponsorBar.tsx index c0d8183..f355691 100644 --- a/packages/docs/src/components/widgets/SponsorBar.tsx +++ b/packages/docs/src/components/widgets/SponsorBar.tsx @@ -7,6 +7,8 @@ import { src as qwik } from '~/assets/images/qwik.png?width=100&metadata' import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata' // @ts-ignore import { src as netlify } from '~/assets/images/full-logo-light.png?width=100&metadata' +// @ts-ignore +import { src as digitalOcean } from '~/assets/images/digital-ocean.png?width=100&metadata' /** * options = [] array con la lista de opciones de la documentacion @@ -41,7 +43,20 @@ export default component$(() => { Qwind Hero Image (Cool dog) + + + +
  • + + + DigitalOcean diff --git a/packages/docs/src/components/widgets/Stats.tsx b/packages/docs/src/components/widgets/Stats.tsx index c4dc31a..0721ba7 100644 --- a/packages/docs/src/components/widgets/Stats.tsx +++ b/packages/docs/src/components/widgets/Stats.tsx @@ -5,33 +5,25 @@ export default component$(() => {
    -
    - 132K -
    +
    132K

    Downloads

    -
    - 24.8K -
    +
    24.8K

    Stars

    -
    - 10.3K -
    +
    10.3K

    Forks

    -
    - 48.4K -
    +
    48.4K

    Users

    diff --git a/packages/docs/src/contexts/index.tsx b/packages/docs/src/contexts/index.tsx index 7282539..ca33495 100644 --- a/packages/docs/src/contexts/index.tsx +++ b/packages/docs/src/contexts/index.tsx @@ -13,5 +13,4 @@ export interface User { avatar_url: string } -export const GlobalStore = - createContext('documentation-site') +export const GlobalStore = createContext('documentation-site') diff --git a/packages/docs/src/root.tsx b/packages/docs/src/root.tsx index 2cddda0..61c3906 100644 --- a/packages/docs/src/root.tsx +++ b/packages/docs/src/root.tsx @@ -1,14 +1,5 @@ -import { - component$, - useContextProvider, - useStore, - useStyles$, -} from '@builder.io/qwik' -import { - QwikCityProvider, - RouterOutlet, - ServiceWorkerRegister, -} from '@builder.io/qwik-city' +import { component$, useContextProvider, useStore, useStyles$ } from '@builder.io/qwik' +import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from '@builder.io/qwik-city' import { RouterHead } from '~/components/core/RouterHead' import { DarkThemeLauncher } from '~/components/core/DarkThemeLauncher' @@ -78,10 +69,7 @@ export default component$(() => { - + diff --git a/packages/docs/src/routes/docs/database/index.mdx b/packages/docs/src/routes/docs/database/index.mdx index dab499f..01eb796 100644 --- a/packages/docs/src/routes/docs/database/index.mdx +++ b/packages/docs/src/routes/docs/database/index.mdx @@ -4,11 +4,10 @@ import Navigation from '../../../components/widgets/Navigation' # DataBase (Base de datos) - ⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar - algunas configuracion adicional como **user, host, password** para esos - casos te recomendamos guiarte de los - **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** - o si gustas puedes editar esta documentación para ir agregando más info + ⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como + **user, host, password** para esos casos te recomendamos guiarte de los + **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta + documentación para ir agregando más info Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo diff --git a/packages/docs/src/routes/docs/essential/index.mdx b/packages/docs/src/routes/docs/essential/index.mdx index 8187544..0f0dc45 100644 --- a/packages/docs/src/routes/docs/essential/index.mdx +++ b/packages/docs/src/routes/docs/essential/index.mdx @@ -22,12 +22,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder** Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles ```js -const { - createBot, - createProvider, - createFlow, - addKeyword, -} = require('@bot-whatsapp/bot') +const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot') const flowPrincipal = addKeyword(['hola', 'alo']) .addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?']) @@ -39,11 +34,10 @@ const flowPrincipal = addKeyword(['hola', 'alo']) ## Provider (Proveedor) - ⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar - algunas configuracion adicional como **token, api, etc.** para esos casos te - recomendamos guiarte de los - **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** - o si gustas puedes editar esta documentación para ir agregando más info + ⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar algunas configuracion adicional como + **token, api, etc.** para esos casos te recomendamos guiarte de los + **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta + documentación para ir agregando más info Es la pieza que conectara tu flujo con Whatsapp. En este chatbot tenemos varios proveedores disponibles la mayoria gratis pero tambien tenemos integracion la api oficial de whatsapp o twilio @@ -71,11 +65,10 @@ Los proveedores disponibles hasta el momento son los siguientes: ## DataBase (Base de datos) - ⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar - algunas configuracion adicional como **user, host, password** para esos - casos te recomendamos guiarte de los - **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** - o si gustas puedes editar esta documentación para ir agregando más info + ⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como + **user, host, password** para esos casos te recomendamos guiarte de los + **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta + documentación para ir agregando más info Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo diff --git a/packages/docs/src/routes/docs/example/index.mdx b/packages/docs/src/routes/docs/example/index.mdx index 8daded3..057fcc6 100644 --- a/packages/docs/src/routes/docs/example/index.mdx +++ b/packages/docs/src/routes/docs/example/index.mdx @@ -5,12 +5,7 @@ import Navigation from '../../../components/widgets/Navigation' Si copias y pegas este codigo y tu entorno de trabajo cumple con todos los requesitos te debe funcionar abajo explico muy por encima ```js -const { - createBot, - createProvider, - createFlow, - addKeyword, -} = require('@bot-whatsapp/bot') +const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot') const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp') const MockAdapter = require('@bot-whatsapp/database/mock') @@ -42,12 +37,7 @@ main() En esta parte solo estamos declaramos las dependencias que vamos a utilizar. Si quieres saber a fondo cada una de las funciones te recomiendo pasarte por la seccion de **[conceptos](/docs/concepts)** ```js -const { - createBot, - createProvider, - createFlow, - addKeyword, -} = require('@bot-whatsapp/bot') +const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot') const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp') const MockAdapter = require('@bot-whatsapp/database/mock') diff --git a/packages/docs/src/routes/docs/flows/index.mdx b/packages/docs/src/routes/docs/flows/index.mdx index 94b1f59..0c2cf0b 100644 --- a/packages/docs/src/routes/docs/flows/index.mdx +++ b/packages/docs/src/routes/docs/flows/index.mdx @@ -9,12 +9,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder** Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles ```js -const { - createBot, - createProvider, - createFlow, - addKeyword, -} = require('@bot-whatsapp/bot') +const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot') const flowPrincipal = addKeyword(['hola', 'alo']) .addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?']) @@ -81,37 +76,21 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()` ```js const { addKeyword } = require('@bot-whatsapp/bot') -const flowString = addKeyword('hola').addAnswer( - 'Este mensaje se enviara 1 segundo despues', - { - delay: 1000, - } -) +const flowString = addKeyword('hola').addAnswer('Este mensaje se enviara 1 segundo despues', { + delay: 1000, +}) -const flowString = addKeyword('hola').addAnswer( - 'Este mensaje envia una imagen', - { - media: 'https://i.imgur.com/0HpzsEm.png', - } -) +const flowString = addKeyword('hola').addAnswer('Este mensaje envia una imagen', { + media: 'https://i.imgur.com/0HpzsEm.png', +}) -const flowString = addKeyword('hola').addAnswer( - 'Este mensaje envia tres botones', - { - buttons: [ - { body: 'Boton 1' }, - { body: 'Boton 2' }, - { body: 'Boton 3' }, - ], - } -) +const flowString = addKeyword('hola').addAnswer('Este mensaje envia tres botones', { + buttons: [{ body: 'Boton 1' }, { body: 'Boton 2' }, { body: 'Boton 3' }], +}) -const flowString = addKeyword('hola').addAnswer( - 'Este mensaje espera una respueta del usuario', - { - capture: true, - } -) +const flowString = addKeyword('hola').addAnswer('Este mensaje espera una respueta del usuario', { + capture: true, +}) ``` --- @@ -123,13 +102,9 @@ Este argumento se utiliza para obtener el contexto de la conversación ```js const { addKeyword } = require('@bot-whatsapp/bot') -const flowString = addKeyword('hola').addAnswer( - 'Indica cual es tu email', - null, - (ctx) => { - console.log('👉 Informacion del contexto: ', ctx) - } -) +const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx) => { + console.log('👉 Informacion del contexto: ', ctx) +}) ``` --- @@ -143,13 +118,9 @@ se repetira el mensaje `Indica cual es tu email` ```js const { addKeyword } = require('@bot-whatsapp/bot') -const flowString = addKeyword('hola').addAnswer( - 'Indica cual es tu email', - null, - (ctx, { fallBack }) => { - if (!ctx.body.includes('@')) return fallBack() - } -) +const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx, { fallBack }) => { + if (!ctx.body.includes('@')) return fallBack() +}) ``` --- diff --git a/packages/docs/src/routes/docs/index.mdx b/packages/docs/src/routes/docs/index.mdx index 505bd6a..ab6d5f1 100644 --- a/packages/docs/src/routes/docs/index.mdx +++ b/packages/docs/src/routes/docs/index.mdx @@ -4,10 +4,9 @@ import Navigation from '../../components/widgets/Navigation' # Introducción - **Atención** estás leyendo la documentación de la **versión v2** de esta - librería, si vienes de la versión anterior te recomendamos pasarte por la - sección de **[migración](/docs/migration/)** para que puedas disfrutar de - las nuevas características. + **Atención** estás leyendo la documentación de la **versión v2** de esta librería, si vienes de la versión anterior + te recomendamos pasarte por la sección de **[migración](/docs/migration/)** para que puedas disfrutar de las nuevas + características. ## ¿Qué es esto? @@ -34,10 +33,7 @@ npm create bot-whatsapp@latest muted playsinline > - +
    diff --git a/packages/docs/src/routes/docs/install/index.mdx b/packages/docs/src/routes/docs/install/index.mdx index 342043a..4fa8575 100644 --- a/packages/docs/src/routes/docs/install/index.mdx +++ b/packages/docs/src/routes/docs/install/index.mdx @@ -28,10 +28,7 @@ El **CLI** te hace una revisión previa, de versión de Node y sistema operativo muted playsinline > - +
    @@ -54,10 +51,8 @@ Cada plantilla tiene sus dependencias necesarias basadas en tu previa selección ``` - 📄 Si deseas cambiar tu **proveedor o tu motor** de base de datos no es - necesario volver ejecutar el CLI (lo puedes hacer sin problema) aunque - tambien basta con solo modificar un par de lineas. [Ver - explicación](/docs/essential) + 📄 Si deseas cambiar tu **proveedor o tu motor** de base de datos no es necesario volver ejecutar el CLI (lo puedes + hacer sin problema) aunque tambien basta con solo modificar un par de lineas. [Ver explicación](/docs/essential) --- diff --git a/packages/docs/src/routes/docs/layout!.tsx b/packages/docs/src/routes/docs/layout!.tsx index 8f49e8a..8fe70cb 100644 --- a/packages/docs/src/routes/docs/layout!.tsx +++ b/packages/docs/src/routes/docs/layout!.tsx @@ -27,11 +27,7 @@ export default component$(() => {
    -
    +
    @@ -54,8 +50,7 @@ export const head: DocumentHead = { meta: [ { name: 'description', - content: - 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource', + content: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource', }, ], } diff --git a/packages/docs/src/routes/docs/migration/index.mdx b/packages/docs/src/routes/docs/migration/index.mdx index 84a1658..2e09f97 100644 --- a/packages/docs/src/routes/docs/migration/index.mdx +++ b/packages/docs/src/routes/docs/migration/index.mdx @@ -49,11 +49,7 @@ En la **_versión (legacy)_** se implementas los flujos de esta manera, en dos a "title": "¿Que te interesa ver?", "message": "Abajo unos botons", "footer": "", - "buttons": [ - { "body": "Telefonos" }, - { "body": "Computadoras" }, - { "body": "Otros" } - ] + "buttons": [{ "body": "Telefonos" }, { "body": "Computadoras" }, { "body": "Otros" }] } }, "catalogo": { @@ -70,51 +66,28 @@ En esta versión es mucho más sencillo, abajo encontrarás un ejemplo del mismo ```js //app.js -const { - createBot, - createProvider, - createFlow, - addKeyword, - addChild, -} = require('@bot-whatsapp/bot') +const { createBot, createProvider, createFlow, addKeyword, addChild } = require('@bot-whatsapp/bot') const BaileysProvider = require('@bot-whatsapp/provider/baileys') //Provider const MockAdapter = require('@bot-whatsapp/database/mock') //Base de datos /** * Declarando flujos principales. */ -const flowHola = addKeyword(['hola', 'ola', 'alo']).addAnswer( - 'Bienvenido a tu tienda online!' -) +const flowHola = addKeyword(['hola', 'ola', 'alo']).addAnswer('Bienvenido a tu tienda online!') -const flowAdios = addKeyword(['adios', 'bye']) - .addAnswer('Que te vaya bien!!') - .addAnswer('Hasta luego!') +const flowAdios = addKeyword(['adios', 'bye']).addAnswer('Que te vaya bien!!').addAnswer('Hasta luego!') -const flowProductos = addKeyword(['productos', 'info']).addAnswer( - 'Te envio una imagen', - { - buttons: [ - { body: 'Telefonos' }, - { body: 'Computadoras' }, - { body: 'Otros' }, - ], - } -) +const flowProductos = addKeyword(['productos', 'info']).addAnswer('Te envio una imagen', { + buttons: [{ body: 'Telefonos' }, { body: 'Computadoras' }, { body: 'Otros' }], +}) -const flowCatalogo = addKeyword(['imagen', 'foto']).addAnswer( - 'Te envio una imagen', - { media: 'https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif' } -) +const flowCatalogo = addKeyword(['imagen', 'foto']).addAnswer('Te envio una imagen', { + media: 'https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif', +}) const main = async () => { const adapterDB = new MockAdapter() - const adapterFlow = createFlow([ - flowHola, - flowAdios, - flowProductos, - flowCatalogo, - ]) //Se crean los flujos. + const adapterFlow = createFlow([flowHola, flowAdios, flowProductos, flowCatalogo]) //Se crean los flujos. const adapterProvider = createProvider(BaileysProvider) createBot({ flow: adapterFlow, diff --git a/packages/docs/src/routes/docs/overview/index.mdx b/packages/docs/src/routes/docs/overview/index.mdx index 79830ff..7d2e57c 100644 --- a/packages/docs/src/routes/docs/overview/index.mdx +++ b/packages/docs/src/routes/docs/overview/index.mdx @@ -49,17 +49,15 @@ Qwik is a new kind of web framework that can deliver instant loading web applica

    Instant-on

    - Unlike other frameworks, Qwik is resumable which means Qwik - applications require 0 hydration. This allows Qwik apps to have - instant-on interactivity, regardless of size or complexity + Unlike other frameworks, Qwik is resumable which means Qwik applications require 0 hydration. This allows + Qwik apps to have instant-on interactivity, regardless of size or complexity

    Optimized for speed

    - Qwik has unprecedented performance, offering sub-second full page - loads even on mobile devices. Qwik achieves this by delivering pure - HTML, and incrementally loading JS only as-needed. + Qwik has unprecedented performance, offering sub-second full page loads even on mobile devices. Qwik + achieves this by delivering pure HTML, and incrementally loading JS only as-needed.

    diff --git a/packages/docs/src/routes/docs/providers/index.mdx b/packages/docs/src/routes/docs/providers/index.mdx index 0f6db6a..e534576 100644 --- a/packages/docs/src/routes/docs/providers/index.mdx +++ b/packages/docs/src/routes/docs/providers/index.mdx @@ -4,11 +4,10 @@ import Navigation from '../../../components/widgets/Navigation' # Proveedores - ⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar - algunas configuracion adicional como **token, api, etc.** para esos casos te - recomendamos guiarte de los - **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** - o si gustas puedes editar esta documentación para ir agregando más info + ⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar algunas configuracion adicional como + **token, api, etc.** para esos casos te recomendamos guiarte de los + **[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta + documentación para ir agregando más info Es la pieza que conectara tu flujo con Whatsapp. En este chatbot tenemos varios proveedores disponibles la mayoria gratis pero tambien tenemos integracion la api oficial de whatsapp o twilio diff --git a/packages/docs/src/routes/docs/providers/meta/index.mdx b/packages/docs/src/routes/docs/providers/meta/index.mdx index a44476f..d0f1d6f 100644 --- a/packages/docs/src/routes/docs/providers/meta/index.mdx +++ b/packages/docs/src/routes/docs/providers/meta/index.mdx @@ -59,10 +59,7 @@ En el **archivo principal** del bot donde estás implementando la función del a - **jwtToken:** Lo puedes encontrar en la pagina anterior - **verifyToken:** Puedes escribir lo que quieras es como una palabra clave - - En el ejemplo de abajo puedes ver como una sugerencia de como puede ser - utilizando variables de entorno - +En el ejemplo de abajo puedes ver como una sugerencia de como puede ser utilizando variables de entorno ```js const main = async () => { diff --git a/packages/docs/src/routes/docs/providers/twilio/index.mdx b/packages/docs/src/routes/docs/providers/twilio/index.mdx index 5548ad5..37fc6dd 100644 --- a/packages/docs/src/routes/docs/providers/twilio/index.mdx +++ b/packages/docs/src/routes/docs/providers/twilio/index.mdx @@ -5,10 +5,7 @@ import Navigation from '../../../../components/widgets/Navigation' Twilio es una plataforma de desarrollo que permite a los desarrolladores construir aplicaciones de comunicación en la nube y sistemas web. Las API de comunicaciones de Twilio permiten a las empresas proporcionar la experiencia de comunicación adecuada para sus clientes dentro de la web y las aplicaciones móviles. Al usar las API de Twilio, los desarrolladores pueden agregar rápidamente esta funcionalidad a una aplicación, como mensajes de voz, videollamadas, mensajes de texto y más. - - Twilio te proporciona una cuenta **Sandbox** para que puedas probar - gratuitamente el servicio - +Twilio te proporciona una cuenta **Sandbox** para que puedas probar gratuitamente el servicio ### Requerimientos @@ -66,10 +63,7 @@ En el **archivo principal** del bot donde estás implementando la función del a - **ACC_VENDOR:** Es el numero de whatsapp (si ya tienes el plan de pago de Twilio usa el numero que compraste), si aun estas en modo sandbox utliza el numero proporcionado en el paso numero 2 - - En el ejemplo de abajo puedes ver como una sugerencia de como puede ser - utilizando variables de entorno - +En el ejemplo de abajo puedes ver como una sugerencia de como puede ser utilizando variables de entorno ```js const main = async () => { diff --git a/packages/docs/src/routes/index.tsx b/packages/docs/src/routes/index.tsx index 9b0f04a..71fa15a 100644 --- a/packages/docs/src/routes/index.tsx +++ b/packages/docs/src/routes/index.tsx @@ -13,8 +13,7 @@ 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 + const CHECK_GITHUB_TOKEN = (platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN const dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN) const dataOpenCollective = await fetchOpenCollective() return { @@ -52,8 +51,7 @@ export const head: DocumentHead = { meta: [ { name: 'description', - content: - 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource', + content: 'Crear chatbot WhatsApp en minutos — Servicio de chatbot para whatspp gratis proyecto OpenSource', }, ], } diff --git a/packages/docs/src/services/github.ts b/packages/docs/src/services/github.ts index e60d250..6ef1186 100644 --- a/packages/docs/src/services/github.ts +++ b/packages/docs/src/services/github.ts @@ -3,17 +3,14 @@ * @returns */ export const fetchGithub = async (token: string) => { - const data = await fetch( - `https://api.github.com/repos/codigoencasa/bot-whatsapp/contributors`, - { - method: 'GET', - headers: { - Accept: 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28', - Authorization: `Bearer ${token}`, - }, - } - ) + const data = await fetch(`https://api.github.com/repos/codigoencasa/bot-whatsapp/contributors`, { + method: 'GET', + headers: { + Accept: 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + Authorization: `Bearer ${token}`, + }, + }) const listUsers = await data.json() return listUsers.map((u: any) => ({ ...u, diff --git a/packages/docs/src/services/opencollective.ts b/packages/docs/src/services/opencollective.ts index 9a89f25..55e7e75 100644 --- a/packages/docs/src/services/opencollective.ts +++ b/packages/docs/src/services/opencollective.ts @@ -3,12 +3,9 @@ * @returns */ export const fetchOpenCollective = async () => { - const data = await fetch( - `https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`, - { - method: 'GET', - } - ) + const data = await fetch(`https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`, { + method: 'GET', + }) const listUsers = await data.json() return listUsers.map((u: any) => ({ html_url: u.profile, diff --git a/packages/docs/tailwind.config.js b/packages/docs/tailwind.config.js index 1614b2e..a92fde1 100644 --- a/packages/docs/tailwind.config.js +++ b/packages/docs/tailwind.config.js @@ -76,9 +76,7 @@ module.exports = { a: { fontWeight: theme('fontWeight.semibold'), textDecoration: 'none', - borderBottom: `1px solid ${theme( - 'colors.sky.300' - )}`, + borderBottom: `1px solid ${theme('colors.sky.300')}`, }, 'a:hover': { borderBottomWidth: '2px', diff --git a/packages/portal/.vscode/qwik-city.code-snippets b/packages/portal/.vscode/qwik-city.code-snippets index b6c1c17..361ddf7 100644 --- a/packages/portal/.vscode/qwik-city.code-snippets +++ b/packages/portal/.vscode/qwik-city.code-snippets @@ -3,11 +3,7 @@ "scope": "javascriptreact,typescriptreact", "prefix": "q:onGet", "description": "onGet function for a route index", - "body": [ - "export const onGet: RequestHandler = (request) => {", - " $0", - "};" - ] + "body": ["export const onGet: RequestHandler = (request) => {", " $0", "};"] }, "onGet (typed)": { "scope": "javascriptreact,typescriptreact", diff --git a/packages/portal/.vscode/qwik.code-snippets b/packages/portal/.vscode/qwik.code-snippets index 4b89dbf..c2a8a8f 100644 --- a/packages/portal/.vscode/qwik.code-snippets +++ b/packages/portal/.vscode/qwik.code-snippets @@ -56,24 +56,13 @@ "scope": "javascriptreact,typescriptreact", "prefix": "q:useTask", "description": "useTask$() function hook", - "body": [ - "useTask$(({ track }) => {", - " track(() => $1);", - " $0", - "});", - "" - ] + "body": ["useTask$(({ track }) => {", " track(() => $1);", " $0", "});", ""] }, "useResource": { "scope": "javascriptreact,typescriptreact", "prefix": "q:useResource", "description": "useResource$() declaration", - "body": [ - "const $1 = useResource$(({ track, cleanup }) => {", - " $0", - "});", - "" - ] + "body": ["const $1 = useResource$(({ track, cleanup }) => {", " $0", "});", ""] }, "useServerMount": { "scope": "javascriptreact,typescriptreact", diff --git a/packages/portal/portal.http.js b/packages/portal/portal.http.js index 3066c12..122f2de 100644 --- a/packages/portal/portal.http.js +++ b/packages/portal/portal.http.js @@ -5,14 +5,9 @@ const polka = require('polka') const HTTP_PORT = process.env.PORT || 3000 const QR_FILE = process.env.QR_FILE ?? 'bot' -const PUBLIC_URL = - process.env.PUBLIC_URL ?? - process.env.RAILWAY_STATIC_URL ?? - 'http://localhost' +const PUBLIC_URL = process.env.PUBLIC_URL ?? process.env.RAILWAY_STATIC_URL ?? 'http://localhost' -const dir = [join(__dirname, 'dist'), join(__dirname, '..', 'dist')].find((i) => - existsSync(i) -) +const dir = [join(__dirname, 'dist'), join(__dirname, '..', 'dist')].find((i) => existsSync(i)) const serve = require('serve-static')(dir) /** @@ -32,14 +27,8 @@ const start = (args) => { console.log(``) console.log(bgYellow(`🚩 ESCANEAR QR 🚩`)) console.log(cyan(`Existen varias maneras de escanear el QR code`)) - console.log( - cyan(`- Tambien puedes visitar `), - yellow(`${publicSite}:${port}`) - ) - console.log( - cyan(`- Se ha creado un archivo que finaliza `), - yellow('qr.png') - ) + console.log(cyan(`- Tambien puedes visitar `), yellow(`${publicSite}:${port}`)) + console.log(cyan(`- Se ha creado un archivo que finaliza `), yellow('qr.png')) console.log(``) } diff --git a/packages/portal/src/components/header/header.tsx b/packages/portal/src/components/header/header.tsx index f1c7fa7..ebaa11b 100644 --- a/packages/portal/src/components/header/header.tsx +++ b/packages/portal/src/components/header/header.tsx @@ -8,28 +8,18 @@ export default component$(() => { return (
    • - + Docs
    • - + Examples
    • diff --git a/packages/portal/src/components/icons/qwik.tsx b/packages/portal/src/components/icons/qwik.tsx index 3bd8d91..fc113f6 100644 --- a/packages/portal/src/components/icons/qwik.tsx +++ b/packages/portal/src/components/icons/qwik.tsx @@ -1,11 +1,5 @@ export const QwikLogo = () => ( - + { @@ -20,12 +15,7 @@ export const QR = component$(() => { return (
      - QR + QR
      ) }) diff --git a/packages/portal/src/components/router-head/router-head.tsx b/packages/portal/src/components/router-head/router-head.tsx index c0811e4..dee9459 100644 --- a/packages/portal/src/components/router-head/router-head.tsx +++ b/packages/portal/src/components/router-head/router-head.tsx @@ -10,10 +10,7 @@ export const RouterHead = component$(() => { {head.title} - + {head.meta.map((m) => ( diff --git a/packages/portal/src/global.css b/packages/portal/src/global.css index cc17b32..6b1eeb6 100644 --- a/packages/portal/src/global.css +++ b/packages/portal/src/global.css @@ -15,8 +15,7 @@ body { background-color: #fafafa; - font-family: 'Inter', sans-serif, ui-sans-serif, system-ui, -apple-system, - BlinkMacSystemFont, sans-serif; + font-family: 'Inter', sans-serif, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif; padding: 20px 20px 40px 20px; } diff --git a/packages/portal/src/routes/index.css b/packages/portal/src/routes/index.css index f5ff37b..cf07671 100644 --- a/packages/portal/src/routes/index.css +++ b/packages/portal/src/routes/index.css @@ -12,8 +12,7 @@ .page .btn-link { background: white; - box-shadow: rgb(0 0 0 / 16%) 0px 10px 36px 0px, - rgb(0 0 0 / 6%) 0px 0px 0px 1px; + box-shadow: rgb(0 0 0 / 16%) 0px 10px 36px 0px, rgb(0 0 0 / 6%) 0px 0px 0px 1px; padding: 10px; border-radius: 5px; font-weight: 600; diff --git a/packages/portal/src/routes/index.tsx b/packages/portal/src/routes/index.tsx index 44c8117..2a26307 100644 --- a/packages/portal/src/routes/index.tsx +++ b/packages/portal/src/routes/index.tsx @@ -15,19 +15,13 @@ export default component$(() => {

      Whatsapp QR

      - Con esta libreria, puedes configurar respuestas - automatizadas para preguntas frecuentes, recibir y responder - mensajes de manera automatizada, y hacer un seguimiento de - las interacciones con los clientes.
      Además, nuestro - Chatbot se integra fácilmente con otros sistemas y - herramientas que ya esté utilizando en su negocio. + Con esta libreria, puedes configurar respuestas automatizadas para preguntas frecuentes, recibir y + responder mensajes de manera automatizada, y hacer un seguimiento de las interacciones con los + clientes.
      Además, nuestro Chatbot se integra fácilmente con otros sistemas y herramientas que + ya esté utilizando en su negocio.

      diff --git a/packages/provider/src/baileys/index.js b/packages/provider/src/baileys/index.js index 9361731..7a5de23 100644 --- a/packages/provider/src/baileys/index.js +++ b/packages/provider/src/baileys/index.js @@ -7,18 +7,9 @@ const { join } = require('path') const { createWriteStream, readFileSync } = require('fs') const { Console } = require('console') -const { - default: makeWASocket, - useMultiFileAuthState, - Browsers, - DisconnectReason, -} = require('@adiwajshing/baileys') +const { default: makeWASocket, useMultiFileAuthState, Browsers, DisconnectReason } = require('@adiwajshing/baileys') -const { - baileyGenerateImage, - baileyCleanNumber, - baileyIsValidNumber, -} = require('./utils') +const { baileyGenerateImage, baileyCleanNumber, baileyIsValidNumber } = require('./utils') const { generalDownload } = require('../../common/download') @@ -46,9 +37,7 @@ class BaileysProvider extends ProviderClass { */ initBailey = async () => { const NAME_DIR_SESSION = `${this.globalVendorArgs.name}_sessions` - const { state, saveCreds } = await useMultiFileAuthState( - NAME_DIR_SESSION - ) + const { state, saveCreds } = await useMultiFileAuthState(NAME_DIR_SESSION) this.saveCredsGlobal = saveCreds try { @@ -57,7 +46,7 @@ class BaileysProvider extends ProviderClass { auth: state, browser: Browsers.macOS('Desktop'), syncFullHistory: false, - logger: pino({ level: 'error' }), + logger: pino({ level: 'fatal' }), }) sock.ev.on('connection.update', async (update) => { @@ -96,10 +85,7 @@ class BaileysProvider extends ProviderClass { `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, ], }) - await baileyGenerateImage( - qr, - `${this.globalVendorArgs.name}.qr.png` - ) + await baileyGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`) } }) @@ -131,9 +117,10 @@ class BaileysProvider extends ProviderClass { const [messageCtx] = messages let payload = { ...messageCtx, - body: messageCtx?.message?.conversation, + body: messageCtx?.message?.extendedTextMessage?.text ?? messageCtx?.message?.conversation, from: messageCtx?.key?.remoteJid, } + if (payload.from === 'status@broadcast') return if (payload?.key?.fromMe) return @@ -142,9 +129,7 @@ class BaileysProvider extends ProviderClass { return } - const btnCtx = - payload?.message?.buttonsResponseMessage - ?.selectedDisplayText + const btnCtx = payload?.message?.buttonsResponseMessage?.selectedDisplayText if (btnCtx) payload.body = btnCtx @@ -174,12 +159,9 @@ class BaileysProvider extends ProviderClass { const fileDownloaded = await generalDownload(imageUrl) const mimeType = mime.lookup(fileDownloaded) - if (mimeType.includes('image')) - return this.sendImage(number, fileDownloaded, text) - if (mimeType.includes('video')) - return this.sendVideo(number, fileDownloaded, text) - if (mimeType.includes('audio')) - return this.sendAudio(number, fileDownloaded, text) + if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text) + if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded, text) + if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded, text) return this.sendFile(number, fileDownloaded) } @@ -294,10 +276,8 @@ class BaileysProvider extends ProviderClass { sendMessage = async (numberIn, message, { options }) => { const number = baileyCleanNumber(numberIn) - if (options?.buttons?.length) - return this.sendButtons(number, message, options.buttons) - if (options?.media) - return this.sendMedia(number, options.media, message) + if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons) + if (options?.media) return this.sendMedia(number, options.media, message) return this.sendText(number, message) } @@ -332,12 +312,7 @@ class BaileysProvider extends ProviderClass { * @example await sendContact("xxxxxxxxxxx@c.us" || "xxxxxxxxxxxxxxxxxx@g.us", "+xxxxxxxxxxx", "Robin Smith", messages) */ - sendContact = async ( - remoteJid, - contactNumber, - displayName, - messages = null - ) => { + sendContact = async (remoteJid, contactNumber, displayName, messages = null) => { const cleanContactNumber = contactNumber.replaceAll(' ', '') const waid = cleanContactNumber.replace('+', '') diff --git a/packages/provider/src/meta/index.js b/packages/provider/src/meta/index.js index b3a106b..2b2e0e0 100644 --- a/packages/provider/src/meta/index.js +++ b/packages/provider/src/meta/index.js @@ -56,15 +56,11 @@ class MetaProvider extends ProviderClass { sendMessageMeta = async (body) => { try { - const response = await axios.post( - `${URL}/${this.numberId}/messages`, - body, - { - headers: { - Authorization: `Bearer ${this.jwtToken}`, - }, - } - ) + const response = await axios.post(`${URL}/${this.numberId}/messages`, body, { + headers: { + Authorization: `Bearer ${this.jwtToken}`, + }, + }) return response.data } catch (error) { return Promise.resolve(error) @@ -106,8 +102,7 @@ class MetaProvider extends ProviderClass { */ sendMessage = async (number, message, { options }) => { if (options?.buttons?.length) return console.log('Envio de botones') - if (options?.media) - return this.sendMedia(number, message, options.media) + if (options?.media) return this.sendMedia(number, message, options.media) this.sendtext(number, message) } diff --git a/packages/provider/src/meta/server.js b/packages/provider/src/meta/server.js index 3d6ef61..cbd59b0 100644 --- a/packages/provider/src/meta/server.js +++ b/packages/provider/src/meta/server.js @@ -81,9 +81,7 @@ class MetaWebHookServer extends EventEmitter { * @returns */ buildHTTPServer = () => { - this.metaServer - .use(urlencoded({ extended: true })) - .get('/webhook', this.verifyToken) + this.metaServer.use(urlencoded({ extended: true })).get('/webhook', this.verifyToken) this.metaServer .use(urlencoded({ extended: true })) @@ -99,9 +97,7 @@ class MetaWebHookServer extends EventEmitter { this.metaServer.listen(this.metaPort, () => { console.log(``) console.log(`[meta]: Agregar esta url "WHEN A MESSAGE COMES IN"`) - console.log( - `[meta]: POST http://localhost:${this.metaPort}/webhook` - ) + console.log(`[meta]: POST http://localhost:${this.metaPort}/webhook`) console.log(`[meta]: Más información en la documentacion`) console.log(``) }) diff --git a/packages/provider/src/twilio/index.js b/packages/provider/src/twilio/index.js index 7c25bb9..e1a50dc 100644 --- a/packages/provider/src/twilio/index.js +++ b/packages/provider/src/twilio/index.js @@ -86,12 +86,8 @@ class TwilioProvider extends ProviderClass { */ sendButtons = async () => { console.log(``) - console.log( - `[NOTA]: Actualmente enviar botons con Twilio esta en desarrollo` - ) - console.log( - `[NOTA]: https://www.twilio.com/es-mx/docs/whatsapp/buttons` - ) + console.log(`[NOTA]: Actualmente enviar botons con Twilio esta en desarrollo`) + console.log(`[NOTA]: https://www.twilio.com/es-mx/docs/whatsapp/buttons`) console.log(``) } @@ -104,10 +100,8 @@ class TwilioProvider extends ProviderClass { */ sendMessage = async (number, message, { options }) => { number = parseNumber(number) - if (options?.buttons?.length) - this.sendButtons(number, message, options.buttons) - if (options?.media) - return this.sendMedia(number, message, options.media) + if (options?.buttons?.length) this.sendButtons(number, message, options.buttons) + if (options?.media) return this.sendMedia(number, message, options.media) return this.vendor.messages.create({ body: message, from: `whatsapp:+${this.vendorNumber}`, diff --git a/packages/provider/src/twilio/server.js b/packages/provider/src/twilio/server.js index ae09da7..aaf49c2 100644 --- a/packages/provider/src/twilio/server.js +++ b/packages/provider/src/twilio/server.js @@ -51,9 +51,7 @@ class TwilioWebHookServer extends EventEmitter { this.twilioServer.listen(this.twilioPort, () => { console.log(``) console.log(`[Twilio]: Agregar esta url "WHEN A MESSAGE COMES IN"`) - console.log( - `[Twilio]: POST http://localhost:${this.twilioPort}/twilio-hook` - ) + console.log(`[Twilio]: POST http://localhost:${this.twilioPort}/twilio-hook`) console.log(`[Twilio]: Más información en la documentacion`) console.log(``) }) diff --git a/packages/provider/src/venom/index.js b/packages/provider/src/venom/index.js index 3e1b630..1369af2 100644 --- a/packages/provider/src/venom/index.js +++ b/packages/provider/src/venom/index.js @@ -4,11 +4,7 @@ const { createWriteStream } = require('fs') const { Console } = require('console') const mime = require('mime-types') -const { - venomCleanNumber, - venomGenerateImage, - venomisValidNumber, -} = require('./utils') +const { venomCleanNumber, venomGenerateImage, venomisValidNumber } = require('./utils') const logger = new Console({ stdout: createWriteStream(`${process.cwd()}/venom.log`), @@ -108,8 +104,7 @@ class VenomProvider extends ProviderClass { const listEvents = this.busEvents() for (const { event, func } of listEvents) { - if (this.vendor[event]) - this.vendor[event]((payload) => func(payload)) + if (this.vendor[event]) this.vendor[event]((payload) => func(payload)) } } @@ -122,16 +117,13 @@ class VenomProvider extends ProviderClass { * @returns */ sendButtons = async (number, message, buttons = []) => { - const NOTE_VENOM_BUTTON = [ - `Actualmente VENOM tiene problemas con la API`, - `para el envio de Botones`, - ].join('\n') + const NOTE_VENOM_BUTTON = [`Actualmente VENOM tiene problemas con la API`, `para el envio de Botones`].join( + '\n' + ) console.log(`[NOTA]: ${NOTE_VENOM_BUTTON}`) - const buttonToStr = [message] - .concat(buttons.map((btn) => `${btn.body}`)) - .join(`\n`) + const buttonToStr = [message].concat(buttons.map((btn) => `${btn.body}`)).join(`\n`) return this.vendor.sendText(number, buttonToStr) // return this.vendor.sendButtons(number, "Title", buttons1, "Description"); } @@ -194,12 +186,9 @@ class VenomProvider extends ProviderClass { const fileDownloaded = await generalDownload(mediaUrl) const mimeType = mime.lookup(fileDownloaded) - if (mimeType.includes('image')) - return this.sendImage(number, fileDownloaded, text) - if (mimeType.includes('video')) - return this.sendVideo(number, fileDownloaded, text) - if (mimeType.includes('audio')) - return this.sendAudio(number, fileDownloaded) + if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text) + if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded, text) + if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded) return this.sendFile(number, fileDownloaded, text) } @@ -213,10 +202,8 @@ class VenomProvider extends ProviderClass { */ sendMessage = async (userId, message, { options }) => { const number = venomCleanNumber(userId) - if (options?.buttons?.length) - return this.sendButtons(number, message, options.buttons) - if (options?.media) - return this.sendMedia(number, options.media, message) + if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons) + if (options?.media) return this.sendMedia(number, options.media, message) return this.vendor.sendText(number, message) } } diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index 60a142d..9fef93c 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -2,11 +2,7 @@ const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js') const { ProviderClass } = require('@bot-whatsapp/bot') const { Console } = require('console') const { createWriteStream, readFileSync } = require('fs') -const { - wwebCleanNumber, - wwebGenerateImage, - wwebIsValidNumber, -} = require('./utils') +const { wwebCleanNumber, wwebGenerateImage, wwebIsValidNumber } = require('./utils') const logger = new Console({ stdout: createWriteStream('./log'), @@ -32,11 +28,7 @@ class WebWhatsappProvider extends ProviderClass { }), puppeteer: { headless: true, - args: [ - '--no-sandbox', - '--disable-setuid-sandbox', - '--unhandled-rejections=strict', - ], + args: ['--no-sandbox', '--disable-setuid-sandbox', '--unhandled-rejections=strict'], //executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', }, }) @@ -80,10 +72,7 @@ class WebWhatsappProvider extends ProviderClass { `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, ], }) - await wwebGenerateImage( - qr, - `${this.globalVendorArgs.name}.qr.png` - ) + await wwebGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`) }, }, { @@ -116,6 +105,9 @@ class WebWhatsappProvider extends ProviderClass { * @returns */ sendButtons = async (number, message, buttons = []) => { + console.log(`🚩 ¿No te funciona los botones? Intenta instalar`) + console.log(`npm i github:pedroslopez/whatsapp-web.js#fix-buttons-list`) + const buttonMessage = new Buttons(message, buttons, '', '') return this.vendor.sendMessage(number, buttonMessage) } @@ -226,12 +218,9 @@ class WebWhatsappProvider extends ProviderClass { const fileDownloaded = await generalDownload(mediaUrl) const mimeType = mime.lookup(fileDownloaded) - if (mimeType.includes('image')) - return this.sendImage(number, fileDownloaded, text) - if (mimeType.includes('video')) - return this.sendVideo(number, fileDownloaded) - if (mimeType.includes('audio')) - return this.sendAudio(number, fileDownloaded, text) + if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text) + if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded) + if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded) return this.sendFile(number, fileDownloaded) } @@ -245,8 +234,7 @@ class WebWhatsappProvider extends ProviderClass { */ sendMessage = async (userId, message, { options }) => { const number = wwebCleanNumber(userId) - if (options?.buttons?.length) - return this.sendButtons(number, message, options.buttons) + if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons) if (options?.media) return this.sendMedia(number, options.media) return this.sendText(number, message) }