Compare commits

...

40 Commits

Author SHA1 Message Date
Leifer Mendez
5735b49e25 Merge pull request #155 from leifermendez/feat/releases
feat(release): added
2022-12-08 22:23:03 +01:00
Leifer Mendez
1988948c30 feat(release): added 2022-12-08 22:22:04 +01:00
Leifer Mendez
cb33c0df68 Merge pull request #154 from leifermendez/feat/releases
feat(relases): added
2022-12-08 22:19:25 +01:00
Leifer Mendez
f4ad7040ab feat(release): added 2022-12-08 22:15:46 +01:00
Leifer Mendez
b115dc3654 feat(ci): 🎨 add releases 2022-12-08 21:56:34 +01:00
Leifer Mendez
5d7c297f2f Merge pull request #150 from leifermendez/fix/ci-yarn
ci(action): update
2022-12-08 20:17:46 +01:00
Leifer Mendez
04f99d5ed2 ci(action): update 2022-12-08 20:16:31 +01:00
Leifer Mendez
bb3f21b056 Merge pull request #149 from leifermendez/fix/ci-yarn
fix(ci): update yarn
2022-12-08 20:13:02 +01:00
Leifer Mendez
cf6188d860 ci(action): update 2022-12-08 20:12:11 +01:00
Leifer Mendez
294bfbb35f ci(action): update 2022-12-08 20:11:33 +01:00
github-actions[bot]
230538bcea docs(contributor): contrib-readme-action has updated readme 2022-12-07 22:43:36 +00:00
Leifer Mendez
5e7aa72494 Merge pull request #138 from vicente1992/feat-jsonfile-adapter
feat(adapter): implementation of json file adapter
2022-12-07 23:43:21 +01:00
vicente1992
3159ea5665 Merge branch 'dev' of https://github.com/vicente1992/bot-whatsapp into feat-jsonfile-adapter 2022-12-07 17:18:36 -05:00
vicente1992
4b307efe79 fix(adapter): conflict resolution 2022-12-07 17:14:16 -05:00
github-actions[bot]
0105dab2c4 docs(contributor): contrib-readme-action has updated readme 2022-12-07 22:10:34 +00:00
github-actions[bot]
6e8e16c9a4 docs(contributor): contrib-readme-action has updated readme 2022-12-07 20:33:21 +00:00
Leifer Mendez
8d73c86946 feat(adapter): mysql adapter
feat(adapter): mysql adapter
2022-12-07 21:33:05 +01:00
Leifer Mendez
a7b19d9bff fix(bot): flow improvement + add utils 2022-12-07 21:29:48 +01:00
vicente1992
4b7de0f690 feat(adapter): sql is added to create the table 2022-12-07 15:07:38 -05:00
github-actions[bot]
520145bf7d docs(contributor): contrib-readme-action has updated readme 2022-12-07 19:54:07 +00:00
Leifer Mendez
2253d57fed Merge branch 'dev' of github.com:leifermendez/bot-whatsapp into dev 2022-12-07 18:13:00 +01:00
Leifer Mendez
0fb93f66a3 Merge branch 'fix/webwhatsapp' into dev 2022-12-07 18:12:45 +01:00
Leifer Mendez
501887300d Merge branch 'fix/delay-message' into dev 2022-12-07 18:11:49 +01:00
Leifer Mendez
14b6247106 Merge pull request #137 from vicente1992/feat-mysql-adapter
feat(adapter): added adapter mysql
2022-12-07 18:09:13 +01:00
Leifer Mendez
eda8a67718 refactor(provider): twilio + hook 2022-12-07 18:06:27 +01:00
Leifer Mendez
73caf090ba fix(bot): added delay promises 2022-12-07 16:20:56 +01:00
vicente1992
afa6771903 fix(adapter): corrections are made to the adapter 2022-12-06 15:48:25 -05:00
Leifer Mendez
8dd3be909b feat(provider): added twilio provider 2022-12-06 21:28:52 +01:00
github-actions[bot]
88af2469cb docs(contributor): contrib-readme-action has updated readme 2022-12-06 18:36:55 +00:00
Leifer Mendez
999d6742b4 Merge pull request #141 from leifermendez:feature/twilio
Feature/twilio
2022-12-06 19:36:42 +01:00
Leifer Mendez
24ac9fbf48 fix(bot): fix sensitive case 2022-12-06 19:35:21 +01:00
Leifer Mendez
4350dff22a feat(provider): 🔥 add twilii (weoking) 2022-12-05 20:45:05 +01:00
github-actions[bot]
30e3d443bb docs(contributor): contrib-readme-action has updated readme 2022-12-05 15:47:15 +00:00
Leifer Mendez
f5ea7fe2c4 Merge branch 'dev' of github.com:leifermendez/bot-whatsapp into dev 2022-12-05 16:46:47 +01:00
Leifer Mendez
94d139e484 ci(contributors): add username avatar 2022-12-05 16:46:29 +01:00
github-actions[bot]
8049241f3f docs(contributor): contrib-readme-action has updated readme 2022-12-05 15:45:01 +00:00
Leifer Mendez
28d308ed4b ci(contributors): add username avatar 2022-12-05 16:44:36 +01:00
Leifer Mendez
e0862053d0 Merge branch 'feature/fallback' into dev 2022-12-05 16:35:05 +01:00
Leifer Mendez
242e44315b Merge pull request #139 from leifermendez/feature/fallback
Feature/fallback
2022-12-05 16:32:02 +01:00
vicente1992
5e1a373730 feat(adapter): implementation of json file adapter 2022-12-02 22:27:31 -05:00
35 changed files with 736 additions and 201 deletions

