Compare commits

...

576 Commits

Author SHA1 Message Date
Davidson Gomes
45e03d87c7 Merge branch 'release/1.6.1' 2023-12-22 11:44:12 -03:00
Davidson Gomes
3e358e5d26 version: 1.6.1 2023-12-22 11:43:58 -03:00
Davidson Gomes
dc5dae04eb fix: when deleting a message in whatsapp, delete the message in chatwoot too 2023-12-22 11:43:10 -03:00
Davidson Gomes
9128b1f47d fix: when deleting a message in whatsapp, delete the message in chatwoot too 2023-12-22 11:43:03 -03:00
Davidson Gomes
16a8226ba7 Merge pull request #317 from jaison-x/pr
fix: when deleting a message in whatsapp, delete the message in chatwoot too
2023-12-21 16:37:01 -03:00
jaison-x
9ecaf3199d Merge branch 'pr' of https://github.com/jaison-x/evolution-api into pr 2023-12-21 07:42:37 -03:00
jaison-x
a44cd0373e fix: simple adjust in key object 2023-12-21 07:42:33 -03:00
jaison-x
2c0b629302 Update whatsapp.service.ts 2023-12-21 00:23:33 -03:00
jaison-x
89a37a1771 fix: show message Connection successfully established after a sucessfull connection on chatwoot 2023-12-20 18:11:41 -03:00
jaison-x
cadc038966 Merge remote-tracking branch 'upstream/develop' into pr 2023-12-20 17:54:52 -03:00
jaison-x
07e8449379 fix: when deleting a message in whatsapp, delete the message in chatwoot too
The message model schema was changed. Old format in message model was field chatwootMessageId. Now we have a document chatwoot with new properties.

I cant find a simple way to create a migration function up then the old field was no migrate to new format.
2023-12-20 17:53:37 -03:00
Davidson Gomes
71e908ad1a Merge pull request #312 from stgcompany/develop
Exclude all .env files on .gitignore and renamed one to .env.example
2023-12-20 12:22:03 -03:00
Davidson Gomes
035c85b775 Merge pull request #313 from gabrielpastori1/issue-template
Add issue templates
2023-12-20 12:21:06 -03:00
Gabriel Pastori
a87b753151 Update issue templates 2023-12-20 12:13:24 -03:00
Eduardo Chaves
edaa4aff7e Add any .env file to .gitignore 2023-12-20 10:31:14 -03:00
Eduardo Chaves
be02610349 Renamed .env to .env.example 2023-12-20 10:29:32 -03:00
Davidson Gomes
1f65731165 fix: Add options to disable docs and manager 2023-12-20 10:03:44 -03:00
Davidson Gomes
fb61fb7849 Merge pull request #310 from gabrielpastori1/disable-docs-manager
Add options to disable docs and manager
2023-12-20 10:02:46 -03:00
Davidson Gomes
060a945aea fix: Fix the problem when disconnecting the instance and connecting again using mongodb 2023-12-20 09:56:53 -03:00
Davidson Gomes
2797250f34 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-12-20 09:56:32 -03:00
Davidson Gomes
97b3f9b3c7 fix: Fix the problem when disconnecting the instance and connecting again using mongodb 2023-12-20 09:55:51 -03:00
Gabriel Pastori
9363301d2a Add DISABLE_DOCS and DISABLE_MANAGER 2023-12-19 21:18:40 -03:00
Davidson Gomes
d93a826e28 Merge pull request #309 from jaison-x/pr
fix: message can be undefined
2023-12-19 18:59:59 -03:00
jaison-x
244fe0835e Update chatwoot.service.ts
fix: message can be undefined
2023-12-19 18:49:31 -03:00
Davidson Gomes
5f1a5d6589 Merge pull request #308 from PurpShell/fix/message-retry
Fix: message retry mechanism
2023-12-19 17:34:39 -03:00
Rajeh Taher
4e27c22292 fix: message retry 2023-12-19 22:28:50 +02:00
Davidson Gomes
53ee270096 Merge pull request #307 from gabrielpastori1/chatwoot-format
Chatwoot Agent Name
2023-12-19 17:15:32 -03:00
Gabriel Pastori
a00ad20c08 chatwoot agent available_name 2023-12-19 16:41:52 -03:00
Davidson Gomes
e8764dd1c6 fix: Fix the problem when disconnecting the instance and connecting again using mongodb 2023-12-19 14:55:16 -03:00
Davidson Gomes
a869d38499 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-12-19 14:27:47 -03:00
Davidson Gomes
7bf7c96587 Merge pull request #301 from drauber/addLogInfo
Add connected number and instance name to connected log
2023-12-19 14:27:41 -03:00
Davidson Gomes
72b857a92f Merge pull request #299 from gabrielpastori1/chatwoot-format
Chatwoot format
2023-12-19 14:27:05 -03:00
Douglas Rauber at Nitro
380d6a43a5 Add connected number and instance name to connected log 2023-12-19 08:02:29 -03:00
Gabriel Pastori
076f2b492e fix: chatwoot media process 2023-12-18 21:23:56 -03:00
Davidson Gomes
547f981c47 fix: adjusts in typebot 2023-12-18 16:46:04 -03:00
Davidson Gomes
8bfc62a3b2 fix: adjusts in typebot 2023-12-18 16:27:37 -03:00
Davidson Gomes
d39776a314 fix: fixed the pairing code 2023-12-18 15:27:22 -03:00
Davidson Gomes
35641d0543 fix: fixed the pairing code 2023-12-18 15:24:19 -03:00
Davidson Gomes
038cd6f149 Merge pull request #293 from gabrielpastori1/chatwoot-format
Chatwoot format
2023-12-18 12:15:00 -03:00
Davidson Gomes
38978dd447 test: adjusts baileys lids 2023-12-18 12:07:02 -03:00
Gabriel Pastori
fb24b7eaa7 Merge branch 'develop' into chatwoot-format 2023-12-17 13:30:54 -03:00
Gabriel Pastori
b4ce45bc4b Add new env and fix message formatting in Chatwoot to changelog 2023-12-17 13:25:03 -03:00
Gabriel Pastori
8d04198309 fix: monospace and bold 2023-12-17 13:24:43 -03:00
Davidson Gomes
da796347c4 fix: include instance Id field in the instance configuration 2023-12-17 09:37:18 -03:00
Davidson Gomes
2d6a29664a fix: include instance Id field in the instance configuration 2023-12-17 07:59:24 -03:00
Davidson Gomes
4ba5cfceaf fix: include instance Id field in the instance configuration 2023-12-17 07:50:17 -03:00
Davidson Gomes
7cc324e1c0 fix: include instance Id field in the instance configuration 2023-12-17 07:04:33 -03:00
Davidson Gomes
cf89601269 fix: include instance Id field in the instance configuration 2023-12-17 06:59:05 -03:00
Davidson Gomes
c07e23bf8d Merge pull request #290 from gabrielpastori1/chatwoot-format
Chatwoot format
2023-12-17 06:32:37 -03:00
Gabriel Pastori
5aa89d85f3 fix: remove comments 2023-12-16 18:39:46 -03:00
Gabriel Pastori
4ed1edf53d chatwoot_sign_delimiter 2023-12-16 17:23:39 -03:00
Gabriel Pastori
1be1326b52 Refactor message formatting in ChatwootService (Bold, italic, etc) 2023-12-16 15:58:01 -03:00
Davidson Gomes
42ae7d1568 Merge pull request #286 from gomessguii/feature/dockerfile-optimization
Dockerfile modified to use multi-stage build
2023-12-15 14:51:49 -03:00
Guilherme Oliveira
b781c83545 Dockerfile modified to use multi-stage build 2023-12-15 14:46:31 -03:00
Davidson Gomes
e48cea18e7 Merge pull request #283 from gabrielpastori1/typeboot-keep-open
simple add keep open
2023-12-15 13:53:06 -03:00
Gabriel Pastori
ff82987144 simple add keep open 2023-12-15 12:39:07 -03:00
Davidson Gomes
f612a45550 fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 17:20:37 -03:00
Davidson Gomes
182dce4840 fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 16:42:03 -03:00
Davidson Gomes
4e41e072d6 fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 16:13:15 -03:00
Davidson Gomes
a369c16db8 fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 15:59:06 -03:00
Davidson Gomes
1fc820787a fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 15:57:34 -03:00
Davidson Gomes
d3a83ba89e fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 15:35:17 -03:00
Davidson Gomes
20fb66e2f7 fix: correction sending s3/minio media to chatwoot and typebot 2023-12-14 11:50:05 -03:00
Davidson Gomes
a44646161b fix: variables in typebot 2023-12-14 08:35:45 -03:00
Davidson Gomes
87027ea2d0 update: manager 2023-12-12 18:16:02 -03:00
Davidson Gomes
c9757cbb4b fix: fixed lids messages 2023-12-12 17:45:12 -03:00
Davidson Gomes
9a8f4aefe0 Merge tag '1.6.0' into develop
* Added AWS SQS Integration
* Added support for new typebot API
* Added endpoint sendPresence
* New Instance Manager
* Added auto_create to the chatwoot set to create the inbox automatically or not
* Added reply, delete and message reaction in chatwoot v3.3.1

* Adjusts in proxy
* Adjusts in start session for Typebot
* Added mimetype field when sending media
* Ajusts in validations to messages.upsert
* Fixed messages not received: error handling when updating contact in chatwoot
* Fix workaround to manage param data as an array in mongodb
* Removed await from webhook when sending a message
* Update typebot.service.ts - element.underline change ~ for *
* Adjusts in proxy
* Removed api restart on receiving an error
* Fixes in mongodb and chatwoot
* Adjusted return from queries in mongodb
* Added restart instance when update profile picture
* Correction of chatwoot functioning with admin flows
* Fixed problem that did not generate qrcode with the chatwoot_conversation_pending option enabled
* Fixed issue where CSAT opened a new ticket when reopen_conversation was disabled
* Fixed issue sending contact to Chatwoot via iOS

- Chatwoot: v3.3.1
- Typebot: v2.20.0
2023-12-12 17:44:42 -03:00
Davidson Gomes
3545b80050 Merge branch 'release/1.6.0' 2023-12-12 17:44:24 -03:00
Davidson Gomes
379855714e version: 1.6.0 2023-12-12 17:44:00 -03:00
Davidson Gomes
ff06cd7643 feat: Added support for new typebot API 2023-12-12 16:55:46 -03:00
Davidson Gomes
ade3952016 fix: Fixed issue sending contact to Chatwoot via iOS 2023-12-12 16:28:01 -03:00
Davidson Gomes
f246516a6e fix: fixed issue where CSAT opened a new ticket when reopen_conversation was disabled 2023-12-12 16:08:09 -03:00
Davidson Gomes
c296bf4178 fix: Fixed problem that did not generate qrcode with the chatwoot_conversation_pending option enabled 2023-12-12 15:46:10 -03:00
Davidson Gomes
1568554a1c feat: added reply, delete and message reaction in chatwoot v3.3.1 2023-12-12 15:24:54 -03:00
Davidson Gomes
ae66be197e feat: added reply, delete and message reaction in chatwoot v3.3.1 2023-12-12 15:16:09 -03:00
Davidson Gomes
3e904aa160 fix: correction of chatwoot functioning with admin flows 2023-12-12 13:56:47 -03:00
Davidson Gomes
64c1440c46 fix: correction of chatwoot functioning with admin flows 2023-12-12 13:56:41 -03:00
Davidson Gomes
f069a41390 fix: added restart instance when update profile pricture 2023-12-11 18:17:18 -03:00
Davidson Gomes
d4a33e2290 fix: added restart instance when update profile pricture 2023-12-11 18:16:11 -03:00
Davidson Gomes
7ee5bcecff fix: added restart instance when update profile pricture 2023-12-11 18:15:24 -03:00
Davidson Gomes
48f6ee8846 feat: added auto_create to the chatwoot set to create the inbox automatically or not 2023-12-11 17:32:19 -03:00
Davidson Gomes
7a24f52782 feat: added auto_create to the chatwoot set to create the inbox automatically or not 2023-12-11 17:32:07 -03:00
Davidson Gomes
324d46120b feat: new manager 2023-12-11 15:31:43 -03:00
Davidson Gomes
87baec5ff8 Merge pull request #250 from gabrielpastori1/manager
Add Manager
2023-12-11 15:27:43 -03:00
Gabriel Pastori
b2e144f35c add manager 2023-12-11 15:06:42 -03:00
Davidson Gomes
87a8e25662 Merge pull request #249 from gabrielpastori1/typebot-auto-create-session
fix: only create if is paused
2023-12-11 12:57:51 -03:00
Gabriel Pastori
8e88f00fb2 fix: only create if is paused 2023-12-11 12:42:09 -03:00
Davidson Gomes
d14505d59a Merge pull request #248 from gabrielpastori1/fix-chatwoot-find
Fix chatwoot find
2023-12-11 12:32:19 -03:00
Davidson Gomes
1e6d4347fa Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-12-11 12:09:08 -03:00
Davidson Gomes
b8d9a8c072 fix: adjusted return from queries in mongodb 2023-12-11 12:08:58 -03:00
Gabriel Pastori
fd15ae5e8c Fix condition to check for empty result object 2023-12-11 12:00:33 -03:00
Davidson Gomes
fb6377414b Merge pull request #237 from gabrielpastori1/add-send-presence
Add sendPresence
2023-12-11 10:47:26 -03:00
Davidson Gomes
9a5dbe055e fix: adjusts in connection 2023-12-08 18:44:52 -03:00
Gabriel Pastori
42dd280aca change sendPresence from sendMessage to chat 2023-12-08 18:40:48 -03:00
Davidson Gomes
41b2946cdc Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-12-06 15:22:08 -03:00
Davidson Gomes
a90f0f2c59 Fixes in mongodb and chatwoot 2023-12-06 15:21:50 -03:00
Gabriel Pastori
4222c0e53b Fix logger message in sendPresence route 2023-12-06 00:32:27 -03:00
Gabriel Pastori
ee0f0f0be0 add send presence router 2023-12-06 00:31:35 -03:00
Davidson Gomes
f8d874453c Merge pull request #233 from gabrielpastori1/typebot-auto-create-session
Add session creation for typebot service
2023-12-05 18:49:31 -03:00
Gabriel Pastori
aa891489f0 Add session creation for typebot service 2023-12-03 21:00:26 -03:00
Davidson Gomes
4c69b059d4 proxy 2023-12-01 21:24:38 -03:00
Davidson Gomes
359bd9f762 fix: adjusts in proxy 2023-12-01 20:09:22 -03:00
Davidson Gomes
2de0b61726 fix: adjusts in proxy 2023-12-01 20:09:19 -03:00
Davidson Gomes
d75163aa57 test: adjusts wasocket 2023-12-01 15:04:57 -03:00
Davidson Gomes
e49f30641e test: adjusts wasocket 2023-12-01 14:30:20 -03:00
Davidson Gomes
1631c2c342 test: adjusts wasocket 2023-12-01 09:42:56 -03:00
Davidson Gomes
cf7de369b2 test: adjusts wasocket 2023-12-01 08:22:40 -03:00
Davidson Gomes
78c03d8f2f test: adjusts wasocket 2023-12-01 08:21:36 -03:00
Davidson Gomes
876320b849 feat: added compatibility with typebot v2 2023-11-30 17:13:05 -03:00
Davidson Gomes
a1d13f8ff3 changelog 2023-11-30 07:12:14 -03:00
Davidson Gomes
3c19bdfaa9 fix: Removed await from webhook when sending a message 2023-11-30 07:09:11 -03:00
Davidson Gomes
4fa895086e fix: adjusts in validation to messages.upsert 2023-11-30 07:02:25 -03:00
Davidson Gomes
9945d8debb Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-11-30 07:01:48 -03:00
Davidson Gomes
4362de2198 fix: adjusts in validation to messages.upsert 2023-11-30 07:01:26 -03:00
Davidson Gomes
a5c5879e4f fix: adjusts in validation to messages.upsert 2023-11-30 07:01:08 -03:00
Davidson Gomes
1a57f4f33d Merge pull request #215 from suissa/patch-3
Update typebot.service.ts - element.underline change ~ for *
2023-11-29 08:47:52 -03:00
Davidson Gomes
a99e173168 Merge pull request #224 from jaison-x/pr
fix: workaround to manage param data as an array in mongodb
2023-11-29 08:46:12 -03:00
Davidson Gomes
e02a28f61e Merge pull request #228 from raimartinsb/develop
fix messages not received: error handling when updating contact
2023-11-29 08:45:24 -03:00
raimartinsb
26d3ff97ce fix messages not received: error handling when updating contact 2023-11-28 11:10:29 -03:00
Davidson Gomes
57fb3c9785 fix: fixed lids messages 2023-11-27 19:58:23 -03:00
Davidson Gomes
edeb970a82 fix: fixed lids messages 2023-11-27 19:57:59 -03:00
jaison-x
e17baddf01 fix: workaround to manage param data as an array in mongodb
When saving data from a group session (sender-key-xxxxx@g.us::xxxxx::xx) we receive the data param as an array.
In mongodb we can't save an array as a root document. Bacause this, in this case we save the array in a property called content_array.
2023-11-24 18:59:19 -03:00
Davidson Gomes
a277d36696 feat: sqs 2023-11-20 17:53:29 -03:00
Davidson Gomes
6c9e86e17a feat: sqs 2023-11-20 17:52:36 -03:00
Davidson Gomes
e75ef21eb6 Merge pull request #216 from craines/main
fix: Removed await from webhook when sending a message
2023-11-18 16:38:32 -03:00
craines
04e5443b82 fix: send reaction 2023-11-15 21:52:56 -03:00
craines
8b4cdf3b9b fix: Removed await from webhook when sending a message 2023-11-14 16:47:25 -03:00
Jean Carlo Nascimento
37f1620f7c Update typebot.service.ts - element.underline change ~ for *
There's no underline in WhatsApp ~ use strikethrough instead, I switched to * bold.
2023-11-12 19:11:47 -03:00
Davidson Gomes
b0a0e805cf Merge pull request #187 from jaison-x/deleting-instances
Deleting instances
2023-11-09 14:41:43 -03:00
Davidson Gomes
c619e253a2 Merge pull request #198 from gabrielpastori1/fix-typebot-error-handle
Handle erros in Typebot
2023-11-09 14:32:30 -03:00
Davidson Gomes
2bd111f1e2 Merge pull request #197 from vitorogen/develop
Handle optional chaining for 'settings.msg_call', this change prevent…
2023-11-05 19:44:27 -03:00
Davidson Gomes
40174b50eb Merge pull request #190 from w3nder/develop
fix: size of group participants
2023-11-05 19:43:45 -03:00
Davidson Gomes
e0fe28717f Merge pull request #186 from jaison-x/adjust-mongo-deletion
-> Adjusting function cleaningStoreFiles to remove itens from missing…
2023-11-05 19:42:24 -03:00
Gabriel Pastori
ac5fc22043 try catch entire sendTypebot 2023-10-30 18:05:18 -03:00
Gabriel Pastori
e30f196dad remove duplicate 2023-10-29 13:22:41 -03:00
Gabriel Pastori
9e4e1ce8ec Merge branch 'fix-typebot-error-handle' of https://github.com/gabrielpastori1/ticketme-evolution-api into fix-typebot-error-handle 2023-10-29 13:01:37 -03:00
Gabriel Pastori
f710898844 fix: in error catch in createNewSession 2023-10-29 12:59:29 -03:00
Gabriel Pastori
94633484ca Merge branch 'develop' into fix-typebot-error-handle 2023-10-29 12:54:05 -03:00
Gabriel Pastori
0817c2589f expand try catch for all function 2023-10-29 12:49:26 -03:00
Gabriel Pastori
8a99386b33 handle erros 2023-10-28 21:21:12 -03:00
Vitor
52d6a563d6 Handle optional chaining for 'settings.msg_call', this change prevents 'TypeError: Cannot read properties of undefined' errors when 'msg_call' is undefined. 2023-10-27 22:49:57 -03:00
Davidson Gomes
d0a5ae1da4 fix: Removed senderKeyDistributionMessage 2023-10-26 18:01:17 -03:00
Davidson Gomes
783c00a1d9 fix: Added mimetype field when sending media 2023-10-25 10:29:24 -03:00
Davidson Gomes
bc70ec8b07 fix: start session 2023-10-25 08:19:44 -03:00
Davidson Gomes
50e1efe5d7 fix: start session 2023-10-25 07:00:58 -03:00
Davidson Gomes
d8629e53f1 fix: start session 2023-10-24 13:16:35 -03:00
Davidson Gomes
cc9df1dabb fix: start session 2023-10-24 12:06:20 -03:00
Davidson Gomes
cd6cb8182e fix: start session 2023-10-24 12:05:58 -03:00
Wender Teixeira
5b0e90e5b9 Update whatsapp.service.ts 2023-10-19 22:41:16 -03:00
jaison-x
3c3bbc84b3 -> When deleting a instance in connecting state, the event remove.instance was not triggered; 2023-10-18 19:52:33 -03:00
Jaison
23615cff4f -> Adjusting function cleaningStoreFiles to remove itens from missing mongo collections;
-> AuthModel was using a wrong filter;
2023-10-18 18:57:11 -03:00
Davidson Gomes
daadc6cb68 fix: adjusts in proxy 2023-10-18 18:09:26 -03:00
Davidson Gomes
e157a2a36b fix: adjusts in proxy 2023-10-18 18:09:01 -03:00
Davidson Gomes
d8d7debfee fix: lid messages 2023-10-11 17:27:49 -03:00
Davidson Gomes
a82b206fe6 test: messages.upsert 2023-10-10 10:00:11 -03:00
Davidson Gomes
a4416214c8 Merge tag '1.5.4' into develop
* Baileys logger typing issue resolved
* Solved problem with duplicate messages in chatwoot
2023-10-09 20:43:50 -03:00
Davidson Gomes
8fe75cd210 Merge branch 'release/1.5.4' 2023-10-09 20:43:40 -03:00
Davidson Gomes
303effebbc version: 1.5.4 2023-10-09 20:43:30 -03:00
Davidson Gomes
f32a34190d fix: adjusts logger 2023-10-09 20:17:01 -03:00
Davidson Gomes
8588ef1d8a fix: adjusts logger 2023-10-09 20:15:53 -03:00
Davidson Gomes
51ec4821f3 fix: adjusts logger 2023-10-09 20:14:50 -03:00
Davidson Gomes
957033a7bb ajustes 2023-10-09 19:57:26 -03:00
Davidson Gomes
62c74deac3 fix: Solved problem with duplicate messages in chatwoot 2023-10-09 18:00:14 -03:00
Davidson Gomes
29fd448998 Merge tag '1.5.3' into develop
* Swagger documentation
* Added base 64 sending option via webhook

* Remove rabbitmq queues when delete instances
* Improvement in restart instance to completely redo the connection
* Update node version: v20
* Correction of messages sent by the api and typebot not appearing in chatwoot
* Adjustment to start typebot, added startSession parameter
* Chatwoot now receives messages sent via api and typebot
* Fixed problem with starting with an input in typebot
* Added check to ensure variables are not empty before executing foreach in start typebot
2023-10-06 18:55:52 -03:00
Davidson Gomes
e55cb08a6a Merge branch 'release/1.5.3' 2023-10-06 18:55:44 -03:00
Davidson Gomes
047359e8dc version: 1.5.3 2023-10-06 18:55:36 -03:00
Davidson Gomes
eb814e181a adjusts in swagger 2023-10-06 18:45:26 -03:00
Davidson Gomes
857031ff5a adjusts in swagger 2023-10-06 18:05:37 -03:00
Davidson Gomes
d5eeb68714 feat: webhook base64 option 2023-10-05 17:05:41 -03:00
Davidson Gomes
966b287026 feat: webhook base64 option 2023-10-05 16:01:47 -03:00
Davidson Gomes
a348729109 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-10-05 15:59:59 -03:00
Davidson Gomes
1f29b7733e Merge pull request #163 from w3nder/develop
Fix: Variables null
2023-10-05 15:59:39 -03:00
Davidson Gomes
e26ae30f6f feat: webhook base64 option 2023-10-05 15:57:53 -03:00
Davidson Gomes
547943a05c Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-10-05 15:54:53 -03:00
Davidson Gomes
46aa229531 fix: adjusts in swagger 2023-10-05 15:54:46 -03:00
Davidson Gomes
28bd796289 Merge pull request #161 from moraisamilton/develop
Recuperar base64 de media enviada por webhook
2023-10-05 15:54:20 -03:00
Wender Teixeira
6a3f82ed7e Fix: Variables null 2023-10-05 11:43:18 -03:00
Amilton Morais
523f3301c0 Update wa.types.ts
Foi criado novas propriedades para recuperar Base64 da media enviada por webhook.
2023-10-03 17:20:14 -03:00
Amilton Morais
f085343a99 Update whatsapp.service.ts
Foi criado novo código para recuperar Base64 da media enviada por webhook.
2023-10-03 17:18:58 -03:00
Amilton Morais
f76a924700 Update webhook.service.ts
Foi criado novo variavel "webhook_base64:false' para retorno erro.
2023-10-03 17:13:58 -03:00
Amilton Morais
f8e3b76a4a Update webhook.model.ts
Foi criado novas propriedades para recuperar Base64 da media enviada por webhook.
2023-10-03 16:59:06 -03:00
Amilton Morais
b8f1e8a7ef Update instance.dto.ts
Foi criado novas propriedades "webhook_base64?: boolean;" para recuperar Base64 da media enviada por webhook.
2023-10-03 16:56:44 -03:00
Amilton Morais
d007fc49d8 Update instance.controller.ts
Foi criado novas propriedades para recuperar Base64 da media enviada por webhook.
2023-10-03 16:45:05 -03:00
Amilton Morais
f6d8ebd8d3 Update dev-env.yml
Inserido nova variável WEBHOOK_BASE64 para recuperar Base64 da media enviar por webhook.
2023-10-03 16:39:04 -03:00
Davidson Gomes
6ff9c4578a Fixed problem with starting with an input in typebot 2023-10-02 18:23:03 -03:00
Davidson Gomes
33acfe1464 chatwoot now receives messages sent via api and typebot 2023-10-02 17:59:54 -03:00
Davidson Gomes
f5eeb16bb1 Adjustment to start typebot, added startSession parameter 2023-10-02 17:05:22 -03:00
Davidson Gomes
c35c5faaa4 correction of messages sent by the api and typebot not appearing in chatwoot 2023-10-02 16:17:28 -03:00
Davidson Gomes
8425ebc13f Merge pull request #156 from EvolutionAPI/revert-154-evolution-api-1.5.2-develop-francis
Revert "Start Typebot com opção de ativar chatbot ou não"
2023-10-02 16:10:45 -03:00
Davidson Gomes
6fc37a4298 Revert "Start Typebot com opção de ativar chatbot ou não" 2023-10-02 19:10:34 +00:00
Davidson Gomes
99f3e77c12 Merge pull request #154 from francisbreit/evolution-api-1.5.2-develop-francis
Start Typebot com opção de ativar chatbot ou não
2023-10-02 16:10:29 -03:00
Davidson Gomes
a9c087c45f correction of messages sent by the api and typebot not appearing in chatwoot 2023-10-02 16:10:04 -03:00
Francis Breit
3f4333087f Start Typebot com opção de ativar chatbot ou não
Foi criada a variável enabled_typebot (não obrigatória)
enabled_typebot igual a true ou vazio: o comportamento do "startTypebot" atua como a nova funcionalidadede sessões persistentes (v1.5.2) onde o flow do Typebot disparado atua como chatbot.
enabled_typebot igual a false: o comportamento do "startTypebot" atua como era na Evolution v.1.5.1 onde o flow do Typebot disparado atua como mensagem simples, nao ativa o chatbot e funciona apenas como mensagens simples.
Obs1: Se setada como true ou se for omitida essa variável no comando start Typebot, enabled_typebot será assumida como true, ou seja, start typebot aciona o flow com o chatbot ativado, imediatamente após o envio, aguardando interação do contato.. Se, antes do acionamento do start typebot, tiver um outro chatbot ativo, o mesmo será substituído pelo novo, ora enviado.
Obs2: Se setada como false, dispara apenas como notificação e não ativa o bot. se tiver outro bot ativo na instancia o mesmo continuará ativo, após disparada a mensagem
2023-10-02 11:56:24 -03:00
Davidson Gomes
e1ac29683d wip: swagger 2023-10-02 09:24:53 -03:00
Davidson Gomes
5c74cbfe19 improvement in restart instance to completely redo the connection 2023-09-30 16:36:32 -03:00
Davidson Gomes
3fdb3fa673 fix: Remove rabbitmq queues when delete instances 2023-09-30 07:20:57 -03:00
Davidson Gomes
ba584974cb Merge tag '1.5.2' into develop
v
2023-09-28 17:58:59 -03:00
Davidson Gomes
bddd6408ac Merge branch 'release/1.5.2' 2023-09-28 17:58:55 -03:00
Davidson Gomes
413ad66a07 version: 1.5.2 2023-09-28 17:58:37 -03:00
Davidson Gomes
0ef5d884cc version: 1.5.2 2023-09-28 17:56:47 -03:00
Davidson Gomes
f6b6d23e93 Merge pull request #133 from francisbreit/fetch-instances
Correção de nao recebimento de midias armazenadas mo minio/s3 Update whatsapp.service.ts
2023-09-28 17:47:17 -03:00
Davidson Gomes
50be69f3d3 Merge pull request #132 from IsraelXabregas/chatwoot-model-fix-schema-db
Fix chatwootSchema in chatwoot model to store reopen_conversation and conversation_pending options
2023-09-28 17:45:13 -03:00
Davidson Gomes
5a75e4d5e6 Merge pull request #131 from matheuskshn/develop
Melhoria no método "startTypebot" para criar sessão persistente quando acionado
2023-09-28 17:44:00 -03:00
Davidson Gomes
ec463df9d6 Merge pull request #126 from francisbreit/main
Novo manager para Evo 1.5.1 - atualização Set Typebot
2023-09-28 17:42:06 -03:00
Francis Breit
b648334323 Corrigir nao recebimento de midias minio/s3 - finalizado- Update whatsapp.service.tsUpdate whatsapp.service.ts
Correção nao recebimento de midias com urls do minio/s3 .
Urls sem o nome da extensão da midia impediam o envio das mensagens por erro na detecção do mimetype.
Imagem e Video
2023-09-26 14:15:50 -03:00
Francis Breit
916972aeb1 Update whatsapp.service.ts 2023-09-26 13:52:11 -03:00
Francis Breit
3893e01af9 Corrigir nao recebimento de midias minio/s3 Update whatsapp.service.ts
Correção nao recebimento de midias com urls do minio/s3 .
Urls sem o nome da extensão da midia impediam o envio das mensagens por erro na detecção do mimetype.
2023-09-26 13:27:58 -03:00
Israel Xabregas Ramos
7835f32c8b Fix chatwootSchema in chatwoot model to store reopen_conversation and conversation_pending options 2023-09-25 20:45:14 -03:00
Matheus Gomes
37302244ee Update typebot.service.ts 2023-09-25 16:37:43 -03:00
Matheus Gomes
f1be7ddb83 Update typebot.service.ts 2023-09-25 16:22:41 -03:00
Matheus Gomes
7447a65a83 Update typebot.service.ts 2023-09-25 16:05:18 -03:00
Matheus Gomes
129009d602 Update typebot.service.ts 2023-09-25 15:55:12 -03:00
Matheus Gomes
c656bd6f4b Enhancement of Session Initialization in "StartTypebot" Function
Enhanced "StartTypebot" to initialize sessionIDs during the initial interaction, improving user experience on WhatsApp and preventing unexpected bot restarts.
2023-09-25 02:38:37 -03:00
Francis Breit
36528d7484 Inclusão de Listening From Me no est Typebot Update manager.json
Correção e inclusão de Listening From Me
2023-09-22 13:28:29 -03:00
Francis Breit
f9c85b6a67 Novo manager para Evo 1.5.1 - atualização Set Typebot
Incluída a opção da variável listening_from_me do Set Typebot
2023-09-21 10:04:00 -03:00
Davidson Gomes
4dfe6bdbe8 Merge pull request #122 from francisbreit/fetch-instances
Update monitor.service.ts - Evolution ap i 1.5.1 - Problemas ao ler / consultar instancias (FETCH_INSTANCES)
2023-09-20 15:09:28 -03:00
Francis Breit
ee343f2fa1 Update monitor.service.ts
Evolution ap i 1.5.1 - Problemas ao ler / consultar instancias (FETCH_INSTANCES)

Ao consultar instancias as mesmas nao apareciam, seja via manager, seja via postman
2023-09-20 11:13:43 -03:00
Davidson Gomes
1a1f5f85b2 Merge tag '1.5.1' into develop
* Added listening_from_me option in Set Typebot
* Added variables options in Start Typebot
* Added webhooks for typebot events
* Added ChamaAI integration
* Added webhook to send errors
* Added support for messaging with ads on chatwoot

