This commit is contained in:
Leifer Mendez
2022-11-08 21:41:16 +01:00
parent 2114800b84
commit 576092fc96
26 changed files with 408 additions and 801 deletions

4
.gitignore vendored
View File

@@ -12,4 +12,6 @@ mediaSend/*
packages/cli/config.json
config.json
coverage/
*.lcov
*.lcov
lib
tmp/

View File

@@ -0,0 +1,79 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
/**
* require('@bot-whatsapp')
*/
const { inout, provider, bot } = require('../lib/index.cjs')
/**
* MockDB
*/
class DatabaseClass {
constructor() {}
saveLog = (ctx) => {
return ctx
}
}
const adapterDB = new DatabaseClass()
const adapterFlow = new inout.instance(
(() => {
const flowA = inout
.addKeyword('hola')
.addAnswer('Bienvenido a tu tienda 🥲')
.addAnswer('escribe *catalogo* o *ofertas*')
.toJson()
const flowB = inout
.addKeyword(['catalogo', 'ofertas'])
.addAnswer('Este es nuestro CATALOGO mas reciente!', {
buttons: [{ body: 'Xiaomi' }, { body: 'Samsung' }],
})
.toJson()
const flowC = inout
.addKeyword('Xiaomi')
.addAnswer('Estos son nuestro productos XIAOMI ....', {
media: 'https://....',
})
.addAnswer('Si quieres mas info escrbie *info*')
.toJson()
const flowD = inout
.addKeyword('chao!')
.addAnswer('bye!')
.addAnswer('Recuerda que tengo esta promo', {
media: 'https://media2.giphy.com/media/VQJu0IeULuAmCwf5SL/giphy.gif',
})
.toJson()
const flowE = inout
.addKeyword('Modelo C', { sensitive: false })
.addAnswer('100USD', { media: 'http//:...' })
.toJson()
return [...flowA, ...flowB, ...flowC, ...flowC, ...flowD, ...flowE]
})()
)
const adapterProvider = new provider.instance()
test(`[Flow Basico]: BotClass`, () => {
let messages = []
const flows = adapterFlow
const databases = adapterDB
const providers = adapterProvider
const botBasic = new bot.instance(flows, databases, providers)
botBasic.on('message', (ctx) => messages.push(ctx.body))
botBasic.emit('message', { body: 'hola' })
botBasic.emit('message', { body: 'otro' })
assert.is(messages.join(','), ['hola', 'otro'].join(','))
})
test.run()

View File

@@ -1,163 +0,0 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const { EventEmitter } = require('node:events')
const { addKeyword } = require('../packages/io')
const database = require('mime-db')
const flow = addKeyword('hola')
.addAnswer('bienvenido')
.addAnswer('chao')
.toJson()
const provider = {
sendMessage: (ctx) => {
console.log('Enviando...', ctx)
},
}
//// DataBaseMock ---------------------------------------------
class DataBaseMock {
flow
provider
constructor(_flow, _provider) {
this.flow = _flow
this.provider = _provider
}
continue = (message, ref = false) => {
let keyRef = ref
let ansRef = null
if (!keyRef) {
keyRef = this.flow.find((n) => n.keyword.includes(message)).ref
}
ansRef = this.flow.find((n) => n.keyword === keyRef)
if (ansRef) {
this.provider.sendMessage(ansRef.answer)
this.continue(null, ansRef.ref)
}
}
}
//// ProviderMock ---------------------------------------------
class ProviderMock {
constructor() {
//twilio ...
}
sendMessage = (ctx) => {
console.log('Enviando...', ctx)
}
}
// const bot = {
// start: ({ flow, database, provider }) => {
// // console.log(database instanceof DataBaseMock)
// const flowCtx = database
// const botEmitter = new MyEmitter()
// botEmitter.on('message', (ctx) => flowCtx.continue(ctx.body))
// return botEmitter
// },
// }
//// BotMock ---------------------------------------------
// test(`[Flow Basico]: Saludar y Responder`, () => {
// let messages = []
// const botBasic = new BotMock(
// flow,
// new DataBaseMock(flow, provider),
// provider
// )
// botBasic.on('message', (ctx) => messages.push(ctx.body))
// // Esta linea emula el llegar un mensaje!
// botBasic.emit('message', { body: 'hola' })
// assert.is(messages.join(','), 'hola')
// })
// test.run()
/***
* NEW
*/
class BotClass extends EventEmitter {
flowClass
databaseClass
providerClass
constructor(_flow, _database, _provider) {
super()
this.flowClass = _flow
this.databaseClass = _database
this.providerClass = _provider
this.on('message', (ctxMessage) => {
this.databaseClass.saveLog(ctxMessage)
this.continue(ctxMessage.body)
})
}
continue = (message, ref = false) => {
const responde = this.flowClass.find(message, ref)
if (responde) {
this.providerClass.sendMessage(responde.answer)
this.continue(null, responde.ref)
}
}
}
class ProviderClass {
constructor() {}
sendMessage = (message) => {
console.log('Enviar...', message)
}
}
class FlowClass {
flow
constructor(_flow) {
this.flow = _flow
}
find = (message, ref = false) => {
let keyRef = ref
let ansRef = null
if (!keyRef) {
keyRef =
this.flow.find((n) => n.keyword.includes(message))?.ref || null
}
ansRef = this.flow.find((n) => n.keyword === keyRef)
if (ansRef) return ansRef
return false
}
}
class DatabaseClass {
constructor() {}
saveLog = (ctx) => {
console.log('Guardando...', ctx)
}
}
test(`[Flow Basico]: Saludar y Responder`, () => {
let messages = []
const botBasic = new BotClass(
new FlowClass(flow),
new DatabaseClass(),
new ProviderClass()
)
botBasic.on('message', (ctx) => messages.push(ctx.body))
botBasic.emit('message', { body: 'hola' })
assert.is(messages.join(','), 'hola')
})
test.run()