View File

@@ -1,4 +1,4 @@
name: Test / Coverage
name: Bot CI Test
on:
push:
@@ -20,7 +20,8 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build --if-present
- run: npm run test.unit
- run: npm run test.coverage
- run: corepack enable
- name: Install NPM Dependencies
run: yarn install --immutable --network-timeout 300000
- name: Test
run: yarn test

View File

@@ -8,17 +8,13 @@ on:
branches: [main, dev]
jobs:
add-contributors:
contrib-readme-job:
runs-on: ubuntu-latest
name: A job to automate contrib in readme
steps:
- uses: actions/checkout@v2
- uses: BobAnkh/add-contributors@master
- name: Contribute List
uses: akhilmhdh/contributors-readme-action@v2.3.6
with:
CONTRIBUTOR: '### Contributors'
COLUMN_PER_ROW: '6'
ACCESS_TOKEN: ${{secrets.GITHUB_TOKEN}}
IMG_WIDTH: '100'
FONT_SIZE: '14'
PATH: '/README.md'
COMMIT_MESSAGE: 'docs(README): update contributors'
AVATAR_SHAPE: 'round'
image_size: 50
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

26
.github/workflows/relases.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Bot Relases
on:
release:
types: [released, published]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: corepack enable
- name: Install NPM Dependencies
run: yarn install --immutable --network-timeout 300000
- name: Test
run: yarn test
- name: Build
run: yarn build

2
.gitignore vendored
View File

@@ -18,6 +18,8 @@ config.json
coverage/
*.lcov
log
log/*
*.log
lib
tmp/
.yarn/*

View File

@@ -1,5 +1,5 @@
packages/**/lib
packages/docs
packages/docs/*.json
**/.git
**/.svn
**/.hg

10
.vscode/settings.json vendored
View File

@@ -1,3 +1,11 @@
{
"conventionalCommits.scopes": ["hook", "contributing", "cli", "bot"]
"conventionalCommits.scopes": [
"hook",
"contributing",
"cli",
"bot",
"provider",
"adapter",
"ci"
]
}

View File

