Compare commits

...

73 Commits

Author SHA1 Message Date
github-actions[bot]
a6236e24df docs(contributor): contrib-readme-action has updated readme 2023-01-25 09:14:57 +00:00
Leifer Mendez
7e2bf22d63 Merge pull request #554 from codigoencasa/release/production
Release/production
2023-01-24 23:00:48 +01:00
Leifer Mendez
a4b610e21f Merge pull request #553 from codigoencasa/release/next
Release/next
2023-01-24 23:00:25 +01:00
Leifer Mendez
120520df50 Merge pull request #552 from codigoencasa/dev
Dev
2023-01-24 22:52:28 +01:00
Leifer Mendez
1551aafd54 Merge branch 'release/next' into dev 2023-01-24 22:52:21 +01:00
Leifer Mendez
eca876db9c Merge pull request #551 from codigoencasa/feat/test-e2e
Feat/test e2e
2023-01-24 22:52:00 +01:00
Leifer Mendez
96a387ed50 Merge branch 'feat/test-e2e' of github.com:codigoencasa/bot-whatsapp into feat/test-e2e 2023-01-24 22:51:08 +01:00
Leifer Mendez
558013b2b4 docs: 📝 add 2023-01-24 22:50:59 +01:00
Leifer Mendez
58df7ddc71 Merge pull request #546 from Gregoriotecnico/patch-1
Adición de endFlow()
2023-01-24 22:47:58 +01:00
Leifer Mendez
e25f3abf1c Merge pull request #547 from Gregoriotecnico/patch-2
Adición blackList a la Documentación
2023-01-24 22:47:35 +01:00
Leifer Mendez
0f6b82a9ab Merge pull request #549 from codigoencasa/feat/test-e2e
Feat/test e2e
2023-01-24 22:46:27 +01:00
Leifer Mendez
8f505bdb2b Merge branch 'release/next' into feat/test-e2e 2023-01-24 22:45:48 +01:00
Leifer Mendez
24220822f4 chore(release): 0.1.18 2023-01-24 22:44:24 +01:00
Gregoriotecnico
943fe8698c Adición blackList 2023-01-24 21:55:11 +01:00
Gregoriotecnico
371b403456 Adición de endFlow() 2023-01-24 21:38:38 +01:00
Leifer Mendez
77145bcc54 docs: 🎨 modal added 2023-01-24 14:22:33 +01:00
Leifer Mendez
8f241834e8 Merge pull request #543 from codigoencasa/contributors-readme-action-gll8X6WZnt
docs(contributor): contributors readme action update
2023-01-24 10:14:49 +01:00
github-actions[bot]
5174c6b3bb docs(contributor): contrib-readme-action has updated readme 2023-01-24 09:10:45 +00:00
Leifer Mendez
f3ed6da4ba Merge pull request #542 from lisandroprada/patch-1
Patch 1
2023-01-23 21:21:04 +01:00
Leifer Mendez
0dc839e531 Merge pull request #541 from codigoencasa/dev
Dev
2023-01-23 20:37:55 +01:00
Leifer Mendez
7475d6f8fd Merge branch 'release/next' into dev 2023-01-23 20:36:41 +01:00
Leifer Mendez
a6a33ac7b7 Merge pull request #540 from codigoencasa/feat/test-e2e
test(bot):  more test and endflow
2023-01-23 20:35:54 +01:00
lisandroprada
71c969f3e9 Update index.mdx 2023-01-23 16:34:53 -03:00
Leifer Mendez
cebfed0382 test(bot): more test and endflow 2023-01-23 20:27:55 +01:00
Leifer Mendez
e89ad450a1 Merge pull request #539 from codigoencasa/feat/test-e2e
test: 🎨 more test e2e
2023-01-23 14:41:40 +01:00
Leifer Mendez
ac39ac831c test: 🎨 more test e2e 2023-01-23 14:38:43 +01:00
Leifer Mendez
0af74602f5 test: 🎨 more test e2e 2023-01-23 13:13:41 +01:00
Leifer Mendez
767e0764d6 test: 🎨 more test e2e 2023-01-23 13:09:41 +01:00
Leifer Mendez
b2a3343f82 Merge pull request #538 from codigoencasa/dev
Dev
2023-01-23 12:05:49 +01:00
Leifer Mendez
5ddd885554 Merge pull request #537 from codigoencasa/fix/flowdynamic-buttons
feat(bot):  add blacklist
2023-01-23 12:03:22 +01:00
Leifer Mendez
7078dc4c93 feat(bot): add blacklist 2023-01-23 12:02:31 +01:00
Leifer Mendez
c7e829e954 Merge pull request #518 from devrlbusiness/patch-1
Update index.mdx
2023-01-23 11:55:01 +01:00
Leifer Mendez
5a81a77802 Merge pull request #526 from codigoencasa/506-concatenación-flowdynamic
506 concatenación flowdynamic
2023-01-23 11:54:42 +01:00
Leifer Mendez
588411653e Merge pull request #536 from codigoencasa/fix/flowdynamic-buttons
Fix/flowdynamic buttons
2023-01-23 11:54:13 +01:00
Leifer Mendez
3c4b1c0fc4 feat(bot): flowDynamic buttons, media 2023-01-23 11:52:49 +01:00
Leifer Mendez
0f06fd3e80 Merge pull request #533 from codigoencasa/leifermendez/issue524
fix(contexts): 🐛 fixed #524 issue
2023-01-23 09:19:09 +01:00
Leifer Mendez
79cc31a96f fix(contexts): 🐛 fixed #524 issue 2023-01-23 09:14:36 +01:00
Leifer Mendez
7067b4a80b fix(contexts): 🐛 fixed #524 issue 2023-01-23 09:09:16 +01:00
Leifer Mendez
aa7e4239ae Merge branch 'fix/issuess-01' into 506-concatenación-flowdynamic 2023-01-20 12:04:59 +01:00
Leifer Mendez
877252bd4a fix(bot): 🐛 flowDynamic stranger behaviour 2023-01-20 12:02:01 +01:00
Leifer Mendez
f5a7de3a00 fix(bot): 🐛 flowDynamic stranger behaviour 2023-01-20 11:58:50 +01:00
Leifer Mendez
c792d47344 Merge pull request #519 from devrlbusiness/patch-2
Muchs gracias @devrlbusiness
2023-01-18 10:14:34 +01:00
Developer RL Business
f6130cf0b9 Update index.mdx 2023-01-17 09:35:21 -07:00
Developer RL Business
9f9d833925 Update index.mdx 2023-01-17 09:33:59 -07:00
Leifer Mendez
02c0d8af76 Merge pull request #517 from codigoencasa/release/production
Release/production
2023-01-17 10:30:03 +01:00
Leifer Mendez
880d5323e8 Merge pull request #513 from codigoencasa/release/next
Release/next
2023-01-17 10:26:50 +01:00
Leifer Mendez
9bb33582fb Merge pull request #516 from codigoencasa/dev
Dev
2023-01-17 10:22:54 +01:00
Leifer Mendez
c8ff84e9cd Merge branch 'release/next' into dev 2023-01-17 10:21:29 +01:00
Leifer Mendez
e942bd1d5e Merge pull request #514 from codigoencasa/fix/launch-dev
Fix/launch dev
2023-01-17 10:21:00 +01:00
Leifer Mendez
7e557bdd30 Merge branch 'fix/launch-dev' of github.com:leifermendez/bot-whatsapp into fix/launch-dev 2023-01-17 10:02:23 +01:00
Leifer Mendez
fcd1a63676 chore: 🚀 launch DEV 2023-01-17 10:02:14 +01:00
Leifer Mendez
4ade5f02a7 chore: 🚀 launch DEV 2023-01-17 10:00:21 +01:00
Leifer Mendez
05c834d6b1 Merge pull request #512 from codigoencasa/fix/launch-dev
Fix/launch dev
2023-01-17 09:24:27 +01:00
Leifer Mendez
234cc3ffb6 Merge branch 'release/next' into fix/launch-dev 2023-01-17 09:24:18 +01:00
Leifer Mendez
e321f35d86 Merge branch 'fix/launch-dev' of github.com:leifermendez/bot-whatsapp into fix/launch-dev 2023-01-17 09:23:32 +01:00
Leifer Mendez
5edd755491 chore: 🚀 launch DEV 2023-01-17 09:23:22 +01:00
Leifer Mendez
10748a46a4 Merge pull request #511 from codigoencasa/fix/launch-dev
chore: 🚀 launch DEV
2023-01-17 09:19:20 +01:00
Leifer Mendez
5b3136999b Merge branch 'release/next' into fix/launch-dev 2023-01-17 09:18:33 +01:00
Leifer Mendez
cb047cca8e chore: 🚀 launch DEV 2023-01-17 09:17:32 +01:00
Leifer Mendez
4b8c09633e Merge pull request #510 from codigoencasa/dev
Dev
2023-01-17 09:13:36 +01:00
Leifer Mendez
7cabc53eed Merge branch 'release/next' into dev 2023-01-17 09:13:28 +01:00
Leifer Mendez
40c34dd7a5 Merge pull request #509 from codigoencasa:fix/launch-dev
chore: 🚀 launch DEV
2023-01-17 09:12:12 +01:00
Leifer Mendez
7e25dcaa93 chore: 🚀 launch DEV 2023-01-17 09:11:08 +01:00
Leifer Mendez
bfa622fad0 Merge pull request #508 from codigoencasa/dev
Dev
2023-01-17 09:07:13 +01:00
Leifer Mendez
e88141077f Merge branch 'release/next' into dev 2023-01-17 09:07:05 +01:00
Leifer Mendez
d743fdcfe3 Merge pull request #507 from codigoencasa/feat/docs-member
chore: 🚀 launch DEV
2023-01-17 09:06:31 +01:00
Leifer Mendez
1261580004 chore: 🚀 launch DEV 2023-01-17 09:05:29 +01:00
Leifer Mendez
a14c67ad45 Merge pull request #505 from codigoencasa/dev
Dev
2023-01-16 17:38:30 +01:00
Leifer Mendez
c5af1f8107 Merge branch 'release/next' into dev 2023-01-16 17:38:22 +01:00
Leifer Mendez
01a4edb7e3 Merge pull request #504 from codigoencasa/feat/docs-member
fix(bot): 📝 more docs
2023-01-16 17:37:59 +01:00
Leifer Mendez
98793d0cfc fix(bot): 📝 more docs 2023-01-16 17:32:09 +01:00
Leifer Mendez
13e0530c01 Merge pull request #493 from codigoencasa/dev
Dev
2023-01-13 22:34:44 +01:00
Leifer Mendez
04c5209cac Merge pull request #479 from codigoencasa/dev
Dev
2023-01-13 21:38:35 +01:00
35 changed files with 895 additions and 102 deletions