View File

@@ -1,328 +0,0 @@
'use strict';
var require$$0$3 = require('prompts');
var require$$0 = require('kleur');
var require$$0$1 = require('fs');
var require$$1$1 = require('path');
var require$$1 = require('cross-spawn');
var require$$0$2 = require('rimraf');
const { red: red$2 } = require$$0;
const spawn = require$$1;
// const { detect } = require('detect-package-manager')
const PKG_OPTION = {
npm: 'install',
yarn: 'add',
pnpm: 'add',
};
const getPkgManage$1 = async () => {
// const pkg = await detect()
// return pkg
return 'npm'
};
const installDeps$1 = (pkgManager, packageList) => {
const errorMessage = `Ocurrio un error instalando ${packageList}`;
let childProcess = [];
const installSingle = (pkgInstall) => () => {
new Promise((resolve) => {
try {
childProcess = spawn(
pkgManager,
[PKG_OPTION[pkgManager], pkgInstall],
{
stdio: 'inherit',
}
);
childProcess.on('error', (e) => {
console.error(e);
console.error(red$2(errorMessage));
resolve();
});
childProcess.on('close', (code) => {
if (code === 0) {
resolve();
} else {
console.error(code);
console.error(red$2(errorMessage));
}
});
resolve();
} catch (e) {
console.error(e);
console.error(red$2(errorMessage));
}
});
};
if (typeof packageList === 'string') {
childProcess.push(installSingle(packageList));
} else {
for (const pkg of packageList) {
childProcess.push(installSingle(pkg));
}
}
const runInstall = () => {
return Promise.all(childProcess.map((i) => i()))
};
return { runInstall }
};
var tool = { getPkgManage: getPkgManage$1, installDeps: installDeps$1 };
const { readFileSync, existsSync } = require$$0$1;
const { join: join$2 } = require$$1$1;
const { installDeps, getPkgManage } = tool;
const PATHS_DIR = [
join$2(__dirname, 'pkg-to-update.json'),
join$2(__dirname, '..', 'pkg-to-update.json'),
];
const PKG_TO_UPDATE = () => {
const PATH_INDEX = PATHS_DIR.findIndex((a) => existsSync(a));
const data = readFileSync(PATHS_DIR[PATH_INDEX], 'utf-8');
const dataParse = JSON.parse(data);
const pkg = Object.keys(dataParse).map((n) => `${n}@${dataParse[n]}`);
return pkg
};
const installAll$1 = async () => {
const pkg = await getPkgManage();
installDeps(pkg, PKG_TO_UPDATE()).runInstall();
};
var install = { installAll: installAll$1 };
const rimraf = require$$0$2;
const { yellow: yellow$2 } = require$$0;
const { join: join$1 } = require$$1$1;
const PATH_WW = [
join$1(process.cwd(), '.wwebjs_auth'),
join$1(process.cwd(), 'session.json'),
];
const cleanSession$1 = () => {
const queue = [];
for (const PATH of PATH_WW) {
console.log(yellow$2(`😬 Eliminando: ${PATH}`));
queue.push(rimraf(PATH, () => Promise.resolve()));
}
return Promise.all(queue)
};
var clean = { cleanSession: cleanSession$1 };
const { red: red$1, yellow: yellow$1, green, bgCyan } = require$$0;
const checkNodeVersion$1 = () => {
console.log(bgCyan('🚀 Revisando tu Node.js'));
const version = process.version;
const majorVersion = parseInt(version.replace('v', '').split('.').shift());
if (majorVersion < 16) {
console.error(
red$1(
`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`
)
);
process.exit(1);
}
console.log(green(`Node.js combatible ${version}`));
console.log(``);
};
const checkOs$1 = () => {
console.log(bgCyan('🙂 Revisando tu Sistema Operativo'));
const os = process.platform;
if (!os.includes('win32')) {
const messages = [
`El sistema operativo actual (${os}) posiblemente requiera`,
`una confiuración adicional referente al puppeter`,
``,
`Recuerda pasar por el WIKI`,
`🔗 https://github.com/leifermendez/bot-whatsapp/wiki/Instalaci%C3%B3n`,
``,
];
console.log(yellow$1(messages.join(' \n')));
}
console.log(``);
};
var check = { checkNodeVersion: checkNodeVersion$1, checkOs: checkOs$1 };
const { writeFile } = require$$0$1.promises;
const { join } = require$$1$1;
/**
* JSON_TEMPLATE = {[key:string]{...pros}}
*/
const JSON_TEMPLATE = {
provider: {
vendor: '',
},
database: {
host: '',
password: '',
port: '',
username: '',
db: '',
},
io: {
vendor: '',
},
};
const PATH_CONFIG = join(process.cwd(), 'config.json');
const jsonConfig$1 = () => {
return writeFile(
PATH_CONFIG,
JSON.stringify(JSON_TEMPLATE, null, 2),
'utf-8'
)
};
var configuration = { jsonConfig: jsonConfig$1 };
const prompts = require$$0$3;
const { yellow, red } = require$$0;
const { installAll } = install;
const { cleanSession } = clean;
const { checkNodeVersion, checkOs } = check;
const { jsonConfig } = configuration;
const startInteractive$1 = async () => {
const questions = [
{
type: 'text',
name: 'dependencies',
message:
'Quieres actualizar las librerias "whatsapp-web.js"? (Y/n)',
},
{
type: 'text',
name: 'cleanTmp',
message: 'Quieres limpiar la session del bot? (Y/n)',
},
{
type: 'multiselect',
name: 'providerWs',
message: 'Proveedor de Whatsapp',
choices: [
{ title: 'whatsapp-web.js', value: 'whatsapp-web.js' },
{ title: 'API Oficial (Meta)', value: 'meta', disabled: true },
{ title: 'Twilio', value: 'twilio', disabled: true },
],
max: 1,
hint: 'Espacio para selecionar',
instructions: '↑/↓',
},
{
type: 'multiselect',
name: 'providerDb',
message: 'Cual base de datos quieres usar',
choices: [
{ title: 'JSONFile', value: 'json' },
{ title: 'MySQL', value: 'mysql', disabled: true },
{ title: 'Mongo', value: 'mongo', disabled: true },
],
max: 1,
hint: 'Espacio para selecionar',
instructions: '↑/↓',
},
];
console.clear();
checkNodeVersion();
checkOs();
const onCancel = () => {
console.log('Proceso cancelado!');
return true
};
const response = await prompts(questions, { onCancel });
const {
dependencies = '',
cleanTmp = '',
providerDb = [],
providerWs = [],
} = response;
/**
* Question #1
* @returns
*/
const installOrUdpateDep = async () => {
const answer = dependencies.toLowerCase() || 'n';
if (answer.includes('n')) return true
if (answer.includes('y')) {
await installAll();
return true
}
};
/**
* Question #2
* @returns
*/
const cleanAllSession = async () => {
const answer = cleanTmp.toLowerCase() || 'n';
if (answer.includes('n')) return true
if (answer.includes('y')) {
await cleanSession();
return true
}
};
const vendorProvider = async () => {
if (!providerWs.length) {
console.log(
red(
`Debes de seleccionar una WS Provider. Tecla [Space] para seleccionar`
)
);
process.exit(1);
}
console.log(yellow(`'Deberia crer una carpeta en root/provider'`));
return true
};
const dbProvider = async () => {
const answer = providerDb;
if (!providerDb.length) {
console.log(
red(
`Debes de seleccionar una DB Provider. Tecla [Space] para seleccionar`
)
);
process.exit(1);
}
if (answer === 'json') {
console.log('Deberia crer una carpeta en root/data');
return 1
}
};
await installOrUdpateDep();
await cleanAllSession();
await vendorProvider();
await dbProvider();
await jsonConfig();
};
var interactive = { startInteractive: startInteractive$1 };
const { startInteractive } = interactive;
if (process.env.NODE_ENV === 'dev') startInteractive();
var cli = { startInteractive };
module.exports = cli;