@@ -8,6 +8,82 @@ Video como hacer PR: https://youtu.be/Lxt8Acob6aU
**Comunidad**
<!-- readme: collaborators,contributors -start -->
<table>
<tr>
<td align="center">
<a href="https://github.com/leifermendez">
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
<br />
<sub><b>Leifer Mendez</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/aurik3">
<img src="https://avatars.githubusercontent.com/u/37228512?v=4" width="50;" alt="aurik3"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vicente1992">
<img src="https://avatars.githubusercontent.com/u/57806030?v=4" width="50;" alt="vicente1992"/>
<br />
<sub><b>Manuel Vicente Ortiz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/leifermendezfroged">
<img src="https://avatars.githubusercontent.com/u/97020486?v=4" width="50;" alt="leifermendezfroged"/>
<br />
<sub><b>Leifer Mendez</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Gonzalito87">
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jzvi12">
<img src="https://avatars.githubusercontent.com/u/10729787?v=4" width="50;" alt="jzvi12"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/tonyvazgar">
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
<br />
<sub><b>Luis Antonio Vázquez García</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ulisesvina">
<img src="https://avatars.githubusercontent.com/u/20508563?v=4" width="50;" alt="ulisesvina"/>
<br />
<sub><b>Ulises Viña</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/rrruuuyyy">
<img src="https://avatars.githubusercontent.com/u/33061671?v=4" width="50;" alt="rrruuuyyy"/>
<br />
<sub><b>Rodrigo Mendoza Cabrera</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/yond1994">
<img src="https://avatars.githubusercontent.com/u/47557263?v=4" width="50;" alt="yond1994"/>
<br />
<sub><b>Yonathan Suarez</b></sub>
</a>
</td></tr>
</table>
<!-- readme: collaborators,contributors -end -->
> Forma parte de este proyecto.
@@ -15,6 +91,3 @@ Video como hacer PR: https://youtu.be/Lxt8Acob6aU
- [Twitter](https://twitter.com/leifermendez)
- [Youtube](https://www.youtube.com/watch?v=5lEMCeWEJ8o&list=PL_WGMLcL4jzWPhdhcUyhbFU6bC0oJd2BR)
- [Telegram](https://t.me/leifermendez)

View File

@@ -2,6 +2,7 @@
- [X] __(doc)__ Video de como colaborar PR
- [ ] __(doc)__ Video implementación de test y cobertura
- [ ] __(doc)__ Video explicacion de github action
- [ ] Crear packages list externas
### @bot-whatsapp/bot
- [X] agregar export package
@@ -10,15 +11,17 @@
- [X] sensitivy viene activado por defecto
- [X] fallback respuesta en hijo: Se puede colocar en option el ref de la answer fallback
- [X] Cuando Envian Sticket devuelve mensaje raro
- [x] addAnswer agregar delay
- [ ] colocar mensaje esperando conectando whatsapp (provider)
- [ ] createDatabase validar implementacion de funciones
- [ ] limitar caracteres de mensajes
- [ ] limitar caracteres de mensajes 4000
- [X] 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

3
core.class.log Normal file
View File

@@ -0,0 +1,3 @@
[handleMsg]: { from: 'XXXXXX', body: 'hola', hasMedia: false }
[handleMsg]: { from: 'XXXXXX', body: 'hola', hasMedia: false }
[handleMsg]: { from: 'XXXXXX', body: 'hola', hasMedia: false }

View File

@@ -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",

View File

@@ -1,6 +1,13 @@
const { toCtx } = require('../io/methods')
const { printer } = require('../utils/interactive')
const { delay } = require('../utils/delay')
const Queue = require('../utils/queue')
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 +32,10 @@ class CoreClass {
* Manejador de eventos
*/
listenerBusEvents = () => [
{
event: 'preinit',
func: () => printer('Iniciando provider espere...'),
},
{
event: 'require_action',
func: ({ instructions, title = '⚡⚡ ACCION REQUERIDA ⚡⚡' }) =>
@@ -52,6 +63,7 @@ class CoreClass {
* @returns
*/
handleMsg = async (messageInComming) => {
logger.log(`[handleMsg]: `, messageInComming)
const { body, from } = messageInComming
let msgToSend = []
let fallBackFlag = false
@@ -130,10 +142,14 @@ class CoreClass {
])
}
sendFlow = (messageToSend, numberOrId) => {
sendFlow = async (messageToSend, numberOrId) => {
const queue = []
for (const ctxMessage of messageToSend) {
queue.push(this.sendProviderAndSave(numberOrId, ctxMessage))
const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs)
Queue.enqueue(() =>
this.sendProviderAndSave(numberOrId, ctxMessage)
)
}
return Promise.all(queue)
}

View File

@@ -22,11 +22,13 @@ const createFlow = (args) => {
/**
* Crear instancia de clase Provider
* Depdendiendo del Provider puedes pasar argumentos
* Ver Documentacion
* @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

View File

@@ -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
}

View File

@@ -3,7 +3,7 @@ const { toJson } = require('./toJson')
/**
*
* @param answer string
* @param options {media:string, buttons:[{"body":"😎 Cursos"}], capture:true default false}
* @param options {media:string, buttons:[{"body":"😎 Cursos"}], delay:ms, capture:true default false}
* @returns
*/
const addAnswer =
@@ -24,6 +24,7 @@ const addAnswer =
: false,
child:
typeof options?.child === 'string' ? `${options?.child}` : null,
delay: typeof options?.delay === 'number' ? options?.delay : 0,
})
const getNested = () => ({

View File

@@ -0,0 +1,4 @@
const delay = (miliseconds) =>
new Promise((res) => setTimeout(res, miliseconds))
module.exports = { delay }

View File

@@ -0,0 +1,46 @@
class Queue {
static queue = []
static pendingPromise = false
static enqueue(promise) {
return new Promise((resolve, reject) => {
this.queue.push({
promise,
resolve,
reject,
})
this.dequeue()
})
}
static dequeue() {
if (this.workingOnPromise) {
return false
}
const item = this.queue.shift()
if (!item) {
return false
}
try {
this.workingOnPromise = true
item.promise()
.then((value) => {
this.workingOnPromise = false
item.resolve(value)
this.dequeue()
})
.catch((err) => {
this.workingOnPromise = false
item.reject(err)
this.dequeue()
})
} catch (err) {
this.workingOnPromise = false
item.reject(err)
this.dequeue()
}
return true
}
}
module.exports = Queue

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
const main = require('../lib/bin/bundle.create.cjs')
main()

View File

@@ -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

View File

@@ -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"
}
}

View File

@@ -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()],
}

View File

@@ -10,11 +10,13 @@
"dependencies": {
"dotenv": "^16.0.3",
"mongodb": "^4.11.0",
"mysql2": "^2.3.3"
"mysql2": "^2.3.3",
"stormdb": "^0.6.0"
},
"exports": {
"./mock": "./lib/mock/index.cjs",
"./mongo": "./lib/mongo/index.cjs",
"./json-file": "./lib/json-file/index.cjs",
"./mysql": "./lib/mysql/index.cjs"
}
}

View File

@@ -30,4 +30,12 @@ module.exports = [
},
plugins: [commonjs()],
},
{
input: join(__dirname, 'src', 'json-file', 'index.js'),
output: {
banner: banner['banner.output'].join(''),
file: join(__dirname, 'lib', 'json-file', 'index.cjs'),
},
plugins: [commonjs()],
},
]

View File