* Fix looping connection messages in chatwoot
* Improved performance of fetch instances
2023-09-17 13:55:02 -03:00
Davidson Gomes
bd64b0c884 Merge branch 'release/1.5.1' 2023-09-17 13:54:49 -03:00
Davidson Gomes
e1c8928ed9 Added support for messaging with ads on chatwoot 2023-09-17 13:52:54 -03:00
Davidson Gomes
1f98940445 Added support for messaging with ads on chatwoot 2023-09-17 13:48:42 -03:00
Davidson Gomes
707aa22a6d Added support for messaging with ads on chatwoot 2023-09-17 13:48:27 -03:00
Davidson Gomes
32da15fa8a Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-09-17 13:35:58 -03:00
Davidson Gomes
97cd6e289a Merge pull request #111 from AdsonCicilioti/ads-preview-1.5.1
Initial support for preview and reference from Ads messages on Chatwoot
2023-09-17 13:35:28 -03:00
Davidson Gomes
def6576fb9 Merge branch 'develop' into ads-preview-1.5.1 2023-09-17 13:35:18 -03:00
Davidson Gomes
196c10b253 Merge pull request #108 from raimartinsb/EvolutionAPI-develop
[Improvement] - Send and Update source_id of messages to chatwoot
2023-09-17 13:32:27 -03:00
AdsonCicilioti
cfdca38d59 add: fixed crop (cover) ads imge thumbnail with Jimp library 2023-09-13 00:04:02 -03:00
AdsonCicilioti
ccd90a69ee add: initial support for preview and reference from messages with Ads metadata 2023-09-12 13:43:17 -03:00
AdsonCicilioti
c16f962d2b chore: compreensive var name for conversation term 2023-09-12 13:39:40 -03:00
Davidson Gomes
8fccf69ceb Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-09-11 09:39:13 -03:00
Davidson Gomes
adc8833670 fix: Debug Bad Request 2023-09-11 09:39:09 -03:00
Davidson Gomes
ecbf90ded8 Merge pull request #99 from moskoweb/bug-bad-request
fix: Debug Bad Request
2023-09-11 09:38:28 -03:00
raimartinsb
c5d2d7782a Merge branch 'develop' of https://github.com/EvolutionAPI/evolution-api into EvolutionAPI-develop 2023-09-11 08:08:18 -03:00
raimartinsb
72dae22ef4 Configuration to update source_id only when desired 2023-09-11 07:44:09 -03:00
Alan Mosko
9a9cd41009 wip 2023-09-06 16:24:13 -03:00
Alan Mosko
0c4c8162c2 wip 2023-09-06 16:18:48 -03:00
Alan Mosko
d47cc5d5f4 wip 2023-09-06 16:11:59 -03:00
raimartinsb
cb942e512d improved message update 2023-09-06 13:28:42 -03:00
raimartinsb
bd0a479645 added source_id in media messages 2023-09-06 09:11:15 -03:00
Davidson Gomes
cd0da914f4 Merge pull request #96 from moskoweb/fetch-profile
Get Info JID Correct
2023-09-05 21:42:21 -03:00
Davidson Gomes
7a7e72897a Merge pull request #95 from w3nder/develop
Melhorando o desempenho no carregamento da instância.
2023-09-05 21:41:29 -03:00
Alan Mosko
c1542054c9 Merge branch 'develop' into fetch-profile 2023-09-05 17:47:41 -03:00
Alan Mosko
250e67e7ae Update whatsapp.service.ts 2023-09-05 17:44:47 -03:00
Wender Teixeira
cdbe839b35 Update monitor.service.ts 2023-09-05 11:49:02 -03:00
Wender Teixeira
240a77dcce Update monitor.service.ts
Fix monitor
2023-09-05 11:48:38 -03:00
Wender Teixeira
1dc5bb8bd1 Update monitor.service.ts 2023-09-05 11:47:24 -03:00
Davidson Gomes
23534da27d fix: added delay in chatwoot receive webhook 2023-09-05 08:39:51 -03:00
Wender Teixeira
8652d4031c Update monitor.service.ts 2023-09-04 19:00:42 -03:00
Davidson Gomes
384e311c7a fix: added delay in chatwoot receive webhook 2023-09-04 16:48:04 -03:00
Davidson Gomes
2791f88b4c fix: added delay in chatwoot receive webhook 2023-09-04 16:13:43 -03:00
Wender Teixeira
402d5af19a Update monitor.service.ts 2023-09-04 15:18:32 -03:00
Wender Teixeira
b554d8c19c Update monitor.service.ts (loadInstances)
Melhorando é organizando o loadInstances
2023-09-04 15:11:23 -03:00
Wender Teixeira
7d9dd64303 Update monitor.service.ts
Isso permite que as operações assíncronas sejam executadas em paralelo
2023-09-04 15:06:18 -03:00
Davidson Gomes
41bea8931f test: process exit when errors 2023-09-04 13:08:16 -03:00
Davidson Gomes
f83d8de476 test: process exit when errors 2023-09-04 13:00:16 -03:00
Davidson Gomes
af2a652098 Merge pull request #90 from moskoweb/patch-6
fix: Group Create
2023-09-01 07:02:10 -03:00
Davidson Gomes
a3c911263d Merge pull request #92 from francisbreit/main
fix: Update manager.json
2023-09-01 06:52:02 -03:00
Davidson Gomes
836c677837 Merge branch 'develop' into main 2023-09-01 06:51:40 -03:00
Davidson Gomes
7e4dbfdd7e fix: Added log when send event to rabbitMQ and Websocket 2023-08-31 18:24:30 -03:00
Davidson Gomes
6eda556242 fix: create rabbitmq queues on set config 2023-08-31 17:10:19 -03:00
Davidson Gomes
3ea454c7ed fix: create rabbitmq queues on set config 2023-08-31 17:01:09 -03:00
Davidson Gomes
9123d7014d fix: create rabbitmq queues on set config 2023-08-31 16:49:50 -03:00
Francis Breit
3ea3abe81a Update manager.json
- Added the following settings for instances: Set Typebot and Typebot Change Session Status.
- Fixed bug in Webhook settings
2023-08-31 07:55:53 -03:00
raimartinsb
7289c3d7f9 Add source_id and update message 2023-08-31 07:52:36 -03:00
Alan Mosko
d00e1df29c [Melhoria] Group Create
Verifica todos os participantes e pega apenas os que existe no WhatsApp
2023-08-30 15:09:03 -03:00
Davidson Gomes
16a18c4f22 fix: update error.config.ts 2023-08-30 13:27:47 -03:00
Davidson Gomes
30b156d92f Merge pull request #89 from w3nder/develop
Update error.config.ts
2023-08-30 13:25:22 -03:00
Davidson Gomes
931f9d33e4 Merge pull request #87 from moskoweb/phone-name
fix: navigator client name
2023-08-30 13:24:40 -03:00
Wender Teixeira
e61fe4d092 Update error.config.ts
encerramento controlado para lidar com erros não capturados no aplicativo.
2023-08-30 12:38:53 -03:00
Davidson Gomes
5bc33ac654 Merge pull request #88 from moskoweb/patch-5
Correção de Erro
2023-08-29 21:00:41 -03:00
Alan Mosko
878ba5a869 Correção de Erro
```This comparison appears to be unintentional because the types 'string' and 'number' have no overlap.```
2023-08-29 18:57:31 -03:00
Alan Mosko
92632b2b96 wip 2023-08-29 14:29:50 -03:00
Davidson Gomes
d803a9e298 Merge pull request #85 from w3nder/develop
Fix set event rabbitmq/websocket
2023-08-29 11:29:14 -03:00
Davidson Gomes
b9f67533dd Merge pull request #83 from moskoweb/patch-4
fix: DEL_INSTANCE
2023-08-29 11:27:57 -03:00
Davidson Gomes
7ade78bedf Merge pull request #78 from AdsonCicilioti/docker-net-declaration
clean: docker network declaration and build of the `evolution/api` image
2023-08-29 11:27:10 -03:00
Davidson Gomes
b4eca48f4d Merge pull request #59 from unilogica/main
Bugfix Internal Error 500: fetchInstances (apikey not found)
2023-08-29 11:24:03 -03:00
Davidson Gomes
2cf8e317fa Merge pull request #57 from helioelias/main
Fix: For webhook to work with localhost
2023-08-29 11:15:08 -03:00
Wender Teixeira
821a422ab5 Fix set event rabbitmq/websocket 2023-08-28 23:26:40 -03:00
Alan Mosko
91c7b4f2cd Correção DEL_INSTANCE 2023-08-28 09:59:04 -03:00
AdsonCicilioti
adb43ec5b3 clean: correct docker network declaration 2023-08-26 02:53:02 -03:00
AdsonCicilioti
c9721d7bc9 clean: docker build will be remove in future releases / build into compose file 2023-08-26 02:36:45 -03:00
AdsonCicilioti
bbc2b8a396 clean: declarative bridge network instead shellscript check 2023-08-26 00:29:58 -03:00
Davidson Gomes
54cfa67d52 Added webhook to send errors 2023-08-25 09:31:13 -03:00
Davidson Gomes
9b72b3e332 Added webhook to send errors 2023-08-25 09:01:48 -03:00
Davidson Gomes
c03919be2d Added ChamaAI integration 2023-08-23 08:58:49 -03:00
Davidson Gomes
706cc6f49c Added webhooks for typebot events 2023-08-23 08:15:53 -03:00
Davidson Gomes
10c7e81e02 Added webhooks for typebot events 2023-08-23 07:54:46 -03:00
Davidson Gomes
03637b2d4d Added listening_from_me option in Set Typebot 2023-08-23 07:27:40 -03:00
Davidson Gomes
b7218a05be feat: Inegration with Chama AI 2023-08-19 15:13:35 -03:00
Davidson Gomes
a2cd57d9c6 feat: Inegration with Chama AI 2023-08-19 10:42:41 -03:00
Unilógica
001849eeaa Merge branch 'EvolutionAPI:main' into main 2023-08-18 18:02:53 -03:00
Davidson Gomes
bf09a70096 Merge tag '1.5.0' into develop
* New instance manager in /manager route
* Added extra files for chatwoot and appsmith
* Added Get Last Message and Archive for Chat
* Added env var QRCODE_COLOR
* Added websocket to send events
* Added rabbitmq to send events
* Added Typebot integration
* Added proxy endpoint
* Added send and date_time in webhook data

* Solved problem when disconnecting from the instance the instance was deleted
* Encoded spaces in chatwoot webhook
* Adjustment in the saving of contacts, saving the information of the number and Jid
* Update Dockerfile
* If you pass empty events in create instance and set webhook it is understood as all
* Fixed issue that did not output base64 averages
* Messages sent by the api now arrive in chatwoot

- Chatwoot: v2.18.0 - v3.0.0
- Typebot: v2.16.0
- Manager Evolution API
2023-08-18 12:49:12 -03:00
Davidson Gomes
530aec92a9 Merge branch 'release/1.5.0' 2023-08-18 12:48:53 -03:00
Davidson Gomes
deb8f2a0b7 Added send and date_time in webhook data 2023-08-18 12:48:30 -03:00
Davidson Gomes
5c247e3d2c Added send and date_time in webhook data 2023-08-18 12:46:47 -03:00
Davidson Gomes
04b9a070c4 Added send and date_time in webhook data 2023-08-18 12:46:46 -03:00
Davidson Gomes
dd2caf720c Added Typebot integration 2023-08-18 12:24:05 -03:00
Davidson Gomes
0d16a7aab0 Added Typebot integration 2023-08-18 11:59:04 -03:00
Davidson Gomes
31325d0999 Added Typebot integration 2023-08-18 11:58:41 -03:00
Davidson Gomes
6f99784224 Added Typebot integration 2023-08-18 11:38:50 -03:00
Davidson Gomes
201e6f7e7b Added rabbitmq to send events 2023-08-18 10:38:32 -03:00
Davidson Gomes
c4d41134b8 Messages sent by the api now arrive in chatwoot 2023-08-18 09:33:17 -03:00
Davidson Gomes
680c92ecec Messages sent by the api now arrive in chatwoot 2023-08-18 09:25:34 -03:00
Davidson Gomes
deb07d2b7f Messages sent by the api now arrive in chatwoot 2023-08-18 08:44:13 -03:00
Davidson Gomes
3a14fc373a adjust params rabbitmq 2023-08-17 18:19:46 -03:00
Allyson de Paula
29e429a02e Merge branch 'main' of https://github.com/unilogica/evolution-api 2023-08-17 13:07:05 -03:00
Allyson de Paula
907a0ee135 Proxy test 2023-08-12 15:05:10 -03:00
Unilógica
22a03f77ab Merge pull request #1 from unilogica/develop
Develop
2023-08-12 15:01:54 -03:00
Unilógica
9761b10bf6 Merge branch 'EvolutionAPI:develop' into develop 2023-08-12 12:41:15 -03:00
Davidson Gomes
c364d3fdca feat: Added Typebot integration 2023-08-11 20:49:39 -03:00
Davidson Gomes
07ad5756eb fix: Fixed issue that did not output base64 averages 2023-08-09 16:57:23 -03:00
Allyson de Paula
6e401eecde Bugfix Internal Error 500: fetchInstances (apikey not found) 2023-08-09 16:56:38 -03:00
Helio Elias
f32e259d2f Fix isURL function to by pass url with localhost, when webhook is enable 2023-08-08 21:06:58 -03:00
Helio Elias
83ed0e6454 Merge branch 'EvolutionAPI:main' into main 2023-08-08 21:02:19 -03:00
Davidson Gomes
da568e4ea5 feat: Added version in logs 2023-08-07 19:46:34 -03:00
Davidson Gomes
ad819bf3ba feat: Added Typebot integration 2023-08-07 19:03:15 -03:00
Davidson Gomes
b502ebd23a feat: Added Typebot integration 2023-08-07 18:54:12 -03:00
Davidson Gomes
7c5d94c19e feat: Added Typebot integration 2023-08-07 15:43:57 -03:00
Davidson Gomes
a16b5f4644 feat: added proxy endpoint 2023-08-07 12:10:53 -03:00
Davidson Gomes
f3cb8c531b feat: added proxy endpoint 2023-08-07 12:10:33 -03:00
Davidson Gomes
469e696ab7 Added Typebot integration 2023-08-04 16:15:59 -03:00
Davidson Gomes
d99ccd9df6 Added Typebot integration 2023-08-04 15:03:08 -03:00
Davidson Gomes
3b3118d764 Added Typebot integration 2023-08-04 15:00:55 -03:00
Davidson Gomes
84386847e2 readme buy me coffe 2023-08-03 07:32:29 -03:00
Davidson Gomes
0da3d100b3 feat: Added rabbitmq to send events 2023-08-02 21:33:59 -03:00
Davidson Gomes
56d621bab8 feat: Added rabbitmq to send events 2023-08-02 21:14:21 -03:00
Davidson Gomes
f1571b5f66 feat: Added rabbitmq to send events 2023-08-02 17:41:15 -03:00
Davidson Gomes
55f8e179af feat: Added rabbitmq to send events 2023-08-02 17:39:07 -03:00
Davidson Gomes
ab5289a136 feat: Added rabbitmq to send events 2023-08-02 17:29:09 -03:00
Davidson Gomes
e05c48979d feat: Added rabbitmq to send events 2023-08-02 17:28:52 -03:00
Davidson Gomes
24c880343b feat: Added websocket with lib socket.io 2023-08-02 16:11:19 -03:00
Davidson Gomes
b3b4ee7a28 fix: If you pass empty events in create instance and set webhook it is understood as all 2023-08-02 14:48:02 -03:00
Helio Elias
e26b440a66 Merge pull request #1 from helioelias/fix/dockers
Fix/dockers
2023-08-02 13:29:13 -03:00
Helio Elias
d6194316e1 Fix Dockers 2023-08-02 13:25:00 -03:00
Davidson Gomes
341148612f feat: Added websocket with lib socket.io 2023-08-02 13:21:15 -03:00
Davidson Gomes
79864e97d6 feat: Added websocket with lib socket.io 2023-08-02 13:08:30 -03:00
Davidson Gomes
ed5e66e430 fix: Update view manager 2023-08-01 18:01:29 -03:00
Davidson Gomes
074a861fb4 fix: Update Dockerfile 2023-07-31 16:02:40 -03:00
Davidson Gomes
b88656829e feat: Added env var QRCODE_COLOR 2023-07-31 15:51:05 -03:00
Davidson Gomes
aefe6a5943 feat: Added Get Last Message and Archive for Chat 2023-07-31 15:30:48 -03:00
Davidson Gomes
3d743f8498 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-31 15:30:33 -03:00
Davidson Gomes
0186fff67d feat: Added Get Last Message and Archive for Chat
Added Get Last Message and Archive for Chat
2023-07-31 15:30:26 -03:00
Davidson Gomes
38f61cdf75 fix: Update Dockerfile 2023-07-31 15:28:00 -03:00
Davidson Gomes
84366002db fix: Update Dockerfile 2023-07-31 15:27:47 -03:00
Davidson Gomes
eff5bb74b5 Merge pull request #50 from EvolutionAPI/revert-43-docker
Revert "Update Dockerfile"
2023-07-31 15:26:00 -03:00
Davidson Gomes
2614088fae Revert "Update Dockerfile" 2023-07-31 15:25:48 -03:00
Davidson Gomes
3699e04db9 Merge pull request #43 from moskoweb/docker
Update Dockerfile
2023-07-31 15:25:09 -03:00
Davidson Gomes
0dca009c01 fix: Adjustment in the saving of contacts, saving the information of the number and Jid 2023-07-31 13:42:37 -03:00
Davidson Gomes
1b39eb1a23 add: Added extra files for chatwoot and appsmith 2023-07-31 13:13:41 -03:00
Davidson Gomes
2637aebb7f fix: Encoded spaces in chatwoot webhook 2023-07-31 12:34:01 -03:00
Davidson Gomes
8afcfde078 add: Added extra files for chatwoot and appsmith 2023-07-31 12:26:50 -03:00
Davidson Gomes
9ea1eaf3ed fix: Encoded spaces in chatwoot webhook 2023-07-31 10:55:24 -03:00
Davidson Gomes
66d06afaf7 feat: New instance manager in /manager route 2023-07-30 11:03:12 -03:00
Davidson Gomes
cffcca9722 fix: adjust in instance name in chatwoot 2023-07-29 11:30:37 -03:00
Davidson Gomes
fe2b9774d8 fix: Solved problem when disconnecting from the instance the instance was deleted 2023-07-29 11:09:56 -03:00
Alan Mosko
3d02fabef4 Update Dockerfile 2023-07-27 10:47:26 -03:00
Davidson Gomes
f89c2b1f63 Merge tag '1.4.8' into develop
* Fixed error return bug
2023-07-27 10:28:47 -03:00
Davidson Gomes
ee755d5a6c Merge branch 'release/1.4.8' 2023-07-27 10:28:40 -03:00
Davidson Gomes
65e2ecf88e version: 1.4.8 2023-07-27 10:28:26 -03:00
Davidson Gomes
332ec69ee8 fix: Adjusts in return errors 2023-07-27 10:27:41 -03:00
Alan Mosko
1ce30f8431 Update whatsapp.service.ts 2023-07-27 10:20:18 -03:00
Alan Mosko
3ae6944307 Update whatsapp.service.ts 2023-07-27 09:24:38 -03:00
Alan Mosko
52533d4b38 Adição de Get Last Message e Archive por Chat 2023-07-27 09:23:44 -03:00
Davidson Gomes
38409d9336 Merge tag '1.4.7' into develop
* Fixed error return bug
* Fixed problem of getting message when deleting message in chatwoot
* Change in error return pattern
2023-07-27 08:53:02 -03:00
Davidson Gomes
d344e513c4 Merge branch 'release/1.4.7' 2023-07-27 08:52:52 -03:00
Davidson Gomes
9af7f67930 version: 1.4.7 2023-07-27 08:52:45 -03:00
Davidson Gomes
f95d938fb6 fix: Adjusts in return errors 2023-07-27 08:51:58 -03:00
Davidson Gomes
f74a7e87bd version: 1.4.7 2023-07-27 08:48:03 -03:00
Davidson Gomes
d3fce5fc89 fix: Fixed problem of getting message when deleting message in chatwoot 2023-07-27 08:45:02 -03:00
Davidson Gomes
14f3f3d2ac fix: fixed error return bug 2023-07-27 08:36:37 -03:00
Davidson Gomes
127d5b97c4 fix: fixed error return bug 2023-07-27 08:36:18 -03:00
Davidson Gomes
7ef1c097e8 text: Fix problem No Session 2023-07-26 21:45:49 -03:00
Davidson Gomes
80e3116cd8 text: Fix problem No Session 2023-07-26 21:45:23 -03:00
Davidson Gomes
46bac55bb3 Merge tag '1.4.6' into develop
* Fixed bug of creating new inbox by chatwoot
* When conversation reopens is pending when conversation pending is true
* Added docker-compose file with dockerhub image
2023-07-26 18:42:10 -03:00
Davidson Gomes
2cadafd5c1 Merge branch 'release/1.4.6' 2023-07-26 18:41:39 -03:00
Davidson Gomes
bb27dca21c Merge pull request #36 from moskoweb/groupJid-query-or-body
Correção Validação de Grupo por Query e Body
2023-07-26 18:41:06 -03:00
Davidson Gomes
86fc9fbffa Merge branch 'develop' into groupJid-query-or-body 2023-07-26 18:40:54 -03:00
Alan Mosko
9bdbfc6f4f wip 2023-07-26 18:28:18 -03:00
Davidson Gomes
28a7d9c62b fix: Adjusts in instance name 2023-07-26 18:02:45 -03:00
Davidson Gomes
2ca344b17c Merge tag '1.4.6' into develop
* Fixed bug of creating new inbox by chatwoot
* When conversation reopens is pending when conversation pending is true
* Added docker-compose file with dockerhub image
2023-07-26 17:54:42 -03:00
Davidson Gomes
1bf2278f31 version: 1.4.6 2023-07-26 17:54:29 -03:00
Davidson Gomes
6188ab0d30 Merge branch 'main' of github.com:EvolutionAPI/evolution-api 2023-07-26 17:47:53 -03:00
Davidson Gomes
f016b53013 Merge tag '1.4.6' into develop
* Fixed bug of creating new inbox by chatwoot
* When conversation reopens is pending when conversation pending is true
* Added docker-compose file with dockerhub image
2023-07-26 17:47:01 -03:00
Davidson Gomes
127cd3e843 Merge branch 'release/1.4.6' 2023-07-26 17:46:52 -03:00
Davidson Gomes
457dbe5831 version: 1.4.6 2023-07-26 17:46:45 -03:00
Davidson Gomes
8d73fb1161 Merge pull request #35 from EvolutionAPI/revert-34-groupJid-query-or-body
Revert "GroupJid por Query ou por Body"
2023-07-26 17:45:41 -03:00
Davidson Gomes
af5746bb39 Revert "GroupJid por Query ou por Body" 2023-07-26 17:45:28 -03:00
Davidson Gomes
3f27d018c7 Merge pull request #34 from moskoweb/groupJid-query-or-body
fix: GroupJid por Query ou por Body
2023-07-26 17:45:16 -03:00
Davidson Gomes
68402393b5 Merge branch 'main' into groupJid-query-or-body 2023-07-26 17:43:28 -03:00
Davidson Gomes
2ad33857f4 Merge tag '1.4.6' into develop
* Fixed bug of creating new inbox by chatwoot
* When conversation reopens is pending when conversation pending is true
* Added docker-compose file with dockerhub image
2023-07-26 17:41:18 -03:00
Davidson Gomes
d3c7677dc7 Merge branch 'release/1.4.6' 2023-07-26 17:41:10 -03:00
Davidson Gomes
73e92f9ef5 version: 1.4.6 2023-07-26 17:41:06 -03:00
Davidson Gomes
fcc8748daf Merge branch 'release/1.4.6' 2023-07-26 17:40:07 -03:00
Davidson Gomes
312ee249b6 version: 1.4.6 2023-07-26 17:39:59 -03:00
Davidson Gomes
e4548f6961 fix: Added docker-compose file with dockerhub image 2023-07-26 17:39:32 -03:00
Davidson Gomes
1b93aac8c5 fix: When conversation reopens is pending when conversation pending is true 2023-07-26 17:33:31 -03:00
Alan Mosko
e7ed666037 Update abstract.router.ts 2023-07-26 17:27:25 -03:00
Davidson Gomes
85ca0683ed fix: fixed bug of creating new inbox by chatwoot 2023-07-26 17:15:09 -03:00
Davidson Gomes
78689a23e5 Code Formatter
fix: Code Formatter
2023-07-26 12:44:01 -03:00
Davidson Gomes
ba63a55883 Merge branch 'develop' into formatter 2023-07-26 12:43:37 -03:00
Alan Mosko
dc3d59bae1 wip 2023-07-26 11:12:00 -03:00
Alan Mosko
0a851b935e Update .gitignore 2023-07-26 11:10:23 -03:00
Alan Mosko
ddc75d710f wip 2023-07-26 11:08:14 -03:00
Alan Mosko
5482601b41 Squashed commit of the following:
commit fb6e58b3c4
Merge: 1d3d557 67e9845
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:39:37 2023 -0300

    Merge branch 'release/1.4.5'

commit 67e98456bb
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:39:27 2023 -0300

    fix: Fix mids going duplicated in chatwoot

commit 3e47420534
Merge: 3f41974 1d3d557
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:38:44 2023 -0300

    Merge tag '1.4.5' into develop

    * Fixed problems in localization template in chatwoot
    * Fix mids going duplicated in chatwoot

commit 1d3d557c43
Merge: 6b926dc 3f41974
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:38:36 2023 -0300

    Merge branch 'release/1.4.5'

commit 3f41974a75
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:38:22 2023 -0300

    fix: Fix mids going duplicated in chatwoot

commit 3e3c7397a5
Merge: de0c9a1 dcb5170
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:36:10 2023 -0300

    Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop

commit dcb51702e7
Merge: 4769d75 dd0c1e2
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:36:01 2023 -0300

    Merge pull request #30 from codephix/patch-1

    Update whatsapp.service.ts

commit de0c9a1eff
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Wed Jul 26 09:34:10 2023 -0300

    fix: fixed problems in localization template

commit dd0c1e20a7
Author: CodePhix <contato@codephix.com>
Date:   Tue Jul 25 19:59:42 2023 -0300

    Update whatsapp.service.ts

commit 4769d75dc3
Merge: ecae077 6b926dc
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 16:20:04 2023 -0300

    Merge tag '1.4.4' into develop

    * Fixed chatwoot line wrap issue
    * Solved receive location in chatwoot
    * When requesting the pairing code, it also brings the qr code
    * Option reopen_conversation in chatwoot endpoint
    * Option conversation_pending in chatwoot endpoint

commit 6b926dc697
Merge: 2b6dbfd ecae077
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 16:19:54 2023 -0300

    Merge branch 'release/1.4.4'

commit ecae077c6d
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 16:16:49 2023 -0300

    fix: Option conversation_pending in chatwoot endpoint

commit 78ab1bed35
Merge: 6bb1abd 2b6dbfd
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 15:31:16 2023 -0300

    Merge tag '1.4.4' into develop

    * Fixed chatwoot line wrap issue
    * Solved receive location in chatwoot
    * When requesting the pairing code, it also brings the qr code
    * Option reopen_conversation in chatwoot endpoint
    * Option conversation_pending in chatwoot endpoint

commit 2b6dbfde6b
Merge: 82b1567 6bb1abd
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 15:31:06 2023 -0300

    Merge branch 'release/1.4.4'

commit 6bb1abd7f0
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 15:29:42 2023 -0300

    fix: Option conversation_pending in chatwoot endpoint

commit aef92240cc
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 15:20:21 2023 -0300

    fix: Option conversation_pending in chatwoot endpoint

commit f0d8c2d095
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 13:19:15 2023 -0300

    fix: Solved receive location in chatwoot

commit 14529f2c35
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 12:47:35 2023 -0300

    fix: When requesting the pairing code, it also brings the qr code

commit 89f40d54d9
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 12:41:54 2023 -0300

    fix: Solved receive location in chatwoot

commit 4c006970a2
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 11:52:26 2023 -0300

    fix: Fixed chatwoot line wrap issue

commit de676041df
Merge: 1cd7291 82b1567
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:51:53 2023 -0300

    Merge tag '1.4.3' into develop

    * Adjusts in settings with options always_online, read_messages and read_status
    * Fixed send webhook for event CALL
    * Create instance with settings

commit 82b1567ae5
Merge: f95f312 1cd7291
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:51:42 2023 -0300

    Merge branch 'release/1.4.3'

commit 1cd7291068
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:51:28 2023 -0300

    version: 1.4.3

commit fdee1df5b3
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:42:45 2023 -0300

    fix: Create instance with settings

commit c314d00ccd
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:42:34 2023 -0300

    fix: Create instance with settings

commit 62e2a8a6e3
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 10:23:18 2023 -0300

    fix: Fixed send webhook for event CALL

commit a12231a0aa
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Tue Jul 25 09:57:28 2023 -0300

    fix: Adjusts in settings with options always_online, read_messages and read_status

commit 183efd427a
Merge: 4d9ca4b f95f312
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:52:58 2023 -0300

    Merge tag '1.4.2' into develop

    * Fixed validation is set settings
    * Adjusts in group validations
    * Ajusts in sticker message to chatwoot

commit f95f3126c3
Merge: cc91f2e 4d9ca4b
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:52:46 2023 -0300

    Merge branch 'release/1.4.2'

commit 4d9ca4b451
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:52:34 2023 -0300

    version: 1.4.2

commit c76334a68a
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:32:29 2023 -0300

    fix: Ajusts in sticker message to chatwoot

commit f475391ba6
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:32:15 2023 -0300

    fix: Ajusts in sticker message to chatwoot

commit b77f22790b
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:13:18 2023 -0300

    fix: Fixed validation is set settings

commit 757a578c6e
Merge: c582476 f8e1892
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:12:51 2023 -0300

    Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop

commit c5824767c8
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:11:49 2023 -0300

    fix: Fixed validation is set settings

commit 84f3f07279
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:11:15 2023 -0300

    fix: Fixed validation is set settings

commit f8e1892eee
Merge: 036a8ed 58ed6f3
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:08:24 2023 -0300

    fix: group validation

    Group validation

commit 036a8edca0
Merge: 3d8e6f4 ef4be6a
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 20:07:05 2023 -0300

    fix: Promote All Participants in Create Group

    Promote All Participants in Create Group

commit 58ed6f395f
Author: Alan Mosko <moskoweb@gmail.com>
Date:   Mon Jul 24 19:59:09 2023 -0300

    Validação de Grupo

commit ef4be6a612
Author: Alan Mosko <moskoweb@gmail.com>
Date:   Mon Jul 24 19:53:03 2023 -0300

    Start

commit 3d8e6f4394
Merge: 8b6e577 0cc1f18
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 19:08:39 2023 -0300

    fix: Fixed mentions

    Fixed mentions

commit 0cc1f18a7e
Author: Alan Mosko <moskoweb@gmail.com>
Date:   Mon Jul 24 19:05:32 2023 -0300

    [BUG] Correção de mencionar

    Caso seja enviado everyOne como false sem passar nada no mentioned

commit 8b6e577b8f
Merge: f9abd90 cc91f2e
Author: Davidson Gomes <davidsongviolao@gmail.com>
Date:   Mon Jul 24 18:28:57 2023 -0300

    Merge tag '1.4.1' into develop

    * Fixed reconnect with pairing code or qrcode
    * Fixed problem in createJid
2023-07-26 10:59:15 -03:00
Alan Mosko
249aecbc0d wip 2023-07-26 10:58:13 -03:00
Alan Mosko
03f3020e9f wip 2023-07-26 10:30:56 -03:00
Alan Mosko
e151eb85f0 wip 2023-07-26 10:30:26 -03:00
Davidson Gomes
348586553e Merge tag '1.4.5' into develop
* Fixed problems in localization template in chatwoot
* Fix mids going duplicated in chatwoot
2023-07-26 09:39:45 -03:00
Davidson Gomes
fb6e58b3c4 Merge branch 'release/1.4.5' 2023-07-26 09:39:37 -03:00
Davidson Gomes
67e98456bb fix: Fix mids going duplicated in chatwoot 2023-07-26 09:39:27 -03:00
Davidson Gomes
3e47420534 Merge tag '1.4.5' into develop
* Fixed problems in localization template in chatwoot
* Fix mids going duplicated in chatwoot
2023-07-26 09:38:44 -03:00
Davidson Gomes
1d3d557c43 Merge branch 'release/1.4.5' 2023-07-26 09:38:36 -03:00
Davidson Gomes
3f41974a75 fix: Fix mids going duplicated in chatwoot 2023-07-26 09:38:22 -03:00
Davidson Gomes
3e3c7397a5 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-26 09:36:10 -03:00
Davidson Gomes
dcb51702e7 Merge pull request #30 from codephix/patch-1
Update whatsapp.service.ts
2023-07-26 09:36:01 -03:00
Davidson Gomes
de0c9a1eff fix: fixed problems in localization template 2023-07-26 09:34:10 -03:00
CodePhix
dd0c1e20a7 Update whatsapp.service.ts 2023-07-25 19:59:42 -03:00
Davidson Gomes
4769d75dc3 Merge tag '1.4.4' into develop
* Fixed chatwoot line wrap issue
* Solved receive location in chatwoot
* When requesting the pairing code, it also brings the qr code
* Option reopen_conversation in chatwoot endpoint
* Option conversation_pending in chatwoot endpoint
2023-07-25 16:20:04 -03:00
Davidson Gomes
6b926dc697 Merge branch 'release/1.4.4' 2023-07-25 16:19:54 -03:00
Davidson Gomes
ecae077c6d fix: Option conversation_pending in chatwoot endpoint 2023-07-25 16:16:49 -03:00
Davidson Gomes
78ab1bed35 Merge tag '1.4.4' into develop
* Fixed chatwoot line wrap issue
* Solved receive location in chatwoot
* When requesting the pairing code, it also brings the qr code
* Option reopen_conversation in chatwoot endpoint
* Option conversation_pending in chatwoot endpoint
2023-07-25 15:31:16 -03:00
Davidson Gomes
2b6dbfde6b Merge branch 'release/1.4.4' 2023-07-25 15:31:06 -03:00
Davidson Gomes
6bb1abd7f0 fix: Option conversation_pending in chatwoot endpoint 2023-07-25 15:29:42 -03:00
Davidson Gomes
aef92240cc fix: Option conversation_pending in chatwoot endpoint 2023-07-25 15:20:21 -03:00
Davidson Gomes
f0d8c2d095 fix: Solved receive location in chatwoot 2023-07-25 13:19:15 -03:00
Davidson Gomes
14529f2c35 fix: When requesting the pairing code, it also brings the qr code 2023-07-25 12:47:35 -03:00
Davidson Gomes
89f40d54d9 fix: Solved receive location in chatwoot 2023-07-25 12:41:54 -03:00
Davidson Gomes
4c006970a2 fix: Fixed chatwoot line wrap issue 2023-07-25 11:52:26 -03:00
Davidson Gomes
de676041df Merge tag '1.4.3' into develop
* Adjusts in settings with options always_online, read_messages and read_status
* Fixed send webhook for event CALL
* Create instance with settings
2023-07-25 10:51:53 -03:00
Davidson Gomes
82b1567ae5 Merge branch 'release/1.4.3' 2023-07-25 10:51:42 -03:00
Davidson Gomes
1cd7291068 version: 1.4.3 2023-07-25 10:51:28 -03:00
Davidson Gomes
fdee1df5b3 fix: Create instance with settings 2023-07-25 10:42:45 -03:00
Davidson Gomes
c314d00ccd fix: Create instance with settings 2023-07-25 10:42:34 -03:00
Davidson Gomes
62e2a8a6e3 fix: Fixed send webhook for event CALL 2023-07-25 10:23:18 -03:00
Davidson Gomes
a12231a0aa fix: Adjusts in settings with options always_online, read_messages and read_status 2023-07-25 09:57:28 -03:00
Davidson Gomes
183efd427a Merge tag '1.4.2' into develop
* Fixed validation is set settings
* Adjusts in group validations
* Ajusts in sticker message to chatwoot
2023-07-24 20:52:58 -03:00
Davidson Gomes
f95f3126c3 Merge branch 'release/1.4.2' 2023-07-24 20:52:46 -03:00
Davidson Gomes
4d9ca4b451 version: 1.4.2 2023-07-24 20:52:34 -03:00
Davidson Gomes
c76334a68a fix: Ajusts in sticker message to chatwoot 2023-07-24 20:32:29 -03:00
Davidson Gomes
f475391ba6 fix: Ajusts in sticker message to chatwoot 2023-07-24 20:32:15 -03:00
Davidson Gomes
b77f22790b fix: Fixed validation is set settings 2023-07-24 20:13:18 -03:00
Davidson Gomes
757a578c6e Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-24 20:12:51 -03:00
Davidson Gomes
c5824767c8 fix: Fixed validation is set settings 2023-07-24 20:11:49 -03:00
Davidson Gomes
84f3f07279 fix: Fixed validation is set settings 2023-07-24 20:11:15 -03:00
Davidson Gomes
f8e1892eee fix: group validation
Group validation
2023-07-24 20:08:24 -03:00
Davidson Gomes
036a8edca0 fix: Promote All Participants in Create Group
Promote All Participants in Create Group
2023-07-24 20:07:05 -03:00
Alan Mosko
58ed6f395f Validação de Grupo 2023-07-24 19:59:09 -03:00
Alan Mosko
ef4be6a612 Start 2023-07-24 19:53:03 -03:00
Davidson Gomes
3d8e6f4394 fix: Fixed mentions
Fixed mentions
2023-07-24 19:08:39 -03:00
Alan Mosko
0cc1f18a7e [BUG] Correção de mencionar
Caso seja enviado everyOne como false sem passar nada no mentioned
2023-07-24 19:05:32 -03:00
Davidson Gomes
8b6e577b8f Merge tag '1.4.1' into develop
* Fixed reconnect with pairing code or qrcode
* Fixed problem in createJid
2023-07-24 18:28:57 -03:00
Davidson Gomes
cc91f2e5db Merge branch 'release/1.4.1' 2023-07-24 18:28:45 -03:00
Davidson Gomes
8d1f2313ac version: 1.4.1 2023-07-24 18:28:39 -03:00
Davidson Gomes
f9abd90cc9 fix: connection state 2023-07-24 18:28:01 -03:00
Davidson Gomes
f7293255cf fix: Fixed reconnect with pairing code or qrcode 2023-07-24 18:21:11 -03:00
Davidson Gomes
7d6a130cf9 Merge tag '1.4.0' into develop
* Added connection functionality via pairing code
* Added fetch profile endpoint in chat controller
* Created settings controller
* Added reject call and send text message when receiving a call
* Added setting to ignore group messages
* Added connection with pairing code in chatwoot with command /init:{NUMBER}
* Added encoding option in endpoint sendWhatsAppAudio