View File

@@ -1,141 +0,0 @@
'use strict';
var require$$0 = require('crypto');
const crypto = require$$0;
const generateRef$3 = () => {
return crypto.randomUUID()
};
var hash = { generateRef: generateRef$3 };
const { generateRef: generateRef$2 } = hash;
var utils = { generateRef: generateRef$2 };
const toJson$3 = (inCtx) => () => {
const lastCtx = inCtx.hasOwnProperty('ctx') ? inCtx.ctx : inCtx;
return lastCtx.json
};
var toJson_1 = { toJson: toJson$3 };
const { generateRef: generateRef$1 } = utils;
const { toJson: toJson$2 } = toJson_1;
/**
*
* @param answer string
* @param options {media:string, buttons:[], capture:true default false}
* @returns
*/
const addAnswer$3 = (inCtx) => (answer, options) => {
const getAnswerOptions = () => ({
media: typeof options?.media === 'string' ? `${options?.media}` : null,
buttons: Array.isArray(options?.buttons) ? options.buttons : [],
capture:
typeof options?.capture === 'boolean' ? options?.capture : false,
});
const lastCtx = inCtx.hasOwnProperty('ctx') ? inCtx.ctx : inCtx;
const ctxAnswer = () => {
const ref = `ans_${generateRef$1()}`;
const options = {
...getAnswerOptions(),
keyword: {},
};
const json = [].concat(inCtx.json).concat([
{
ref,
keyword: lastCtx.ref,
answer,
options,
},
]);
return { ...lastCtx, ref, answer, json, options }
};
const ctx = ctxAnswer();
return {
ctx,
ref: ctx.ref,
addAnswer: addAnswer$3(ctx),
toJson: toJson$2(ctx),
}
};
var addAnswer_1 = { addAnswer: addAnswer$3 };
const { generateRef } = utils;
const { addAnswer: addAnswer$2 } = addAnswer_1;
const { toJson: toJson$1 } = toJson_1;
/**
* addKeyword:
* Es necesario que genere id|hash
*/
/**
*
* @param {*} message `string | string[]`
* @param {*} options {sensitive:boolean} default false
*/
const addKeyword$2 = (keyword, options) => {
/**
* Esta funcion deberia parsear y validar las opciones
* del keyword
* @returns
*/
const parseOptions = () => {
const defaultProperties = {
sensitive:
typeof options?.sensitive === 'boolean'
? options?.sensitive
: false,
};
return defaultProperties
};
const ctxAddKeyword = () => {
const ref = `key_${generateRef()}`;
const options = parseOptions();
const json = [
{
ref,
keyword,
options,
},
];
/**
* Se guarda en db
*/
return { ref, keyword, options, json }
};
const ctx = ctxAddKeyword();
return {
ctx,
ref: ctx.ref,
addAnswer: addAnswer$2(ctx),
toJson: toJson$1(ctx),
}
};
var addKeyword_1 = { addKeyword: addKeyword$2 };
const { addAnswer: addAnswer$1 } = addAnswer_1;
const { addKeyword: addKeyword$1 } = addKeyword_1;
const { toJson } = toJson_1;
var methods = { addAnswer: addAnswer$1, addKeyword: addKeyword$1, toJson };
const { addKeyword, addAnswer } = methods;
var io = { addKeyword, addAnswer };
module.exports = io;