@@ -0,0 +1,48 @@
const path = require('path')
const StormDB = require('stormdb')
const engine = new StormDB.localFileEngine(
path.join(process.cwd(), './db.stormdb')
)
class JsonFileAdapter {
db
listHistory = []
constructor() {
this.init().then()
}
init() {
return new Promise((resolve) => {
this.db = new StormDB(engine)
this.db.default({ history: [] })
resolve(this.db)
})
}
getPrevByNumber = async (from) => {
const response = await this.db.get('history')
const { history } = response.state
if (!history.length) {
return null
}
const result = history.filter((res) => res.from === from).pop()
return {
...result,
}
}
save = async (ctx) => {
await this.db
.get('history')
.push({ ...ctx })
.save()
console.log('Guardado en DB...', ctx)
this.listHistory.push(ctx)
}
}
module.exports = JsonFileAdapter

View File

@@ -1,28 +1,22 @@
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) => {
await this.db.connect(async (error) => {
if (!error) {
console.log(`Solicitud de conexión a base de datos exitosa`)
await this.checkTableExists()
}
if (error) {
@@ -71,6 +65,42 @@ class MyslAdapter {
})
this.listHistory.push(ctx)
}
createTable = () =>
new Promise((resolve) => {
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
)`
this.db.query(sql, (err) => {
if (err) throw err
console.log(`Tabla ${tableName} creada correctamente `)
resolve(true)
})
})
checkTableExists = () =>
new Promise((resolve) => {
const sql = "SHOW TABLES LIKE 'history'"
this.db.query(sql, (err, rows) => {
if (err) throw err
if (!rows.length) {
this.createTable()
}
resolve(!!rows.length)
})
})
}
module.exports = MyslAdapter

View File

@@ -1,13 +0,0 @@
# @bot-whatsapp/provider
```js
// bootstrap.js Como iniciar el provider
const { inout, provider, database } = require('@bot-whatsapp')
provider.start()
provider.close()
```
- [ ] whatsapp-web.js _verificar update_
- [ ] Meta _verificar tokens_
- [ ] Twilio _verificar tokens_

View File

@@ -1,19 +1,116 @@
const twilio = require('twilio')
const { ProviderClass } = require('@bot-whatsapp/bot')
const TwilioVendor = new twilio(accountSid, authToken)
const TwilioWebHookServer = require('./server')
const { parseNumber } = require('./utils')
/**
* ⚙TwilioProvider: Es un provedor que te ofrece enviar
* mensaje a Whatsapp via API
* info: https://www.twilio.com/es-mx/messaging/whatsapp
* video: https://youtu.be/KoOmsHylxUw
*
* Necesitas las siguientes tokens y valores
* { accountSid, authToken, vendorNumber }
*/
class TwilioProvider extends ProviderClass {
constructor() {
super(TwilioVendor)
twilioHook
vendor
vendorNumber
constructor({ accountSid, authToken, vendorNumber }, _port = 3000) {
super()
this.vendor = new twilio(accountSid, authToken)
this.twilioHook = new TwilioWebHookServer(_port)
this.vendorNumber = parseNumber(vendorNumber)
this.twilioHook.start()
const listEvents = this.busEvents()
for (const { event, func } of listEvents) {
this.twilioHook.on(event, func)
}
}
sendMessage = (message) =>
this.vendor.messages.create({
/**
* Mapeamos los eventos nativos de whatsapp-web.js a los que la clase Provider espera
* para tener un standar de eventos
* @returns
*/
busEvents = () => [
{
event: 'auth_failure',
func: (payload) => this.emit('error', payload),
},
{
event: 'ready',
func: () => this.emit('ready', true),
},
{
event: 'message',
func: (payload) => {
this.emit('message', payload)
},
},
]
/**
* Enviar un archivo multimedia
* https://www.twilio.com/es-mx/docs/whatsapp/tutorial/send-and-receive-media-messages-whatsapp-nodejs
* @private
* @param {*} number
* @param {*} mediaInput
* @returns
*/
sendMedia = async (number, message, mediaInput = null) => {
if (!mediaInput) throw new Error(`MEDIA_INPUT_NULL_: ${mediaInput}`)
number = parseNumber(number)
return this.vendor.messages.create({
mediaUrl: [`${mediaInput}`],
body: message,
to: '+12345678901', // Text this number
from: '+12345678901', // From a valid Twilio number
from: `whatsapp:+${this.vendorNumber}`,
to: `whatsapp:+${number}`,
})
}
/**
* Enviar botones
* https://www.twilio.com/es-mx/docs/whatsapp/buttons
* @private
* @param {*} number
* @param {*} message
* @param {*} buttons []
* @returns
*/
sendButtons = async (number, message, buttons = []) => {
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(``)
}
/**
*
* @param {*} userId
* @param {*} message
* @param {*} param2
* @returns
*/
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)
return this.vendor.messages.create({
body: message,
from: `whatsapp:+${this.vendorNumber}`,
to: `whatsapp:+${number}`,
})
}
}
module.exports = TwilioProvider

View File

@@ -0,0 +1,64 @@
const { EventEmitter } = require('node:events')
const polka = require('polka')
const { urlencoded } = require('body-parser')
const { parseNumber } = require('./utils')
/**
* Encargado de levantar un servidor HTTP con una hook url
* [POST] /twilio-hook
*/
class TwilioWebHookServer extends EventEmitter {
twilioServer
twilioPort
constructor(_twilioPort) {
super()
this.twilioServer = this.buildHTTPServer()
this.twilioPort = _twilioPort
}
/**
* Mensaje entrante
* emit: 'message'
* @param {*} req
* @param {*} res
*/
incomingMsg = (req, res) => {
const { body } = req
this.emit('message', {
from: parseNumber(body.From),
to: parseNumber(body.To),
body: body.Body,
})
const json = JSON.stringify({ body })
res.end(json)
}
/**
* Contruir HTTP Server
* @returns
*/
buildHTTPServer = () => {
return polka()
.use(urlencoded({ extended: true }))
.post('/twilio-hook', this.incomingMsg)
}
/**
* Puerto del HTTP
* @param {*} port default 3000
*/
start = () => {
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]: Más información en la documentacion`)
console.log(``)
})
this.emit('ready')
}
}
module.exports = TwilioWebHookServer