* Added link preview option in send text message
* Fixed problem with fileSha256 appearing when sending a sticker in chatwoot
* Fixed issue where it was not possible to open a conversation when sent at first by me on my cell phone in chatwoot
* Now it only updates the contact name if it is the same as the phone number in chatwoot
* Now accepts all chatwoot inbox templates
* Command to create new instances set to /new_instance:{NAME}:{NUMBER}
* Fix in chatwoot set, sign msg can now be disabled

- Chatwoot: v2.18.0 - v3.0.0 (Beta)
2023-07-24 17:05:43 -03:00
Davidson Gomes
be7bb2e39f Merge branch 'release/1.4.0' 2023-07-24 17:05:33 -03:00
Davidson Gomes
1c30728880 version: 1.4.0 2023-07-24 17:05:18 -03:00
Davidson Gomes
8d91e7cb1d feat: Added encoding option in endpoint sendWhatsAppAudio 2023-07-24 16:21:29 -03:00
Davidson Gomes
68d980795a fix: fix in chatwoot set, sign msg can now be disabled 2023-07-24 15:13:46 -03:00
Davidson Gomes
45c11a5a8e fix: fix in chatwoot set, sign msg can now be disabled 2023-07-24 15:12:13 -03:00
Davidson Gomes
4d00351db7 fix: command to create new instances set to /new_instance:<NAME>:<NUMBER> 2023-07-24 15:05:26 -03:00
Davidson Gomes
fff420b652 fix: command to create new instances set to /new_instance:<NAME>:<NUMBER> 2023-07-24 15:05:03 -03:00
Davidson Gomes
7103a95305 feat: Added connection with pairing code in chatwoot 2023-07-24 13:43:18 -03:00
Davidson Gomes
bcada5d553 fix: Now accepts all chatwoot inbox templates 2023-07-24 13:03:40 -03:00
Davidson Gomes
c9b24ff612 fix: adjusts for chatwoot v3 2023-07-24 12:55:27 -03:00
Davidson Gomes
854c7ed04d fix: Improvement for Validation of Numbers and Groups 2023-07-24 12:02:38 -03:00
Davidson Gomes
c0054959cd fix: Improvement for Validation of Numbers and Groups
Improvement for Validation of Numbers and Groups
2023-07-24 12:00:33 -03:00
Davidson Gomes
1aa837d220 fix: Adjusts in chatwoot integration 2023-07-24 11:58:52 -03:00
Alan Mosko
95df402c4c wip 2023-07-24 11:57:15 -03:00
Davidson Gomes
2f3d6f7e63 fix: Fixed problem with fileSha256 appearing when sending a sticker in chatwoot 2023-07-24 11:48:10 -03:00
Alan Mosko
ffe1523170 Update whatsapp.service.ts 2023-07-24 11:42:06 -03:00
Davidson Gomes
a73d5f4b4d Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-24 11:18:12 -03:00
Davidson Gomes
f35b62ed12 fix: Adjusts in createJid 2023-07-24 11:18:08 -03:00
Davidson Gomes
20abdd2908 fix: Adjusts in createJid to sendContact
Adjusts in createJid to sendContact
2023-07-24 11:17:35 -03:00
Alan Mosko
28c2c7285c Gerar Wuid no SendContact 2023-07-24 11:15:58 -03:00
Davidson Gomes
3ca8ab12a4 fix: Adjusts in createJid
Adjusts in createJid
2023-07-24 11:13:30 -03:00
Alan Mosko
fd82aa143c wip 2023-07-24 11:10:32 -03:00
Davidson Gomes
1fcbd4f9fd feat: Added reject call and send text message when receiving a call and Added setting to ignore group messages 2023-07-24 10:18:16 -03:00
Davidson Gomes
73d9cd62a5 feat: Created settings Controller 2023-07-24 09:42:29 -03:00
Davidson Gomes
be699d24a1 feat: Added fetch profile endpoint in chat controller and link preview option in send text message 2023-07-23 22:26:38 -03:00
Davidson Gomes
798eb90bed feat: Added fetch profile endpoint in chat controller and link preview option in send text message 2023-07-23 22:24:21 -03:00
Davidson Gomes
c252f5f8d9 Merge pull request #20 from EvolutionAPI/revert-18-fetch-profile
Revert "Adição de FetchProfile"
2023-07-23 22:05:38 -03:00
Davidson Gomes
76d77ad76f Revert "Adição de FetchProfile" 2023-07-23 22:05:21 -03:00
Davidson Gomes
69f5cdd61a feat: added fetchProfile endpoint in chat controller
Added fetchProfile endpoint in chat controller
2023-07-23 21:30:11 -03:00
Davidson Gomes
9f52f20660 feat: Add LinkPreview Option
Add LinkPreview Option
2023-07-23 21:25:20 -03:00
Alan Mosko
90048afa9d Add LinkPreview Option 2023-07-23 11:24:16 -03:00
Alan Mosko
1ec3ed32ee Melhorias 2023-07-23 10:18:00 -03:00
Davidson Gomes
16ed5821e2 Added connection functionality via pairing code 2023-07-21 20:58:37 -03:00
Davidson Gomes
b681e33944 Added connection functionality via pairing code 2023-07-21 20:38:10 -03:00
Davidson Gomes
8f4d44a212 Added connection functionality via pairing code 2023-07-21 20:37:58 -03:00
Davidson Gomes
93a5d07f9a Merge tag '1.3.2' into develop
* Fix in update settings that needed to restart after updated
* Correction in the use of the api with mongodb
* Adjustments to search endpoint for contacts, chats, messages and Status messages
* Now when deleting the instance, the data referring to it in mongodb is also deleted
* It is now validated if the instance name contains uppercase and special characters
* For compatibility reasons, container mode has been removed
* Added docker-compose files example
2023-07-21 17:20:19 -03:00
Davidson Gomes
40c230c7db Merge branch 'release/1.3.2' 2023-07-21 17:20:08 -03:00
Davidson Gomes
d0fa3b92f8 version: 1.3.2 2023-07-21 17:19:59 -03:00
Davidson Gomes
2a7727cf5f Merge tag '1.3.2' into develop
* Fix in update settings that needed to restart after updated
* Correction in the use of the api with mongodb
* Adjustments to search endpoint for contacts, chats, messages and Status messages
* Now when deleting the instance, the data referring to it in mongodb is also deleted
* It is now validated if the instance name contains uppercase and special characters
* For compatibility reasons, container mode has been removed
* Added docker-compose files example
2023-07-21 17:18:50 -03:00
Davidson Gomes
98722e7acf Merge branch 'release/1.3.2' 2023-07-21 17:18:40 -03:00
Davidson Gomes
683fe4c3db fix: added docker-compose files example 2023-07-21 16:00:58 -03:00
Alan Mosko
e851696430 Adição de Profile Route 2023-07-21 15:32:28 -03:00
Davidson Gomes
b2ccf965bb fix: added docker-compose files example 2023-07-21 15:14:46 -03:00
Davidson Gomes
f847f38812 fix: added docker-compose files example 2023-07-21 15:13:49 -03:00
Davidson Gomes
19039aa281 fix: For compatibility reasons, container mode has been removed 2023-07-21 13:12:55 -03:00
Davidson Gomes
091b920a22 fix: It is now validated if the instance name contains uppercase and special characters 2023-07-21 12:40:58 -03:00
Davidson Gomes
d7f264c1c2 fix: It is now validated if the instance name contains uppercase and special characters 2023-07-21 12:26:43 -03:00
Davidson Gomes
897f8164b9 fix: Now when deleting the instance, the data referring to it in mongodb is also deleted 2023-07-21 12:13:03 -03:00
Helio Elias
04a6f7c954 fix docker and create docker-compose with all services 2023-07-21 15:02:09 +00:00
Davidson Gomes
796287a776 fix: Adjustments to search endpoint for contacts, chats, messages and Status messages 2023-07-21 11:38:36 -03:00
Davidson Gomes
763e30bd1d fix: fix in update settings that needed to restart after updated 2023-07-21 09:34:39 -03:00
Davidson Gomes
5121374d60 Merge tag '1.3.1' into develop
version: 1.3.1
2023-07-21 08:26:24 -03:00
Davidson Gomes
3e3a175bdc Merge branch 'release/1.3.1' 2023-07-21 08:26:15 -03:00
Davidson Gomes
4a1aa9130b version: 1.3.1 2023-07-21 08:26:05 -03:00
Davidson Gomes
5a3f5f60b6 test: container mode with chatwoot 2023-07-20 10:08:57 -03:00
Davidson Gomes
8c1600be55 Merge tag '1.3.1' into develop
* Adjust in create store files
2023-07-20 07:49:54 -03:00
Davidson Gomes
7d3ae2347b Merge branch 'release/1.3.1' 2023-07-20 07:49:43 -03:00
Davidson Gomes
27add47db4 fix: Adjust in create store files 2023-07-20 07:49:32 -03:00
Davidson Gomes
836bcab036 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-20 07:15:36 -03:00
Davidson Gomes
2d20a07dfb fix: Adjust in create store files 2023-07-20 07:14:07 -03:00
Davidson Gomes
24c5c70466 fix: remove comments in .env to docker
fix: remove comments in .env to docker
2023-07-19 12:32:47 -03:00
Davidson Gomes
22ead22499 Merge branch 'develop' into patch-1 2023-07-19 12:32:06 -03:00
Davidson Gomes
65e1620b43 Merge tag '1.3.0' into develop
* Added messages.delete event
* Added restart instance endpoint
* Created automation for creating instances in the chatwoot bot with the command '#inbox_whatsapp:<INSTANCE_NAME>'
* Change Baileys version to: 6.4.0
* Send contact in chatwoot
* Send contact array in chatwoot
* Added apiKey in webhook and serverUrl in fetchInstance if EXPOSE_IN_FETCH_INSTANCES: true
* Translation set to default (english) in chatwoot

* Fixed error to send message in large groups
* Docker files adjusted
* Fixed in the postman collection the webhookByEvent parameter by webhook_by_events
* Added validations in create instance
* Removed link preview endpoint, now it's done automatically from sending conventional text
* Added group membership validation before sending message to groups
* Adjusts in docker files
* Adjusts in returns in endpoints chatwoot and webhook
* Fixed ghost mentions in send text message
* Fixed bug that saved contacts from groups came without number in chatwoot
* Fixed problem to receive csat in chatwoot
* Fixed require fileName for document only in base64 for send media message
* Bug fix when sending mobile message change contact name to number in chatwoot
* Bug fix when connecting whatsapp does not send confirmation message
* Fixed quoted message with id or message directly
* Adjust in validation for mexican and argentine numbers
* Adjust in create store files

- Chatwoot: v2.18.0
2023-07-19 11:33:42 -03:00
Davidson Gomes
acac09375e Merge branch 'release/1.3.0' 2023-07-19 11:33:32 -03:00
Davidson Gomes
83cf859da3 version: 1.3.0 2023-07-19 11:33:23 -03:00
Alan Mosko
956c391f13 Remoção de Comentários dos Valores
Ao subir um container de testes, verifiquei que os comentários subiram como valores dos campos, o que invalidou algumas conigurações.
2023-07-19 10:15:05 -03:00
Davidson Gomes
7767a2607e test: chatwoot 2023-07-19 08:18:07 -03:00
Davidson Gomes
429d1ac183 fix: Adjust in create store files 2023-07-19 08:14:11 -03:00
Davidson Gomes
f42928f88f fix: Adjust in create store files 2023-07-19 08:13:59 -03:00
Davidson Gomes
2d816ab92d Merge pull request #5 from w3nder/develop
fix: create store folder
2023-07-19 08:11:16 -03:00
Davidson Gomes
aa75380662 fix: Adjust in validation for mexican and argentine numbers 2023-07-19 08:02:24 -03:00
Davidson Gomes
3cf0ced62e test: status/stories 2023-07-18 20:23:18 -03:00
Davidson Gomes
41fa700fb3 feat: translation set to default (english) in chatwoot 2023-07-18 16:01:05 -03:00
Davidson Gomes
a4ef9fb9b7 feat: translation set to default (english) in chatwoot 2023-07-18 15:55:24 -03:00
Davidson Gomes
1db23b5277 fix: Adjusts to receive contact with no whatsapp 2023-07-18 15:53:53 -03:00
Davidson Gomes
584f0cbac0 fix: Adjusts to receive contact with more numbers 2023-07-18 15:13:41 -03:00
Davidson Gomes
dc432a19a3 fix: Adjusts to receive contact with more numbers 2023-07-18 14:57:18 -03:00
Davidson Gomes
6727b1cfca fix: Adjusts to receive contact with more numbers 2023-07-18 14:49:38 -03:00
Davidson Gomes
8c7b0698f3 feat: Added apiKey in webhook and serverUrl in fetchInstance if EXPOSE_IN_FETCH_INSTANCES: true 2023-07-18 14:30:40 -03:00
Davidson Gomes
69e1622e82 feat: Send contact array in chatwoot 2023-07-18 13:17:03 -03:00
w3nder
af7a5d3248 Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-18 13:08:59 -03:00
w3nder
7b1a4554ad fix: create folder store 2023-07-18 13:08:53 -03:00
Davidson Gomes
b3e213c133 fix: Added replace special caracters and espaces in instanceName 2023-07-18 12:58:53 -03:00
Davidson Gomes
a9fafec79d fix: Bug fix when connecting whatsapp does not send confirmation message 2023-07-18 12:50:18 -03:00
Davidson Gomes
7cacf7bbaf fix: Bug fix when connecting whatsapp does not send confirmation message 2023-07-18 12:47:03 -03:00
Davidson Gomes
44bf39f7b7 feat: Send contact in chatwoot 2023-07-18 12:36:26 -03:00
Davidson Gomes
0db8f7295b feat: Send contact in chatwoot 2023-07-18 12:33:55 -03:00
Davidson Gomes
c1226062b1 test: contacts update 2023-07-18 11:25:34 -03:00
Davidson Gomes
819ed168da fix: Fixed require fileName for document only in base64 for send media message 2023-07-18 11:23:40 -03:00
Davidson Gomes
19940953e2 fix: Fixed require fileName for document only in base64 for send media message 2023-07-18 11:21:55 -03:00
Davidson Gomes
f4af3eaf5d fix: adjusts in docker files 2023-07-18 11:00:40 -03:00
Davidson Gomes
718563fe6a fix: adjusts in docker files 2023-07-18 10:58:53 -03:00
Davidson Gomes
7e996ad6fa fix: change Baileys version, fixed problem to receive csat in chatwoot 2023-07-18 10:56:26 -03:00
Davidson Gomes
0b07fb6a49 fix: fixed bug that saved contacts from groups came without number in chatwoot 2023-07-17 15:40:46 -03:00
Davidson Gomes
0cb87e6ed9 feat: Created automation for creating instances in the chatwoot bot with the command #inbox_whatsapp:<INSTANCE_NAME> 2023-07-17 15:37:49 -03:00
Davidson Gomes
71a3e75ae2 fix: Fixed ghost mentions in send text message 2023-07-17 14:57:52 -03:00
Davidson Gomes
a2448ea4c1 fix: adjusts in returns in endpoints chatwoot and webhook 2023-07-17 11:33:18 -03:00
Davidson Gomes
8a14141021 fix: adjusts in returns in endpoints chatwoot and webhook 2023-07-17 11:33:08 -03:00
Davidson Gomes
69353892d9 feat: Added restart instance endpoint 2023-07-16 21:55:12 -03:00
Davidson Gomes
7a2fcc3469 fix: adjusts in dockerfile 2023-07-16 19:21:17 -03:00
Davidson Gomes
dfa6dd5011 fix: adjusts in dockerfile 2023-07-16 19:15:39 -03:00
Davidson Gomes
654400c0cf fix: adjusts in dockerfile 2023-07-16 19:14:00 -03:00
Davidson Gomes
3c15fc1b0d fix: adjusts in dockerfile 2023-07-16 19:05:17 -03:00
Davidson Gomes
4b32485e3c fix: adjusts in dockerfile 2023-07-16 18:52:21 -03:00
Davidson Gomes
b90736ed25 fix: adjusts in dockerfile 2023-07-16 18:51:03 -03:00
Davidson Gomes
f28d5c7781 fix: adjusts in dockerfile 2023-07-16 18:44:10 -03:00
Davidson Gomes
0654627478 fix: adjusts in dockerfile 2023-07-16 18:35:48 -03:00
Davidson Gomes
2e91a2ecdb fix: adjusts in env files 2023-07-16 18:26:53 -03:00
Davidson Gomes
66a8ceb27a feat: added messages.delete event 2023-07-16 18:16:51 -03:00
Davidson Gomes
e6b0addb6c feat: added messages.delete event 2023-07-16 18:16:05 -03:00
Davidson Gomes
c00f132145 fix: Added group membership validation before sending message to groups 2023-07-16 18:01:43 -03:00
Davidson Gomes
b9eb8d45b2 fix: removed link preview endpoint, now it's done automatically from sending conventional text 2023-07-16 17:57:37 -03:00
Davidson Gomes
ec7ad70458 fix: Now it's getting the API URL directly in the request, no longer need the variable in the env file 2023-07-16 17:38:01 -03:00
Davidson Gomes
64e19699fb fix: Docker files adjusted 2023-07-16 15:05:02 -03:00
Davidson Gomes
6d3e1b0cbe fix: Fixed error to send message in large groups 2023-07-16 15:01:38 -03:00
Davidson Gomes
d3a53e1d3c Merge tag '1.2.2' into develop
* Tweak in route "/" with version info
* Adjusts chatwoot version