6
package-lock.json generated
View File

@@ -2527,6 +2527,12 @@
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true
},
"husky": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.2.tgz",
"integrity": "sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==",
"dev": true
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",

View File

@@ -4,12 +4,26 @@
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
"main": "app.js",
"scripts": {
"cli": "node ./packages/cli/bin/cli.js",
"cli:rollup": "rollup ./packages/cli/index.js --config ./packages/cli/rollup-cli.config.js",
"io:rollup": "rollup ./packages/io/index.js --config ./packages/io/rollup-cli.config.js",
"core:rollup": "rollup ./packages/core/index.js --config ./packages/core/rollup-cli.config.js",
"provider:rollup": "rollup ./packages/provider/index.js --config ./packages/provider/rollup-cli.config.js",
"all:rollup": "rollup ./packages/index.js --config ./packages/rollup-cli.config.js",
"format:check": "prettier --check ./packages",
"format:write": "prettier --write ./packages",
"lint:check": "eslint ./packages",
"lint:fix": "eslint --fix ./packages",
"build": "npm run all:rollup",
"test.unit": "node ./node_modules/uvu/bin.js packages test",
"test.e2e": "node ./node_modules/uvu/bin.js __tests__ test",
"test.coverage": "node ./node_modules/c8/bin/c8.js --check-coverage --lines=90 npm run test.unit"
"test.coverage": "node ./node_modules/c8/bin/c8.js --check-coverage --lines=90 npm run test.unit",
"cli": "node ./packages/cli/bin/cli.js"
},
"husky": {
"hooks": {
"pre-commit": "npm run format:check && npm run lint:fix",
"pre-push": "npm run test"
}
},
"workspaces": [
"packages/cli",
@@ -63,6 +77,7 @@
"detect-package-manager": "^2.0.1",
"eslint": "^8.26.0",
"eslint-config-prettier": "^8.5.0",
"husky": "^8.0.2",
"kleur": "^4.1.5",
"pm2": "^5.2.0",
"prettier": "^2.7.1",

View File

@@ -3,37 +3,42 @@
Se separaran responsabilidades del proyecto en diferentes packages, de esta manera se podra versionar y controlar los diferentes versionamientos y cambios con un mayor desacoplamiento.
##### Principales Funciones
El bot tiene tres funciones principales hasta este momento la cuales divideremos en paquetes para que puedan trabajarse y por separador sin acoplamiento.
__Package CLI__ (*Command Line Interface*)
El bot tiene tres funciones principales hasta este momento la cuales divideremos en paquetes para que puedan trabajarse y por separador sin acoplamiento.
**Package CLI** (_Command Line Interface_)
> Sera basicamente un asistente via `cosola` el cual nos ayudara a realizar las instalacion de las dependencias necesarias y a crear un archivo de configuracion para tener un migrado rápido.
> La idea esque se pueda ejecutar un commando parecido a `npm create bot@leifermendez` o algo parecido y comienze a instalar todo.
> La idea esque se pueda ejecutar un commando parecido a `npm create bot@leifermendez` o algo parecido y comienze a instalar todo.
🤞 Funciones deseadas:
- Que actualice y corrija los problema de versionamientos más frecuetes
- Verificar la versión de NODE correcta
- Verificar OS para brindar mejor soporte de puppeter
- Limpiar sesion, borrar carpeta de sesion
- Seleccionar provider
- Poder usar un archivo .json con la configuración
- Que actualice y corrija los problema de versionamientos más frecuetes
- Verificar la versión de NODE correcta
- Verificar OS para brindar mejor soporte de puppeter
- Limpiar sesion, borrar carpeta de sesion
- Seleccionar provider
- Poder usar un archivo .json con la configuración
**Package Provider**
__Package Provider__
> Es parte clave del proyecto la idea es poder tener la opcion de incluir otro proveedor de mensajeria como la api oficial o api de twilio
- WhatsappWeb (*default*)
- Whatsapp API official
- Twilio
- WhatsappWeb (_default_)
- Whatsapp API official
- Twilio
**Package Input/Output**
__Package Input/Output__
> Gestionar los diferentes mensajes entranates y poder responder, a la vez de mantener un registro de los datos
---------
__Comunidad__
---
**Comunidad**
> Forma 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)
- [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)