View File

@@ -10,9 +10,15 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
outputs:
commit: ${{ steps.vars.outputs.commit }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{github.event.after}}
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@v3
@@ -50,8 +56,9 @@ jobs:
- name: Release @bot-whatsapp/portal
run: yarn node ./scripts/release.js --name=portal --version= --token="${{ secrets.NPM_TOKEN }}"
- name: Commit Versioning & Push changes
uses: stefanzweifel/git-auto-commit-action@v4
- name: Commit & Push changes
uses: actions-js/push@master
with:
commit_message: 'ci(version): :zap: automatic - "${date}" updated versions every packages'
branch: dev
branch: release/next
github_token: ${{ secrets.GITHUB_TOKEN }}
force: true

View File

@@ -67,13 +67,9 @@ jobs:
- name: Release Github
run: yarn node ./scripts/github.js --version="${{ steps.package-version.outputs.current-version}}" --token="${{ secrets.OCTO_TOKEN }}"
- name: 'Run if changes have been detected'
run: |
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
- name: Commit & Push changes
uses: actions-js/push@master
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
View File

@@ -1,4 +1,5 @@
/node_modules
/packages/repl
/packages/*/starters
/packages/*/node_modules
/packages/*/dist

View File

@@ -2,6 +2,47 @@
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.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)

View File

@@ -34,6 +34,13 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<!-- readme: collaborators,contributors -start -->
<table>
<tr>
<td align="center">
<a href="https://github.com/cheveguerra">
<img src="https://avatars.githubusercontent.com/u/5891114?v=4" width="50;" alt="cheveguerra"/>
<br />
<sub><b>Jose Alberto Guerra Ugalde</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/leifermendez">
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
@@ -42,10 +49,10 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
</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"/>
<a href="https://github.com/leifermendezfroged">
<img src="https://avatars.githubusercontent.com/u/97020486?v=4" width="50;" alt="leifermendezfroged"/>
<br />
<sub><b>Null</b></sub>
<sub><b>Leifer Mendez</b></sub>
</a>
</td>
<td align="center">
@@ -56,12 +63,20 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
</a>
</td>
<td align="center">
<a href="https://github.com/leifermendezfroged">
<img src="https://avatars.githubusercontent.com/u/97020486?v=4" width="50;" alt="leifermendezfroged"/>
<a href="https://github.com/danielcasta0398">
<img src="https://avatars.githubusercontent.com/u/98791147?v=4" width="50;" alt="danielcasta0398"/>
<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/marianarolfo">
<img src="https://avatars.githubusercontent.com/u/68322254?v=4" width="50;" alt="marianarolfo"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/HKong31">
<img src="https://avatars.githubusercontent.com/u/113340082?v=4" width="50;" alt="HKong31"/>
@@ -75,8 +90,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<br />
<sub><b>Zvi</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/JosephVTX">
<img src="https://avatars.githubusercontent.com/u/91026290?v=4" width="50;" alt="JosephVTX"/>
<br />
<sub><b>Joseph Vega Callupe</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Gonzalito87">
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
@@ -84,6 +105,42 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/devrlbusiness">
<img src="https://avatars.githubusercontent.com/u/66280283?v=4" width="50;" alt="devrlbusiness"/>
<br />
<sub><b>Developer RL Business</b></sub>
</a>
</td>
<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></tr>
<tr>
<td align="center">
<a href="https://github.com/aurik3">
<img src="https://avatars.githubusercontent.com/u/37228512?v=4" width="50;" alt="aurik3"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/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/6rak0">
<img src="https://avatars.githubusercontent.com/u/12260031?v=4" width="50;" alt="6rak0"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/tonyvazgar">
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
@@ -92,10 +149,10 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
</a>
</td>
<td align="center">
<a href="https://github.com/ulisesvina">
<img src="https://avatars.githubusercontent.com/u/20508563?v=4" width="50;" alt="ulisesvina"/>
<a href="https://github.com/lisandroprada">
<img src="https://avatars.githubusercontent.com/u/7232326?v=4" width="50;" alt="lisandroprada"/>
<br />
<sub><b>Ulises Viña</b></sub>
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
@@ -104,7 +161,8 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<br />
<sub><b>Rodrigo Mendoza Cabrera</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/yond1994">
<img src="https://avatars.githubusercontent.com/u/47557263?v=4" width="50;" alt="yond1994"/>

41
__test__/01-case.test.js Normal file
View 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
View 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
View 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
View 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))
}

View File

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

View File

@@ -21,10 +21,12 @@ class CoreClass {
flowClass
databaseClass
providerClass
constructor(_flow, _database, _provider) {
generalArgs = { blackList: [] }
constructor(_flow, _database, _provider, _args) {
this.flowClass = _flow
this.databaseClass = _database
this.providerClass = _provider
this.generalArgs = { ...this.generalArgs, ..._args }
for (const { event, func } of this.listenerBusEvents()) {
this.providerClass.on(event, func)
@@ -70,10 +72,12 @@ class CoreClass {
const { body, from } = messageCtxInComming
let msgToSend = []
let fallBackFlag = false
let endFlowFlag = false
if (this.generalArgs.blackList.includes(from)) return
if (!body) return
if (!body.length) return
const prevMsg = await this.databaseClass.getPrevByNumber(from)
let prevMsg = await this.databaseClass.getPrevByNumber(from)
const refToContinue = this.flowClass.findBySerialize(
prevMsg?.refSerialize
)
@@ -87,16 +91,35 @@ class CoreClass {
this.databaseClass.save(ctxByNumber)
}
// 📄 Limpiar cola de procesos
const clearQueue = () => {
QueuePrincipal.pendingPromise = false
QueuePrincipal.queue = []
}
// 📄 Finalizar flujo
const endFlow = async () => {
prevMsg = null
endFlowFlag = true
clearQueue()
return
}
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
const sendFlow = async (messageToSend, numberOrId) => {
// [1 Paso] esto esta bien!
if (prevMsg?.options?.capture) await cbEveryCtx(prevMsg?.ref)
const queue = []
for (const ctxMessage of messageToSend) {
if (endFlowFlag) return
const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() =>
Promise.all([
this.sendProviderAndSave(numberOrId, ctxMessage),
resolveCbEveryCtx(ctxMessage),
this.sendProviderAndSave(numberOrId, ctxMessage).then(
() => resolveCbEveryCtx(ctxMessage)
),
])
)
}
@@ -113,6 +136,7 @@ class CoreClass {
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
// para evitar bloque de whatsapp
const flowDynamic = async (
listMsg = [],
optListMsg = { limit: 5, fallback: false }
@@ -122,15 +146,22 @@ class CoreClass {
fallBackFlag = optListMsg.fallback
const parseListMsg = listMsg
.map(({ body }, index) =>
toCtx({
.map((opt, index) => {
const body = typeof opt === 'string' ? opt : opt.body
const media = opt?.media ?? null
const buttons = opt?.buttons ?? []
return toCtx({
body,
from,
keyword: null,
index,
options: { media, buttons },
})
)
})
.slice(0, optListMsg.limit)
if (endFlowFlag) return
for (const msg of parseListMsg) {
await this.sendProviderAndSave(from, msg)
}
@@ -139,7 +170,6 @@ class CoreClass {
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
const resolveCbEveryCtx = async (ctxMessage) => {
if (prevMsg?.options?.capture) return cbEveryCtx(prevMsg?.ref)
if (!ctxMessage?.options?.capture)
return await cbEveryCtx(ctxMessage?.ref)
}
@@ -150,20 +180,10 @@ class CoreClass {
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
fallBack,
flowDynamic,
endFlow,
})
}
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
if (!fallBackFlag && prevMsg?.options?.nested?.length) {
const nestedRef = prevMsg.options.nested
@@ -173,11 +193,6 @@ class CoreClass {
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
// //TODO AQUI
// for (const ite of msgToSend) {
// cbEveryCtx(ite?.ref)
// }
sendFlow(msgToSend, from)
return
}
@@ -225,5 +240,24 @@ class CoreClass {
this.continue(null, responde.ref)
}
}
/**
* Funcion dedicada a enviar el mensaje sin pasar por el flow
* (dialogflow)
* @param {*} messageToSend
* @param {*} numberOrId
* @returns
*/
sendFlowSimple = async (messageToSend, numberOrId) => {
const queue = []
for (const ctxMessage of messageToSend) {
const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() =>
this.sendProviderAndSave(numberOrId, ctxMessage)
)
}
return Promise.all(queue)
}
}
module.exports = CoreClass

