mirror of
https://github.com/cheveguerra/bot-whatsapp.git
synced 2026-04-21 04:59:15 +00:00
Compare commits
127 Commits
feature/pr
...
contributo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1d5cc14a1 | ||
|
|
186c48d884 | ||
|
|
bb31045a95 | ||
|
|
74fb3b864d | ||
|
|
88c05c12a4 | ||
|
|
5260a7eb47 | ||
|
|
9e1698b729 | ||
|
|
811618b256 | ||
|
|
331d2a309c | ||
|
|
318ac3adec | ||
|
|
0a69b8d9b5 | ||
|
|
f434d6a101 | ||
|
|
753d80b93e | ||
|
|
c07e148dfd | ||
|
|
3f30a1cb51 | ||
|
|
9b679192db | ||
|
|
f7d90efc2f | ||
|
|
0aa793e08c | ||
|
|
eeb4bb305e | ||
|
|
012d43847c | ||
|
|
87a4203cd5 | ||
|
|
f6114affad | ||
|
|
15b64185cb | ||
|
|
b655ae449e | ||
|
|
1c66f178a5 | ||
|
|
f201c5097b | ||
|
|
b33e34692d | ||
|
|
8f967578c6 | ||
|
|
fd2847aea0 | ||
|
|
f95331d3dc | ||
|
|
791ab8e970 | ||
|
|
880c729199 | ||
|
|
8da4b204b4 | ||
|
|
3fdd49ff86 | ||
|
|
e22780d3fa | ||
|
|
0ad4c58457 | ||
|
|
f8c7184487 | ||
|
|
b2afa45352 | ||
|
|
dcb0566d2b | ||
|
|
cbe438b778 | ||
|
|
6ff1a3a980 | ||
|
|
dceb13f4f5 | ||
|
|
bbbdb1c206 | ||
|
|
bd7d150c04 | ||
|
|
9dd7c02b6a | ||
|
|
11a74b8bea | ||
|
|
e7a8e85ead | ||
|
|
6bfbae7b94 | ||
|
|
d5d7f9dfee | ||
|
|
0a23d2c761 | ||
|
|
b2feaea588 | ||
|
|
7e2bf22d63 | ||
|
|
a4b610e21f | ||
|
|
120520df50 | ||
|
|
1551aafd54 | ||
|
|
eca876db9c | ||
|
|
96a387ed50 | ||
|
|
558013b2b4 | ||
|
|
58df7ddc71 | ||
|
|
e25f3abf1c | ||
|
|
0f6b82a9ab | ||
|
|
8f505bdb2b | ||
|
|
24220822f4 | ||
|
|
14d1a61fa2 | ||
|
|
943fe8698c | ||
|
|
371b403456 | ||
|
|
e19c3a25a4 | ||
|
|
eab39e4ac0 | ||
|
|
77145bcc54 | ||
|
|
8f241834e8 | ||
|
|
5174c6b3bb | ||
|
|
f3ed6da4ba | ||
|
|
0dc839e531 | ||
|
|
7475d6f8fd | ||
|
|
a6a33ac7b7 | ||
|
|
71c969f3e9 | ||
|
|
cebfed0382 | ||
|
|
e89ad450a1 | ||
|
|
ac39ac831c | ||
|
|
0af74602f5 | ||
|
|
767e0764d6 | ||
|
|
b2a3343f82 | ||
|
|
5ddd885554 | ||
|
|
7078dc4c93 | ||
|
|
c7e829e954 | ||
|
|
5a81a77802 | ||
|
|
588411653e | ||
|
|
3c4b1c0fc4 | ||
|
|
0f06fd3e80 | ||
|
|
79cc31a96f | ||
|
|
7067b4a80b | ||
|
|
aa7e4239ae | ||
|
|
877252bd4a | ||
|
|
f5a7de3a00 | ||
|
|
c792d47344 | ||
|
|
f6130cf0b9 | ||
|
|
9f9d833925 | ||
|
|
02c0d8af76 | ||
|
|
880d5323e8 | ||
|
|
9bb33582fb | ||
|
|
c8ff84e9cd | ||
|
|
e942bd1d5e | ||
|
|
7e557bdd30 | ||
|
|
fcd1a63676 | ||
|
|
4ade5f02a7 | ||
|
|
05c834d6b1 | ||
|
|
234cc3ffb6 | ||
|
|
e321f35d86 | ||
|
|
5edd755491 | ||
|
|
10748a46a4 | ||
|
|
5b3136999b | ||
|
|
cb047cca8e | ||
|
|
4b8c09633e | ||
|
|
7cabc53eed | ||
|
|
40c34dd7a5 | ||
|
|
7e25dcaa93 | ||
|
|
bfa622fad0 | ||
|
|
e88141077f | ||
|
|
d743fdcfe3 | ||
|
|
1261580004 | ||
|
|
a14c67ad45 | ||
|
|
c5af1f8107 | ||
|
|
01a4edb7e3 | ||
|
|
98793d0cfc | ||
|
|
8cbfd560a3 | ||
|
|
13e0530c01 | ||
|
|
04c5209cac |
15
.github/workflows/releases-dev.yml
vendored
15
.github/workflows/releases-dev.yml
vendored
@@ -10,9 +10,15 @@ jobs:
|
|||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
commit: ${{ steps.vars.outputs.commit }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: ${{github.event.after}}
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
@@ -50,8 +56,9 @@ jobs:
|
|||||||
- name: Release @bot-whatsapp/portal
|
- name: Release @bot-whatsapp/portal
|
||||||
run: yarn node ./scripts/release.js --name=portal --version= --token="${{ secrets.NPM_TOKEN }}"
|
run: yarn node ./scripts/release.js --name=portal --version= --token="${{ secrets.NPM_TOKEN }}"
|
||||||
|
|
||||||
- name: Commit Versioning & Push changes
|
- name: Commit & Push changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
uses: actions-js/push@master
|
||||||
with:
|
with:
|
||||||
commit_message: 'ci(version): :zap: automatic - "${date}" updated versions every packages'
|
branch: release/next
|
||||||
branch: dev
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
force: true
|
||||||
|
|||||||
14
.github/workflows/releases.yml
vendored
14
.github/workflows/releases.yml
vendored
@@ -67,13 +67,9 @@ jobs:
|
|||||||
- name: Release Github
|
- name: Release Github
|
||||||
run: yarn node ./scripts/github.js --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.OCTO_TOKEN }}"
|
run: yarn node ./scripts/github.js --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.OCTO_TOKEN }}"
|
||||||
|
|
||||||
- name: 'Run if changes have been detected'
|
- name: Commit & Push changes
|
||||||
run: |
|
uses: actions-js/push@master
|
||||||
git add .
|
|
||||||
git commit -m "chore(version): pre release"
|
|
||||||
|
|
||||||
- name: Commit Versioning & Push changes
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
|
||||||
with:
|
with:
|
||||||
commit_message: 'chore(version): launch release 🚀 "${{ steps.package-version.outputs.current-version}}"'
|
branch: release/production
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
force: true
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
|
/packages/repl
|
||||||
/packages/*/starters
|
/packages/*/starters
|
||||||
/packages/*/node_modules
|
/packages/*/node_modules
|
||||||
/packages/*/dist
|
/packages/*/dist
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"tabWidth": 4,
|
"tabWidth": 4,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true
|
"singleQuote": true,
|
||||||
|
"printWidth": 120
|
||||||
}
|
}
|
||||||
|
|||||||
71
CHANGELOG.md
71
CHANGELOG.md
@@ -2,6 +2,77 @@
|
|||||||
|
|
||||||
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.
|
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.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)
|
### [0.1.17](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.16...v0.1.17) (2023-01-13)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
100
README.md
100
README.md
@@ -1,8 +1,7 @@
|
|||||||
# Chatbot Library
|
# Chatbot Library
|
||||||

