mirror of
https://github.com/cheveguerra/bot-whatsapp.git
synced 2026-04-17 19:26:23 +00:00
feat(provider): ⚡ add location provider
feat(provider): ⚡ add location provider
This commit is contained in:
@@ -1 +1,2 @@
|
||||
packages/docs/*
|
||||
packages/docs/*
|
||||
packages/portal/*
|
||||
20
.github/workflows/check-provider-major.yml
vendored
20
.github/workflows/check-provider-major.yml
vendored
@@ -25,20 +25,28 @@ jobs:
|
||||
run: yarn install --immutable --network-timeout 300000
|
||||
|
||||
- name: Check Baileys
|
||||
run: yarn node ./scripts/checker.js --name=baileys --stable=false
|
||||
run: yarn node ./scripts/checker.js --name=baileys --stable=true
|
||||
|
||||
- name: Check Venom
|
||||
run: yarn node ./scripts/checker.js --name=venom --stable=false
|
||||
run: yarn node ./scripts/checker.js --name=venom --stable=true
|
||||
|
||||
- name: Check web-whatsapp
|
||||
run: yarn node ./scripts/checker.js --name=web-whatsapp --stable=false
|
||||
run: yarn node ./scripts/checker.js --name=web-whatsapp --stable=true
|
||||
|
||||
- name: Check Meta
|
||||
run: yarn node ./scripts/checker.js --name=meta --stable=false
|
||||
run: yarn node ./scripts/checker.js --name=meta --stable=true
|
||||
|
||||
- name: Check Twilio
|
||||
run: yarn node ./scripts/checker.js --name=twilio --stable=false
|
||||
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 BREAKING CHANGE'
|
||||
commit_message: 'ci(providers): check provider versions'
|
||||
create_branch: true
|
||||
branch: feature/providers-major
|
||||
|
||||
48
.github/workflows/check-providers.yml
vendored
48
.github/workflows/check-providers.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: Rev Providers
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
|
||||
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
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: 'ci(providers): 👍 updated versions stable providers'
|
||||
57
.github/workflows/ci.yml
vendored
57
.github/workflows/ci.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
@@ -32,7 +29,7 @@ jobs:
|
||||
run: yarn install --immutable --network-timeout 300000
|
||||
|
||||
- name: Build Package
|
||||
run: yarn build
|
||||
run: yarn build:full
|
||||
|
||||
- name: Build Eslint rules
|
||||
run: yarn lint:fix
|
||||
@@ -59,3 +56,55 @@ jobs:
|
||||
|
||||
- name: Unit Tests
|
||||
run: yarn test
|
||||
|
||||
############ UNIT TEST ############
|
||||
check-providers:
|
||||
name: Check Providers Versions
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
commit: ${{ steps.vars.outputs.commit }}
|
||||
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
|
||||
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: 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
|
||||
|
||||
3
.github/workflows/codeql.yml
vendored
3
.github/workflows/codeql.yml
vendored
@@ -13,7 +13,7 @@ name: 'CodeQL'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['main', dev, next-release]
|
||||
branches: [release/next]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: ['main']
|
||||
@@ -22,6 +22,7 @@ on:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
if: ${{ !github.event.act }}
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
||||
11
.github/workflows/contributors.yml
vendored
11
.github/workflows/contributors.yml
vendored
@@ -1,13 +1,8 @@
|
||||
name: Revisando Colaboradores
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
types: [closed]
|
||||
schedule:
|
||||
- cron: '0 9 * * *'
|
||||
|
||||
jobs:
|
||||
contrib-readme-job:
|
||||
|
||||
1
.github/workflows/netlify-dev.yml
vendored
1
.github/workflows/netlify-dev.yml
vendored
@@ -13,6 +13,7 @@ on:
|
||||
jobs:
|
||||
############ DOCUMENTATION BUILD ############
|
||||
build-documentation:
|
||||
if: ${{ !github.event.act }}
|
||||
name: Build Package
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
5
.github/workflows/netlify.yml
vendored
5
.github/workflows/netlify.yml
vendored
@@ -3,12 +3,11 @@ name: 📄 (PROD) Desplegando documentacion
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next-release
|
||||
- release/next
|
||||
|
||||
jobs:
|
||||
############ DOCUMENTATION BUILD ############
|
||||
build-documentation:
|
||||
build-documentation-prod:
|
||||
name: Build Package
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
25
.github/workflows/releases-dev.yml
vendored
25
.github/workflows/releases-dev.yml
vendored
@@ -3,16 +3,22 @@ name: 🚀 (DEV) Liberando versiones
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- next-release
|
||||
- release/next
|
||||
|
||||
jobs:
|
||||
############ RELEASE ############
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
commit: ${{ steps.vars.outputs.commit }}
|
||||
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
|
||||
@@ -27,7 +33,7 @@ jobs:
|
||||
run: yarn install --immutable --network-timeout 300000
|
||||
|
||||
- name: Build Package
|
||||
run: yarn build
|
||||
run: yarn build:full
|
||||
|
||||
- name: Release @bot-whatsapp/bot
|
||||
run: yarn node ./scripts/release.js --name=bot --version= --token="${{ secrets.NPM_TOKEN }}"
|
||||
@@ -44,8 +50,15 @@ jobs:
|
||||
- name: Release @bot-whatsapp/provider
|
||||
run: yarn node ./scripts/release.js --name=provider --version= --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Commit Versioning & Push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
- name: Release @bot-whatsapp/contexts
|
||||
run: yarn node ./scripts/release.js --name=contexts --version= --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/portal
|
||||
run: yarn node ./scripts/release.js --name=portal --version= --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Commit & Push changes
|
||||
uses: actions-js/push@master
|
||||
with:
|
||||
commit_message: 'ci(version): :zap: automatic - "${date}" updated versions every packages'
|
||||
branch: dev
|
||||
branch: release/next
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
force: true
|
||||
|
||||
48
.github/workflows/releases.yml
vendored
48
.github/workflows/releases.yml
vendored
@@ -2,12 +2,12 @@ name: 🚀⚡ Liberando versiones
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
branches:
|
||||
- release/production
|
||||
jobs:
|
||||
############ RELEASE ############
|
||||
release:
|
||||
release-prod:
|
||||
if: ${{ !github.event.act }}
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -27,29 +27,49 @@ jobs:
|
||||
|
||||
- run: corepack enable
|
||||
|
||||
- name: Set User
|
||||
run: git config --global user.email "leifer.contacto@gmail.com" && git config --global user.name "Leifer Mendez"
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: yarn install --immutable --network-timeout 300000
|
||||
|
||||
- name: Set CHANGELOG
|
||||
run: yarn release
|
||||
|
||||
- name: get-npm-version
|
||||
id: package-version
|
||||
uses: martinbeentjes/npm-get-version-action@main
|
||||
|
||||
- name: Build Package
|
||||
run: yarn build
|
||||
run: yarn build:full
|
||||
|
||||
- name: Release @bot-whatsapp/bot
|
||||
run: yarn node ./scripts/release.js --name=bot --version="${{ steps.vars.outputs.tag }}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
run: yarn node ./scripts/release.js --name=bot --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/cli
|
||||
run: yarn node ./scripts/release.js --name=cli --version="${{ steps.vars.outputs.tag }}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
run: yarn node ./scripts/release.js --name=cli --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/create-bot-whatsapp
|
||||
run: yarn node ./scripts/release.js --name=create-bot-whatsapp --version="${{ steps.vars.outputs.tag }}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
run: yarn node ./scripts/release.js --name=create-bot-whatsapp --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/database
|
||||
run: yarn node ./scripts/release.js --name=database --version="${{ steps.vars.outputs.tag }}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
run: yarn node ./scripts/release.js --name=database --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/provider
|
||||
run: yarn node ./scripts/release.js --name=provider --version="${{ steps.vars.outputs.tag }}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
run: yarn node ./scripts/release.js --name=provider --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Commit Versioning & Push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
- name: Release @bot-whatsapp/contexts
|
||||
run: yarn node ./scripts/release.js --name=contexts --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release @bot-whatsapp/portal
|
||||
run: yarn node ./scripts/release.js --name=portal --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.NPM_TOKEN }}"
|
||||
|
||||
- name: Release Github
|
||||
run: yarn node ./scripts/github.js --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.OCTO_TOKEN }}"
|
||||
|
||||
- name: Commit & Push changes
|
||||
uses: actions-js/push@master
|
||||
with:
|
||||
commit_message: 'release(version): 🚀 - "${{ steps.vars.outputs.tag }}" release'
|
||||
branch: dev
|
||||
branch: release/production
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
force: true
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
/node_modules
|
||||
/packages/repl
|
||||
/packages/*/starters
|
||||
/packages/*/node_modules
|
||||
/packages/*/dist
|
||||
@@ -14,6 +15,10 @@ mediaSend/*
|
||||
!mediaSend/nota-de-voz.mp3
|
||||
.env
|
||||
.wwebjs_auth
|
||||
/session
|
||||
/session/*
|
||||
/tokens
|
||||
/tokens/*
|
||||
packages/cli/config.json
|
||||
config.json
|
||||
.yarnrc.yml
|
||||
@@ -38,3 +43,4 @@ yarn-error.log
|
||||
.npmrc
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
.secrets
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit
|
||||
npm run lint:fix && npx --no -- commitlint --edit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
packages/**/lib
|
||||
packages/docs/*.json
|
||||
packages/docs/
|
||||
**/.git
|
||||
**/.svn
|
||||
**/.hg
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
}
|
||||
|
||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"recommendations": ["xyc.vscode-mdx-preview"]
|
||||
"recommendations": ["xyc.vscode-mdx-preview", "vivaxy.vscode-conventional-commits", "mhutchie.git-graph"]
|
||||
}
|
||||
|
||||
193
CHANGELOG.md
193
CHANGELOG.md
@@ -2,6 +2,199 @@
|
||||
|
||||
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.20](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.19...v0.1.20) (2023-02-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cli:** :fire: add regex expression in addKeyworkd ([e34560c](https://github.com/leifermendez/bot-whatsapp/commit/e34560c77d4852d2e90930f0858e51aa67d4eeab))
|
||||
* **provider:** :zap: possible get class provider ([76ba717](https://github.com/leifermendez/bot-whatsapp/commit/76ba717927a75b3d6299206aa0b8aee2bc25b726))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** :zap: working flowDynamic test ([c0113ca](https://github.com/leifermendez/bot-whatsapp/commit/c0113ca49295aff220d8defcb53f2ba7f2872d75))
|
||||
* **cli:** :zap: working flowDynamic test ([aef52d2](https://github.com/leifermendez/bot-whatsapp/commit/aef52d2694fa6616d614338643db198b4f7f1fe8))
|
||||
* **cli:** :zap: working flowDynamic test ([f769320](https://github.com/leifermendez/bot-whatsapp/commit/f76932021ce968d93241b55cfcdb8ae0e0e6c934))
|
||||
* **cli:** :zap: working flowDynamic test ([23e09ef](https://github.com/leifermendez/bot-whatsapp/commit/23e09efaeccaf51018c55da492edff45b625f0a9))
|
||||
* **database:** add support emoji in mysql ([9311aa0](https://github.com/leifermendez/bot-whatsapp/commit/9311aa0a65623a1bf40e96207a281625154dae90))
|
||||
* **database:** fix naming ([cd082f2](https://github.com/leifermendez/bot-whatsapp/commit/cd082f235012cd5f5844c6437f51711beee0c865))
|
||||
* **database:** fix naming ([1afc3ba](https://github.com/leifermendez/bot-whatsapp/commit/1afc3ba182070713b5bec40eaab0fa1f680830cd))
|
||||
* **database:** fix naming ([c9831d2](https://github.com/leifermendez/bot-whatsapp/commit/c9831d202ab2c85f15a0247cd2a2426bc435270c))
|
||||
* **provider:** :zap: baily wa.link ([96c2bff](https://github.com/leifermendez/bot-whatsapp/commit/96c2bffd093269be8e39474a84c156938504a6cb))
|
||||
|
||||
### [0.1.19](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.18...v0.1.19) (2023-01-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* :fire: bailey add media ([eab39e4](https://github.com/leifermendez/bot-whatsapp/commit/eab39e4ac06fd46f1a4671f8c15d1456b4400b97))
|
||||
* :zap: more feature ([e19c3a2](https://github.com/leifermendez/bot-whatsapp/commit/e19c3a25a40259c74b4add9635af4844907eed26))
|
||||
* **provider:** :rocket: fix issues in providers venom and wwebjs ([cbe438b](https://github.com/leifermendez/bot-whatsapp/commit/cbe438b77854e8df48b9dafaf7a837d21124ac5f))
|
||||
* **provider:** :rocket: fix provider ([0ad4c58](https://github.com/leifermendez/bot-whatsapp/commit/0ad4c58457b548dc41c0f9e8470d59c48de7b95a))
|
||||
* **provider:** :rocket: fix provider ([f8c7184](https://github.com/leifermendez/bot-whatsapp/commit/f8c7184487065443ab10f77aaf585e8bd63ca441))
|
||||
* **provider:** :rocket: fix provider ([b2afa45](https://github.com/leifermendez/bot-whatsapp/commit/b2afa45352a7ab1f5d9775f3c1fde475bd8ca204))
|
||||
* **provider:** :rocket: fix provider venom and wwebjs ([dcb0566](https://github.com/leifermendez/bot-whatsapp/commit/dcb0566d2bc3da40cd0c71554bb5ea0ec115d9ca))
|
||||
* **provider:** :rocket: implements all send media to venom provider ([9dd7c02](https://github.com/leifermendez/bot-whatsapp/commit/9dd7c02b6a5474aff063f7d6be0ca8519504b93c))
|
||||
* **provider:** :rocket: send file wwebjs ([6ff1a3a](https://github.com/leifermendez/bot-whatsapp/commit/6ff1a3a980196c01c66ed04ee07d0e7e57256504))
|
||||
* **provider:** :zap: bailey add send file video audio ([14d1a61](https://github.com/leifermendez/bot-whatsapp/commit/14d1a61fa259c09135c37c55bd79e97c9c8367e4))
|
||||
* **provider:** :zap: venom wweb ([fd2847a](https://github.com/leifermendez/bot-whatsapp/commit/fd2847aea0db17a0bdf33b5bca67a4cb8db2da16))
|
||||
* **provider:** :zap: venom wweb ([f95331d](https://github.com/leifermendez/bot-whatsapp/commit/f95331d3dc70e76a3dfbe4c8d24059f0e7a164ef))
|
||||
* **provider:** 🚀 implements all send media to venom provider ([bd7d150](https://github.com/leifermendez/bot-whatsapp/commit/bd7d150c047af41fdbb47f0a50a21e82cd79ee85))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bot:** :fire: endFlow with ctx ([f6114af](https://github.com/leifermendez/bot-whatsapp/commit/f6114affadfbc324536a86167d1fdfe8da3c8de6))
|
||||
* **bot:** :fire: endFlow with ctx ([b655ae4](https://github.com/leifermendez/bot-whatsapp/commit/b655ae449e7958ea940d8cc3c678fd66f60b6385))
|
||||
* **bot:** :zap: endFlow butons ([87a4203](https://github.com/leifermendez/bot-whatsapp/commit/87a4203cd5b88f566387a76d586248e4265d6e4e))
|
||||
* **bot:** :zap: fix fallback refactor ([e22780d](https://github.com/leifermendez/bot-whatsapp/commit/e22780d3faba94f71a70f1f201a20690608fa5bf))
|
||||
* **cli:** :zap: endflow ([1c66f17](https://github.com/leifermendez/bot-whatsapp/commit/1c66f178a56d284bb8cb9df5ca17685c7e5d1ddd))
|
||||
* **cli:** :zap: refactor fallback in child flow ([b33e346](https://github.com/leifermendez/bot-whatsapp/commit/b33e34692d3abcb6874308a9be79f74be4a2c3a8))
|
||||
* **cli:** :zap: refactor fallback in child flow ([8da4b20](https://github.com/leifermendez/bot-whatsapp/commit/8da4b204b41125b5d0fa0aee4fa87c1f5faf5568))
|
||||
|
||||
### [0.1.18](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.17...v0.1.18) (2023-01-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bot:** :zap: add blacklist ([7078dc4](https://github.com/leifermendez/bot-whatsapp/commit/7078dc4c93d01bf90ef08ecb34e89a1abbe16fd2))
|
||||
* **bot:** :zap: flowDynamic buttons, media ([3c4b1c0](https://github.com/leifermendez/bot-whatsapp/commit/3c4b1c0fc4b6d98d67c67806d918d3604bb2209b))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bot:** :bug: body undefined ([bb6ed4a](https://github.com/leifermendez/bot-whatsapp/commit/bb6ed4a084ae98070dfdf0c4ba1eca574c4092cc))
|
||||
* **bot:** :bug: body undefined ([9234cf1](https://github.com/leifermendez/bot-whatsapp/commit/9234cf1c5d00abdd35e62a826b3c450ab056987a))
|
||||
* **bot:** :bug: body undefined ([a118bbb](https://github.com/leifermendez/bot-whatsapp/commit/a118bbbf7f0a7023cb7f33c23f37db72adad151f))
|
||||
* **bot:** :bug: body undefined ([f54dea5](https://github.com/leifermendez/bot-whatsapp/commit/f54dea52b01063acd6122eeba1fbbe324aa7805d))
|
||||
* **bot:** :bug: body undefined ([72e0a91](https://github.com/leifermendez/bot-whatsapp/commit/72e0a910503e9643db7dfbc6e09c41c96934e1f7))
|
||||
* **bot:** :bug: body undefined ([70dd4d7](https://github.com/leifermendez/bot-whatsapp/commit/70dd4d73e814fc5636d19a887f3621c483b837c1))
|
||||
* **bot:** :bug: body undefined ([ecf0eef](https://github.com/leifermendez/bot-whatsapp/commit/ecf0eef928917d76c59bd23886cb7a4108b421f1))
|
||||
* **bot:** :bug: flowDynamic stranger behaviour ([877252b](https://github.com/leifermendez/bot-whatsapp/commit/877252bd4a8a7bbbbf083c3ceaeaeb952b0a1828))
|
||||
* **bot:** :bug: flowDynamic stranger behaviour ([f5a7de3](https://github.com/leifermendez/bot-whatsapp/commit/f5a7de3a003c012e2164e51fff26892cfc3144be))
|
||||
* **bot:** :memo: more docs ([98793d0](https://github.com/leifermendez/bot-whatsapp/commit/98793d0cfc1674830beaa3707f933c5a791eec14))
|
||||
* **cli:** :zap: refactor ([a29b9d4](https://github.com/leifermendez/bot-whatsapp/commit/a29b9d4e1f85fc163cf1d633c0857f0c8b7f03e1))
|
||||
* **cli:** :zap: refactor ([18ef4e9](https://github.com/leifermendez/bot-whatsapp/commit/18ef4e9d726575ca390ca24354825860328d3347))
|
||||
* **cli:** :zap: refactor ([3648757](https://github.com/leifermendez/bot-whatsapp/commit/3648757fa083bdb88a16bf6c2e90c828c233bdb1))
|
||||
* **cli:** :zap: refactor ([32f6a70](https://github.com/leifermendez/bot-whatsapp/commit/32f6a70f8f6fb26d8ea2a0f1a4aec4827b9d6a93))
|
||||
* **cli:** :zap: refactor ([8c825e7](https://github.com/leifermendez/bot-whatsapp/commit/8c825e7f6b7133f7cc7f3041ce331b80a9fe60e0))
|
||||
* **cli:** :zap: refactor ([0c0f437](https://github.com/leifermendez/bot-whatsapp/commit/0c0f4375b84549bee809340a85f9ce038ee2739e))
|
||||
* **cli:** :zap: refactor ([039ce5d](https://github.com/leifermendez/bot-whatsapp/commit/039ce5dd7cac8115b335ad5de05f7bd871e24140))
|
||||
* **cli:** :zap: refactor ([5e87918](https://github.com/leifermendez/bot-whatsapp/commit/5e879188b8bf9d486399b308a9a9c2612607d465))
|
||||
* **cli:** :zap: refactor ([21a7270](https://github.com/leifermendez/bot-whatsapp/commit/21a72702817bc6b344223b34ca4513a7ff45fc93))
|
||||
* **cli:** :zap: refactor ([82a99b2](https://github.com/leifermendez/bot-whatsapp/commit/82a99b2c80e6738566042ea738bbab8208a17758))
|
||||
* **cli:** :zap: refactor ([cc19974](https://github.com/leifermendez/bot-whatsapp/commit/cc19974579379777b05cb69c38cec0fce6740471))
|
||||
* **cli:** :zap: refactor ([56fcb8f](https://github.com/leifermendez/bot-whatsapp/commit/56fcb8fb72169bc21fce7c4fcdceccf2acd39c73))
|
||||
* **cli:** :zap: refactor ([f36cff1](https://github.com/leifermendez/bot-whatsapp/commit/f36cff1eefdd96be4ab531e1cb2d3b630b1a81c3))
|
||||
* **cli:** :zap: refactor ([b393c11](https://github.com/leifermendez/bot-whatsapp/commit/b393c11af6c0ebccb0a690be8b90b9df8877dad1))
|
||||
* **cli:** :zap: refactor ([6683715](https://github.com/leifermendez/bot-whatsapp/commit/6683715ad617ea1075654a475a1c62ea607c733f))
|
||||
* **contexts:** :bug: fixed [#524](https://github.com/leifermendez/bot-whatsapp/issues/524) issue ([79cc31a](https://github.com/leifermendez/bot-whatsapp/commit/79cc31a96f6a9836447cc4e6bb1e1521c54183fe))
|
||||
* **contexts:** :bug: fixed [#524](https://github.com/leifermendez/bot-whatsapp/issues/524) issue ([7067b4a](https://github.com/leifermendez/bot-whatsapp/commit/7067b4a80b7938ccfaf1ed141a37d645a1a3a062))
|
||||
* **provider:** wwebjs upgrade ([345f256](https://github.com/leifermendez/bot-whatsapp/commit/345f256a1b4a238519dafc15c9a31bc5e6bad4fe))
|
||||
* se agrego @bot-whatsapp/portal a package.json ([46a9fa6](https://github.com/leifermendez/bot-whatsapp/commit/46a9fa6793e06600335de998d2bd9d0691b02ca4))
|
||||
|
||||
### [0.1.17](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.16...v0.1.17) (2023-01-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* mod de starters para habiltar portal ([eceb170](https://github.com/leifermendez/bot-whatsapp/commit/eceb170df03721dca4183b658c863b94fa04bc84))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** pre-release ([aaec075](https://github.com/leifermendez/bot-whatsapp/commit/aaec0751408ab49483d428810d94aaf7d46acb94))
|
||||
* correccion en starters app.js para portal QR ([f430380](https://github.com/leifermendez/bot-whatsapp/commit/f430380b4f23d41702395c96c628bf13bf443278))
|
||||
* **starters:** :zap: added dockerfile ([230981e](https://github.com/leifermendez/bot-whatsapp/commit/230981e2676361149cb2a99def7f705e75009260))
|
||||
|
||||
### [0.1.16](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.15...v0.1.16) (2023-01-11)
|
||||
|
||||
### [0.1.15](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.14...v0.1.15) (2023-01-11)
|
||||
|
||||
### [0.1.14](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.13...v0.1.14) (2023-01-11)
|
||||
|
||||
### [0.1.13](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.12...v0.1.13) (2023-01-11)
|
||||
|
||||
### [0.1.12](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.10...v0.1.12) (2023-01-11)
|
||||
|
||||
### [0.1.9-pre](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.9...v0.1.9-pre) (2023-01-10)
|
||||
|
||||
### [0.1.7-pre-1](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-alpha...v0.1.7-pre-1) (2023-01-10)
|
||||
|
||||
### [0.1.7-alpha](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-pre...v0.1.7-alpha) (2023-01-10)
|
||||
|
||||
### [0.1.11](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.10...v0.1.11) (2023-01-11)
|
||||
|
||||
### [0.1.9-pre](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.9...v0.1.9-pre) (2023-01-10)
|
||||
|
||||
### [0.1.7-pre-1](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-alpha...v0.1.7-pre-1) (2023-01-10)
|
||||
|
||||
### [0.1.7-alpha](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-pre...v0.1.7-alpha) (2023-01-10)
|
||||
|
||||
### [0.1.10](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.8...v0.1.10) (2023-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :fire: update qr package ([ecde23f](https://github.com/leifermendez/bot-whatsapp/commit/ecde23fdea65def209aa874af35a3f293e6b1a91))
|
||||
|
||||
### [0.1.8](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-pre...v0.1.8) (2023-01-10)
|
||||
|
||||
### [0.1.7](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.7-pre...v0.1.7) (2023-01-10)
|
||||
|
||||
### [0.1.6](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.5...v0.1.6) (2023-01-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* :zap: new portal web for qr scan ([cb2e869](https://github.com/leifermendez/bot-whatsapp/commit/cb2e8692a3f94c8b24993cd11dd564f094b0e4ef))
|
||||
* :zap: new portal web for qr scan ([9e93795](https://github.com/leifermendez/bot-whatsapp/commit/9e93795e6fce38890045389da95184fef1fbe0da))
|
||||
* :zap: new portal web for qr scan ([3c178ea](https://github.com/leifermendez/bot-whatsapp/commit/3c178ea113b140535a51f5dcd521dbb66251670e))
|
||||
* :zap: new portal web for qr scan ([1f1f564](https://github.com/leifermendez/bot-whatsapp/commit/1f1f564f4e2e3aa13b84de500fe215e0c45c2770))
|
||||
* :zap: new portal web for qr scan ([3de5f4b](https://github.com/leifermendez/bot-whatsapp/commit/3de5f4b77a10e30632ff7555f5af5d8e93cb2019))
|
||||
* :zap: qr code filename ([d794f60](https://github.com/leifermendez/bot-whatsapp/commit/d794f604ac8a835e523709dbf18c9b1609bbd00e))
|
||||
* :zap: qr portal ([246ecdc](https://github.com/leifermendez/bot-whatsapp/commit/246ecdc11a8c4e652867c842b612dc4ce73f9828))
|
||||
* :zap: qr portal ([af8b401](https://github.com/leifermendez/bot-whatsapp/commit/af8b401d075e1c35065589ede61476461ce86b4d))
|
||||
* agregamos dockerfile y webserver a starters ([f9e3bbc](https://github.com/leifermendez/bot-whatsapp/commit/f9e3bbc6655060408e4fdbe1d7e920c2ed4fca53))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :zap: add Dockerfile, starter ([4e0d33c](https://github.com/leifermendez/bot-whatsapp/commit/4e0d33c6bb46ad259774f6d0c38c6c0b5f8ca4a9))
|
||||
* :zap: fix inject port args ([20f752e](https://github.com/leifermendez/bot-whatsapp/commit/20f752e6c1b1f7d11948fc4f2f8950f7834df7d9))
|
||||
* :zap: fix inject port args ([7a23eb0](https://github.com/leifermendez/bot-whatsapp/commit/7a23eb0cc6f93ec21c5ab34e46981ae7a93f42ff))
|
||||
* **provider:** :zap: fix send image baileys ([2ddea54](https://github.com/leifermendez/bot-whatsapp/commit/2ddea5468d235035478d4e91e63c821da19da179))
|
||||
* **provider:** :zap: fix send image baileys ([391e11c](https://github.com/leifermendez/bot-whatsapp/commit/391e11ce738cd64792b5237d69f3739b0263c198))
|
||||
* **provider:** :zap: fix send image baileys ([5d10cb9](https://github.com/leifermendez/bot-whatsapp/commit/5d10cb9026da60043e9a2f86117ebb04d0631a3f))
|
||||
* **provider:** fix error docker as root user ([5a033da](https://github.com/leifermendez/bot-whatsapp/commit/5a033da83aee1f614120bccf27c9f330500cc7b0))
|
||||
|
||||
### [0.1.4](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.5...v0.1.4) (2023-01-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* :zap: new portal web for qr scan ([cb2e869](https://github.com/leifermendez/bot-whatsapp/commit/cb2e8692a3f94c8b24993cd11dd564f094b0e4ef))
|
||||
* :zap: new portal web for qr scan ([9e93795](https://github.com/leifermendez/bot-whatsapp/commit/9e93795e6fce38890045389da95184fef1fbe0da))
|
||||
* :zap: new portal web for qr scan ([3c178ea](https://github.com/leifermendez/bot-whatsapp/commit/3c178ea113b140535a51f5dcd521dbb66251670e))
|
||||
* :zap: new portal web for qr scan ([1f1f564](https://github.com/leifermendez/bot-whatsapp/commit/1f1f564f4e2e3aa13b84de500fe215e0c45c2770))
|
||||
* :zap: new portal web for qr scan ([3de5f4b](https://github.com/leifermendez/bot-whatsapp/commit/3de5f4b77a10e30632ff7555f5af5d8e93cb2019))
|
||||
* :zap: qr code filename ([d794f60](https://github.com/leifermendez/bot-whatsapp/commit/d794f604ac8a835e523709dbf18c9b1609bbd00e))
|
||||
* :zap: qr portal ([246ecdc](https://github.com/leifermendez/bot-whatsapp/commit/246ecdc11a8c4e652867c842b612dc4ce73f9828))
|
||||
* :zap: qr portal ([af8b401](https://github.com/leifermendez/bot-whatsapp/commit/af8b401d075e1c35065589ede61476461ce86b4d))
|
||||
* agregamos dockerfile y webserver a starters ([f9e3bbc](https://github.com/leifermendez/bot-whatsapp/commit/f9e3bbc6655060408e4fdbe1d7e920c2ed4fca53))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* :zap: add Dockerfile, starter ([4e0d33c](https://github.com/leifermendez/bot-whatsapp/commit/4e0d33c6bb46ad259774f6d0c38c6c0b5f8ca4a9))
|
||||
* :zap: fix inject port args ([20f752e](https://github.com/leifermendez/bot-whatsapp/commit/20f752e6c1b1f7d11948fc4f2f8950f7834df7d9))
|
||||
* :zap: fix inject port args ([7a23eb0](https://github.com/leifermendez/bot-whatsapp/commit/7a23eb0cc6f93ec21c5ab34e46981ae7a93f42ff))
|
||||
* **provider:** :zap: fix send image baileys ([2ddea54](https://github.com/leifermendez/bot-whatsapp/commit/2ddea5468d235035478d4e91e63c821da19da179))
|
||||
* **provider:** :zap: fix send image baileys ([391e11c](https://github.com/leifermendez/bot-whatsapp/commit/391e11ce738cd64792b5237d69f3739b0263c198))
|
||||
* **provider:** :zap: fix send image baileys ([5d10cb9](https://github.com/leifermendez/bot-whatsapp/commit/5d10cb9026da60043e9a2f86117ebb04d0631a3f))
|
||||
* **provider:** fix error docker as root user ([5a033da](https://github.com/leifermendez/bot-whatsapp/commit/5a033da83aee1f614120bccf27c9f330500cc7b0))
|
||||
|
||||
### [0.1.3](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.2...v0.1.3) (2023-01-04)
|
||||
|
||||
|
||||
|
||||
81
README.md
81
README.md
@@ -1,8 +1,7 @@
|
||||
# Chatbot Library
|
||||

|
||||
[](http://commitizen.github.io/cz-cli/)
|
||||
[](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml)
|
||||
|
||||
[](https://link.codigoencasa.com/DISCORD)
|
||||
|
||||
<p align="center">
|
||||
<img width="300" src="https://i.imgur.com/Oauef6t.png">
|
||||
@@ -34,6 +33,13 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
||||
<!-- readme: collaborators,contributors -start -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/cheveguerra">
|
||||
<img src="https://avatars.githubusercontent.com/u/5891114?v=4" width="50;" alt="cheveguerra"/>
|
||||
<br />
|
||||
<sub><b>Jose Alberto Guerra Ugalde</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/leifermendez">
|
||||
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
|
||||
@@ -62,6 +68,21 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
||||
<sub><b>Leifer Mendez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/danielcasta0398">
|
||||
<img src="https://avatars.githubusercontent.com/u/98791147?v=4" width="50;" alt="danielcasta0398"/>
|
||||
<br />
|
||||
<sub><b>Juan Daniel Castaño</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/marianarolfo">
|
||||
<img src="https://avatars.githubusercontent.com/u/68322254?v=4" width="50;" alt="marianarolfo"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/HKong31">
|
||||
<img src="https://avatars.githubusercontent.com/u/113340082?v=4" width="50;" alt="HKong31"/>
|
||||
@@ -75,8 +96,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
||||
<br />
|
||||
<sub><b>Zvi</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/JosephVTX">
|
||||
<img src="https://avatars.githubusercontent.com/u/91026290?v=4" width="50;" alt="JosephVTX"/>
|
||||
<br />
|
||||
<sub><b>Joseph Vega Callupe</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"/>
|
||||
@@ -84,6 +111,42 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/devrlbusiness">
|
||||
<img src="https://avatars.githubusercontent.com/u/66280283?v=4" width="50;" alt="devrlbusiness"/>
|
||||
<br />
|
||||
<sub><b>Developer RL Business</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Gregoriotecnico">
|
||||
<img src="https://avatars.githubusercontent.com/u/118696506?v=4" width="50;" alt="Gregoriotecnico"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/jlferrete">
|
||||
<img src="https://avatars.githubusercontent.com/u/36698913?v=4" width="50;" alt="jlferrete"/>
|
||||
<br />
|
||||
<sub><b>Jose Luis Ferrete Olarte</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lisandroprada">
|
||||
<img src="https://avatars.githubusercontent.com/u/7232326?v=4" width="50;" alt="lisandroprada"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/6rak0">
|
||||
<img src="https://avatars.githubusercontent.com/u/12260031?v=4" width="50;" alt="6rak0"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/tonyvazgar">
|
||||
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
|
||||
@@ -91,20 +154,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
||||
<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></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/yond1994">
|
||||
<img src="https://avatars.githubusercontent.com/u/47557263?v=4" width="50;" alt="yond1994"/>
|
||||
|
||||
36
__test__/01-case.test.js
Normal file
36
__test__/01-case.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
test(`[Caso - 01] Flow Basico`, async () => {
|
||||
const [VALUE_A, VALUE_B] = ['hola', 'buenas']
|
||||
|
||||
const flow = addKeyword(VALUE_A).addAnswer(VALUE_B)
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flow]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(100, 'message', {
|
||||
from: '000',
|
||||
body: VALUE_A,
|
||||
})
|
||||
|
||||
await delay(100)
|
||||
|
||||
const prevMsg = database.getPrevByNumber('000')
|
||||
|
||||
assert.is(prevMsg.answer, VALUE_B)
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
94
__test__/02-case.test.js
Normal file
94
__test__/02-case.test.js
Normal file
@@ -0,0 +1,94 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
/**
|
||||
* Falsear peticion async
|
||||
* @param {*} fakeData
|
||||
* @returns
|
||||
*/
|
||||
const fakeHTTP = async (fakeData = []) => {
|
||||
console.log('⚡ Server request!')
|
||||
await delay(50)
|
||||
console.log('⚡ Server return!')
|
||||
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
|
||||
console.log(data)
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
test(`[Caso - 02] Flow (flowDynamic)`, async () => {
|
||||
const MOCK_VALUES = [
|
||||
'Bienvenido te envio muchas marcas (5510)',
|
||||
'Seleccione marca del auto a cotizar, con el *número* correspondiente',
|
||||
'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:',
|
||||
'Los precios rondan:',
|
||||
]
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola'])
|
||||
.addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => {
|
||||
console.log('execute...')
|
||||
const data = await fakeHTTP(['Ford', 'GM', 'BMW'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[1], null, async (ctx, { flowDynamic }) => {
|
||||
const data = await fakeHTTP(['Ranger', 'Explorer'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
|
||||
const data = await fakeHTTP(['Usado', 'Nuevos'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => {
|
||||
const data = await fakeHTTP(['1000', '2000', '3000'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
await delay(1200)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
|
||||
//FlowDynamic
|
||||
assert.is('1 Ford', getHistory[1])
|
||||
assert.is('2 GM', getHistory[2])
|
||||
assert.is('3 BMW', getHistory[3])
|
||||
|
||||
assert.is(MOCK_VALUES[1], getHistory[4])
|
||||
|
||||
//FlowDynamic
|
||||
assert.is('1 Ranger', getHistory[5])
|
||||
assert.is('2 Explorer', getHistory[6])
|
||||
|
||||
assert.is(MOCK_VALUES[2], getHistory[7])
|
||||
|
||||
//FlowDynamic
|
||||
assert.is('1 Usado', getHistory[8])
|
||||
assert.is('2 Nuevos', getHistory[9])
|
||||
|
||||
assert.is(MOCK_VALUES[3], getHistory[10])
|
||||
|
||||
//FlowDynamic
|
||||
assert.is('1 1000', getHistory[11])
|
||||
assert.is('2 2000', getHistory[12])
|
||||
assert.is('3 3000', getHistory[13])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
37
__test__/03-case.test.js
Normal file
37
__test__/03-case.test.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
test(`[Caso - 03] Flow puro`, async () => {
|
||||
const MOCK_VALUES = ['Bienvenido a mi tienda', 'Como estas?']
|
||||
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola']).addAnswer(MOCK_VALUES[0]).addAnswer(MOCK_VALUES[1])
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
await delay(10)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
assert.is(MOCK_VALUES[1], getHistory[1])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
77
__test__/04-case.test.js
Normal file
77
__test__/04-case.test.js
Normal file
@@ -0,0 +1,77 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
/**
|
||||
* Falsear peticion async
|
||||
* @param {*} fakeData
|
||||
* @returns
|
||||
*/
|
||||
const fakeHTTP = async (fakeData = []) => {
|
||||
console.log('⚡ Server request!')
|
||||
await delay(50)
|
||||
console.log('⚡ Server return!')
|
||||
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
|
||||
console.log(data)
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
test(`[Caso - 04] Romper flujo (endFlow)`, async () => {
|
||||
const MOCK_VALUES = [
|
||||
'Bienvenido te envio muchas marcas (5510)',
|
||||
'Seleccione marca del auto a cotizar, con el *número* correspondiente',
|
||||
'Seleccione la sub marca del auto a cotizar, con el *número* correspondiente:',
|
||||
'Los precios rondan:',
|
||||
]
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola'])
|
||||
.addAnswer(MOCK_VALUES[0], null, async (ctx, { flowDynamic }) => {
|
||||
console.log('execute...')
|
||||
const data = await fakeHTTP(['Ford', 'GM', 'BMW'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[1], null, async (ctx, { endFlow }) => {
|
||||
return endFlow()
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
|
||||
const data = await fakeHTTP(['Usado', 'Nuevos'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[3], null, async (ctx, { flowDynamic }) => {
|
||||
const data = await fakeHTTP(['1000', '2000', '3000'])
|
||||
return flowDynamic(data)
|
||||
})
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
await delay(1200)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
|
||||
//FlowDynamic
|
||||
assert.is('1 Ford', getHistory[1])
|
||||
assert.is('2 GM', getHistory[2])
|
||||
assert.is('3 BMW', getHistory[3])
|
||||
|
||||
assert.is(MOCK_VALUES[1], getHistory[4])
|
||||
assert.is(undefined, getHistory[5])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
100
__test__/05-case.test.js
Normal file
100
__test__/05-case.test.js
Normal file
@@ -0,0 +1,100 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
/**
|
||||
* Falsear peticion async
|
||||
* @param {*} fakeData
|
||||
* @returns
|
||||
*/
|
||||
const fakeHTTP = async (fakeData = []) => {
|
||||
await delay(5)
|
||||
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => {
|
||||
const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?']
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola'])
|
||||
.addAnswer(
|
||||
MOCK_VALUES[0],
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
async (ctx, { flowDynamic, fallBack }) => {
|
||||
const validation = ctx.body.includes('@')
|
||||
|
||||
if (validation) {
|
||||
const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta'])
|
||||
return flowDynamic(getDataFromApi)
|
||||
}
|
||||
return fallBack(validation)
|
||||
}
|
||||
)
|
||||
.addAnswer(MOCK_VALUES[1])
|
||||
.addAnswer(MOCK_VALUES[2], { capture: true }, async (ctx, { flowDynamic, fallBack }) => {
|
||||
if (ctx.body !== '18') {
|
||||
await delay(50)
|
||||
return fallBack(false, 'Ups creo que no eres mayor de edad')
|
||||
}
|
||||
return flowDynamic('Bien tu edad es correcta!')
|
||||
})
|
||||
.addAnswer('Puedes pasar')
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(10, 'message', {
|
||||
from: '000',
|
||||
body: 'this is not email value',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(20, 'message', {
|
||||
from: '000',
|
||||
body: 'test@test.com',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(90, 'message', {
|
||||
from: '000',
|
||||
body: '20',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(200, 'message', {
|
||||
from: '000',
|
||||
body: '18',
|
||||
})
|
||||
|
||||
await delay(1200)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
assert.is('this is not email value', getHistory[1])
|
||||
assert.is(MOCK_VALUES[0], getHistory[2])
|
||||
assert.is('test@test.com', getHistory[3])
|
||||
assert.is('1 Gracias por tu email se ha validado de manera correcta', getHistory[4])
|
||||
assert.is(MOCK_VALUES[1], getHistory[5])
|
||||
assert.is(MOCK_VALUES[2], getHistory[6])
|
||||
assert.is('20', getHistory[7])
|
||||
assert.is('Ups creo que no eres mayor de edad', getHistory[8])
|
||||
assert.is('18', getHistory[9])
|
||||
assert.is('Bien tu edad es correcta!', getHistory[10])
|
||||
assert.is('Puedes pasar', getHistory[11])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
93
__test__/06-case.test.js
Normal file
93
__test__/06-case.test.js
Normal file
@@ -0,0 +1,93 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
/**
|
||||
* Falsear peticion async
|
||||
* @param {*} fakeData
|
||||
* @returns
|
||||
*/
|
||||
const fakeHTTP = async (fakeData = []) => {
|
||||
await delay(5)
|
||||
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
test(`[Caso - 06] Finalizar Flujo (endFlow)`, async () => {
|
||||
const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?']
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola'])
|
||||
.addAnswer(
|
||||
MOCK_VALUES[0],
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
async (ctx, { flowDynamic, fallBack }) => {
|
||||
const validation = ctx.body.includes('@')
|
||||
|
||||
if (validation) {
|
||||
const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta'])
|
||||
return flowDynamic(getDataFromApi)
|
||||
}
|
||||
return fallBack(validation)
|
||||
}
|
||||
)
|
||||
.addAnswer(MOCK_VALUES[1], null, async (_, { endFlow }) => {
|
||||
return endFlow()
|
||||
})
|
||||
.addAnswer(MOCK_VALUES[2], { capture: true }, async (ctx, { flowDynamic, fallBack }) => {
|
||||
if (ctx.body !== '18') {
|
||||
await delay(50)
|
||||
return fallBack(false, 'Ups creo que no eres mayor de edad')
|
||||
}
|
||||
return flowDynamic('Bien tu edad es correcta!')
|
||||
})
|
||||
.addAnswer('Puedes pasar')
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(10, 'message', {
|
||||
from: '000',
|
||||
body: 'this is not email value',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(20, 'message', {
|
||||
from: '000',
|
||||
body: 'test@test.com',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(90, 'message', {
|
||||
from: '000',
|
||||
body: '20',
|
||||
})
|
||||
|
||||
await delay(1200)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
assert.is('this is not email value', getHistory[1])
|
||||
assert.is(MOCK_VALUES[0], getHistory[2])
|
||||
assert.is('test@test.com', getHistory[3])
|
||||
assert.is('1 Gracias por tu email se ha validado de manera correcta', getHistory[4])
|
||||
assert.is(MOCK_VALUES[1], getHistory[5])
|
||||
assert.is('20', getHistory[6])
|
||||
assert.is(undefined, getHistory[7])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
92
__test__/07-case.test.js
Normal file
92
__test__/07-case.test.js
Normal file
@@ -0,0 +1,92 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
/**
|
||||
* Falsear peticion async
|
||||
* @param {*} fakeData
|
||||
* @returns
|
||||
*/
|
||||
const fakeHTTP = async (fakeData = []) => {
|
||||
await delay(5)
|
||||
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
let STATE_APP = {}
|
||||
|
||||
test(`[Caso - 07] Retornar estado`, async () => {
|
||||
const MOCK_VALUES = ['¿Cual es tu nombre?', '¿Cual es tu edad?', 'Tu datos son:']
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const flujoPrincipal = addKeyword(['hola'])
|
||||
.addAnswer(
|
||||
MOCK_VALUES[0],
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
async (ctx, { flowDynamic, fallBack }) => {
|
||||
STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], name: ctx.body }
|
||||
|
||||
flowDynamic('Gracias por tu nombre!')
|
||||
}
|
||||
)
|
||||
.addAnswer(
|
||||
MOCK_VALUES[1],
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
async (ctx, { flowDynamic, endFlow }) => {
|
||||
STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], age: ctx.body }
|
||||
|
||||
await flowDynamic('Gracias por tu edad!')
|
||||
}
|
||||
)
|
||||
.addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
|
||||
flowDynamic(`Nombre: ${STATE_APP[ctx.from].name} Edad: ${STATE_APP[ctx.from].age}`)
|
||||
})
|
||||
.addAnswer('🤖🤖 Gracias por tu participacion')
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(20, 'message', {
|
||||
from: '000',
|
||||
body: 'Leifer',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(40, 'message', {
|
||||
from: '000',
|
||||
body: '90',
|
||||
})
|
||||
|
||||
await delay(1200)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is(MOCK_VALUES[0], getHistory[0])
|
||||
assert.is('Leifer', getHistory[1])
|
||||
assert.is('Gracias por tu nombre!', getHistory[2])
|
||||
assert.is('¿Cual es tu edad?', getHistory[3])
|
||||
assert.is('90', getHistory[4])
|
||||
assert.is('Gracias por tu edad!', getHistory[5])
|
||||
assert.is('Tu datos son:', getHistory[6])
|
||||
assert.is('Nombre: Leifer Edad: 90', getHistory[7])
|
||||
assert.is('🤖🤖 Gracias por tu participacion', getHistory[8])
|
||||
assert.is(undefined, getHistory[9])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
43
__test__/08-case.test.js
Normal file
43
__test__/08-case.test.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_DB = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
test(`[Caso - 08] Regular expression on keyword`, async () => {
|
||||
const provider = createProvider(PROVIDER_DB)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm`
|
||||
const flujoPrincipal = addKeyword(REGEX_CREDIT_NUMBER, { regex: true })
|
||||
.addAnswer(`Gracias por proporcionar un numero de tarjeta valido`)
|
||||
.addAnswer('Fin!')
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flujoPrincipal]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(0, 'message', {
|
||||
from: '000',
|
||||
body: 'hola',
|
||||
})
|
||||
|
||||
provider.delaySendMessage(20, 'message', {
|
||||
from: '000',
|
||||
body: '374245455400126',
|
||||
})
|
||||
|
||||
await delay(40)
|
||||
const getHistory = database.listHistory.map((i) => i.answer)
|
||||
assert.is('Gracias por proporcionar un numero de tarjeta valido', getHistory[0])
|
||||
assert.is('Fin!', getHistory[1])
|
||||
assert.is(undefined, getHistory[2])
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
41
__test__/09-case.test.js
Normal file
41
__test__/09-case.test.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const MOCK_DB = require('../packages/database/src/mock')
|
||||
const PROVIDER_MOCK = require('../packages/provider/src/mock')
|
||||
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
|
||||
|
||||
let PROVIDER = undefined
|
||||
|
||||
test(`[Caso - 09] Check provider WS`, async () => {
|
||||
const [VALUE_A, VALUE_B] = ['hola', 'buenas']
|
||||
|
||||
const flow = addKeyword(VALUE_A).addAnswer(VALUE_B, null, async (_, { provider }) => {
|
||||
PROVIDER = provider
|
||||
})
|
||||
const provider = createProvider(PROVIDER_MOCK)
|
||||
const database = new MOCK_DB()
|
||||
|
||||
createBot({
|
||||
database,
|
||||
flow: createFlow([flow]),
|
||||
provider,
|
||||
})
|
||||
|
||||
provider.delaySendMessage(100, 'message', {
|
||||
from: '000',
|
||||
body: VALUE_A,
|
||||
})
|
||||
|
||||
await delay(100)
|
||||
|
||||
const prevMsg = database.getPrevByNumber('000')
|
||||
|
||||
assert.is(prevMsg.answer, VALUE_B)
|
||||
assert.is(typeof PROVIDER.sendMessage, 'function')
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((res) => setTimeout(res, ms))
|
||||
}
|
||||
@@ -1,28 +1,10 @@
|
||||
module.exports = {
|
||||
disableEmoji: false,
|
||||
format: '{type}{scope}: {emoji}{subject}',
|
||||
list: [
|
||||
'test',
|
||||
'feat',
|
||||
'fix',
|
||||
'chore',
|
||||
'docs',
|
||||
'refactor',
|
||||
'style',
|
||||
'ci',
|
||||
'perf',
|
||||
],
|
||||
list: ['test', 'feat', 'fix', 'chore', 'docs', 'refactor', 'style', 'ci', 'perf'],
|
||||
maxMessageLength: 64,
|
||||
minMessageLength: 3,
|
||||
questions: [
|
||||
'type',
|
||||
'scope',
|
||||
'subject',
|
||||
'body',
|
||||
'breaking',
|
||||
'issues',
|
||||
'lerna',
|
||||
],
|
||||
questions: ['type', 'scope', 'subject', 'body', 'breaking', 'issues', 'lerna'],
|
||||
scopes: [],
|
||||
types: {
|
||||
chore: {
|
||||
@@ -56,8 +38,7 @@ module.exports = {
|
||||
value: 'perf',
|
||||
},
|
||||
refactor: {
|
||||
description:
|
||||
'A code change that neither fixes a bug or adds a feature',
|
||||
description: 'A code change that neither fixes a bug or adds a feature',
|
||||
emoji: '(💡)',
|
||||
value: 'refactor',
|
||||
},
|
||||
@@ -67,8 +48,7 @@ module.exports = {
|
||||
value: 'release',
|
||||
},
|
||||
style: {
|
||||
description:
|
||||
'Markup, white-space, formatting, missing semi-colons...',
|
||||
description: 'Markup, white-space, formatting, missing semi-colons...',
|
||||
emoji: '(💄)',
|
||||
value: 'style',
|
||||
},
|
||||
@@ -80,8 +60,7 @@ module.exports = {
|
||||
messages: {
|
||||
type: "Select the type of change that you're committing:",
|
||||
customScope: 'Select the scope this component affects:',
|
||||
subject:
|
||||
'Write a short, imperative mood description of the change:\n',
|
||||
subject: 'Write a short, imperative mood description of the change:\n',
|
||||
body: 'Provide a longer description of the change:\n ',
|
||||
breaking: 'List any breaking changes:\n',
|
||||
footer: 'Issues this commit closes, e.g #123:',
|
||||
|
||||
15
package.json
15
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/root",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.20",
|
||||
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
@@ -13,15 +13,19 @@
|
||||
"contexts:rollup": "rollup --config ./packages/contexts/rollup-contexts.config.js",
|
||||
"database:rollup": "rollup --config ./packages/database/rollup-database.config.js",
|
||||
"create-bot-whatsapp:rollup": "rollup --config ./packages/create-bot-whatsapp/rollup-create.config.js",
|
||||
"portal:rollup": "rollup --config ./packages/portal/rollup-portal.config.js",
|
||||
"format:check": "prettier --check ./packages",
|
||||
"format:write": "prettier --write ./packages",
|
||||
"fmt.staged": "pretty-quick --staged",
|
||||
"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 && yarn run contexts:rollup && yarn run create-bot-whatsapp:rollup",
|
||||
"build:portal-web": "cd ./packages/portal/ && yarn run build.types && yarn run build.client && yarn run build.server && yarn run lint --fix",
|
||||
"build:full": "yarn run build:portal-web && yarn run cli:rollup && yarn run bot:rollup && yarn run provider:rollup && yarn run database:rollup && yarn run contexts:rollup && yarn run create-bot-whatsapp:rollup && yarn run portal:rollup",
|
||||
"build": "yarn run cli:rollup && yarn run bot:rollup && yarn run provider:rollup && yarn run database:rollup && yarn run contexts:rollup && yarn run create-bot-whatsapp:rollup && yarn run portal:rollup",
|
||||
"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.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": "npm run test.coverage",
|
||||
"cli": "node ./packages/cli/bin/cli.js",
|
||||
"create": "node ./packages/create-bot-whatsapp/bin/create.js",
|
||||
@@ -30,7 +34,7 @@
|
||||
"prepare": "npx husky install",
|
||||
"preinstall": "npx only-allow yarn",
|
||||
"postinstall": "npx prettier --write .",
|
||||
"release": "standard-version -- --prerelease"
|
||||
"release": "standard-version -- --prerelease --global"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/create-bot-whatsapp",
|
||||
@@ -39,6 +43,7 @@
|
||||
"packages/database",
|
||||
"packages/provider",
|
||||
"packages/contexts",
|
||||
"packages/portal",
|
||||
"packages/docs"
|
||||
],
|
||||
"keywords": [
|
||||
@@ -63,6 +68,7 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.3.0",
|
||||
"@commitlint/config-conventional": "^17.3.0",
|
||||
"@octokit/core": "^4.1.0",
|
||||
"@rollup/plugin-commonjs": "^23.0.2",
|
||||
"@rollup/plugin-json": "^5.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
@@ -75,6 +81,7 @@
|
||||
"fs-extra": "^11.1.0",
|
||||
"git-cz": "^4.9.0",
|
||||
"husky": "^8.0.2",
|
||||
"mime-types": "^2.1.35",
|
||||
"only-allow": "^1.1.1",
|
||||
"prettier": "^2.8.0",
|
||||
"pretty-quick": "^3.1.3",
|
||||
|
||||
@@ -8,6 +8,9 @@ const { createWriteStream } = require('fs')
|
||||
const logger = new Console({
|
||||
stdout: createWriteStream(`${process.cwd()}/core.class.log`),
|
||||
})
|
||||
|
||||
const QueuePrincipal = new Queue()
|
||||
|
||||
/**
|
||||
* [ ] Escuchar eventos del provider asegurarte que los provider emitan eventos
|
||||
* [ ] Guardar historial en db
|
||||
@@ -18,10 +21,12 @@ class CoreClass {
|
||||
flowClass
|
||||
databaseClass
|
||||
providerClass
|
||||
constructor(_flow, _database, _provider) {
|
||||
generalArgs = { blackList: [] }
|
||||
constructor(_flow, _database, _provider, _args) {
|
||||
this.flowClass = _flow
|
||||
this.databaseClass = _database
|
||||
this.providerClass = _provider
|
||||
this.generalArgs = { ...this.generalArgs, ..._args }
|
||||
|
||||
for (const { event, func } of this.listenerBusEvents()) {
|
||||
this.providerClass.on(event, func)
|
||||
@@ -38,8 +43,7 @@ class CoreClass {
|
||||
},
|
||||
{
|
||||
event: 'require_action',
|
||||
func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) =>
|
||||
printer(instructions, title),
|
||||
func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) => printer(instructions, title),
|
||||
},
|
||||
{
|
||||
event: 'ready',
|
||||
@@ -47,8 +51,7 @@ class CoreClass {
|
||||
},
|
||||
{
|
||||
event: 'auth_failure',
|
||||
func: ({ instructions }) =>
|
||||
printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'),
|
||||
func: ({ instructions }) => printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'),
|
||||
},
|
||||
|
||||
{
|
||||
@@ -66,14 +69,14 @@ class CoreClass {
|
||||
logger.log(`[handleMsg]: `, messageCtxInComming)
|
||||
const { body, from } = messageCtxInComming
|
||||
let msgToSend = []
|
||||
let endFlowFlag = false
|
||||
let fallBackFlag = false
|
||||
|
||||
if (this.generalArgs.blackList.includes(from)) return
|
||||
if (!body) return
|
||||
if (!body.length) return
|
||||
|
||||
const prevMsg = await this.databaseClass.getPrevByNumber(from)
|
||||
const refToContinue = this.flowClass.findBySerialize(
|
||||
prevMsg?.refSerialize
|
||||
)
|
||||
let prevMsg = await this.databaseClass.getPrevByNumber(from)
|
||||
const refToContinue = this.flowClass.findBySerialize(prevMsg?.refSerialize)
|
||||
|
||||
if (prevMsg?.ref) {
|
||||
const ctxByNumber = toCtx({
|
||||
@@ -84,53 +87,128 @@ class CoreClass {
|
||||
this.databaseClass.save(ctxByNumber)
|
||||
}
|
||||
|
||||
// 📄 Crar CTX de mensaje (uso private)
|
||||
const createCtxMessage = (payload = {}, index = 0) => {
|
||||
const body = typeof payload === 'string' ? payload : payload?.body ?? payload?.answer
|
||||
const media = payload?.media ?? null
|
||||
const buttons = payload?.buttons ?? []
|
||||
const capture = payload?.capture ?? false
|
||||
|
||||
return toCtx({
|
||||
body,
|
||||
from,
|
||||
keyword: null,
|
||||
index,
|
||||
options: { media, buttons, capture },
|
||||
})
|
||||
}
|
||||
|
||||
// 📄 Limpiar cola de procesos
|
||||
const clearQueue = () => {
|
||||
QueuePrincipal.pendingPromise = false
|
||||
QueuePrincipal.queue = []
|
||||
}
|
||||
|
||||
// 📄 Finalizar flujo
|
||||
const endFlow = async (message = null) => {
|
||||
endFlowFlag = true
|
||||
if (message) this.sendProviderAndSave(from, createCtxMessage(message))
|
||||
clearQueue()
|
||||
sendFlow([])
|
||||
return
|
||||
}
|
||||
|
||||
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
|
||||
const sendFlow = async (messageToSend, numberOrId, options = { prev: prevMsg }) => {
|
||||
if (options.prev?.options?.capture) await cbEveryCtx(options.prev?.ref)
|
||||
|
||||
const queue = []
|
||||
for (const ctxMessage of messageToSend) {
|
||||
if (endFlowFlag) return
|
||||
const delayMs = ctxMessage?.options?.delay || 0
|
||||
if (delayMs) await delay(delayMs)
|
||||
QueuePrincipal.enqueue(() =>
|
||||
Promise.all([
|
||||
this.sendProviderAndSave(numberOrId, ctxMessage).then(() => resolveCbEveryCtx(ctxMessage)),
|
||||
])
|
||||
)
|
||||
}
|
||||
return Promise.all(queue)
|
||||
}
|
||||
|
||||
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
|
||||
const fallBack = () => {
|
||||
fallBackFlag = true
|
||||
msgToSend = this.flowClass.find(refToContinue?.keyword, true) || []
|
||||
this.sendFlow(msgToSend, from)
|
||||
return refToContinue
|
||||
const fallBack = async (validation = false, message = null) => {
|
||||
QueuePrincipal.queue = []
|
||||
|
||||
if (validation) {
|
||||
const currentPrev = await this.databaseClass.getPrevByNumber(from)
|
||||
const nextFlow = await this.flowClass.find(refToContinue?.ref, true)
|
||||
const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize)
|
||||
|
||||
return sendFlow(filterNextFlow, from, { prev: undefined })
|
||||
}
|
||||
|
||||
await this.sendProviderAndSave(from, {
|
||||
...prevMsg,
|
||||
answer: typeof message === 'string' ? message : message?.body ?? prevMsg.answer,
|
||||
options: {
|
||||
...prevMsg.options,
|
||||
buttons: prevMsg.options?.buttons,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
|
||||
// para evitar bloque de whatsapp
|
||||
const flowDynamic = (listMsg = [], optListMsg = { limit: 3 }) => {
|
||||
if (!Array.isArray(listMsg))
|
||||
throw new Error('Esto debe ser un ARRAY')
|
||||
|
||||
const parseListMsg = listMsg
|
||||
.map(({ body }, index) =>
|
||||
toCtx({
|
||||
body,
|
||||
from,
|
||||
keyword: null,
|
||||
index,
|
||||
})
|
||||
)
|
||||
.slice(0, optListMsg.limit)
|
||||
msgToSend = parseListMsg
|
||||
this.sendFlow(msgToSend, from)
|
||||
const flowDynamic = async (listMsg = []) => {
|
||||
if (!Array.isArray(listMsg)) listMsg = [listMsg]
|
||||
|
||||
const parseListMsg = listMsg.map((opt, index) => createCtxMessage(opt, index))
|
||||
const currentPrev = await this.databaseClass.getPrevByNumber(from)
|
||||
|
||||
const skipContinueFlow = async () => {
|
||||
const nextFlow = await this.flowClass.find(refToContinue?.ref, true)
|
||||
const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize)
|
||||
const isContinueFlow = filterNextFlow.map((i) => i.keyword).includes(currentPrev?.ref)
|
||||
return {
|
||||
continue: !isContinueFlow,
|
||||
contexts: filterNextFlow,
|
||||
}
|
||||
}
|
||||
|
||||
if (endFlowFlag) return
|
||||
for (const msg of parseListMsg) {
|
||||
await this.sendProviderAndSave(from, msg)
|
||||
}
|
||||
|
||||
const continueFlowData = await skipContinueFlow()
|
||||
|
||||
if (continueFlowData.continue) return sendFlow(continueFlowData.contexts, from, { prev: undefined })
|
||||
return
|
||||
}
|
||||
|
||||
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
|
||||
const resolveCbEveryCtx = async (ctxMessage) => {
|
||||
if (!ctxMessage?.options?.capture) return await cbEveryCtx(ctxMessage?.ref)
|
||||
}
|
||||
|
||||
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo
|
||||
const cbEveryCtx = (inRef) => {
|
||||
this.flowClass.allCallbacks[inRef](messageCtxInComming, {
|
||||
const cbEveryCtx = async (inRef) => {
|
||||
const provider = this.providerClass
|
||||
|
||||
if (!this.flowClass.allCallbacks[inRef]) return Promise.resolve()
|
||||
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
|
||||
provider,
|
||||
fallBack,
|
||||
flowDynamic,
|
||||
endFlow,
|
||||
})
|
||||
}
|
||||
|
||||
// 📄 [options: callback]: Si se tiene un callback se ejecuta
|
||||
if (!fallBackFlag) {
|
||||
if (refToContinue?.options?.capture) cbEveryCtx(refToContinue?.ref)
|
||||
for (const ite of this.flowClass.find(body)) {
|
||||
if (!ite?.options?.capture) cbEveryCtx(ite?.ref)
|
||||
}
|
||||
}
|
||||
|
||||
// 📄🤘(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa
|
||||
if (!fallBackFlag && prevMsg?.options?.nested?.length) {
|
||||
if (!endFlowFlag && prevMsg?.options?.nested?.length) {
|
||||
const nestedRef = prevMsg.options.nested
|
||||
const flowStandalone = nestedRef.map((f) => ({
|
||||
...nestedRef.find((r) => r.refSerialize === f.refSerialize),
|
||||
@@ -138,28 +216,23 @@ class CoreClass {
|
||||
|
||||
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
|
||||
|
||||
for (const ite of msgToSend) {
|
||||
cbEveryCtx(ite?.ref)
|
||||
}
|
||||
|
||||
this.sendFlow(msgToSend, from)
|
||||
sendFlow(msgToSend, from)
|
||||
return
|
||||
}
|
||||
|
||||
// 📄🤘(tiene return) [options: capture (boolean)]: Si se tiene option boolean
|
||||
if (!fallBackFlag && !prevMsg?.options?.nested?.length) {
|
||||
// 📄🤘(tiene return) Si el mensaje previo implementa capture
|
||||
if (!endFlowFlag && !prevMsg?.options?.nested?.length) {
|
||||
const typeCapture = typeof prevMsg?.options?.capture
|
||||
const valueCapture = prevMsg?.options?.capture
|
||||
|
||||
if (['string', 'boolean'].includes(typeCapture) && valueCapture) {
|
||||
if (typeCapture === 'boolean' && fallBackFlag) {
|
||||
msgToSend = this.flowClass.find(refToContinue?.ref, true) || []
|
||||
this.sendFlow(msgToSend, from)
|
||||
sendFlow(msgToSend, from)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
msgToSend = this.flowClass.find(body) || []
|
||||
this.sendFlow(msgToSend, from)
|
||||
sendFlow(msgToSend, from)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,25 +243,13 @@ class CoreClass {
|
||||
*/
|
||||
sendProviderAndSave = (numberOrId, ctxMessage) => {
|
||||
const { answer } = ctxMessage
|
||||
return Promise.all([
|
||||
this.providerClass.sendMessage(numberOrId, answer, ctxMessage),
|
||||
this.databaseClass.save({ ...ctxMessage, from: numberOrId }),
|
||||
])
|
||||
}
|
||||
|
||||
sendFlow = async (messageToSend, numberOrId) => {
|
||||
const queue = []
|
||||
for (const ctxMessage of messageToSend) {
|
||||
const delayMs = ctxMessage?.options?.delay || 0
|
||||
if (delayMs) await delay(delayMs)
|
||||
Queue.enqueue(() =>
|
||||
this.sendProviderAndSave(numberOrId, ctxMessage)
|
||||
)
|
||||
}
|
||||
return Promise.all(queue)
|
||||
return this.providerClass
|
||||
.sendMessage(numberOrId, answer, ctxMessage)
|
||||
.then(() => this.databaseClass.save({ ...ctxMessage, from: numberOrId }))
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @private
|
||||
* @param {*} message
|
||||
* @param {*} ref
|
||||
@@ -201,5 +262,22 @@ class CoreClass {
|
||||
this.continue(null, responde.ref)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Funcion dedicada a enviar el mensaje sin pasar por el flow
|
||||
* (dialogflow)
|
||||
* @param {*} messageToSend
|
||||
* @param {*} numberOrId
|
||||
* @returns
|
||||
*/
|
||||
sendFlowSimple = async (messageToSend, numberOrId) => {
|
||||
const queue = []
|
||||
for (const ctxMessage of messageToSend) {
|
||||
const delayMs = ctxMessage?.options?.delay || 0
|
||||
if (delayMs) await delay(delayMs)
|
||||
QueuePrincipal.enqueue(() => this.sendProviderAndSave(numberOrId, ctxMessage))
|
||||
}
|
||||
return Promise.all(queue)
|
||||
}
|
||||
}
|
||||
module.exports = CoreClass
|
||||
|
||||
@@ -8,8 +8,7 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBot = async ({ flow, database, provider }) =>
|
||||
new CoreClass(flow, database, provider)
|
||||
const createBot = async ({ flow, database, provider }, args = {}) => new CoreClass(flow, database, provider, args)
|
||||
|
||||
/**
|
||||
* Crear instancia de clase Io (Flow)
|
||||
@@ -29,8 +28,7 @@ const createFlow = (args) => {
|
||||
*/
|
||||
const createProvider = (providerClass = class {}, args = null) => {
|
||||
const providerInstance = new providerClass(args)
|
||||
if (!providerClass.prototype instanceof ProviderClass)
|
||||
throw new Error('El provider no implementa ProviderClass')
|
||||
if (!providerClass.prototype instanceof ProviderClass) throw new Error('El provider no implementa ProviderClass')
|
||||
return providerInstance
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,17 @@ class FlowClass {
|
||||
let refSymbol = null
|
||||
overFlow = overFlow ?? this.flowSerialize
|
||||
|
||||
const customRegex = (str = null) => {
|
||||
if (typeof str !== 'string') return
|
||||
const instanceRegex = new RegExp(str)
|
||||
return instanceRegex.test(str)
|
||||
}
|
||||
|
||||
/** Retornar expresion regular para buscar coincidencia */
|
||||
const mapSensitive = (str, flag = false) => {
|
||||
const regexSensitive = flag ? 'g' : 'i'
|
||||
const mapSensitive = (str, mapOptions = { sensitive: false, regex: false }) => {
|
||||
if (mapOptions.regex) return customRegex(str)
|
||||
|
||||
const regexSensitive = mapOptions.sensitive ? 'g' : 'i'
|
||||
if (Array.isArray(str)) {
|
||||
return new RegExp(str.join('|'), regexSensitive)
|
||||
}
|
||||
@@ -36,6 +44,7 @@ class FlowClass {
|
||||
|
||||
const findIn = (keyOrWord, symbol = false, flow = overFlow) => {
|
||||
const sensitive = refSymbol?.options?.sensitive || false
|
||||
const regex = refSymbol?.options?.regex || false
|
||||
capture = refSymbol?.options?.capture || false
|
||||
|
||||
if (capture) return messages
|
||||
@@ -46,7 +55,7 @@ class FlowClass {
|
||||
if (refSymbol?.ref) findIn(refSymbol.ref, true)
|
||||
} else {
|
||||
refSymbol = flow.find((c) => {
|
||||
return mapSensitive(c.keyword, sensitive).test(keyOrWord)
|
||||
return mapSensitive(c.keyword, { sensitive, regex }).test(keyOrWord)
|
||||
})
|
||||
if (refSymbol?.ref) findIn(refSymbol.ref, true)
|
||||
return messages
|
||||
@@ -56,8 +65,7 @@ class FlowClass {
|
||||
return messages
|
||||
}
|
||||
|
||||
findBySerialize = (refSerialize) =>
|
||||
this.flowSerialize.find((r) => r.refSerialize === refSerialize)
|
||||
findBySerialize = (refSerialize) => this.flowSerialize.find((r) => r.refSerialize === refSerialize)
|
||||
|
||||
findIndexByRef = (ref) => this.flowSerialize.findIndex((r) => r.ref === ref)
|
||||
}
|
||||
|
||||
@@ -17,15 +17,10 @@ const addAnswer =
|
||||
* @returns
|
||||
*/
|
||||
const getAnswerOptions = () => ({
|
||||
media:
|
||||
typeof options?.media === 'string' ? `${options?.media}` : null,
|
||||
media: typeof options?.media === 'string' ? `${options?.media}` : null,
|
||||
buttons: Array.isArray(options?.buttons) ? options.buttons : [],
|
||||
capture:
|
||||
typeof options?.capture === 'boolean'
|
||||
? options?.capture
|
||||
: false,
|
||||
child:
|
||||
typeof options?.child === 'string' ? `${options?.child}` : null,
|
||||
capture: typeof options?.capture === 'boolean' ? options?.capture : false,
|
||||
child: typeof options?.child === 'string' ? `${options?.child}` : null,
|
||||
delay: typeof options?.delay === 'number' ? options?.delay : 0,
|
||||
})
|
||||
|
||||
@@ -49,8 +44,7 @@ const addAnswer =
|
||||
* Esta funcion aplana y busca los callback anidados de los hijos
|
||||
* @returns
|
||||
*/
|
||||
const getCbFromNested = () =>
|
||||
flatObject(Array.isArray(nested) ? nested : [nested])
|
||||
const getCbFromNested = () => flatObject(Array.isArray(nested) ? nested : [nested])
|
||||
|
||||
const callback = typeof cb === 'function' ? cb : () => null
|
||||
|
||||
|
||||
@@ -8,12 +8,14 @@ const { toJson } = require('./toJson')
|
||||
* @param {*} options {sensitive:boolean} default false
|
||||
*/
|
||||
const addKeyword = (keyword, options) => {
|
||||
if (typeof keyword !== 'string' && !Array.isArray(keyword)) {
|
||||
throw new Error('DEBE_SER_STRING_ARRAY_REGEX')
|
||||
}
|
||||
|
||||
const parseOptions = () => {
|
||||
const defaultProperties = {
|
||||
sensitive:
|
||||
typeof options?.sensitive === 'boolean'
|
||||
? options?.sensitive
|
||||
: false,
|
||||
sensitive: typeof options?.sensitive === 'boolean' ? options?.sensitive : false,
|
||||
regex: typeof options?.regex === 'boolean' ? options?.regex : false,
|
||||
}
|
||||
|
||||
return defaultProperties
|
||||
|
||||
@@ -5,12 +5,12 @@ const { generateRef, generateRefSerialize } = require('../../utils/hash')
|
||||
* @param options {media:string, buttons:[], capture:true default false}
|
||||
* @returns
|
||||
*/
|
||||
const toCtx = ({ body, from, prevRef, index }) => {
|
||||
const toCtx = ({ body, from, prevRef, options = {}, index }) => {
|
||||
return {
|
||||
ref: generateRef(),
|
||||
keyword: prevRef,
|
||||
answer: body,
|
||||
options: {},
|
||||
options: options ?? {},
|
||||
from,
|
||||
refSerialize: generateRefSerialize({ index, answer: body }),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/bot",
|
||||
"version": "0.0.29-alpha.0",
|
||||
"version": "0.0.96-alpha.0",
|
||||
"description": "",
|
||||
"main": "./lib/bundle.bot.cjs",
|
||||
"scripts": {
|
||||
@@ -28,5 +28,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.0.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codigoencasa/bot-whatsapp/tree/main/packages/bot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ class ProviderClass extends EventEmitter {
|
||||
*/
|
||||
|
||||
sendMessage = async (userId, message) => {
|
||||
if (NODE_ENV !== 'production')
|
||||
console.log('[sendMessage]', { userId, message })
|
||||
if (NODE_ENV !== 'production') console.log('[sendMessage]', { userId, message })
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ module.exports = [
|
||||
banner: banner['banner.output'].join(''),
|
||||
file: join(__dirname, 'lib', 'bundle.bot.cjs'),
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: [commonjs(), nodeResolve()],
|
||||
},
|
||||
|
||||
@@ -2,13 +2,7 @@ const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const FlowClass = require('../io/flow.class')
|
||||
const MockProvider = require('../../../__mocks__/mock.provider')
|
||||
const {
|
||||
createBot,
|
||||
CoreClass,
|
||||
createFlow,
|
||||
createProvider,
|
||||
ProviderClass,
|
||||
} = require('../index')
|
||||
const { createBot, CoreClass, createFlow, createProvider, ProviderClass } = require('../index')
|
||||
|
||||
class MockFlow {
|
||||
allCallbacks = { ref: () => 1 }
|
||||
@@ -100,20 +94,13 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => {
|
||||
await createBot(setting)
|
||||
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -121,21 +108,12 @@ test(`[Bot] Eventos 'require_action,ready,auth_failure,message '`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
@@ -166,20 +144,13 @@ test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
await createBot(setting)
|
||||
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -187,21 +158,12 @@ test(`[Bot] Probando Flujos Internos`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
@@ -234,20 +196,13 @@ test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
botInstance.sendProviderAndSave('xxxxx', 'xxxxx')
|
||||
botInstance.continue('xxxxx', 'xxxxx')
|
||||
/// Escuchamos eventos
|
||||
mockProvider.on(
|
||||
'require_action',
|
||||
(r) => (responseEvents['require_action'] = r)
|
||||
)
|
||||
mockProvider.on('require_action', (r) => (responseEvents['require_action'] = r))
|
||||
mockProvider.on('ready', (r) => (responseEvents['ready'] = r))
|
||||
mockProvider.on('auth_failure', (r) => (responseEvents['auth_failure'] = r))
|
||||
mockProvider.on('message', (r) => (responseEvents['message'] = r))
|
||||
|
||||
/// Emitimos eventos
|
||||
mockProvider.delaySendMessage(
|
||||
0,
|
||||
'require_action',
|
||||
MOCK_EVENTS.require_action
|
||||
)
|
||||
mockProvider.delaySendMessage(0, 'require_action', MOCK_EVENTS.require_action)
|
||||
mockProvider.delaySendMessage(0, 'ready', MOCK_EVENTS.ready)
|
||||
mockProvider.delaySendMessage(0, 'auth_failure', MOCK_EVENTS.auth_failure)
|
||||
mockProvider.delaySendMessage(0, 'message', MOCK_EVENTS.message)
|
||||
@@ -255,21 +210,12 @@ test(`[Bot] Probando Flujos Nested`, async () => {
|
||||
await delay(0)
|
||||
|
||||
/// Testeamos eventos
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.require_action),
|
||||
JSON.stringify(MOCK_EVENTS.require_action)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.require_action), JSON.stringify(MOCK_EVENTS.require_action))
|
||||
assert.is(responseEvents.ready, MOCK_EVENTS.ready)
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.auth_failure),
|
||||
JSON.stringify(MOCK_EVENTS.auth_failure)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.auth_failure), JSON.stringify(MOCK_EVENTS.auth_failure))
|
||||
|
||||
assert.is(
|
||||
JSON.stringify(responseEvents.message),
|
||||
JSON.stringify(MOCK_EVENTS.message)
|
||||
)
|
||||
assert.is(JSON.stringify(responseEvents.message), JSON.stringify(MOCK_EVENTS.message))
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
||||
28
packages/bot/tests/flow.class.test.js
Normal file
28
packages/bot/tests/flow.class.test.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const { test } = require('uvu')
|
||||
const assert = require('uvu/assert')
|
||||
const FlowClass = require('../io/flow.class')
|
||||
const { addKeyword } = require('../index')
|
||||
|
||||
test(`[FlowClass] Probando instanciamiento de clase`, async () => {
|
||||
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
|
||||
const flowClass = new FlowClass([MOCK_FLOW])
|
||||
assert.is(flowClass instanceof FlowClass, true)
|
||||
})
|
||||
|
||||
test(`[FlowClass] Probando find`, async () => {
|
||||
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
|
||||
const flowClass = new FlowClass([MOCK_FLOW])
|
||||
|
||||
flowClass.find('hola')
|
||||
assert.is(flowClass instanceof FlowClass, true)
|
||||
})
|
||||
|
||||
test(`[FlowClass] Probando findBySerialize`, async () => {
|
||||
const MOCK_FLOW = addKeyword('hola').addAnswer('Buenas!')
|
||||
const flowClass = new FlowClass([MOCK_FLOW])
|
||||
|
||||
flowClass.findBySerialize('')
|
||||
assert.is(flowClass instanceof FlowClass, true)
|
||||
})
|
||||
|
||||
test.run()
|
||||
@@ -35,10 +35,7 @@ test('Debere probar toSerialize', () => {
|
||||
const ARRANGE = {
|
||||
keyword: ['hola!', 'ole'],
|
||||
}
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword)
|
||||
.addAnswer('Segundo!')
|
||||
.addAnswer('Segundo!')
|
||||
.toJson()
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer('Segundo!').addAnswer('Segundo!').toJson()
|
||||
|
||||
const [ANSWER_A] = MAIN_CTX
|
||||
|
||||
@@ -71,9 +68,7 @@ test('Debere probar la anidación', () => {
|
||||
answer_A: 'Bienvenido',
|
||||
answer_B: 'Continuar',
|
||||
}
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword)
|
||||
.addAnswer(ARRANGE.answer_A)
|
||||
.addAnswer(ARRANGE.answer_B)
|
||||
const MAIN_CTX = addKeyword(ARRANGE.keyword).addAnswer(ARRANGE.answer_A).addAnswer(ARRANGE.answer_B)
|
||||
|
||||
assert.is(MAIN_CTX.ctx.answer, ARRANGE.answer_B)
|
||||
})
|
||||
@@ -107,10 +102,7 @@ test('Debere probar error las addAnswer', () => {
|
||||
})
|
||||
|
||||
test('Obtener toJson', () => {
|
||||
const [ctxA, ctxB, ctxC] = addKeyword('hola')
|
||||
.addAnswer('pera!')
|
||||
.addAnswer('chao')
|
||||
.toJson()
|
||||
const [ctxA, ctxB, ctxC] = addKeyword('hola').addAnswer('pera!').addAnswer('chao').toJson()
|
||||
|
||||
assert.is(ctxA.keyword, 'hola')
|
||||
assert.match(ctxA.ref, /^key_/)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const delay = (miliseconds) =>
|
||||
new Promise((res) => setTimeout(res, miliseconds))
|
||||
const delay = (miliseconds) => new Promise((res) => setTimeout(res, miliseconds))
|
||||
|
||||
module.exports = { delay }
|
||||
|
||||
@@ -3,9 +3,7 @@ const flatObject = (listArray = []) => {
|
||||
|
||||
if (!listArray.length) return {}
|
||||
|
||||
const cbNestedObj = cbNestedList
|
||||
.map(({ ctx }) => ctx?.callbacks)
|
||||
.filter((i) => !!i)
|
||||
const cbNestedObj = cbNestedList.map(({ ctx }) => ctx?.callbacks).filter((i) => !!i)
|
||||
const queueCb = cbNestedObj.reduce((acc, current) => {
|
||||
const getKeys = Object.keys(current)
|
||||
const parse = getKeys.map((icb, i) => ({
|
||||
|
||||
@@ -16,9 +16,6 @@ const generateRef = (prefix = false) => {
|
||||
* @returns
|
||||
*/
|
||||
const generateRefSerialize = ({ index, answer, keyword }) =>
|
||||
crypto
|
||||
.createHash('md5')
|
||||
.update(JSON.stringify({ index, answer, keyword }))
|
||||
.digest('hex')
|
||||
crypto.createHash('md5').update(JSON.stringify({ index, answer, keyword })).digest('hex')
|
||||
|
||||
module.exports = { generateRef, generateRefSerialize }
|
||||
|
||||
@@ -4,9 +4,7 @@ const printer = (message, title) => {
|
||||
if (NODE_ENV !== 'test') {
|
||||
// console.clear()
|
||||
if (title) console.log(bgRed(`${title}`))
|
||||
console.log(
|
||||
yellow(Array.isArray(message) ? message.join('\n') : message)
|
||||
)
|
||||
console.log(yellow(Array.isArray(message) ? message.join('\n') : message))
|
||||
console.log(``)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class Queue {
|
||||
static queue = []
|
||||
static pendingPromise = false
|
||||
queue = []
|
||||
pendingPromise = false
|
||||
|
||||
static enqueue(promise) {
|
||||
enqueue(promise) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.queue.push({
|
||||
promise,
|
||||
@@ -13,7 +13,7 @@ class Queue {
|
||||
})
|
||||
}
|
||||
|
||||
static dequeue() {
|
||||
dequeue() {
|
||||
if (this.workingOnPromise) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,38 +1,59 @@
|
||||
const { red, yellow, green, bgCyan } = require('kleur')
|
||||
const { exec } = require('node:child_process')
|
||||
|
||||
const checkNodeVersion = () => {
|
||||
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(
|
||||
`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`
|
||||
)
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(green(`Node.js compatible ${version}`))
|
||||
console.log(``)
|
||||
return new Promise((resolve, reject) => {
|
||||
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(`🔴 Se require Node.js 16 o superior. Actualmente esta ejecutando Node.js ${version}`))
|
||||
console.log(``)
|
||||
reject('ERROR_NODE')
|
||||
}
|
||||
console.log(green(`Node.js: ${version} compatible ✅`))
|
||||
console.log(``)
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
const checkOs = () => {
|
||||
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 configuración adicional referente al puppeteer`,
|
||||
``,
|
||||
`Recuerda pasar por el WIKI`,
|
||||
`🔗 https://github.com/leifermendez/bot-whatsapp/wiki/Instalación`,
|
||||
``,
|
||||
]
|
||||
return new Promise((resolve) => {
|
||||
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 configuración adicional referente al puppeteer`,
|
||||
``,
|
||||
`Recuerda pasar por el WIKI`,
|
||||
`🔗 https://github.com/leifermendez/bot-whatsapp/wiki/Instalación`,
|
||||
``,
|
||||
]
|
||||
|
||||
console.log(yellow(messages.join(' \n')))
|
||||
}
|
||||
|
||||
console.log(``)
|
||||
console.log(yellow(messages.join(' \n')))
|
||||
}
|
||||
console.log(green(`OS: compatible ✅`))
|
||||
console.log(``)
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { checkNodeVersion, checkOs }
|
||||
const checkGit = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(bgCyan('🤓 Revisando GIT'))
|
||||
exec('git --version', (error) => {
|
||||
if (error) {
|
||||
console.error(red(`🔴 Se require instalar GIT`))
|
||||
console.log(``)
|
||||
reject('ERROR_GIT')
|
||||
} else {
|
||||
console.log(green(`Git: Compatible ✅`))
|
||||
console.log(``)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { checkNodeVersion, checkOs, checkGit }
|
||||
|
||||
@@ -2,10 +2,7 @@ const rimraf = require('rimraf')
|
||||
const { yellow } = require('kleur')
|
||||
const { join } = require('path')
|
||||
|
||||
const PATH_WW = [
|
||||
join(process.cwd(), '.wwebjs_auth'),
|
||||
join(process.cwd(), 'session.json'),
|
||||
]
|
||||
const PATH_WW = [join(process.cwd(), '.wwebjs_auth'), join(process.cwd(), 'session.json')]
|
||||
|
||||
const cleanSession = () => {
|
||||
const queue = []
|
||||
|
||||
@@ -23,11 +23,7 @@ const JSON_TEMPLATE = {
|
||||
const PATH_CONFIG = join(process.cwd(), 'config.json')
|
||||
|
||||
const jsonConfig = () => {
|
||||
return writeFile(
|
||||
PATH_CONFIG,
|
||||
JSON.stringify(JSON_TEMPLATE, null, 2),
|
||||
'utf-8'
|
||||
)
|
||||
return writeFile(PATH_CONFIG, JSON.stringify(JSON_TEMPLATE, null, 2), 'utf-8')
|
||||
}
|
||||
|
||||
module.exports = { jsonConfig }
|
||||
|
||||
@@ -20,13 +20,9 @@ const installDeps = (pkgManager, packageList) => {
|
||||
const installSingle = (pkgInstall) => () => {
|
||||
new Promise((resolve) => {
|
||||
try {
|
||||
childProcess = spawn(
|
||||
pkgManager,
|
||||
[PKG_OPTION[pkgManager], pkgInstall],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
}
|
||||
)
|
||||
childProcess = spawn(pkgManager, [PKG_OPTION[pkgManager], pkgInstall], {
|
||||
stdio: 'inherit',
|
||||
})
|
||||
|
||||
childProcess.on('error', (e) => {
|
||||
console.error(e)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const prompts = require('prompts')
|
||||
const { join } = require('path')
|
||||
const { yellow, red, cyan, bgMagenta } = require('kleur')
|
||||
const { yellow, red, cyan, bgMagenta, bgRed } = require('kleur')
|
||||
const { existsSync } = require('fs')
|
||||
const { copyBaseApp } = require('../create-app')
|
||||
const { checkNodeVersion, checkOs } = require('../check')
|
||||
const { checkNodeVersion, checkOs, checkGit } = require('../check')
|
||||
|
||||
const bannerDone = () => {
|
||||
console.log(``)
|
||||
@@ -21,6 +21,20 @@ const bannerDone = () => {
|
||||
}
|
||||
|
||||
const startInteractive = async () => {
|
||||
try {
|
||||
console.clear()
|
||||
await checkNodeVersion()
|
||||
checkOs()
|
||||
await checkGit()
|
||||
console.clear()
|
||||
await nextSteps()
|
||||
} catch (e) {
|
||||
console.error(bgRed(`Ups! 🙄 algo no va bien.`))
|
||||
console.error(bgRed(`Revisa los requerimientos minimos en la documentacion`))
|
||||
}
|
||||
}
|
||||
|
||||
const nextSteps = async () => {
|
||||
const questions = [
|
||||
{
|
||||
type: 'text',
|
||||
@@ -32,11 +46,11 @@ const startInteractive = async () => {
|
||||
name: 'providerWs',
|
||||
message: '¿Cuál proveedor de whatsapp quieres utilizar?',
|
||||
choices: [
|
||||
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
|
||||
{ title: 'Venom (gratis)', value: 'venom' },
|
||||
{ title: 'Baileys (gratis)', value: 'baileys' },
|
||||
{ title: 'Venom (gratis)', value: 'venom' },
|
||||
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
|
||||
{ title: 'Twilio', value: 'twilio' },
|
||||
{ title: 'API Oficial (Meta)', value: 'meta' },
|
||||
{ title: 'Meta', value: 'meta' },
|
||||
],
|
||||
max: 1,
|
||||
hint: 'Espacio para seleccionar',
|
||||
@@ -58,9 +72,6 @@ const startInteractive = async () => {
|
||||
},
|
||||
]
|
||||
|
||||
console.clear()
|
||||
checkNodeVersion()
|
||||
checkOs()
|
||||
const onCancel = () => {
|
||||
console.log('¡Proceso cancelado!')
|
||||
return true
|
||||
@@ -69,8 +80,7 @@ const startInteractive = async () => {
|
||||
const { outDir = '', providerDb = [], providerWs = [] } = response
|
||||
|
||||
const createApp = async (templateName = null) => {
|
||||
if (!templateName)
|
||||
throw new Error('TEMPLATE_NAME_INVALID: ', templateName)
|
||||
if (!templateName) throw new Error('TEMPLATE_NAME_INVALID: ', templateName)
|
||||
|
||||
const possiblesPath = [
|
||||
join(__dirname, '..', '..', 'starters', 'apps', templateName),
|
||||
@@ -102,11 +112,7 @@ const startInteractive = async () => {
|
||||
const vendorProvider = async () => {
|
||||
const [answer] = providerWs
|
||||
if (!providerWs.length) {
|
||||
console.log(
|
||||
red(
|
||||
`Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar`
|
||||
)
|
||||
)
|
||||
console.log(red(`Debes seleccionar un proveedor de whatsapp. Tecla [Space] para seleccionar`))
|
||||
process.exit(1)
|
||||
}
|
||||
return answer
|
||||
@@ -119,11 +125,7 @@ const startInteractive = async () => {
|
||||
const dbProvider = async () => {
|
||||
const [answer] = providerDb
|
||||
if (!providerDb.length) {
|
||||
console.log(
|
||||
red(
|
||||
`Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar`
|
||||
)
|
||||
)
|
||||
console.log(red(`Debes seleccionar un proveedor de base de datos. Tecla [Space] para seleccionar`))
|
||||
process.exit(1)
|
||||
}
|
||||
return answer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/cli",
|
||||
"version": "0.0.36-alpha.0",
|
||||
"version": "0.0.72-alpha.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
@@ -15,5 +15,9 @@
|
||||
],
|
||||
"bin": {
|
||||
"bot": "./bin/cli.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codigoencasa/bot-whatsapp/tree/main/packages/cli"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/contexts",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.16-alpha.0",
|
||||
"description": "",
|
||||
"main": "./lib/bundle.contexts.cjs",
|
||||
"files": [
|
||||
@@ -13,5 +13,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@bot-whatsapp/bot": "*"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codigoencasa/bot-whatsapp/tree/main/packages/contexts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,8 @@ class DialogFlowCXContext extends CoreClass {
|
||||
* */
|
||||
}
|
||||
|
||||
if (!this.optionsDX.location.length)
|
||||
throw new Error('LOCATION_NO_ENCONTRADO')
|
||||
if (!this.optionsDX.agentId.length)
|
||||
throw new Error('AGENTID_NO_ENCONTRADO')
|
||||
if (!this.optionsDX.location.length) throw new Error('LOCATION_NO_ENCONTRADO')
|
||||
if (!this.optionsDX.agentId.length) throw new Error('AGENTID_NO_ENCONTRADO')
|
||||
|
||||
const rawJson = readFileSync(GOOGLE_ACCOUNT_PATH, 'utf-8')
|
||||
const { project_id, private_key, client_email } = JSON.parse(rawJson)
|
||||
@@ -86,9 +84,7 @@ class DialogFlowCXContext extends CoreClass {
|
||||
},
|
||||
}
|
||||
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [
|
||||
null,
|
||||
]
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null]
|
||||
|
||||
const listMessages = single.queryResult.responseMessages.map((res) => {
|
||||
if (res.message == 'text') {
|
||||
@@ -96,17 +92,11 @@ class DialogFlowCXContext extends CoreClass {
|
||||
}
|
||||
|
||||
if (res.message == 'payload') {
|
||||
const {
|
||||
media = null,
|
||||
buttons = [],
|
||||
answer = '',
|
||||
} = res.payload.fields
|
||||
const buttonsArray = buttons?.listValue?.values?.map(
|
||||
(btnValue) => {
|
||||
const { stringValue } = btnValue.structValue.fields.body
|
||||
return { body: stringValue }
|
||||
}
|
||||
)
|
||||
const { media = null, buttons = [], answer = '' } = res.payload.fields
|
||||
const buttonsArray = buttons?.listValue?.values?.map((btnValue) => {
|
||||
const { stringValue } = btnValue.structValue.fields.body
|
||||
return { body: stringValue }
|
||||
})
|
||||
return {
|
||||
answer: answer?.stringValue,
|
||||
options: {
|
||||
@@ -117,7 +107,7 @@ class DialogFlowCXContext extends CoreClass {
|
||||
}
|
||||
})
|
||||
|
||||
this.sendFlow(listMessages, from)
|
||||
this.sendFlowSimple(listMessages, from)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ const DialogCXFlowClass = require('./dialogflow-cx.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotDialog = async ({ database, provider }, _options) =>
|
||||
new DialogCXFlowClass(database, provider, _options)
|
||||
const createBotDialog = async ({ database, provider }, _options) => new DialogCXFlowClass(database, provider, _options)
|
||||
|
||||
module.exports = {
|
||||
createBotDialog,
|
||||
|
||||
@@ -65,10 +65,7 @@ class DialogFlowContext extends CoreClass {
|
||||
* para evitar este problema.
|
||||
* https://github.com/codigoencasa/bot-whatsapp/pull/140
|
||||
*/
|
||||
const session = this.sessionClient.projectAgentSessionPath(
|
||||
this.projectId,
|
||||
from
|
||||
)
|
||||
const session = this.sessionClient.projectAgentSessionPath(this.projectId, from)
|
||||
const reqDialog = {
|
||||
session,
|
||||
queryInput: {
|
||||
@@ -79,15 +76,11 @@ class DialogFlowContext extends CoreClass {
|
||||
},
|
||||
}
|
||||
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [
|
||||
null,
|
||||
]
|
||||
const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [null]
|
||||
|
||||
const { queryResult } = single
|
||||
|
||||
const msgPayload = queryResult?.fulfillmentMessages?.find(
|
||||
(a) => a.message === 'payload'
|
||||
)
|
||||
const msgPayload = queryResult?.fulfillmentMessages?.find((a) => a.message === 'payload')
|
||||
|
||||
// Revisamos si el dialogFlow tiene multimedia
|
||||
if (msgPayload && msgPayload?.payload) {
|
||||
@@ -97,17 +90,25 @@ class DialogFlowContext extends CoreClass {
|
||||
})
|
||||
|
||||
customPayload = {
|
||||
media: fields?.media?.stringValue,
|
||||
buttons: mapButtons,
|
||||
options: {
|
||||
media: fields?.media?.stringValue,
|
||||
buttons: mapButtons,
|
||||
},
|
||||
}
|
||||
|
||||
const ctxFromDX = {
|
||||
...customPayload,
|
||||
answer: fields?.answer?.stringValue,
|
||||
}
|
||||
this.sendFlowSimple([ctxFromDX], from)
|
||||
return
|
||||
}
|
||||
|
||||
const ctxFromDX = {
|
||||
...customPayload,
|
||||
answer: queryResult?.fulfillmentText,
|
||||
}
|
||||
|
||||
this.sendFlow([ctxFromDX], from)
|
||||
this.sendFlowSimple([ctxFromDX], from)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ const DialogFlowClass = require('./dialogflow.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotDialog = async ({ database, provider }) =>
|
||||
new DialogFlowClass(database, provider)
|
||||
const createBotDialog = async ({ database, provider }) => new DialogFlowClass(database, provider)
|
||||
|
||||
module.exports = {
|
||||
createBotDialog,
|
||||
|
||||
@@ -5,8 +5,7 @@ const MockClass = require('./mock.class')
|
||||
* @param {*} args
|
||||
* @returns
|
||||
*/
|
||||
const createBotMock = async ({ database, provider }) =>
|
||||
new MockClass(database, provider)
|
||||
const createBotMock = async ({ database, provider }) => new MockClass(database, provider)
|
||||
|
||||
module.exports = {
|
||||
createBotMock,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-bot-whatsapp",
|
||||
"version": "0.0.47-alpha.0",
|
||||
"version": "0.0.93-alpha.0",
|
||||
"description": "",
|
||||
"main": "./lib/bundle.create-bot-whatsapp.cjs",
|
||||
"files": [
|
||||
@@ -11,5 +11,9 @@
|
||||
"bin": "./bin/create.js",
|
||||
"dependencies": {
|
||||
"@bot-whatsapp/cli": "*"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codigoencasa/bot-whatsapp/tree/main/packages/create-bot-whatsapp"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bot-whatsapp/database",
|
||||
"version": "0.0.28-alpha.0",
|
||||
"version": "0.0.64-alpha.0",
|
||||
"description": "Esto es el conector a mysql, pg, mongo",
|
||||
"main": "./lib/mock/index.cjs",
|
||||
"keywords": [],
|
||||
@@ -19,5 +19,9 @@
|
||||
"./mongo": "./lib/mongo/index.cjs",
|
||||
"./json": "./lib/json/index.cjs",
|
||||
"./mysql": "./lib/mysql/index.cjs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codigoencasa/bot-whatsapp/tree/main/packages/database"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ class MockDatabase {
|
||||
constructor() {}
|
||||
|
||||
getPrevByNumber = (from) => {
|
||||
const history = this.listHistory.slice().reverse()
|
||||
const history = this.listHistory
|
||||
.slice()
|
||||
.reverse()
|
||||
.filter((i) => !!i.keyword)
|
||||
return history.find((a) => a.from === from)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,7 @@ class MongoAdapter {
|
||||
}
|
||||
|
||||
getPrevByNumber = async (from) => {
|
||||
const result = await this.db
|
||||
.collection('history')
|
||||
.find({ from })
|
||||
.sort({ _id: -1 })
|
||||
.limit(1)
|
||||
.toArray()
|
||||
const result = await this.db.collection('history').find({ from }).sort({ _id: -1 }).limit(1).toArray()
|
||||
return result[0]
|
||||
}
|
||||
|
||||
|
||||
@@ -46,18 +46,8 @@ class MyslAdapter {
|
||||
})
|
||||
|
||||
save = (ctx) => {
|
||||
const values = [
|
||||
[
|
||||
ctx.ref,
|
||||
ctx.keyword,
|
||||
ctx.answer,
|
||||
ctx.refSerialize,
|
||||
ctx.from,
|
||||
JSON.stringify(ctx.options),
|
||||
],
|
||||
]
|
||||
const sql =
|
||||
'INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?'
|
||||
const values = [[ctx.ref, ctx.keyword, ctx.answer, ctx.refSerialize, ctx.from, JSON.stringify(ctx.options)]]
|
||||
const sql = 'INSERT INTO history (ref, keyword, answer, refSerialize, phone, options ) values ?'
|
||||
|
||||
this.db.query(sql, [values], (err) => {
|
||||
if (err) throw err
|
||||
@@ -71,14 +61,14 @@ class MyslAdapter {
|
||||
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
|
||||
)`
|
||||
(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)
|
||||
CHARACTER SET utf8mb4 COLLATE utf8mb4_General_ci`
|
||||
|
||||
this.db.query(sql, (err) => {
|
||||
if (err) throw err
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
font-family: IBMPlexMono-Regular;
|
||||
src: url(IBMPlexMono-Regular-subset.woff2) format('woff2'),
|
||||
url(IBMPlexMono-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58,
|
||||
U+61-65, U+67-69, U+6C-76;
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-43, U+46, U+49, U+4B-4F, U+53-55, U+58, U+61-65, U+67-69, U+6C-76;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
font-family: IBMPlexMono-SemiBold;
|
||||
src: url(IBMPlexMono-SemiBold-subset.woff2) format('woff2'),
|
||||
url(IBMPlexMono-SemiBold-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47,
|
||||
U+4E, U+4F, U+52-55, U+57, U+59, U+65, U+68, U+6F, U+72, U+74;
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+38, U+39, U+41, U+42, U+44, U+47, U+4E, U+4F, U+52-55, U+57, U+59, U+65,
|
||||
U+68, U+6F, U+72, U+74;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
@font-face {
|
||||
font-family: Pally-Variable;
|
||||
src: url(Pally-Variable-subset.woff2) format('woff2'),
|
||||
url(Pally-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46,
|
||||
U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69, U+6B-77, U+79;
|
||||
src: url(Pally-Variable-subset.woff2) format('woff2'), url(Pally-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+39, U+41-43, U+46, U+49-4D, U+53, U+55, U+58, U+61-65, U+67-69,
|
||||
U+6B-77, U+79;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
font-family: SourceSerifPro-Regular;
|
||||
src: url(SourceSerifPro-Regular-subset.woff2) format('woff2'),
|
||||
url(SourceSerifPro-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55,
|
||||
U+61-65, U+67-69, U+6B-76, U+79;
|
||||
unicode-range: U+20, U+2C, U+2E, U+41-44, U+49, U+4A, U+4C, U+53, U+55, U+61-65, U+67-69, U+6B-76, U+79;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
@font-face {
|
||||
font-family: Synonym-Variable;
|
||||
src: url(Synonym-Variable-subset.woff2) format('woff2'),
|
||||
url(Synonym-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47,
|
||||
U+49, U+4B-4F, U+53-55, U+57-59, U+61, U+63-65, U+67-69, U+6C-76;
|
||||
src: url(Synonym-Variable-subset.woff2) format('woff2'), url(Synonym-Variable-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2C, U+2E, U+30, U+33, U+35, U+41-44, U+46, U+47, U+49, U+4B-4F, U+53-55, U+57-59, U+61,
|
||||
U+63-65, U+67-69, U+6C-76;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: TenorSans-Regular;
|
||||
src: url(TenorSans-Regular-subset.woff2) format('woff2'),
|
||||
url(TenorSans-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54,
|
||||
U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F, U+72-75, U+79;
|
||||
src: url(TenorSans-Regular-subset.woff2) format('woff2'), url(TenorSans-Regular-subset.zopfli.woff) format('woff');
|
||||
unicode-range: U+20, U+24, U+2E, U+30, U+36, U+46, U+49, U+4A, U+53, U+54, U+61, U+63, U+65, U+69, U+6B, U+6E, U+6F,
|
||||
U+72-75, U+79;
|
||||
}
|
||||
|
||||
BIN
packages/docs/src/assets/images/digital-ocean.png
Normal file
BIN
packages/docs/src/assets/images/digital-ocean.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.0 KiB |
189
packages/docs/src/components/atoms/DigitalOcean.tsx
Normal file
189
packages/docs/src/components/atoms/DigitalOcean.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
export const DigitalOcean = () => (
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 604 129"
|
||||
style="enable-background:new 0 0 604 129;"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
class="st0"
|
||||
d="M174.3,3c4.9,0,8.7,2.9,8.7,8.6c0,5.6-3.8,8.5-8.7,8.5h-7.6v11.1h-3.5V3H174.3z M166.7,17.1h7.2
|
||||
c3,0,5.6-1.8,5.6-5.5c0-3.8-2.5-5.5-5.6-5.5h-7.2V17.1z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M208.8,21.7c0,6.1-4.3,10-9.9,10c-5.6,0-9.9-3.9-9.9-10c0-6.1,4.3-10,9.9-10
|
||||
C204.5,11.7,208.8,15.6,208.8,21.7z M192.3,21.7c0,4.5,2.9,7.2,6.6,7.2c3.7,0,6.6-2.7,6.6-7.2c0-4.5-2.9-7.1-6.6-7.1
|
||||
C195.2,14.5,192.3,17.2,192.3,21.7z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M234.4,31.3l-5.2-13.8L224,31.3h-2.6L214.1,12h3.6l5.2,14l5.2-14h2.3l5.3,14l5.2-14h3.5L237,31.3H234.4z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M253,22.9c0.2,3.7,2.6,5.9,6,5.9c2.8,0,4.8-1.3,5.4-3.4l3.2,0.2c-0.8,3.5-4.1,6.1-8.6,6.1
|
||||
c-5.5,0-9.6-3.7-9.6-10c0-6.3,4-10,9.5-10c5.5,0,8.8,3.7,8.8,9.4v1.8H253z M253,20.3h11.6c-0.1-3.4-2-5.7-5.6-5.7
|
||||
C255.6,14.5,253.2,16.5,253,20.3z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M285.4,14.9c-3.4,0-5.6,2.3-5.6,5.3v11.1h-3.2V12h3.2v2.9c0.7-1.6,2.5-3.1,5.7-3.1V14.9z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M294.7,22.9c0.2,3.7,2.6,5.9,6,5.9c2.8,0,4.8-1.3,5.4-3.4l3.2,0.2c-0.8,3.5-4.1,6.1-8.6,6.1
|
||||
c-5.5,0-9.6-3.7-9.6-10c0-6.3,4-10,9.5-10c5.5,0,8.8,3.7,8.8,9.4v1.8H294.7z M294.7,20.3h11.6c-0.1-3.4-2-5.7-5.6-5.7
|
||||
C297.4,14.5,294.9,16.5,294.7,20.3z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M333.1,31.3v-3.1c-1.1,2-3.6,3.5-6.8,3.5c-5.3,0-9.3-3.8-9.3-10c0-6.2,4-10,9.3-10c3.2,0,5.6,1.4,6.6,3.2V2
|
||||
h3.2v29.4H333.1z M320.3,21.7c0,4.6,2.8,7.2,6.5,7.2c3.6,0,6.2-2.2,6.2-6.6v-1.1c0-4.3-2.6-6.6-6.2-6.6
|
||||
C323.1,14.5,320.3,17.1,320.3,21.7z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M361.8,14.9c1.1-1.9,3.4-3.2,6.7-3.2c5.3,0,9.3,3.8,9.3,10c0,6.2-4,10-9.3,10c-3.3,0-5.7-1.5-6.8-3.5v3.1
|
||||
h-3.1V2h3.2V14.9z M361.9,21.1v1.1c0,4.4,2.6,6.6,6.2,6.6c3.7,0,6.5-2.5,6.5-7.2c0-4.6-2.8-7.1-6.5-7.1
|
||||
C364.5,14.5,361.9,16.8,361.9,21.1z"
|
||||
/>
|
||||
<path class="st0" d="M386.3,40.9l4.6-10.7L383.2,12h3.6l5.8,14.5l5.8-14.5h3.6l-12.2,28.9H386.3z" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="XMLID_2369_">
|
||||
<g>
|
||||
<g id="XMLID_281_">
|
||||
<g id="XMLID_282_">
|
||||
<g>
|
||||
<g id="XMLID_283_">
|
||||
<g id="XMLID_287_">
|
||||
<path
|
||||
id="XMLID_288_"
|
||||
class="st0"
|
||||
d="M64.4,127l0-24.2c25.6,0,45.5-25.4,35.7-52.3c-3.6-10-11.6-17.9-21.6-21.6
|
||||
c-27-9.8-52.3,10-52.3,35.7c0,0,0,0,0,0L2,64.7C2,23.8,41.5-8,84.3,5.4c18.7,5.8,33.6,20.7,39.4,39.4
|
||||
C137,87.6,105.2,127,64.4,127z"
|
||||
/>
|
||||
</g>
|
||||
<polygon
|
||||
id="XMLID_286_"
|
||||
class="st1"
|
||||
points="64.4,102.9 40.4,102.9 40.4,78.9 40.4,78.9 64.4,78.9 64.4,78.9 "
|
||||
/>
|
||||
<polygon
|
||||
id="XMLID_285_"
|
||||
class="st1"
|
||||
points="40.3,121.5 21.8,121.5 21.8,121.5 21.8,102.9 40.4,102.9 40.4,121.5 "
|
||||
/>
|
||||
<path
|
||||
id="XMLID_284_"
|
||||
class="st1"
|
||||
d="M21.9,102.9H6.3c0,0,0,0,0,0V87.4c0,0,0,0,0,0h15.5c0,0,0,0,0,0V102.9z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="XMLID_254_">
|
||||
<path
|
||||
id="XMLID_278_"
|
||||
class="st0"
|
||||
d="M200.9,52.4c-5.5-3.8-12.4-5.8-20.5-5.8h-17.5v55.5h17.5c8,0,14.9-2.1,20.5-6.1
|
||||
c3-2.1,5.4-5.1,7.1-8.9c1.7-3.7,2.5-8.2,2.5-13.1c0-4.9-0.8-9.3-2.5-13C206.3,57.4,203.9,54.4,200.9,52.4z M173.1,56h5.5
|
||||
c6.1,0,11.1,1.2,15,3.6c4.2,2.6,6.4,7.4,6.4,14.4c0,7.2-2.2,12.3-6.4,15.1h0c-3.7,2.4-8.7,3.6-14.9,3.6h-5.6V56z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_277_"
|
||||
class="st0"
|
||||
d="M222.6,45.9c-1.7,0-3.1,0.6-4.3,1.8c-1.2,1.1-1.8,2.6-1.8,4.2c0,1.7,0.6,3.1,1.8,4.3
|
||||
c1.2,1.2,2.6,1.8,4.3,1.8c1.7,0,3.1-0.6,4.3-1.8c1.2-1.2,1.8-2.6,1.8-4.3c0-1.7-0.6-3.1-1.8-4.2
|
||||
C225.7,46.5,224.3,45.9,222.6,45.9z"
|
||||
/>
|
||||
<rect id="XMLID_276_" x="217.6" y="63" class="st0" width="9.8" height="39.1" />
|
||||
<path
|
||||
id="XMLID_273_"
|
||||
class="st0"
|
||||
d="M263.2,66.3c-3-2.6-6.3-4.2-9.9-4.2c-5.4,0-9.9,1.9-13.4,5.6c-3.5,3.7-5.3,8.4-5.3,14.1
|
||||
c0,5.5,1.8,10.2,5.2,14c3.5,3.7,8,5.5,13.5,5.5c3.8,0,7.1-1.1,9.7-3.1V99c0,3.2-0.9,5.8-2.6,7.5c-1.7,1.7-4.1,2.6-7.1,2.6
|
||||
c-4.5,0-7.4-1.8-10.9-6.5l-6.7,6.4l0.2,0.3c1.4,2,3.7,4,6.6,5.9c2.9,1.9,6.6,2.8,10.9,2.8c5.8,0,10.6-1.8,14.1-5.4
|
||||
c3.5-3.6,5.3-8.4,5.3-14.2V63h-9.7V66.3z M260.6,89.4c-1.7,2-3.9,2.9-6.8,2.9c-2.8,0-5-0.9-6.7-2.9c-1.7-1.9-2.5-4.5-2.5-7.7
|
||||
c0-3.2,0.9-5.8,2.5-7.7c1.7-1.9,3.9-2.9,6.7-2.9c2.8,0,5,1,6.8,2.9c1.7,2,2.6,4.6,2.6,7.7C263.2,84.9,262.3,87.5,260.6,89.4z"
|
||||
/>
|
||||
<rect id="XMLID_272_" x="281.3" y="63" class="st0" width="9.8" height="39.1" />
|
||||
<path
|
||||
id="XMLID_271_"
|
||||
class="st0"
|
||||
d="M286.3,45.9c-1.7,0-3.1,0.6-4.3,1.8c-1.2,1.1-1.8,2.6-1.8,4.2c0,1.7,0.6,3.1,1.8,4.3
|
||||
c1.2,1.2,2.6,1.8,4.3,1.8c1.7,0,3.1-0.6,4.3-1.8c1.2-1.2,1.8-2.6,1.8-4.3c0-1.7-0.6-3.1-1.8-4.2C289.4,46.5,288,45.9,286.3,45.9
|
||||
z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_270_"
|
||||
class="st0"
|
||||
d="M312.7,52.5H303V63h-5.6v9h5.6v16.2c0,5.1,1,8.7,3,10.8c2,2.1,5.6,3.2,10.6,3.2
|
||||
c1.6,0,3.2-0.1,4.8-0.2l0.4,0v-9l-3.4,0.2c-2.3,0-3.9-0.4-4.7-1.2c-0.8-0.8-1.1-2.6-1.1-5.2V72h9.2v-9h-9.2V52.5z"
|
||||
/>
|
||||
<rect id="XMLID_269_" x="368" y="46.6" class="st0" width="9.8" height="55.5" />
|
||||
<path
|
||||
id="XMLID_268_"
|
||||
class="st0"
|
||||
d="M477.3,88.2c-1.8,2-3.6,3.7-4.9,4.6v0c-1.4,0.9-3.1,1.3-5.1,1.3c-2.9,0-5.2-1.1-7.1-3.2
|
||||
c-1.9-2.2-2.8-4.9-2.8-8.3s0.9-6.1,2.8-8.2c1.9-2.2,4.2-3.2,7.1-3.2c3.2,0,6.5,2,9.4,5.4l6.5-6.2l0,0c-4.2-5.5-9.7-8.1-16.1-8.1
|
||||
c-5.4,0-10.1,2-13.9,5.8c-3.8,3.9-5.7,8.8-5.7,14.6s1.9,10.7,5.7,14.6c3.8,3.9,8.5,5.9,13.9,5.9c7.1,0,12.9-3.1,16.8-8.7
|
||||
L477.3,88.2z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_265_"
|
||||
class="st0"
|
||||
d="M517.7,68.5c-1.4-1.9-3.3-3.5-5.7-4.7c-2.3-1.1-5.1-1.7-8.1-1.7c-5.5,0-10,2-13.4,6
|
||||
c-3.3,4-4.9,8.9-4.9,14.7c0,5.9,1.8,10.8,5.4,14.6c3.6,3.7,8.4,5.6,14.2,5.6c6.6,0,12.1-2.7,16.2-8l0.2-0.3l-6.4-6.2l0,0
|
||||
c-0.6,0.7-1.4,1.5-2.2,2.3c-1,0.9-1.9,1.6-2.9,2.1c-1.5,0.7-3.1,1.1-5,1.1c-2.7,0-5-0.8-6.7-2.4c-1.6-1.5-2.6-3.5-2.8-5.9h26.1
|
||||
l0.1-3.6c0-2.5-0.3-5-1-7.3C520.1,72.6,519.1,70.4,517.7,68.5z M496.2,77.7c0.5-1.9,1.3-3.4,2.6-4.6c1.3-1.3,3.1-2,5.2-2
|
||||
c2.4,0,4.2,0.7,5.5,2c1.2,1.2,1.8,2.8,2,4.6H496.2z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_262_"
|
||||
class="st0"
|
||||
d="M555.5,66L555.5,66c-3-2.5-7.1-3.8-12.3-3.8c-3.3,0-6.3,0.7-9.1,2.1
|
||||
c-2.6,1.3-5.1,3.5-6.7,6.3l0.1,0.1l6.3,6c2.6-4.1,5.5-5.6,9.3-5.6c2.1,0,3.8,0.6,5.1,1.6c1.3,1.1,1.9,2.5,1.9,4.2v1.9
|
||||
c-2.4-0.7-4.9-1.1-7.2-1.1c-4.9,0-8.9,1.2-11.8,3.4c-3,2.3-4.5,5.6-4.5,9.8c0,3.7,1.3,6.7,3.8,8.9c2.6,2.1,5.8,3.2,9.5,3.2
|
||||
c3.7,0,7.3-1.5,10.4-4.1v3.2h9.7V77C560,72.2,558.5,68.5,555.5,66z M538,87.2c1.1-0.8,2.7-1.2,4.7-1.2c2.4,0,4.9,0.5,7.5,1.4
|
||||
v3.8c-2.1,2-5,3-8.5,3c-1.7,0-3-0.4-3.9-1.1c-0.9-0.7-1.3-1.7-1.3-2.8C536.4,89,536.9,88,538,87.2z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_261_"
|
||||
class="st0"
|
||||
d="M597.9,66.7c-2.7-3.1-6.6-4.6-11.5-4.6c-3.9,0-7.1,1.1-9.4,3.3V63h-9.7v39.1h9.8V80.6
|
||||
c0-3,0.7-5.3,2.1-7c1.4-1.7,3.3-2.5,5.8-2.5c2.2,0,3.9,0.7,5.2,2.2c1.3,1.5,1.9,3.6,1.9,6.2v22.7h9.8V79.5
|
||||
C602,74.1,600.6,69.8,597.9,66.7z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_258_"
|
||||
class="st0"
|
||||
d="M355.6,66L355.6,66c-3-2.5-7.1-3.8-12.3-3.8c-3.3,0-6.3,0.7-9.1,2.1
|
||||
c-2.6,1.3-5.1,3.5-6.7,6.3l0.1,0.1l6.3,6c2.6-4.1,5.5-5.6,9.3-5.6c2.1,0,3.8,0.6,5.1,1.6c1.3,1.1,1.9,2.5,1.9,4.2v1.9
|
||||
c-2.4-0.7-4.9-1.1-7.2-1.1c-4.9,0-8.9,1.2-11.8,3.4c-3,2.3-4.5,5.6-4.5,9.8c0,3.7,1.3,6.7,3.8,8.9c2.6,2.1,5.8,3.2,9.5,3.2
|
||||
c3.7,0,7.3-1.5,10.4-4.1v3.2h9.7V77C360.2,72.2,358.7,68.5,355.6,66z M338.2,87.2c1.1-0.8,2.7-1.2,4.7-1.2
|
||||
c2.4,0,4.9,0.5,7.5,1.4v3.8c-2.1,2-5,3-8.5,3c-1.7,0-3-0.4-3.9-1.1c-0.9-0.7-1.3-1.7-1.3-2.8C336.6,89,337.1,88,338.2,87.2z"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_255_"
|
||||
class="st0"
|
||||
d="M413.6,103c-15.8,0-28.6-12.8-28.6-28.6s12.8-28.6,28.6-28.6s28.6,12.8,28.6,28.6
|
||||
S429.4,103,413.6,103z M413.6,55.8c-10.2,0-18.5,8.3-18.5,18.5s8.3,18.5,18.5,18.5s18.5-8.3,18.5-18.5S423.8,55.8,413.6,55.8z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
@@ -5,14 +5,7 @@ import logoSrc from '~/assets/images/chatbot-whatsapp.png?width=64&height=64&png
|
||||
|
||||
export default component$(() => (
|
||||
<span class="self-center ml-2 text-2xl md:text-xl font-bold text-gray-900 whitespace-nowrap dark:text-white flex items-center">
|
||||
<img
|
||||
src={logoSrc}
|
||||
class="inline-block mr-1"
|
||||
width={32}
|
||||
height={32}
|
||||
alt="Qwind Logo"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img src={logoSrc} class="inline-block mr-1" width={32} height={32} alt="Qwind Logo" loading="lazy" />
|
||||
Chatbot
|
||||
</span>
|
||||
))
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
export const Netlify = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={147}
|
||||
height={40}
|
||||
role="img"
|
||||
fill="currentColor"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={147} height={40} role="img" fill="currentColor">
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M53.37 12.978l.123 2.198c1.403-1.7 3.245-2.55 5.525-2.55 3.951 0 5.962 2.268 6.032 6.804v12.568H60.79V19.676c0-1.207-.26-2.1-.78-2.681-.52-.58-1.371-.87-2.552-.87-1.719 0-3 .78-3.84 2.338v13.535h-4.262v-19.02h4.016zM77.748 32.35c-2.7 0-4.89-.852-6.567-2.557-1.678-1.705-2.517-3.976-2.517-6.812v-.527c0-1.898.365-3.595 1.096-5.089.73-1.494 1.757-2.657 3.078-3.49 1.321-.831 2.794-1.247 4.42-1.247 2.583 0 4.58.826 5.988 2.478 1.41 1.653 2.114 3.99 2.114 7.014v1.723h-12.4c.13 1.57.652 2.812 1.57 3.726.918.914 2.073 1.371 3.464 1.371 1.952 0 3.542-.79 4.77-2.373l2.297 2.198c-.76 1.136-1.774 2.018-3.042 2.645-1.269.627-2.692.94-4.27.94zm-.508-16.294c-1.17 0-2.113.41-2.832 1.23-.72.82-1.178 1.963-1.377 3.428h8.12v-.317c-.094-1.43-.474-2.51-1.14-3.243-.667-.732-1.59-1.098-2.771-1.098zm16.765-7.7v4.623h3.35v3.164h-3.35V26.76c0 .726.144 1.25.43 1.573.286.322.798.483 1.535.483a6.55 6.55 0 0 0 1.49-.176v3.305c-.97.27-1.905.404-2.806.404-3.273 0-4.91-1.81-4.91-5.431V16.142H86.62v-3.164h3.122V8.355h4.261zm11.137 23.643h-4.262v-27h4.262v27zm9.172 0h-4.262v-19.02h4.262v19.02zm-4.525-23.96c0-.655.207-1.2.622-1.634.416-.433 1.009-.65 1.78-.65.772 0 1.368.217 1.79.65.42.434.63.979.63 1.635 0 .644-.21 1.18-.63 1.608-.422.428-1.018.642-1.79.642-.771 0-1.364-.214-1.78-.642-.415-.427-.622-.964-.622-1.608zm10.663 23.96V16.142h-2.894v-3.164h2.894v-1.74c0-2.11.584-3.738 1.753-4.887 1.17-1.148 2.806-1.722 4.91-1.722.749 0 1.544.105 2.386.316l-.105 3.34a8.375 8.375 0 0 0-1.631-.14c-2.035 0-3.052 1.048-3.052 3.146v1.687h3.858v3.164h-3.858v15.856h-4.261zm17.87-6.117l3.858-12.903h4.542l-7.54 21.903c-1.158 3.199-3.122 4.799-5.893 4.799-.62 0-1.304-.106-2.052-.317v-3.305l.807.053c1.075 0 1.885-.196 2.429-.589.543-.392.973-1.051 1.289-1.977l.613-1.635-6.664-18.932h4.595l4.016 12.903z" />
|
||||
<path
|
||||
|
||||
@@ -13,10 +13,7 @@ export const RouterHead = component$(() => {
|
||||
<title>{head.title}</title>
|
||||
|
||||
<link rel="canonical" href={loc.href} />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
|
||||
{head.meta.map((m) => (
|
||||
|
||||
@@ -34,14 +34,8 @@ export const Social = () => {
|
||||
content="https://campaign.codigoencasa.com"
|
||||
/>
|
||||
<meta property="og:site_name" content="campaign.codigoencasa.com" /> */}
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
></meta>
|
||||
<meta
|
||||
property="og:image:secure_url"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
/>
|
||||
<meta property="og:image" content="https://i.imgur.com/0HpzsEm.png"></meta>
|
||||
<meta property="og:image:secure_url" content="https://i.imgur.com/0HpzsEm.png" />
|
||||
<meta property="og:image:type" content="image/png"></meta>
|
||||
<meta property="og:image:width" content="1200"></meta>
|
||||
<meta property="og:image:height" content="630"></meta>
|
||||
@@ -52,10 +46,7 @@ export const Social = () => {
|
||||
name="twitter:title"
|
||||
content="💻 Conviértete en un Programador Backend aprendiendo todo de Cloud y Nodejs"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://i.imgur.com/0HpzsEm.png"
|
||||
/>
|
||||
<meta name="twitter:image" content="https://i.imgur.com/0HpzsEm.png" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@ export default component$((props: ItemProps) => {
|
||||
// TODO:
|
||||
document.body.classList.toggle('overflow-hidden')
|
||||
document.getElementById('header')?.classList.toggle('h-screen')
|
||||
document
|
||||
.querySelector('#header nav')
|
||||
?.classList.toggle('hidden')
|
||||
document.querySelector('#header nav')?.classList.toggle('hidden')
|
||||
}}
|
||||
>
|
||||
<IconMenu class={iconClass} />
|
||||
|
||||
@@ -10,16 +10,13 @@ interface ItemProps {
|
||||
export default component$((props: ItemProps) => {
|
||||
const { iconClass } = props
|
||||
const store = useStore({
|
||||
theme:
|
||||
(typeof window !== 'undefined' && window?.localStorage?.theme) ||
|
||||
undefined,
|
||||
theme: (typeof window !== 'undefined' && window?.localStorage?.theme) || undefined,
|
||||
})
|
||||
|
||||
useClientEffect$(() => {
|
||||
store.theme =
|
||||
window.localStorage.theme === 'dark' ||
|
||||
(!('theme' in window.localStorage) &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
(!('theme' in window.localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
? 'dark'
|
||||
: 'light'
|
||||
})
|
||||
@@ -42,11 +39,7 @@ export default component$((props: ItemProps) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{store.theme == 'dark' ? (
|
||||
<IconMoon class={iconClass} />
|
||||
) : (
|
||||
<IconSun class={iconClass} />
|
||||
)}
|
||||
{store.theme == 'dark' ? <IconMoon class={iconClass} /> : <IconSun class={iconClass} />}
|
||||
</button>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,9 +7,7 @@ export const IconArrowDownRight = (props: ItemProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class={`icon icon-tabler icon-tabler-arrow-down-right ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-arrow-down-right ${className || 'w-5 h-5'}`}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -8,9 +8,7 @@ export const IconMenu = (props: ItemProps) => {
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class={`icon icon-tabler icon-tabler-menu ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-menu ${className || 'w-5 h-5'}`}
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
|
||||
@@ -7,9 +7,7 @@ export const IconMoon = (props: ItemProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class={`icon icon-tabler icon-tabler-moon ${
|
||||
className || 'w-5 h-5'
|
||||
}`}
|
||||
class={`icon icon-tabler icon-tabler-moon ${className || 'w-5 h-5'}`}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
|
||||
@@ -14,7 +14,7 @@ export default component$(
|
||||
<a href={props.user.html_url} target="_blank">
|
||||
<img
|
||||
class="w-16 h-16 rounded-full mx-auto object-cover"
|
||||
src={props.user.avatar_url + '&s=80'}
|
||||
src={props.user.avatar_url}
|
||||
alt={props.user.login}
|
||||
width="80"
|
||||
height="80"
|
||||
@@ -23,7 +23,7 @@ export default component$(
|
||||
|
||||
<div class="pt-2 space-y-4 justify-center flex">
|
||||
<figcaption class="text-sm">
|
||||
<div class={'font-semibold'}>{props.user.login}</div>
|
||||
<div class={'font-semibold truncate'}>{props.user.login}</div>
|
||||
</figcaption>
|
||||
</div>
|
||||
</figure>
|
||||
|
||||
@@ -32,8 +32,7 @@ export default component$((props: { users: User[] }) => {
|
||||
Super estrellas
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Todo es posible gracias a el mayor recursos de todos, el
|
||||
recurso humano. Tu tambien puedes{' '}
|
||||
Todo es posible gracias a el mayor recursos de todos, el recurso humano. Tu tambien puedes{' '}
|
||||
<a class={'font-semibold'} href="/docs/contributing">
|
||||
formar parte
|
||||
</a>
|
||||
|
||||
@@ -15,8 +15,8 @@ export default component$(() => {
|
||||
📄 Editar esta pagina
|
||||
</a>
|
||||
<p class={'text-xs'}>
|
||||
Forma parte de esta comunidad mejorando la documentación
|
||||
siente libre de poder agregar o editar lo que quieras
|
||||
Forma parte de esta comunidad mejorando la documentación siente libre de poder agregar o editar
|
||||
lo que quieras
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -56,13 +56,9 @@ export default component$(() => {
|
||||
<IconArrowDownRight class="w-7 h-7 text-primary-600 inline-block" />
|
||||
{question}
|
||||
</div>
|
||||
{answer
|
||||
.split('\n\n')
|
||||
.map((paragraph) => (
|
||||
<p class="text-gray-700 dark:text-gray-400 mb-2">
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
{answer.split('\n\n').map((paragraph) => (
|
||||
<p class="text-gray-700 dark:text-gray-400 mb-2">{paragraph}</p>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -50,13 +50,11 @@ export default component$(() => {
|
||||
Caracteristicas
|
||||
</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
Nuestras principales{' '}
|
||||
<span class="whitespace-nowrap">funciones</span>
|
||||
Nuestras principales <span class="whitespace-nowrap">funciones</span>
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
El secreto es mantener los procesos repetitivos en
|
||||
procesos automatizados simples, por eso te mostramos en
|
||||
que destacamos.
|
||||
El secreto es mantener los procesos repetitivos en procesos automatizados simples, por eso te
|
||||
mostramos en que destacamos.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid mx-auto space-y-6 md:grid-cols-2 md:space-y-0">
|
||||
@@ -70,12 +68,8 @@ export default component$(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mb-3 text-xl font-bold">
|
||||
{title}
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400">
|
||||
{description}
|
||||
</p>
|
||||
<h3 class="mb-3 text-xl font-bold">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -9,36 +9,24 @@ import { src as placeholder } from '~/assets/images/chatbot-whatsapp.png?width=4
|
||||
|
||||
export default component$(() => {
|
||||
return (
|
||||
<section
|
||||
class={` from-white via-purple-50 to-sky-100 dark:bg-none mt-[-95px]`}
|
||||
>
|
||||
<section class={` from-white via-purple-50 to-sky-100 dark:bg-none mt-[-95px]`}>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 md:flex md:h-screen 2xl:h-auto pt-[72px]">
|
||||
<div class="py-12 md:py-12 lg:py-16 block md:flex text-center md:text-left">
|
||||
<div class="pb-12 md:pb-0 md:py-0 max-w-5xl mx-auto md:pr-16 flex items-center basis-[56%]">
|
||||
<div>
|
||||
<h1 class="text-5xl md:text-[3.48rem] font-bold leading-tighter tracking-tighter mb-4 font-heading px-4 md:px-0">
|
||||
Crear chatbot{' '}
|
||||
<span class="sm:whitespace-nowrap text-[#25b637]">
|
||||
WhatsApp
|
||||
</span>
|
||||
<br class="hidden lg:block" />{' '}
|
||||
<span class="lg:inline">en minutos</span>
|
||||
Crear chatbot <span class="sm:whitespace-nowrap text-[#25b637]">WhatsApp</span>
|
||||
<br class="hidden lg:block" /> <span class="lg:inline">en minutos</span>
|
||||
</h1>
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<p class="text-xl text-gray-600 mb-8 dark:text-slate-400">
|
||||
<span class="font-semibold ">
|
||||
Con esta libreria,{' '}
|
||||
</span>
|
||||
<span class="font-semibold ">Con esta libreria, </span>
|
||||
<span class="font-semibold ">
|
||||
puedes configurar respuestas
|
||||
automatizadas para preguntas frecuentes
|
||||
puedes configurar respuestas automatizadas para preguntas frecuentes
|
||||
</span>{' '}
|
||||
, recibir y responder mensajes de manera
|
||||
automatizada, y hacer un seguimiento de las
|
||||
interacciones con los clientes. Además,
|
||||
nuestro Chatbot se integra fácilmente con
|
||||
otros sistemas y herramientas que ya esté
|
||||
utilizando en su negocio.
|
||||
, recibir y responder mensajes de manera automatizada, y hacer un seguimiento de las
|
||||
interacciones con los clientes. Además, nuestro Chatbot se integra fácilmente con
|
||||
otros sistemas y herramientas que ya esté utilizando en su negocio.
|
||||
</p>
|
||||
|
||||
<div class="max-w-xs sm:max-w-md flex flex-nowrap flex-col sm:flex-col gap-4 m-auto md:m-0 justify-center md:justify-start">
|
||||
@@ -47,12 +35,16 @@ export default component$(() => {
|
||||
npm create bot-whatsapp@latest
|
||||
</code>
|
||||
</div>
|
||||
<div class="flex w-full sm:w-auto">
|
||||
<div class="flex w-full sm:w-auto gap-3">
|
||||
<a href="/docs" class="btn bg-gray-50 dark:bg-transparent">
|
||||
Ver documentación
|
||||
</a>
|
||||
<a
|
||||
href="/docs"
|
||||
target={'_blank'}
|
||||
href="https://youtu.be/UgoS8PXxe-A"
|
||||
class="btn bg-gray-50 dark:bg-transparent"
|
||||
>
|
||||
Ver documentación
|
||||
Ver video
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
49
packages/docs/src/components/widgets/Members.tsx
Normal file
49
packages/docs/src/components/widgets/Members.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
import { RequestHandlerCloudflarePages } from '@builder.io/qwik-city/middleware/cloudflare-pages'
|
||||
import { User } from '~/contexts'
|
||||
import Collaborator from './Collaborator'
|
||||
|
||||
export const onRequest: RequestHandlerCloudflarePages = async () => {
|
||||
console.log('??heree')
|
||||
}
|
||||
|
||||
export const TaleUsers = component$((props: { users: User[] }) => {
|
||||
return (
|
||||
<>
|
||||
{props.users.map((user) => (
|
||||
<div class="col-span-2 ">
|
||||
{' '}
|
||||
<Collaborator user={user} />
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default component$((props: { users: User[] }) => {
|
||||
return (
|
||||
<section class="relative ">
|
||||
<div class={'px-4 py-16 mx-auto max-w-6xl lg:py-20'}>
|
||||
<div class="mb-10 md:mx-auto sm:text-center md:mb-12 max-w-3xl">
|
||||
<p class="text-base text-primary-600 dark:text-purple-200 font-semibold tracking-wide uppercase">
|
||||
Premium
|
||||
</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
Miembros
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Conviértete en un miembro destacado y forma parte del proyecto y disfruta de manera adelantada
|
||||
de las actualizaciones{' '}
|
||||
<a class={'font-semibold'} target={'_blank'} href="https://opencollective.com/bot-whatsapp">
|
||||
Únete
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid lg:grid-cols-12 grid-cols-1 gap-4 ">
|
||||
<TaleUsers users={props.users} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
})
|
||||
@@ -5,55 +5,45 @@ import { DocumentationCtx } from '~/contexts'
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
*/
|
||||
export default component$(
|
||||
({ options = [] }: { options: DocumentationCtx[] }) => {
|
||||
return (
|
||||
<div>
|
||||
{options.map((item, i) => (
|
||||
<UlCompoent key={i} title={item.title} list={item.list} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
export default component$(({ options = [] }: { options: DocumentationCtx[] }) => {
|
||||
return (
|
||||
<div>
|
||||
{options.map((item, i) => (
|
||||
<UlCompoent key={i} title={item.title} list={item.list} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export const UlCompoent = component$(
|
||||
(porps: { title: string; list: { link: string; name: string }[] }) => {
|
||||
return (
|
||||
<ul>
|
||||
<li class="mt-2 lg:mt-2">
|
||||
<h5 class="mb-8 lg:mb-3 font-semibold text-slate-900 dark:text-slate-200">
|
||||
{porps.title}
|
||||
</h5>
|
||||
<LiComponent list={porps.list} />
|
||||
export const UlCompoent = component$((porps: { title: string; list: { link: string; name: string }[] }) => {
|
||||
return (
|
||||
<ul>
|
||||
<li class="mt-2 lg:mt-2">
|
||||
<h5 class="mb-8 lg:mb-3 font-semibold text-slate-900 dark:text-slate-200">{porps.title}</h5>
|
||||
<LiComponent list={porps.list} />
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
})
|
||||
|
||||
export const LiComponent = component$((porps: { list: { link: string; name: string }[] }) => {
|
||||
const location = useLocation()
|
||||
const currentPage = location.pathname
|
||||
return (
|
||||
<ul class="space-y-6 lg:space-y-2 border-l border-slate-100 dark:border-slate-800">
|
||||
{porps.list.map((opt) => (
|
||||
<li>
|
||||
<Link
|
||||
class={[
|
||||
currentPage === `${opt.link}/` ? 'font-semibold' : '',
|
||||
'block border-l pl-4 -ml-px border-transparent hover:border-slate-400 dark:hover:border-slate-500 text-slate-700 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300 ',
|
||||
]}
|
||||
href={opt.link}
|
||||
>
|
||||
{opt.name}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export const LiComponent = component$(
|
||||
(porps: { list: { link: string; name: string }[] }) => {
|
||||
const location = useLocation()
|
||||
const currentPage = location.pathname
|
||||
return (
|
||||
<ul class="space-y-6 lg:space-y-2 border-l border-slate-100 dark:border-slate-800">
|
||||
{porps.list.map((opt) => (
|
||||
<li>
|
||||
<Link
|
||||
class={[
|
||||
currentPage === `${opt.link}/`
|
||||
? 'font-semibold'
|
||||
: '',
|
||||
'block border-l pl-4 -ml-px border-transparent hover:border-slate-400 dark:hover:border-slate-500 text-slate-700 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300 ',
|
||||
]}
|
||||
href={opt.link}
|
||||
>
|
||||
{opt.name}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,74 +1,63 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
export const ButtonLink = component$(
|
||||
(props: { name: string; link: string; direction: 'left' | 'right' }) => {
|
||||
const ArrowRight = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="ml-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M0 0L3 3L0 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
export const ButtonLink = component$((props: { name: string; link: string; direction: 'left' | 'right' }) => {
|
||||
const ArrowRight = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="ml-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M0 0L3 3L0 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ArrowLeft = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="mr-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M3 0L0 3L3 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
const ArrowLeft = () => (
|
||||
<svg
|
||||
viewBox="0 0 3 6"
|
||||
class="mr-3 w-auto h-1.5 text-slate-400 overflow-visible group-hover:text-slate-600 dark:group-hover:text-slate-300"
|
||||
>
|
||||
<path
|
||||
d="M3 0L0 3L3 6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
|
||||
return (
|
||||
<a
|
||||
class="group flex items-center hover:text-slate-900 dark:hover:text-white"
|
||||
href={props.link}
|
||||
>
|
||||
{props.direction === 'left' ? (
|
||||
<>
|
||||
<ArrowLeft />
|
||||
{props.name}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{props.name}
|
||||
<ArrowRight />
|
||||
</>
|
||||
)}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
)
|
||||
return (
|
||||
<a class="group flex items-center hover:text-slate-900 dark:hover:text-white" href={props.link}>
|
||||
{props.direction === 'left' ? (
|
||||
<>
|
||||
<ArrowLeft />
|
||||
{props.name}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{props.name}
|
||||
<ArrowRight />
|
||||
</>
|
||||
)}
|
||||
</a>
|
||||
)
|
||||
})
|
||||
|
||||
export default component$(
|
||||
(props: { pages: ({ name: string; link: string } | null)[] }) => {
|
||||
const { pages } = props
|
||||
return (
|
||||
<div class="text-sm leading-6 mt-12">
|
||||
<div class="mb-10 text-slate-700 font-semibold flex justify-between items-center dark:text-slate-200">
|
||||
{pages[0] ? (
|
||||
<ButtonLink direction="left" {...pages[0]} />
|
||||
) : null}
|
||||
{pages[1] ? (
|
||||
<ButtonLink direction="right" {...pages[1]} />
|
||||
) : null}
|
||||
</div>
|
||||
export default component$((props: { pages: ({ name: string; link: string } | null)[] }) => {
|
||||
const { pages } = props
|
||||
return (
|
||||
<div class="text-sm leading-6 mt-12">
|
||||
<div class="mb-10 text-slate-700 font-semibold flex justify-between items-center dark:text-slate-200">
|
||||
{pages[0] ? <ButtonLink direction="left" {...pages[0]} /> : null}
|
||||
{pages[1] ? <ButtonLink direction="right" {...pages[1]} /> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
20
packages/docs/src/components/widgets/SearchModal.tsx
Normal file
20
packages/docs/src/components/widgets/SearchModal.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { component$ } from '@builder.io/qwik'
|
||||
|
||||
export const SearchModal = component$(() => {
|
||||
// const state = useStore({
|
||||
// open: false,
|
||||
// src: '',
|
||||
// })
|
||||
|
||||
return (
|
||||
<div class={'bg-gray-100/75 fixed w-[100vw] h-[100vh] z-50'}>
|
||||
<div class={'bg-red-200 w-1/3 m-auto mt-12'}>
|
||||
<SingleModal />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export const SingleModal = component$(() => {
|
||||
return <div class={'bg-blue-300 w-100 px-3 py-2'}>Modal singlke</div>
|
||||
})
|
||||
@@ -7,6 +7,8 @@ import { src as qwik } from '~/assets/images/qwik.png?width=100&metadata'
|
||||
import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata'
|
||||
// @ts-ignore
|
||||
import { src as netlify } from '~/assets/images/full-logo-light.png?width=100&metadata'
|
||||
// @ts-ignore
|
||||
import { src as digitalOcean } from '~/assets/images/digital-ocean.png?width=100&metadata'
|
||||
|
||||
/**
|
||||
* options = [] array con la lista de opciones de la documentacion
|
||||
@@ -41,7 +43,20 @@ export default component$(() => {
|
||||
<img
|
||||
src={netlify}
|
||||
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
||||
alt="Qwind Hero Image (Cool dog)"
|
||||
alt="Netlify"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target={'_blank'} href="https://m.do.co/c/140291d21736">
|
||||
<picture>
|
||||
<img
|
||||
src={digitalOcean}
|
||||
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
||||
alt="DigitalOcean"
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
/>
|
||||
|
||||
@@ -5,33 +5,25 @@ export default component$(() => {
|
||||
<div class="px-4 py-8 md:py-16 sm:px-6 mx-auto md:px-24 lg:px-8 lg:py-20 max-w-6xl">
|
||||
<div class="grid grid-cols-2 row-gap-8 md:grid-cols-4">
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
132K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">132K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Downloads
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
24.8K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">24.8K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Stars
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 font-heading">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1]">
|
||||
10.3K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1]">10.3K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Forks
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">
|
||||
48.4K
|
||||
</div>
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-[#039de1] font-heading">48.4K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Users
|
||||
</p>
|
||||
|
||||
@@ -13,5 +13,4 @@ export interface User {
|
||||
avatar_url: string
|
||||
}
|
||||
|
||||
export const GlobalStore =
|
||||
createContext<DocumentationCtx[]>('documentation-site')
|
||||
export const GlobalStore = createContext<DocumentationCtx[]>('documentation-site')
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import {
|
||||
component$,
|
||||
useContextProvider,
|
||||
useStore,
|
||||
useStyles$,
|
||||
} from '@builder.io/qwik'
|
||||
import {
|
||||
QwikCityProvider,
|
||||
RouterOutlet,
|
||||
ServiceWorkerRegister,
|
||||
} from '@builder.io/qwik-city'
|
||||
import { component$, useContextProvider, useStore, useStyles$ } from '@builder.io/qwik'
|
||||
import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from '@builder.io/qwik-city'
|
||||
|
||||
import { RouterHead } from '~/components/core/RouterHead'
|
||||
import { DarkThemeLauncher } from '~/components/core/DarkThemeLauncher'
|
||||
@@ -52,16 +43,22 @@ export default component$(() => {
|
||||
title: 'Avanzado',
|
||||
list: [
|
||||
{ name: 'Migración', link: '/docs/migration' },
|
||||
{ name: 'Extender funcionalidades', link: '/docs/custom' },
|
||||
{ name: 'MasterClass', link: '/docs/masterclass' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Despliegue',
|
||||
list: [
|
||||
{ name: 'Local', link: '/docs/deploy/local' },
|
||||
{ name: 'Docker', link: '/docs/deploy/docker' },
|
||||
{ name: 'Cloud', link: '/docs/deploy/cloud' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Comunidad',
|
||||
list: [
|
||||
{ name: 'MasterClass', link: '/docs/masterclass' },
|
||||
{ name: 'Colabores', link: '/docs/contributing' },
|
||||
{ name: 'Unirme al proyecto', link: '/docs/join' },
|
||||
{ name: 'Sponsors', link: '/docs/sponsors' },
|
||||
],
|
||||
},
|
||||
])
|
||||
@@ -72,10 +69,7 @@ export default component$(() => {
|
||||
<QwikCityProvider>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
|
||||
<RouterHead />
|
||||
|
||||
@@ -4,11 +4,10 @@ import Navigation from '../../../components/widgets/Navigation'
|
||||
# DataBase (Base de datos)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **user, host, password** para esos
|
||||
casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**user, host, password** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo
|
||||
|
||||
108
packages/docs/src/routes/docs/deploy/cloud/index.mdx
Normal file
108
packages/docs/src/routes/docs/deploy/cloud/index.mdx
Normal file
@@ -0,0 +1,108 @@
|
||||
import Alert from '../../../../components/widgets/Alert'
|
||||
import Navigation from '../../../../components/widgets/Navigation'
|
||||
|
||||
# Entorno Cloud
|
||||
|
||||
Si deseas tener tu chatbot en ejecución en un servidor en la nueba esta, guía te ayudará.
|
||||
El servidor deberá cumplir con los requisitos mínimos, puedes ver en [este enlace.](/docs/requirements)
|
||||
|
||||
---
|
||||
|
||||
Dependiendo de tu proveedor de **servicio Cloud** debes crear una instancia (máquina virtual), este ejemplo iremos orientando en un entorno de AWS.
|
||||
En nuestro ejemplo creamos una maquina virtual con **Ubuntu 20.04**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
Posterior al proceso de crear la máquina esperamos unos minutos hasta que ya está operativo y tomamos nota del usuario y la IP pública para proceder a conectarnos vía SSH
|
||||
|
||||
## 
|
||||
|
||||
## Conectarse via SSH
|
||||
|
||||
Luego de obtener los datos necesarios para conectarnos a nuestra máquina, procedemos a hacerlo
|
||||
|
||||
```shell
|
||||
ssh -i llaveBot.pem ubutnu@34.228.208.104
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Luego puede aparecer un mensaje como el siguiente donde solo debes de responder **yes**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
Una vez conectado ya estás dentro de la máquina virtual, te aconsejamos la primera vez hacer una actualización de dependencias de Ubuntu con los siguientes comandos
|
||||
|
||||
```shell
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
```shell
|
||||
sudo apt-get upgrade
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recuerda instalar Node 16 o superior
|
||||
|
||||
Puedes ver más a detalle los pasos de la instalacion en este [blog](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-es)
|
||||
|
||||
```shell
|
||||
curl -sL https://deb.nodesource.com/setup_18.x -o nodesource_setup.sh
|
||||
```
|
||||
|
||||
```shell
|
||||
sudo bash nodesource_setup.sh
|
||||
```
|
||||
|
||||
```shell
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementar el bot
|
||||
|
||||
Si tienes el código de tu chatbot en un repositorio, solo falta que clones el repo en el servidor y ejecutes `npm start`
|
||||
|
||||
Para escanear el **QR** puedes hacerlo vía WEB accediendo a la URL `http://[TU_IP_PUBLICA]:3000` en este ejemplo seria `http://34.228.208.10:3000`
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Firewall
|
||||
|
||||
Si no te abre la pagina web asegurate de tener el puerto abierto en tu firewall.
|
||||
Ejemplo permitir el puerto **3000**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Escanear QR
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Ejecutar en Producción
|
||||
|
||||
Debes ubicarte en el directorio donde tienes el codigo fuente de tu chatbot.
|
||||
|
||||
Independientemente de tu sistema operativo deberás ejecutar el chatbot con el comando atrevés de un sistema que mantenga el proceso en ejecución.
|
||||
Recomendamos [Pm2](https://pm2.keymetrics.io/)
|
||||
|
||||
```shell
|
||||
pm2 start app.js --name=bot1
|
||||
```
|
||||
|
||||

|
||||
|
||||
La consola de devolver un mensaje con una lista de procesos, en el ejemplo puedes observar, que tenemos un proceso llamado `bot1`
|
||||
|
||||
De esta manera ya puedes cerrar la terminal y tu bot seguirá en ejecución sin problema
|
||||
32
packages/docs/src/routes/docs/deploy/docker/index.mdx
Normal file
32
packages/docs/src/routes/docs/deploy/docker/index.mdx
Normal file
@@ -0,0 +1,32 @@
|
||||
import Alert from '../../../../components/widgets/Alert'
|
||||
import Navigation from '../../../../components/widgets/Navigation'
|
||||
|
||||
# Entorno Docker
|
||||
|
||||
Previamente, necesitas tener instalado Docker en tu servidor dependiendo del sistema operativo, los procesos cambian,
|
||||
puedes encontrar toda la información oficial de docker en [este enlace.](https://docs.docker.com/get-docker/)
|
||||
|
||||
---
|
||||
|
||||
Dependiendo del proveedor que has elegido necesitaras una implementación de Docker específica, pero no te preocupes, ya que viene implementada automáticamente en un archivo llamado **Dockerfile**, también puedes ver los otros Dockerfile en el apartado de [plantillas.](https://github.com/codigoencasa/bot-whatsapp/tree/main/starters/apps)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Contruir imagen
|
||||
|
||||
Solo es necesario construir la imagen del docker lo puedes hacer con el siguiente comando
|
||||
|
||||
```shell
|
||||
docker build . -t botwhatsapp:latest
|
||||
```
|
||||
|
||||
## Iniciar contenedor
|
||||
|
||||
Para iniciar el contenedor con la imagen previamente construida puedes realizarlo ejecutando el siguiente comando.
|
||||
Se utiliza el puerto **3001** solo com un ejemplo puedes usar el puerto que tu quieras
|
||||
|
||||
```shell
|
||||
docker run -e PORT=3001 -p 3001:3001 botwhatsapp:latest
|
||||
```
|
||||
26
packages/docs/src/routes/docs/deploy/local/index.mdx
Normal file
26
packages/docs/src/routes/docs/deploy/local/index.mdx
Normal file
@@ -0,0 +1,26 @@
|
||||
import Alert from '../../../../components/widgets/Alert'
|
||||
import Navigation from '../../../../components/widgets/Navigation'
|
||||
|
||||
# Entorno Local
|
||||
|
||||
Si deseas tener tu chatbot en ejecución en un servidor local (computadora personal, etc.) esta, guía te ayudará.
|
||||
El servidor local deberá cumplir con los requisitos mínimos, puedes ver en [este enlace.](/docs/requirements)
|
||||
|
||||
---
|
||||
|
||||
<Alert>Si deseas instalar pm2 puedes ejecutar `npm install pm2 --global`</Alert>
|
||||
|
||||
Debes ubicarte en el directorio donde tienes el codigo fuente de tu chatbot.
|
||||
|
||||
Independientemente de tu sistema operativo deberás ejecutar el chatbot con el comando atrevés de un sistema que mantenga el proceso en ejecución.
|
||||
Recomendamos [Pm2](https://pm2.keymetrics.io/)
|
||||
|
||||
```shell
|
||||
pm2 start app.js --name=bot1
|
||||
```
|
||||
|
||||

|
||||
|
||||
La consola de devolver un mensaje con una lista de procesos, en el ejemplo puedes observar, que tenemos un proceso llamado `bot1`
|
||||
|
||||
De esta manera ya puedes cerrar la terminal y tu bot seguirá en ejecución sin problema
|
||||
@@ -22,12 +22,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder**
|
||||
Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
@@ -39,11 +34,10 @@ const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
## Provider (Proveedor)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **token, api, etc.** para esos casos te
|
||||
recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de proveedor que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**token, api, etc.** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza que conectara tu flujo con Whatsapp. En este chatbot tenemos varios proveedores disponibles la mayoria gratis pero tambien tenemos integracion la api oficial de whatsapp o twilio
|
||||
@@ -71,11 +65,10 @@ Los proveedores disponibles hasta el momento son los siguientes:
|
||||
## DataBase (Base de datos)
|
||||
|
||||
<Alert>
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar
|
||||
algunas configuracion adicional como **user, host, password** para esos
|
||||
casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)**
|
||||
o si gustas puedes editar esta documentación para ir agregando más info
|
||||
⚡ Dependiendo del tipo de conector que utlices puede que necesites pasar algunas configuracion adicional como
|
||||
**user, host, password** para esos casos te recomendamos guiarte de los
|
||||
**[starters](https://github.com/codigoencasa/bot-whatsapp/tree/dev/starters/apps)** o si gustas puedes editar esta
|
||||
documentación para ir agregando más info
|
||||
</Alert>
|
||||
|
||||
Es la pieza encargada de mantener el **"estado"** de una conversación, para mayor facilidad la libreria te proporcia diferentes conectores que se de adapten mejor a tu desarrollo
|
||||
|
||||
@@ -5,12 +5,7 @@ import Navigation from '../../../components/widgets/Navigation'
|
||||
Si copias y pegas este codigo y tu entorno de trabajo cumple con todos los requesitos te debe funcionar abajo explico muy por encima
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
@@ -42,12 +37,7 @@ main()
|
||||
En esta parte solo estamos declaramos las dependencias que vamos a utilizar. Si quieres saber a fondo cada una de las funciones te recomiendo pasarte por la seccion de **[conceptos](/docs/concepts)**
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const WebWhatsappProvider = require('@bot-whatsapp/provider/web-whatsapp')
|
||||
const MockAdapter = require('@bot-whatsapp/database/mock')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Navigation from '../../../components/widgets/Navigation'
|
||||
|
||||
# Flow (Flujos)
|
||||
# Flow
|
||||
|
||||
Los flujos hace referencia al hecho de construir un flujo de conversion. Esto es un flow podemos observar que estan presente dos metodos importantes **addKeyword** y el **addAnswer**.
|
||||
|
||||
@@ -9,12 +9,7 @@ Tan sencillo como decir **palabra/s clave** y **mensaje a responder**
|
||||
Ambos metodos **[addKeyword](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addKeyword.js)** y el **[addAnswer](https://github.com/codigoencasa/bot-whatsapp/blob/dev/packages/bot/io/methods/addAnswer.js)** tienen una serie opciones disponibles
|
||||
|
||||
```js
|
||||
const {
|
||||
createBot,
|
||||
createProvider,
|
||||
createFlow,
|
||||
addKeyword,
|
||||
} = require('@bot-whatsapp/bot')
|
||||
const { createBot, createProvider, createFlow, addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
.addAnswer(['Hola, bienvenido a mi tienda', '¿Como puedo ayudarte?'])
|
||||
@@ -23,6 +18,206 @@ const flowPrincipal = addKeyword(['hola', 'alo'])
|
||||
|
||||
---
|
||||
|
||||
## blackList
|
||||
|
||||
Éste argumento se utiliza para **evitar que el bot se active** cuando los números de la lista activen el bot.
|
||||
Es importante que el número **vaya acompañado de su prefijo**, en el caso de España "34".
|
||||
|
||||
```js
|
||||
createBot(
|
||||
{
|
||||
flow: adapterFlow,
|
||||
provider: adapterProvider,
|
||||
database: adapterDB,
|
||||
},
|
||||
{
|
||||
blackList: ['34XXXXXXXXX', '34XXXXXXXXX', '34XXXXXXXXX', '34XXXXXXXXX'],
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## addKeyword()
|
||||
|
||||
Esta funcion se utliza para iniciar un flujo de conversion. <br /> Recibe un `string` o un `array`
|
||||
de string `['hola','buenas']`.
|
||||
|
||||
**Opciones**
|
||||
|
||||
- sensitive: Sensible a mayusculas y minusculas por defecto `false`
|
||||
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola')
|
||||
|
||||
const flowArray = addKeyword(['hola', 'alo'])
|
||||
|
||||
const flowSensitive = addKeyword(['hola', 'alo'], {
|
||||
sensitive: true,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## addAnswer()
|
||||
|
||||
Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
|
||||
|
||||
**Opciones**
|
||||
|
||||
- delay: 0 (milisegundos)
|
||||
- media: url de imagen
|
||||
- buttons: array `[{body:'Boton1'}, {body:'Boton2'}, {body:'Boton3'}]`
|
||||
- capture: true (para esperar respuesta)
|
||||
- child: Objecto tipo flujo o arra de flujos hijos
|
||||
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje se enviara 1 segundo despues', {
|
||||
delay: 1000,
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje envia una imagen', {
|
||||
media: 'https://i.imgur.com/0HpzsEm.png',
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje envia tres botones', {
|
||||
buttons: [{ body: 'Boton 1' }, { body: 'Boton 2' }, { body: 'Boton 3' }],
|
||||
})
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Este mensaje espera una respueta del usuario', {
|
||||
capture: true,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ctx
|
||||
|
||||
Este argumento se utiliza para obtener el contexto de la conversación
|
||||
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx) => {
|
||||
console.log('👉 Informacion del contexto: ', ctx)
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## fallBack()
|
||||
|
||||
Esta funcion se utliza para volver a enviar el ultimo mensaje abajo un ejemplo.
|
||||
En el ejemplo de abajo esperamos que el usuario ingrese un mensaje que contenga `@` sino contiene
|
||||
se repetira el mensaje `Indica cual es tu email`
|
||||
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola').addAnswer('Indica cual es tu email', null, (ctx, { fallBack }) => {
|
||||
if (!ctx.body.includes('@')) return fallBack()
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## flowDynamic()
|
||||
|
||||
Esta funcion se utliza para devolver mensajes dinamicos que pueden venir de una API o Base de datos.
|
||||
La funcion recibe un array que debe contener la siguiente estrucutura:
|
||||
|
||||
`[{body:'Mensaje}, {body:'Mensaje2}]`
|
||||
|
||||
```js
|
||||
const { addKeyword } = require('@bot-whatsapp/bot')
|
||||
|
||||
const flowString = addKeyword('hola')
|
||||
.addAnswer('Indica cual es tu email', null, async (ctx, {flowDynamic}) => {
|
||||
const mensajesDB = () => {
|
||||
const categories = db.find(...)
|
||||
const mapDatos = categories.map((c) => ({body:c.name}))
|
||||
return mapDatos
|
||||
}
|
||||
await flowDynamic(mensajesDB())
|
||||
})
|
||||
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## endFlow()
|
||||
|
||||
Esta funcion se utliza para finalizar un flujo con dos o más addAnswer. Un ejemplo de uso sería registrar 3 datos de un usuario en 3 preguntas distinas y
|
||||
que el usuario pueda finalizar por él mismo el flujo.
|
||||
Como podrás comprobar en el ejemplo siguiente, se puede vincular flowDynamic y todas sus funciones; como por ejemplo botones.
|
||||
|
||||
```js
|
||||
const flowFormulario = addKeyword(['Hola'])
|
||||
.addAnswer(
|
||||
['Hola!', 'Escriba su *Nombre* para generar su solicitud'],
|
||||
{ capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] },
|
||||
async (ctx, { flowDynamic, endFlow }) => {
|
||||
if (ctx.body == '❌ Cancelar solicitud') {
|
||||
await flowDynamic([
|
||||
{
|
||||
body: '❌ *Su solicitud de cita ha sido cancelada* ❌',
|
||||
buttons: [{ body: '⬅️ Volver al Inicio' }],
|
||||
},
|
||||
])
|
||||
return endFlow()
|
||||
}
|
||||
}
|
||||
)
|
||||
.addAnswer(
|
||||
['También necesito tus dos apellidos'],
|
||||
{ capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] },
|
||||
async (ctx, { flowDynamic, endFlow }) => {
|
||||
if (ctx.body == '❌ Cancelar solicitud') {
|
||||
await flowDynamic([
|
||||
{
|
||||
body: '❌ *Su solicitud de cita ha sido cancelada* ❌',
|
||||
buttons: [{ body: '⬅️ Volver al Inicio' }],
|
||||
},
|
||||
])
|
||||
return endFlow()
|
||||
}
|
||||
}
|
||||
)
|
||||
.addAnswer(
|
||||
['Dejeme su número de teléfono y le llamaré lo antes posible.'],
|
||||
{ capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] },
|
||||
async (ctx, { flowDynamic, endFlow }) => {
|
||||
if (ctx.body == '❌ Cancelar solicitud') {
|
||||
await flowDynamic([
|
||||
{
|
||||
body: '❌ *Su solicitud de cita ha sido cancelada* ❌',
|
||||
buttons: [{ body: '⬅️ Volver al Inicio' }],
|
||||
},
|
||||
])
|
||||
return endFlow()
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# QRPortalWeb
|
||||
|
||||
Argumento para asignar nombre y puerto al BOT
|
||||
|
||||
```js
|
||||
const BOTNAME = 'bot'
|
||||
QRPortalWeb({ name: BOTNAME, port: 3005 })
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<Navigation
|
||||
pages={[
|
||||
{ name: 'Conceptos', link: '/docs/essential' },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user