- Chatwoot: v2.18.0
2023-07-15 09:37:39 -03:00
Davidson Gomes
23bbb3ee32 Merge branch 'release/1.2.2' 2023-07-15 09:37:25 -03:00
Davidson Gomes
56bfcd52b7 fix: Adjusts chatwoot version 2023-07-15 09:37:17 -03:00
Davidson Gomes
1c19b6de1e fix: Adjusts chatwoot version 2023-07-15 09:37:03 -03:00
Davidson Gomes
85bed0bdf1 Merge tag '1.2.1-3' into develop
* Adjusts in docker files
* Save picture url groups in chatwoot
2023-07-14 19:05:19 -03:00
141 changed files with 12233 additions and 2459 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -3,10 +3,14 @@ module.exports = {
parserOptions: {
sourceType: 'CommonJS',
},
plugins: ['@typescript-eslint/eslint-plugin'],
plugins: [
'@typescript-eslint',
'simple-import-sort',
'import'
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:prettier/recommended'
],
globals: {
@@ -26,7 +30,11 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
'import/first': 'error',
'import/no-duplicates': 'error',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'@typescript-eslint/ban-types': [
'error',
{

View File

@@ -0,0 +1,38 @@
---
name: "[EN] Bug report"
about: Create a report to help us improve
title: "[EN][BUG]"
labels: bug
assignees: ''
---
### Title: [Brief Description of the Bug]
#### Description:
Describe in detail the problem you encountered. Include any relevant context that may help understand the origin of the bug.
#### Steps to Reproduce:
1. List the steps necessary to reproduce the problem.
2. Try to be as specific as possible.
3. If the problem occurs in a specific scenario, describe it here.
#### Expected Behavior:
Describe what you expected to happen when following the steps above.
#### Current Behavior:
Explain what actually happens when you follow the steps above.
#### Screenshots/Videos:
If possible, add screenshots or videos illustrating the problem. This can be extremely helpful in understanding the issue.
#### Environment:
- **Server:** [e.g., Ubuntu 18.04]
- **API Version:** [e.g., 1.5.4]
- **Other Hardware/Software Specifications:** [e.g., CPU, GPU]
#### Submitting Logs:
Please attach logs that may be related to the problem. If the logs contain sensitive information, consider sending them privately to one of the project maintainers.
#### Additional Notes:
Include here any other information that you think might be useful in understanding or resolving the bug.

View File

@@ -0,0 +1,28 @@
---
name: "[EN] Feature request"
about: Suggest an idea for the API
title: "[EN][FEAT]"
labels: enhancement
assignees: ''
---
### Title: [Brief Description of Feature Request]
#### Detailed Description:
Clearly and in detail, describe the functionality you wish to be implemented. Explain how this fits into the context of the project.
#### Rationale:
Explain why this functionality would be useful for the project. This helps in understanding the importance and priority of the request.
#### Usage Examples:
Provide specific examples of how this feature could be used. This can include scenarios or use cases where the feature would be particularly beneficial.
#### Possible Implementations:
If you have ideas on how this feature might be implemented, please share them here. This is not mandatory but can be helpful for the development team.
#### Impact on the Project:
Discuss how this new feature could impact other parts of the project, if applicable.
#### Additional Notes:
Any other information you believe is relevant to your request.

View File

@@ -0,0 +1,38 @@
---
name: "[PT] Reportar bug"
about: Reportar um problema
title: "[PT][BUG]"
labels: bug
assignees: ''
---
### Título: [Breve Descrição do Bug]
#### Descrição:
Descreva detalhadamente o problema que você encontrou. Inclua qualquer contexto relevante que possa ajudar a entender a origem do bug.
#### Passos para Reproduzir:
1. Liste os passos necessários para reproduzir o problema.
2. Tente ser o mais específico possível.
3. Se o problema ocorrer em um cenário específico, descreva-o aqui.
#### Comportamento Esperado:
Descreva o que você esperava que acontecesse quando seguisse os passos acima.
#### Comportamento Atual:
Explique o que realmente acontece quando você segue os passos acima.
#### Capturas de Tela/Vídeos:
Se possível, adicione capturas de tela ou vídeos que ilustrem o problema. Isso pode ser extremamente útil para entender o problema.
#### Ambiente:
- **Servidor:** [ex: Ubuntu 18.04]
- **Versão da API:** [ex: 1.5.4]
- **Outras Especificações de Hardware/Software:** [ex: CPU, GPU]
#### Envio de Logs:
Por favor, anexe os logs que possam estar relacionados ao problema. Se os logs contiverem informações sensíveis, considere enviá-los de forma privada para um dos mantenedores do projeto.
#### Notas Adicionais:
Inclua aqui qualquer outra informação que você ache que possa ser útil para entender ou resolver o bug.

View File

@@ -0,0 +1,28 @@
---
name: "[PT] Solicitar recurso"
about: Sugira novos recursos para a API
title: "[PT][FEAT]"
labels: enhancement
assignees: ''
---
### Título: [Breve Descrição da Solicitação de Recurso]
#### Descrição Detalhada:
Descreva claramente e em detalhes a funcionalidade que você deseja que seja implementada. Explique como isso se encaixa no contexto do projeto.
#### Racional:
Explique por que essa funcionalidade seria útil para o projeto. Isso ajuda a entender a importância e a prioridade da solicitação.
#### Exemplos de Uso:
Forneça exemplos específicos de como essa funcionalidade poderia ser utilizada. Isso pode incluir cenários ou casos de uso onde a funcionalidade seria particularmente benéfica.
#### Possíveis Implementações:
Se você tem ideias sobre como essa funcionalidade pode ser implementada, por favor, compartilhe-as aqui. Isso não é obrigatório, mas pode ser útil para a equipe de desenvolvimento.
#### Impacto no Projeto:
Discuta como essa nova funcionalidade poderia impactar outras partes do projeto, se aplicável.
#### Notas Adicionais:
Qualquer outra informação que você acredita ser relevante para a sua solicitação.

9
.gitignore vendored
View File

@@ -16,16 +16,19 @@ lerna-debug.log*
/docker-compose-data
/docker-data
docker-compose.yaml
# Package
/yarn.lock
/package-lock.json
# IDE - VSCode
# IDEs
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.nova/*
# Prisma
/prisma/migrations
@@ -36,5 +39,9 @@ lerna-debug.log*
/test/
/src/env.yml
/store
*.env
/temp/*
.DS_Store
*.DS_Store

View File

@@ -2,8 +2,11 @@ module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 90,
printWidth: 120,
arrowParens: 'always',
tabWidth: 2,
bracketSameLine: true,
bracketSpacing: true
useTabs: false,
bracketSameLine: false,
bracketSpacing: true,
parser: 'typescript'
}

View File

@@ -5,7 +5,9 @@
"editor.smoothScrolling": true,
"editor.tabSize": 2,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll": true
}
"source.fixAll.eslint": "explicit",
"source.fixAll": "explicit"
},
"prisma-smart-formatter.typescript.defaultFormatter": "esbenp.prettier-vscode",
"prisma-smart-formatter.prisma.defaultFormatter": "Prisma.prisma"
}

View File

@@ -1,3 +1,300 @@
# 1.6.1 (2023-12-22 11:43)
### Fixed
* Fixed Lid Messages
* Fixed sending variables to typebot
* Fixed sending variables from typebot
* Correction sending s3/minio media to chatwoot and typebot
* Fixed the problem with typebot closing at the end of the flow, now this is optional with the TYPEBOT_KEEP_OPEN variable
* Fixed chatwoot Bold, Italic and Underline formatting using Regex
* Added the sign_delimiter property to the Chatwoot configuration, allowing you to set a different delimiter for the signature. Default when not defined \n
* Include instance Id field in the instance configuration
* Fixed the pairing code
* Adjusts in typebot
* Fix the problem when disconnecting the instance and connecting again using mongodb
* Options to disable docs and manager
* When deleting a message in whatsapp, delete the message in chatwoot too
# 1.6.0 (2023-12-12 17:24)
### Feature
* Added AWS SQS Integration
* Added support for new typebot API
* Added endpoint sendPresence
* New Instance Manager
* Added auto_create to the chatwoot set to create the inbox automatically or not
* Added reply, delete and message reaction in chatwoot v3.3.1
### Fixed
* Adjusts in proxy
* Adjusts in start session for Typebot
* Added mimetype field when sending media
* Ajusts in validations to messages.upsert
* Fixed messages not received: error handling when updating contact in chatwoot
* Fix workaround to manage param data as an array in mongodb
* Removed await from webhook when sending a message
* Update typebot.service.ts - element.underline change ~ for *
* Removed api restart on receiving an error
* Fixes in mongodb and chatwoot
* Adjusted return from queries in mongodb
* Added restart instance when update profile picture
* Correction of chatwoot functioning with admin flows
* Fixed problem that did not generate qrcode with the chatwoot_conversation_pending option enabled
* Fixed issue where CSAT opened a new ticket when reopen_conversation was disabled
* Fixed issue sending contact to Chatwoot via iOS
### Integrations
* Chatwoot: v3.3.1
* Typebot: v2.20.0
# 1.5.4 (2023-10-09 20:43)
### Fixed
* Baileys logger typing issue resolved
* Solved problem with duplicate messages in chatwoot
# 1.5.3 (2023-10-06 18:55)
### Feature
* Swagger documentation
* Added base 64 sending option via webhook
### Fixed
* Remove rabbitmq queues when delete instances
* Improvement in restart instance to completely redo the connection
* Update node version: v20
* Correction of messages sent by the api and typebot not appearing in chatwoot
* Adjustment to start typebot, added startSession parameter
* Chatwoot now receives messages sent via api and typebot
* Fixed problem with starting with an input in typebot
* Added check to ensure variables are not empty before executing foreach in start typebot
# 1.5.2 (2023-09-28 17:56)
### Fixed
* Fix chatwootSchema in chatwoot model to store reopen_conversation and conversation_pending options
* Problem resolved when sending files from minio to typebot
* Improvement in the "startTypebot" method to create persistent session when triggered
* New manager for Evo 1.5.2 - Set Typebot update
* Resolved problems when reading/querying instances
# 1.5.1 (2023-09-17 13:50)
### Feature
* Added listening_from_me option in Set Typebot
* Added variables options in Start Typebot
* Added webhooks for typebot events
* Added ChamaAI integration
* Added webhook to send errors
* Added support for messaging with ads on chatwoot
### Fixed
* Fix looping connection messages in chatwoot
* Improved performance of fetch instances
# 1.5.0 (2023-08-18 12:47)
### Feature
* New instance manager in /manager route
* Added extra files for chatwoot and appsmith
* Added Get Last Message and Archive for Chat
* Added env var QRCODE_COLOR
* Added websocket to send events
* Added rabbitmq to send events
* Added Typebot integration
* Added proxy endpoint
* Added send and date_time in webhook data
### Fixed
* Solved problem when disconnecting from the instance the instance was deleted
* Encoded spaces in chatwoot webhook
* Adjustment in the saving of contacts, saving the information of the number and Jid
* Update Dockerfile
* If you pass empty events in create instance and set webhook it is understood as all
* Fixed issue that did not output base64 averages
* Messages sent by the api now arrive in chatwoot
### Integrations
* Chatwoot: v2.18.0 - v3.0.0
* Typebot: v2.16.0
* Manager Evolution API
# 1.4.8 (2023-07-27 10:27)
### Fixed
* Fixed error return bug
# 1.4.7 (2023-07-27 08:47)
### Fixed
* Fixed error return bug
* Fixed problem of getting message when deleting message in chatwoot
* Change in error return pattern
# 1.4.6 (2023-07-26 17:54)
### Fixed
* Fixed bug of creating new inbox by chatwoot
* When conversation reopens is pending when conversation pending is true
* Added docker-compose file with dockerhub image
# 1.4.5 (2023-07-26 09:32)
### Fixed
* Fixed problems in localization template in chatwoot
* Fix mids going duplicated in chatwoot
# 1.4.4 (2023-07-25 15:24)
### Fixed
* Fixed chatwoot line wrap issue
* Solved receive location in chatwoot
* When requesting the pairing code, it also brings the qr code
* Option reopen_conversation in chatwoot endpoint
* Option conversation_pending in chatwoot endpoint
# 1.4.3 (2023-07-25 10:51)
### Fixed
* Adjusts in settings with options always_online, read_messages and read_status
* Fixed send webhook for event CALL
* Create instance with settings
# 1.4.2 (2023-07-24 20:52)
### Fixed
* Fixed validation is set settings
* Adjusts in group validations
* Ajusts in sticker message to chatwoot
# 1.4.1 (2023-07-24 18:28)
### Fixed
* Fixed reconnect with pairing code or qrcode
* Fixed problem in createJid
# 1.4.0 (2023-07-24 17:03)
### Features
* Added connection functionality via pairing code
* Added fetch profile endpoint in chat controller
* Created settings controller
* Added reject call and send text message when receiving a call
* Added setting to ignore group messages
* Added connection with pairing code in chatwoot with command /init:{NUMBER}
* Added encoding option in endpoint sendWhatsAppAudio
### Fixed
* Added link preview option in send text message
* Fixed problem with fileSha256 appearing when sending a sticker in chatwoot
* Fixed issue where it was not possible to open a conversation when sent at first by me on my cell phone in chatwoot
* Now it only updates the contact name if it is the same as the phone number in chatwoot
* Now accepts all chatwoot inbox templates
* Command to create new instances set to /new_instance:{NAME}:{NUMBER}
* Fix in chatwoot set, sign msg can now be disabled
### Integrations
* Chatwoot: v2.18.0 - v3.0.0 (Beta)
# 1.3.2 (2023-07-21 17:19)
### Fixed
* Fix in update settings that needed to restart after updated
* Correction in the use of the api with mongodb
* Adjustments to search endpoint for contacts, chats, messages and Status messages
* Now when deleting the instance, the data referring to it in mongodb is also deleted
* It is now validated if the instance name contains uppercase and special characters
* For compatibility reasons, container mode has been removed
* Added docker-compose files example
### Integrations
* Chatwoot: v2.18.0
# 1.3.1 (2023-07-20 07:48)
### Fixed
* Adjust in create store files
### Integrations
* Chatwoot: v2.18.0
# 1.3.0 (2023-07-19 11:33)
### Features
* Added messages.delete event
* Added restart instance endpoint
* Created automation for creating instances in the chatwoot bot with the command '#inbox_whatsapp:{INSTANCE_NAME}
* Change Baileys version to: 6.4.0
* Send contact in chatwoot
* Send contact array in chatwoot
* Added apiKey in webhook and serverUrl in fetchInstance if EXPOSE_IN_FETCH_INSTANCES: true
* Translation set to default (english) in chatwoot
### Fixed
* Fixed error to send message in large groups
* Docker files adjusted
* Fixed in the postman collection the webhookByEvent parameter by webhook_by_events
* Added validations in create instance
* Removed link preview endpoint, now it's done automatically from sending conventional text
* Added group membership validation before sending message to groups
* Adjusts in docker files
* Adjusts in returns in endpoints chatwoot and webhook
* Fixed ghost mentions in send text message
* Fixed bug that saved contacts from groups came without number in chatwoot
* Fixed problem to receive csat in chatwoot
* Fixed require fileName for document only in base64 for send media message
* Bug fix when sending mobile message change contact name to number in chatwoot
* Bug fix when connecting whatsapp does not send confirmation message
* Fixed quoted message with id or message directly
* Adjust in validation for mexican and argentine numbers
* Adjust in create store files
### Integrations
* Chatwoot: v2.18.0
# 1.2.2 (2023-07-15 09:36)
### Fixed
* Tweak in route "/" with version info
* Adjusts chatwoot version
### Integrations
* Chatwoot: v2.18.0
# 1.2.1 (2023-07-14 19:04)
### Fixed
@@ -152,4 +449,4 @@
* Sending the local webhook url as destination in the webhook data for webhook redirection
* Startup modes, server or container
* Server Mode works normally as everyone is used to
* Container mode made to use one instance per container, when starting the application an instance is already created and the qrcode is generated and it starts sending webhook without having to call it manually, it only allows one instance at a time.
* Container mode made to use one instance per container, when starting the application an instance is already created and the qrcode is generated and it starts sending webhook without having to call it manually, it only allows one instance at a time.

View File

@@ -1,13 +1,16 @@
SERVER_URL='<url>' # ex.: http://localhost:3333
# Server URL - Set your application url
SERVER_URL=http://localhost:8080
CORS_ORIGIN='*' # Or separate by commas - ex.: 'yourdomain1.com, yourdomain2.com'
CORS_METHODS='POST,GET,PUT,DELETE'
# Cors - * for all or set separate by commas - ex.: 'yourdomain1.com, yourdomain2.com'
CORS_ORIGIN=*
CORS_METHODS=POST,GET,PUT,DELETE
CORS_CREDENTIALS=true
# Determine the logs to be displayed
LOG_LEVEL='ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS'
LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS
LOG_COLOR=true
LOG_BAILEYS=error # "fatal" | "error" | "warn" | "info" | "debug" | "trace"
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
LOG_BAILEYS=error
# Determine how long the instance should be deleted from memory in case of no connection.
# Default time: 5 minutes
@@ -20,7 +23,8 @@ STORE_MESSAGE_UP=true
STORE_CONTACTS=true
STORE_CHATS=true
CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds === 2h
# Set Store Interval in Seconds (7200 = 2h)
CLEAN_STORE_CLEANING_INTERVAL=7200
CLEAN_STORE_MESSAGES=true
CLEAN_STORE_MESSAGE_UP=true
CLEAN_STORE_CONTACTS=true
@@ -29,7 +33,7 @@ CLEAN_STORE_CHATS=true
# Permanent data storage
DATABASE_ENABLED=false
DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
DATABASE_CONNECTION_DB_PREFIX_NAME=evdocker
# Choose the data you want to save in the application's database or store
DATABASE_SAVE_DATA_INSTANCE=false
@@ -40,12 +44,23 @@ DATABASE_SAVE_DATA_CHATS=false
REDIS_ENABLED=false
REDIS_URI=redis://redis:6379
REDIS_PREFIX_KEY=evolution
REDIS_PREFIX_KEY=evdocker
RABBITMQ_ENABLED=false
RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672
WEBSOCKET_ENABLED=false
SQS_ENABLED=false
SQS_ACCESS_KEY_ID=
SQS_SECRET_ACCESS_KEY=
SQS_ACCOUNT_ID=
SQS_REGION=
# Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created
## Define a global webhook that will listen for enabled events from all instances
WEBHOOK_GLOBAL_URL='<url>'
WEBHOOK_GLOBAL_URL=''
WEBHOOK_GLOBAL_ENABLED=false
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
@@ -55,6 +70,7 @@ WEBHOOK_EVENTS_QRCODE_UPDATED=true
WEBHOOK_EVENTS_MESSAGES_SET=true
WEBHOOK_EVENTS_MESSAGES_UPSERT=true
WEBHOOK_EVENTS_MESSAGES_UPDATE=true
WEBHOOK_EVENTS_MESSAGES_DELETE=true
WEBHOOK_EVENTS_SEND_MESSAGE=true
WEBHOOK_EVENTS_CONTACTS_SET=true
WEBHOOK_EVENTS_CONTACTS_UPSERT=true
@@ -68,33 +84,41 @@ WEBHOOK_EVENTS_GROUPS_UPSERT=true
WEBHOOK_EVENTS_GROUPS_UPDATE=true
WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
WEBHOOK_EVENTS_CONNECTION_UPDATE=true
WEBHOOK_EVENTS_CALL=true
# This event fires every time a new token is requested via the refresh route
WEBHOOK_EVENTS_NEW_JWT_TOKEN=false
# This events is used with Typebot
WEBHOOK_EVENTS_TYPEBOT_START=false
WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS=false
# This event is used with Chama AI
WEBHOOK_EVENTS_CHAMA_AI_ACTION=false
# This event is used to send errors
WEBHOOK_EVENTS_ERRORS=false
WEBHOOK_EVENTS_ERRORS_WEBHOOK=
# Name that will be displayed on smartphone connection
CONFIG_SESSION_PHONE_CLIENT='Evolution API'
CONFIG_SESSION_PHONE_NAME=chrome # chrome | firefox | edge | opera | safari
CONFIG_SESSION_PHONE_CLIENT=EvolutionAPI
# Browser Name = Chrome | Firefox | Edge | Opera | Safari
CONFIG_SESSION_PHONE_NAME=Chrome
# Set qrcode display limit
QRCODE_LIMIT=30
QRCODE_COLOR=#198754
# old | latest
TYPEBOT_API_VERSION=latest
TYPEBOT_KEEP_OPEN=false
# Defines an authentication type for the api
# We recommend using the apikey because it will allow you to use a custom token,
# if you use jwt, a random token will be generated and may be expired and you will have to generate a new token
AUTHENTICATION_TYPE='apikey' # jwt or 'apikey'
# jwt or 'apikey'
AUTHENTICATION_TYPE=apikey
## Define a global apikey to access all instances.
### OBS: This key must be inserted in the request header to create an instance.
AUTHENTICATION_API_KEY='B6D711FCDE4D4FD5936544120E713976'
AUTHENTICATION_API_KEY=B6D711FCDE4D4FD5936544120E713976
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
## Set the secret key to encrypt and decrypt your token and its expiration time
AUTHENTICATION_JWT_EXPIRIN_IN=0 # seconds - 3600s ===1h | zero (0) - never expires
AUTHENTICATION_JWT_SECRET='L0YWtjb2w554WFqPG'
# Set the instance name and webhook url to create an instance in init the application
# With this option activated, you work with a url per webhook event, respecting the local url and the name of each event
AUTHENTICATION_INSTANCE_MODE=server # container or server
# if you are using container mode, set the container name and the webhook url to default instance
AUTHENTICATION_INSTANCE_NAME=evolution
AUTHENTICATION_INSTANCE_WEBHOOK_URL='<url>'
AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID=1
AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN=123456
AUTHENTICATION_INSTANCE_CHATWOOT_URL='<url>'
# seconds - 3600s ===1h | zero (0) - never expires
AUTHENTICATION_JWT_EXPIRIN_IN=0
AUTHENTICATION_JWT_SECRET='L=0YWt]b2w[WF>#>:&E`'

View File

@@ -0,0 +1,22 @@
version: '3.3'
services:
api:
container_name: evolution_api
image: davidsongomes/evolution-api
restart: always
ports:
- 8080:8080
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
env_file:
- .env
command: ['node', './dist/src/main.js']
expose:
- 8080
volumes:
evolution_instances:
evolution_store:

View File

@@ -0,0 +1,109 @@
# Server URL - Set your application url
SERVER_URL='http://localhost:8080'
# Cors - * for all or set separate by commas - ex.: 'yourdomain1.com, yourdomain2.com'
CORS_ORIGIN='*'
CORS_METHODS='POST,GET,PUT,DELETE'
CORS_CREDENTIALS=true
# Determine the logs to be displayed
LOG_LEVEL='ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS'
LOG_COLOR=true
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
LOG_BAILEYS=error
# Determine how long the instance should be deleted from memory in case of no connection.
# Default time: 5 minutes
# If you don't even want an expiration, enter the value false
DEL_INSTANCE=false
# Temporary data storage
STORE_MESSAGES=true
STORE_MESSAGE_UP=true
STORE_CONTACTS=true
STORE_CHATS=true
# Set Store Interval in Seconds (7200 = 2h)
CLEAN_STORE_CLEANING_INTERVAL=7200
CLEAN_STORE_MESSAGES=true
CLEAN_STORE_MESSAGE_UP=true
CLEAN_STORE_CONTACTS=true
CLEAN_STORE_CHATS=true
# Permanent data storage
DATABASE_ENABLED=true
DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
# Choose the data you want to save in the application's database or store
DATABASE_SAVE_DATA_INSTANCE=false
DATABASE_SAVE_DATA_NEW_MESSAGE=false
DATABASE_SAVE_MESSAGE_UPDATE=false
DATABASE_SAVE_DATA_CONTACTS=false
DATABASE_SAVE_DATA_CHATS=false
REDIS_ENABLED=true
REDIS_URI=redis://redis:6379
REDIS_PREFIX_KEY=evolution
# Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created
## Define a global webhook that will listen for enabled events from all instances
WEBHOOK_GLOBAL_URL=''
WEBHOOK_GLOBAL_ENABLED=false
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
## Set the events you want to hear
WEBHOOK_EVENTS_APPLICATION_STARTUP=false
WEBHOOK_EVENTS_QRCODE_UPDATED=true
WEBHOOK_EVENTS_MESSAGES_SET=true
WEBHOOK_EVENTS_MESSAGES_UPSERT=true
WEBHOOK_EVENTS_MESSAGES_UPDATE=true
WEBHOOK_EVENTS_MESSAGES_DELETE=true
WEBHOOK_EVENTS_SEND_MESSAGE=true
WEBHOOK_EVENTS_CONTACTS_SET=true
WEBHOOK_EVENTS_CONTACTS_UPSERT=true
WEBHOOK_EVENTS_CONTACTS_UPDATE=true
WEBHOOK_EVENTS_PRESENCE_UPDATE=true
WEBHOOK_EVENTS_CHATS_SET=true
WEBHOOK_EVENTS_CHATS_UPSERT=true
WEBHOOK_EVENTS_CHATS_UPDATE=true
WEBHOOK_EVENTS_CHATS_DELETE=true
WEBHOOK_EVENTS_GROUPS_UPSERT=true
WEBHOOK_EVENTS_GROUPS_UPDATE=true
WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
WEBHOOK_EVENTS_CONNECTION_UPDATE=true
# This event fires every time a new token is requested via the refresh route
WEBHOOK_EVENTS_NEW_JWT_TOKEN=false
# Name that will be displayed on smartphone connection
CONFIG_SESSION_PHONE_CLIENT='Evolution API'
# Browser Name = chrome | firefox | edge | opera | safari
CONFIG_SESSION_PHONE_NAME=chrome
# Set qrcode display limit
QRCODE_LIMIT=30
# Defines an authentication type for the api
# We recommend using the apikey because it will allow you to use a custom token,
# if you use jwt, a random token will be generated and may be expired and you will have to generate a new token
# jwt or 'apikey'
AUTHENTICATION_TYPE='apikey'
## Define a global apikey to access all instances.
### OBS: This key must be inserted in the request header to create an instance.
AUTHENTICATION_API_KEY='B6D711FCDE4D4FD5936544120E713976'
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
## Set the secret key to encrypt and decrypt your token and its expiration time
# seconds - 3600s ===1h | zero (0) - never expires
AUTHENTICATION_JWT_EXPIRIN_IN=0
AUTHENTICATION_JWT_SECRET='L0YWtjb2w554WFqPG'
# Set the instance name and webhook url to create an instance in init the application
# With this option activated, you work with a url per webhook event, respecting the local url and the name of each event
# container or server
AUTHENTICATION_INSTANCE_MODE=server
# if you are using container mode, set the container name and the webhook url to default instance
AUTHENTICATION_INSTANCE_NAME=evolution
AUTHENTICATION_INSTANCE_WEBHOOK_URL=''
AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID=1
AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN=123456
AUTHENTICATION_INSTANCE_CHATWOOT_URL=''

View File

@@ -0,0 +1,91 @@
version: '3.3'
services:
mongodb:
container_name: mongodb
image: mongo
restart: on-failure
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=root
- PUID=1000
- PGID=1000
volumes:
- evolution_mongodb_data:/data/db
- evolution_mongodb_configdb:/data/configdb
expose:
- 27017
mongo-express:
container_name: mongodb-express
image: mongo-express
restart: on-failure
ports:
- 8081:8081
depends_on:
- mongodb
environment:
ME_CONFIG_BASICAUTH_USERNAME: root
ME_CONFIG_BASICAUTH_PASSWORD: root
ME_CONFIG_MONGODB_SERVER: mongodb
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: root
links:
- mongodb
redis:
container_name: redis
image: redis:latest
restart: on-failure
ports:
- 6379:6379
command: >
redis-server
--port 6379
--appendonly yes
volumes:
- evolution_redis:/data
rebrow:
container_name: rebrow
image: marian/rebrow
restart: on-failure
depends_on:
- redis
ports:
- 5001:5001
links:
- redis
api:
container_name: evolution_api
image: davidsongomes/evolution-api
restart: always
depends_on:
- mongodb
- redis
ports:
- 8080:8080
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
env_file:
- .env
command: ['node', './dist/src/main.js']
expose:
- 8080
volumes:
evolution_mongodb_data:
evolution_mongodb_configdb:
evolution_redis:
evolution_instances:
evolution_store:
networks:
evolution-net:
external: true

View File

@@ -15,8 +15,6 @@ services:
volumes:
- evolution_mongodb_data:/data/db
- evolution_mongodb_configdb:/data/configdb
networks:
- evolution-net
expose:
- 27017
@@ -37,7 +35,8 @@ volumes:
evolution_mongodb_data:
evolution_mongodb_configdb:
networks:
default:
evolution-net:
name: evolution-net
driver: bridge

View File

@@ -5,24 +5,17 @@ services:
image: redis:latest
container_name: redis
command: >
redis-server
--port 6379
--appendonly yes
redis-server --port 6379 --appendonly yes
volumes:
- evolution_redis:/data
ports:
- 6379:6379
rebrow:
image: marian/rebrow
ports:
- 5001:5001
links:
- redis
volumes:
evolution_redis:
networks:
default:
evolution-net:
name: evolution-net
driver: bridge

View File

@@ -1,103 +1,141 @@
FROM node:16.18-alpine
FROM node:20.7.0-alpine AS builder
LABEL version="1.1.3" description="Api to control whatsapp features through http requests."
LABEL version="1.6.1" description="Api to control whatsapp features through http requests."
LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes"
LABEL contact="contato@agenciadgcode.com"
RUN apk update && apk upgrade && \
apk add --no-cache git
apk add --no-cache git tzdata ffmpeg wget curl
WORKDIR /evolution
COPY ./package.json .
ENV DOCKER_ENV=true
ENV SERVER_TYPE="http"
ENV SERVER_PORT=8080
ENV SERVER_URL=$SERVER_URL
ENV CORS_ORIGIN="*"
ENV CORS_METHODS="POST,GET,PUT,DELETE"
ENV CORS_CREDENTIALS=true
ENV LOG_LEVEL=$LOG_LEVEL
ENV LOG_COLOR=$LOG_COLOR
ENV DEL_INSTANCE=$DEL_INSTANCE
ENV STORE_MESSAGES=$STORE_MESSAGE
ENV STORE_MESSAGE_UP=$STORE_MESSAGE_UP
ENV STORE_CONTACTS=$STORE_CONTACTS
ENV STORE_CHATS=$STORE_CHATS
ENV CLEAN_STORE_CLEANING_INTERVAL=$CLEAN_STORE_CLEANING_INTERVAL
ENV CLEAN_STORE_MESSAGES=$CLEAN_STORE_MESSAGE
ENV CLEAN_STORE_MESSAGE_UP=$CLEAN_STORE_MESSAGE_UP
ENV CLEAN_STORE_CONTACTS=$CLEAN_STORE_CONTACTS
ENV CLEAN_STORE_CHATS=$CLEAN_STORE_CHATS
ENV DATABASE_ENABLED=$DATABASE_ENABLED
ENV DATABASE_CONNECTION_URI=$DATABASE_CONNECTION_URI
ENV DATABASE_CONNECTION_DB_PREFIX_NAME=$DATABASE_CONNECTION_DB_PREFIX_NAME
ENV DATABASE_SAVE_DATA_INSTANCE=$DATABASE_SAVE_DATA_INSTANCE
ENV DATABASE_SAVE_DATA_NEW_MESSAGE=$DATABASE_SAVE_DATA_NEW_MESSAGE
ENV DATABASE_SAVE_MESSAGE_UPDATE=$DATABASE_SAVE_MESSAGE_UPDATE
ENV DATABASE_SAVE_DATA_CONTACTS=$DATABASE_SAVE_DATA_CONTACTS
ENV DATABASE_SAVE_DATA_CHATS=$DATABASE_SAVE_DATA_CHATS
ENV REDIS_ENABLED=$REDIS_ENABLED
ENV REDIS_URI=$REDIS_URI
ENV REDIS_PREFIX_KEY=$REDIS_PREFIX_KEY
ENV WEBHOOK_GLOBAL_URL=$WEBHOOK_GLOBAL_URL
ENV WEBHOOK_GLOBAL_ENABLED=$WEBHOOK_GLOBAL_ENABLED
ENV WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=$WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS
ENV WEBHOOK_EVENTS_APPLICATION_STARTUP=$WEBHOOK_EVENTS_APPLICATION_STARTUP
ENV WEBHOOK_EVENTS_QRCODE_UPDATED=$WEBHOOK_EVENTS_QRCODE_UPDATED
ENV WEBHOOK_EVENTS_MESSAGES_SET=$WEBHOOK_EVENTS_MESSAGES_SET
ENV WEBHOOK_EVENTS_MESSAGES_UPSERT=$WEBHOOK_EVENTS_MESSAGES_UPSERT
ENV WEBHOOK_EVENTS_MESSAGES_UPDATE=$WEBHOOK_EVENTS_MESSAGES_UPDATE
ENV WEBHOOK_EVENTS_SEND_MESSAGE=$WEBHOOK_EVENTS_SEND_MESSAGE
ENV WEBHOOK_EVENTS_CONTACTS_SET=$WEBHOOK_EVENTS_CONTACTS_SET
ENV WEBHOOK_EVENTS_CONTACTS_UPSERT=$WEBHOOK_EVENTS_CONTACTS_UPSERT
ENV WEBHOOK_EVENTS_CONTACTS_UPDATE=$WEBHOOK_EVENTS_CONTACTS_UPDATE
ENV WEBHOOK_EVENTS_PRESENCE_UPDATE=$WEBHOOK_EVENTS_PRESENCE_UPDATE
ENV WEBHOOK_EVENTS_CHATS_SET=$WEBHOOK_EVENTS_CHATS_SET
ENV WEBHOOK_EVENTS_CHATS_UPSERT=$WEBHOOK_EVENTS_CHATS_UPSERT
ENV WEBHOOK_EVENTS_CHATS_UPDATE=$WEBHOOK_EVENTS_CHATS_UPDATE
ENV WEBHOOK_EVENTS_CONNECTION_UPDATE=$WEBHOOK_EVENTS_CONNECTION_UPDATE
ENV WEBHOOK_EVENTS_GROUPS_UPSERT=$WEBHOOK_EVENTS_GROUPS_UPSERT
ENV WEBHOOK_EVENTS_GROUPS_UPDATE=$WEBHOOK_EVENTS_GROUPS_UPDATE
ENV WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=$WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE
ENV WEBHOOK_EVENTS_NEW_JWT_TOKEN=$WEBHOOK_EVENTS_NEW_JWT_TOKEN
ENV CONFIG_SESSION_PHONE_CLIENT=$CONFIG_SESSION_PHONE_CLIENT
ENV CONFIG_SESSION_PHONE_NAME=$CONFIG_SESSION_PHONE_NAME
ENV QRCODE_LIMIT=$QRCODE_LIMIT
ENV AUTHENTICATION_TYPE=$AUTHENTICATION_TYPE
ENV AUTHENTICATION_API_KEY=$AUTHENTICATION_API_KEY
ENV AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=$AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES
ENV AUTHENTICATION_JWT_EXPIRIN_IN=$AUTHENTICATION_JWT_EXPIRIN_IN
ENV AUTHENTICATION_JWT_SECRET="L=0YWt]b2w[WF>#>:&E`"
ENV AUTHENTICATION_INSTANCE_NAME=$AUTHENTICATION_INSTANCE_NAME
ENV AUTHENTICATION_INSTANCE_WEBHOOK_URL=$AUTHENTICATION_INSTANCE_WEBHOOK_URL
ENV AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID=$AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID
ENV AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN=$AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN
ENV AUTHENTICATION_INSTANCE_CHATWOOT_URL=$AUTHENTICATION_INSTANCE_CHATWOOT_URL
ENV AUTHENTICATION_INSTANCE_MODE=$AUTHENTICATION_INSTANCE_MODE
RUN npm install
COPY . .
RUN npm run build
FROM node:20.7.0-alpine AS final
ENV TZ=America/Sao_Paulo
ENV DOCKER_ENV=true
ENV SERVER_TYPE=http
ENV SERVER_PORT=8080
ENV SERVER_URL=http://localhost:8080
ENV CORS_ORIGIN=*
ENV CORS_METHODS=POST,GET,PUT,DELETE
ENV CORS_CREDENTIALS=true
ENV LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS
ENV LOG_COLOR=true
ENV LOG_BAILEYS=error
ENV DEL_INSTANCE=false
ENV STORE_MESSAGES=true
ENV STORE_MESSAGE_UP=true
ENV STORE_CONTACTS=true
ENV STORE_CHATS=true
ENV CLEAN_STORE_CLEANING_INTERVAL=7200
ENV CLEAN_STORE_MESSAGES=true
ENV CLEAN_STORE_MESSAGE_UP=true
ENV CLEAN_STORE_CONTACTS=true
ENV CLEAN_STORE_CHATS=true
ENV DATABASE_ENABLED=false
ENV DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
ENV DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
ENV DATABASE_SAVE_DATA_INSTANCE=false
ENV DATABASE_SAVE_DATA_NEW_MESSAGE=false
ENV DATABASE_SAVE_MESSAGE_UPDATE=false
ENV DATABASE_SAVE_DATA_CONTACTS=false
ENV DATABASE_SAVE_DATA_CHATS=false
ENV REDIS_ENABLED=false
ENV REDIS_URI=redis://redis:6379
ENV REDIS_PREFIX_KEY=evolution
ENV RABBITMQ_ENABLED=false
ENV RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672
ENV WEBSOCKET_ENABLED=false
ENV SQS_ENABLED=false
ENV SQS_ACCESS_KEY_ID=
ENV SQS_SECRET_ACCESS_KEY=
ENV SQS_ACCOUNT_ID=
ENV SQS_REGION=
ENV WEBHOOK_GLOBAL_URL=
ENV WEBHOOK_GLOBAL_ENABLED=false
ENV WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
ENV WEBHOOK_EVENTS_APPLICATION_STARTUP=false
ENV WEBHOOK_EVENTS_INSTANCE_CREATE=false
ENV WEBHOOK_EVENTS_INSTANCE_DELETE=false
ENV WEBHOOK_EVENTS_QRCODE_UPDATED=true
ENV WEBHOOK_EVENTS_MESSAGES_SET=true
ENV WEBHOOK_EVENTS_MESSAGES_UPSERT=true
ENV WEBHOOK_EVENTS_MESSAGES_UPDATE=true
ENV WEBHOOK_EVENTS_MESSAGES_DELETE=true
ENV WEBHOOK_EVENTS_SEND_MESSAGE=true
ENV WEBHOOK_EVENTS_CONTACTS_SET=true
ENV WEBHOOK_EVENTS_CONTACTS_UPSERT=true
ENV WEBHOOK_EVENTS_CONTACTS_UPDATE=true
ENV WEBHOOK_EVENTS_PRESENCE_UPDATE=true
ENV WEBHOOK_EVENTS_CHATS_SET=true
ENV WEBHOOK_EVENTS_CHATS_UPSERT=true
ENV WEBHOOK_EVENTS_CHATS_UPDATE=true
ENV WEBHOOK_EVENTS_CHATS_DELETE=true
ENV WEBHOOK_EVENTS_GROUPS_UPSERT=true
ENV WEBHOOK_EVENTS_GROUPS_UPDATE=true
ENV WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
ENV WEBHOOK_EVENTS_CONNECTION_UPDATE=true
ENV WEBHOOK_EVENTS_CALL=true
ENV WEBHOOK_EVENTS_NEW_JWT_TOKEN=false
ENV WEBHOOK_EVENTS_TYPEBOT_START=false
ENV WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS=false
ENV WEBHOOK_EVENTS_CHAMA_AI_ACTION=false
ENV WEBHOOK_EVENTS_ERRORS=false
ENV WEBHOOK_EVENTS_ERRORS_WEBHOOK=
ENV CONFIG_SESSION_PHONE_CLIENT=EvolutionAPI
ENV CONFIG_SESSION_PHONE_NAME=Chrome
ENV QRCODE_LIMIT=30
ENV QRCODE_COLOR=#198754
ENV TYPEBOT_API_VERSION=latest
ENV AUTHENTICATION_TYPE=apikey
ENV AUTHENTICATION_API_KEY=B6D711FCDE4D4FD5936544120E713976
ENV AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
ENV AUTHENTICATION_JWT_EXPIRIN_IN=0
ENV AUTHENTICATION_JWT_SECRET='L=0YWt]b2w[WF>#>:&E`'
ENV AUTHENTICATION_INSTANCE_MODE=server
ENV AUTHENTICATION_INSTANCE_NAME=evolution
ENV AUTHENTICATION_INSTANCE_WEBHOOK_URL=<url>
ENV AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID=1
ENV AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN=123456
ENV AUTHENTICATION_INSTANCE_CHATWOOT_URL=<url>
WORKDIR /evolution
COPY --from=builder /evolution .
CMD [ "node", "./dist/src/main.js" ]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,241 @@
{
"name": "[Evolution] Configurar Admin",
"nodes": [
{
"parameters": {
"values": {
"string": [
{
"name": "api_access_token",
"value": "CHATWOOT_ADMIN_USER_TOKEN"
},
{
"name": "chatwoot_url",
"value": "https://CHATWOOT_URL"
},
{
"name": "n8n_url",
"value": "https://N8N_URL"
},
{
"name": "organization",
"value": "ORGANIZATION_NAME"
},
{
"name": "logo",
"value": "ORGANIZATION_LOGO"
}
]
},
"options": {}
},
"id": "7a89a538-2cae-4032-8896-09627c07bc68",
"name": "Info Base",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
620,
480
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/1/contacts/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"inbox_id\": {{ $('Cria Inbox Start').item.json[\"id\"] }},\n \"name\": \"Bot {{ $('Info Base').item.json[\"organization\"] }}\",\n \"phone_number\": \"+123456\",\n \"avatar_url\": \"{{ $('Info Base').item.json[\"logo\"] }}\"\n}",
"options": {}
},
"id": "12a39df3-6b95-4f83-a0bc-50b25adaca7f",
"name": "Cria Contato Bot",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1020,
480
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/1/inboxes/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"Start {{ $('Info Base').item.json[\"organization\"] }}\",\n \"channel\": {\n \"type\": \"api\",\n \"website_url\": \"\"\n }\n}",
"options": {}
},
"id": "bed7c54d-e232-4fe4-9584-0515e9679868",
"name": "Cria Inbox Start",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
820,
480
]
},
{
"parameters": {},
"id": "36ada769-a757-4193-989b-0cc4ea504b80",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
420,
480
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/1/automation_rules/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"Create Company Chatwoot\",\n \"description\": \"Create Company Chatwoot\",\n \"event_name\": \"message_created\",\n \"active\": true,\n \"actions\": \n [\n {\n \"action_name\": \"send_webhook_event\",\n \"action_params\": [\"{{ $('Info Base').item.json[\"n8n_url\"] }}/webhook/criadorchatwoot\"]\n }\n ],\n \"conditions\": \n [\n {\n \"attribute_key\": \"content\",\n \"filter_operator\": \"contains\",\n \"query_operator\": \"and\",\n \"values\": [\"Tema Criador de Empresa:\"]\n },\n {\n \"attribute_key\": \"phone_number\",\n \"filter_operator\": \"equal_to\",\n \"values\": [\"+123456\"]\n }\n ]\n}",
"options": {}
},
"id": "f5bbb285-71a8-4c58-a4d7-e56002d697f0",
"name": "Cria Automação Empresas",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1220,
480
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/1/automation_rules/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"Create Inbox {{ $('Info Base').item.json[\"organization\"] }}\",\n \"description\": \"Create Inbox {{ $('Info Base').item.json[\"organization\"] }}\",\n \"event_name\": \"message_created\",\n \"active\": true,\n \"actions\": \n [\n {\n \"action_name\": \"send_webhook_event\",\n \"action_params\": [\"{{ $('Info Base').item.json[\"n8n_url\"] }}/webhook/inbox_whatsapp?utoken={{ $('Info Base').item.json[\"api_access_token\"] }}&organization={{ $('Info Base').item.json[\"organization\"] }}\"]\n }\n ],\n \"conditions\": \n [\n {\n \"attribute_key\": \"content\",\n \"filter_operator\": \"contains\",\n \"query_operator\": \"and\",\n \"values\": [\"start:\"]\n },\n \n {\n \"attribute_key\": \"phone_number\",\n \"filter_operator\": \"equal_to\",\n \"query_operator\": \"or\",\n \"values\": [\"+123456\"]\n },\n\n\n {\n \"attribute_key\": \"content\",\n \"filter_operator\": \"contains\",\n \"query_operator\": \"and\",\n \"values\": [\"new_instance:\"]\n },\n {\n \"attribute_key\": \"phone_number\",\n \"filter_operator\": \"equal_to\",\n \"values\": [\"+123456\"]\n }\n ]\n}",
"options": {}
},
"id": "a36bebdc-a318-40a2-8532-c7f476f8adb7",
"name": "Cria Automação Inboxes",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1420,
480
]
},
{
"parameters": {
"content": "## Workflow Para Configurar admin\n**Aqui você prepara o Chatwoot Principal com um usuário (Superadmin) que poderá criar empresas e caixas de entrada**\n**Instruções**\n**No node Info Base, configure as variáveis de seu Chatwoot e N8N**\n**Obs: A variável api_access_token é o token do usuário que irá poder criar as empresas**",
"width": 894.6435495898575
},
"id": "db66e867-e9f4-452d-b521-725eeac652c8",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
420,
280
]
}
],
"pinData": {},
"connections": {
"Info Base": {
"main": [
[
{
"node": "Cria Inbox Start",
"type": "main",
"index": 0
}
]
]
},
"Cria Contato Bot": {
"main": [
[
{
"node": "Cria Automação Empresas",
"type": "main",
"index": 0
}
]
]
},
"Cria Inbox Start": {
"main": [
[
{
"node": "Cria Contato Bot",
"type": "main",
"index": 0
}
]
]
},
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Info Base",
"type": "main",
"index": 0
}
]
]
},
"Cria Automação Empresas": {
"main": [
[
{
"node": "Cria Automação Inboxes",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "78f155dc-7809-4bfc-9282-63f49b07fc4d",
"id": "BSATyGpGWLR4ZwNm",
"meta": {
"instanceId": "4ff16e963c7f5197d7e99e6239192860914312fea0ce2a9a7fd14d74a0a0e906"
},
"tags": []
}

View File

@@ -0,0 +1,456 @@
{
"name": "[Evolution] Criador de Empresas",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "criadorchatwoot",
"options": {}
},
"id": "5a47c10a-e43c-4fa5-baad-4b6cc511bfcd",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
1420,
860
],
"webhookId": "6fe428e3-1752-453c-9358-abf18b793387"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/platform/api/v1/accounts",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "name",
"value": "={{ $json.name_company }}"
},
{
"name": "locale",
"value": "pt_BR"
}
]
},
"options": {}
},
"id": "8295c119-3a96-424e-9386-43d75f6816f5",
"name": "Cria Conta",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2020,
860
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/platform/api/v1/users",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "name",
"value": "={{ $('Info Base').item.json.name_admin }}"
},
{
"name": "email",
"value": "={{ $('Info Base').item.json[\"email\"] }}"
},
{
"name": "password",
"value": "={{ $('Info Base').item.json[\"password\"] }}"
}
]
},
"options": {}
},
"id": "4fe5007a-3a6b-490a-a446-e45cc168189f",
"name": "Cria Usuario",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2220,
860
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/platform/api/v1/accounts/{{ $node[\"Cria Conta\"].json[\"id\"] }}/account_users",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json[\"api_access_token\"] }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "user_id",
"value": "={{ $node[\"Cria Usuario\"].json[\"id\"] }}"
},
{
"name": "role",
"value": "administrator"
}
]
},
"options": {}
},
"id": "848c55e2-5678-4291-9602-c94d994da95b",
"name": "Add Usuario a Conta",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2420,
860
]
},
{
"parameters": {
"fromEmail": "={{ $('Info Base').item.json[\"from_email\"] }}",
"toEmail": "={{ $('LimpaDados').item.json.email }}",
"subject": "=Bem vindo à {{ $('Info Base').item.json[\"organization\"] }}",
"text": "=Olá seja bem vindo:\n\nAbaixo segue seus dados de acesso:\n\nURL: {{ $('Info Base').item.json[\"chatwoot_url\"] }}\n\nuser: {{ $('LimpaDados').item.json[\"email\"] }}\n\nSenha: {{ $('LimpaDados').item.json[\"password\"] }}",
"options": {}
},
"id": "27f3b24f-1cf2-4d0d-a354-ecba066059f6",
"name": "Send Email",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
3220,
860
],
"credentials": {
"smtp": {
"id": "6BxluEUV8zrXKoVG",
"name": "[Dgcode] SMTP"
}
}
},
{
"parameters": {
"values": {
"string": [
{
"name": "api_access_token",
"value": "CHATWOOT_PLATFORM_TOKEN"
},
{
"name": "chatwoot_url",
"value": "https://CHATWOOT_URL"
},
{
"name": "n8n_url",
"value": "https://N8N_URL"
},
{
"name": "organization",
"value": "ORGANIZATION_NAME"
},
{
"name": "logo",
"value": "ORGANIZATION_LOGO"
},
{
"name": "from_email",
"value": "FROM_EMAIL"
},
{
"name": "name",
"value": "={{ $json.name_company }}"
},
{
"name": "email",
"value": "={{ $json.email }}"
},
{
"name": "password",
"value": "={{ $json.password }}"
},
{
"name": "name_company",
"value": "={{ $json.name_company }}"
}
]
},
"options": {}
},
"id": "38b4069d-e51e-4db7-933f-941b1be6d124",
"name": "Info Base",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
1820,
860
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "name_admin",
"value": "={{$node[\"Webhook\"].json[\"body\"][\"messages\"][0][\"content\"].match(/Nome Usuario Administrador: ([^\\n]+)/)[1];}}"
},
{
"name": "name_company",
"value": "={{$node[\"Webhook\"].json[\"body\"][\"messages\"][0][\"content\"].match(/Nome da Empresa: ([^\\n]+)/)[1];}}"
},
{
"name": "email",
"value": "={{$node[\"Webhook\"].json[\"body\"][\"messages\"][0][\"content\"].match(/Email: ([^\\s]+)/)[1];}}"
},
{
"name": "password",
"value": "={{$node[\"Webhook\"].json[\"body\"][\"messages\"][0][\"content\"].match(/Senha: ([^\\s]+)/)[1];}}"
}
]
},
"options": {}
},
"id": "28e29e73-aadc-49ca-bd6d-b57ee0160a21",
"name": "LimpaDados",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
1620,
860
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $('Add Usuario a Conta').item.json.account_id }}/contacts/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Cria Usuario').item.json.access_token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"inbox_id\": {{ $('Cria Inbox Start').item.json[\"id\"] }},\n \"name\": \"Bot {{ $('Info Base').item.json[\"organization\"] }}\",\n \"phone_number\": \"+123456\",\n \"avatar_url\": \"{{ $('Info Base').item.json[\"logo\"] }}\"\n}",
"options": {}
},
"id": "bb671443-bdb4-4f56-99af-f0baef246a3e",
"name": "Cria Contato Bot",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2820,
860
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $('Add Usuario a Conta').item.json.account_id }}/automation_rules/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Cria Usuario').item.json.access_token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"Create Inbox {{ $('Info Base').item.json[\"organization\"] }}\",\n \"description\": \"Create Inbox {{ $('Info Base').item.json[\"organization\"] }}\",\n \"event_name\": \"message_created\",\n \"active\": true,\n \"actions\": \n [\n {\n \"action_name\": \"send_webhook_event\",\n \"action_params\": [\"{{ $('Info Base').item.json[\"n8n_url\"] }}/webhook/inbox_whatsapp?utoken={{ $('Cria Usuario').item.json.access_token }}&organization={{ $('Info Base').item.json[\"organization\"] }}\"]\n }\n ],\n \"conditions\": \n [\n {\n \"attribute_key\": \"content\",\n \"filter_operator\": \"contains\",\n \"query_operator\": \"and\",\n \"values\": [\"start:\"]\n },\n {\n \"attribute_key\": \"phone_number\",\n \"filter_operator\": \"equal_to\",\n \"query_operator\": \"or\",\n \"values\": [\"+123456\"]\n },\n {\n \"attribute_key\": \"content\",\n \"filter_operator\": \"contains\",\n \"query_operator\": \"and\",\n \"values\": [\"new_instance:\"]\n },\n {\n \"attribute_key\": \"phone_number\",\n \"filter_operator\": \"equal_to\",\n \"values\": [\"+123456\"]\n }\n ]\n}",
"options": {}
},
"id": "e016a2af-b212-4e00-a3ff-8cd03530aa06",
"name": "Cria Automação",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
3020,
860
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $json.account_id }}/inboxes/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Cria Usuario').item.json.access_token }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"Start {{ $('Info Base').item.json[\"organization\"] }}\",\n \"channel\": {\n \"type\": \"api\",\n \"website_url\": \"\"\n }\n}",
"options": {}
},
"id": "d3c42148-8920-4c98-a874-eb7113f2dd22",
"name": "Cria Inbox Start",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2620,
860
]
},
{
"parameters": {
"content": "## Workflow Criador de Empresas\n**Cria Contas (Empresas) e Usuários através de tema**\n**Instruções**\n**No node Info Base, configure as variáveis de seu Chatwoot e N8N**\n**Obs: A variável api_access_token é o token PlatformApp encontrado no acesso ao Super Admin**\n**Tema para criar novas empresa:**\n\nTema Criador de Empresa:\n\nNome Usuario Administrador: Joao Linhares\nNome da Empresa: Oficina Linhates\nEmail: machineteste24@gmail.com\nSenha: Mfcd62!!",
"height": 304.02684563758396,
"width": 1129.7777777777778
},
"id": "d07516c0-4c8e-43ab-ba86-c8d063b09be5",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1420,
520
]
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "LimpaDados",
"type": "main",
"index": 0
}
]
]
},
"Cria Conta": {
"main": [
[
{
"node": "Cria Usuario",
"type": "main",
"index": 0
}
]
]
},
"Cria Usuario": {
"main": [
[
{
"node": "Add Usuario a Conta",
"type": "main",
"index": 0
}
]
]
},
"Add Usuario a Conta": {
"main": [
[
{
"node": "Cria Inbox Start",
"type": "main",
"index": 0
}
]
]
},
"Info Base": {
"main": [
[
{
"node": "Cria Conta",
"type": "main",
"index": 0
}
]
]
},
"LimpaDados": {
"main": [
[
{
"node": "Info Base",
"type": "main",
"index": 0
}
]
]
},
"Cria Contato Bot": {
"main": [
[
{
"node": "Cria Automação",
"type": "main",
"index": 0
}
]
]
},
"Cria Automação": {
"main": [
[
{
"node": "Send Email",
"type": "main",
"index": 0
}
]
]
},
"Cria Inbox Start": {
"main": [
[
{
"node": "Cria Contato Bot",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {},
"versionId": "3ffd6d3f-6966-4de4-af8f-1fda464bc1b8",
"id": "79R6qQDtfyCwgYjJ",
"meta": {
"instanceId": "4ff16e963c7f5197d7e99e6239192860914312fea0ce2a9a7fd14d74a0a0e906"
},
"tags": []
}

View File

@@ -0,0 +1,510 @@
{
"name": "[Evolution] Criador de Inbox",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "inbox_whatsapp",
"options": {}
},
"id": "8205b929-73e9-456a-9b0d-e1474991663a",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
320,
300
],
"webhookId": "cf37002d-3869-4bb1-af3a-739fdd3c1756"
},
{
"parameters": {
"method": "POST",
"url": "={{ $json.evolution_url }}/instance/create",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "apikey",
"value": "={{ $json.global_api_key }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "instanceName",
"value": "={{ $json.instance_name }}"
},
{
"name": "qrcode",
"value": "={{ $json.qrcode }}"
},
{
"name": "chatwoot_account_id",
"value": "={{ $json.chatwoot_account_id }}"
},
{
"name": "chatwoot_token",
"value": "={{ $json.chatwoot_token }}"
},
{
"name": "chatwoot_url",
"value": "={{ $json.chatwoot_url }}"
},
{
"name": "chatwoot_sign_msg",
"value": "={{ $json.chatwoot_sign_msg }}"
},
{
"name": "chatwoot_reopen_conversation",
"value": "={{ $json.chatwoot_reopen_conversation }}"
},
{
"name": "chatwoot_conversation_pending",
"value": "={{ $json.chatwoot_conversation_pending }}"
},
{
"name": "reject_call",
"value": "={{ $json.reject_call }}"
},
{
"name": "msg_call",
"value": "={{ $json.msg_call }}"
},
{
"name": "groups_ignore",
"value": "={{ $json.groups_ignore }}"
},
{
"name": "always_online",
"value": "={{ $json.always_online }}"
},
{
"name": "read_messages",
"value": "={{ $json.read_messages }}"
},
{
"name": "read_status",
"value": "={{ $json.read_status }}"
}
]
},
"options": {}
},
"id": "275aa370-2fdb-42f4-844a-2fb3051301bd",
"name": "Cria Instancia",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
760,
300
]
},
{
"parameters": {
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $('Info Base').item.json[\"chatwoot_account_id\"] }}/inboxes/",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json.chatwoot_token }}"
}
]
},
"options": {}
},
"id": "e4650812-ba0a-4f72-8bd8-a235eca4b2de",
"name": "Lista Inboxes",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
980,
300
]
},
{
"parameters": {
"content": "## Workflow Para Criar Inbox\n**Aqui você configura a comunicação entre o chatwoot e a Evolution API para criar novas instâncias a partir do chatwoot**\n**Instruções**\n**No node Info Base, configure as variáveis de seu Chatwoot e Evolution API**",
"width": 1129.7777777777778
},
"id": "aa763d9e-d973-44fc-8399-277bb24718a5",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
320,
80
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "chatwoot_url",
"value": "CHATWOOT_URL"
},
{
"name": "evolution_url",
"value": "EVOLUTION_URL"
},
{
"name": "global_api_key",
"value": "EVOLUTION_GLOBAL_API_KEY"
},
{
"name": "organization",
"value": "={{ $json.query.organization }}"
},
{
"name": "instance_name",
"value": "={{ $json.body.messages[0].content.split(':')[1] }}-cwId-{{ $json.body.messages[0].account_id }}"
},
{
"name": "chatwoot_token",
"value": "={{ $json.query.utoken }}"
},
{
"name": "msg_call",
"value": "Não aceitamos chamadas, por favor deixe uma mensagem!"
}
],
"boolean": [
{
"name": "qrcode",
"value": true
},
{
"name": "chatwoot_sign_msg",
"value": true
},
{
"name": "chatwoot_reopen_conversation",
"value": true
},
{
"name": "chatwoot_conversation_pending"
},
{
"name": "reject_call",
"value": true
},
{
"name": "groups_ignore"
},
{
"name": "always_online",
"value": true
},
{
"name": "read_messages",
"value": true
},
{
"name": "read_status"
}
],
"number": [
{
"name": "chatwoot_account_id",
"value": "={{ $json.body.messages[0].account_id }}"
}
]
},
"options": {}
},
"id": "297df325-ecc4-4a34-817c-092d16d5753b",
"name": "Info Base",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
540,
300
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.name }}",
"value2": "=Start {{ $('Info Base').item.json[\"organization\"] }}"
}
]
}
},
"id": "a8d955e6-ac51-4316-aeec-09d4d65e943a",
"name": "é Start Inbox?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1660,
200
]
},
{
"parameters": {
"batchSize": 1,
"options": {}
},
"id": "0d2d2194-aa4a-4241-9022-217d88bb581f",
"name": "Split In Batches",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 2,
"position": [
1420,
300
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.name }}",
"value2": "={{ $('Webhook').item.json[\"body\"][\"messages\"][0][\"content\"].split(':')[1] }}"
}
]
}
},
"id": "0bfbc2cb-eff5-423c-bd3a-b266aaf6a943",
"name": "é_pre-existente?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1900,
340
]
},
{
"parameters": {
"method": "PATCH",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $('Info Base').item.json[\"chatwoot_account_id\"] }}/inboxes/{{ $json.id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json.chatwoot_token }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n\"channel\": {\n\"webhook_url\": \"{{ $('Info Base').item.json[\"evolution_url\"] }}/chatwoot/webhook/{{ encodeURIComponent($('Info Base').item.json[\"instance_name\"]) }}\"\n}\n}",
"options": {}
},
"id": "fb589456-5566-4a45-96a7-75986d0aa1d5",
"name": "Update_webhook_url",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
2120,
340
]
},
{
"parameters": {
"method": "DELETE",
"url": "={{ $('Info Base').item.json[\"chatwoot_url\"] }}/api/v1/accounts/{{ $('Info Base').item.json[\"chatwoot_account_id\"] }}/inboxes/{{ $json.id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Info Base').item.json.chatwoot_token }}"
}
]
},
"options": {}
},
"id": "e6094941-410f-496c-9c9c-7b95fd9349af",
"name": "Deleta Inbox Start",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 3,
"position": [
1900,
100
]
},
{
"parameters": {},
"id": "8cf9a78f-9e8a-4288-9d7b-801790af68d5",
"name": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
1660,
400
]
},
{
"parameters": {
"fieldToSplitOut": "payload",
"options": {}
},
"id": "9468896a-5f86-4598-9d20-e8f495cae859",
"name": "Ajusta lista",
"type": "n8n-nodes-base.itemLists",
"typeVersion": 2.2,
"position": [
1200,
300
]
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Info Base",
"type": "main",
"index": 0
}
]
]
},
"Lista Inboxes": {
"main": [
[
{
"node": "Ajusta lista",
"type": "main",
"index": 0
}
]
]
},
"Cria Instancia": {
"main": [
[
{
"node": "Lista Inboxes",
"type": "main",
"index": 0
}
]
]
},
"Info Base": {
"main": [
[
{
"node": "Cria Instancia",
"type": "main",
"index": 0
}
]
]
},
"é Start Inbox?": {
"main": [
[
{
"node": "Deleta Inbox Start",
"type": "main",
"index": 0
}
],
[
{
"node": "é_pre-existente?",
"type": "main",
"index": 0
}
]
]
},
"Split In Batches": {
"main": [
[
{
"node": "é Start Inbox?",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"é_pre-existente?": {
"main": [
[
{
"node": "Update_webhook_url",
"type": "main",
"index": 0
}
],
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Update_webhook_url": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Deleta Inbox Start": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Ajusta lista": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {},
"versionId": "ab910349-b559-4738-9ac6-de6b06d6bbce",
"id": "ByW2ccjR4XPrOyio",
"meta": {
"instanceId": "4ff16e963c7f5197d7e99e6239192860914312fea0ce2a9a7fd14d74a0a0e906"
},
"tags": []
}

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,8 @@
[![Postman Collection](https://img.shields.io/badge/Postman-Collection-orange)](https://evolution-api.com/postman)
[![Documentation](https://img.shields.io/badge/Documentation-Official-green)](https://doc.evolution-api.com)
[![License](https://img.shields.io/badge/license-GPL--3.0-orange)](./LICENSE)
[![Support](https://img.shields.io/badge/Buy%20me-coffe-orange)](https://app.picpay.com/user/davidsongomes1998)
[![Support](https://img.shields.io/badge/Donation-picpay-green)](https://app.picpay.com/user/davidsongomes1998)
[![Support](https://img.shields.io/badge/Buy%20me-coffe-orange)](https://bmc.link/evolutionapi)
</div>
@@ -34,8 +35,17 @@ This code was produced based on the baileys library and it is still under develo
<div align="center">
<a href="https://app.picpay.com/user/davidsongomes1998" target="_blank" rel="noopener noreferrer">
<img src="./public/images/picpay-image.png" style="width: 50% !important;">
<img src="./public/images/picpay-qr.jpeg" style="width: 50% !important;">
</a>
</div>
#### Buy me coffe - PIX
<div align="center">
<a href="https://bmc.link/evolutionapi" target="_blank" rel="noopener noreferrer">
<img src="./public/images/qrcode-pix.png" style="width: 50% !important;">
</a>
<p><b>CHAVE PIX (Telefone):</b> (74)99987-9409</p>
</div>
</br>

View File

@@ -4,12 +4,15 @@ services:
api:
container_name: evolution_api
image: evolution/api:local
build: .
restart: always
ports:
- 8080:8080
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
networks:
- evolution-net
env_file:
- ./Docker/.env
command: ['node', './dist/src/main.js']
@@ -21,6 +24,6 @@ volumes:
evolution_store:
networks:
default:
evolution-net:
name: evolution-net
driver: bridge

View File

@@ -1,36 +1,47 @@
version: '3.3'
services:
redis:
image: redis:latest
container_name: redis
api:
container_name: evolution_api
image: evolution/api:local
build: .
restart: always
ports:
- 6379:6379
rebrow:
image: marian/rebrow
ports:
- 5001:5001
links:
- redis
- 8080:8080
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
networks:
- evolution-net
env_file:
- ./Docker/.env
command: ['node', './dist/src/main.js']
expose:
- 8080
mongodb:
container_name: mongodb
image: mongo
restart: always
volumes:
- evolution_mongodb_data:/data/db
- evolution_mongodb_configdb:/data/configdb
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=root
- PUID=1000
- PGID=1000
volumes:
- evolution_mongodb_data:/data/db
- evolution_mongodb_configdb:/data/configdb
networks:
- evolution-net
expose:
- 27017
mongo-express:
image: mongo-express
networks:
- evolution-net
environment:
ME_CONFIG_BASICAUTH_USERNAME: root
ME_CONFIG_BASICAUTH_PASSWORD: root
@@ -41,23 +52,20 @@ services:
- 8081:8081
links:
- mongodb
api:
container_name: evolution_api
image: evolution/api:local
restart: always
ports:
- 8080:8080
redis:
image: redis:latest
container_name: redis
command: >
redis-server
--port 6379
--appendonly yes
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
env_file:
- ./Docker/.env
command: ['node', './dist/src/main.js']
expose:
- 8080
links:
- mongodb
- redis
- evolution_redis:/data
networks:
- evolution-net
ports:
- 6379:6379
volumes:
evolution_instances:
@@ -67,6 +75,6 @@ volumes:
evolution_redis:
networks:
default:
evolution-net:
name: evolution-net
driver: bridge

View File

@@ -0,0 +1,28 @@
version: '3.3'
services:
api:
container_name: evolution_api
image: atendai/evolution-api:latest
restart: always
ports:
- 8080:8080
volumes:
- evolution_instances:/evolution/instances
- evolution_store:/evolution/store
networks:
- evolution-net
env_file:
- ./Docker/.env
command: ['node', './dist/src/main.js']
expose:
- 8080
volumes:
evolution_instances:
evolution_store:
networks:
evolution-net:
name: evolution-net
driver: bridge

View File

@@ -1,13 +0,0 @@
#!/bin/bash
NET='evolution-net'
IMAGE='evolution/api:local'
if !(docker network ls | grep ${NET} > /dev/null)
then
docker network create -d bridge ${NET}
fi
docker build -t ${IMAGE} .
docker compose up -d

View File

@@ -1,6 +1,6 @@
{
"name": "evolution-api",
"version": "1.2.1",
"version": "1.6.1",
"description": "Rest api for communication with WhatsApp",
"main": "./dist/src/main.js",
"scripts": {
@@ -8,7 +8,8 @@
"start": "ts-node --files --transpile-only ./src/main.ts",
"start:prod": "bash start.sh",
"dev:server": "clear && tsnd --files --transpile-only --respawn --ignore-watch node_modules ./src/main.ts",
"test": "clear && tsnd --files --transpile-only --respawn --ignore-watch node_modules ./test/all.test.ts"
"test": "clear && tsnd --files --transpile-only --respawn --ignore-watch node_modules ./test/all.test.ts",
"lint": "eslint --fix --ext .ts src"
},
"repository": {
"type": "git",
@@ -42,9 +43,12 @@
"dependencies": {
"@adiwajshing/keyed-db": "^0.2.4",
"@ffmpeg-installer/ffmpeg": "^1.1.0",
"@figuro/chatwoot-sdk": "^1.1.16",
"@hapi/boom": "^10.0.1",
"@whiskeysockets/baileys": "github:DavidsonGomes/Baileys",
"@figuro/chatwoot-sdk": "^1.1.14",
"@sentry/node": "^7.59.2",
"@whiskeysockets/baileys": "github:PurpShell/Baileys#combined",
"amqplib": "^0.10.3",
"aws-sdk": "^2.1499.0",
"axios": "^1.3.5",
"class-validator": "^0.13.2",
"compression": "^1.7.4",
@@ -52,6 +56,7 @@
"cross-env": "^7.0.3",
"dayjs": "^1.11.7",
"eventemitter2": "^6.4.9",
"evolution-manager": "^0.4.11",
"exiftool-vendored": "^22.0.0",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
@@ -61,17 +66,23 @@
"js-yaml": "^4.1.0",
"jsonschema": "^1.4.1",
"jsonwebtoken": "^8.5.1",
"libphonenumber-js": "^1.10.39",
"link-preview-js": "^3.0.4",
"mongoose": "^6.10.5",
"node-cache": "^5.1.2",
"node-mime-types": "^1.1.0",
"node-windows": "^1.0.0-beta.8",
"pino": "^8.11.0",
"proxy-agent": "^6.2.1",
"proxy-agent": "^6.3.0",
"qrcode": "^1.5.1",
"qrcode-terminal": "^0.12.0",
"redis": "^4.6.5",
"sharp": "^0.30.7",
"uuid": "^9.0.0"
"socket.io": "^4.7.1",
"socks-proxy-agent": "^8.0.1",
"swagger-ui-express": "^5.0.0",
"uuid": "^9.0.0",
"yamljs": "^0.3.0"
},
"devDependencies": {
"@types/compression": "^1.7.2",
@@ -79,16 +90,20 @@
"@types/express": "^4.17.17",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.9",
"@types/mime-types": "^2.1.1",
"@types/node": "^18.15.11",
"@types/node-windows": "^0.1.2",
"@types/qrcode": "^1.5.0",
"@types/qrcode-terminal": "^0.12.0",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"eslint": "^8.38.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.45.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.7",
"eslint-plugin-simple-import-sort": "^10.0.0",
"prettier": "^2.8.8",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.5"
}

BIN
public/images/bmc_qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,10 +1,15 @@
import { isBooleanString } from 'class-validator';
import { readFileSync } from 'fs';
import { load } from 'js-yaml';
import { join } from 'path';
import { SRC_DIR } from './path.config';
import { isBooleanString } from 'class-validator';
export type HttpServer = { TYPE: 'http' | 'https'; PORT: number; URL: string };
export type HttpServer = {
TYPE: 'http' | 'https';
PORT: number;
URL: string;
DISABLE_DOCS: boolean;
DISABLE_MANAGER: boolean;
};
export type HttpMethods = 'POST' | 'GET' | 'PUT' | 'DELETE';
export type Cors = {
@@ -15,15 +20,7 @@ export type Cors = {
export type LogBaileys = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
export type LogLevel =
| 'ERROR'
| 'WARN'
| 'DEBUG'
| 'INFO'
| 'LOG'
| 'VERBOSE'
| 'DARK'
| 'WEBHOOKS';
export type LogLevel = 'ERROR' | 'WARN' | 'DEBUG' | 'INFO' | 'LOG' | 'VERBOSE' | 'DARK' | 'WEBHOOKS';
export type Log = {
LEVEL: LogLevel[];
@@ -70,12 +67,32 @@ export type Redis = {
PREFIX_KEY: string;
};
export type Rabbitmq = {
ENABLED: boolean;
URI: string;
};
export type Sqs = {
ENABLED: boolean;
ACCESS_KEY_ID: string;
SECRET_ACCESS_KEY: string;
ACCOUNT_ID: string;
REGION: string;
};
export type Websocket = {
ENABLED: boolean;
};
export type EventsWebhook = {
APPLICATION_STARTUP: boolean;
INSTANCE_CREATE: boolean;
INSTANCE_DELETE: boolean;
QRCODE_UPDATED: boolean;
MESSAGES_SET: boolean;
MESSAGES_UPSERT: boolean;
MESSAGES_UPDATE: boolean;
MESSAGES_DELETE: boolean;
SEND_MESSAGE: boolean;
CONTACTS_SET: boolean;
CONTACTS_UPDATE: boolean;
@@ -89,25 +106,23 @@ export type EventsWebhook = {
GROUPS_UPSERT: boolean;
GROUP_UPDATE: boolean;
GROUP_PARTICIPANTS_UPDATE: boolean;
CALL: boolean;
NEW_JWT_TOKEN: boolean;
TYPEBOT_START: boolean;
TYPEBOT_CHANGE_STATUS: boolean;
CHAMA_AI_ACTION: boolean;
ERRORS: boolean;
ERRORS_WEBHOOK: string;
};
export type ApiKey = { KEY: string };
export type Jwt = { EXPIRIN_IN: number; SECRET: string };
export type Instance = {
NAME: string;
WEBHOOK_URL: string;
MODE: string;
CHATWOOT_ACCOUNT_ID?: string;
CHATWOOT_TOKEN?: string;
CHATWOOT_URL?: string;
};
export type Auth = {
API_KEY: ApiKey;
EXPOSE_IN_FETCH_INSTANCES: boolean;
JWT: Jwt;
TYPE: 'jwt' | 'apikey';
INSTANCE: Instance;
};
export type DelInstance = number | boolean;
@@ -120,7 +135,8 @@ export type GlobalWebhook = {
export type SslConf = { PRIVKEY: string; FULLCHAIN: string };
export type Webhook = { GLOBAL?: GlobalWebhook; EVENTS: EventsWebhook };
export type ConfigSessionPhone = { CLIENT: string; NAME: string };
export type QrCode = { LIMIT: number };
export type QrCode = { LIMIT: number; COLOR: string };
export type Typebot = { API_VERSION: string; KEEP_OPEN: boolean };
export type Production = boolean;
export interface Env {
@@ -131,11 +147,15 @@ export interface Env {
CLEAN_STORE: CleanStoreConf;
DATABASE: Database;
REDIS: Redis;
RABBITMQ: Rabbitmq;
SQS: Sqs;
WEBSOCKET: Websocket;
LOG: Log;
DEL_INSTANCE: DelInstance;
WEBHOOK: Webhook;
CONFIG_SESSION_PHONE: ConfigSessionPhone;
QRCODE: QrCode;
TYPEBOT: Typebot;
AUTHENTICATION: Auth;
PRODUCTION?: Production;
}
@@ -157,32 +177,32 @@ export class ConfigService {
this.env = !(process.env?.DOCKER_ENV === 'true') ? this.envYaml() : this.envProcess();
this.env.PRODUCTION = process.env?.NODE_ENV === 'PROD';
if (process.env?.DOCKER_ENV === 'true') {
this.env.SERVER.TYPE = 'http';
this.env.SERVER.PORT = 8080;
this.env.SERVER.TYPE = process.env.SERVER_TYPE as 'http' | 'http';
this.env.SERVER.PORT = Number.parseInt(process.env.SERVER_PORT) || 8080;
}
}
private envYaml(): Env {
return load(
readFileSync(join(process.cwd(), 'src', 'env.yml'), { encoding: 'utf-8' }),
) as Env;
return load(readFileSync(join(process.cwd(), 'src', 'env.yml'), { encoding: 'utf-8' })) as Env;
}
private envProcess(): Env {
return {
SERVER: {
TYPE: process.env.SERVER_TYPE as 'http' | 'https',
PORT: Number.parseInt(process.env.SERVER_PORT),
TYPE: (process.env.SERVER_TYPE as 'http' | 'https') || 'http',
PORT: Number.parseInt(process.env.SERVER_PORT) || 8080,
URL: process.env.SERVER_URL,
DISABLE_DOCS: process.env?.SERVER_DISABLE_DOCS === 'true',
DISABLE_MANAGER: process.env?.SERVER_DISABLE_MANAGER === 'true',
},
CORS: {
ORIGIN: process.env.CORS_ORIGIN.split(','),
METHODS: process.env.CORS_METHODS.split(',') as HttpMethods[],
ORIGIN: process.env.CORS_ORIGIN.split(',') || ['*'],
METHODS: (process.env.CORS_METHODS.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'],
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
},
SSL_CONF: {
PRIVKEY: process.env?.SSL_CONF_PRIVKEY,
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN,
PRIVKEY: process.env?.SSL_CONF_PRIVKEY || '',
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN || '',
},
STORE: {
MESSAGES: process.env?.STORE_MESSAGES === 'true',
@@ -193,7 +213,7 @@ export class ConfigService {
CLEAN_STORE: {
CLEANING_INTERVAL: Number.isInteger(process.env?.CLEAN_STORE_CLEANING_TERMINAL)
? Number.parseInt(process.env.CLEAN_STORE_CLEANING_TERMINAL)
: undefined,
: 7200,
MESSAGES: process.env?.CLEAN_STORE_MESSAGES === 'true',
MESSAGE_UP: process.env?.CLEAN_STORE_MESSAGE_UP === 'true',
CONTACTS: process.env?.CLEAN_STORE_CONTACTS === 'true',
@@ -201,8 +221,8 @@ export class ConfigService {
},
DATABASE: {
CONNECTION: {
URI: process.env.DATABASE_CONNECTION_URI,
DB_PREFIX_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_NAME,
URI: process.env.DATABASE_CONNECTION_URI || '',
DB_PREFIX_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_NAME || 'evolution',
},
ENABLED: process.env?.DATABASE_ENABLED === 'true',
SAVE_DATA: {
@@ -215,29 +235,55 @@ export class ConfigService {
},
REDIS: {
ENABLED: process.env?.REDIS_ENABLED === 'true',
URI: process.env.REDIS_URI,
PREFIX_KEY: process.env.REDIS_PREFIX_KEY,
URI: process.env.REDIS_URI || '',
PREFIX_KEY: process.env.REDIS_PREFIX_KEY || 'evolution',
},
RABBITMQ: {
ENABLED: process.env?.RABBITMQ_ENABLED === 'true',
URI: process.env.RABBITMQ_URI || '',
},
SQS: {
ENABLED: process.env?.SQS_ENABLED === 'true',
ACCESS_KEY_ID: process.env.SQS_ACCESS_KEY_ID || '',
SECRET_ACCESS_KEY: process.env.SQS_SECRET_ACCESS_KEY || '',
ACCOUNT_ID: process.env.SQS_ACCOUNT_ID || '',
REGION: process.env.SQS_REGION || '',
},
WEBSOCKET: {
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
},
LOG: {
LEVEL: process.env?.LOG_LEVEL.split(',') as LogLevel[],
LEVEL: (process.env?.LOG_LEVEL.split(',') as LogLevel[]) || [
'ERROR',
'WARN',
'DEBUG',
'INFO',
'LOG',
'VERBOSE',
'DARK',
'WEBHOOKS',
],
COLOR: process.env?.LOG_COLOR === 'true',
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
},
DEL_INSTANCE: isBooleanString(process.env?.DEL_INSTANCE)
? process.env.DEL_INSTANCE === 'true'
: Number.parseInt(process.env.DEL_INSTANCE),
: Number.parseInt(process.env.DEL_INSTANCE) || false,
WEBHOOK: {
GLOBAL: {
URL: process.env?.WEBHOOK_GLOBAL_URL,
URL: process.env?.WEBHOOK_GLOBAL_URL || '',
ENABLED: process.env?.WEBHOOK_GLOBAL_ENABLED === 'true',
WEBHOOK_BY_EVENTS: process.env?.WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS === 'true',
},
EVENTS: {
APPLICATION_STARTUP: process.env?.WEBHOOK_EVENTS_APPLICATION_STARTUP === 'true',
INSTANCE_CREATE: process.env?.WEBHOOK_EVENTS_INSTANCE_CREATE === 'true',
INSTANCE_DELETE: process.env?.WEBHOOK_EVENTS_INSTANCE_DELETE === 'true',
QRCODE_UPDATED: process.env?.WEBHOOK_EVENTS_QRCODE_UPDATED === 'true',
MESSAGES_SET: process.env?.WEBHOOK_EVENTS_MESSAGES_SET === 'true',
MESSAGES_UPSERT: process.env?.WEBHOOK_EVENTS_MESSAGES_UPSERT === 'true',
MESSAGES_UPDATE: process.env?.WEBHOOK_EVENTS_MESSAGES_UPDATE === 'true',
MESSAGES_DELETE: process.env?.WEBHOOK_EVENTS_MESSAGES_DELETE === 'true',
SEND_MESSAGE: process.env?.WEBHOOK_EVENTS_SEND_MESSAGE === 'true',
CONTACTS_SET: process.env?.WEBHOOK_EVENTS_CONTACTS_SET === 'true',
CONTACTS_UPDATE: process.env?.WEBHOOK_EVENTS_CONTACTS_UPDATE === 'true',
@@ -250,39 +296,39 @@ export class ConfigService {
CONNECTION_UPDATE: process.env?.WEBHOOK_EVENTS_CONNECTION_UPDATE === 'true',
GROUPS_UPSERT: process.env?.WEBHOOK_EVENTS_GROUPS_UPSERT === 'true',
GROUP_UPDATE: process.env?.WEBHOOK_EVENTS_GROUPS_UPDATE === 'true',
GROUP_PARTICIPANTS_UPDATE:
process.env?.WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE === 'true',
GROUP_PARTICIPANTS_UPDATE: process.env?.WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE === 'true',
CALL: process.env?.WEBHOOK_EVENTS_CALL === 'true',
NEW_JWT_TOKEN: process.env?.WEBHOOK_EVENTS_NEW_JWT_TOKEN === 'true',
TYPEBOT_START: process.env?.WEBHOOK_EVENTS_TYPEBOT_START === 'true',
TYPEBOT_CHANGE_STATUS: process.env?.WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS === 'true',
CHAMA_AI_ACTION: process.env?.WEBHOOK_EVENTS_CHAMA_AI_ACTION === 'true',
ERRORS: process.env?.WEBHOOK_EVENTS_ERRORS === 'true',
ERRORS_WEBHOOK: process.env?.WEBHOOK_EVENTS_ERRORS_WEBHOOK || '',
},
},
CONFIG_SESSION_PHONE: {
CLIENT: process.env?.CONFIG_SESSION_PHONE_CLIENT,
NAME: process.env?.CONFIG_SESSION_PHONE_NAME,
CLIENT: process.env?.CONFIG_SESSION_PHONE_CLIENT || 'Evolution API',
NAME: process.env?.CONFIG_SESSION_PHONE_NAME || 'Chrome',
},
QRCODE: {
LIMIT: Number.parseInt(process.env.QRCODE_LIMIT),
LIMIT: Number.parseInt(process.env.QRCODE_LIMIT) || 30,
COLOR: process.env.QRCODE_COLOR || '#198754',
},
TYPEBOT: {
API_VERSION: process.env?.TYPEBOT_API_VERSION || 'old',
KEEP_OPEN: process.env.TYPEBOT_KEEP_OPEN === 'true',
},
AUTHENTICATION: {
TYPE: process.env.AUTHENTICATION_TYPE as 'jwt',
TYPE: process.env.AUTHENTICATION_TYPE as 'apikey',
API_KEY: {
KEY: process.env.AUTHENTICATION_API_KEY,
KEY: process.env.AUTHENTICATION_API_KEY || 'BQYHJGJHJ',
},
EXPOSE_IN_FETCH_INSTANCES:
process.env?.AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES === 'true',
EXPOSE_IN_FETCH_INSTANCES: process.env?.AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES === 'true',
JWT: {
EXPIRIN_IN: Number.isInteger(process.env?.AUTHENTICATION_JWT_EXPIRIN_IN)
? Number.parseInt(process.env.AUTHENTICATION_JWT_EXPIRIN_IN)
: 3600,
SECRET: process.env.AUTHENTICATION_JWT_SECRET,
},
INSTANCE: {
NAME: process.env.AUTHENTICATION_INSTANCE_NAME,
WEBHOOK_URL: process.env.AUTHENTICATION_INSTANCE_WEBHOOK_URL,
MODE: process.env.AUTHENTICATION_INSTANCE_MODE,
CHATWOOT_ACCOUNT_ID:
process.env.AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID || '',
CHATWOOT_TOKEN: process.env.AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN || '',
CHATWOOT_URL: process.env.AUTHENTICATION_INSTANCE_CHATWOOT_URL || '',
SECRET: process.env.AUTHENTICATION_JWT_SECRET || 'L=0YWt]b2w[WF>#>:&E`',
},
},
};

View File

@@ -1,5 +1,8 @@
import { configService, Log } from './env.config';
import dayjs from 'dayjs';
import fs from 'fs';
import { configService, Log } from './env.config';
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
const formatDateLog = (timestamp: number) =>
dayjs(timestamp)
@@ -73,6 +76,8 @@ export class Logger {
/*Command.UNDERSCORE +*/ Command.BRIGHT + Level[type],
'[Evolution API]',
Command.BRIGHT + Color[type],
`v${packageJson.version}`,
Command.BRIGHT + Color[type],
process.pid.toString(),
Command.RESET,
Command.BRIGHT + Color[type],

View File

@@ -9,6 +9,9 @@ SERVER:
TYPE: http # https
PORT: 8080 # 443
URL: localhost
DISABLE_MANAGER: false
DISABLE_DOCS: false
CORS:
ORIGIN:
@@ -39,7 +42,7 @@ LOG:
- DARK
- WEBHOOKS
COLOR: true
BAILEYS: error # "fatal" | "error" | "warn" | "info" | "debug" | "trace"
BAILEYS: error # fatal | error | warn | info | debug | trace
# Determine how long the instance should be deleted from memory in case of no connection.
# Default time: 5 minutes
@@ -79,6 +82,20 @@ REDIS:
URI: "redis://localhost:6379"
PREFIX_KEY: "evolution"
RABBITMQ:
ENABLED: false
URI: "amqp://guest:guest@localhost:5672"
SQS:
ENABLED: true
ACCESS_KEY_ID: ""
SECRET_ACCESS_KEY: ""
ACCOUNT_ID: ""
REGION: "us-east-1"
WEBSOCKET:
ENABLED: false
# Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created
WEBHOOK:
@@ -96,6 +113,7 @@ WEBHOOK:
MESSAGES_SET: true
MESSAGES_UPSERT: true
MESSAGES_UPDATE: true
MESSAGES_DELETE: true
SEND_MESSAGE: true
CONTACTS_SET: true
CONTACTS_UPSERT: true
@@ -109,17 +127,31 @@ WEBHOOK:
GROUP_UPDATE: true
GROUP_PARTICIPANTS_UPDATE: true
CONNECTION_UPDATE: true
CALL: true
# This event fires every time a new token is requested via the refresh route
NEW_JWT_TOKEN: false
# This events is used with Typebot
TYPEBOT_START: false
TYPEBOT_CHANGE_STATUS: false
# This event is used with Chama AI
CHAMA_AI_ACTION: false
# This event is used to send errors to the webhook
ERRORS: false
ERRORS_WEBHOOK: <url>
CONFIG_SESSION_PHONE:
# Name that will be displayed on smartphone connection
CLIENT: "Evolution API"
NAME: chrome # chrome | firefox | edge | opera | safari
NAME: Chrome # Chrome | Firefox | Edge | Opera | Safari
# Set qrcode display limit
QRCODE:
LIMIT: 30
COLOR: "#198754"
TYPEBOT:
API_VERSION: 'old' # old | latest
KEEP_OPEN: false
# Defines an authentication type for the api
# We recommend using the apikey because it will allow you to use a custom token,
@@ -136,13 +168,3 @@ AUTHENTICATION:
JWT:
EXPIRIN_IN: 0 # seconds - 3600s === 1h | zero (0) - never expires
SECRET: L=0YWt]b2w[WF>#>:&E`
# Set the instance name and webhook url to create an instance in init the application
INSTANCE:
# With this option activated, you work with a url per webhook event, respecting the local url and the name of each event
MODE: server # container or server
# if you are using container mode, set the container name and the webhook url to default instance
NAME: evolution
WEBHOOK_URL: <url>
CHATWOOT_ACCOUNT_ID: 1
CHATWOOT_TOKEN: 123456
CHATWOOT_URL: <url>

17
src/docs/swagger.conf.ts Normal file
View File

@@ -0,0 +1,17 @@
import { Router } from 'express';
import { join } from 'path';
import swaggerUi from 'swagger-ui-express';
import YAML from 'yamljs';
const document = YAML.load(join(process.cwd(), 'src', 'docs', 'swagger.yaml'));
const router = Router();
export const swaggerRouter = router.use('/docs', swaggerUi.serve).get(
'/docs',
swaggerUi.setup(document, {
customCssUrl: '/css/dark-theme-swagger.css',
customSiteTitle: 'Evolution API',
customfavIcon: '/images/logo.svg',
}),
);

2597
src/docs/swagger.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ export class UnauthorizedException {
throw {
status: HttpStatus.UNAUTHORIZED,
error: 'Unauthorized',
message: objectError.length > 0 ? objectError : undefined,
message: objectError.length > 0 ? objectError : 'Unauthorized',
};
}
}

100
src/libs/amqp.server.ts Normal file
View File

@@ -0,0 +1,100 @@
import * as amqp from 'amqplib/callback_api';
import { configService, Rabbitmq } from '../config/env.config';
import { Logger } from '../config/logger.config';
const logger = new Logger('AMQP');
let amqpChannel: amqp.Channel | null = null;
export const initAMQP = () => {
return new Promise<void>((resolve, reject) => {
const uri = configService.get<Rabbitmq>('RABBITMQ').URI;
amqp.connect(uri, (error, connection) => {
if (error) {
reject(error);
return;
}
connection.createChannel((channelError, channel) => {
if (channelError) {
reject(channelError);
return;
}
const exchangeName = 'evolution_exchange';
channel.assertExchange(exchangeName, 'topic', {
durable: true,
autoDelete: false,
});
amqpChannel = channel;
logger.info('AMQP initialized');
resolve();
});
});
});
};
export const getAMQP = (): amqp.Channel | null => {
return amqpChannel;
};
export const initQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
const queues = events.map((event) => {
return `${event.replace(/_/g, '.').toLowerCase()}`;
});
queues.forEach((event) => {
const amqp = getAMQP();
const exchangeName = instanceName ?? 'evolution_exchange';
amqp.assertExchange(exchangeName, 'topic', {
durable: true,
autoDelete: false,
});
const queueName = `${instanceName}.${event}`;
amqp.assertQueue(queueName, {
durable: true,
autoDelete: false,
arguments: {
'x-queue-type': 'quorum',
},
});
amqp.bindQueue(queueName, exchangeName, event);
});
};
export const removeQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
const channel = getAMQP();
const queues = events.map((event) => {
return `${event.replace(/_/g, '.').toLowerCase()}`;
});
const exchangeName = instanceName ?? 'evolution_exchange';
queues.forEach((event) => {
const amqp = getAMQP();
amqp.assertExchange(exchangeName, 'topic', {
durable: true,
autoDelete: false,
});
const queueName = `${instanceName}.${event}`;
amqp.deleteQueue(queueName);
});
channel.deleteExchange(exchangeName);
};

View File

@@ -1,4 +1,5 @@
import mongoose from 'mongoose';
import { configService, Database } from '../config/env.config';
import { Logger } from '../config/logger.config';

View File

@@ -1,48 +1,59 @@
import { createClient, RedisClientType } from '@redis/client';
import { Logger } from '../config/logger.config';
import { BufferJSON } from '@whiskeysockets/baileys';
import { Redis } from '../config/env.config';
import { Logger } from '../config/logger.config';
export class RedisCache {
constructor() {
this.logger.verbose('instance created');
process.on('beforeExit', async () => {
this.logger.verbose('instance destroyed');
if (this.statusConnection) {
this.logger.verbose('instance disconnect');
await this.client.disconnect();
}
});
}
private readonly logger = new Logger(RedisCache.name);
private client: RedisClientType;
private statusConnection = false;
private instanceName: string;
private redisEnv: Redis;
constructor() {
this.logger.verbose('RedisCache instance created');
process.on('beforeExit', () => {
this.logger.verbose('RedisCache instance destroyed');
this.disconnect();
});
}
public set reference(reference: string) {
this.logger.verbose('set reference: ' + reference);
this.instanceName = reference;
}
public async connect(redisEnv: Redis) {
this.logger.verbose('connecting');
this.logger.verbose('Connecting to Redis...');
this.client = createClient({ url: redisEnv.URI });
this.logger.verbose('connected in ' + redisEnv.URI);
this.client.on('error', (err) => this.logger.error('Redis Client Error ' + err));
await this.client.connect();
this.statusConnection = true;
this.redisEnv = redisEnv;
this.logger.verbose(`Connected to ${redisEnv.URI}`);
}
private readonly logger = new Logger(RedisCache.name);
private client: RedisClientType;
public async disconnect() {
if (this.statusConnection) {
await this.client.disconnect();
this.statusConnection = false;
this.logger.verbose('Redis client disconnected');
}
}
public async instanceKeys(): Promise<string[]> {
const keys: string[] = [];
try {
this.logger.verbose('instance keys: ' + this.redisEnv.PREFIX_KEY + ':*');
return await this.client.sendCommand(['keys', this.redisEnv.PREFIX_KEY + ':*']);
this.logger.verbose('Fetching instance keys');
for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) {
keys.push(key);
}
} catch (error) {
this.logger.error(error);
this.logger.error('Error fetching instance keys ' + error);
}
return keys;
}
public async keyExists(key?: string) {
@@ -59,11 +70,7 @@ export class RedisCache {
this.logger.verbose('writeData: ' + field);
const json = JSON.stringify(data, BufferJSON.replacer);
return await this.client.hSet(
this.redisEnv.PREFIX_KEY + ':' + this.instanceName,
field,
json,
);
return await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json);
} catch (error) {
this.logger.error(error);
}
@@ -72,10 +79,7 @@ export class RedisCache {
public async readData(field: string) {
try {
this.logger.verbose('readData: ' + field);
const data = await this.client.hGet(
this.redisEnv.PREFIX_KEY + ':' + this.instanceName,
field,
);
const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
if (data) {
this.logger.verbose('readData: ' + field + ' success');
@@ -92,10 +96,7 @@ export class RedisCache {
public async removeData(field: string) {
try {
this.logger.verbose('removeData: ' + field);
return await this.client.hDel(
this.redisEnv.PREFIX_KEY + ':' + this.instanceName,
field,
);
return await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field);
} catch (error) {
this.logger.error(error);
}
@@ -104,9 +105,7 @@ export class RedisCache {
public async delAll(hash?: string) {
try {
this.logger.verbose('instance delAll: ' + hash);
const result = await this.client.del(
hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName,
);
const result = await this.client.del(hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName);
return result;
} catch (error) {

44
src/libs/socket.server.ts Normal file
View File

@@ -0,0 +1,44 @@
import { Server } from 'http';
import { Server as SocketIO } from 'socket.io';
import { configService, Cors, Websocket } from '../config/env.config';
import { Logger } from '../config/logger.config';
const logger = new Logger('Socket');
let io: SocketIO;
const cors = configService.get<Cors>('CORS').ORIGIN;
export const initIO = (httpServer: Server) => {
if (configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
io = new SocketIO(httpServer, {
cors: {
origin: cors,
},
});
io.on('connection', (socket) => {
logger.info('User connected');
socket.on('disconnect', () => {
logger.info('User disconnected');
});
});
logger.info('Socket.io initialized');
return io;
}
return null;
};
export const getIO = (): SocketIO => {
logger.verbose('Getting Socket.io');
if (!io) {
logger.error('Socket.io not initialized');
throw new Error('Socket.io not initialized');
}
return io;
};

97
src/libs/sqs.server.ts Normal file
View File

@@ -0,0 +1,97 @@
import { SQS } from 'aws-sdk';
import { configService, Sqs } from '../config/env.config';
import { Logger } from '../config/logger.config';
const logger = new Logger('SQS');
let sqs: SQS;
export const initSQS = () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return new Promise<void>((resolve, reject) => {
const awsConfig = configService.get<Sqs>('SQS');
sqs = new SQS({
accessKeyId: awsConfig.ACCESS_KEY_ID,
secretAccessKey: awsConfig.SECRET_ACCESS_KEY,
region: awsConfig.REGION,
});
logger.info('SQS initialized');
resolve();
});
};
export const getSQS = (): SQS => {
return sqs;
};
export const initQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
const queues = events.map((event) => {
return `${event.replace(/_/g, '_').toLowerCase()}`;
});
const sqs = getSQS();
queues.forEach((event) => {
const queueName = `${instanceName}_${event}.fifo`;
sqs.createQueue(
{
QueueName: queueName,
Attributes: {
FifoQueue: 'true',
},
},
(err, data) => {
if (err) {
logger.error(`Error creating queue ${queueName}: ${err.message}`);
} else {
logger.info(`Queue ${queueName} created: ${data.QueueUrl}`);
}
},
);
});
};
export const removeQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
const sqs = getSQS();
const queues = events.map((event) => {
return `${event.replace(/_/g, '_').toLowerCase()}`;
});
queues.forEach((event) => {
const queueName = `${instanceName}_${event}.fifo`;
sqs.getQueueUrl(
{
QueueName: queueName,
},
(err, data) => {
if (err) {
logger.error(`Error getting queue URL for ${queueName}: ${err.message}`);
} else {
const queueUrl = data.QueueUrl;
sqs.deleteQueue(
{
QueueUrl: queueUrl,
},
(deleteErr) => {
if (deleteErr) {
logger.error(`Error deleting queue ${queueName}: ${deleteErr.message}`);
} else {
logger.info(`Queue ${queueName} deleted`);
}
},
);
}
},
);
});
};

View File

@@ -1,15 +1,22 @@
import 'express-async-errors';
import axios from 'axios';
import compression from 'compression';
import { configService, Cors, HttpServer } from './config/env.config';
import cors from 'cors';
import express, { json, NextFunction, Request, Response, urlencoded } from 'express';
import { join } from 'path';
import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config';
import { onUnexpectedError } from './config/error.config';
import { Logger } from './config/logger.config';
import { ROOT_DIR } from './config/path.config';
import { waMonitor } from './whatsapp/whatsapp.module';
import { HttpStatus, router } from './whatsapp/routers/index.router';
import 'express-async-errors';
import { swaggerRouter } from './docs/swagger.conf';
import { initAMQP } from './libs/amqp.server';
import { initIO } from './libs/socket.server';
import { initSQS } from './libs/sqs.server';
import { ServerUP } from './utils/server-up';
import { HttpStatus, router } from './whatsapp/routers/index.router';
import { waMonitor } from './whatsapp/whatsapp.module';
function initWA() {
waMonitor.loadInstance();
@@ -23,7 +30,9 @@ function bootstrap() {
cors({
origin(requestOrigin, callback) {
const { ORIGIN } = configService.get<Cors>('CORS');
!requestOrigin ? (requestOrigin = '*') : undefined;
if (ORIGIN.includes('*')) {
return callback(null, true);
}
if (ORIGIN.indexOf(requestOrigin) !== -1) {
return callback(null, true);
}
@@ -41,21 +50,67 @@ function bootstrap() {
app.set('views', join(ROOT_DIR, 'views'));
app.use(express.static(join(ROOT_DIR, 'public')));
app.use('/store', express.static(join(ROOT_DIR, 'store')));
app.use('/', router);
if (!configService.get('SERVER').DISABLE_DOCS) app.use(swaggerRouter);
app.use(
(err: Error, req: Request, res: Response, next: NextFunction) => {
if (err) {
return res.status(err['status'] || 500).json(err);
const webhook = configService.get<Webhook>('WEBHOOK');
if (webhook.EVENTS.ERRORS_WEBHOOK && webhook.EVENTS.ERRORS_WEBHOOK != '' && webhook.EVENTS.ERRORS) {
const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
const localISOTime = new Date(Date.now() - tzoffset).toISOString();
const now = localISOTime;
const globalApiKey = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
const serverUrl = configService.get<HttpServer>('SERVER').URL;
const errorData = {
event: 'error',
data: {
error: err['error'] || 'Internal Server Error',
message: err['message'] || 'Internal Server Error',
status: err['status'] || 500,
response: {
message: err['message'] || 'Internal Server Error',
},
},
date_time: now,
api_key: globalApiKey,
server_url: serverUrl,
};
logger.error(errorData);
const baseURL = webhook.EVENTS.ERRORS_WEBHOOK;
const httpService = axios.create({ baseURL });
httpService.post('', errorData);
}
return res.status(err['status'] || 500).json({
status: err['status'] || 500,
error: err['error'] || 'Internal Server Error',
response: {
message: err['message'] || 'Internal Server Error',
},
});
}
next();
},
(req: Request, res: Response, next: NextFunction) => {
const { method, url } = req;
res.status(HttpStatus.NOT_FOUND).json({
status: HttpStatus.NOT_FOUND,
message: `Cannot ${method.toUpperCase()} ${url}`,
error: 'Not Found',
response: {
message: [`Cannot ${method.toUpperCase()} ${url}`],
},
});
next();
@@ -67,12 +122,16 @@ function bootstrap() {
ServerUP.app = app;
const server = ServerUP[httpServer.TYPE];
server.listen(httpServer.PORT, () =>
logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT),
);
server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT));
initWA();
initIO(server);
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
if (configService.get<Sqs>('SQS')?.ENABLED) initSQS();
onUnexpectedError();
}

View File

@@ -1,8 +1,9 @@
import { Express } from 'express';
import { readFileSync } from 'fs';
import { configService, SslConf } from '../config/env.config';
import * as https from 'https';
import * as http from 'http';
import * as https from 'https';
import { configService, SslConf } from '../config/env.config';
export class ServerUP {
static #app: Express;

View File

@@ -6,9 +6,10 @@ import {
proto,
SignalDataTypeMap,
} from '@whiskeysockets/baileys';
import { configService, Database } from '../config/env.config';
import { Logger } from '../config/logger.config';
import { dbserver } from '../db/db.connect';
import { dbserver } from '../libs/db.connect';
export async function useMultiFileAuthStateDb(
coll: string,
@@ -24,28 +25,42 @@ export async function useMultiFileAuthStateDb(
const writeData = async (data: any, key: string): Promise<any> => {
try {
await client.connect();
return await collection.replaceOne(
{ _id: key },
JSON.parse(JSON.stringify(data, BufferJSON.replacer)),
{ upsert: true },
);
} catch {}
let msgParsed = JSON.parse(JSON.stringify(data, BufferJSON.replacer));
if (Array.isArray(msgParsed)) {
msgParsed = {
_id: key,
content_array: msgParsed,
};
}
return await collection.replaceOne({ _id: key }, msgParsed, {
upsert: true,
});
} catch (error) {
logger.error(error);
}
};
const readData = async (key: string): Promise<any> => {
try {
await client.connect();
const data = await collection.findOne({ _id: key });
let data = (await collection.findOne({ _id: key })) as any;
if (data?.content_array) {
data = data.content_array;
}
const creds = JSON.stringify(data);
return JSON.parse(creds, BufferJSON.reviver);
} catch {}
} catch (error) {
logger.error(error);
}
};
const removeData = async (key: string) => {
try {
await client.connect();
return await collection.deleteOne({ _id: key });
} catch {}
} catch (error) {
logger.error(error);
}
};
const creds: AuthenticationCreds = (await readData('creds')) || initAuthCreds();
@@ -86,7 +101,7 @@ export async function useMultiFileAuthStateDb(
},
},
saveCreds: async () => {
return writeData(creds, 'creds');
return await writeData(creds, 'creds');
},
};
}

View File

@@ -5,9 +5,9 @@ import {
proto,
SignalDataTypeMap,
} from '@whiskeysockets/baileys';
import { RedisCache } from '../db/redis.client';
import { Logger } from '../config/logger.config';
import { Redis } from '../config/env.config';
import { RedisCache } from '../libs/redis.client';
export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{
state: AuthenticationState;

View File

@@ -39,6 +39,7 @@ export const instanceNameSchema: JSONSchema7 = {
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
@@ -52,11 +53,16 @@ export const instanceNameSchema: JSONSchema7 = {
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},
qrcode: { type: 'boolean', enum: [true, false] },
number: { type: 'string', pattern: '^\\d+[\\.@\\w-]+' },
token: { type: 'string' },
},
...isNotEmpty('instanceName'),
@@ -81,8 +87,8 @@ const quotedOptionsSchema: JSONSchema7 = {
remoteJid: { type: 'string' },
fromMe: { type: 'boolean', enum: [true, false] },
},
required: ['id', 'remoteJid', 'fromMe'],
...isNotEmpty('id', 'remoteJid'),
required: ['id'],
...isNotEmpty('id'),
},
message: { type: 'object' },
},
@@ -122,7 +128,6 @@ const optionsSchema: JSONSchema7 = {
const numberDefinition: JSONSchema7Definition = {
type: 'string',
pattern: '^\\d+[\\.@\\w-]+',
description: 'Invalid format',
};
@@ -144,22 +149,14 @@ export const textMessageSchema: JSONSchema7 = {
required: ['textMessage', 'number'],
};
export const linkPreviewSchema: JSONSchema7 = {
export const presenceSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
number: { ...numberDefinition },
options: { ...optionsSchema },
linkPreview: {
type: 'object',
properties: {
text: { type: 'string' },
},
required: ['text'],
...isNotEmpty('text'),
},
options: { ...optionsSchema, required: ['presence', 'delay'] },
},
required: ['linkPreview', 'number'],
required: ['options', 'number'],
};
export const pollMessageSchema: JSONSchema7 = {
@@ -415,7 +412,7 @@ export const contactMessageSchema: JSONSchema7 = {
email: { type: 'string' },
url: { type: 'string' },
},
required: ['fullName', 'wuid', 'phoneNumber'],
required: ['fullName', 'phoneNumber'],
...isNotEmpty('fullName'),
},
minItems: 1,
@@ -462,7 +459,6 @@ export const whatsappNumberSchema: JSONSchema7 = {
uniqueItems: true,
items: {
type: 'string',
pattern: '^\\d+',
description: '"numbers" must be an array of numeric strings',
},
},
@@ -473,7 +469,7 @@ export const readMessageSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
readMessages: {
read_messages: {
type: 'array',
minItems: 1,
uniqueItems: true,
@@ -488,7 +484,7 @@ export const readMessageSchema: JSONSchema7 = {
},
},
},
required: ['readMessages'],
required: ['read_messages'],
};
export const privacySettingsSchema: JSONSchema7 = {
@@ -525,6 +521,7 @@ export const archiveChatSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
chat: { type: 'string' },
lastMessage: {
type: 'object',
properties: {
@@ -545,7 +542,7 @@ export const archiveChatSchema: JSONSchema7 = {
},
archive: { type: 'boolean', enum: [true, false] },
},
required: ['lastMessage', 'archive'],
required: ['archive'],
};
export const deleteMessageSchema: JSONSchema7 = {
@@ -604,6 +601,17 @@ export const profilePictureSchema: JSONSchema7 = {
},
};
export const profileSchema: JSONSchema7 = {
type: 'object',
properties: {
wuid: { type: 'string' },
name: { type: 'string' },
picture: { type: 'string' },
status: { type: 'string' },
isBusiness: { type: 'boolean' },
},
};
export const messageValidateSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
@@ -674,6 +682,7 @@ export const createGroupSchema: JSONSchema7 = {
subject: { type: 'string' },
description: { type: 'string' },
profilePicture: { type: 'string' },
promoteParticipants: { type: 'boolean', enum: [true, false] },
participants: {
type: 'array',
minItems: 1,
@@ -828,13 +837,11 @@ export const updateGroupDescriptionSchema: JSONSchema7 = {
...isNotEmpty('groupJid', 'description'),
};
// Webhook Schema
export const webhookSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
url: { type: 'string' },
enabled: { type: 'boolean', enum: [true, false] },
events: {
type: 'array',
minItems: 0,
@@ -846,6 +853,7 @@ export const webhookSchema: JSONSchema7 = {
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
@@ -859,12 +867,16 @@ export const webhookSchema: JSONSchema7 = {
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},
},
required: ['url', 'enabled'],
required: ['url'],
...isNotEmpty('url'),
};
@@ -877,7 +889,219 @@ export const chatwootSchema: JSONSchema7 = {
token: { type: 'string' },
url: { type: 'string' },
sign_msg: { type: 'boolean', enum: [true, false] },
sign_delimiter: { type: ['string', 'null'] },
reopen_conversation: { type: 'boolean', enum: [true, false] },
conversation_pending: { type: 'boolean', enum: [true, false] },
auto_create: { type: 'boolean', enum: [true, false] },
},
required: ['enabled', 'account_id', 'token', 'url', 'sign_msg'],
...isNotEmpty('account_id', 'token', 'url', 'sign_msg'),
required: ['enabled', 'account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'],
...isNotEmpty('account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'),
};
export const settingsSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
reject_call: { type: 'boolean', enum: [true, false] },
msg_call: { type: 'string' },
groups_ignore: { type: 'boolean', enum: [true, false] },
always_online: { type: 'boolean', enum: [true, false] },
read_messages: { type: 'boolean', enum: [true, false] },
read_status: { type: 'boolean', enum: [true, false] },
},
required: ['reject_call', 'groups_ignore', 'always_online', 'read_messages', 'read_status'],
...isNotEmpty('reject_call', 'groups_ignore', 'always_online', 'read_messages', 'read_status'),
};
export const websocketSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
events: {
type: 'array',
minItems: 0,
items: {
type: 'string',
enum: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},
},
required: ['enabled'],
...isNotEmpty('enabled'),
};
export const rabbitmqSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
events: {
type: 'array',
minItems: 0,
items: {
type: 'string',
enum: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},
},
required: ['enabled'],
...isNotEmpty('enabled'),
};
export const sqsSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
events: {
type: 'array',
minItems: 0,
items: {
type: 'string',
enum: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
],
},
},
},
required: ['enabled'],
...isNotEmpty('enabled'),
};
export const typebotSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
url: { type: 'string' },
typebot: { type: 'string' },
expire: { type: 'integer' },
delay_message: { type: 'integer' },
unknown_message: { type: 'string' },
listening_from_me: { type: 'boolean', enum: [true, false] },
},
required: ['enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'],
...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'),
};
export const typebotStatusSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
remoteJid: { type: 'string' },
status: { type: 'string', enum: ['opened', 'closed', 'paused'] },
},
required: ['remoteJid', 'status'],
...isNotEmpty('remoteJid', 'status'),
};
export const typebotStartSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
remoteJid: { type: 'string' },
url: { type: 'string' },
typebot: { type: 'string' },
},
required: ['remoteJid', 'url', 'typebot'],
...isNotEmpty('remoteJid', 'url', 'typebot'),
};
export const proxySchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
proxy: { type: 'string' },
},
required: ['enabled', 'proxy'],
...isNotEmpty('enabled', 'proxy'),
};
export const chamaaiSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
url: { type: 'string' },
token: { type: 'string' },
waNumber: { type: 'string' },
answerByAudio: { type: 'boolean', enum: [true, false] },
},
required: ['enabled', 'url', 'token', 'waNumber', 'answerByAudio'],
...isNotEmpty('enabled', 'url', 'token', 'waNumber', 'answerByAudio'),
};

