diff --git a/.gitignore b/.gitignore index 60be892..d5e4ade 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ config.json coverage/ *.lcov log +log/* +*.log lib tmp/ .yarn/* diff --git a/.vscode/settings.json b/.vscode/settings.json index e286082..d35c0e4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "conventionalCommits.scopes": ["hook", "contributing", "cli", "bot"] + "conventionalCommits.scopes": [ + "hook", + "contributing", + "cli", + "bot", + "provider" + ] } diff --git a/TODO.md b/TODO.md index b5c0a4c..5f3179a 100644 --- a/TODO.md +++ b/TODO.md @@ -13,12 +13,13 @@ - [ ] colocar mensaje esperando conectando whatsapp (provider) - [ ] createDatabase validar implementacion de funciones - [ ] limitar caracteres de mensajes +- [ ] cuando envias numeros (5 o 1) se dispara el flujo ### @bot-whatsapp/database - [X] agregar export package - [X] __(doc):__ Video para explicar como implementar nuevos database - [X] Mongo adapter -- [ ] MySQL adapter +- [X] MySQL adapter - [ ] JsonFile adapter ### @bot-whatsapp/provider diff --git a/package.json b/package.json index 062be61..9515320 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "commit": "git-cz", "cli:rollup": "rollup --config ./packages/cli/rollup-cli.config.js ", + "create-bot:rollup": "rollup --config ./packages/create-bot-whatsapp/rollup-create.config.js ", "bot:rollup": "rollup --config ./packages/bot/rollup-bot.config.js", "provider:rollup": "rollup --config ./packages/provider/rollup-provider.config.js ", "database:rollup": "rollup --config ./packages/database/rollup-database.config.js", @@ -16,12 +17,12 @@ "lint:check": "eslint ./packages", "lint:fix": "eslint --fix ./packages", "build": "yarn run cli:rollup && yarn run bot:rollup && yarn run provider:rollup && yarn run database:rollup", - "link.dist": "cd packages/bot && npm link && cd ../provider && npm link && cd ../cli && npm link && cd ../database && npm link && cd ../provider && npm link", "copy.lib": "node ./scripts/move.js", "test.unit": "node ./node_modules/uvu/bin.js packages test", "test.coverage": "node ./node_modules/c8/bin/c8.js npm run test.unit", "test": "npm run test.coverage", "cli": "node ./packages/cli/bin/cli.js", + "create": "node ./packages/create-bot-whatsapp/bin/create.js", "dev:debug": "node --inspect ./example-app/app.js", "dev": "node ./example-app/app.js", "prepare": "npx husky install", @@ -30,6 +31,7 @@ "release": "standard-version" }, "workspaces": [ + "packages/create-bot-whatsapp", "packages/bot", "packages/cli", "packages/database", diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index b1e2fbc..c5062bb 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -1,6 +1,11 @@ const { toCtx } = require('../io/methods') const { printer } = require('../utils/interactive') +const { Console } = require('console') +const { createWriteStream } = require('fs') +const logger = new Console({ + stdout: createWriteStream(`${process.cwd()}/core.class.log`), +}) /** * [ ] Escuchar eventos del provider asegurarte que los provider emitan eventos * [ ] Guardar historial en db @@ -25,6 +30,10 @@ class CoreClass { * Manejador de eventos */ listenerBusEvents = () => [ + { + event: 'preinit', + func: () => printer('Iniciando provider espere...'), + }, { event: 'require_action', func: ({ instructions, title = '⚡⚡ ACCION REQUERIDA ⚡⚡' }) => @@ -52,6 +61,7 @@ class CoreClass { * @returns */ handleMsg = async (messageInComming) => { + logger.log(`[handleMsg]: `, messageInComming) const { body, from } = messageInComming let msgToSend = [] let fallBackFlag = false diff --git a/packages/bot/index.js b/packages/bot/index.js index 5972d61..8964221 100644 --- a/packages/bot/index.js +++ b/packages/bot/index.js @@ -25,8 +25,8 @@ const createFlow = (args) => { * @param {*} args * @returns */ -const createProvider = (providerClass = class {}) => { - const providerInstance = new providerClass() +const createProvider = (providerClass = class {}, args = null) => { + const providerInstance = new providerClass(args) 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 5ed8eb4..2c18268 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -21,29 +21,25 @@ class FlowClass { } find = (keyOrWord, symbol = false, overFlow = null) => { + keyOrWord = `${keyOrWord}` let capture = false let messages = [] let refSymbol = null overFlow = overFlow ?? this.flowSerialize - const mapSensitiveString = (str, flag = false) => { - if (!flag && Array.isArray(str)) { - return str.map((c) => c.toLowerCase()) + /** Retornar expresion regular para buscar coincidencia */ + const mapSensitive = (str, flag = false) => { + const regexSensitive = flag ? 'g' : 'i' + if (Array.isArray(str)) { + return new RegExp(str.join('|'), regexSensitive) } - - if (!flag && typeof str === 'string') { - return str.toLowerCase() - } - - return str + return new RegExp(str, regexSensitive) } const findIn = (keyOrWord, symbol = false, flow = overFlow) => { const sensitive = refSymbol?.options?.sensitive || false capture = refSymbol?.options?.capture || false - keyOrWord = mapSensitiveString(keyOrWord, sensitive) - if (capture) return messages if (symbol) { @@ -51,9 +47,9 @@ class FlowClass { if (refSymbol?.answer) messages.push(refSymbol) if (refSymbol?.ref) findIn(refSymbol.ref, true) } else { - refSymbol = flow.find((c) => - mapSensitiveString(c.keyword, sensitive).includes(keyOrWord) - ) + refSymbol = flow.find((c) => { + return mapSensitive(c.keyword, sensitive).test(keyOrWord) + }) if (refSymbol?.ref) findIn(refSymbol.ref, true) return messages } diff --git a/packages/create-bot-whatsapp/bin/create.js b/packages/create-bot-whatsapp/bin/create.js new file mode 100644 index 0000000..546eca2 --- /dev/null +++ b/packages/create-bot-whatsapp/bin/create.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +const main = require('../lib/bin/bundle.create.cjs') +main() diff --git a/packages/create-bot-whatsapp/index.js b/packages/create-bot-whatsapp/index.js new file mode 100644 index 0000000..7df7d03 --- /dev/null +++ b/packages/create-bot-whatsapp/index.js @@ -0,0 +1,12 @@ +/** + * Main function + */ +const main = () => { + console.clear() + console.log(``) + console.log(`[PostInstall]: Este es el main function.`) + console.log(`[PostInstall]: 👌 Aqui podrias instalar cosas`) + console.log(``) +} + +module.exports = main diff --git a/packages/create-bot-whatsapp/package.json b/packages/create-bot-whatsapp/package.json new file mode 100644 index 0000000..65926f8 --- /dev/null +++ b/packages/create-bot-whatsapp/package.json @@ -0,0 +1,13 @@ +{ + "name": "create-bot-whatsapp", + "version": "0.0.1", + "description": "", + "main": "./lib/bin/bundle.create.cjs", + "private": true, + "dependencies": { + "@bot-whatsapp/cli": "*" + }, + "bin": { + "bot": "./lib/bin/bundle.create.cjs" + } +} diff --git a/packages/create-bot-whatsapp/rollup-create.config.js b/packages/create-bot-whatsapp/rollup-create.config.js new file mode 100644 index 0000000..54f93f1 --- /dev/null +++ b/packages/create-bot-whatsapp/rollup-create.config.js @@ -0,0 +1,16 @@ +const banner = require('../../config/banner.rollup.json') +const commonjs = require('@rollup/plugin-commonjs') +const { nodeResolve } = require('@rollup/plugin-node-resolve') +const { join } = require('path') + +const PATH = join(__dirname, 'lib', 'bin', 'bundle.create.cjs') + +module.exports = { + input: join(__dirname, 'index.js'), + output: { + banner: banner['banner.output'].join(''), + file: PATH, + format: 'cjs', + }, + plugins: [commonjs(), nodeResolve()], +} diff --git a/packages/database/src/mysql/index.js b/packages/database/src/mysql/index.js index dfeb22e..63e6e7d 100644 --- a/packages/database/src/mysql/index.js +++ b/packages/database/src/mysql/index.js @@ -1,24 +1,17 @@ -require('dotenv').config() const mysql = require('mysql2') -const DB_NAME = process.env.DB_NAME || 'db_bot' -const DB_HOST = process.env.DB_HOST || 'localhost' -const DB_USER = process.env.DB_USER || 'root' - class MyslAdapter { db listHistory = [] + credentials = { host: null, user: null, database: null } - constructor() { + constructor(_credentials) { + this.credentials = _credentials this.init().then() } async init() { - this.db = mysql.createConnection({ - host: DB_HOST, - user: DB_USER, - database: DB_NAME, - }) + this.db = mysql.createConnection(this.credentials) await this.db.connect((error) => { if (!error) { diff --git a/packages/provider/src/twilio/index.js b/packages/provider/src/twilio/index.js index 41795b1..a49bcde 100644 --- a/packages/provider/src/twilio/index.js +++ b/packages/provider/src/twilio/index.js @@ -1,19 +1,24 @@ const twilio = require('twilio') const { ProviderClass } = require('@bot-whatsapp/bot') -const TwilioVendor = new twilio(accountSid, authToken) - +const WebHookServer = require('./server') class TwilioProvider extends ProviderClass { - constructor() { - super(TwilioVendor) + vendor + vendorNumber + constructor({ accountSid, authToken, vendorNumber }) { + super() + this.vendor = new twilio(accountSid, authToken) + this.vendorNumber = vendorNumber + new WebHookServer().start() } - sendMessage = (message) => - this.vendor.messages.create({ + sendMessage = async (number, message) => { + return this.vendor.messages.create({ body: message, - to: '+12345678901', // Text this number - from: '+12345678901', // From a valid Twilio number + from: ['whatsapp:', this.vendorNumber].join(''), + to: ['whatsapp:', number].join(''), }) + } } module.exports = TwilioProvider diff --git a/packages/provider/src/twilio/server.js b/packages/provider/src/twilio/server.js new file mode 100644 index 0000000..4be9c0b --- /dev/null +++ b/packages/provider/src/twilio/server.js @@ -0,0 +1,21 @@ +const polka = require('polka') +const parsePolka = require('@polka/parse') + +class WebHookServer { + incomingMsg = (req, res, next) => { + const { body } = req + let json = JSON.stringify({ error: 'Missing CSRF token', body }) + res.end(json) + } + + start = () => { + polka() + .use(parsePolka.urlencoded({ extended: false })) + .post('/hook', this.incomingMsg) + .listen(3000, () => { + console.log(`> Running on localhost:3000 /hook`) + }) + } +} + +module.exports = WebHookServer diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index a010da6..463987c 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -32,7 +32,7 @@ class WebWhatsappProvider extends ProviderClass { for (const { event, func } of listEvents) { this.vendor.on(event, func) } - + this.vendor.emit('preinit') this.vendor.initialize().catch((e) => { logger.log(e) this.emit('require_action', { @@ -72,10 +72,6 @@ class WebWhatsappProvider extends ProviderClass { event: 'ready', func: () => this.emit('ready', true), }, - { - event: 'authenticated', - func: () => this.emit('ready', true), - }, { event: 'message', func: (payload) => { diff --git a/scripts/move.js b/scripts/move.js index 46dd625..5a0d8b6 100644 --- a/scripts/move.js +++ b/scripts/move.js @@ -11,6 +11,7 @@ const copyLibPkg = async (pkgName, to) => { } Promise.all([ + copyLibPkg('create-bot-whatsapp', appDir), copyLibPkg('bot', appDir), copyLibPkg('database', appDir), copyLibPkg('provider', appDir), diff --git a/yarn.lock b/yarn.lock index 8d6a213..a62b2db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3136,6 +3136,16 @@ __metadata: languageName: node linkType: hard +"create-bot-whatsapp@workspace:packages/create-bot-whatsapp": + version: 0.0.0-use.local + resolution: "create-bot-whatsapp@workspace:packages/create-bot-whatsapp" + dependencies: + "@bot-whatsapp/cli": "*" + bin: + bot: ./lib/bin/bundle.create.cjs + languageName: unknown + linkType: soft + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1"