View File

@@ -0,0 +1,5 @@
const parseNumber = (number) => {
return `${number}`.replace('whatsapp:', '').replace('+', '')
}
module.exports = { parseNumber }

View File

@@ -8,14 +8,19 @@ const {
const { ProviderClass } = require('@bot-whatsapp/bot')
const { Console } = require('console')
const { createWriteStream, existsSync } = require('fs')
const { cleanNumber, generateImage, isValidNumber } = require('./utils')
const {
cleanNumber,
generateImage,
isValidNumber,
downloadMedia,
} = require('./utils')
const logger = new Console({
stdout: createWriteStream('./log'),
})
/**
* WebWhatsappProvider: Es una clase tipo adaptor
* ⚙️ WebWhatsappProvider: Es una clase tipo adaptor
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
* https://github.com/pedroslopez/whatsapp-web.js
*/
@@ -32,7 +37,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 +77,6 @@ class WebWhatsappProvider extends ProviderClass {
event: 'ready',
func: () => this.emit('ready', true),
},
{
event: 'authenticated',
func: () => this.emit('ready', true),
},
{
event: 'message',
func: (payload) => {
@@ -101,9 +102,9 @@ class WebWhatsappProvider extends ProviderClass {
* @returns
*/
sendMedia = async (number, mediaInput = null) => {
if (!existsSync(mediaInput))
throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
const media = MessageMedia.fromFilePath(mediaInput)
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
const fileDownloaded = await downloadMedia(mediaInput)
const media = MessageMedia.fromFilePath(fileDownloaded)
return this.vendor.sendMessage(number, media, {
sendAudioAsVoice: true,
})
@@ -168,9 +169,9 @@ class WebWhatsappProvider extends ProviderClass {
*/
sendMessage = async (userId, message, { options }) => {
const number = cleanNumber(userId)
if (options?.media) return this.sendMedia(number, options.media)
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)
}
}

View File

@@ -1,5 +1,8 @@
const { createWriteStream } = require('fs')
const qr = require('qr-image')
const { tmpdir } = require('os')
const http = require('http')
const https = require('https')
const cleanNumber = (number, full = false) => {
number = number.replace('@c.us', '')
@@ -18,4 +21,33 @@ const isValidNumber = (rawNumber) => {
return !exist
}
module.exports = { cleanNumber, generateImage, isValidNumber }
/**
* Incompleta
* Descargar archivo multimedia para enviar
* @param {*} url
* @returns
*/
const downloadMedia = (url) => {
return new Promise((resolve, reject) => {
const ext = url.split('.').pop()
const checkProtocol = url.includes('https:')
const handleHttp = checkProtocol ? https : http
const name = `tmp-${Date.now()}.${ext}`
const fullPath = `${tmpdir()}/${name}`
const file = createWriteStream(fullPath)
handleHttp.get(url, function (response) {
response.pipe(file)
file.on('finish', function () {
file.close()
resolve(fullPath)
})
file.on('error', function () {
console.log('errro')
file.close()
reject(null)
})
})
})
}
module.exports = { cleanNumber, generateImage, isValidNumber, downloadMedia }

View File

@@ -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),

33
scripts/release.js Normal file
View File

@@ -0,0 +1,33 @@
const { writeFile, readFileSync } = require('fs')
const { join } = require('path')
const PATH_PACKAGES = join(__dirname, '..', `packages`)
const [PKG_ARG, PKG_ARG_VERSION] = process.argv.slice(2) || [null]
/**
* Actualizar ramdon version de package
* @param {*} packageName
*/
const updateVersion = (packageName = null, number = null) => {
if (!packageName) throw new Error(`PATH_ERROR_PACKAGE: ${packageName}`)
const pkgJson = join(PATH_PACKAGES, packageName, 'package.json')
const rawFile = readFileSync(pkgJson, 'utf-8')
if (!rawFile) throw new Error(`ERROR_FILE_READ`)
let pkgJsonObject = JSON.parse(rawFile)
const build = !number ? Date.now() : number
let [versionNumber] = pkgJsonObject.version.split('-')
pkgJsonObject.version = !number ? `${versionNumber}-${build}` : `${number}`
pkgJsonObject = JSON.stringify(pkgJsonObject)
writeFile(pkgJson, pkgJsonObject, (err) => {
if (err) throw err
})
}
/**
* Recibe los argumentos entrantes
*/
if (PKG_ARG) {
const pkgName = PKG_ARG ? PKG_ARG.split('=').at(1) : null
const pkgNumber = PKG_ARG_VERSION ? PKG_ARG_VERSION.split('=').at(1) : null
updateVersion(pkgName, pkgNumber)
}

144
yarn.lock
View File

@@ -82,15 +82,15 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/client-cognito-identity@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/client-cognito-identity@npm:3.222.0"
"@aws-sdk/client-cognito-identity@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/client-cognito-identity@npm:3.223.0"
dependencies:
"@aws-crypto/sha256-browser": 2.0.0
"@aws-crypto/sha256-js": 2.0.0
"@aws-sdk/client-sts": 3.222.0
"@aws-sdk/client-sts": 3.223.0
"@aws-sdk/config-resolver": 3.222.0
"@aws-sdk/credential-provider-node": 3.222.0
"@aws-sdk/credential-provider-node": 3.223.0
"@aws-sdk/fetch-http-handler": 3.222.0
"@aws-sdk/hash-node": 3.222.0
"@aws-sdk/invalid-dependency": 3.222.0
@@ -116,19 +116,18 @@ __metadata:
"@aws-sdk/util-defaults-mode-browser": 3.222.0
"@aws-sdk/util-defaults-mode-node": 3.222.0
"@aws-sdk/util-endpoints": 3.222.0
"@aws-sdk/util-retry": 3.222.0
"@aws-sdk/util-user-agent-browser": 3.222.0
"@aws-sdk/util-user-agent-node": 3.222.0
"@aws-sdk/util-utf8-browser": 3.188.0
"@aws-sdk/util-utf8-node": 3.208.0
tslib: ^2.3.1
checksum: b733d9bad0232a17967da9b27311cb2adf41acaefc584173e6d74b3b966ed3908b9e9fa65b3a0f3e12709dc305e64b1a5351ea43ac666650a375cb10143368e3
checksum: ada894c3fbe943044617d719dc947af51546dbfea72e5b63f23c6230677c39dc0355248ed1ba119a29f2d4b7bc64e28400880b580a263bcd45d05fdf45007ad7
languageName: node
linkType: hard
"@aws-sdk/client-sso-oidc@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/client-sso-oidc@npm:3.222.0"
"@aws-sdk/client-sso-oidc@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/client-sso-oidc@npm:3.223.0"
dependencies:
"@aws-crypto/sha256-browser": 2.0.0
"@aws-crypto/sha256-js": 2.0.0
@@ -157,19 +156,18 @@ __metadata:
"@aws-sdk/util-defaults-mode-browser": 3.222.0
"@aws-sdk/util-defaults-mode-node": 3.222.0
"@aws-sdk/util-endpoints": 3.222.0
"@aws-sdk/util-retry": 3.222.0
"@aws-sdk/util-user-agent-browser": 3.222.0
"@aws-sdk/util-user-agent-node": 3.222.0
"@aws-sdk/util-utf8-browser": 3.188.0
"@aws-sdk/util-utf8-node": 3.208.0
tslib: ^2.3.1
checksum: 40674d89438b689480bdfa10bfb044d90341d87096ae6b0803e6ecc1695d48b1f7a8c513109e92001c380e2b2f5b18aa3e8af1c8ecd3d2f04f63f160cb039611
checksum: ab5b6142d897ec48a3bb246577c23d1b6e26ee228c7ce264f826d10f88caa83e03f0dac9d88e361c70b778ceef45f0ebd9712cd03ca5b60ab240a3d4382ecb7c
languageName: node
linkType: hard
"@aws-sdk/client-sso@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/client-sso@npm:3.222.0"
"@aws-sdk/client-sso@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/client-sso@npm:3.223.0"
dependencies:
"@aws-crypto/sha256-browser": 2.0.0
"@aws-crypto/sha256-js": 2.0.0
@@ -198,24 +196,23 @@ __metadata:
"@aws-sdk/util-defaults-mode-browser": 3.222.0
"@aws-sdk/util-defaults-mode-node": 3.222.0
"@aws-sdk/util-endpoints": 3.222.0
"@aws-sdk/util-retry": 3.222.0
"@aws-sdk/util-user-agent-browser": 3.222.0
"@aws-sdk/util-user-agent-node": 3.222.0
"@aws-sdk/util-utf8-browser": 3.188.0
"@aws-sdk/util-utf8-node": 3.208.0
tslib: ^2.3.1
checksum: bc0cd1125bc5aa94b3fdec15167ce9539acf4a187da060d51fa8ad7c30d0bf6cfee9e3a0175d65e204aba92efee4087c99d1190e1b43927c01cd7a8b1bbbb93e
checksum: 856e3745182906d274dc894baa7d853966b0074f89ea892f29132e1cefdf49f267f1d0fffaa2de3de352d19ff3963d59290602057bd4510731e0156199bed664
languageName: node
linkType: hard
"@aws-sdk/client-sts@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/client-sts@npm:3.222.0"
"@aws-sdk/client-sts@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/client-sts@npm:3.223.0"
dependencies:
"@aws-crypto/sha256-browser": 2.0.0
"@aws-crypto/sha256-js": 2.0.0
"@aws-sdk/config-resolver": 3.222.0
"@aws-sdk/credential-provider-node": 3.222.0
"@aws-sdk/credential-provider-node": 3.223.0
"@aws-sdk/fetch-http-handler": 3.222.0
"@aws-sdk/hash-node": 3.222.0
"@aws-sdk/invalid-dependency": 3.222.0
@@ -242,14 +239,13 @@ __metadata:
"@aws-sdk/util-defaults-mode-browser": 3.222.0
"@aws-sdk/util-defaults-mode-node": 3.222.0
"@aws-sdk/util-endpoints": 3.222.0
"@aws-sdk/util-retry": 3.222.0
"@aws-sdk/util-user-agent-browser": 3.222.0
"@aws-sdk/util-user-agent-node": 3.222.0
"@aws-sdk/util-utf8-browser": 3.188.0
"@aws-sdk/util-utf8-node": 3.208.0
fast-xml-parser: 4.0.11
tslib: ^2.3.1
checksum: 79f18e5b44541673213715e3465a8b000716c03120ea087e6920abba3542683dbd4b881ecb091ef90df34947eec00c82daf70089ea0e5e92cffbb4e57e2d76d7
checksum: 6976345f839b0028a0e83f6d11e3323da68cef103ae5381299c6d75df25a1ef336b83023c79896242fbc4b7d2a27f3deebb1b1922e815e6cc7780f3eee302210
languageName: node
linkType: hard
@@ -266,15 +262,15 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/credential-provider-cognito-identity@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.222.0"
"@aws-sdk/credential-provider-cognito-identity@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.223.0"
dependencies:
"@aws-sdk/client-cognito-identity": 3.222.0
"@aws-sdk/client-cognito-identity": 3.223.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: e6a61cf601825907931ed0cc42050b895b150468feb95c1052e053ce00d33e8d225663ca337da1c5825eee7e24438311ba0d28b2a6021868d3e6796aa81fdeeb
checksum: e0f03110b120699ef9c458edd5b1a248f5e3f360931b2e8be7ebb7fc33da51ac1c3fdf96bb05a755a2d303c00c7effee7a582706da2333b4ee43c0040ff551a5
languageName: node
linkType: hard
@@ -302,37 +298,37 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/credential-provider-ini@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/credential-provider-ini@npm:3.222.0"
"@aws-sdk/credential-provider-ini@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/credential-provider-ini@npm:3.223.0"
dependencies:
"@aws-sdk/credential-provider-env": 3.222.0
"@aws-sdk/credential-provider-imds": 3.222.0
"@aws-sdk/credential-provider-sso": 3.222.0
"@aws-sdk/credential-provider-sso": 3.223.0
"@aws-sdk/credential-provider-web-identity": 3.222.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/shared-ini-file-loader": 3.222.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: eac19a9b52066f76cf23bee102369df7d50097dfee3be14b12c2e178c16868acd1a79b13c00d3e3ac40d2fbc14b4e2b06119d0c51c5d875c6be3606c33514d62
checksum: f407fe591999f1da1d5580b182af261ceeb4455da9a53d18ae871c9cf244e6e72fa10ef28036419790e2b5787d64c5de5b4daf4c7f69acb866894410baa880d0
languageName: node
linkType: hard
"@aws-sdk/credential-provider-node@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/credential-provider-node@npm:3.222.0"
"@aws-sdk/credential-provider-node@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/credential-provider-node@npm:3.223.0"
dependencies:
"@aws-sdk/credential-provider-env": 3.222.0
"@aws-sdk/credential-provider-imds": 3.222.0
"@aws-sdk/credential-provider-ini": 3.222.0
"@aws-sdk/credential-provider-ini": 3.223.0
"@aws-sdk/credential-provider-process": 3.222.0
"@aws-sdk/credential-provider-sso": 3.222.0
"@aws-sdk/credential-provider-sso": 3.223.0
"@aws-sdk/credential-provider-web-identity": 3.222.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/shared-ini-file-loader": 3.222.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: f17ce6c9b45d48d9bebd63766b5d85e45f6a1d50b02bea4784d0055269a0f5c05e5ba343c6b138cd29086b94c6bb4511568e9fb59f340f3988526b2d7950cb4c
checksum: 6ce5f88f75a6e879344ea76fa2b390c779d74f1b3657fa15367b15797b09d9713ef0d2f14c95421254a6bc0b8bde1acd2634978a6549e02a74c33160ae6130fd
languageName: node
linkType: hard
@@ -348,17 +344,17 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/credential-provider-sso@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/credential-provider-sso@npm:3.222.0"
"@aws-sdk/credential-provider-sso@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/credential-provider-sso@npm:3.223.0"
dependencies:
"@aws-sdk/client-sso": 3.222.0
"@aws-sdk/client-sso": 3.223.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/shared-ini-file-loader": 3.222.0
"@aws-sdk/token-providers": 3.222.0
"@aws-sdk/token-providers": 3.223.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: 8e0a39a722fd6548b9758ab4c711eac9128a64bae1fa9bfce5f0b92c2df34883fdcd544c9a48f501d3a7b695e6d0b51a9b5e1be1b7eac626a1818860cfc86072
checksum: 4593a94dc86ef7218517061cf875285c2c6087f1d4a1199442055e6165701f11f9921612a04ab3c1b3f29b3132d46a8ce8cd26070fad132509e20eca1b89f217
languageName: node
linkType: hard
@@ -374,25 +370,25 @@ __metadata:
linkType: hard
"@aws-sdk/credential-providers@npm:^3.186.0":
version: 3.222.0
resolution: "@aws-sdk/credential-providers@npm:3.222.0"
version: 3.223.0
resolution: "@aws-sdk/credential-providers@npm:3.223.0"
dependencies:
"@aws-sdk/client-cognito-identity": 3.222.0
"@aws-sdk/client-sso": 3.222.0
"@aws-sdk/client-sts": 3.222.0
"@aws-sdk/credential-provider-cognito-identity": 3.222.0
"@aws-sdk/client-cognito-identity": 3.223.0
"@aws-sdk/client-sso": 3.223.0
"@aws-sdk/client-sts": 3.223.0
"@aws-sdk/credential-provider-cognito-identity": 3.223.0
"@aws-sdk/credential-provider-env": 3.222.0
"@aws-sdk/credential-provider-imds": 3.222.0
"@aws-sdk/credential-provider-ini": 3.222.0
"@aws-sdk/credential-provider-node": 3.222.0
"@aws-sdk/credential-provider-ini": 3.223.0
"@aws-sdk/credential-provider-node": 3.223.0
"@aws-sdk/credential-provider-process": 3.222.0
"@aws-sdk/credential-provider-sso": 3.222.0
"@aws-sdk/credential-provider-sso": 3.223.0
"@aws-sdk/credential-provider-web-identity": 3.222.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/shared-ini-file-loader": 3.222.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: a6c159abbc210d62ed7d1153278b423595493583f53ec2a9143b402ee149cc1ae39be41615c76c3b658e1e9f70e89019a594c8e7a6a320cf7ea37443714a79ac
checksum: 289d043f41460751e90c3adc323f3a56e517f67c0a7f8889249e0969b3302f19d093eef4a10d3528bdf34f1043f95fa41555ed5c91af4d2ca636cded1775c81c
languageName: node
linkType: hard
@@ -678,16 +674,16 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/token-providers@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/token-providers@npm:3.222.0"
"@aws-sdk/token-providers@npm:3.223.0":
version: 3.223.0
resolution: "@aws-sdk/token-providers@npm:3.223.0"
dependencies:
"@aws-sdk/client-sso-oidc": 3.222.0
"@aws-sdk/client-sso-oidc": 3.223.0
"@aws-sdk/property-provider": 3.222.0
"@aws-sdk/shared-ini-file-loader": 3.222.0
"@aws-sdk/types": 3.222.0
tslib: ^2.3.1
checksum: e0d2d9af50570ca1e9ae4cfe32889a9146a0e49ce3004dfc4d5305ba0f64b7561da95d09ccaf18927638417d3bd1eb9772cb58256aef242beab03a56e4e68883
checksum: 08d724bc685b90761159b449413c9dddb581cc61cd982ee9a189e8682d1a703acc70663beec2ae31d1ebf6fe9a86480b63fb65da531e35b2e8772a2c3906969f
languageName: node
linkType: hard
@@ -819,16 +815,6 @@ __metadata:
languageName: node
linkType: hard
"@aws-sdk/util-retry@npm:3.222.0":
version: 3.222.0
resolution: "@aws-sdk/util-retry@npm:3.222.0"
dependencies:
"@aws-sdk/service-error-classification": 3.222.0
tslib: ^2.3.1
checksum: d4b38a23a310d44d211db2cfb2ae53ef41cf805308d08e56d9ca786fc69fd6b244f331d40ea35023bbc53625c7b2c1f4fab9fabd32d0a10396d4359ac50eff09
languageName: node
linkType: hard
"@aws-sdk/util-uri-escape@npm:3.201.0":
version: 3.201.0
resolution: "@aws-sdk/util-uri-escape@npm:3.201.0"
@@ -950,6 +936,7 @@ __metadata:
dotenv: ^16.0.3
mongodb: ^4.11.0
mysql2: ^2.3.3
stormdb: ^0.6.0
languageName: unknown
linkType: soft
@@ -3136,6 +3123,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"
@@ -7897,6 +7894,13 @@ __metadata:
languageName: node
linkType: hard
"stormdb@npm:^0.6.0":
version: 0.6.0
resolution: "stormdb@npm:0.6.0"
checksum: 5974329c1c5af9f0829a5551bef8476dcf6df921f4b9e135acb96863ed0d20ece9bec32d9fd42b84b5d76de30c7d20d3095d14cc75c8f0777f4799b422bd4053
languageName: node
linkType: hard
"streamsearch@npm:^1.1.0":
version: 1.1.0
resolution: "streamsearch@npm:1.1.0"