diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05afdd0..f3c2553 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,9 @@ name: 🤪 Build and Test on: + push: + branches: + - dev pull_request: branches: - dev diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 91195c8..0770f1b 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -115,24 +115,16 @@ class CoreClass { // 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo const cbEveryCtx = (inRef) => { - const indexFlow = this.flowClass.findIndexByRef(inRef) - this.flowClass.allCallbacks[indexFlow].callback( - messageCtxInComming, - { - fallBack, - flowDynamic, - } - ) + this.flowClass.allCallbacks[inRef](messageCtxInComming, { + fallBack, + flowDynamic, + }) } // 📄 [options: callback]: Si se tiene un callback se ejecuta if (!fallBackFlag) { - if (refToContinue && prevMsg?.options?.callback) { - cbEveryCtx(refToContinue?.ref) - } else { - for (const ite of this.flowClass.find(body)) { - cbEveryCtx(ite?.ref) - } + for (const ite of this.flowClass.find(body)) { + cbEveryCtx(ite?.ref) } } @@ -144,6 +136,11 @@ class CoreClass { })) msgToSend = this.flowClass.find(body, false, flowStandalone) || [] + + for (const ite of msgToSend) { + cbEveryCtx(ite?.ref) + } + this.sendFlow(msgToSend, from) return } diff --git a/packages/bot/io/flow.class.js b/packages/bot/io/flow.class.js index cfd4afd..583a237 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -1,4 +1,5 @@ const { toSerialize } = require('./methods/toSerialize') +const { flatObject } = require('../utils/flattener') class FlowClass { allCallbacks = [] @@ -8,7 +9,8 @@ class FlowClass { if (!Array.isArray(_flow)) throw new Error('Esto debe ser un ARRAY') this.flowRaw = _flow - this.getAllCb(this.flowRaw) + this.allCallbacks = flatObject(_flow) + console.log('[🙌🙌🙌]', this.allCallbacks) const mergeToJsonSerialize = Object.keys(_flow) .map((indexObjectFlow) => _flow[indexObjectFlow].toJson()) @@ -17,17 +19,6 @@ class FlowClass { this.flowSerialize = toSerialize(mergeToJsonSerialize) } - /** - * Buscar y aplanar todos los callbacks - * @param {*} inFlow - */ - getAllCb = (inFlow) => { - this.allCallbacks = inFlow - .map((cbIn) => cbIn.ctx.callbacks) - .flat(2) - .map((c, i) => ({ callback: c?.callback, index: i })) - } - find = (keyOrWord, symbol = false, overFlow = null) => { keyOrWord = `${keyOrWord}` let capture = false diff --git a/packages/bot/io/methods/addAnswer.js b/packages/bot/io/methods/addAnswer.js index a7db6d6..f0ccdad 100644 --- a/packages/bot/io/methods/addAnswer.js +++ b/packages/bot/io/methods/addAnswer.js @@ -1,4 +1,6 @@ +const { flatObject } = require('../../utils/flattener') const { generateRef } = require('../../utils/hash') +const { addChild } = require('./addChild') const { toJson } = require('./toJson') /** * @@ -27,9 +29,28 @@ const addAnswer = delay: typeof options?.delay === 'number' ? options?.delay : 0, }) - const getNested = () => ({ - nested: Array.isArray(nested) ? nested : [], - }) + const getNested = () => { + let flatNested = [] + if (Array.isArray(nested)) { + for (const iterator of nested) { + flatNested = [...flatNested, ...addChild(iterator)] + } + + return { + nested: flatNested, + } + } + return { + nested: addChild(nested), + } + } + + /** + * Esta funcion aplana y busca los callback anidados de los hijos + * @returns + */ + const getCbFromNested = () => + flatObject(Array.isArray(nested) ? nested : [nested]) const callback = typeof cb === 'function' ? cb : () => null @@ -59,12 +80,12 @@ const addAnswer = }, ]) - const callbacks = [].concat(inCtx.callbacks).concat([ - { - ref: lastCtx.ref, - callback, - }, - ]) + getCbFromNested() + const callbacks = { + ...inCtx.callbacks, + ...getCbFromNested(), + [ref]: callback, + } return { ...lastCtx, diff --git a/packages/bot/package.json b/packages/bot/package.json index 6c473c8..87d283b 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.27-alpha.0", + "version": "0.0.28-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { diff --git a/packages/bot/rollup-bot.config.js b/packages/bot/rollup-bot.config.js index acd4229..f8ffa2a 100644 --- a/packages/bot/rollup-bot.config.js +++ b/packages/bot/rollup-bot.config.js @@ -3,14 +3,23 @@ const commonjs = require('@rollup/plugin-commonjs') const { nodeResolve } = require('@rollup/plugin-node-resolve') const { join } = require('path') -const PATH = join(__dirname, 'lib', 'bundle.bot.cjs') - -module.exports = { - input: join(__dirname, 'index.js'), - output: { - banner: banner['banner.output'].join(''), - file: PATH, - format: 'cjs', +module.exports = [ + { + input: join(__dirname, 'index.js'), + output: { + banner: banner['banner.output'].join(''), + file: join(__dirname, 'lib', 'bundle.bot.cjs'), + format: 'cjs', + }, + plugins: [commonjs(), nodeResolve()], }, - plugins: [commonjs(), nodeResolve()], -} + { + input: join(__dirname, 'index.js'), + output: { + banner: banner['banner.output'].join(''), + file: join(__dirname, 'lib', 'bundle.bot.cjs'), + format: 'cjs', + }, + plugins: [commonjs(), nodeResolve()], + }, +] diff --git a/packages/bot/tests/bot.class.test.js b/packages/bot/tests/bot.class.test.js index 74fdb79..d74fdad 100644 --- a/packages/bot/tests/bot.class.test.js +++ b/packages/bot/tests/bot.class.test.js @@ -11,7 +11,7 @@ const { } = require('../index') class MockFlow { - allCallbacks = [{ callback: () => console.log('') }] + allCallbacks = { ref: () => 1 } flowSerialize = [] flowRaw = [] find = (arg) => { diff --git a/packages/bot/utils/flattener.js b/packages/bot/utils/flattener.js new file mode 100644 index 0000000..875736d --- /dev/null +++ b/packages/bot/utils/flattener.js @@ -0,0 +1,25 @@ +const flatObject = (listArray = []) => { + const cbNestedList = Array.isArray(listArray) ? listArray : [] + + if (!listArray.length) return {} + + 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) => ({ + [icb]: Object.values(current)[i], + })) + return [...acc, ...parse] + }, []) + + const flatObj = {} + for (const iteration of queueCb) { + const [keyCb] = Object.keys(iteration) + flatObj[keyCb] = iteration[keyCb] + } + return flatObj +} + +module.exports = { flatObject } diff --git a/packages/cli/package.json b/packages/cli/package.json index 07c47f9..5a678c4 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/cli", - "version": "0.0.34-alpha.0", + "version": "0.0.35-alpha.0", "description": "", "main": "index.js", "devDependencies": { diff --git a/packages/create-bot-whatsapp/package.json b/packages/create-bot-whatsapp/package.json index d9e0a92..2386b2e 100644 --- a/packages/create-bot-whatsapp/package.json +++ b/packages/create-bot-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "create-bot-whatsapp", - "version": "0.0.45-alpha.0", + "version": "0.0.46-alpha.0", "description": "", "main": "./lib/bundle.create-bot-whatsapp.cjs", "files": [ diff --git a/packages/database/package.json b/packages/database/package.json index a29afab..a79d823 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/database", - "version": "0.0.26-alpha.0", + "version": "0.0.27-alpha.0", "description": "Esto es el conector a mysql, pg, mongo", "main": "./lib/mock/index.cjs", "keywords": [], diff --git a/packages/docs/src/assets/styles/fonts.css b/packages/docs/src/assets/styles/fonts.css index c2b1344..7ab0599 100644 --- a/packages/docs/src/assets/styles/fonts.css +++ b/packages/docs/src/assets/styles/fonts.css @@ -5,6 +5,7 @@ font-style: normal; font-named-instance: 'Regular'; src: url('../fonts/Inter-roman-latin.var.woff2') format('woff2'); + font-display: swap; } @font-face { @@ -14,6 +15,7 @@ font-style: italic; font-named-instance: 'Italic'; src: url('../fonts/Inter-italic-latin.var.woff2') format('woff2'); + font-display: swap; } @font-face { @@ -22,6 +24,7 @@ font-style: normal; src: url('../fonts/FiraCode-VF.woff2') format('woff2-variations'), url('../fonts/FiraCode-VF.woff') format('woff-variations'); + font-display: swap; } .font-mono { @@ -34,6 +37,7 @@ font-weight: 400; font-display: swap; src: url('../fonts/SourceSansPro-Regular.otf') format('opentype'); + font-display: swap; } @font-face { @@ -41,4 +45,5 @@ font-weight: 700; font-style: normal; src: url('../fonts/Ubuntu-Mono-bold.woff2') format('woff2'); + font-display: swap; } diff --git a/packages/docs/src/routes/docs/join/index.mdx b/packages/docs/src/routes/docs/join/index.mdx index 4d4a99b..90ca067 100644 --- a/packages/docs/src/routes/docs/join/index.mdx +++ b/packages/docs/src/routes/docs/join/index.mdx @@ -4,7 +4,7 @@ Bienvenido al proyecto! Estamos emocionados de tenerte a bordo y esperamos traba Deseamos que te sientas cómodo y que puedas aportar tu valioso conocimiento y habilidades. -Recuerda que si tienes alguna inquietud, o simplemente deseas interactuar con los otros colaboradores puedes unirte a la comunidad. +Recuerda que si tienes alguna inquietud, o simplemente deseas interactuar con los otros colaboradores puedes unirte a la comunidad. ## Ventajas al unirme @@ -14,12 +14,11 @@ Al unirte te estará brindando la oportunidad de **adquirir experiencia en el de La visibilidad es uno de los puntos que más se requieren hoy en día, al unirte se te brinda la oportunidad de **mayor visibilidad en la comunidad de desarrolladores y de demostrar tus habilidades**. Esto puede ayudarte a encontrar oportunidades de trabajo o a colaborar con otros proyectos. -Colaboración con otros desarrolladores de todo el mundo y **trabajar juntos para mejorar el proyecto** Al trabajar en equipo y colaborar con otros, podrás mejorar tu comunicación, resolución de problemas y liderazgo, habilidades que cada vez son más demandadas en el entorno laboral. +Colaboración con otros desarrolladores de todo el mundo y **trabajar juntos para mejorar el proyecto** Al trabajar en equipo y colaborar con otros, podrás mejorar tu comunicación, resolución de problemas y liderazgo, habilidades que cada vez son más demandadas en el entorno laboral. Contribución al bien común Participar en un proyecto de código abierto te permite contribuir a la comunidad y a la sociedad en general, ya que el código abierto es accesible y utilizable por cualquier persona. **Esto puede ser muy gratificante y sentirte parte de algo más grande**. -Es una excelente manera de incrementar tus habilidades tecnológicas y **estar al tanto de las últimas tendencias y desarrollos en el mundo del software**. Al trabajar con otros desarrolladores y contribuir a proyectos de código abierto, tendrás la oportunidad de **aprender y practicar nuevas tecnologías y metodologías, lo que te ayudará a mejorar tus habilidades y a mantenerte actualizado en el mundo en constante cambio de la tecnología. - +Es una excelente manera de incrementar tus habilidades tecnológicas y **estar al tanto de las últimas tendencias y desarrollos en el mundo del software**. Al trabajar con otros desarrolladores y contribuir a proyectos de código abierto, tendrás la oportunidad de \*\*aprender y practicar nuevas tecnologías y metodologías, lo que te ayudará a mejorar tus habilidades y a mantenerte actualizado en el mundo en constante cambio de la tecnología. Esperamos que estés listo para **unirte a nosotros en esta emocionante aventura** diff --git a/packages/provider/package.json b/packages/provider/package.json index c3d77ea..7bc108b 100644 --- a/packages/provider/package.json +++ b/packages/provider/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/provider", - "version": "0.0.32-alpha.0", + "version": "0.0.33-alpha.0", "description": "Esto es el conector a Twilio, Meta, etc...", "main": "./lib/mock/index.cjs", "keywords": [], diff --git a/packages/provider/src/meta/server.js b/packages/provider/src/meta/server.js index cb2ac9a..3d6ef61 100644 --- a/packages/provider/src/meta/server.js +++ b/packages/provider/src/meta/server.js @@ -1,6 +1,6 @@ const { EventEmitter } = require('node:events') const polka = require('polka') -const { urlencoded } = require('body-parser') +const { urlencoded, json } = require('body-parser') class MetaWebHookServer extends EventEmitter { metaServer @@ -8,9 +8,11 @@ class MetaWebHookServer extends EventEmitter { token constructor(_token, _metaPort) { super() - this.metaServer = this.buildHTTPServer() + this.metaServer = polka() this.metaPort = _metaPort this.token = _token + + this.buildHTTPServer() } /** @@ -21,12 +23,18 @@ class MetaWebHookServer extends EventEmitter { */ incomingMsg = (req, res) => { const { body } = req - const message = body.entry[0].changes[0].value.messages[0] + + const messages = body.entry[0].changes[0].value?.messages + + if (!messages) return + + const [message] = messages const to = body.entry[0].changes[0].value.metadata.display_phone_number + this.emit('message', { from: message.from, to, - body: message.text.body, + body: message.text?.body, }) const json = JSON.stringify({ body }) res.end(json) @@ -55,16 +63,16 @@ class MetaWebHookServer extends EventEmitter { const challenge = query['hub.challenge'] if (!mode || !token) { - return res.sendStatus(403) + return (res.statusCode = 403), res.end('No token!') } if (this.tokenIsValid(mode, token)) { console.log('Webhook verified--->😎😎😎😎') - res.status(200).send(challenge) + return (res.statusCode = 200), res.end(challenge) } if (!this.tokenIsValid(mode, token)) { - res.sendStatus(403) + return (res.statusCode = 403), res.end('No token!') } } @@ -73,12 +81,13 @@ class MetaWebHookServer extends EventEmitter { * @returns */ buildHTTPServer = () => { - polka() + this.metaServer .use(urlencoded({ extended: true })) .get('/webhook', this.verifyToken) - return polka() + this.metaServer .use(urlencoded({ extended: true })) + .use(json()) .post('/webhook', this.incomingMsg) } @@ -91,7 +100,7 @@ class MetaWebHookServer extends EventEmitter { console.log(``) console.log(`[meta]: Agregar esta url "WHEN A MESSAGE COMES IN"`) console.log( - `[meta]: POST http://localhost:${this.metaPort}/meta-hook` + `[meta]: POST http://localhost:${this.metaPort}/webhook` ) console.log(`[meta]: Más información en la documentacion`) console.log(``) diff --git a/starters/apps/base-meta-json/README.md b/starters/apps/base-meta-json/README.md new file mode 100644 index 0000000..d0e43d2 --- /dev/null +++ b/starters/apps/base-meta-json/README.md @@ -0,0 +1,34 @@ +### CHATBOT Whatsapp + +Este bot es una aplicación que puedes vincular con tu whatsapp y crear flujos para automatizar tareas en tu negocio o procesos repetitivos. + +Este bot contiene un flujo básico en el cual una persona (cliente) escribe **"hola"** y el bot responde: +- Bienvenido a mi tienda +- ¿Como puedo ayudarte? +- Tengo: Zapatos, Bolsos etc.. + +__Iniciar__ + +Los flujos se declaran de atrás para adelante, es decir que si tienes un flujo de este tipo: + + Menu Principal + - SubMenu 1 + - Submenu 1.1 + - Submenu 2 + - Submenu 2.1 + +Primero se declaran los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + +``` +npm install +npm start +``` + +__¿Tienes problemas?:__ [Abrir Issue](https://github.com/codigoencasa/bot-whatsapp/issues/new/choose) + +------ +> ¿Quieres se parte de este proyecto? +> - [Discord](https://link.codigoencasa.com/DISCORD) +> - [Twitter](https://twitter.com/leifermendez) +> - [Youtube](https://www.youtube.com/watch?v=5lEMCeWEJ8o&list=PL_WGMLcL4jzWPhdhcUyhbFU6bC0oJd2BR) +> - [Telegram](https://t.me/leifermendez) diff --git a/starters/apps/base-meta-json/app.js b/starters/apps/base-meta-json/app.js new file mode 100644 index 0000000..506ef6f --- /dev/null +++ b/starters/apps/base-meta-json/app.js @@ -0,0 +1,95 @@ +const { + createBot, + createProvider, + createFlow, + addKeyword, + addChild, +} = require('@bot-whatsapp/bot') + +const MetaProvider = require('@bot-whatsapp/provider/meta') +const JsonFileAdapter = require('@bot-whatsapp/database/json') + +/** + * Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo: + * + * Menu Principal + * - SubMenu 1 + * - Submenu 1.1 + * - Submenu 2 + * - Submenu 2.1 + * + * Primero declaras los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + */ + +const flowBolsos2 = addKeyword(['bolsos2', '2']) + .addAnswer('🤯 *MUCHOS* bolsos ...') + .addAnswer('y mas bolsos... bla bla') + +const flowZapatos2 = addKeyword(['zapatos2', '2']) + .addAnswer('🤯 repito que tengo *MUCHOS* zapatos.') + .addAnswer('y algunas otras cosas.') + +const flowZapatos = addKeyword(['1', 'zapatos', 'ZAPATOS']) + .addAnswer('🤯 Veo que elegiste zapatos') + .addAnswer('Tengo muchos zapatos...bla bla') + .addAnswer( + ['Manda:', '*(2) Zapatos2*', 'para mas información'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowZapatos2)] + ) + +const flowBolsos = addKeyword(['2', 'bolsos', 'BOLSOS']) + .addAnswer('🙌 Veo que elegiste bolsos') + .addAnswer('Tengo muchos bolsos...bla bla') + .addAnswer( + ['Manda:', '*(2) Bolsos2*', 'para mas información.'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos2)] + ) + +/** + * Declarando flujo principal + */ + +const flowPrincipal = addKeyword(['hola', 'ole', 'alo']) + .addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?']) + .addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...']) + .addAnswer( + ['Para continuar escribe:', '*(1) Zapatos*', '*(2) Bolsos*'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos), ...addChild(flowZapatos)] + ) + +const main = async () => { + const adapterDB = new JsonFileAdapter() + const adapterFlow = createFlow([flowPrincipal]) + + const adapterProvider = createProvider(MetaProvider, { + jwtToken: 'jwtToken', + numberId: 'numberId', + verifyToken: 'verifyToken', + }) + + createBot({ + flow: adapterFlow, + provider: adapterProvider, + database: adapterDB, + }) +} + +main() diff --git a/starters/apps/base-meta-json/package.json b/starters/apps/base-meta-json/package.json new file mode 100644 index 0000000..3243406 --- /dev/null +++ b/starters/apps/base-meta-json/package.json @@ -0,0 +1,22 @@ +{ + "name": "bot-whatsapp-base-meta-json", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "pre-copy": "cd .. && yarn run copy.lib base-meta-json", + "start": "node app.js" + }, + "keywords": [], + "dependencies": { + "body-parser": "^1.20.1", + "polka": "^0.5.2", + "@bot-whatsapp/bot": "latest", + "@bot-whatsapp/cli": "latest", + "@bot-whatsapp/database": "latest", + "@bot-whatsapp/provider": "latest", + "axios": "^1.2.1" + }, + "author": "", + "license": "ISC" +} diff --git a/starters/apps/base-meta-memory/app.js b/starters/apps/base-meta-memory/app.js index ab26888..c141fad 100644 --- a/starters/apps/base-meta-memory/app.js +++ b/starters/apps/base-meta-memory/app.js @@ -6,7 +6,7 @@ const { addChild, } = require('@bot-whatsapp/bot') -const TwilioProvider = require('@bot-whatsapp/provider/twilio') +const MetaProvider = require('@bot-whatsapp/provider/meta') const MockAdapter = require('@bot-whatsapp/database/mock') /** @@ -79,10 +79,10 @@ const main = async () => { const adapterDB = new MockAdapter() const adapterFlow = createFlow([flowPrincipal]) - const adapterProvider = createProvider(TwilioProvider, { - accountSid: 'YOUR_ACCOUNT_SID', - authToken: 'YOUR_ACCOUNT_TOKEN', - vendorNumber: '+14155238886', + const adapterProvider = createProvider(MetaProvider, { + jwtToken: 'jwtToken', + numberId: 'numberId', + verifyToken: 'verifyToken', }) createBot({ diff --git a/starters/apps/base-meta-memory/package.json b/starters/apps/base-meta-memory/package.json index af95cf3..f86e916 100644 --- a/starters/apps/base-meta-memory/package.json +++ b/starters/apps/base-meta-memory/package.json @@ -14,7 +14,8 @@ "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest", - "@bot-whatsapp/provider": "latest" + "@bot-whatsapp/provider": "latest", + "axios": "^1.2.1" }, "author": "", "license": "ISC" diff --git a/starters/apps/base-meta-mongo/README.md b/starters/apps/base-meta-mongo/README.md new file mode 100644 index 0000000..d0e43d2 --- /dev/null +++ b/starters/apps/base-meta-mongo/README.md @@ -0,0 +1,34 @@ +### CHATBOT Whatsapp + +Este bot es una aplicación que puedes vincular con tu whatsapp y crear flujos para automatizar tareas en tu negocio o procesos repetitivos. + +Este bot contiene un flujo básico en el cual una persona (cliente) escribe **"hola"** y el bot responde: +- Bienvenido a mi tienda +- ¿Como puedo ayudarte? +- Tengo: Zapatos, Bolsos etc.. + +__Iniciar__ + +Los flujos se declaran de atrás para adelante, es decir que si tienes un flujo de este tipo: + + Menu Principal + - SubMenu 1 + - Submenu 1.1 + - Submenu 2 + - Submenu 2.1 + +Primero se declaran los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + +``` +npm install +npm start +``` + +__¿Tienes problemas?:__ [Abrir Issue](https://github.com/codigoencasa/bot-whatsapp/issues/new/choose) + +------ +> ¿Quieres se parte de este proyecto? +> - [Discord](https://link.codigoencasa.com/DISCORD) +> - [Twitter](https://twitter.com/leifermendez) +> - [Youtube](https://www.youtube.com/watch?v=5lEMCeWEJ8o&list=PL_WGMLcL4jzWPhdhcUyhbFU6bC0oJd2BR) +> - [Telegram](https://t.me/leifermendez) diff --git a/starters/apps/base-meta-mongo/app.js b/starters/apps/base-meta-mongo/app.js new file mode 100644 index 0000000..8cf05d6 --- /dev/null +++ b/starters/apps/base-meta-mongo/app.js @@ -0,0 +1,106 @@ +const { + createBot, + createProvider, + createFlow, + addKeyword, + addChild, +} = require('@bot-whatsapp/bot') + +const MetaProvider = require('@bot-whatsapp/provider/meta') +const MongoAdapter = require('@bot-whatsapp/database/mongo') + +/** + * Declaramos las conexiones de Mongo + */ + +const MONGO_DB_URI = 'mongodb://0.0.0.0:27017' +const MONGO_DB_NAME = 'db_bot' + +/** + * Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo: + * + * Menu Principal + * - SubMenu 1 + * - Submenu 1.1 + * - Submenu 2 + * - Submenu 2.1 + * + * Primero declaras los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + */ + +const flowBolsos2 = addKeyword(['bolsos2', '2']) + .addAnswer('🤯 *MUCHOS* bolsos ...') + .addAnswer('y mas bolsos... bla bla') + +const flowZapatos2 = addKeyword(['zapatos2', '2']) + .addAnswer('🤯 repito que tengo *MUCHOS* zapatos.') + .addAnswer('y algunas otras cosas.') + +const flowZapatos = addKeyword(['1', 'zapatos', 'ZAPATOS']) + .addAnswer('🤯 Veo que elegiste zapatos') + .addAnswer('Tengo muchos zapatos...bla bla') + .addAnswer( + ['Manda:', '*(2) Zapatos2*', 'para mas información'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowZapatos2)] + ) + +const flowBolsos = addKeyword(['2', 'bolsos', 'BOLSOS']) + .addAnswer('🙌 Veo que elegiste bolsos') + .addAnswer('Tengo muchos bolsos...bla bla') + .addAnswer( + ['Manda:', '*(2) Bolsos2*', 'para mas información.'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos2)] + ) + +/** + * Declarando flujo principal + */ + +const flowPrincipal = addKeyword(['hola', 'ole', 'alo']) + .addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?']) + .addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...']) + .addAnswer( + ['Para continuar escribe:', '*(1) Zapatos*', '*(2) Bolsos*'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos), ...addChild(flowZapatos)] + ) + +const main = async () => { + const adapterDB = new MongoAdapter({ + dbUri: MONGO_DB_URI, + dbName: MONGO_DB_NAME, + }) + + const adapterFlow = createFlow([flowPrincipal]) + + const adapterProvider = createProvider(MetaProvider, { + jwtToken: 'jwtToken', + numberId: 'numberId', + verifyToken: 'verifyToken', + }) + + createBot({ + flow: adapterFlow, + provider: adapterProvider, + database: adapterDB, + }) +} + +main() diff --git a/starters/apps/base-meta-mongo/package.json b/starters/apps/base-meta-mongo/package.json new file mode 100644 index 0000000..94055f8 --- /dev/null +++ b/starters/apps/base-meta-mongo/package.json @@ -0,0 +1,23 @@ +{ + "name": "bot-whatsapp-base-meta-mongo", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "pre-copy": "cd .. && yarn run copy.lib base-meta-mongo", + "start": "node app.js" + }, + "keywords": [], + "dependencies": { + "body-parser": "^1.20.1", + "polka": "^0.5.2", + "@bot-whatsapp/bot": "latest", + "@bot-whatsapp/cli": "latest", + "@bot-whatsapp/database": "latest", + "@bot-whatsapp/provider": "latest", + "axios": "^1.2.1", + "mongodb": "^4.12.1" + }, + "author": "", + "license": "ISC" +} diff --git a/starters/apps/base-meta-mysql/README.md b/starters/apps/base-meta-mysql/README.md new file mode 100644 index 0000000..d0e43d2 --- /dev/null +++ b/starters/apps/base-meta-mysql/README.md @@ -0,0 +1,34 @@ +### CHATBOT Whatsapp + +Este bot es una aplicación que puedes vincular con tu whatsapp y crear flujos para automatizar tareas en tu negocio o procesos repetitivos. + +Este bot contiene un flujo básico en el cual una persona (cliente) escribe **"hola"** y el bot responde: +- Bienvenido a mi tienda +- ¿Como puedo ayudarte? +- Tengo: Zapatos, Bolsos etc.. + +__Iniciar__ + +Los flujos se declaran de atrás para adelante, es decir que si tienes un flujo de este tipo: + + Menu Principal + - SubMenu 1 + - Submenu 1.1 + - Submenu 2 + - Submenu 2.1 + +Primero se declaran los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + +``` +npm install +npm start +``` + +__¿Tienes problemas?:__ [Abrir Issue](https://github.com/codigoencasa/bot-whatsapp/issues/new/choose) + +------ +> ¿Quieres se parte de este proyecto? +> - [Discord](https://link.codigoencasa.com/DISCORD) +> - [Twitter](https://twitter.com/leifermendez) +> - [Youtube](https://www.youtube.com/watch?v=5lEMCeWEJ8o&list=PL_WGMLcL4jzWPhdhcUyhbFU6bC0oJd2BR) +> - [Telegram](https://t.me/leifermendez) diff --git a/starters/apps/base-meta-mysql/app.js b/starters/apps/base-meta-mysql/app.js new file mode 100644 index 0000000..796f9ba --- /dev/null +++ b/starters/apps/base-meta-mysql/app.js @@ -0,0 +1,108 @@ +const { + createBot, + createProvider, + createFlow, + addKeyword, + addChild, +} = require('@bot-whatsapp/bot') + +const MetaProvider = require('@bot-whatsapp/provider/meta') +const MySQLAdapter = require('@bot-whatsapp/database/mysql') + +/** + * Declaramos las conexiones de MySQL + */ +const MYSQL_DB_HOST = 'localhost' +const MYSQL_DB_USER = 'usr' +const MYSQL_DB_PASSWORD = 'pass' +const MYSQL_DB_NAME = 'bot' + +/** + * Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo: + * + * Menu Principal + * - SubMenu 1 + * - Submenu 1.1 + * - Submenu 2 + * - Submenu 2.1 + * + * Primero declaras los submenus 1.1 y 2.1, luego el 1 y 2 y al final el principal. + */ + +const flowBolsos2 = addKeyword(['bolsos2', '2']) + .addAnswer('🤯 *MUCHOS* bolsos ...') + .addAnswer('y mas bolsos... bla bla') + +const flowZapatos2 = addKeyword(['zapatos2', '2']) + .addAnswer('🤯 repito que tengo *MUCHOS* zapatos.') + .addAnswer('y algunas otras cosas.') + +const flowZapatos = addKeyword(['1', 'zapatos', 'ZAPATOS']) + .addAnswer('🤯 Veo que elegiste zapatos') + .addAnswer('Tengo muchos zapatos...bla bla') + .addAnswer( + ['Manda:', '*(2) Zapatos2*', 'para mas información'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowZapatos2)] + ) + +const flowBolsos = addKeyword(['2', 'bolsos', 'BOLSOS']) + .addAnswer('🙌 Veo que elegiste bolsos') + .addAnswer('Tengo muchos bolsos...bla bla') + .addAnswer( + ['Manda:', '*(2) Bolsos2*', 'para mas información.'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos2)] + ) + +/** + * Declarando flujo principal + */ + +const flowPrincipal = addKeyword(['hola', 'ole', 'alo']) + .addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?']) + .addAnswer(['Tengo:', 'Zapatos', 'Bolsos', 'etc ...']) + .addAnswer( + ['Para continuar escribe:', '*(1) Zapatos*', '*(2) Bolsos*'], + { capture: true }, + (ctx) => { + console.log('Aqui puedes ver más info del usuario...') + console.log('Puedes enviar un mail, hook, etc..') + console.log(ctx) + }, + [...addChild(flowBolsos), ...addChild(flowZapatos)] + ) + +const main = async () => { + const adapterDB = new MySQLAdapter({ + host: MYSQL_DB_HOST, + user: MYSQL_DB_USER, + database: MYSQL_DB_NAME, + password: MYSQL_DB_PASSWORD, + }) + const adapterFlow = createFlow([flowPrincipal]) + + const adapterProvider = createProvider(MetaProvider, { + jwtToken: 'jwtToken', + numberId: 'numberId', + verifyToken: 'verifyToken', + }) + + createBot({ + flow: adapterFlow, + provider: adapterProvider, + database: adapterDB, + }) +} + +main() diff --git a/starters/apps/base-meta-mysql/package.json b/starters/apps/base-meta-mysql/package.json new file mode 100644 index 0000000..a9a71b0 --- /dev/null +++ b/starters/apps/base-meta-mysql/package.json @@ -0,0 +1,23 @@ +{ + "name": "bot-whatsapp-base-meta-mysql", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "pre-copy": "cd .. && yarn run copy.lib base-meta-mysql", + "start": "node app.js" + }, + "keywords": [], + "dependencies": { + "body-parser": "^1.20.1", + "polka": "^0.5.2", + "@bot-whatsapp/bot": "latest", + "@bot-whatsapp/cli": "latest", + "@bot-whatsapp/database": "latest", + "@bot-whatsapp/provider": "latest", + "axios": "^1.2.1", + "mysql2": "^2.3.3" + }, + "author": "", + "license": "ISC" +}