View File

@@ -1,30 +1,30 @@
'use strict';
'use strict'
var require$$0$3 = require('prompts');
var require$$0 = require('kleur');
var require$$0$1 = require('fs');
var require$$1$1 = require('path');
var require$$1 = require('cross-spawn');
var require$$2 = require('detect-package-manager');
var require$$0$2 = require('rimraf');
var require$$0$3 = require('prompts')
var require$$0 = require('kleur')
var require$$0$1 = require('fs')
var require$$1$1 = require('path')
var require$$1 = require('cross-spawn')
var require$$2 = require('detect-package-manager')
var require$$0$2 = require('rimraf')
const { red: red$2 } = require$$0;
const spawn = require$$1;
const { detect } = require$$2;
const { red: red$2 } = require$$0
const spawn = require$$1
const { detect } = require$$2
const PKG_OPTION = {
npm: 'install',
yarn: 'add',
pnpm: 'add',
};
}
const getPkgManage = async () => {
const pkg = await detect();
const pkg = await detect()
return pkg
};
}
const installDeps$1 = (pkgManager, packageList) => {
const errorMessage = `Ocurrio un error instalando ${packageList}`;
let childProcess = [];
const errorMessage = `Ocurrio un error instalando ${packageList}`
let childProcess = []
const installSingle = (pkgInstall) => () => {
new Promise((resolve) => {
@@ -35,112 +35,112 @@ const installDeps$1 = (pkgManager, packageList) => {
{
stdio: 'inherit',
}
);
)
childProcess.on('error', (e) => {
console.error(e);
console.error(red$2(errorMessage));
resolve();
});
console.error(e)
console.error(red$2(errorMessage))
resolve()
})
childProcess.on('close', (code) => {
if (code === 0) {
resolve();
resolve()
} else {
console.error(code);
console.error(red$2(errorMessage));
console.error(code)
console.error(red$2(errorMessage))
}
});
})
resolve();
resolve()
} catch (e) {
console.error(e);
console.error(red$2(errorMessage));
console.error(e)
console.error(red$2(errorMessage))
}
});
};
})
}
if (typeof packageList === 'string') {
childProcess.push(installSingle(packageList));
childProcess.push(installSingle(packageList))
} else {
for (const pkg of packageList) {
childProcess.push(installSingle(pkg));
childProcess.push(installSingle(pkg))
}
}
const runInstall = () => {
return Promise.all(childProcess.map((i) => i()))
};
}
return { runInstall }
};
}
var tool = { getPkgManage, installDeps: installDeps$1 };
var tool = { getPkgManage, installDeps: installDeps$1 }
const { readFileSync, existsSync } = require$$0$1;
const { join: join$2 } = require$$1$1;
const { installDeps } = tool;
const { readFileSync, existsSync } = require$$0$1
const { join: join$2 } = require$$1$1
const { installDeps } = tool
const PATHS_DIR = [
join$2(__dirname, 'pkg-to-update.json'),
join$2(__dirname, '..', 'pkg-to-update.json'),
];
]
const PKG_TO_UPDATE = () => {
const PATH_INDEX = PATHS_DIR.findIndex((a) => existsSync(a));
const data = readFileSync(PATHS_DIR[PATH_INDEX], 'utf-8');
const dataParse = JSON.parse(data);
const pkg = Object.keys(dataParse).map((n) => `${n}@${dataParse[n]}`);
const PATH_INDEX = PATHS_DIR.findIndex((a) => existsSync(a))
const data = readFileSync(PATHS_DIR[PATH_INDEX], 'utf-8')
const dataParse = JSON.parse(data)
const pkg = Object.keys(dataParse).map((n) => `${n}@${dataParse[n]}`)
return pkg
};
}
const installAll$1 = async () => {
// const pkg = await getPkgManage()
installDeps('npm', PKG_TO_UPDATE()).runInstall();
};
installDeps('npm', PKG_TO_UPDATE()).runInstall()
}
var install = { installAll: installAll$1 };
var install = { installAll: installAll$1 }
const rimraf = require$$0$2;
const { yellow: yellow$2 } = require$$0;
const { join: join$1 } = require$$1$1;
const rimraf = require$$0$2
const { yellow: yellow$2 } = require$$0
const { join: join$1 } = require$$1$1
const PATH_WW = [
join$1(process.cwd(), '.wwebjs_auth'),
join$1(process.cwd(), 'session.json'),
];
]
const cleanSession$1 = () => {
const queue = [];
const queue = []
for (const PATH of PATH_WW) {
console.log(yellow$2(`😬 Eliminando: ${PATH}`));
queue.push(rimraf(PATH, () => Promise.resolve()));
console.log(yellow$2(`😬 Eliminando: ${PATH}`))
queue.push(rimraf(PATH, () => Promise.resolve()))
}
return Promise.all(queue)
};
}
var clean = { cleanSession: cleanSession$1 };
var clean = { cleanSession: cleanSession$1 }
const { red: red$1, yellow: yellow$1, green, bgCyan } = require$$0;
const { red: red$1, yellow: yellow$1, green, bgCyan } = require$$0
const checkNodeVersion$1 = () => {
console.log(bgCyan('🚀 Revisando tu Node.js'));
const version = process.version;
const majorVersion = parseInt(version.replace('v', '').split('.').shift());
console.log(bgCyan('🚀 Revisando tu Node.js'))
const version = process.version
const majorVersion = parseInt(version.replace('v', '').split('.').shift())
if (majorVersion < 16) {
console.error(
red$1(
`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`
)
);
process.exit(1);
)
process.exit(1)
}
console.log(green(`Node.js combatible ${version}`));
console.log(``);
};
console.log(green(`Node.js combatible ${version}`))
console.log(``)
}
const checkOs$1 = () => {
console.log(bgCyan('🙂 Revisando tu Sistema Operativo'));
const os = process.platform;
console.log(bgCyan('🙂 Revisando tu Sistema Operativo'))
const os = process.platform
if (!os.includes('win32')) {
const messages = [
`El sistema operativo actual (${os}) posiblemente requiera`,
@@ -149,18 +149,18 @@ const checkOs$1 = () => {
`Recuerda pasar por el WIKI`,
`🔗 https://github.com/leifermendez/bot-whatsapp/wiki/Instalaci%C3%B3n`,
``,
];
]
console.log(yellow$1(messages.join(' \n')));
console.log(yellow$1(messages.join(' \n')))
}
console.log(``);
};
console.log(``)
}
var check = { checkNodeVersion: checkNodeVersion$1, checkOs: checkOs$1 };
var check = { checkNodeVersion: checkNodeVersion$1, checkOs: checkOs$1 }
const { writeFile } = require$$0$1.promises;
const { join } = require$$1$1;
const { writeFile } = require$$0$1.promises
const { join } = require$$1$1
/**
* JSON_TEMPLATE = {[key:string]{...pros}}
@@ -179,9 +179,9 @@ const JSON_TEMPLATE = {
io: {
vendor: '',
},
};
}
const PATH_CONFIG = join(process.cwd(), 'config.json');
const PATH_CONFIG = join(process.cwd(), 'config.json')
const jsonConfig$1 = () => {
return writeFile(
@@ -189,16 +189,16 @@ const jsonConfig$1 = () => {
JSON.stringify(JSON_TEMPLATE, null, 2),
'utf-8'
)
};
}
var configuration = { jsonConfig: jsonConfig$1 };
var configuration = { jsonConfig: jsonConfig$1 }
const prompts = require$$0$3;
const { yellow, red } = require$$0;
const { installAll } = install;
const { cleanSession } = clean;
const { checkNodeVersion, checkOs } = check;
const { jsonConfig } = configuration;
const prompts = require$$0$3
const { yellow, red } = require$$0
const { installAll } = install
const { cleanSession } = clean
const { checkNodeVersion, checkOs } = check
const { jsonConfig } = configuration
const startInteractive$1 = async () => {
const questions = [
@@ -239,49 +239,49 @@ const startInteractive$1 = async () => {
hint: 'Espacio para selecionar',
instructions: '↑/↓',
},
];
]
console.clear();
checkNodeVersion();
checkOs();
console.clear()
checkNodeVersion()
checkOs()
const onCancel = () => {
console.log('Proceso cancelado!');
console.log('Proceso cancelado!')
return true
};
const response = await prompts(questions, { onCancel });
}
const response = await prompts(questions, { onCancel })
const {
dependencies = '',
cleanTmp = '',
providerDb = [],
providerWs = [],
} = response;
} = response
/**
* Question #1
* @returns
*/
const installOrUdpateDep = async () => {
const answer = dependencies.toLowerCase() || 'n';
const answer = dependencies.toLowerCase() || 'n'
if (answer.includes('n')) return true
if (answer.includes('y')) {
await installAll();
await installAll()
return true
}
};
}
/**
* Question #2
* @returns
*/
const cleanAllSession = async () => {
const answer = cleanTmp.toLowerCase() || 'n';
const answer = cleanTmp.toLowerCase() || 'n'
if (answer.includes('n')) return true
if (answer.includes('y')) {
await cleanSession();
await cleanSession()
return true
}
};
}
const vendorProvider = async () => {
if (!providerWs.length) {
@@ -289,40 +289,40 @@ const startInteractive$1 = async () => {
red(
`Debes de seleccionar una WS Provider. Tecla [Space] para seleccionar`
)
);
process.exit(1);
)
process.exit(1)
}
console.log(yellow(`'Deberia crer una carpeta en root/provider'`));
console.log(yellow(`'Deberia crer una carpeta en root/provider'`))
return true
};
}
const dbProvider = async () => {
const answer = providerDb;
const answer = providerDb
if (!providerDb.length) {
console.log(
red(
`Debes de seleccionar una DB Provider. Tecla [Space] para seleccionar`
)
);
process.exit(1);
)
process.exit(1)
}
if (answer === 'json') {
console.log('Deberia crer una carpeta en root/data');
console.log('Deberia crer una carpeta en root/data')
return 1
}
};
}
await installOrUdpateDep();
await cleanAllSession();
await vendorProvider();
await dbProvider();
await jsonConfig();
};
await installOrUdpateDep()
await cleanAllSession()
await vendorProvider()
await dbProvider()
await jsonConfig()
}
var interactive = { startInteractive: startInteractive$1 };
var interactive = { startInteractive: startInteractive$1 }
const { startInteractive } = interactive;
if (process.env.NODE_ENV === 'dev') startInteractive();
var cli = { startInteractive };
const { startInteractive } = interactive
if (process.env.NODE_ENV === 'dev') startInteractive()
var cli = { startInteractive }
module.exports = cli;
module.exports = cli

