Compare commits

...

98 Commits

Author SHA1 Message Date
github-actions[bot]
cc9dfa10cb docs(contributor): contrib-readme-action has updated readme 2023-02-09 09:16:25 +00:00
Leifer Mendez
186c48d884 Merge pull request #595 from codigoencasa/dev
Dev
2023-02-03 10:59:35 +01:00
Leifer Mendez
bb31045a95 Merge pull request #594 from codigoencasa/feat/docs-digitalocean
Feat/docs-digitalocean
2023-02-03 10:53:54 +01:00
Leifer Mendez
74fb3b864d docs: digitalocean sponsor 2023-02-03 10:39:17 +01:00
Leifer Mendez
88c05c12a4 docs: digitalocean sponsor 2023-02-03 10:24:48 +01:00
Leifer Mendez
5260a7eb47 Merge branch 'contributors-readme-action-2AwvRwXk2x' 2023-02-03 10:20:02 +01:00
Leifer Mendez
9e1698b729 docs: digitalocean sponsor 2023-02-03 10:19:10 +01:00
Leifer Mendez
811618b256 docs: digitalocean sponsor 2023-02-03 10:12:45 +01:00
github-actions[bot]
331d2a309c docs(contributor): contrib-readme-action has updated readme 2023-02-02 09:10:57 +00:00
Leifer Mendez
318ac3adec Merge pull request #585 from Jhonarias13/fix/caption-sendImage
corrige caption 'soy una imagen' en el método sendImage() con whatsapp web provider
@Jhonarias13 gracias buen trabajo
2023-01-31 16:00:31 +01:00
Jhonarias13
0a69b8d9b5 corrige caption 'soy una imagen' en sendImage() wwebprovider 2023-01-31 09:35:02 -05:00
Leifer Mendez
f434d6a101 chore(release): 0.1.20
chore(release): 0.1.20
2023-01-29 18:44:19 +01:00
Leifer Mendez
753d80b93e chore(release): 0.1.20
chore(release): 0.1.20
2023-01-29 18:39:07 +01:00
Leifer Mendez
c07e148dfd Merge pull request #578 from codigoencasa/dev
chore(release): 0.1.20
2023-01-29 18:35:48 +01:00
Leifer Mendez
3f30a1cb51 Merge branch 'release/next' into dev 2023-01-29 18:35:42 +01:00
Leifer Mendez
9b679192db Merge pull request #577 from codigoencasa/fix/end-flow
chore(release): 0.1.20
2023-01-29 18:35:08 +01:00
Leifer Mendez
f7d90efc2f chore(release): 0.1.19 2023-01-29 18:33:32 +01:00
Leifer Mendez
0aa793e08c Merge pull request #575 from codigoencasa/dev
Dev
2023-01-29 14:55:31 +01:00
Leifer Mendez
eeb4bb305e Merge branch 'release/next' into dev 2023-01-29 14:54:54 +01:00
Leifer Mendez
012d43847c Merge pull request #574 from codigoencasa/fix/end-flow
Fix/end flow
2023-01-29 14:07:29 +01:00
Leifer Mendez
87a4203cd5 fix(bot): endFlow butons 2023-01-29 14:06:23 +01:00
Leifer Jesús Mendez
f6114affad fix(bot): 🔥 endFlow with ctx 2023-01-29 13:39:09 +01:00
Leifer Mendez
15b64185cb Merge commit 'b655ae449e7958ea940d8cc3c678fd66f60b6385' into fix/end-flow 2023-01-29 12:48:50 +01:00
Leifer Jesús Mendez
b655ae449e fix(bot): 🔥 endFlow with ctx 2023-01-29 12:46:31 +01:00
Leifer Mendez
1c66f178a5 fix(cli): endflow 2023-01-28 18:41:58 +01:00
Leifer Mendez
f201c5097b Merge pull request #570 from codigoencasa/545-cuando-se-activa-fallback-dentro-de-un-addanswer-con-capture-true-no-espera-el-capture-true-y-se-salta-al-siguiente-addanswer
fix(cli):  refactor fallback in child flow
2023-01-28 16:53:52 +01:00
Leifer Mendez
b33e34692d fix(cli): refactor fallback in child flow 2023-01-28 16:46:46 +01:00
Leifer Mendez
8f967578c6 Merge branch 'fix/send-media-all' into 545-cuando-se-activa-fallback-dentro-de-un-addanswer-con-capture-true-no-espera-el-capture-true-y-se-salta-al-siguiente-addanswer 2023-01-28 16:44:39 +01:00
Leifer Mendez
fd2847aea0 feat(provider): venom wweb 2023-01-28 16:44:30 +01:00
Leifer Mendez
f95331d3dc feat(provider): venom wweb 2023-01-28 16:25:22 +01:00
Leifer Mendez
791ab8e970 Merge pull request #566 from codigoencasa/feat/send-media-wwebjs
feat(provider): 🚀 send file wwebjs
2023-01-28 16:12:12 +01:00
Leifer Mendez
880c729199 Merge commit '8da4b204b41125b5d0fa0aee4fa87c1f5faf5568' into 545-cuando-se-activa-fallback-dentro-de-un-addanswer-con-capture-true-no-espera-el-capture-true-y-se-salta-al-siguiente-addanswer 2023-01-28 16:07:16 +01:00
Leifer Jesús Mendez
8da4b204b4 fix(cli): refactor fallback in child flow 2023-01-28 16:06:12 +01:00
Leifer Mendez
3fdd49ff86 Merge pull request #568 from codigoencasa/fix/fallback-issue
fix(bot):  fix fallback refactor
2023-01-28 15:47:03 +01:00
Leifer Jesús Mendez
e22780d3fa fix(bot): fix fallback refactor 2023-01-28 15:46:13 +01:00
aurik3
0ad4c58457 feat(provider): 🚀 fix provider 2023-01-27 14:51:20 -05:00
aurik3
f8c7184487 feat(provider): 🚀 fix provider 2023-01-27 14:42:45 -05:00
aurik3
b2afa45352 feat(provider): 🚀 fix provider 2023-01-27 14:32:42 -05:00
aurik3
dcb0566d2b feat(provider): 🚀 fix provider venom and wwebjs 2023-01-27 14:31:05 -05:00
aurik3
cbe438b778 feat(provider): 🚀 fix issues in providers venom and wwebjs 2023-01-27 14:28:25 -05:00
aurik3
6ff1a3a980 feat(provider): 🚀 send file wwebjs 2023-01-27 12:51:15 -05:00
Leifer Mendez
dceb13f4f5 Merge pull request #563 from codigoencasa/dev
Dev
2023-01-25 22:13:48 +01:00
Leifer Mendez
bbbdb1c206 Merge branch 'release/next' into dev 2023-01-25 22:13:39 +01:00
Leifer Mendez
bd7d150c04 feat(provider): 🚀 implements all send media to venom provider
Muchas gracias @aurik3
2023-01-25 22:11:59 +01:00
aurik3
9dd7c02b6a feat(provider): 🚀 implements all send media to venom provider 2023-01-25 16:10:13 -05:00
Leifer Mendez
11a74b8bea Merge pull request #561 from lisandroprada/patch-2
muchas gracias @lisandroprada
2023-01-25 12:44:23 +01:00
lisandroprada
e7a8e85ead Update index.mdx
Agregado: Definición de la constante BOTNAME.
2023-01-25 08:21:12 -03:00
Leifer Mendez
6bfbae7b94 Merge pull request #559 from codigoencasa/dev
Dev
2023-01-25 09:33:32 +01:00
Leifer Mendez
d5d7f9dfee Merge branch 'release/next' into dev 2023-01-25 09:30:42 +01:00
Leifer Mendez
0a23d2c761 Merge pull request #558 from codigoencasa:feat/docs-modal-fix
docs: 🐛 fix modal
2023-01-25 09:06:00 +01:00
Leifer Mendez
b2feaea588 docs: 🐛 fix modal 2023-01-25 09:05:01 +01: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
Leifer Mendez
14d1a61fa2 feat(provider): bailey add send file video audio 2023-01-24 22:14:55 +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
e19c3a25a4 feat: more feature 2023-01-24 19:43:11 +01:00
Leifer Mendez
eab39e4ac0 feat: 🔥 bailey add media 2023-01-24 16:54:31 +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
8cbfd560a3 ci(providers): � Check BREAKING CHANGE 2023-01-16 09:13:52 +01:00
36 changed files with 1408 additions and 161 deletions