View File

@@ -1,5 +1,6 @@
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, Database } from '../../config/env.config';
import { ROOT_DIR } from '../../config/path.config';
@@ -34,11 +35,9 @@ export abstract class Repository implements IRepository {
mkdirSync(create.path, { recursive: true });
}
try {
writeFileSync(
join(create.path, create.fileName + '.json'),
JSON.stringify({ ...create.data }),
{ encoding: 'utf-8' },
);
writeFileSync(join(create.path, create.fileName + '.json'), JSON.stringify({ ...create.data }), {
encoding: 'utf-8',
});
return { message: 'create - success' };
} finally {
@@ -46,19 +45,23 @@ export abstract class Repository implements IRepository {
}
};
public insert(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
// eslint-disable-next-line
public insert(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
throw new Error('Method not implemented.');
}
public update(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
// eslint-disable-next-line
public update(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
throw new Error('Method not implemented.');
}
public find(query: any): Promise<any> {
// eslint-disable-next-line
public find(query: any): Promise<any> {
throw new Error('Method not implemented.');
}
delete(query: any, force?: boolean): Promise<any> {
// eslint-disable-next-line
delete(query: any, force?: boolean): Promise<any> {
throw new Error('Method not implemented.');
}
}

View File

@@ -1,11 +1,13 @@
import { InstanceDto } from '../dto/instance.dto';
import { JSONSchema7 } from 'json-schema';
import { Request } from 'express';
import { validate } from 'jsonschema';
import { BadRequestException } from '../../exceptions';
import 'express-async-errors';
import { Request } from 'express';
import { JSONSchema7 } from 'json-schema';
import { validate } from 'jsonschema';
import { Logger } from '../../config/logger.config';
import { GetParticipant, GroupInvite, GroupJid } from '../dto/group.dto';
import { BadRequestException } from '../../exceptions';
import { GetParticipant, GroupInvite } from '../dto/group.dto';
import { InstanceDto } from '../dto/instance.dto';
type DataValidate<T> = {
request: Request;
@@ -46,20 +48,21 @@ export abstract class RouterBroker {
const v = schema ? validate(ref, schema) : { valid: true, errors: [] };
if (!v.valid) {
const message: any[] = v.errors.map(({ property, stack, schema }) => {
const message: any[] = v.errors.map(({ stack, schema }) => {
let message: string;
if (schema['description']) {
message = schema['description'];
} else {
message = stack.replace('instance.', '');
}
return {
property: property.replace('instance.', ''),
message,
};
return message;
// return {
// property: property.replace('instance.', ''),
// message,
// };
});
logger.error([...message]);
throw new BadRequestException(...message);
logger.error(message);
throw new BadRequestException(message);
}
return await execute(instance, ref);
@@ -99,21 +102,29 @@ export abstract class RouterBroker {
public async groupValidate<T>(args: DataValidate<T>) {
const { request, ClassRef, schema, execute } = args;
const groupJid = request.query as unknown as GroupJid;
if (!groupJid?.groupJid) {
throw new BadRequestException(
'The group id needs to be informed in the query',
'ex: "groupJid=120362@g.us"',
);
}
const instance = request.params as unknown as InstanceDto;
const body = request.body;
let groupJid = body?.groupJid;
if (!groupJid) {
if (request.query?.groupJid) {
groupJid = request.query.groupJid;
} else {
throw new BadRequestException('The group id needs to be informed in the query', 'ex: "groupJid=120362@g.us"');
}
}
if (!groupJid.endsWith('@g.us')) {
groupJid = groupJid + '@g.us';
}
Object.assign(body, {
groupJid: groupJid,
});
const ref = new ClassRef();
Object.assign(body, groupJid);
Object.assign(ref, body);
const v = validate(ref, schema);
@@ -160,8 +171,6 @@ export abstract class RouterBroker {
const v = validate(ref, schema);
console.log(v, '@checkei aqui');
if (!v.valid) {
const message: any[] = v.errors.map(({ property, stack, schema }) => {
let message: string;
@@ -188,9 +197,7 @@ export abstract class RouterBroker {
const getParticipants = request.query as unknown as GetParticipant;
if (!getParticipants?.getParticipants) {
throw new BadRequestException(
'The getParticipants needs to be informed in the query',
);
throw new BadRequestException('The getParticipants needs to be informed in the query');
}
const instance = request.params as unknown as InstanceDto;
@@ -203,8 +210,6 @@ export abstract class RouterBroker {
const v = validate(ref, schema);
console.log(v, '@checkei aqui');
if (!v.valid) {
const message: any[] = v.errors.map(({ property, stack, schema }) => {
let message: string;

View File

@@ -0,0 +1,29 @@
import { Logger } from '../../config/logger.config';
import { ChamaaiDto } from '../dto/chamaai.dto';
import { InstanceDto } from '../dto/instance.dto';
import { ChamaaiService } from '../services/chamaai.service';
const logger = new Logger('ChamaaiController');
export class ChamaaiController {
constructor(private readonly chamaaiService: ChamaaiService) {}
public async createChamaai(instance: InstanceDto, data: ChamaaiDto) {
logger.verbose('requested createChamaai from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('chamaai disabled');
data.url = '';
data.token = '';
data.waNumber = '';
data.answerByAudio = false;
}
return this.chamaaiService.create(instance, data);
}
public async findChamaai(instance: InstanceDto) {
logger.verbose('requested findChamaai from ' + instance.instanceName + ' instance');
return this.chamaaiService.find(instance);
}
}

View File

@@ -1,22 +1,22 @@
import { proto } from '@whiskeysockets/baileys';
import { Logger } from '../../config/logger.config';
import {
ArchiveChatDto,
DeleteMessage,
getBase64FromMediaMessageDto,
NumberDto,
PrivacySettingDto,
ProfileNameDto,
ProfilePictureDto,
ProfileStatusDto,
ReadMessageDto,
SendPresenceDto,
WhatsAppNumberDto,
getBase64FromMediaMessageDto,
} from '../dto/chat.dto';
import { InstanceDto } from '../dto/instance.dto';
import { ContactQuery } from '../repository/contact.repository';
import { MessageQuery } from '../repository/message.repository';
import { MessageUpQuery } from '../repository/messageUp.repository';
import { WAMonitoringService } from '../services/monitor.service';
import { Logger } from '../../config/logger.config';
const logger = new Logger('ChatController');
@@ -48,18 +48,18 @@ export class ChatController {
return await this.waMonitor.waInstances[instanceName].profilePicture(data.number);
}
public async fetchProfile({ instanceName }: InstanceDto, data: NumberDto) {
logger.verbose('requested fetchProfile from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].fetchProfile(instanceName, data.number);
}
public async fetchContacts({ instanceName }: InstanceDto, query: ContactQuery) {
logger.verbose('requested fetchContacts from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].fetchContacts(query);
}
public async getBase64FromMediaMessage(
{ instanceName }: InstanceDto,
data: getBase64FromMediaMessageDto,
) {
logger.verbose(
'requested getBase64FromMediaMessage from ' + instanceName + ' instance',
);
public async getBase64FromMediaMessage({ instanceName }: InstanceDto, data: getBase64FromMediaMessageDto) {
logger.verbose('requested getBase64FromMediaMessage from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].getBase64FromMediaMessage(data);
}
@@ -78,27 +78,24 @@ export class ChatController {
return await this.waMonitor.waInstances[instanceName].fetchChats();
}
public async sendPresence({ instanceName }: InstanceDto, data: SendPresenceDto) {
logger.verbose('requested sendPresence from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].sendPresence(data);
}
public async fetchPrivacySettings({ instanceName }: InstanceDto) {
logger.verbose('requested fetchPrivacySettings from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].fetchPrivacySettings();
}
public async updatePrivacySettings(
{ instanceName }: InstanceDto,
data: PrivacySettingDto,
) {
public async updatePrivacySettings({ instanceName }: InstanceDto, data: PrivacySettingDto) {
logger.verbose('requested updatePrivacySettings from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].updatePrivacySettings(data);
}
public async fetchBusinessProfile(
{ instanceName }: InstanceDto,
data: ProfilePictureDto,
) {
public async fetchBusinessProfile({ instanceName }: InstanceDto, data: ProfilePictureDto) {
logger.verbose('requested fetchBusinessProfile from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].fetchBusinessProfile(
data.number,
);
return await this.waMonitor.waInstances[instanceName].fetchBusinessProfile(data.number);
}
public async updateProfileName({ instanceName }: InstanceDto, data: ProfileNameDto) {
@@ -106,30 +103,17 @@ export class ChatController {
return await this.waMonitor.waInstances[instanceName].updateProfileName(data.name);
}
public async updateProfileStatus(
{ instanceName }: InstanceDto,
data: ProfileStatusDto,
) {
public async updateProfileStatus({ instanceName }: InstanceDto, data: ProfileStatusDto) {
logger.verbose('requested updateProfileStatus from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].updateProfileStatus(
data.status,
);
return await this.waMonitor.waInstances[instanceName].updateProfileStatus(data.status);
}
public async updateProfilePicture(
{ instanceName }: InstanceDto,
data: ProfilePictureDto,
) {
public async updateProfilePicture({ instanceName }: InstanceDto, data: ProfilePictureDto) {
logger.verbose('requested updateProfilePicture from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].updateProfilePicture(
data.picture,
);
return await this.waMonitor.waInstances[instanceName].updateProfilePicture(data.picture);
}
public async removeProfilePicture(
{ instanceName }: InstanceDto,
data: ProfilePictureDto,
) {
public async removeProfilePicture({ instanceName }: InstanceDto) {
logger.verbose('requested removeProfilePicture from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].removeProfilePicture();
}

View File

@@ -1,11 +1,13 @@
import { isURL } from 'class-validator';
import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { ChatwootDto } from '../dto/chatwoot.dto';
import { ChatwootService } from '../services/chatwoot.service';
import { Logger } from '../../config/logger.config';
import { waMonitor } from '../whatsapp.module';
import { ConfigService, HttpServer } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { BadRequestException } from '../../exceptions';
import { ChatwootDto } from '../dto/chatwoot.dto';
import { InstanceDto } from '../dto/instance.dto';
import { RepositoryBroker } from '../repository/repository.manager';
import { ChatwootService } from '../services/chatwoot.service';
import { waMonitor } from '../whatsapp.module';
const logger = new Logger('ChatwootController');
@@ -13,12 +15,11 @@ export class ChatwootController {
constructor(
private readonly chatwootService: ChatwootService,
private readonly configService: ConfigService,
private readonly repository: RepositoryBroker,
) {}
public async createChatwoot(instance: InstanceDto, data: ChatwootDto) {
logger.verbose(
'requested createChatwoot from ' + instance.instanceName + ' instance',
);
logger.verbose('requested createChatwoot from ' + instance.instanceName + ' instance');
if (data.enabled) {
if (!isURL(data.url, { require_tld: false })) {
@@ -33,9 +34,10 @@ export class ChatwootController {
throw new BadRequestException('token is required');
}
if (!data.sign_msg) {
if (data.sign_msg !== true && data.sign_msg !== false) {
throw new BadRequestException('sign_msg is required');
}
if (data.sign_msg === false) data.sign_delimiter = null;
}
if (!data.enabled) {
@@ -44,17 +46,21 @@ export class ChatwootController {
data.token = '';
data.url = '';
data.sign_msg = false;
data.sign_delimiter = null;
data.reopen_conversation = false;
data.conversation_pending = false;
data.auto_create = false;
}
data.name_inbox = instance.instanceName;
const result = this.chatwootService.create(instance, data);
const result = await this.chatwootService.create(instance, data);
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
const response = {
...result,
webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`,
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
};
return response;
@@ -66,19 +72,29 @@ export class ChatwootController {
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
if (Object.keys(result || {}).length === 0) {
return {
enabled: false,
url: '',
account_id: '',
token: '',
sign_msg: false,
name_inbox: '',
webhook_url: '',
};
}
const response = {
...result,
webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`,
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
};
return response;
}
public async receiveWebhook(instance: InstanceDto, data: any) {
logger.verbose(
'requested receiveWebhook from ' + instance.instanceName + ' instance',
);
const chatwootService = new ChatwootService(waMonitor);
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
const chatwootService = new ChatwootService(waMonitor, this.configService, this.repository);
return chatwootService.receiveWebhook(instance, data);
}

View File

@@ -1,3 +1,4 @@
import { Logger } from '../../config/logger.config';
import {
CreateGroupDto,
GetParticipant,
@@ -13,7 +14,6 @@ import {
} from '../dto/group.dto';
import { InstanceDto } from '../dto/instance.dto';
import { WAMonitoringService } from '../services/monitor.service';
import { Logger } from '../../config/logger.config';
const logger = new Logger('ChatController');
@@ -26,33 +26,18 @@ export class GroupController {
}
public async updateGroupPicture(instance: InstanceDto, update: GroupPictureDto) {
logger.verbose(
'requested updateGroupPicture from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].updateGroupPicture(
update,
);
logger.verbose('requested updateGroupPicture from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].updateGroupPicture(update);
}
public async updateGroupSubject(instance: InstanceDto, update: GroupSubjectDto) {
logger.verbose(
'requested updateGroupSubject from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].updateGroupSubject(
update,
);
logger.verbose('requested updateGroupSubject from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].updateGroupSubject(update);
}
public async updateGroupDescription(
instance: InstanceDto,
update: GroupDescriptionDto,
) {
logger.verbose(
'requested updateGroupDescription from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].updateGroupDescription(
update,
);
public async updateGroupDescription(instance: InstanceDto, update: GroupDescriptionDto) {
logger.verbose('requested updateGroupDescription from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].updateGroupDescription(update);
}
public async findGroupInfo(instance: InstanceDto, groupJid: GroupJid) {
@@ -61,12 +46,8 @@ export class GroupController {
}
public async fetchAllGroups(instance: InstanceDto, getPaticipants: GetParticipant) {
logger.verbose(
'requested fetchAllGroups from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].fetchAllGroups(
getPaticipants,
);
logger.verbose('requested fetchAllGroups from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].fetchAllGroups(getPaticipants);
}
public async inviteCode(instance: InstanceDto, groupJid: GroupJid) {
@@ -85,49 +66,28 @@ export class GroupController {
}
public async revokeInviteCode(instance: InstanceDto, groupJid: GroupJid) {
logger.verbose(
'requested revokeInviteCode from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].revokeInviteCode(
groupJid,
);
logger.verbose('requested revokeInviteCode from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].revokeInviteCode(groupJid);
}
public async findParticipants(instance: InstanceDto, groupJid: GroupJid) {
logger.verbose(
'requested findParticipants from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].findParticipants(
groupJid,
);
logger.verbose('requested findParticipants from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].findParticipants(groupJid);
}
public async updateGParticipate(
instance: InstanceDto,
update: GroupUpdateParticipantDto,
) {
logger.verbose(
'requested updateGParticipate from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].updateGParticipant(
update,
);
public async updateGParticipate(instance: InstanceDto, update: GroupUpdateParticipantDto) {
logger.verbose('requested updateGParticipate from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].updateGParticipant(update);
}
public async updateGSetting(instance: InstanceDto, update: GroupUpdateSettingDto) {
logger.verbose(
'requested updateGSetting from ' + instance.instanceName + ' instance',
);
logger.verbose('requested updateGSetting from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].updateGSetting(update);
}
public async toggleEphemeral(instance: InstanceDto, update: GroupToggleEphemeralDto) {
logger.verbose(
'requested toggleEphemeral from ' + instance.instanceName + ' instance',
);
return await this.waMonitor.waInstances[instance.instanceName].toggleEphemeral(
update,
);
logger.verbose('requested toggleEphemeral from ' + instance.instanceName + ' instance');
return await this.waMonitor.waInstances[instance.instanceName].toggleEphemeral(update);
}
public async leaveGroup(instance: InstanceDto, groupJid: GroupJid) {

View File

@@ -1,17 +1,26 @@
import { delay } from '@whiskeysockets/baileys';
import { isURL } from 'class-validator';
import EventEmitter2 from 'eventemitter2';
import { Auth, ConfigService, HttpServer } from '../../config/env.config';
import { v4 } from 'uuid';
import { ConfigService, HttpServer } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { BadRequestException, InternalServerErrorException } from '../../exceptions';
import { RedisCache } from '../../libs/redis.client';
import { InstanceDto } from '../dto/instance.dto';
import { RepositoryBroker } from '../repository/repository.manager';
import { AuthService, OldToken } from '../services/auth.service';
import { WAMonitoringService } from '../services/monitor.service';
import { WAStartupService } from '../services/whatsapp.service';
import { WebhookService } from '../services/webhook.service';
import { ChatwootService } from '../services/chatwoot.service';
import { Logger } from '../../config/logger.config';
import { wa } from '../types/wa.types';
import { RedisCache } from '../../db/redis.client';
import { WAMonitoringService } from '../services/monitor.service';
import { ProxyService } from '../services/proxy.service';
import { RabbitmqService } from '../services/rabbitmq.service';
import { SettingsService } from '../services/settings.service';
import { SqsService } from '../services/sqs.service';
import { TypebotService } from '../services/typebot.service';
import { WebhookService } from '../services/webhook.service';
import { WebsocketService } from '../services/websocket.service';
import { WAStartupService } from '../services/whatsapp.service';
import { Events, wa } from '../types/wa.types';
export class InstanceController {
constructor(
@@ -22,6 +31,12 @@ export class InstanceController {
private readonly authService: AuthService,
private readonly webhookService: WebhookService,
private readonly chatwootService: ChatwootService,
private readonly settingsService: SettingsService,
private readonly websocketService: WebsocketService,
private readonly rabbitmqService: RabbitmqService,
private readonly proxyService: ProxyService,
private readonly sqsService: SqsService,
private readonly typebotService: TypebotService,
private readonly cache: RedisCache,
) {}
@@ -31,39 +46,55 @@ export class InstanceController {
instanceName,
webhook,
webhook_by_events,
webhook_base64,
events,
qrcode,
number,
token,
chatwoot_account_id,
chatwoot_token,
chatwoot_url,
chatwoot_sign_msg,
chatwoot_reopen_conversation,
chatwoot_conversation_pending,
reject_call,
msg_call,
groups_ignore,
always_online,
read_messages,
read_status,
websocket_enabled,
websocket_events,
rabbitmq_enabled,
rabbitmq_events,
sqs_enabled,
sqs_events,
typebot_url,
typebot,
typebot_expire,
typebot_keyword_finish,
typebot_delay_message,
typebot_unknown_message,
typebot_listening_from_me,
proxy,
}: InstanceDto) {
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
const mode = this.configService.get<Auth>('AUTHENTICATION').INSTANCE.MODE;
if (mode === 'container') {
this.logger.verbose('container mode');
if (Object.keys(this.waMonitor.waInstances).length > 0) {
throw new BadRequestException([
'Instance already created',
'Only one instance can be created',
]);
}
try {
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
this.logger.verbose('checking duplicate token');
await this.authService.checkDuplicateToken(token);
this.logger.verbose('creating instance');
const instance = new WAStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.cache,
);
const instance = new WAStartupService(this.configService, this.eventEmitter, this.repository, this.cache);
instance.instanceName = instanceName;
const instanceId = v4();
instance.sendDataWebhook(Events.INSTANCE_CREATE, {
instanceName,
instanceId: instanceId,
});
this.logger.verbose('instance: ' + instance.instanceName + ' created');
this.waMonitor.waInstances[instance.instanceName] = instance;
@@ -73,185 +104,315 @@ export class InstanceController {
const hash = await this.authService.generateHash(
{
instanceName: instance.instanceName,
instanceId: instanceId,
},
token,
);
this.logger.verbose('hash: ' + hash + ' generated');
let getEvents: string[];
let webhookEvents: string[];
if (webhook) {
if (!isURL(webhook, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property in webhook');
}
this.logger.verbose('creating webhook');
try {
let newEvents: string[] = [];
if (events.length === 0) {
newEvents = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = events;
}
this.webhookService.create(instance, {
enabled: true,
url: webhook,
events,
events: newEvents,
webhook_by_events,
webhook_base64,
});
getEvents = (await this.webhookService.find(instance)).events;
webhookEvents = (await this.webhookService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
if (!chatwoot_account_id || !chatwoot_token || !chatwoot_url) {
this.logger.verbose('instance created');
this.logger.verbose({
instance: {
instanceName: instance.instanceName,
status: 'created',
},
hash,
webhook,
events: getEvents,
});
let websocketEvents: string[];
return {
instance: {
instanceName: instance.instanceName,
status: 'created',
},
hash,
webhook,
events: getEvents,
};
if (websocket_enabled) {
this.logger.verbose('creating websocket');
try {
let newEvents: string[] = [];
if (websocket_events.length === 0) {
newEvents = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = websocket_events;
}
this.websocketService.create(instance, {
enabled: true,
events: newEvents,
});
websocketEvents = (await this.websocketService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
if (!chatwoot_account_id) {
throw new BadRequestException('account_id is required');
let rabbitmqEvents: string[];
if (rabbitmq_enabled) {
this.logger.verbose('creating rabbitmq');
try {
let newEvents: string[] = [];
if (rabbitmq_events.length === 0) {
newEvents = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = rabbitmq_events;
}
this.rabbitmqService.create(instance, {
enabled: true,
events: newEvents,
});
rabbitmqEvents = (await this.rabbitmqService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
if (!chatwoot_token) {
throw new BadRequestException('token is required');
if (proxy) {
this.logger.verbose('creating proxy');
try {
this.proxyService.create(
instance,
{
enabled: true,
proxy,
},
false,
);
} catch (error) {
this.logger.log(error);
}
}
if (!chatwoot_url) {
throw new BadRequestException('url is required');
let sqsEvents: string[];
if (sqs_enabled) {
this.logger.verbose('creating sqs');
try {
let newEvents: string[] = [];
if (sqs_events.length === 0) {
newEvents = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
} else {
newEvents = sqs_events;
}
this.sqsService.create(instance, {
enabled: true,
events: newEvents,
});
sqsEvents = (await this.sqsService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
if (typebot_url) {
try {
if (!isURL(typebot_url, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property in typebot_url');
}
try {
this.chatwootService.create(instance, {
enabled: true,
account_id: chatwoot_account_id,
token: chatwoot_token,
url: chatwoot_url,
sign_msg: chatwoot_sign_msg || false,
name_inbox: instance.instanceName,
});
this.logger.verbose('creating typebot');
this.chatwootService.initInstanceChatwoot(
instance,
instance.instanceName,
`${urlServer}/chatwoot/webhook/${instance.instanceName}`,
qrcode,
);
} catch (error) {
this.logger.log(error);
this.typebotService.create(instance, {
enabled: true,
url: typebot_url,
typebot: typebot,
expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message,
listening_from_me: typebot_listening_from_me,
});
} catch (error) {
this.logger.log(error);
}
}
return {
instance: {
instanceName: instance.instanceName,
status: 'created',
},
hash,
chatwoot: {
enabled: true,
account_id: chatwoot_account_id,
token: chatwoot_token,
url: chatwoot_url,
sign_msg: chatwoot_sign_msg || false,
name_inbox: instance.instanceName,
webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`,
},
this.logger.verbose('creating settings');
const settings: wa.LocalSettings = {
reject_call: reject_call || false,
msg_call: msg_call || '',
groups_ignore: groups_ignore || true,
always_online: always_online || false,
read_messages: read_messages || false,
read_status: read_status || false,
};
} else {
this.logger.verbose('server mode');
this.logger.verbose('checking duplicate token');
await this.authService.checkDuplicateToken(token);
this.logger.verbose('settings: ' + JSON.stringify(settings));
this.logger.verbose('creating instance');
const instance = new WAStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.cache,
);
instance.instanceName = instanceName;
this.logger.verbose('instance: ' + instance.instanceName + ' created');
this.waMonitor.waInstances[instance.instanceName] = instance;
this.waMonitor.delInstanceTime(instance.instanceName);
this.logger.verbose('generating hash');
const hash = await this.authService.generateHash(
{
instanceName: instance.instanceName,
},
token,
);
this.logger.verbose('hash: ' + hash + ' generated');
let getEvents: string[];
if (webhook) {
this.logger.verbose('creating webhook');
try {
this.webhookService.create(instance, {
enabled: true,
url: webhook,
events,
webhook_by_events,
});
getEvents = (await this.webhookService.find(instance)).events;
} catch (error) {
this.logger.log(error);
}
}
this.settingsService.create(instance, settings);
if (!chatwoot_account_id || !chatwoot_token || !chatwoot_url) {
let getQrcode: wa.QrCode;
if (qrcode) {
this.logger.verbose('creating qrcode');
await instance.connectToWhatsapp();
await delay(2000);
await instance.connectToWhatsapp(number);
await delay(5000);
getQrcode = instance.qrCode;
}
this.logger.verbose('instance created');
this.logger.verbose({
const result = {
instance: {
instanceName: instance.instanceName,
instanceId: instanceId,
status: 'created',
},
hash,
webhook,
webhook_by_events,
events: getEvents,
qrcode: getQrcode,
});
return {
instance: {
instanceName: instance.instanceName,
status: 'created',
webhook: {
webhook,
webhook_by_events,
webhook_base64,
events: webhookEvents,
},
hash,
webhook,
webhook_by_events,
events: getEvents,
websocket: {
enabled: websocket_enabled,
events: websocketEvents,
},
rabbitmq: {
enabled: rabbitmq_enabled,
events: rabbitmqEvents,
},
sqs: {
enabled: sqs_enabled,
events: sqsEvents,
},
typebot: {
enabled: typebot_url ? true : false,
url: typebot_url,
typebot,
expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message,
listening_from_me: typebot_listening_from_me,
},
settings,
qrcode: getQrcode,
proxy,
};
this.logger.verbose('instance created');
this.logger.verbose(result);
return result;
}
if (!chatwoot_account_id) {
@@ -266,6 +427,22 @@ export class InstanceController {
throw new BadRequestException('url is required');
}
if (!isURL(chatwoot_url, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property in chatwoot');
}
if (chatwoot_sign_msg !== true && chatwoot_sign_msg !== false) {
throw new BadRequestException('sign_msg is required');
}
if (chatwoot_reopen_conversation !== true && chatwoot_reopen_conversation !== false) {
throw new BadRequestException('reopen_conversation is required');
}
if (chatwoot_conversation_pending !== true && chatwoot_conversation_pending !== false) {
throw new BadRequestException('conversation_pending is required');
}
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
try {
@@ -275,15 +452,12 @@ export class InstanceController {
token: chatwoot_token,
url: chatwoot_url,
sign_msg: chatwoot_sign_msg || false,
name_inbox: instance.instanceName,
name_inbox: instance.instanceName.split('-cwId-')[0],
number,
reopen_conversation: chatwoot_reopen_conversation || false,
conversation_pending: chatwoot_conversation_pending || false,
auto_create: true,
});
this.chatwootService.initInstanceChatwoot(
instance,
instance.instanceName,
`${urlServer}/chatwoot/webhook/${instance.instanceName}`,
qrcode,
);
} catch (error) {
this.logger.log(error);
}
@@ -291,47 +465,95 @@ export class InstanceController {
return {
instance: {
instanceName: instance.instanceName,
instanceId: instanceId,
status: 'created',
},
hash,
webhook,
webhook_by_events,
events: getEvents,
webhook: {
webhook,
webhook_by_events,
webhook_base64,
events: webhookEvents,
},
websocket: {
enabled: websocket_enabled,
events: websocketEvents,
},
rabbitmq: {
enabled: rabbitmq_enabled,
events: rabbitmqEvents,
},
sqs: {
enabled: sqs_enabled,
events: sqsEvents,
},
typebot: {
enabled: typebot_url ? true : false,
url: typebot_url,
typebot,
expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message,
listening_from_me: typebot_listening_from_me,
},
settings,
chatwoot: {
enabled: true,
account_id: chatwoot_account_id,
token: chatwoot_token,
url: chatwoot_url,
sign_msg: chatwoot_sign_msg || false,
reopen_conversation: chatwoot_reopen_conversation || false,
conversation_pending: chatwoot_conversation_pending || false,
number,
name_inbox: instance.instanceName,
webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`,
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
},
proxy,
};
} catch (error) {
this.logger.error(error.message[0]);
throw new BadRequestException(error.message[0]);
}
}
public async connectToWhatsapp({ instanceName }: InstanceDto) {
public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) {
try {
this.logger.verbose(
'requested connectToWhatsapp from ' + instanceName + ' instance',
);
this.logger.verbose('requested connectToWhatsapp from ' + instanceName + ' instance');
const instance = this.waMonitor.waInstances[instanceName];
const state = instance?.connectionStatus?.state;
this.logger.verbose('state: ' + state);
switch (state) {
case 'close':
this.logger.verbose('connecting');
await instance.connectToWhatsapp();
await delay(2000);
return instance.qrCode;
case 'connecting':
return instance.qrCode;
default:
return await this.connectionState({ instanceName });
if (!state) {
throw new BadRequestException('The "' + instanceName + '" instance does not exist');
}
if (state == 'open') {
return await this.connectionState({ instanceName });
}
if (state == 'connecting') {
return instance.qrCode;
}
if (state == 'close') {
this.logger.verbose('connecting');
await instance.connectToWhatsapp(number);
await delay(5000);
return instance.qrCode;
}
return {
instance: {
instanceName: instanceName,
status: state,
},
qrcode: instance?.qrCode,
};
} catch (error) {
this.logger.error(error);
}
@@ -341,26 +563,19 @@ export class InstanceController {
try {
this.logger.verbose('requested restartInstance from ' + instanceName + ' instance');
this.logger.verbose('deleting instance: ' + instanceName);
delete this.waMonitor.waInstances[instanceName];
const instance = this.waMonitor.waInstances[instanceName];
const state = instance?.connectionStatus?.state;
this.logger.verbose('creating instance: ' + instanceName);
const instance = new WAStartupService(
this.configService,
this.eventEmitter,
this.repository,
this.cache,
);
switch (state) {
case 'open':
this.logger.verbose('logging out instance: ' + instanceName);
await instance.reloadConnection();
await delay(2000);
instance.instanceName = instanceName;
this.logger.verbose('instance: ' + instance.instanceName + ' created');
this.logger.verbose('connecting instance: ' + instanceName);
await instance.connectToWhatsapp();
this.waMonitor.waInstances[instance.instanceName] = instance;
return { error: false, message: 'Instance restarted' };
return await this.connectionState({ instanceName });
default:
return await this.connectionState({ instanceName });
}
} catch (error) {
this.logger.error(error);
}
@@ -368,39 +583,43 @@ export class InstanceController {
public async connectionState({ instanceName }: InstanceDto) {
this.logger.verbose('requested connectionState from ' + instanceName + ' instance');
return this.waMonitor.waInstances[instanceName]?.connectionStatus;
return {
instance: {
instanceName: instanceName,
state: this.waMonitor.waInstances[instanceName]?.connectionStatus?.state,
},
};
}
public async fetchInstances({ instanceName }: InstanceDto) {
this.logger.verbose('requested fetchInstances from ' + instanceName + ' instance');
public async fetchInstances({ instanceName, instanceId }: InstanceDto) {
if (instanceName) {
this.logger.verbose('requested fetchInstances from ' + instanceName + ' instance');
this.logger.verbose('instanceName: ' + instanceName);
return this.waMonitor.instanceInfo(instanceName);
} else if (instanceId) {
return this.waMonitor.instanceInfoById(instanceId);
}
this.logger.verbose('requested fetchInstances (all instances)');
return this.waMonitor.instanceInfo();
}
public async logout({ instanceName }: InstanceDto) {
this.logger.verbose('requested logout from ' + instanceName + ' instance');
const stateConn = await this.connectionState({ instanceName });
const { instance } = await this.connectionState({ instanceName });
if (stateConn.state === 'close') {
throw new BadRequestException(
'The "' + instanceName + '" instance is not connected',
);
if (instance.state === 'close') {
throw new BadRequestException('The "' + instanceName + '" instance is not connected');
}
try {
this.logger.verbose('logging out instance: ' + instanceName);
await this.waMonitor.waInstances[instanceName]?.client?.logout(
'Log out instance: ' + instanceName,
);
await this.waMonitor.waInstances[instanceName]?.client?.logout('Log out instance: ' + instanceName);
this.logger.verbose('close connection instance: ' + instanceName);
this.waMonitor.waInstances[instanceName]?.client?.ws?.close();
return { error: false, message: 'Instance logged out' };
return { status: 'SUCCESS', error: false, response: { message: 'Instance logged out' } };
} catch (error) {
throw new InternalServerErrorException(error.toString());
}
@@ -408,27 +627,29 @@ export class InstanceController {
public async deleteInstance({ instanceName }: InstanceDto) {
this.logger.verbose('requested deleteInstance from ' + instanceName + ' instance');
const stateConn = await this.connectionState({ instanceName });
const { instance } = await this.connectionState({ instanceName });
if (stateConn.state === 'open') {
throw new BadRequestException(
'The "' + instanceName + '" instance needs to be disconnected',
);
if (instance.state === 'open') {
throw new BadRequestException('The "' + instanceName + '" instance needs to be disconnected');
}
try {
if (stateConn.state === 'connecting') {
this.waMonitor.waInstances[instanceName]?.removeRabbitmqQueues();
if (instance.state === 'connecting') {
this.logger.verbose('logging out instance: ' + instanceName);
await this.logout({ instanceName });
delete this.waMonitor.waInstances[instanceName];
return { error: false, message: 'Instance deleted' };
} else {
this.logger.verbose('deleting instance: ' + instanceName);
delete this.waMonitor.waInstances[instanceName];
this.eventEmitter.emit('remove.instance', instanceName, 'inner');
return { error: false, message: 'Instance deleted' };
}
this.logger.verbose('deleting instance: ' + instanceName);
this.waMonitor.waInstances[instanceName].sendDataWebhook(Events.INSTANCE_DELETE, {
instanceName,
instanceId: (await this.repository.auth.find(instanceName))?.instanceId,
});
delete this.waMonitor.waInstances[instanceName];
this.eventEmitter.emit('remove.instance', instanceName, 'inner');
return { status: 'SUCCESS', error: false, response: { message: 'Instance deleted' } };
} catch (error) {
throw new BadRequestException(error.toString());
}

View File

@@ -0,0 +1,26 @@
import { Logger } from '../../config/logger.config';
import { InstanceDto } from '../dto/instance.dto';
import { ProxyDto } from '../dto/proxy.dto';
import { ProxyService } from '../services/proxy.service';
const logger = new Logger('ProxyController');
export class ProxyController {
constructor(private readonly proxyService: ProxyService) {}
public async createProxy(instance: InstanceDto, data: ProxyDto) {
logger.verbose('requested createProxy from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('proxy disabled');
data.proxy = '';
}
return this.proxyService.create(instance, data);
}
public async findProxy(instance: InstanceDto) {
logger.verbose('requested findProxy from ' + instance.instanceName + ' instance');
return this.proxyService.find(instance);
}
}

View File

@@ -0,0 +1,56 @@
import { Logger } from '../../config/logger.config';
import { InstanceDto } from '../dto/instance.dto';
import { RabbitmqDto } from '../dto/rabbitmq.dto';
import { RabbitmqService } from '../services/rabbitmq.service';
const logger = new Logger('RabbitmqController');
export class RabbitmqController {
constructor(private readonly rabbitmqService: RabbitmqService) {}
public async createRabbitmq(instance: InstanceDto, data: RabbitmqDto) {
logger.verbose('requested createRabbitmq from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('rabbitmq disabled');
data.events = [];
}
if (data.events.length === 0) {
logger.verbose('rabbitmq events empty');
data.events = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}
return this.rabbitmqService.create(instance, data);
}
public async findRabbitmq(instance: InstanceDto) {
logger.verbose('requested findRabbitmq from ' + instance.instanceName + ' instance');
return this.rabbitmqService.find(instance);
}
}

View File

@@ -1,11 +1,12 @@
import { isBase64, isURL } from 'class-validator';
import { Logger } from '../../config/logger.config';
import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import {
SendAudioDto,
SendButtonDto,
SendContactDto,
SendLinkPreviewDto,
SendListDto,
SendLocationDto,
SendMediaDto,
@@ -17,8 +18,6 @@ import {
} from '../dto/sendMessage.dto';
import { WAMonitoringService } from '../services/monitor.service';
import { Logger } from '../../config/logger.config';
const logger = new Logger('MessageRouter');
export class SendMessageController {
@@ -31,15 +30,16 @@ export class SendMessageController {
public async sendMedia({ instanceName }: InstanceDto, data: SendMediaDto) {
logger.verbose('requested sendMedia from ' + instanceName + ' instance');
if (isBase64(data?.mediaMessage?.media) && !data?.mediaMessage?.fileName) {
throw new BadRequestException('For bse64 the file name must be informed.');
if (
isBase64(data?.mediaMessage?.media) &&
!data?.mediaMessage?.fileName &&
data?.mediaMessage?.mediatype === 'document'
) {
throw new BadRequestException('For base64 the file name must be informed.');
}
logger.verbose(
'isURL: ' +
isURL(data?.mediaMessage?.media) +
', isBase64: ' +
isBase64(data?.mediaMessage?.media),
);
logger.verbose('isURL: ' + isURL(data?.mediaMessage?.media) + ', isBase64: ' + isBase64(data?.mediaMessage?.media));
if (isURL(data?.mediaMessage?.media) || isBase64(data?.mediaMessage?.media)) {
return await this.waMonitor.waInstances[instanceName].mediaMessage(data);
}
@@ -50,10 +50,7 @@ export class SendMessageController {
logger.verbose('requested sendSticker from ' + instanceName + ' instance');
logger.verbose(
'isURL: ' +
isURL(data?.stickerMessage?.image) +
', isBase64: ' +
isBase64(data?.stickerMessage?.image),
'isURL: ' + isURL(data?.stickerMessage?.image) + ', isBase64: ' + isBase64(data?.stickerMessage?.image),
);
if (isURL(data.stickerMessage.image) || isBase64(data.stickerMessage.image)) {
return await this.waMonitor.waInstances[instanceName].mediaSticker(data);
@@ -64,12 +61,7 @@ export class SendMessageController {
public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto) {
logger.verbose('requested sendWhatsAppAudio from ' + instanceName + ' instance');
logger.verbose(
'isURL: ' +
isURL(data?.audioMessage?.audio) +
', isBase64: ' +
isBase64(data?.audioMessage?.audio),
);
logger.verbose('isURL: ' + isURL(data?.audioMessage?.audio) + ', isBase64: ' + isBase64(data?.audioMessage?.audio));
if (isURL(data.audioMessage.audio) || isBase64(data.audioMessage.audio)) {
return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data);
}
@@ -78,10 +70,7 @@ export class SendMessageController {
public async sendButtons({ instanceName }: InstanceDto, data: SendButtonDto) {
logger.verbose('requested sendButtons from ' + instanceName + ' instance');
if (
isBase64(data.buttonMessage.mediaMessage?.media) &&
!data.buttonMessage.mediaMessage?.fileName
) {
if (isBase64(data.buttonMessage.mediaMessage?.media) && !data.buttonMessage.mediaMessage?.fileName) {
throw new BadRequestException('For bse64 the file name must be informed.');
}
return await this.waMonitor.waInstances[instanceName].buttonMessage(data);
@@ -104,7 +93,7 @@ export class SendMessageController {
public async sendReaction({ instanceName }: InstanceDto, data: SendReactionDto) {
logger.verbose('requested sendReaction from ' + instanceName + ' instance');
if (!data.reactionMessage.reaction.match(/[^\(\)\w\sà-ú"-\+]+/)) {
if (!data.reactionMessage.reaction.match(/[^()\w\sà-ú"-+]+/)) {
throw new BadRequestException('"reaction" must be an emoji');
}
return await this.waMonitor.waInstances[instanceName].reactionMessage(data);
@@ -119,9 +108,4 @@ export class SendMessageController {
logger.verbose('requested sendStatus from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].statusMessage(data);
}
public async sendLinkPreview({ instanceName }: InstanceDto, data: SendLinkPreviewDto) {
logger.verbose('requested sendLinkPreview from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].linkPreview(data);
}
}

View File

@@ -0,0 +1,25 @@
// import { isURL } from 'class-validator';
import { Logger } from '../../config/logger.config';
// import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { SettingsDto } from '../dto/settings.dto';
import { SettingsService } from '../services/settings.service';
const logger = new Logger('SettingsController');
export class SettingsController {
constructor(private readonly settingsService: SettingsService) {}
public async createSettings(instance: InstanceDto, data: SettingsDto) {
logger.verbose('requested createSettings from ' + instance.instanceName + ' instance');
return this.settingsService.create(instance, data);
}
public async findSettings(instance: InstanceDto) {
logger.verbose('requested findSettings from ' + instance.instanceName + ' instance');
const settings = this.settingsService.find(instance);
return settings;
}
}

View File

@@ -0,0 +1,56 @@
import { Logger } from '../../config/logger.config';
import { InstanceDto } from '../dto/instance.dto';
import { SqsDto } from '../dto/sqs.dto';
import { SqsService } from '../services/sqs.service';
const logger = new Logger('SqsController');
export class SqsController {
constructor(private readonly sqsService: SqsService) {}
public async createSqs(instance: InstanceDto, data: SqsDto) {
logger.verbose('requested createSqs from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('sqs disabled');
data.events = [];
}
if (data.events.length === 0) {
logger.verbose('sqs events empty');
data.events = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}
return this.sqsService.create(instance, data);
}
public async findSqs(instance: InstanceDto) {
logger.verbose('requested findSqs from ' + instance.instanceName + ' instance');
return this.sqsService.find(instance);
}
}

View File

@@ -0,0 +1,46 @@
import { Logger } from '../../config/logger.config';
import { InstanceDto } from '../dto/instance.dto';
import { TypebotDto } from '../dto/typebot.dto';
import { TypebotService } from '../services/typebot.service';
const logger = new Logger('TypebotController');
export class TypebotController {
constructor(private readonly typebotService: TypebotService) {}
public async createTypebot(instance: InstanceDto, data: TypebotDto) {
logger.verbose('requested createTypebot from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('typebot disabled');
data.url = '';
data.typebot = '';
data.expire = 0;
data.sessions = [];
} else {
const saveData = await this.typebotService.find(instance);
if (saveData.enabled) {
logger.verbose('typebot enabled');
data.sessions = saveData.sessions;
}
}
return this.typebotService.create(instance, data);
}
public async findTypebot(instance: InstanceDto) {
logger.verbose('requested findTypebot from ' + instance.instanceName + ' instance');
return this.typebotService.find(instance);
}
public async changeStatus(instance: InstanceDto, data: any) {
logger.verbose('requested changeStatus from ' + instance.instanceName + ' instance');
return this.typebotService.changeStatus(instance, data);
}
public async startTypebot(instance: InstanceDto, data: any) {
logger.verbose('requested startTypebot from ' + instance.instanceName + ' instance');
return this.typebotService.startTypebot(instance, data);
}
}

View File

@@ -1,28 +0,0 @@
import { Request, Response } from 'express';
import { Auth, ConfigService } from '../../config/env.config';
import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { HttpStatus } from '../routers/index.router';
import { WAMonitoringService } from '../services/monitor.service';
export class ViewsController {
constructor(
private readonly waMonit: WAMonitoringService,
private readonly configService: ConfigService,
) {}
public async qrcode(request: Request, response: Response) {
try {
const param = request.params as unknown as InstanceDto;
const instance = this.waMonit.waInstances[param.instanceName];
if (instance.connectionStatus.state === 'open') {
throw new BadRequestException('The instance is already connected');
}
const type = this.configService.get<Auth>('AUTHENTICATION').TYPE;
return response.status(HttpStatus.OK).render('qrcode', { type, ...param });
} catch (error) {
console.log('ERROR: ', error);
}
}
}

View File

@@ -1,9 +1,10 @@
import { isURL } from 'class-validator';
import { Logger } from '../../config/logger.config';
import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { WebhookDto } from '../dto/webhook.dto';
import { WebhookService } from '../services/webhook.service';
import { Logger } from '../../config/logger.config';
const logger = new Logger('WebhookController');
@@ -13,14 +14,44 @@ export class WebhookController {
public async createWebhook(instance: InstanceDto, data: WebhookDto) {
logger.verbose('requested createWebhook from ' + instance.instanceName + ' instance');
if (data.enabled && !isURL(data.url, { require_tld: false })) {
if (!isURL(data.url, { require_tld: false })) {
throw new BadRequestException('Invalid "url" property');
}
data.enabled = data.enabled ?? true;
if (!data.enabled) {
logger.verbose('webhook disabled');
data.url = '';
data.events = [];
} else if (data.events.length === 0) {
logger.verbose('webhook events empty');
data.events = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}
return this.webhookService.create(instance, data);

View File

@@ -0,0 +1,56 @@
import { Logger } from '../../config/logger.config';
import { InstanceDto } from '../dto/instance.dto';
import { WebsocketDto } from '../dto/websocket.dto';
import { WebsocketService } from '../services/websocket.service';
const logger = new Logger('WebsocketController');
export class WebsocketController {
constructor(private readonly websocketService: WebsocketService) {}
public async createWebsocket(instance: InstanceDto, data: WebsocketDto) {
logger.verbose('requested createWebsocket from ' + instance.instanceName + ' instance');
if (!data.enabled) {
logger.verbose('websocket disabled');
data.events = [];
}
if (data.events.length === 0) {
logger.verbose('websocket events empty');
data.events = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'CALL',
'NEW_JWT_TOKEN',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'CHAMA_AI_ACTION',
];
}
return this.websocketService.create(instance, data);
}
public async findWebsocket(instance: InstanceDto) {
logger.verbose('requested findWebsocket from ' + instance.instanceName + ' instance');
return this.websocketService.find(instance);
}
}

View File

@@ -0,0 +1,7 @@
export class ChamaaiDto {
enabled: boolean;
url: string;
token: string;
waNumber: string;
answerByAudio: boolean;
}

View File

@@ -1,16 +1,7 @@
import {
WAPrivacyOnlineValue,
WAPrivacyValue,
WAReadReceiptsValue,
proto,
} from '@whiskeysockets/baileys';
import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '@whiskeysockets/baileys';
export class OnWhatsAppDto {
constructor(
public readonly jid: string,
public readonly exists: boolean,
public readonly name?: string,
) {}
constructor(public readonly jid: string, public readonly exists: boolean, public readonly name?: string) {}
}
export class getBase64FromMediaMessageDto {
@@ -26,6 +17,19 @@ export class NumberDto {
number: string;
}
export class NumberBusiness {
wid?: string;
jid?: string;
exists?: boolean;
isBusiness: boolean;
name?: string;
message?: string;
description?: string;
email?: string;
website?: string[];
address?: string;
}
export class ProfileNameDto {
name: string;
}
@@ -46,16 +50,17 @@ class Key {
remoteJid: string;
}
export class ReadMessageDto {
readMessages: Key[];
read_messages: Key[];
}
class LastMessage {
export class LastMessage {
key: Key;
messageTimestamp?: number;
}
export class ArchiveChatDto {
lastMessage: LastMessage;
lastMessage?: LastMessage;
chat?: string;
archive: boolean;
}
@@ -78,3 +83,20 @@ export class DeleteMessage {
remoteJid: string;
participant?: string;
}
export class Options {
delay?: number;
presence?: WAPresence;
}
class OptionsMessage {
options: Options;
}
export class Metadata extends OptionsMessage {
number: string;
}
export class SendPresenceDto extends Metadata {
options: {
presence: WAPresence;
delay: number;
};
}

View File

@@ -5,4 +5,9 @@ export class ChatwootDto {
url?: string;
name_inbox?: string;
sign_msg?: boolean;
sign_delimiter?: string;
number?: string;
reopen_conversation?: boolean;
conversation_pending?: boolean;
auto_create?: boolean;
}

View File

@@ -1,7 +1,8 @@
export class CreateGroupDto {
subject: string;
description?: string;
participants: string[];
description?: string;
promoteParticipants?: boolean;
}
export class GroupPictureDto {

View File

@@ -1,12 +1,37 @@
export class InstanceDto {
instanceName: string;
instanceId?: string;
qrcode?: boolean;
number?: string;
token?: string;
webhook?: string;
webhook_by_events?: boolean;
webhook_base64?: boolean;
events?: string[];
qrcode?: boolean;
token?: string;
reject_call?: boolean;
msg_call?: string;
groups_ignore?: boolean;
always_online?: boolean;
read_messages?: boolean;
read_status?: boolean;
chatwoot_account_id?: string;
chatwoot_token?: string;
chatwoot_url?: string;
chatwoot_sign_msg?: boolean;
chatwoot_reopen_conversation?: boolean;
chatwoot_conversation_pending?: boolean;
websocket_enabled?: boolean;
websocket_events?: string[];
rabbitmq_enabled?: boolean;
rabbitmq_events?: string[];
sqs_enabled?: boolean;
sqs_events?: string[];
typebot_url?: string;
typebot?: string;
typebot_expire?: number;
typebot_keyword_finish?: string;
typebot_delay_message?: number;
typebot_unknown_message?: string;
typebot_listening_from_me?: boolean;
proxy?: string;
}

View File

@@ -0,0 +1,4 @@
export class ProxyDto {
enabled: boolean;
proxy: string;
}

View File

@@ -0,0 +1,4 @@
export class RabbitmqDto {
enabled: boolean;
events?: string[];
}

View File

@@ -15,6 +15,8 @@ export class Options {
presence?: WAPresence;
quoted?: Quoted;
mentions?: Mentions;
linkPreview?: boolean;
encoding?: boolean;
}
class OptionsMessage {
options: Options;
@@ -28,10 +30,6 @@ class TextMessage {
text: string;
}
class linkPreviewMessage {
text: string;
}
export class StatusMessage {
type: string;
content: string;
@@ -48,12 +46,12 @@ class PollMessage {
values: string[];
messageSecret?: Uint8Array;
}
export class SendTextDto extends Metadata {
textMessage: TextMessage;
}
export class SendLinkPreviewDto extends Metadata {
linkPreview: linkPreviewMessage;
export class SendPresence extends Metadata {
textMessage: TextMessage;
}
export class SendStatusDto extends Metadata {
@@ -67,6 +65,7 @@ export class SendPollDto extends Metadata {
export type MediaType = 'image' | 'document' | 'video' | 'audio';
export class MediaMessage {
mediatype: MediaType;
mimetype?: string;
caption?: string;
// for document
fileName?: string;

View File

@@ -0,0 +1,8 @@
export class SettingsDto {
reject_call?: boolean;
msg_call?: string;
groups_ignore?: boolean;
always_online?: boolean;
read_messages?: boolean;
read_status?: boolean;
}

View File

@@ -0,0 +1,4 @@
export class SqsDto {
enabled: boolean;
events?: string[];
}

View File

@@ -0,0 +1,26 @@
export class Session {
remoteJid?: string;
sessionId?: string;
status?: string;
createdAt?: number;
updateAt?: number;
prefilledVariables?: PrefilledVariables;
}
export class PrefilledVariables {
remoteJid?: string;
pushName?: string;
additionalData?: { [key: string]: any };
}
export class TypebotDto {
enabled?: boolean;
url: string;
typebot?: string;
expire?: number;
keyword_finish?: string;
delay_message?: number;
unknown_message?: string;
listening_from_me?: boolean;
sessions?: Session[];
}

View File

@@ -3,4 +3,5 @@ export class WebhookDto {
url?: string;
events?: string[];
webhook_by_events?: boolean;
webhook_base64?: boolean;
}

View File

@@ -0,0 +1,4 @@
export class WebsocketDto {
enabled: boolean;
events?: string[];
}

View File

@@ -1,12 +1,13 @@
import { isJWT } from 'class-validator';
import { NextFunction, Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import { name } from '../../../package.json';
import { Auth, configService } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { name } from '../../../package.json';
import { ForbiddenException, UnauthorizedException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto';
import { JwtPayload } from '../services/auth.service';
import { ForbiddenException, UnauthorizedException } from '../../exceptions';
import { repository } from '../whatsapp.module';
const logger = new Logger('GUARD');
@@ -22,15 +23,8 @@ async function jwtGuard(req: Request, res: Response, next: NextFunction) {
return next();
}
if (
(req.originalUrl.includes('/instance/create') ||
req.originalUrl.includes('/instance/fetchInstances')) &&
!key
) {
throw new ForbiddenException(
'Missing global api key',
'The global api key must be set',
);
if ((req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) && !key) {
throw new ForbiddenException('Missing global api key', 'The global api key must be set');
}
const jwtOpts = configService.get<Auth>('AUTHENTICATION').JWT;
@@ -61,7 +55,7 @@ async function jwtGuard(req: Request, res: Response, next: NextFunction) {
}
}
async function apikey(req: Request, res: Response, next: NextFunction) {
async function apikey(req: Request, _: Response, next: NextFunction) {
const env = configService.get<Auth>('AUTHENTICATION').API_KEY;
const key = req.get('apikey');
@@ -69,15 +63,8 @@ async function apikey(req: Request, res: Response, next: NextFunction) {
return next();
}
if (
(req.originalUrl.includes('/instance/create') ||
req.originalUrl.includes('/instance/fetchInstances')) &&
!key
) {
throw new ForbiddenException(
'Missing global api key',
'The global api key must be set',
);
if ((req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) && !key) {
throw new ForbiddenException('Missing global api key', 'The global api key must be set');
}
try {
@@ -86,7 +73,9 @@ async function apikey(req: Request, res: Response, next: NextFunction) {
if (instanceKey.apikey === key) {
return next();
}
} catch (error) {}
} catch (error) {
logger.error(error);
}
throw new UnauthorizedException();
}

View File

@@ -1,45 +1,47 @@
import { NextFunction, Request, Response } from 'express';
import { existsSync } from 'fs';
import { join } from 'path';
import { configService, Database, Redis } from '../../config/env.config';
import { INSTANCE_DIR } from '../../config/path.config';
import { dbserver } from '../../db/db.connect';
import {
BadRequestException,
ForbiddenException,
InternalServerErrorException,
NotFoundException,
} from '../../exceptions';
import { dbserver } from '../../libs/db.connect';
import { InstanceDto } from '../dto/instance.dto';
import { cache, waMonitor } from '../whatsapp.module';
import { Database, Redis, configService } from '../../config/env.config';
import { RedisCache } from '../../db/redis.client';
async function getInstance(instanceName: string) {
const db = configService.get<Database>('DATABASE');
const redisConf = configService.get<Redis>('REDIS');
try {
const db = configService.get<Database>('DATABASE');
const redisConf = configService.get<Redis>('REDIS');
const exists = !!waMonitor.waInstances[instanceName];
const exists = !!waMonitor.waInstances[instanceName];
if (redisConf.ENABLED) {
const keyExists = await cache.keyExists();
return exists || keyExists;
if (redisConf.ENABLED) {
const keyExists = await cache.keyExists();
return exists || keyExists;
}
if (db.ENABLED) {
const collection = dbserver
.getClient()
.db(db.CONNECTION.DB_PREFIX_NAME + '-instances')
.collection(instanceName);
return exists || (await collection.find({}).toArray()).length > 0;
}
return exists || existsSync(join(INSTANCE_DIR, instanceName));
} catch (error) {
throw new InternalServerErrorException(error?.toString());
}
if (db.ENABLED) {
const collection = dbserver
.getClient()
.db(db.CONNECTION.DB_PREFIX_NAME + '-instances')
.collection(instanceName);
return exists || (await collection.find({}).toArray()).length > 0;
}
return exists || existsSync(join(INSTANCE_DIR, instanceName));
}
export async function instanceExistsGuard(req: Request, _: Response, next: NextFunction) {
if (
req.originalUrl.includes('/instance/create') ||
req.originalUrl.includes('/instance/fetchInstances')
) {
if (req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) {
return next();
}
@@ -59,12 +61,11 @@ export async function instanceLoggedGuard(req: Request, _: Response, next: NextF
if (req.originalUrl.includes('/instance/create')) {
const instance = req.body as InstanceDto;
if (await getInstance(instance.instanceName)) {
throw new ForbiddenException(
`This name "${instance.instanceName}" is already in use.`,
);
throw new ForbiddenException(`This name "${instance.instanceName}" is already in use.`);
}
if (waMonitor.waInstances[instance.instanceName]) {
waMonitor.waInstances[instance.instanceName]?.removeRabbitmqQueues();
delete waMonitor.waInstances[instance.instanceName];
}
}

View File

@@ -1,16 +1,19 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
export class AuthRaw {
_id?: string;
jwt?: string;
apikey?: string;
instanceId?: string;
}
const authSchema = new Schema<AuthRaw>({
_id: { type: String, _id: true },
jwt: { type: String, minlength: 1 },
apikey: { type: String, minlength: 1 },
instanceId: { type: String, minlength: 1 },
});
export const AuthModel = dbserver?.model(AuthRaw.name, authSchema, 'authentication');

View File

@@ -0,0 +1,24 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class ChamaaiRaw {
_id?: string;
enabled?: boolean;
url?: string;
token?: string;
waNumber?: string;
answerByAudio?: boolean;
}
const chamaaiSchema = new Schema<ChamaaiRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
url: { type: String, required: true },
token: { type: String, required: true },
waNumber: { type: String, required: true },
answerByAudio: { type: Boolean, required: true },
});
export const ChamaaiModel = dbserver?.model(ChamaaiRaw.name, chamaaiSchema, 'chamaai');
export type IChamaaiModel = typeof ChamaaiModel;

View File

@@ -1,5 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
export class ChatRaw {
_id?: string;

View File

@@ -1,5 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
export class ChatwootRaw {
_id?: string;
@@ -9,6 +10,10 @@ export class ChatwootRaw {
url?: string;
name_inbox?: string;
sign_msg?: boolean;
sign_delimiter?: string;
number?: string;
reopen_conversation?: boolean;
conversation_pending?: boolean;
}
const chatwootSchema = new Schema<ChatwootRaw>({
@@ -19,11 +24,11 @@ const chatwootSchema = new Schema<ChatwootRaw>({
url: { type: String, required: true },
name_inbox: { type: String, required: true },
sign_msg: { type: Boolean, required: true },
sign_delimiter: { type: String, required: false },
number: { type: String, required: true },
reopen_conversation: { type: Boolean, required: true },
conversation_pending: { type: Boolean, required: true },
});
export const ChatwootModel = dbserver?.model(
ChatwootRaw.name,
chatwootSchema,
'chatwoot',
);
export const ChatwootModel = dbserver?.model(ChatwootRaw.name, chatwootSchema, 'chatwoot');
export type IChatwootModel = typeof ChatwootModel;

View File

@@ -1,5 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
export class ContactRaw {
_id?: string;

View File

@@ -1,6 +1,13 @@
export * from './auth.model';
export * from './chamaai.model';
export * from './chat.model';
export * from './chatwoot.model';
export * from './contact.model';
export * from './message.model';
export * from './auth.model';
export * from './proxy.model';
export * from './rabbitmq.model';
export * from './settings.model';
export * from './sqs.model';
export * from './typebot.model';
export * from './webhook.model';
export * from './chatwoot.model';
export * from './websocket.model';

View File

@@ -1,5 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
import { wa } from '../types/wa.types';
class Key {
@@ -9,6 +10,12 @@ class Key {
participant?: string;
}
class ChatwootMessage {
messageId?: number;
inboxId?: number;
conversationId?: number;
}
export class MessageRaw {
_id?: string;
key?: Key;
@@ -19,6 +26,9 @@ export class MessageRaw {
messageTimestamp?: number | Long.Long;
owner: string;
source?: 'android' | 'web' | 'ios';
source_id?: string;
source_reply_id?: string;
chatwoot?: ChatwootMessage;
}
const messageSchema = new Schema<MessageRaw>({
@@ -36,8 +46,18 @@ const messageSchema = new Schema<MessageRaw>({
source: { type: String, minlength: 3, enum: ['android', 'web', 'ios'] },
messageTimestamp: { type: Number, required: true },
owner: { type: String, required: true, minlength: 1 },
chatwoot: {
messageId: { type: Number },
inboxId: { type: Number },
conversationId: { type: Number },
},
});
messageSchema.index({ 'chatwoot.messageId': 1, owner: 1 });
messageSchema.index({ 'key.id': 1 });
messageSchema.index({ 'key.id': 1, owner: 1 });
messageSchema.index({ owner: 1 });
export const MessageModel = dbserver?.model(MessageRaw.name, messageSchema, 'messages');
export type IMessageModel = typeof MessageModel;
@@ -64,9 +84,5 @@ const messageUpdateSchema = new Schema<MessageUpdateRaw>({
owner: { type: String, required: true, min: 1 },
});
export const MessageUpModel = dbserver?.model(
MessageUpdateRaw.name,
messageUpdateSchema,
'messageUpdate',
);
export const MessageUpModel = dbserver?.model(MessageUpdateRaw.name, messageUpdateSchema, 'messageUpdate');
export type IMessageUpModel = typeof MessageUpModel;

View File

@@ -0,0 +1,18 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class ProxyRaw {
_id?: string;
enabled?: boolean;
proxy?: string;
}
const proxySchema = new Schema<ProxyRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
proxy: { type: String, required: true },
});
export const ProxyModel = dbserver?.model(ProxyRaw.name, proxySchema, 'proxy');
export type IProxyModel = typeof ProxyModel;

View File

@@ -0,0 +1,18 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class RabbitmqRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const rabbitmqSchema = new Schema<RabbitmqRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const RabbitmqModel = dbserver?.model(RabbitmqRaw.name, rabbitmqSchema, 'rabbitmq');
export type IRabbitmqModel = typeof RabbitmqModel;

View File

@@ -0,0 +1,26 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class SettingsRaw {
_id?: string;
reject_call?: boolean;
msg_call?: string;
groups_ignore?: boolean;
always_online?: boolean;
read_messages?: boolean;
read_status?: boolean;
}
const settingsSchema = new Schema<SettingsRaw>({
_id: { type: String, _id: true },
reject_call: { type: Boolean, required: true },
msg_call: { type: String, required: true },
groups_ignore: { type: Boolean, required: true },
always_online: { type: Boolean, required: true },
read_messages: { type: Boolean, required: true },
read_status: { type: Boolean, required: true },
});
export const SettingsModel = dbserver?.model(SettingsRaw.name, settingsSchema, 'settings');
export type ISettingsModel = typeof SettingsModel;

View File

@@ -0,0 +1,18 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class SqsRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const sqsSchema = new Schema<SqsRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const SqsModel = dbserver?.model(SqsRaw.name, sqsSchema, 'sqs');
export type ISqsModel = typeof SqsModel;

View File

@@ -0,0 +1,58 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
class Session {
remoteJid?: string;
sessionId?: string;
status?: string;
createdAt?: number;
updateAt?: number;
prefilledVariables?: {
remoteJid?: string;
pushName?: string;
additionalData?: { [key: string]: any };
};
}
export class TypebotRaw {
_id?: string;
enabled?: boolean;
url: string;
typebot?: string;
expire?: number;
keyword_finish?: string;
delay_message?: number;
unknown_message?: string;
listening_from_me?: boolean;
sessions?: Session[];
}
const typebotSchema = new Schema<TypebotRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
url: { type: String, required: true },
typebot: { type: String, required: true },
expire: { type: Number, required: true },
keyword_finish: { type: String, required: true },
delay_message: { type: Number, required: true },
unknown_message: { type: String, required: true },
listening_from_me: { type: Boolean, required: true },
sessions: [
{
remoteJid: { type: String, required: true },
sessionId: { type: String, required: true },
status: { type: String, required: true },
createdAt: { type: Number, required: true },
updateAt: { type: Number, required: true },
prefilledVariables: {
remoteJid: { type: String, required: false },
pushName: { type: String, required: false },
additionalData: { type: Schema.Types.Mixed, required: false },
},
},
],
});
export const TypebotModel = dbserver?.model(TypebotRaw.name, typebotSchema, 'typebot');
export type ITypebotModel = typeof TypebotModel;

View File

@@ -1,5 +1,6 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../db/db.connect';
import { dbserver } from '../../libs/db.connect';
export class WebhookRaw {
_id?: string;
@@ -7,6 +8,7 @@ export class WebhookRaw {
enabled?: boolean;
events?: string[];
webhook_by_events?: boolean;
webhook_base64?: boolean;
}
const webhookSchema = new Schema<WebhookRaw>({
@@ -14,6 +16,8 @@ const webhookSchema = new Schema<WebhookRaw>({
url: { type: String, required: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
webhook_by_events: { type: Boolean, required: true },
webhook_base64: { type: Boolean, required: true },
});
export const WebhookModel = dbserver?.model(WebhookRaw.name, webhookSchema, 'webhook');

View File

@@ -0,0 +1,18 @@
import { Schema } from 'mongoose';
import { dbserver } from '../../libs/db.connect';
export class WebsocketRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const websocketSchema = new Schema<WebsocketRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const WebsocketModel = dbserver?.model(WebsocketRaw.name, websocketSchema, 'websocket');
export type IWebsocketModel = typeof WebsocketModel;

View File

@@ -1,16 +1,14 @@
import { join } from 'path';
import { Auth, ConfigService } from '../../config/env.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { IAuthModel, AuthRaw } from '../models';
import { readFileSync } from 'fs';
import { AUTH_DIR } from '../../config/path.config';
import { join } from 'path';
import { Auth, ConfigService } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { AUTH_DIR } from '../../config/path.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { AuthRaw, IAuthModel } from '../models';
export class AuthRepository extends Repository {
constructor(
private readonly authModel: IAuthModel,
readonly configService: ConfigService,
) {
constructor(private readonly authModel: IAuthModel, readonly configService: ConfigService) {
super(configService);
this.auth = configService.get<Auth>('AUTHENTICATION');
}
@@ -21,13 +19,10 @@ export class AuthRepository extends Repository {
public async create(data: AuthRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating auth');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving auth to db');
const insert = await this.authModel.replaceOne(
{ _id: instance },
{ ...data },
{ upsert: true },
);
const insert = await this.authModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('auth saved to db: ' + insert.modifiedCount + ' auth');
return { insertCount: insert.modifiedCount };
@@ -40,9 +35,7 @@ export class AuthRepository extends Repository {
fileName: instance,
data,
});
this.logger.verbose(
'auth saved to store in path: ' + join(AUTH_DIR, this.auth.TYPE) + '/' + instance,
);
this.logger.verbose('auth saved to store in path: ' + join(AUTH_DIR, this.auth.TYPE) + '/' + instance);
this.logger.verbose('auth created');
return { insertCount: 1 };
@@ -70,4 +63,20 @@ export class AuthRepository extends Repository {
return {};
}
}
public async findInstanceNameById(instanceId: string): Promise<string | null> {
try {
this.logger.verbose('finding auth by instanceId');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding auth in db');
const response = await this.authModel.findOne({ instanceId });
return response._id;
}
this.logger.verbose('finding auth in store is not supported');
} catch (error) {
return null;
}
}
}

View File

@@ -0,0 +1,62 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ChamaaiRaw, IChamaaiModel } from '../models';
export class ChamaaiRepository extends Repository {
constructor(private readonly chamaaiModel: IChamaaiModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('ChamaaiRepository');
public async create(data: ChamaaiRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating chamaai');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving chamaai to db');
const insert = await this.chamaaiModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('chamaai saved to db: ' + insert.modifiedCount + ' chamaai');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving chamaai to store');
this.writeStore<ChamaaiRaw>({
path: join(this.storePath, 'chamaai'),
fileName: instance,
data,
});
this.logger.verbose('chamaai saved to store in path: ' + join(this.storePath, 'chamaai') + '/' + instance);
this.logger.verbose('chamaai created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<ChamaaiRaw> {
try {
this.logger.verbose('finding chamaai');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding chamaai in db');
return await this.chamaaiModel.findOne({ _id: instance });
}
this.logger.verbose('finding chamaai in store');
return JSON.parse(
readFileSync(join(this.storePath, 'chamaai', instance + '.json'), {
encoding: 'utf-8',
}),
) as ChamaaiRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -1,29 +1,23 @@
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { opendirSync, readFileSync, rmSync } from 'fs';
import { ChatRaw, IChatModel } from '../models';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ChatRaw, IChatModel } from '../models';
export class ChatQuery {
where: ChatRaw;
}
export class ChatRepository extends Repository {
constructor(
private readonly chatModel: IChatModel,
private readonly configService: ConfigService,
) {
constructor(private readonly chatModel: IChatModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('ChatRepository');
public async insert(
data: ChatRaw[],
instanceName: string,
saveDb = false,
): Promise<IInsert> {
public async insert(data: ChatRaw[], instanceName: string, saveDb = false): Promise<IInsert> {
this.logger.verbose('inserting chats');
if (data.length === 0) {
this.logger.verbose('no chats to insert');
@@ -53,10 +47,7 @@ export class ChatRepository extends Repository {
data: chat,
});
this.logger.verbose(
'chats saved to store in path: ' +
join(this.storePath, 'chats', instanceName) +
'/' +
chat.id,
'chats saved to store in path: ' + join(this.storePath, 'chats', instanceName) + '/' + chat.id,
);
});
@@ -89,10 +80,9 @@ export class ChatRepository extends Repository {
if (dirent.isFile()) {
chats.push(
JSON.parse(
readFileSync(
join(this.storePath, 'chats', query.where.owner, dirent.name),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'chats', query.where.owner, dirent.name), {
encoding: 'utf-8',
}),
),
);
}

View File

@@ -1,15 +1,13 @@
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ConfigService } from '../../config/env.config';
import { join } from 'path';
import { readFileSync } from 'fs';
import { IChatwootModel, ChatwootRaw } from '../models';
import { join } from 'path';
import { ConfigService } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ChatwootRaw, IChatwootModel } from '../models';
export class ChatwootRepository extends Repository {
constructor(
private readonly chatwootModel: IChatwootModel,
private readonly configService: ConfigService,
) {
constructor(private readonly chatwootModel: IChatwootModel, private readonly configService: ConfigService) {
super(configService);
}
@@ -20,15 +18,9 @@ export class ChatwootRepository extends Repository {
this.logger.verbose('creating chatwoot');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving chatwoot to db');
const insert = await this.chatwootModel.replaceOne(
{ _id: instance },
{ ...data },
{ upsert: true },
);
const insert = await this.chatwootModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose(
'chatwoot saved to db: ' + insert.modifiedCount + ' chatwoot',
);
this.logger.verbose('chatwoot saved to db: ' + insert.modifiedCount + ' chatwoot');
return { insertCount: insert.modifiedCount };
}
@@ -40,12 +32,7 @@ export class ChatwootRepository extends Repository {
data,
});
this.logger.verbose(
'chatwoot saved to store in path: ' +
join(this.storePath, 'chatwoot') +
'/' +
instance,
);
this.logger.verbose('chatwoot saved to store in path: ' + join(this.storePath, 'chatwoot') + '/' + instance);
this.logger.verbose('chatwoot created');
return { insertCount: 1 };

View File

@@ -1,29 +1,23 @@
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { ContactRaw, IContactModel } from '../models';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { ContactRaw, IContactModel } from '../models';
export class ContactQuery {
where: ContactRaw;
}
export class ContactRepository extends Repository {
constructor(
private readonly contactModel: IContactModel,
private readonly configService: ConfigService,
) {
constructor(private readonly contactModel: IContactModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('ContactRepository');
public async insert(
data: ContactRaw[],
instanceName: string,
saveDb = false,
): Promise<IInsert> {
public async insert(data: ContactRaw[], instanceName: string, saveDb = false): Promise<IInsert> {
this.logger.verbose('inserting contacts');
if (data.length === 0) {
@@ -54,10 +48,7 @@ export class ContactRepository extends Repository {
data: contact,
});
this.logger.verbose(
'contacts saved to store in path: ' +
join(this.storePath, 'contacts', instanceName) +
'/' +
contact.id,
'contacts saved to store in path: ' + join(this.storePath, 'contacts', instanceName) + '/' + contact.id,
);
});
@@ -74,11 +65,7 @@ export class ContactRepository extends Repository {
}
}
public async update(
data: ContactRaw[],
instanceName: string,
saveDb = false,
): Promise<IInsert> {
public async update(data: ContactRaw[], instanceName: string, saveDb = false): Promise<IInsert> {
try {
this.logger.verbose('updating contacts');
@@ -119,10 +106,7 @@ export class ContactRepository extends Repository {
data: contact,
});
this.logger.verbose(
'contacts updated in store in path: ' +
join(this.storePath, 'contacts', instanceName) +
'/' +
contact.id,
'contacts updated in store in path: ' + join(this.storePath, 'contacts', instanceName) + '/' + contact.id,
);
});
@@ -154,15 +138,9 @@ export class ContactRepository extends Repository {
this.logger.verbose('finding contacts in store by id');
contacts.push(
JSON.parse(
readFileSync(
join(
this.storePath,
'contacts',
query.where.owner,
query.where.id + '.json',
),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'contacts', query.where.owner, query.where.id + '.json'), {
encoding: 'utf-8',
}),
),
);
} else {
@@ -175,10 +153,9 @@ export class ContactRepository extends Repository {
if (dirent.isFile()) {
contacts.push(
JSON.parse(
readFileSync(
join(this.storePath, 'contacts', query.where.owner, dirent.name),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'contacts', query.where.owner, dirent.name), {
encoding: 'utf-8',
}),
),
);
}

View File

@@ -1,9 +1,10 @@
import { ConfigService, StoreConf } from '../../config/env.config';
import { join } from 'path';
import { IMessageModel, MessageRaw } from '../models';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { IMessageModel, MessageRaw } from '../models';
export class MessageQuery {
where: MessageRaw;
@@ -11,20 +12,13 @@ export class MessageQuery {
}
export class MessageRepository extends Repository {
constructor(
private readonly messageModel: IMessageModel,
private readonly configService: ConfigService,
) {
constructor(private readonly messageModel: IMessageModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('MessageRepository');
public async insert(
data: MessageRaw[],
instanceName: string,
saveDb = false,
): Promise<IInsert> {
public async insert(data: MessageRaw[], instanceName: string, saveDb = false): Promise<IInsert> {
this.logger.verbose('inserting messages');
if (!Array.isArray(data) || data.length === 0) {
@@ -74,10 +68,7 @@ export class MessageRepository extends Repository {
data: message,
});
this.logger.verbose(
'messages saved to store in path: ' +
join(this.storePath, 'messages', instanceName) +
'/' +
message.key.id,
'messages saved to store in path: ' + join(this.storePath, 'messages', instanceName) + '/' + message.key.id,
);
});
@@ -100,11 +91,13 @@ export class MessageRepository extends Repository {
this.logger.verbose('finding messages');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding messages in db');
if (query?.where?.key) {
for (const [k, v] of Object.entries(query.where.key)) {
query.where['key.' + k] = v;
for (const [o, p] of Object.entries(query?.where)) {
if (typeof p === 'object' && p !== null && !Array.isArray(p)) {
for (const [k, v] of Object.entries(p)) {
query.where[`${o}.${k}`] = v;
}
delete query.where[o];
}
delete query?.where?.key;
}
return await this.messageModel
@@ -119,15 +112,9 @@ export class MessageRepository extends Repository {
this.logger.verbose('finding messages in store by id');
messages.push(
JSON.parse(
readFileSync(
join(
this.storePath,
'messages',
query.where.owner,
query.where.key.id + '.json',
),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'messages', query.where.owner, query.where.key.id + '.json'), {
encoding: 'utf-8',
}),
),
);
} else {
@@ -140,10 +127,9 @@ export class MessageRepository extends Repository {
if (dirent.isFile()) {
messages.push(
JSON.parse(
readFileSync(
join(this.storePath, 'messages', query.where.owner, dirent.name),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'messages', query.where.owner, dirent.name), {
encoding: 'utf-8',
}),
),
);
}
@@ -160,4 +146,55 @@ export class MessageRepository extends Repository {
return [];
}
}
public async update(data: MessageRaw[], instanceName: string, saveDb?: boolean): Promise<IInsert> {
try {
if (this.dbSettings.ENABLED && saveDb) {
this.logger.verbose('updating messages in db');
const messages = data.map((message) => {
return {
updateOne: {
filter: { 'key.id': message.key.id },
update: { ...message },
},
};
});
const { nModified } = await this.messageModel.bulkWrite(messages);
this.logger.verbose('messages updated in db: ' + nModified + ' messages');
return { insertCount: nModified };
}
this.logger.verbose('updating messages in store');
const store = this.configService.get<StoreConf>('STORE');
if (store.MESSAGES) {
this.logger.verbose('updating messages in store');
data.forEach((message) => {
this.writeStore({
path: join(this.storePath, 'messages', instanceName),
fileName: message.key.id,
data: message,
});
this.logger.verbose(
'messages updated in store in path: ' +
join(this.storePath, 'messages', instanceName) +
'/' +
message.key.id,
);
});
this.logger.verbose('messages updated in store: ' + data.length + ' messages');
return { insertCount: data.length };
}
this.logger.verbose('messages not updated');
return { insertCount: 0 };
} catch (error) {
this.logger.error(error);
}
}
}

View File

@@ -1,9 +1,10 @@
import { ConfigService, StoreConf } from '../../config/env.config';
import { IMessageUpModel, MessageUpdateRaw } from '../models';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { join } from 'path';
import { opendirSync, readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService, StoreConf } from '../../config/env.config';
import { Logger } from '../../config/logger.config';
import { IInsert, Repository } from '../abstract/abstract.repository';
import { IMessageUpModel, MessageUpdateRaw } from '../models';
export class MessageUpQuery {
where: MessageUpdateRaw;
@@ -11,20 +12,13 @@ export class MessageUpQuery {
}
export class MessageUpRepository extends Repository {
constructor(
private readonly messageUpModel: IMessageUpModel,
private readonly configService: ConfigService,
) {
constructor(private readonly messageUpModel: IMessageUpModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('MessageUpRepository');
public async insert(
data: MessageUpdateRaw[],
instanceName: string,
saveDb?: boolean,
): Promise<IInsert> {
public async insert(data: MessageUpdateRaw[], instanceName: string, saveDb?: boolean): Promise<IInsert> {
this.logger.verbose('inserting message up');
if (data.length === 0) {
@@ -54,10 +48,7 @@ export class MessageUpRepository extends Repository {
data: update,
});
this.logger.verbose(
'message up saved to store in path: ' +
join(this.storePath, 'message-up', instanceName) +
'/' +
update.id,
'message up saved to store in path: ' + join(this.storePath, 'message-up', instanceName) + '/' + update.id,
);
});
@@ -91,42 +82,32 @@ export class MessageUpRepository extends Repository {
messageUpdate.push(
JSON.parse(
readFileSync(
join(
this.storePath,
'message-up',
query.where.owner,
query.where.id + '.json',
),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'message-up', query.where.owner, query.where.id + '.json'), {
encoding: 'utf-8',
}),
),
);
} else {
this.logger.verbose('finding message up in store by owner');
const openDir = opendirSync(
join(this.storePath, 'message-up', query.where.owner),
{ encoding: 'utf-8' },
);
const openDir = opendirSync(join(this.storePath, 'message-up', query.where.owner), {
encoding: 'utf-8',
});
for await (const dirent of openDir) {
if (dirent.isFile()) {
messageUpdate.push(
JSON.parse(
readFileSync(
join(this.storePath, 'message-up', query.where.owner, dirent.name),
{ encoding: 'utf-8' },
),
readFileSync(join(this.storePath, 'message-up', query.where.owner, dirent.name), {
encoding: 'utf-8',
}),
),
);
}
}
}
this.logger.verbose(
'message up found in store: ' + messageUpdate.length + ' message up',
);
this.logger.verbose('message up found in store: ' + messageUpdate.length + ' message up');
return messageUpdate
.sort((x, y) => {
return y.datetime - x.datetime;

Some files were not shown because too many files have changed in this diff Show More