View File

@@ -8,8 +8,8 @@ const { addKeyword, addAnswer, addChild, toSerialize } = require('./io/methods')
* @param {*} args
* @returns
*/
const createBot = async ({ flow, database, provider }) =>
new CoreClass(flow, database, provider)
const createBot = async ({ flow, database, provider }, args = {}) =>
new CoreClass(flow, database, provider, args)
/**
* Crear instancia de clase Io (Flow)

View File

@@ -5,12 +5,12 @@ const { generateRef, generateRefSerialize } = require('../../utils/hash')
* @param options {media:string, buttons:[], capture:true default false}
* @returns
*/
const toCtx = ({ body, from, prevRef, index }) => {
const toCtx = ({ body, from, prevRef, options = {}, index }) => {
return {
ref: generateRef(),
keyword: prevRef,
answer: body,
options: {},
options: options ?? {},
from,
refSerialize: generateRefSerialize({ index, answer: body }),
}

View File

@@ -1,6 +1,6 @@
{
"name": "@bot-whatsapp/bot",
"version": "0.0.66-alpha.0",
"version": "0.0.73-alpha.0",
"description": "",
"main": "./lib/bundle.bot.cjs",
"scripts": {

View 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()

View File

@@ -48,11 +48,11 @@ const nextSteps = async () => {
name: 'providerWs',
message: '¿Cuál proveedor de whatsapp quieres utilizar?',
choices: [
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
{ title: 'Venom (gratis)', value: 'venom' },
{ title: 'Baileys (gratis)', value: 'baileys' },
{ title: 'Venom (gratis)', value: 'venom' },
{ title: 'whatsapp-web.js (gratis)', value: 'wweb' },
{ title: 'Twilio', value: 'twilio' },
{ title: 'API Oficial (Meta)', value: 'meta' },
{ title: 'Meta', value: 'meta' },
],
max: 1,
hint: 'Espacio para seleccionar',

View File

@@ -117,7 +117,7 @@ class DialogFlowCXContext extends CoreClass {
}
})
this.sendFlow(listMessages, from)
this.sendFlowSimple(listMessages, from)
}
}

View File

@@ -107,7 +107,7 @@ class DialogFlowContext extends CoreClass {
...customPayload,
answer: fields?.answer?.stringValue,
}
this.sendFlow([ctxFromDX], from)
this.sendFlowSimple([ctxFromDX], from)
return
}
@@ -115,7 +115,7 @@ class DialogFlowContext extends CoreClass {
answer: queryResult?.fulfillmentText,
}
this.sendFlow([ctxFromDX], from)
this.sendFlowSimple([ctxFromDX], from)
}
}