1
.gitignore vendored
View File

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

View File

@@ -2,5 +2,6 @@
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
"singleQuote": true,
"printWidth": 120
}

View File

@@ -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.
### [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)

100
README.md
View File

@@ -1,8 +1,7 @@
# Chatbot Library
![](https://img.shields.io/npm/v/@bot-whatsapp/bot?color=%2300c200&label=%40bot-whatsapp)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![BotWhatsapp Releases(Prod)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml/badge.svg)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml)
[![](https://img.shields.io/discord/915193197645402142?logo=discord)](https://link.codigoencasa.com/DISCORD)
<p align="center">
<img width="300" src="https://i.imgur.com/Oauef6t.png">
@@ -34,6 +33,13 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<!-- readme: collaborators,contributors -start -->
<table>
<tr>
<td align="center">
<a href="https://github.com/cheveguerra">
<img src="https://avatars.githubusercontent.com/u/5891114?v=4" width="50;" alt="cheveguerra"/>
<br />
<sub><b>Jose Alberto Guerra Ugalde</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/leifermendez">
<img src="https://avatars.githubusercontent.com/u/15802366?v=4" width="50;" alt="leifermendez"/>
@@ -42,10 +48,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,10 +62,25 @@ 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/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>
</td>
<td align="center">
@@ -75,8 +96,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<br />
<sub><b>Zvi</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/JosephVTX">
<img src="https://avatars.githubusercontent.com/u/91026290?v=4" width="50;" alt="JosephVTX"/>
<br />
<sub><b>Joseph Vega Callupe</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Gonzalito87">
<img src="https://avatars.githubusercontent.com/u/100331586?v=4" width="50;" alt="Gonzalito87"/>
@@ -84,20 +111,57 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/devrlbusiness">
<img src="https://avatars.githubusercontent.com/u/66280283?v=4" width="50;" alt="devrlbusiness"/>
<br />
<sub><b>Developer RL Business</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/Gregoriotecnico">
<img src="https://avatars.githubusercontent.com/u/118696506?v=4" width="50;" alt="Gregoriotecnico"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jlferrete">
<img src="https://avatars.githubusercontent.com/u/36698913?v=4" width="50;" alt="jlferrete"/>
<br />
<sub><b>Jose Luis Ferrete Olarte</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/lisandroprada">
<img src="https://avatars.githubusercontent.com/u/7232326?v=4" width="50;" alt="lisandroprada"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/6rak0">
<img src="https://avatars.githubusercontent.com/u/12260031?v=4" width="50;" alt="6rak0"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/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">
<a href="https://github.com/tonyvazgar">
<img src="https://avatars.githubusercontent.com/u/21047090?v=4" width="50;" alt="tonyvazgar"/>
<br />
<sub><b>Luis Antonio Vázquez García</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ulisesvina">
<img src="https://avatars.githubusercontent.com/u/20508563?v=4" width="50;" alt="ulisesvina"/>
<br />
<sub><b>Ulises Viña</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/rrruuuyyy">
<img src="https://avatars.githubusercontent.com/u/33061671?v=4" width="50;" alt="rrruuuyyy"/>

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

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

View File

@@ -1,6 +1,6 @@
{
"name": "@bot-whatsapp/root",
"version": "0.1.17",
"version": "0.1.19",
"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",
@@ -80,6 +81,7 @@
"fs-extra": "^11.1.0",
"git-cz": "^4.9.0",
"husky": "^8.0.2",
"mime-types": "^2.1.35",
"only-allow": "^1.1.1",
"prettier": "^2.8.0",
"pretty-quick": "^3.1.3",

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)
@@ -69,11 +71,13 @@ class CoreClass {
logger.log(`[handleMsg]: `, messageCtxInComming)
const { body, from } = messageCtxInComming
let msgToSend = []
let endFlowFlag = false
let fallBackFlag = false
if (this.generalArgs.blackList.includes(from)) return
if (!body) return
if (!body.length) return
const prevMsg = await this.databaseClass.getPrevByNumber(from)
let prevMsg = await this.databaseClass.getPrevByNumber(from)
const refToContinue = this.flowClass.findBySerialize(
prevMsg?.refSerialize
)
@@ -87,16 +91,68 @@ class CoreClass {
this.databaseClass.save(ctxByNumber)
}
// 📄 Crar CTX de mensaje (uso private)
const createCtxMessage = (payload = {}, index = 0) => {
const body =
typeof payload === 'string'
? payload
: payload?.body ?? payload?.answer
const media = payload?.media ?? null
const buttons = payload?.buttons ?? []
const capture = payload?.capture ?? false
return toCtx({
body,
from,
keyword: null,
index,
options: { media, buttons, capture },
})
}
// 📄 Limpiar cola de procesos
const clearQueue = () => {
QueuePrincipal.pendingPromise = false
QueuePrincipal.queue = []
}
// 📄 Finalizar flujo
const endFlow = async (message = null) => {
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
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 = []
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)
),
])
)
}
@@ -104,42 +160,41 @@ class CoreClass {
}
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
const fallBack = async () => {
fallBackFlag = true
await this.sendProviderAndSave(from, refToContinue)
const fallBack = async (next = false, message = null) => {
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
// 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 parseListMsg = listMsg
.map(({ body }, index) =>
toCtx({
body,
from,
keyword: null,
index,
})
)
.slice(0, optListMsg.limit)
const flowDynamic = async (listMsg = []) => {
if (!Array.isArray(listMsg)) listMsg = [listMsg]
const parseListMsg = listMsg.map((opt, index) =>
createCtxMessage(opt, index)
)
if (endFlowFlag) return
for (const msg of parseListMsg) {
await this.sendProviderAndSave(from, msg)
}
return
return continueFlow()
}
// 📄 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,22 +205,13 @@ class CoreClass {
return this.flowClass.allCallbacks[inRef](messageCtxInComming, {
fallBack,
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
if (!fallBackFlag && prevMsg?.options?.nested?.length) {
if (!endFlowFlag && prevMsg?.options?.nested?.length) {
const nestedRef = prevMsg.options.nested
const flowStandalone = nestedRef.map((f) => ({
...nestedRef.find((r) => r.refSerialize === f.refSerialize),
@@ -173,21 +219,15 @@ class CoreClass {
msgToSend = this.flowClass.find(body, false, flowStandalone) || []
// //TODO AQUI
// for (const ite of msgToSend) {
// cbEveryCtx(ite?.ref)
// }
sendFlow(msgToSend, from)
return
}
// 📄🤘(tiene return) [options: capture (boolean)]: Si se tiene option boolean
if (!fallBackFlag && !prevMsg?.options?.nested?.length) {
// 📄🤘(tiene return) Si el mensaje previo implementa capture
if (!endFlowFlag && !prevMsg?.options?.nested?.length) {
const typeCapture = typeof prevMsg?.options?.capture
const valueCapture = prevMsg?.options?.capture
if (['string', 'boolean'].includes(typeCapture) && valueCapture) {
if (typeCapture === 'boolean' && fallBackFlag) {
msgToSend = this.flowClass.find(refToContinue?.ref, true) || []
sendFlow(msgToSend, from)
return
@@ -213,6 +253,7 @@ class CoreClass {
}
/**
* @deprecated
* @private
* @param {*} message
* @param {*} ref
@@ -225,5 +266,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.91-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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

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

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

@@ -7,6 +7,8 @@ import { src as qwik } from '~/assets/images/qwik.png?width=100&metadata'
import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata'
// @ts-ignore
import { src as netlify } from '~/assets/images/full-logo-light.png?width=100&metadata'
// @ts-ignore
import { src as digitalOcean } from '~/assets/images/digital-ocean.png?width=100&metadata'
/**
* options = [] array con la lista de opciones de la documentacion
@@ -41,7 +43,20 @@ export default component$(() => {
<img
src={netlify}
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
alt="Qwind Hero Image (Cool dog)"
alt="Netlify"
loading="eager"
decoding="async"
/>
</picture>
</a>
</li>
<li>
<a target={'_blank'} href="https://m.do.co/c/140291d21736">
<picture>
<img
src={digitalOcean}
class="border border-slate-200 rounded my-2 p-1 bg-gray-50 dark:border-gray-600 dark:bg-gray-700"
alt="DigitalOcean"
loading="eager"
decoding="async"
/>

View File

@@ -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()
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)
- 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
@@ -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
pages={[
{ name: 'Conceptos', link: '/docs/essential' },

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

@@ -10,11 +10,11 @@ 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 dataGithub = await fetchGithub(CHECK_GITHUB_TOKEN)
const dataOpenCollective = await fetchOpenCollective()
return {

View File

@@ -4,7 +4,7 @@
*/
export const fetchOpenCollective = async () => {
const data = await fetch(
`https://opencollective.com/bot-whatsapp/members/users.json?limit=10&offset=0`,
`https://opencollective.com/bot-whatsapp/members/users.json?limit=22&offset=0`,
{
method: 'GET',
}

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',

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

View File

@@ -4,7 +4,7 @@ const pino = require('pino')
const rimraf = require('rimraf')
const mime = require('mime-types')
const { join } = require('path')
const { existsSync, createWriteStream, readFileSync } = require('fs')
const { createWriteStream, readFileSync } = require('fs')
const { Console } = require('console')
const {
@@ -13,13 +13,15 @@ const {
Browsers,
DisconnectReason,
} = require('@adiwajshing/baileys')
const {
baileyGenerateImage,
baileyCleanNumber,
baileyIsValidNumber,
baileyDownloadMedia,
} = require('./utils')
const { generalDownload } = require('../../common/download')
const logger = new Console({
stdout: createWriteStream(`${process.cwd()}/baileys.log`),
})
@@ -169,14 +171,50 @@ class BaileysProvider extends ProviderClass {
*/
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, {
image: readFileSync(fileDownloaded),
image: readFileSync(filePath),
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
* @param {string} number
* @param {string} message
@@ -185,8 +223,7 @@ class BaileysProvider extends ProviderClass {
*/
sendAudio = async (number, audioUrl, voiceNote = false) => {
const numberClean = number.replace('+', '')
await this.vendor.sendMessage(`${numberClean}@c.us`, {
return this.vendor.sendMessage(number, {
audio: { url: audioUrl },
ptt: voiceNote,
})
@@ -210,17 +247,13 @@ class BaileysProvider extends ProviderClass {
*/
sendFile = async (number, filePath) => {
if (existsSync(filePath)) {
const mimeType = mime.lookup(filePath)
const numberClean = number.replace('+', '')
const fileName = filePath.split('/').pop()
await this.vendor.sendMessage(`${numberClean}@c.us`, {
document: { url: filePath },
mimetype: mimeType,
fileName: fileName,
})
}
const mimeType = mime.lookup(filePath)
const fileName = filePath.split('/').pop()
return this.vendor.sendMessage(number, {
document: { url: filePath },
mimetype: mimeType,
fileName: fileName,
})
}
/**

View File

@@ -1,7 +1,6 @@
{
"dependencies": {
"@adiwajshing/baileys": "4.4.0",
"mime-types": "2.1.35",
"wa-sticker-formatter": "4.3.2"
}
}

View File

@@ -1,9 +1,6 @@
const { createWriteStream } = require('fs')
const combineImage = require('combine-image')
const qr = require('qr-image')
const { tmpdir } = require('os')
const http = require('http')
const https = require('https')
const baileyCleanNumber = (number, full = false) => {
number = number.replace('@s.whatsapp.net', '')
@@ -41,38 +38,8 @@ const baileyIsValidNumber = (rawNumber) => {
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 = {
baileyCleanNumber,
baileyGenerateImage,
baileyIsValidNumber,
baileyDownloadMedia,
}

View File

@@ -2,18 +2,20 @@ const { ProviderClass } = require('@bot-whatsapp/bot')
const venom = require('venom-bot')
const { createWriteStream } = require('fs')
const { Console } = require('console')
const mime = require('mime-types')
const {
venomCleanNumber,
venomGenerateImage,
venomisValidNumber,
venomDownloadMedia,
} = require('./utils')
const logger = new Console({
stdout: createWriteStream(`${process.cwd()}/venom.log`),
})
const { generalDownload } = require('../../common/download')
/**
* ⚙️ VenomProvider: Es una clase tipo adaptor
* 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");
}
/**
* 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
* @param {*} number
@@ -141,10 +190,18 @@ class VenomProvider extends ProviderClass {
* @param {*} message
* @returns
*/
sendMedia = async (number, mediaInput, message) => {
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
const fileDownloaded = await venomDownloadMedia(mediaInput)
return this.vendor.sendImage(number, fileDownloaded, '.', message)
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, text)
if (mimeType.includes('audio'))
return this.sendAudio(number, fileDownloaded)
return this.sendFile(number, fileDownloaded, text)
}
/**

View File

@@ -1,10 +1,9 @@
const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js')
const { ProviderClass } = require('@bot-whatsapp/bot')
const { Console } = require('console')
const { createWriteStream } = require('fs')
const { createWriteStream, readFileSync } = require('fs')
const {
wwebCleanNumber,
wwebDownloadMedia,
wwebGenerateImage,
wwebIsValidNumber,
} = require('./utils')
@@ -13,6 +12,9 @@ const logger = new Console({
stdout: createWriteStream('./log'),
})
const { generalDownload } = require('../../common/download')
const mime = require('mime-types')
/**
* ⚙️ WebWhatsappProvider: Es una clase tipo adaptor
* 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',
'--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
* https://docs.wwebjs.dev/Buttons.html
@@ -170,6 +156,86 @@ class WebWhatsappProvider extends ProviderClass {
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

View File

@@ -1,5 +1,5 @@
{
"dependencies": {
"whatsapp-web.js": "1.19.2"
"whatsapp-web.js": "1.19.3"
}
}

View File

@@ -1113,6 +1113,7 @@ __metadata:
fs-extra: ^11.1.0
git-cz: ^4.9.0
husky: ^8.0.2
mime-types: ^2.1.35
only-allow: ^1.1.1
prettier: ^2.8.0
pretty-quick: ^3.1.3
@@ -13443,7 +13444,7 @@ __metadata:
languageName: node
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
resolution: "mime-types@npm:2.1.35"
dependencies: