chore(release): 0.1.21

chore(release): 0.1.21
This commit is contained in:
Leifer Mendez
2023-02-12 22:16:32 +01:00
committed by GitHub
26 changed files with 180 additions and 149 deletions

View File

@@ -1,52 +0,0 @@
name: Rev Major Providers
on:
schedule:
- cron: '0 9 * * *'
jobs:
check-npm:
name: Install Dependencies
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'yarn'
registry-url: https://registry.npmjs.org/
- run: corepack enable
- name: Install NPM Dependencies
run: yarn install --immutable --network-timeout 300000
- name: Check Baileys
run: yarn node ./scripts/checker.js --name=baileys --stable=true
- name: Check Venom
run: yarn node ./scripts/checker.js --name=venom --stable=true
- name: Check web-whatsapp
run: yarn node ./scripts/checker.js --name=web-whatsapp --stable=true
- name: Check Meta
run: yarn node ./scripts/checker.js --name=meta --stable=true
- name: Check Twilio
run: yarn node ./scripts/checker.js --name=twilio --stable=true
- name: Add and commit changes to gh-pages branch
run: |
git config --local user.email 'action@github.com'
git config --local user.name 'GitHub Action'
git add .
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'ci(providers): check provider versions'
create_branch: true
branch: feature/providers-major

View File

@@ -12,6 +12,7 @@ jobs:
runs-on: ubuntu-latest
needs:
- test-unit
- test-e2e
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -56,20 +57,15 @@ jobs:
- name: Unit Tests
run: yarn test
############ UNIT TEST ############
check-providers:
name: Check Providers Versions
test-e2e:
name: e2e Tests
runs-on: ubuntu-latest
outputs:
commit: ${{ steps.vars.outputs.commit }}
needs:
- test-unit
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{github.event.after}}
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@v3
@@ -83,28 +79,5 @@ jobs:
- name: Install NPM Dependencies
run: yarn install --immutable --network-timeout 300000
- name: Check Baileys
run: yarn node ./scripts/checker.js --name=baileys --stable=true
- name: Check Venom
run: yarn node ./scripts/checker.js --name=venom --stable=true
- name: Check web-whatsapp
run: yarn node ./scripts/checker.js --name=web-whatsapp --stable=true
- name: Check Meta
run: yarn node ./scripts/checker.js --name=meta --stable=true
- name: Check Twilio
run: yarn node ./scripts/checker.js --name=twilio --stable=true
- name: Set output
id: vars
run: echo "commit=$(git log --format=%B -n 1 ${{github.event.after}})" >> $GITHUB_OUTPUT
- name: Commit & Push changes
uses: actions-js/push@master
with:
branch: feature/providers-major
github_token: ${{ secrets.GITHUB_TOKEN }}
force: true
- name: e2e Tests
run: yarn test.e2e

1
.gitignore vendored
View File

@@ -36,6 +36,7 @@ tmp/
.fleet/
example-app*/
base-*/
test-*.json
!starters/apps/base-*/
qr.svg
package-lock.json

View File