View File

@@ -4,15 +4,6 @@
"description": "",
"main": "index.js",
"private": true,
"scripts": {
"cli:dev": "cross-env NODE_ENV=dev node ./index.js",
"cli:rollup": "rollup index.js --config ./rollup-cli.config.js",
"format:check": "prettier --check .",
"format:write": "prettier --write .",
"lint:check": "eslint .",
"lint:fix": "eslint --fix .",
"build:cli": "npm run format:write && npm run lint:fix && npm run cli:rollup"
},
"keywords": [],
"author": "",
"license": "ISC"

View File

@@ -3,7 +3,7 @@ const commonjs = require('@rollup/plugin-commonjs')
module.exports = {
input: 'index.js',
output: {
file: 'lib/cli/bundle.cjs',
file: 'lib/cli/bundle.cli.cjs',
format: 'cjs',
},
plugins: [commonjs()],

View File

@@ -0,0 +1,32 @@
const { EventEmitter } = require('node:events')
/**
* Clase principal del BOT
*/
class BotClass extends EventEmitter {
flowClass
databaseClass
providerClass
constructor(_flow, _database, _provider) {
super()
this.flowClass = _flow
this.databaseClass = _database
this.providerClass = _provider
this.on('message', (ctxMessage) => this.handleOnMessage(ctxMessage))
}
handleOnMessage = (ctxMessage) => {
this.databaseClass.saveLog(ctxMessage)
this.continue(ctxMessage.body)
}
continue = (message, ref = false) => {
const responde = this.flowClass.find(message, ref)
if (responde) {
this.providerClass.sendMessage(responde.answer)
this.continue(null, responde.ref)
}
}
}
module.exports = BotClass

2
packages/core/index.js Normal file
View File

@@ -0,0 +1,2 @@
const BotClass = require('./classes/bot.class')
module.exports = { instance: BotClass }

View File

@@ -0,0 +1,21 @@
{
"name": "bot-core",
"version": "0.0.1",
"description": "",
"main": "index.js",
"private": true,
"scripts": {
"core:dev": "node ./index.js",
"core:rollup": "node ../../node_modules/.bin/rollup index.js --config ./rollup-cli.config.js",
"format:check": "prettier --check .",
"format:write": "prettier --write .",
"lint:check": "eslint .",
"lint:fix": "eslint --fix .",
"test:core": "node ../../node_modules/uvu/bin.js tests",
"build:core": "npm run format:write && npm run lint:fix && npm run io:rollup"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {}
}

View File

@@ -0,0 +1,10 @@
const commonjs = require('@rollup/plugin-commonjs')
module.exports = {
input: 'index.js',
output: {
file: 'lib/core/bundle.core.cjs',
format: 'cjs',
},
plugins: [commonjs()],
}

View File

@@ -0,0 +1,32 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const BotClass = require('../classes/bot.class')
class MockDB {
saveLog = () => {}
}
class MockProvider {
sendMessage = () => {}
}
class MockFlow {
find = () => {}
}
test(`BotClass emit ping`, () => {
let messages = []
const botBasic = new BotClass(
new MockFlow(),
new MockDB(),
new MockProvider()
)
botBasic.on('message', (ctx) => messages.push(ctx))
botBasic.emit('message', 'ping')
assert.is(messages.join(''), 'ping')
})
test.run()

5
packages/index.js Normal file
View File

@@ -0,0 +1,5 @@
const inout = require('./io')
const provider = require('./provider')
const bot = require('./core')
module.exports = { inout, provider, bot }

View File

@@ -0,0 +1,20 @@
class FlowClass {
flow
constructor(_flow) {
this.flow = _flow
}
find = (message, ref = false) => {
let keyRef = ref
let ansRef = null
if (!keyRef) {
keyRef =
this.flow.find((n) => n.keyword.includes(message))?.ref || null
}
ansRef = this.flow.find((n) => n.keyword === keyRef)
if (ansRef) return ansRef
return false
}
}
module.exports = FlowClass

View File

@@ -1,4 +1,3 @@
const { addKeyword, addAnswer } = require('./methods')
module.exports = { addKeyword, addAnswer }
const FlowClass = require('./classes/flow.class')
module.exports = { addKeyword, addAnswer, instance: FlowClass }

View File

@@ -4,16 +4,6 @@
"description": "",
"main": "index.js",
"private": true,
"scripts": {
"io:dev": "node ./index.js",
"io:rollup": "node ../../node_modules/.bin/rollup index.js --config ./rollup-cli.config.js",
"format:check": "prettier --check .",
"format:write": "prettier --write .",
"lint:check": "eslint .",
"lint:fix": "eslint --fix .",
"test:io": "node ../../node_modules/uvu/bin.js tests",
"build:io": "npm run format:write && npm run lint:fix && npm run io:rollup"
},
"keywords": [],
"author": "",
"license": "ISC",

View File

@@ -3,7 +3,7 @@ const commonjs = require('@rollup/plugin-commonjs')
module.exports = {
input: 'index.js',
output: {
file: 'lib/io/bundle.cjs',
file: 'lib/io/bundle.io.cjs',
format: 'cjs',
},
plugins: [commonjs()],

View File

@@ -6,9 +6,8 @@ const { inout, provider, database } = require('@bot-whatsapp')
provider.start()
provider.close()
```
- [ ] whatsapp-web.js _verificar update_
- [ ] Meta _verificar tokens_
- [ ] Twilio _verificar tokens_
- [ ] whatsapp-web.js _verificar update_
- [ ] Meta _verificar tokens_
- [ ] Twilio _verificar tokens_

View File

@@ -0,0 +1,9 @@
class ProviderClass {
constructor() {}
sendMessage = (message) => {
return message
}
}
module.exports = ProviderClass

View File

@@ -0,0 +1,2 @@
const ProviderClass = require('./classes/provider.class')
module.exports = { instance: ProviderClass }

View File

@@ -0,0 +1,10 @@
const commonjs = require('@rollup/plugin-commonjs')
module.exports = {
input: 'index.js',
output: {
file: 'lib/provider/bundle.provider.cjs',
format: 'cjs',
},
plugins: [commonjs()],
}

View File

@@ -0,0 +1,10 @@
const commonjs = require('@rollup/plugin-commonjs')
module.exports = {
input: 'index.js',
output: {
file: 'lib/index.cjs',
format: 'cjs',
},
plugins: [commonjs()],
}