View File

@@ -14,7 +14,7 @@ export default component$(
<a href={props.user.html_url} target="_blank">
<img
class="w-16 h-16 rounded-full mx-auto object-cover"
src={props.user.avatar_url + '&s=80'}
src={props.user.avatar_url}
alt={props.user.login}
width="80"
height="80"
@@ -23,7 +23,9 @@ export default component$(
<div class="pt-2 space-y-4 justify-center flex">
<figcaption class="text-sm">
<div class={'font-semibold'}>{props.user.login}</div>
<div class={'font-semibold truncate'}>
{props.user.login}
</div>
</figcaption>
</div>
</figure>

View File

@@ -56,7 +56,7 @@ export default component$(() => {
</a>
<a
target={'_blank'}
href="https://youtu.be/DEIyGyJNGa8"
href="https://youtu.be/UgoS8PXxe-A"
class="btn bg-gray-50 dark:bg-transparent"
>
Ver video

View 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>
)
})

View 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>
})

View File

@@ -52,16 +52,22 @@ export default component$(() => {
title: 'Avanzado',
list: [
{ name: 'Migración', link: '/docs/migration' },
{ name: 'Extender funcionalidades', link: '/docs/custom' },
{ name: 'MasterClass', link: '/docs/masterclass' },
],
},
{
title: 'Despliegue',
list: [
{ name: 'Local', link: '/docs/deploy/local' },
{ name: 'Docker', link: '/docs/deploy/docker' },
{ name: 'Cloud', link: '/docs/deploy/cloud' },
],
},
{
title: 'Comunidad',
list: [
{ name: 'MasterClass', link: '/docs/masterclass' },
{ name: 'Colabores', link: '/docs/contributing' },
{ name: 'Unirme al proyecto', link: '/docs/join' },
{ name: 'Sponsors', link: '/docs/sponsors' },
],
},
])