|

|
||||||
[](http://commitizen.github.io/cz-cli/)
|
[](http://commitizen.github.io/cz-cli/)
|
||||||
[](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml)
|
[](https://link.codigoencasa.com/DISCORD)
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="300" src="https://i.imgur.com/Oauef6t.png">
|
<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 -->
|
<!-- readme: collaborators,contributors -start -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<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">
|
<td align="center">
|
||||||
<a href="https://github.com/leifermendez">
|
<a href="https://github.com/leifermendez">
|
||||||
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
|
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
|
||||||
@@ -42,10 +48,10 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/aurik3">
|
<a href="https://github.com/leifermendezfroged">
|
||||||
<img src="https://avatars.githubusercontent.com/u/37228512?v=4" width="50;" alt="aurik3"/>
|
<img src="https://avatars.githubusercontent.com/u/97020486?v=4" width="50;" alt="leifermendezfroged"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Null</b></sub>
|
<sub><b>Leifer Mendez</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
@@ -56,10 +62,25 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/leifermendezfroged">
|
<a href="https://github.com/danielcasta0398">
|
||||||
<img src="https://avatars.githubusercontent.com/u/97020486?v=4" width="50;" alt="leifermendezfroged"/>
|
<img src="https://avatars.githubusercontent.com/u/98791147?v=4" width="50;" alt="danielcasta0398"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Leifer Mendez</b></sub>
|
<sub><b>Juan Daniel Castaño</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/aurik3">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/37228512?v=4" width="50;" alt="aurik3"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Null</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></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>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
@@ -75,8 +96,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
|||||||
<br />
|
<br />
|
||||||
<sub><b>Zvi</b></sub>
|
<sub><b>Zvi</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td></tr>
|
</td>
|
||||||
<tr>
|
<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">
|
<td align="center">
|
||||||
<a href="https://github.com/Gonzalito87">
|
<a href="https://github.com/Gonzalito87">
|
||||||
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
|
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
|
||||||
@@ -84,20 +111,57 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
|
|||||||
<sub><b>Null</b></sub>
|
<sub><b>Null</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</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/Jhonarias13">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/19483021?v=4" width="50;" alt="Jhonarias13"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Jhon Freiman Arias</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/tonyvazgar">
|
<a href="https://github.com/tonyvazgar">
|
||||||
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
|
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Luis Antonio Vázquez García</b></sub>
|
<sub><b>Luis Antonio Vázquez García</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td></tr>
|
||||||
<td align="center">
|
<tr>
|
||||||
<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">
|
<td align="center">
|
||||||
<a href="https://github.com/rrruuuyyy">
|
<a href="https://github.com/rrruuuyyy">
|
||||||
<img src="https://avatars.githubusercontent.com/u/33061671?v=4" width="50;" alt="rrruuuyyy"/>
|
<img src="https://avatars.githubusercontent.com/u/33061671?v=4" width="50;" alt="rrruuuyyy"/>
|
||||||
|
|||||||
41
__test__/01-case.test.js
Normal file
41
__test__/01-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_DB = require('../packages/provider/src/mock')
|
||||||
|
const {
|
||||||
|
addKeyword,
|
||||||
|
createBot,
|
||||||
|
createFlow,
|
||||||
|
createProvider,
|
||||||
|
} = require('../packages/bot')
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
99
__test__/02-case.test.js
Normal file
99
__test__/02-case.test.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
44
__test__/03-case.test.js
Normal file
44
__test__/03-case.test.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
82
__test__/04-case.test.js
Normal file
82
__test__/04-case.test.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
118
__test__/05-case.test.js
Normal file
118
__test__/05-case.test.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
111
__test__/06-case.test.js
Normal file
111
__test__/06-case.test.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bot-whatsapp/root",
|
"name": "@bot-whatsapp/root",
|
||||||
"version": "0.1.17",
|
"version": "0.1.19",
|
||||||
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
|
"description": "Bot de wahtsapp open source para MVP o pequeños negocios",
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
"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",
|
"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",
|
"copy.lib": "node ./scripts/move.js",
|
||||||
"test.unit": "node ./node_modules/uvu/bin.js packages test",
|
"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",
|
"test": "npm run test.coverage",
|
||||||
"cli": "node ./packages/cli/bin/cli.js",
|
"cli": "node ./packages/cli/bin/cli.js",
|
||||||
"create": "node ./packages/create-bot-whatsapp/bin/create.js",
|
"create": "node ./packages/create-bot-whatsapp/bin/create.js",
|
||||||
@@ -80,6 +81,7 @@
|
|||||||
"fs-extra": "^11.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
"git-cz": "^4.9.0",
|
"git-cz": "^4.9.0",
|
||||||
"husky": "^8.0.2",
|
"husky": "^8.0.2",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
"only-allow": "^1.1.1",
|
"only-allow": "^1.1.1",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ class CoreClass {
|
|||||||
flowClass
|
flowClass
|
||||||
databaseClass
|
databaseClass
|
||||||
providerClass
|
providerClass
|
||||||
constructor(_flow, _database, _provider) {
|
generalArgs = { blackList: [] }
|
||||||
|
constructor(_flow, _database, _provider, _args) {
|
||||||
this.flowClass = _flow
|
this.flowClass = _flow
|
||||||
this.databaseClass = _database
|
this.databaseClass = _database
|
||||||
this.providerClass = _provider
|
this.providerClass = _provider
|
||||||
|
this.generalArgs = { ...this.generalArgs, ..._args }
|
||||||
|
|
||||||
for (const { event, func } of this.listenerBusEvents()) {
|
for (const { event, func } of this.listenerBusEvents()) {
|
||||||
this.providerClass.on(event, func)
|
this.providerClass.on(event, func)
|
||||||
@@ -69,11 +71,13 @@ class CoreClass {
|
|||||||
logger.log(`[handleMsg]: `, messageCtxInComming)
|
logger.log(`[handleMsg]: `, messageCtxInComming)
|
||||||
const { body, from } = messageCtxInComming
|
const { body, from } = messageCtxInComming
|
||||||
let msgToSend = []
|
let msgToSend = []
|
||||||
|
let endFlowFlag = false
|
||||||
let fallBackFlag = false
|
let fallBackFlag = false
|
||||||
|
if (this.generalArgs.blackList.includes(from)) return
|
||||||
if (!body) return
|
if (!body) return
|
||||||
if (!body.length) return
|
if (!body.length) return
|
||||||
|
|
||||||
const prevMsg = await this.databaseClass.getPrevByNumber(from)
|
let prevMsg = await this.databaseClass.getPrevByNumber(from)
|
||||||
const refToContinue = this.flowClass.findBySerialize(
|
const refToContinue = this.flowClass.findBySerialize(
|
||||||
prevMsg?.refSerialize
|
prevMsg?.refSerialize
|
||||||
)
|
)
|
||||||
@@ -87,16 +91,68 @@ class CoreClass {
|
|||||||
this.databaseClass.save(ctxByNumber)
|
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) => {
|
||||||
|
prevMsg = null
|
||||||
|
endFlowFlag = true
|
||||||
|
if (message)
|
||||||
|
this.sendProviderAndSave(from, createCtxMessage(message))
|
||||||
|
clearQueue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 📄 Continuar con el siguiente flujo
|
||||||
|
const continueFlow = async () => {
|
||||||
|
const cotinueMessage =
|
||||||
|
this.flowClass.find(refToContinue?.ref, true) || []
|
||||||
|
sendFlow(cotinueMessage, from, { continue: true })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
|
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
|
||||||
const sendFlow = async (messageToSend, numberOrId) => {
|
const sendFlow = async (
|
||||||
|
messageToSend,
|
||||||
|
numberOrId,
|
||||||
|
options = { continue: false }
|
||||||
|
) => {
|
||||||
|
if (!options.continue && prevMsg?.options?.capture)
|
||||||
|
await cbEveryCtx(prevMsg?.ref)
|
||||||
|
|
||||||
const queue = []
|
const queue = []
|
||||||
for (const ctxMessage of messageToSend) {
|
for (const ctxMessage of messageToSend) {
|
||||||
|
if (endFlowFlag) return
|
||||||
const delayMs = ctxMessage?.options?.delay || 0
|
const delayMs = ctxMessage?.options?.delay || 0
|
||||||
if (delayMs) await delay(delayMs)
|
if (delayMs) await delay(delayMs)
|
||||||
QueuePrincipal.enqueue(() =>
|
QueuePrincipal.enqueue(() =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
this.sendProviderAndSave(numberOrId, ctxMessage),
|
this.sendProviderAndSave(numberOrId, ctxMessage).then(
|
||||||
resolveCbEveryCtx(ctxMessage),
|
() => resolveCbEveryCtx(ctxMessage)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -104,42 +160,41 @@ class CoreClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
|
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
|
||||||
const fallBack = async () => {
|
const fallBack = async (next = false, message = null) => {
|
||||||
fallBackFlag = true
|
|
||||||
await this.sendProviderAndSave(from, refToContinue)
|
|
||||||
QueuePrincipal.queue = []
|
QueuePrincipal.queue = []
|
||||||
return refToContinue
|
if (next) return continueFlow()
|
||||||
|
return this.sendProviderAndSave(from, {
|
||||||
|
...prevMsg,
|
||||||
|
answer:
|
||||||
|
typeof message === 'string'
|
||||||
|
? message
|
||||||
|
: message?.body ?? prevMsg.answer,
|
||||||
|
options: {
|
||||||
|
...prevMsg.options,
|
||||||
|
buttons: message?.buttons ?? prevMsg.options?.buttons,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
|
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
|
||||||
// para evitar bloque de whatsapp
|
// para evitar bloque de whatsapp
|
||||||
const flowDynamic = async (
|
|
||||||
listMsg = [],
|
|
||||||
optListMsg = { limit: 5, fallback: false }
|
|
||||||
) => {
|
|
||||||
if (!Array.isArray(listMsg))
|
|
||||||
throw new Error('Esto debe ser un ARRAY')
|
|
||||||
|
|
||||||
fallBackFlag = optListMsg.fallback
|
const flowDynamic = async (listMsg = []) => {
|
||||||
const parseListMsg = listMsg
|
if (!Array.isArray(listMsg)) listMsg = [listMsg]
|
||||||
.map(({ body }, index) =>
|
|
||||||
toCtx({
|
const parseListMsg = listMsg.map((opt, index) =>
|
||||||
body,
|
createCtxMessage(opt, index)
|
||||||
from,
|
)
|
||||||
keyword: null,
|
|
||||||
index,
|
if (endFlowFlag) return
|
||||||
})
|
|
||||||
)
|
|
||||||
.slice(0, optListMsg.limit)
|
|
||||||
for (const msg of parseListMsg) {
|
for (const msg of parseListMsg) {
|
||||||
await this.sendProviderAndSave(from, msg)
|
await this.sendProviderAndSave(from, msg)
|
||||||
}
|
}
|
||||||
return
|
return continueFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
|
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
|
||||||
const resolveCbEveryCtx = async (ctxMessage) => {
|
const resolveCbEveryCtx = async (ctxMessage) => {
|
||||||
if (prevMsg?.options?.capture) return cbEveryCtx(prevMsg?.ref)
|
|
||||||
if (!ctxMessage?.options?.capture)
|
if (!ctxMessage?.options?.capture)
|
||||||
return await cbEveryCtx(ctxMessage?.ref)
|
return await cbEveryCtx(ctxMessage?.ref)
|
||||||
}
|
}
|
||||||
@@ -150,22 +205,13 @@ class CoreClass {
|
|||||||
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
|
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
|
||||||
fallBack,
|
fallBack,
|
||||||
flowDynamic,
|
flowDynamic,
|
||||||
|
endFlow,
|
||||||
|
continueFlow,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevMsg?.ref) resolveCbEveryCtx(prevMsg)
|
|
||||||
|
|
||||||
// 📄 [options: callback]: Si se tiene un callback se ejecuta
|
|
||||||
//TODO AQUI
|
|
||||||
// if (!fallBackFlag) {
|
|
||||||
// if (prevMsg?.options?.capture) cbEveryCtx(prevMsg?.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
|
// 📄🤘(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 nestedRef = prevMsg.options.nested
|
||||||
const flowStandalone = nestedRef.map((f) => ({
|
const flowStandalone = nestedRef.map((f) => ({
|
||||||
...nestedRef.find((r) => r.refSerialize === f.refSerialize),
|
...nestedRef.find((r) => r.refSerialize === f.refSerialize),
|
||||||
@@ -173,21 +219,15 @@ class CoreClass {
|
|||||||
|
|
||||||
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
|
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
|
||||||
|
|
||||||
// //TODO AQUI
|
|
||||||
// for (const ite of msgToSend) {
|
|
||||||
// cbEveryCtx(ite?.ref)
|
|
||||||
// }
|
|
||||||
|
|
||||||
sendFlow(msgToSend, from)
|
sendFlow(msgToSend, from)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📄🤘(tiene return) [options: capture (boolean)]: Si se tiene option boolean
|
// 📄🤘(tiene return) Si el mensaje previo implementa capture
|
||||||
if (!fallBackFlag && !prevMsg?.options?.nested?.length) {
|
if (!endFlowFlag && !prevMsg?.options?.nested?.length) {
|
||||||
const typeCapture = typeof prevMsg?.options?.capture
|
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) || []
|
msgToSend = this.flowClass.find(refToContinue?.ref, true) || []
|
||||||
sendFlow(msgToSend, from)
|
sendFlow(msgToSend, from)
|
||||||
return
|
return
|
||||||
@@ -213,6 +253,7 @@ class CoreClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated
|
||||||
* @private
|
* @private
|
||||||
* @param {*} message
|
* @param {*} message
|
||||||
* @param {*} ref
|
* @param {*} ref
|
||||||
@@ -225,5 +266,24 @@ class CoreClass {
|
|||||||
this.continue(null, responde.ref)
|
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
|
module.exports = CoreClass
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
|
|||||||
* @param {*} args
|
* @param {*} args
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const createBot = async ({ flow, database, provider }) =>
|
const createBot = async ({ flow, database, provider }, args = {}) =>
|
||||||
new CoreClass(flow, database, provider)
|
new CoreClass(flow, database, provider, args)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crear instancia de clase Io (Flow)
|
* Crear instancia de clase Io (Flow)
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ const { generateRef, generateRefSerialize } = require('../../utils/hash')
|
|||||||
* @param options {media:string, buttons:[], capture:true default false}
|
* @param options {media:string, buttons:[], capture:true default false}
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const toCtx = ({ body, from, prevRef, index }) => {
|
const toCtx = ({ body, from, prevRef, options = {}, index }) => {
|
||||||
return {
|
return {
|
||||||
ref: generateRef(),
|
ref: generateRef(),
|
||||||
keyword: prevRef,
|
keyword: prevRef,
|
||||||
answer: body,
|
answer: body,
|
||||||
options: {},
|
options: options ?? {},
|
||||||
from,
|
from,
|
||||||
refSerialize: generateRefSerialize({ index, answer: body }),
|
refSerialize: generateRefSerialize({ index, answer: body }),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bot-whatsapp/bot",
|
"name": "@bot-whatsapp/bot",
|
||||||
"version": "0.0.66-alpha.0",
|
"version": "0.0.91-alpha.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./lib/bundle.bot.cjs",
|
"main": "./lib/bundle.bot.cjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
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()
|
||||||
@@ -48,11 +48,11 @@ const nextSteps = async () => {
|
|||||||
name: 'providerWs',
|
name: 'providerWs',
|
||||||
message: '¿Cuál proveedor de whatsapp quieres utilizar?',
|
message: '¿Cuál proveedor de whatsapp quieres utilizar?',
|
||||||
choices: [
|
choices: [
|
||||||
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
|
|
||||||
{ title: 'Venom (gratis)', value: 'venom' },
|
|
||||||
{ title: 'Baileys (gratis)', value: 'baileys' },
|
{ title: 'Baileys (gratis)', value: 'baileys' },
|
||||||
|
{ title: 'Venom (gratis)', value: 'venom' },
|
||||||
|
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
|
||||||
{ title: 'Twilio', value: 'twilio' },
|
{ title: 'Twilio', value: 'twilio' },
|
||||||
{ title: 'API Oficial (Meta)', value: 'meta' },
|
{ title: 'Meta', value: 'meta' },
|
||||||
],
|
],
|
||||||
max: 1,
|
max: 1,
|
||||||
hint: 'Espacio para seleccionar',
|
hint: 'Espacio para seleccionar',
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class DialogFlowCXContext extends CoreClass {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.sendFlow(listMessages, from)
|
this.sendFlowSimple(listMessages, from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class DialogFlowContext extends CoreClass {
|
|||||||
...customPayload,
|
...customPayload,
|
||||||
answer: fields?.answer?.stringValue,
|
answer: fields?.answer?.stringValue,
|
||||||
}
|
}
|
||||||
this.sendFlow([ctxFromDX], from)
|
this.sendFlowSimple([ctxFromDX], from)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ class DialogFlowContext extends CoreClass {
|
|||||||
answer: queryResult?.fulfillmentText,
|
answer: queryResult?.fulfillmentText,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendFlow([ctxFromDX], from)
|
this.sendFlowSimple([ctxFromDX], from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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 |
213
packages/docs/src/components/atoms/DigitalOcean.tsx
Normal file
213
packages/docs/src/components/atoms/DigitalOcean.tsx
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
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>
|
||||||
|
)
|
||||||
@@ -14,7 +14,7 @@ export default component$(
|
|||||||
<a href={props.user.html_url} target="_blank">
|
<a href={props.user.html_url} target="_blank">
|
||||||
<img
|
<img
|
||||||
class="w-16 h-16 rounded-full mx-auto object-cover"
|
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}
|
alt={props.user.login}
|
||||||
width="80"
|
width="80"
|
||||||
height="80"
|
height="80"
|
||||||
@@ -23,7 +23,9 @@ export default component$(
|
|||||||
|
|
||||||
<div class="pt-2 space-y-4 justify-center flex">
|
<div class="pt-2 space-y-4 justify-center flex">
|
||||||
<figcaption class="text-sm">
|
<figcaption class="text-sm">
|
||||||
<div class={'font-semibold'}>{props.user.login}</div>
|
<div class={'font-semibold truncate'}>
|
||||||
|
{props.user.login}
|
||||||
|
</div>
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default component$(() => {
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
target={'_blank'}
|
target={'_blank'}
|
||||||
href="https://youtu.be/DEIyGyJNGa8"
|
href="https://youtu.be/UgoS8PXxe-A"
|
||||||
class="btn bg-gray-50 dark:bg-transparent"
|
class="btn bg-gray-50 dark:bg-transparent"
|
||||||
>
|
>
|
||||||
Ver video
|
Ver video
|
||||||
|
|||||||
54
packages/docs/src/components/widgets/Members.tsx
Normal file
54
packages/docs/src/components/widgets/Members.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
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>
|
||||||
|
)
|
||||||
|
})
|
||||||
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'
|
import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { src as netlify } from '~/assets/images/full-logo-light.png?width=100&metadata'
|
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
|
* options = [] array con la lista de opciones de la documentacion
|
||||||
@@ -41,7 +43,20 @@ export default component$(() => {
|
|||||||
<img
|
<img
|
||||||
src={netlify}
|
src={netlify}
|
||||||
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
|
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"
|
loading="eager"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -52,16 +52,22 @@ export default component$(() => {
|
|||||||
title: 'Avanzado',
|
title: 'Avanzado',
|
||||||
list: [
|
list: [
|
||||||
{ name: 'Migración', link: '/docs/migration' },
|
{ 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',
|
title: 'Comunidad',
|
||||||
list: [
|
list: [
|
||||||
{ name: 'MasterClass', link: '/docs/masterclass' },
|
|
||||||
{ name: 'Colabores', link: '/docs/contributing' },
|
{ name: 'Colabores', link: '/docs/contributing' },
|
||||||
{ name: 'Unirme al proyecto', link: '/docs/join' },
|
{ name: 'Unirme al proyecto', link: '/docs/join' },
|
||||||
{ name: 'Sponsors', link: '/docs/sponsors' },
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
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
|
||||||
@@ -23,6 +23,26 @@ 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()
|
## addKeyword()
|
||||||
|
|
||||||
Esta funcion se utliza para iniciar un flujo de conversion. <br /> Recibe un `string` o un `array`
|
Esta funcion se utliza para iniciar un flujo de conversion. <br /> Recibe un `string` o un `array`
|
||||||
@@ -55,7 +75,7 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
|
|||||||
- delay: 0 (milisegundos)
|
- delay: 0 (milisegundos)
|
||||||
- media: url de imagen
|
- media: url de imagen
|
||||||
- buttons: array `[{body:'Boton1'}, {body:'Boton2'}, {body:'Boton3'}]`
|
- buttons: array `[{body:'Boton1'}, {body:'Boton2'}, {body:'Boton3'}]`
|
||||||
- capture: false (para esperar respuesta)
|
- capture: true (para esperar respuesta)
|
||||||
- child: Objecto tipo flujo o arra de flujos hijos
|
- child: Objecto tipo flujo o arra de flujos hijos
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -159,6 +179,74 @@ const flowString = addKeyword('hola')
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 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
|
<Navigation
|
||||||
pages={[
|
pages={[
|
||||||
{ name: 'Conceptos', link: '/docs/essential' },
|
{ name: 'Conceptos', link: '/docs/essential' },
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { DocumentHead } from '@builder.io/qwik-city'
|
|||||||
import ExtraBar from '~/components/widgets/ExtraBar'
|
import ExtraBar from '~/components/widgets/ExtraBar'
|
||||||
import Header from '~/components/widgets/Header'
|
import Header from '~/components/widgets/Header'
|
||||||
import NavBar from '~/components/widgets/NavBar'
|
import NavBar from '~/components/widgets/NavBar'
|
||||||
|
// import { SearchModal } from '~/components/widgets/SearchModal'
|
||||||
import SponsorBar from '~/components/widgets/SponsorBar'
|
import SponsorBar from '~/components/widgets/SponsorBar'
|
||||||
import { GlobalStore } from '~/contexts'
|
import { GlobalStore } from '~/contexts'
|
||||||
// import Navigation from '~/components/widgets/Navigation'
|
// import Navigation from '~/components/widgets/Navigation'
|
||||||
@@ -14,6 +15,7 @@ export default component$(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* <SearchModal /> */}
|
||||||
<Header />
|
<Header />
|
||||||
<main class={'overflow-hidden'}>
|
<main class={'overflow-hidden'}>
|
||||||
<div class={'max-w-8xl'}>
|
<div class={'max-w-8xl'}>
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
[](https://hackmd.io/79xQyVSgRD6RsTpqtMPPdw)
|
|
||||||
### Preguntas Frecuentes para Master Class BOT v2
|
|
||||||
> Anota aqui las preguntas o dudas que tengas
|
|
||||||
> Pronto estare publicando fecha y hora para la masterclass
|
|
||||||
|
|
||||||
1.- Si necesito correr dos bots al mismo tiempo ¿donde puedo cambiar el puerto?
|
|
||||||
|
|
||||||
2.- Si necesito agregar o modificar funciones del bot, ¿como puedo hacerlo?
|
|
||||||
|
|
||||||
3.- Si quiero mi bot con otra base de datos diferente a MySQL ¿como lo puedo hacer?
|
|
||||||
|
|
||||||
4.- Quiero conectarme a tal o cual API con JSON/XML/etc, ¿se puede hacer?
|
|
||||||
|
|
||||||
5.- ¿Como integrar listas?
|
|
||||||
|
|
||||||
6.- Preguntas y respuestas con el Bot
|
|
||||||
|
|
||||||
7.- Guardar conversaciones en Excel.
|
|
||||||
|
|
||||||
8.- ¿Puedo usar 2 o mas sesiones (códigos QR) al mismo tiempo?
|
|
||||||
|
|
||||||
9.- ¿Puede ser que al usar el provider bailey, al leer el qr.png, que sea desde una url en el navegador, y no desde visual studio? Gracias
|
|
||||||
|
|
||||||
10.- ¿Cómo tomo los datos que me envían en un mensaje para utilizarlo internamente en la búsqueda de datos propios y devolver la respuesta?
|
|
||||||
26
packages/docs/src/routes/docs/masterclass/index.mdx
Normal file
26
packages/docs/src/routes/docs/masterclass/index.mdx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# MasterClass
|
||||||
|
|
||||||
|
<iframe
|
||||||
|
width="560"
|
||||||
|
height="315"
|
||||||
|
src="https://www.youtube.com/embed/22jiE2Z3XGM"
|
||||||
|
title="YouTube video player"
|
||||||
|
frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen
|
||||||
|
></iframe>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Preguntas de la masterclass
|
||||||
|
|
||||||
|
- Si necesito correr dos bots al mismo tiempo ¿donde puedo cambiar el puerto?
|
||||||
|
- Si necesito agregar o modificar funciones del bot, ¿como puedo hacerlo?
|
||||||
|
- Si quiero mi bot con otra base de datos diferente a MySQL ¿como lo puedo hacer?
|
||||||
|
- Quiero conectarme a tal o cual API con JSON/XML/etc, ¿se puede hacer?
|
||||||
|
- ¿Como integrar listas?
|
||||||
|
- Preguntas y respuestas con el Bot
|
||||||
|
- Guardar conversaciones en Excel.
|
||||||
|
- ¿Puedo usar 2 o mas sesiones (códigos QR) al mismo tiempo?
|
||||||
|
- ¿Puede ser que al usar el provider bailey, al leer el qr.png, que sea desde una url en el navegador, y no desde visual studio? Gracias
|
||||||
|
- ¿Cómo tomo los datos que me envían en un mensaje para utilizarlo internamente en la búsqueda de datos propios y devolver la respuesta?
|
||||||
@@ -5,16 +5,22 @@ import Features from '~/components/widgets/Features'
|
|||||||
import FAQs from '~/components/widgets/FAQs'
|
import FAQs from '~/components/widgets/FAQs'
|
||||||
import CallToAction from '~/components/widgets/CallToAction'
|
import CallToAction from '~/components/widgets/CallToAction'
|
||||||
import Collaborators from '~/components/widgets/Collaborators'
|
import Collaborators from '~/components/widgets/Collaborators'
|
||||||
|
import Members from '~/components/widgets/Members'
|
||||||
import { fetchGithub } from '~/services/github'
|
import { fetchGithub } from '~/services/github'
|
||||||
|
import { fetchOpenCollective } from '~/services/opencollective'
|
||||||
import { RequestHandlerNetlify } from '@builder.io/qwik-city/middleware/netlify-edge'
|
import { RequestHandlerNetlify } from '@builder.io/qwik-city/middleware/netlify-edge'
|
||||||
import { GITHUB_TOKEN } from './docs/constant'
|
import { GITHUB_TOKEN } from './docs/constant'
|
||||||
|
// import { SearchModal } from '~/components/widgets/SearchModal'
|
||||||
|
|
||||||
export const onGet: RequestHandlerNetlify = async ({ platform }) => {
|
export const onGet: RequestHandlerNetlify = async ({ platform }) => {
|
||||||
const CHECK_GITHUB_TOKEN =
|
const CHECK_GITHUB_TOKEN =
|
||||||
(platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
|
(platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
|
||||||
console.log(`[🚩 platform]: `, GITHUB_TOKEN)
|
const dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN)
|
||||||
const data = await fetchGithub(CHECK_GITHUB_TOKEN)
|
const dataOpenCollective = await fetchOpenCollective()
|
||||||
return data
|
return {
|
||||||
|
dataGithub,
|
||||||
|
dataOpenCollective,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default component$(() => {
|
export default component$(() => {
|
||||||
@@ -27,9 +33,16 @@ export default component$(() => {
|
|||||||
<CallToAction />
|
<CallToAction />
|
||||||
<Resource
|
<Resource
|
||||||
value={resource}
|
value={resource}
|
||||||
onResolved={(data: any) => <Collaborators users={data} />}
|
onResolved={(data: any) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Collaborators users={data.dataGithub} />
|
||||||
|
<FAQs />
|
||||||
|
<Members users={data.dataOpenCollective} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}}
|
||||||
></Resource>
|
></Resource>
|
||||||
<FAQs />
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ export const fetchGithub = async (token: string) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
const listUsers = data.json()
|
const listUsers = await data.json()
|
||||||
return listUsers
|
return listUsers.map((u: any) => ({
|
||||||
|
...u,
|
||||||
|
avatar_url: `${u.avatar_url}&s=80`,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
19
packages/docs/src/services/opencollective.ts
Normal file
19
packages/docs/src/services/opencollective.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* GET API from OpenCollective
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const fetchOpenCollective = async () => {
|
||||||
|
const data = await fetch(
|
||||||
|
`https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`,
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const listUsers = await data.json()
|
||||||
|
return listUsers.map((u: any) => ({
|
||||||
|
html_url: u.profile,
|
||||||
|
avatar_url: u.image ?? 'https://i.imgur.com/HhiYKwN.png',
|
||||||
|
login: u.name,
|
||||||
|
id: u.MemberId,
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
const notFounds = [
|
const notFounds = [
|
||||||
[
|
[
|
||||||
'/',
|
'/',
|
||||||
'<!DOCTYPE html>\n<html>\n<head>\n <meta charset="utf-8">\n <meta http-equiv="Status" content="404"/>\n <title>404 Resource Not Found</title>\n <meta name="viewport" content="width=device-width,initial-scale=1">\n <style>\n body { color: #006ce9; background-color: #fafafa; padding: 30px; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif; }\n p { max-width: 600px; margin: 60px auto 30px auto; background: white; border-radius: 4px; box-shadow: 0px 0px 50px -20px #006ce9; overflow: hidden; }\n strong { display: inline-block; padding: 15px; background: #006ce9; color: white; }\n span { display: inline-block; padding: 15px; }\n pre { max-width: 580px; margin: 0 auto; }\n </style>\n</head>\n<body>\n <p><strong>404</strong> <span>Resource Not Found</span></p>\n</body>\n</html>',
|
'<!DOCTYPE html>\n<html>\n <head>\n <meta charset="utf-8" />\n <meta http-equiv="Status" content="404" />\n <title>404 Resource Not Found</title>\n <meta name="viewport" content="width=device-width,initial-scale=1" />\n <style>\n body {\n color: #006ce9;\n background-color: #fafafa;\n padding: 30px;\n font-family: ui-sans-serif, system-ui, -apple-system,\n BlinkMacSystemFont, Roboto, sans-serif;\n }\n p {\n max-width: 600px;\n margin: 60px auto 30px auto;\n background: white;\n border-radius: 4px;\n box-shadow: 0px 0px 50px -20px #006ce9;\n overflow: hidden;\n }\n strong {\n display: inline-block;\n padding: 15px;\n background: #006ce9;\n color: white;\n }\n span {\n display: inline-block;\n padding: 15px;\n }\n pre {\n max-width: 580px;\n margin: 0 auto;\n }\n </style>\n </head>\n <body>\n <p><strong>404</strong> <span>Resource Not Found</span></p>\n </body>\n</html>\n',
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
function getNotFound(p) {
|
function getNotFound(p) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const staticPaths = new Set([
|
const staticPaths = new Set([
|
||||||
'/',
|
|
||||||
'/favicon.svg',
|
'/favicon.svg',
|
||||||
'/manifest.json',
|
'/manifest.json',
|
||||||
'/q-manifest.json',
|
'/q-manifest.json',
|
||||||
|
|||||||
65
packages/provider/common/download.js
Normal file
65
packages/provider/common/download.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
const mimeDep = require('mime-types')
|
||||||
|
const { tmpdir } = require('os')
|
||||||
|
const http = require('http')
|
||||||
|
const https = require('https')
|
||||||
|
const { rename, createWriteStream } = require('fs')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrar el mimetype from buffer
|
||||||
|
* @param {string} response
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const fileTypeFromFile = async (response) => {
|
||||||
|
const type = response.headers['content-type'] ?? null
|
||||||
|
const ext = mimeDep.extension(type)
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
ext,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Descargar archivo binay en tmp
|
||||||
|
* @param {*} url
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const generalDownload = async (url) => {
|
||||||
|
const handleDownload = () => {
|
||||||
|
const checkProtocol = url.includes('https:')
|
||||||
|
const handleHttp = checkProtocol ? https : http
|
||||||
|
const name = `tmp-${Date.now()}-dat`
|
||||||
|
const fullPath = `${tmpdir()}/${name}`
|
||||||
|
const file = createWriteStream(fullPath)
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
handleHttp.get(url, function (response) {
|
||||||
|
response.pipe(file)
|
||||||
|
file.on('finish', async function () {
|
||||||
|
file.close()
|
||||||
|
res({ response, fullPath })
|
||||||
|
})
|
||||||
|
file.on('error', function () {
|
||||||
|
file.close()
|
||||||
|
rej(null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFile = (pathInput, ext) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const fullPath = `${pathInput}.${ext}`
|
||||||
|
rename(pathInput, fullPath, (err) => {
|
||||||
|
if (err) reject(null)
|
||||||
|
resolve(fullPath)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const httpResponse = await handleDownload()
|
||||||
|
const { ext } = await fileTypeFromFile(httpResponse.response)
|
||||||
|
const getPath = await handleFile(httpResponse.fullPath, ext)
|
||||||
|
|
||||||
|
return getPath
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { generalDownload }
|
||||||
@@ -4,7 +4,7 @@ const pino = require('pino')
|
|||||||
const rimraf = require('rimraf')
|
const rimraf = require('rimraf')
|
||||||
const mime = require('mime-types')
|
const mime = require('mime-types')
|
||||||
const { join } = require('path')
|
const { join } = require('path')
|
||||||
const { existsSync, createWriteStream, readFileSync } = require('fs')
|
const { createWriteStream, readFileSync } = require('fs')
|
||||||
const { Console } = require('console')
|
const { Console } = require('console')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -13,13 +13,15 @@ const {
|
|||||||
Browsers,
|
Browsers,
|
||||||
DisconnectReason,
|
DisconnectReason,
|
||||||
} = require('@adiwajshing/baileys')
|
} = require('@adiwajshing/baileys')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
baileyGenerateImage,
|
baileyGenerateImage,
|
||||||
baileyCleanNumber,
|
baileyCleanNumber,
|
||||||
baileyIsValidNumber,
|
baileyIsValidNumber,
|
||||||
baileyDownloadMedia,
|
|
||||||
} = require('./utils')
|
} = require('./utils')
|
||||||
|
|
||||||
|
const { generalDownload } = require('../../common/download')
|
||||||
|
|
||||||
const logger = new Console({
|
const logger = new Console({
|
||||||
stdout: createWriteStream(`${process.cwd()}/baileys.log`),
|
stdout: createWriteStream(`${process.cwd()}/baileys.log`),
|
||||||
})
|
})
|
||||||
@@ -169,14 +171,50 @@ class BaileysProvider extends ProviderClass {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sendMedia = async (number, imageUrl, text) => {
|
sendMedia = async (number, imageUrl, text) => {
|
||||||
const fileDownloaded = await baileyDownloadMedia(imageUrl)
|
const fileDownloaded = await generalDownload(imageUrl)
|
||||||
|
const mimeType = mime.lookup(fileDownloaded)
|
||||||
|
|
||||||
|
if (mimeType.includes('image'))
|
||||||
|
return this.sendImage(number, fileDownloaded, text)
|
||||||
|
if (mimeType.includes('video'))
|
||||||
|
return this.sendVideo(number, fileDownloaded, text)
|
||||||
|
if (mimeType.includes('audio'))
|
||||||
|
return this.sendAudio(number, fileDownloaded, text)
|
||||||
|
|
||||||
|
return this.sendFile(number, fileDownloaded)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar imagen
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendImage = async (number, filePath, text) => {
|
||||||
return this.vendor.sendMessage(number, {
|
return this.vendor.sendMessage(number, {
|
||||||
image: readFileSync(fileDownloaded),
|
image: readFileSync(filePath),
|
||||||
caption: text,
|
caption: text,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Enviar video
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendVideo = async (number, filePath, text) => {
|
||||||
|
return this.vendor.sendMessage(number, {
|
||||||
|
video: readFileSync(filePath),
|
||||||
|
caption: text,
|
||||||
|
gifPlayback: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar audio
|
||||||
* @alpha
|
* @alpha
|
||||||
* @param {string} number
|
* @param {string} number
|
||||||
* @param {string} message
|
* @param {string} message
|
||||||
@@ -185,8 +223,7 @@ class BaileysProvider extends ProviderClass {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sendAudio = async (number, audioUrl, voiceNote = false) => {
|
sendAudio = async (number, audioUrl, voiceNote = false) => {
|
||||||
const numberClean = number.replace('+', '')
|
return this.vendor.sendMessage(number, {
|
||||||
await this.vendor.sendMessage(`${numberClean}@c.us`, {
|
|
||||||
audio: { url: audioUrl },
|
audio: { url: audioUrl },
|
||||||
ptt: voiceNote,
|
ptt: voiceNote,
|
||||||
})
|
})
|
||||||
@@ -210,17 +247,13 @@ class BaileysProvider extends ProviderClass {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sendFile = async (number, filePath) => {
|
sendFile = async (number, filePath) => {
|
||||||
if (existsSync(filePath)) {
|
const mimeType = mime.lookup(filePath)
|
||||||
const mimeType = mime.lookup(filePath)
|
const fileName = filePath.split('/').pop()
|
||||||
const numberClean = number.replace('+', '')
|
return this.vendor.sendMessage(number, {
|
||||||
const fileName = filePath.split('/').pop()
|
document: { url: filePath },
|
||||||
|
mimetype: mimeType,
|
||||||
await this.vendor.sendMessage(`${numberClean}@c.us`, {
|
fileName: fileName,
|
||||||
document: { url: filePath },
|
})
|
||||||
mimetype: mimeType,
|
|
||||||
fileName: fileName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adiwajshing/baileys": "4.4.0",
|
"@adiwajshing/baileys": "4.4.0",
|
||||||
"mime-types": "2.1.35",
|
|
||||||
"wa-sticker-formatter": "4.3.2"
|
"wa-sticker-formatter": "4.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
const { createWriteStream } = require('fs')
|
const { createWriteStream } = require('fs')
|
||||||
const combineImage = require('combine-image')
|
const combineImage = require('combine-image')
|
||||||
const qr = require('qr-image')
|
const qr = require('qr-image')
|
||||||
const { tmpdir } = require('os')
|
|
||||||
const http = require('http')
|
|
||||||
const https = require('https')
|
|
||||||
|
|
||||||
const baileyCleanNumber = (number, full = false) => {
|
const baileyCleanNumber = (number, full = false) => {
|
||||||
number = number.replace('@s.whatsapp.net', '')
|
number = number.replace('@s.whatsapp.net', '')
|
||||||
@@ -41,38 +38,8 @@ const baileyIsValidNumber = (rawNumber) => {
|
|||||||
return !exist
|
return !exist
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Incompleta
|
|
||||||
* Descargar archivo multimedia para enviar
|
|
||||||
* @param {*} url
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const baileyDownloadMedia = (url) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const ext = url.split('.').pop()
|
|
||||||
const checkProtocol = url.includes('https:')
|
|
||||||
const handleHttp = checkProtocol ? https : http
|
|
||||||
const name = `tmp-${Date.now()}.${ext}`
|
|
||||||
const fullPath = `${tmpdir()}/${name}`
|
|
||||||
const file = createWriteStream(fullPath)
|
|
||||||
handleHttp.get(url, function (response) {
|
|
||||||
response.pipe(file)
|
|
||||||
file.on('finish', function () {
|
|
||||||
file.close()
|
|
||||||
resolve(fullPath)
|
|
||||||
})
|
|
||||||
file.on('error', function () {
|
|
||||||
console.log('errro')
|
|
||||||
file.close()
|
|
||||||
reject(null)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
baileyCleanNumber,
|
baileyCleanNumber,
|
||||||
baileyGenerateImage,
|
baileyGenerateImage,
|
||||||
baileyIsValidNumber,
|
baileyIsValidNumber,
|
||||||
baileyDownloadMedia,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,20 @@ const { ProviderClass } = require('@bot-whatsapp/bot')
|
|||||||
const venom = require('venom-bot')
|
const venom = require('venom-bot')
|
||||||
const { createWriteStream } = require('fs')
|
const { createWriteStream } = require('fs')
|
||||||
const { Console } = require('console')
|
const { Console } = require('console')
|
||||||
|
const mime = require('mime-types')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
venomCleanNumber,
|
venomCleanNumber,
|
||||||
venomGenerateImage,
|
venomGenerateImage,
|
||||||
venomisValidNumber,
|
venomisValidNumber,
|
||||||
venomDownloadMedia,
|
|
||||||
} = require('./utils')
|
} = require('./utils')
|
||||||
|
|
||||||
const logger = new Console({
|
const logger = new Console({
|
||||||
stdout: createWriteStream(`${process.cwd()}/venom.log`),
|
stdout: createWriteStream(`${process.cwd()}/venom.log`),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { generalDownload } = require('../../common/download')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ⚙️ VenomProvider: Es una clase tipo adaptor
|
* ⚙️ VenomProvider: Es una clase tipo adaptor
|
||||||
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
|
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
|
||||||
@@ -134,6 +136,53 @@ class VenomProvider extends ProviderClass {
|
|||||||
// return this.vendor.sendButtons(number, "Title", buttons1, "Description");
|
// return this.vendor.sendButtons(number, "Title", buttons1, "Description");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar audio
|
||||||
|
* @alpha
|
||||||
|
* @param {string} number
|
||||||
|
* @param {string} message
|
||||||
|
* @param {boolean} voiceNote optional
|
||||||
|
* @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
|
||||||
|
*/
|
||||||
|
|
||||||
|
sendAudio = async (number, audioPath) => {
|
||||||
|
return this.vendor.sendVoice(number, audioPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar imagen
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendImage = async (number, filePath, text) => {
|
||||||
|
return this.vendor.sendImage(number, filePath, 'image-name', text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} number
|
||||||
|
* @param {string} filePath
|
||||||
|
* @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
|
||||||
|
*/
|
||||||
|
|
||||||
|
sendFile = async (number, filePath, text) => {
|
||||||
|
const fileName = filePath.split('/').pop()
|
||||||
|
return this.vendor.sendFile(number, filePath, fileName, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar video
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendVideo = async (number, filePath, text) => {
|
||||||
|
return this.vendor.sendVideoAsGif(number, filePath, 'video.gif', text)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enviar imagen o multimedia
|
* Enviar imagen o multimedia
|
||||||
* @param {*} number
|
* @param {*} number
|
||||||
@@ -141,10 +190,18 @@ class VenomProvider extends ProviderClass {
|
|||||||
* @param {*} message
|
* @param {*} message
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
sendMedia = async (number, mediaInput, message) => {
|
sendMedia = async (number, mediaUrl, text) => {
|
||||||
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
|
const fileDownloaded = await generalDownload(mediaUrl)
|
||||||
const fileDownloaded = await venomDownloadMedia(mediaInput)
|
const mimeType = mime.lookup(fileDownloaded)
|
||||||
return this.vendor.sendImage(number, fileDownloaded, '.', message)
|
|
||||||
|
if (mimeType.includes('image'))
|
||||||
|
return this.sendImage(number, fileDownloaded, text)
|
||||||
|
if (mimeType.includes('video'))
|
||||||
|
return this.sendVideo(number, fileDownloaded, text)
|
||||||
|
if (mimeType.includes('audio'))
|
||||||
|
return this.sendAudio(number, fileDownloaded)
|
||||||
|
|
||||||
|
return this.sendFile(number, fileDownloaded, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js')
|
const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js')
|
||||||
const { ProviderClass } = require('@bot-whatsapp/bot')
|
const { ProviderClass } = require('@bot-whatsapp/bot')
|
||||||
const { Console } = require('console')
|
const { Console } = require('console')
|
||||||
const { createWriteStream } = require('fs')
|
const { createWriteStream, readFileSync } = require('fs')
|
||||||
const {
|
const {
|
||||||
wwebCleanNumber,
|
wwebCleanNumber,
|
||||||
wwebDownloadMedia,
|
|
||||||
wwebGenerateImage,
|
wwebGenerateImage,
|
||||||
wwebIsValidNumber,
|
wwebIsValidNumber,
|
||||||
} = require('./utils')
|
} = require('./utils')
|
||||||
@@ -13,6 +12,9 @@ const logger = new Console({
|
|||||||
stdout: createWriteStream('./log'),
|
stdout: createWriteStream('./log'),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { generalDownload } = require('../../common/download')
|
||||||
|
const mime = require('mime-types')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ⚙️ WebWhatsappProvider: Es una clase tipo adaptor
|
* ⚙️ WebWhatsappProvider: Es una clase tipo adaptor
|
||||||
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
|
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
|
||||||
@@ -35,6 +37,7 @@ class WebWhatsappProvider extends ProviderClass {
|
|||||||
'--disable-setuid-sandbox',
|
'--disable-setuid-sandbox',
|
||||||
'--unhandled-rejections=strict',
|
'--unhandled-rejections=strict',
|
||||||
],
|
],
|
||||||
|
//executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -103,23 +106,6 @@ class WebWhatsappProvider extends ProviderClass {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
|
||||||
* Enviar un archivo multimedia
|
|
||||||
* https://docs.wwebjs.dev/MessageMedia.html
|
|
||||||
* @private
|
|
||||||
* @param {*} number
|
|
||||||
* @param {*} mediaInput
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
sendMedia = async (number, mediaInput = null) => {
|
|
||||||
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
|
|
||||||
const fileDownloaded = await wwebDownloadMedia(mediaInput)
|
|
||||||
const media = MessageMedia.fromFilePath(fileDownloaded)
|
|
||||||
return this.vendor.sendMessage(number, media, {
|
|
||||||
sendAudioAsVoice: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enviar botones
|
* Enviar botones
|
||||||
* https://docs.wwebjs.dev/Buttons.html
|
* https://docs.wwebjs.dev/Buttons.html
|
||||||
@@ -170,6 +156,86 @@ class WebWhatsappProvider extends ProviderClass {
|
|||||||
return this.vendor.sendMessage(number, message)
|
return this.vendor.sendMessage(number, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar imagen
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendImage = async (number, filePath, caption) => {
|
||||||
|
const base64 = readFileSync(filePath, { encoding: 'base64' })
|
||||||
|
const mimeType = mime.lookup(filePath)
|
||||||
|
const media = new MessageMedia(mimeType, base64)
|
||||||
|
return this.vendor.sendMessage(number, media, { caption })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar audio
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
|
||||||
|
sendAudio = async (number, filePath, caption) => {
|
||||||
|
const base64 = readFileSync(filePath, { encoding: 'base64' })
|
||||||
|
const mimeType = mime.lookup(filePath)
|
||||||
|
const media = new MessageMedia(mimeType, base64)
|
||||||
|
return this.vendor.sendMessage(number, media, { caption })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar video
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendVideo = async (number, filePath) => {
|
||||||
|
const base64 = readFileSync(filePath, { encoding: 'base64' })
|
||||||
|
const mimeType = mime.lookup(filePath)
|
||||||
|
const media = new MessageMedia(mimeType, base64)
|
||||||
|
return this.vendor.sendMessage(number, media, {
|
||||||
|
sendMediaAsDocument: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar Arhivos/pdf
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} imageUrl
|
||||||
|
* @param {*} text
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendFile = async (number, filePath) => {
|
||||||
|
const base64 = readFileSync(filePath, { encoding: 'base64' })
|
||||||
|
const mimeType = mime.lookup(filePath)
|
||||||
|
const media = new MessageMedia(mimeType, base64)
|
||||||
|
return this.vendor.sendMessage(number, media)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enviar imagen o multimedia
|
||||||
|
* @param {*} number
|
||||||
|
* @param {*} mediaInput
|
||||||
|
* @param {*} message
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
sendMedia = async (number, mediaUrl, text) => {
|
||||||
|
const fileDownloaded = await generalDownload(mediaUrl)
|
||||||
|
const mimeType = mime.lookup(fileDownloaded)
|
||||||
|
|
||||||
|
if (mimeType.includes('image'))
|
||||||
|
return this.sendImage(number, fileDownloaded, text)
|
||||||
|
if (mimeType.includes('video'))
|
||||||
|
return this.sendVideo(number, fileDownloaded)
|
||||||
|
if (mimeType.includes('audio'))
|
||||||
|
return this.sendAudio(number, fileDownloaded, text)
|
||||||
|
|
||||||
|
return this.sendFile(number, fileDownloaded)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} userId
|
* @param {*} userId
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"whatsapp-web.js": "1.19.2"
|
"whatsapp-web.js": "1.19.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1113,6 +1113,7 @@ __metadata:
|
|||||||
fs-extra: ^11.1.0
|
fs-extra: ^11.1.0
|
||||||
git-cz: ^4.9.0
|
git-cz: ^4.9.0
|
||||||
husky: ^8.0.2
|
husky: ^8.0.2
|
||||||
|
mime-types: ^2.1.35
|
||||||
only-allow: ^1.1.1
|
only-allow: ^1.1.1
|
||||||
prettier: ^2.8.0
|
prettier: ^2.8.0
|
||||||
pretty-quick: ^3.1.3
|
pretty-quick: ^3.1.3
|
||||||
@@ -13443,7 +13444,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"mime-types@npm:^2.1.12, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
|
"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
|
||||||
version: 2.1.35
|
version: 2.1.35
|
||||||
resolution: "mime-types@npm:2.1.35"
|
resolution: "mime-types@npm:2.1.35"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user