@@ -2,6 +2,23 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.1.21](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.20...v0.1.21) (2023-02-12)
### Features
* **provider:** :bug: add_location ([a46a9ef](https://github.com/leifermendez/bot-whatsapp/commit/a46a9efd8dbd921c773395d331154dc9a8aae783))
* **provider:** :rocket: feat Instance provider ([2278149](https://github.com/leifermendez/bot-whatsapp/commit/227814929561cedc11a1f69c8029515a7f47c9ff))
* **provider:** :rocket: provider raw ([2d44a00](https://github.com/leifermendez/bot-whatsapp/commit/2d44a002ff226fb0eb7362ad49936f1e00b84242))
* **provider:** :zap: add location provider ([c7de860](https://github.com/leifermendez/bot-whatsapp/commit/c7de860803fb362f5afe06cc38ad71b2c316d524))
* **provider:** :zap: add location provider ([c0ece6f](https://github.com/leifermendez/bot-whatsapp/commit/c0ece6feb2b0325476880a604c32de341eb60544))
* **provider:** :zap: support location <20> ([a147677](https://github.com/leifermendez/bot-whatsapp/commit/a147677a26b36bba429c3dd3c2c81a44a7a4d2b6))
### Bug Fixes
* arreglando dir y varios mensajes en dialog flow essential ([01c7db8](https://github.com/leifermendez/bot-whatsapp/commit/01c7db8fe7dda2482eb0aa1fd7b3469b6ae8eae1))
### [0.1.20](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.19...v0.1.20) (2023-02-05)

View File

@@ -16,14 +16,25 @@ class MOCK_FLOW {
findIndexByRef = () => 0
}
const cleaName = (name) => {
name = name.toLowerCase()
name = name.replaceAll(' ', '-')
name = name.replaceAll(':', '-')
name = name.replaceAll('"', '-')
return name
}
/**
* Preparar env para el test
* @param {*} context
*/
const setup = async (context) => {
const name = cleaName(`${context.__suite__}-${context.__test__}`)
const filename = `test-${name}.json`
context.provider = new PROVIDER_DB()
context.database = new MOCK_DB()
context.database = new MOCK_DB({ filename })
context.flow = new MOCK_FLOW()
await delay(10)
}
const clear = async (context) => {

View File

@@ -22,8 +22,7 @@ suiteCase(`Responder a "hola"`, async ({ database, provider }) => {
body: 'hola',
})
await delay(0)
await delay(10)
assert.is('Buenas!', database.listHistory[0].answer)
assert.is('Como vamos!', database.listHistory[1].answer)
assert.is(undefined, database.listHistory[2])
@@ -43,7 +42,7 @@ suiteCase(`NO reponder a "pepe"`, async ({ database, provider }) => {
body: 'pepe',
})
await delay(0)
await delay(100)
assert.is(undefined, database.listHistory[0])
assert.is(undefined, database.listHistory[1])

View File

@@ -0,0 +1,31 @@
const { suite } = require('uvu')
const assert = require('uvu/assert')
const { addKeyword, createBot, createFlow } = require('../packages/bot/index')
const { setup, clear, delay } = require('../__mocks__/env')
const suiteCase = suite('Flujo: Provider envia un location')
suiteCase.before.each(setup)
suiteCase.after.each(clear)
suiteCase(`Responder a "CURRENT_LOCATION"`, async ({ database, provider }) => {
const flow = addKeyword('#CURRENT_LOCATION#').addAnswer('Gracias por tu location')
createBot({
database,
provider,
flow: createFlow([flow]),
})
await provider.delaySendMessage(0, 'message', {
from: '000',
body: '#CURRENT_LOCATION#',
})
await delay(200)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Gracias por tu location', getHistory[0])
assert.is(undefined, getHistory[1])
})
suiteCase.run()

View File

@@ -22,7 +22,7 @@ suiteCase(`Responder a "ole" en minuscula`, async ({ database, provider }) => {
body: 'ole',
})
await delay(0)
await delay(100)
assert.is('Bienvenido a la OLA', database.listHistory[0].answer)
assert.is(undefined, database.listHistory[1])
@@ -42,7 +42,7 @@ suiteCase(`NO Responder a "ole" en minuscula`, async ({ database, provider }) =>
body: 'OLE',
})
await delay(0)
await delay(100)
assert.is(undefined, database.listHistory[0])
assert.is(undefined, database.listHistory[1])

View File

@@ -51,22 +51,22 @@ suiteCase(`Debe continuar el flujo del hijo`, async ({ database, provider }) =>
body: 'hola',
})
await provider.delaySendMessage(10, 'message', {
await provider.delaySendMessage(30, 'message', {
from: '000',
body: 'test@test.com',
})
await provider.delaySendMessage(15, 'message', {
await provider.delaySendMessage(60, 'message', {
from: '000',
body: 'paypal',
})
await provider.delaySendMessage(20, 'message', {
await provider.delaySendMessage(90, 'message', {
from: '000',
body: 'continue!',
})
await delay(500)
await delay(800)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('¿Como estas todo bien?', getHistory[0])

View File

@@ -26,7 +26,7 @@ suiteCase(`Responder a una expresion regular`, async ({ database, provider }) =>
body: '374245455400126',
})
await delay(10)
await delay(100)
assert.is('Gracias por proporcionar un numero de tarjeta valido', database.listHistory[0].answer)
assert.is('Fin!', database.listHistory[1].answer)
@@ -50,7 +50,7 @@ suiteCase(`NO Responder a una expresion regular`, async ({ database, provider })
body: 'hola',
})
await delay(10)
await delay(100)
assert.is(undefined, database.listHistory[0])
assert.is(undefined, database.listHistory[1])

View File

@@ -29,7 +29,7 @@ suiteCase(`Responder a "pregunta"`, async ({ database, provider }) => {
body: '90',
})
await delay(20)
await delay(100)
assert.is(['Hola como estas?', '¿Cual es tu edad?'].join('\n'), database.listHistory[0].answer)
assert.is('90', database.listHistory[1].answer)

View File

@@ -50,7 +50,7 @@ suiteCase(`Responder con mensajes asyncronos`, async ({ database, provider }) =>
body: 'hola',
})
await delay(1200)
await delay(1500)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is(MOCK_VALUES[0], getHistory[0])
@@ -98,7 +98,7 @@ suiteCase(`Responder con un "string"`, async ({ database, provider }) => {
body: 'hola',
})
await delay(10)
await delay(100)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Como vas?', getHistory[0])
assert.is('Todo bien!', getHistory[1])
@@ -124,7 +124,7 @@ suiteCase(`Responder con un "array"`, async ({ database, provider }) => {
body: 'hola',
})
await delay(10)
await delay(100)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Como vas?', getHistory[0])
assert.is('Todo bien!', getHistory[1])
@@ -151,7 +151,7 @@ suiteCase(`Responder con un "object"`, async ({ database, provider }) => {
body: 'hola',
})
await delay(10)
await delay(100)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Como vas?', getHistory[0])
assert.is('Todo bien!', getHistory[1])

View File

@@ -46,7 +46,7 @@ suiteCase(`Detener el flujo`, async ({ database, provider }) => {
body: 'hola',
})
await delay(500)
await delay(900)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is(MOCK_VALUES[0], getHistory[0])
@@ -81,7 +81,7 @@ suiteCase(`Detener el flujo flowDynamic`, async ({ database, provider }) => {
body: 'hola',
})
await delay(10)
await delay(100)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Buenas!', getHistory[0])
assert.is('Continuamos...', getHistory[1])
@@ -148,7 +148,7 @@ suiteCase(`flowDynamic con capture`, async ({ database, provider }) => {
body: '18',
})
await delay(500)
await delay(900)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is(MOCK_VALUES[0], getHistory[0])
assert.is('this is not email value', getHistory[1])

View File

@@ -76,7 +76,7 @@ suiteCase(`Debe retornar un mensaje resumen`, async ({ database, provider }) =>
body: '100',
})
await delay(500)
await delay(1000)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is(MOCK_VALUES[0], getHistory[0])
assert.is('¿Cual es tu nombre?', getHistory[1])

View File

@@ -1,6 +1,6 @@
{
"name": "@bot-whatsapp/root",
"version": "0.1.20",
"version": "0.1.21",
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
"main": "app.js",
"private": true,
@@ -25,7 +25,7 @@
"copy.lib": "node ./scripts/move.js",
"test.unit": "node ./node_modules/uvu/bin.js packages test",
"test.e2e": "node ./node_modules/uvu/bin.js __test__",
"test.coverage": "node ./node_modules/c8/bin/c8.js npm run test.unit && npm run test.e2e",
"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",

View File

@@ -84,7 +84,7 @@ class CoreClass {
from,
prevRef: prevMsg.refSerialize,
})
this.databaseClass.save(ctxByNumber)
await this.databaseClass.save(ctxByNumber)
}
// 📄 Crar CTX de mensaje (uso private)

View File

@@ -104,11 +104,19 @@ class DialogFlowContext extends CoreClass {
return
}
const ctxFromDX = {
/* const ctxFromDX = {
answer: queryResult?.fulfillmentText,
}
} */
this.sendFlowSimple([ctxFromDX], from)
const messagesFromCX = queryResult['fulfillmentMessages']
.map((a) => {
if (a.message === 'text') {
return { answer: a.text.text[0] }
}
})
.filter((e) => e)
this.sendFlowSimple(messagesFromCX, from)
}
}

View File

@@ -1,63 +1,79 @@
const { join } = require('path')
const { existsSync, writeFileSync, readFileSync } = require('fs')
const { existsSync } = require('fs')
const { writeFile, readFile } = require('fs').promises
class JsonFileAdapter {
db
pathFile
listHistory = []
options = { filename: 'db.json' }
constructor() {
this.pathFile = join(process.cwd(), 'db.json')
constructor(options = {}) {
this.options = { ...this.options, ...options }
this.pathFile = join(process.cwd(), this.options.filename)
this.init().then()
}
databaseExists() {
return existsSync(this.pathFile)
}
async init() {
const dbExists = await this.databaseExists()
if (!dbExists) {
const data = {
history: [],
}
await this.saveData(data)
/**
* Revisamos si existe o no el json file
* @returns
*/
init = async () => {
if (existsSync(this.pathFile)) {
return Promise.resolve()
}
try {
const parseData = JSON.stringify([], null, 2)
return writeFile(this.pathFile, parseData, 'utf-8')
} catch (e) {
return Promise.reject(e.message)
}
}
readDatabase() {
const db = readFileSync(this.pathFile)
return JSON.parse(db)
validateJson = (raw) => {
try {
return JSON.parse(raw)
} catch (e) {
return {}
}
}
saveData(data) {
writeFileSync(this.pathFile, JSON.stringify(data, null, 2))
/**
* Leer archivo y parsear
* @returns
*/
readFileAndParse = async () => {
const data = await readFile(this.pathFile, 'utf-8')
const parseData = this.validateJson(data)
return parseData
}
/**
* Buscamos el ultimo mensaje por numero
* @param {*} from
* @returns
*/
getPrevByNumber = async (from) => {
const { history } = await this.readDatabase()
const history = await this.readFileAndParse()
if (!history.length) {
return null
return []
}
const result = history.filter((res) => res.from === from).pop()
return {
...result,
}
const result = history
.slice()
.reverse()
.filter((i) => !!i.keyword)
return result.find((a) => a.from === from)
}
/**
* Guardar dato
* @param {*} ctx
*/
save = async (ctx) => {
this.db = await this.readDatabase()
this.db.history.push(ctx)
await this.saveData(this.db)
this.listHistory.push(ctx)
console.log('Guardado en DB...', ctx)
const parseData = JSON.stringify(this.listHistory, null, 2)
await writeFile(this.pathFile, parseData, 'utf-8')
}
}

View File

@@ -118,9 +118,17 @@ class BaileysProvider extends ProviderClass {
let payload = {
...messageCtx,
body: messageCtx?.message?.extendedTextMessage?.text ?? messageCtx?.message?.conversation,
from: messageCtx?.key?.remoteJid,
}
if (messageCtx.message.locationMessage) {
const { degreesLatitude, degreesLongitude } = messageCtx.message.locationMessage
if (typeof degreesLatitude === 'number' && typeof degreesLongitude === 'number') {
payload = { ...payload, body: `#CURRENT_LOCATION#` }
}
}
if (payload.from === 'status@broadcast') return
if (payload?.key?.fromMe) return

View File

@@ -85,11 +85,17 @@ class VenomProvider extends ProviderClass {
if (payload.from === 'status@broadcast') {
return
}
if (!venomisValidNumber(payload.from)) {
return
}
payload.from = venomCleanNumber(payload.from, true)
if (payload.hasOwnProperty('lat') && payload.hasOwnProperty('lng')) {
const lat = payload.lat
const lng = payload.lng
if (lat !== '' && lng !== '') {
payload = { ...payload, body: `#CURRENT_LOCATION#` }
}
}
this.emit('message', payload)
},
},

View File

@@ -90,6 +90,9 @@ class WebWhatsappProvider extends ProviderClass {
return
}
payload.from = wwebCleanNumber(payload.from, true)
if (payload._data.lat && payload._data.lng) {
payload = { ...payload, body: `#CURRENT_LOCATION#` }
}
this.emit('message', payload)
},
},

View File

@@ -11,6 +11,7 @@ const MYSQL_DB_HOST = 'localhost'
const MYSQL_DB_USER = 'usr'
const MYSQL_DB_PASSWORD = 'pass'
const MYSQL_DB_NAME = 'bot'
const MYSQL_DB_PORT = '3306'
/**
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
@@ -88,6 +89,7 @@ const main = async () => {
user: MYSQL_DB_USER,
database: MYSQL_DB_NAME,
password: MYSQL_DB_PASSWORD,
port: MYSQL_DB_PORT,
})
const adapterFlow = createFlow([flowPrincipal])
const adapterProvider = createProvider(BaileysProvider)

View File

@@ -10,6 +10,7 @@ const MYSQL_DB_HOST = 'localhost'
const MYSQL_DB_USER = 'usr'
const MYSQL_DB_PASSWORD = 'pass'
const MYSQL_DB_NAME = 'bot'
const MYSQL_DB_PORT = '3306'
/**
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
@@ -87,6 +88,7 @@ const main = async () => {
user: MYSQL_DB_USER,
database: MYSQL_DB_NAME,
password: MYSQL_DB_PASSWORD,
port: MYSQL_DB_PORT,
})
const adapterFlow = createFlow([flowPrincipal])

View File

@@ -11,6 +11,7 @@ const MYSQL_DB_HOST = 'localhost'
const MYSQL_DB_USER = 'user'
const MYSQL_DB_PASSWORD = 'pass'
const MYSQL_DB_NAME = 'bot'
const MYSQL_DB_PORT = '3306'
/**
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
@@ -88,6 +89,7 @@ const main = async () => {
user: MYSQL_DB_USER,
database: MYSQL_DB_NAME,
password: MYSQL_DB_PASSWORD,
port: MYSQL_DB_PORT,
})
const adapterFlow = createFlow([flowPrincipal])
const adapterProvider = createProvider(TwilioProvider, {

View File

@@ -12,6 +12,7 @@ const MYSQL_DB_HOST = 'localhost'
const MYSQL_DB_USER = 'user'
const MYSQL_DB_PASSWORD = 'pass'
const MYSQL_DB_NAME = 'bot'
const MYSQL_DB_PORT = '3306'
/**
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
@@ -89,6 +90,7 @@ const main = async () => {
user: MYSQL_DB_USER,
database: MYSQL_DB_NAME,
password: MYSQL_DB_PASSWORD,
port: MYSQL_DB_PORT,
})
const adapterFlow = createFlow([flowPrincipal])
const adapterProvider = createProvider(VenomProvider)

View File

@@ -12,6 +12,7 @@ const MYSQL_DB_HOST = 'localhost'
const MYSQL_DB_USER = 'user'
const MYSQL_DB_PASSWORD = 'pass'
const MYSQL_DB_NAME = 'bot'
const MYSQL_DB_PORT = '3306'
/**
* Aqui declaramos los flujos hijos, los flujos se declaran de atras para adelante, es decir que si tienes un flujo de este tipo:
@@ -89,6 +90,7 @@ const main = async () => {
user: MYSQL_DB_USER,
database: MYSQL_DB_NAME,
password: MYSQL_DB_PASSWORD,
port: MYSQL_DB_PORT,
})
const adapterFlow = createFlow([flowPrincipal])
const adapterProvider = createProvider(WebWhatsappProvider)