View 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**
![](https://i.imgur.com/5zRCz9q.png)
---
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
## ![](https://i.imgur.com/ljyJPBm.png)
## 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**
![](https://i.imgur.com/rUBASqR.png)
---
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`
![](https://i.imgur.com/xcovczm.png)
---
## Firewall
Si no te abre la pagina web asegurate de tener el puerto abierto en tu firewall.
Ejemplo permitir el puerto **3000**
![](https://i.imgur.com/0dAz0B1.png)
---
## Escanear QR
![](https://i.imgur.com/2m3NbXC.png)
---
## 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
```
![](https://i.imgur.com/ilPS75H.png)
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

View 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)
![](https://i.imgur.com/cDspa0R.png)
---
## 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
```

View 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
```
![](https://i.imgur.com/ilPS75H.png)
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

View File

@@ -23,6 +23,23 @@ const flowPrincipal = addKeyword(['hola', 'alo'])
---
## blackList
Éste argumento se utiliza para **evitar que el bot se active** cuando los números de la lista activen el bot.
Es importante que el número **vaya acompañado de su prefijo**, en el caso de España "34".
```js
createBot({
flow: adapterFlow,
provider: adapterProvider,
database: adapterDB,
},{
blackList:['34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX']
})
```
---
## addKeyword()
Esta funcion se utliza para iniciar un flujo de conversion. <br /> Recibe un `string` o un `array`
@@ -55,7 +72,7 @@ Esta funcion se utliza para responder un mensaje despues del `addKeyword()`
- delay: 0 (milisegundos)
- media: url de imagen
- 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
```js
@@ -158,6 +175,64 @@ 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
QRPortalWeb({name:BOTNAME, port:3005 });
```
---
<Navigation
pages={[

View File

@@ -3,6 +3,7 @@ import type { DocumentHead } from '@builder.io/qwik-city'
import ExtraBar from '~/components/widgets/ExtraBar'
import Header from '~/components/widgets/Header'
import NavBar from '~/components/widgets/NavBar'
import { SearchModal } from '~/components/widgets/SearchModal'
import SponsorBar from '~/components/widgets/SponsorBar'
import { GlobalStore } from '~/contexts'
// import Navigation from '~/components/widgets/Navigation'
@@ -14,6 +15,7 @@ export default component$(() => {
return (
<>
<SearchModal />
<Header />
<main class={'overflow-hidden'}>
<div class={'max-w-8xl'}>

View File

@@ -1,24 +0,0 @@
[![hackmd-github-sync-badge](https://hackmd.io/79xQyVSgRD6RsTpqtMPPdw/badge)](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?

View 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?

View File

@@ -5,16 +5,22 @@ import Features from '~/components/widgets/Features'
import FAQs from '~/components/widgets/FAQs'
import CallToAction from '~/components/widgets/CallToAction'
import Collaborators from '~/components/widgets/Collaborators'
import Members from '~/components/widgets/Members'
import { fetchGithub } from '~/services/github'
import { fetchOpenCollective } from '~/services/opencollective'
import { RequestHandlerNetlify } from '@builder.io/qwik-city/middleware/netlify-edge'
import { GITHUB_TOKEN } from './docs/constant'
// import { SearchModal } from '~/components/widgets/SearchModal'
export const onGet: RequestHandlerNetlify = async ({ platform }) => {
const CHECK_GITHUB_TOKEN =
(platform as any)?.['GITHUB_TOKEN'] ?? GITHUB_TOKEN
console.log(`[🚩 platform]: `, GITHUB_TOKEN)
const data = await fetchGithub(CHECK_GITHUB_TOKEN)
return data
const dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN)
const dataOpenCollective = await fetchOpenCollective()
return {
dataGithub,
dataOpenCollective,
}
}
export default component$(() => {
@@ -27,9 +33,16 @@ export default component$(() => {
<CallToAction />
<Resource
value={resource}
onResolved={(data: any) => <Collaborators users={data} />}
onResolved={(data: any) => {
return (
<>
<Collaborators users={data.dataGithub} />
<FAQs />
<Members users={data.dataOpenCollective} />
</>
)
}}
></Resource>
<FAQs />
</>
)
})

View File

@@ -14,6 +14,9 @@ export const fetchGithub = async (token: string) => {
},
}
)
const listUsers = data.json()
return listUsers
const listUsers = await data.json()
return listUsers.map((u: any) => ({
...u,
avatar_url: `${u.avatar_url}&s=80`,
}))
}

View 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,
}))
}

View File

@@ -1,7 +1,7 @@
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) {

View File

@@ -1,5 +1,4 @@
const staticPaths = new Set([
'/',
'/favicon.svg',
'/manifest.json',
'/q-manifest.json',