Compare commits

...
157 Commits
Author SHA1 Message Date
allburov 5e2de1d47d [core] Bump to 2024.2.4
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-02-25 17:57:29 +07:00
allburov 591ca51104 [core] add GET /health 2024-02-25 17:56:58 +07:00
allburov b210841158 [core] Fix documentation for message.revoked 2024-02-21 10:31:54 +07:00
allburov a223a3985b [core] Self-hosted solution 2024-02-19 14:52:23 +07:00
allburov 8baa6a73cd [core] Self-hosted 2024-02-19 14:52:07 +07:00
allburov 508efac2ea [core] Add links on index 2024-02-19 14:51:59 +07:00
allburov b6eed9e228 [core] Rewrite tiers 2024-02-19 14:46:17 +07:00
allburov b62cad07f0 [core] Icons on main page 2024-02-19 14:28:18 +07:00
allburov 6d552d27ac [core] Bold 2024-02-19 14:11:24 +07:00
allburov 39d0f2a060 [core] Fix doc about WEBJS
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
2024-02-18 20:22:45 +07:00
allburov 0b03abee91 [core] Fix delete file when it doesn't exist anymore 2024-02-18 20:22:41 +07:00
allburov b4fb69d0ee [core] Use extends instead of implements for LocalStoreCore.ts 2024-02-18 19:55:54 +07:00
allburov 5b9ed029b3 [core] NOWEB - fix stop session 2024-02-18 19:42:32 +07:00
allburov c29397371b [core] Use network host in mongo example 2024-02-18 19:37:45 +07:00
allburov fe47e27788 [core] Fix yarn file 2024-02-18 19:37:33 +07:00
allburov a14c702c79 [core] Bump to 2024.2.3 2024-02-18 19:25:12 +07:00
allburov fe4246036d [core] Support MongoDB 2024-02-18 19:21:19 +07:00
allburov 074063b814 [core] Fix set presence documentation 2024-02-12 11:34:15 +07:00
allburov 0271a8b721 [core] Fix changelog version
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-02-10 15:09:16 +07:00
allburov 08617383be [core] Listen for page close event
fix #262
2024-02-10 15:08:03 +07:00
allburov 3840459b0a [core] add noweb engine performance 2024-02-09 15:11:36 +07:00
Sunil Sankar aee7ac28bc [core] Fix the image name (#260)
The image name is wrongly mentioned
2024-02-05 14:02:21 +07:00
allburov 9e6cd39b2d [core] fix types
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
2024-02-01 16:23:42 +03:00
allburov 8898429046 [core] Update engines 2024-02-01 16:23:36 +03:00
allburov a74def6dbd [core] Add Patron Portal link 2024-02-01 16:15:42 +03:00
allburov 9f783cd35e [core] Add Patron Portal link 2024-02-01 16:14:04 +03:00
allburov 9d2f061d81 [core] Pass other parameters to requestCode, like locale 2024-01-27 15:11:16 +07:00
allburov a6045b2d54 [core] Add badge example 2024-01-27 13:58:50 +07:00
allburov 6142b2b564 [core] Link fixes 2024-01-27 13:56:30 +07:00
allburov ed53ccb919 [core] One more PRO tier perk 2024-01-27 13:54:38 +07:00
allburov 1ab45c6cfd [core] Add MOBILE engine note 2024-01-27 13:40:10 +07:00
allburov c2fdb090e1 [core] build via ssh 2024-01-27 13:40:10 +07:00
allburov a10b47eb7e [core] Dockerfile - mount ssh in case of private repositories 2024-01-27 13:40:10 +07:00
allburov 7b234e2e37 [core] make build-ssh 2024-01-27 13:40:10 +07:00
allburov 90d45a4698 [core] Add captcha API endpoints 2024-01-27 13:40:10 +07:00
allburov 5e40b70e19 [core] NOWEB - Listen connection events from the start 2024-01-27 13:40:10 +07:00
allburov a27d0c3efb [core] Add MOBILE engine 2024-01-27 13:40:10 +07:00
allburov 46ed506b35 [core] start stop typing in the example 2024-01-27 13:01:52 +07:00
allburov 0ad813a1fe [core] Add links 2024-01-08 18:58:44 +07:00
allburov e57e42f47a [core] Add tiers 2024-01-08 18:53:31 +07:00
Alex cc58157d37 [core] Add badges for patreons 2024-01-08 11:55:34 +07:00
Alex 9b5bb0a339 [core] Create gh-team-labels.yml 2024-01-07 16:34:03 +07:00
Alex 84ebbea287 Delete .github/.github/gh-team-labels.yml 2024-01-07 16:33:44 +07:00
Alex 1c2021f54b Update gh-team-labels.yml 2024-01-07 16:33:09 +07:00
Alex 98a7f00d7d [core] Update gh-team-labels.yml 2024-01-07 16:29:14 +07:00
Alex 60d97d0e67 [core] Create gh-team-labels.yml 2024-01-07 16:28:17 +07:00
allburov 03f4a07cbe [core] Update NOWEB 2023-12-26 18:33:53 +07:00
allburov 3fbe526793 [core] log phone 2023-12-26 17:54:34 +07:00
allburov a892f03382 [core] Bump version to 2023.12.3 2023-12-26 17:20:12 +07:00
allburov 8db69f6e69 [core] Update WEBJS 2023-12-26 17:20:00 +07:00
allburov f9037ff9fc [core] Add github link to authroize-code 2023-12-26 17:10:37 +07:00
allburov 366ddffa2b [core] Add more about How to not get Banned 2023-12-22 16:05:25 +07:00
allburov b8468588de [core] Add note about wa.me link 2023-12-18 21:12:43 +07:00
allburov 62dd6f7f4a [core] No --rm 2023-12-11 13:26:33 +07:00
allburov 858202f1bb [core] Add chatId to changelog 2023-12-02 16:36:20 +07:00
allburov db7900dc26 [core] Bump version to 2023.12.2 2023-12-02 16:34:20 +07:00
allburov aa87e437dc [core] Add note for Brazilian phone number 2023-12-02 16:33:50 +07:00
allburov 741e5e86f8 [core] Reformat send messages documentation 2023-12-02 16:28:44 +07:00
allburov 390a171891 [core] Document check exists changes 2023-12-02 16:23:00 +07:00
allburov 1fc5e2b47c [core] Add chatId to check exists result 2023-12-02 16:13:23 +07:00
allburov 8926dc7cc6 [core] update swagger 2023-12-01 09:38:52 +07:00
allburov 5c3d3c0d70 [core] No null in swagger 2023-12-01 09:38:52 +07:00
allburov 41b29cbf60 [core] Update swagger
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2023-12-01 09:34:25 +07:00
allburov 44463c199a [core] Try to fix swagger for redoc 2023-12-01 09:33:56 +07:00
allburov 9071adcdcc [core] Update NOWEB engine 2023-12-01 09:32:11 +07:00
allburov 21cd92ca13 [core] Update WEBJS engine 2023-12-01 09:30:02 +07:00
allburov d8a3e8dc43 [core] Bump version to 2023.12.1 2023-12-01 09:25:23 +07:00
allburov 3f5707952c [core] Update swagger 2023-12-01 09:25:06 +07:00
allburov 38a9590be0 [core] Add screenshot and QR to changelog
Fix #177
2023-11-30 18:01:51 +07:00
allburov a7ce117b87 [core] VENOM supports /qr 2023-11-30 18:01:51 +07:00
allburov c3b24a243c [core] document QR code formats 2023-11-30 18:01:51 +07:00
allburov cb2c11df43 [core] screenshot base64 2023-11-30 18:01:50 +07:00
allburov 98f88dcf68 [core] screenshot doc 2023-11-30 18:01:50 +07:00
allburov 9fb12e0e23 [core] Add base64 to screenshot 2023-11-30 18:01:49 +07:00
allburov 0ca106f16b [core] Fix swagger 2023-11-30 18:01:49 +07:00
allburov 33210c6374 [core] Get raw QR value 2023-11-30 18:01:49 +07:00
allburov 045ab67f5d [core] Add BufferResponseInterceptor 2023-11-30 18:01:49 +07:00
allburov 19259c93ea [core] Return json or binary based on Accept header 2023-11-30 18:01:49 +07:00
allburov 9b6784a018 [core] Use "default" session by default 2023-11-30 18:01:49 +07:00
allburov 2fe3706e9c [core] Add base64 file 2023-11-30 18:01:49 +07:00
allburov a4e310a7f8 [core] Get screenshot return only buffer 2023-11-30 18:01:49 +07:00
allburov 802da9f3b2 [core] Use StreamableFile 2023-11-30 18:01:49 +07:00
allburov 0692979b19 [core] Add swagger to config page 2023-11-25 20:43:05 +07:00
allburov fb8b146bc4 [core] Add hide swagger doc 2023-11-25 20:33:35 +07:00
allburov fdbaa43ec9 [core] Add WHATSAPP_SWAGGER_ENABLED environment variable 2023-11-25 20:33:35 +07:00
allburov 4a807530c1 [core] Remove unused method 2023-11-25 20:33:35 +07:00
allburov 84784faa1e [core] eslint no warnings 2023-11-25 20:03:34 +07:00
allburov bd40978dee [core] Apply prettier to other files too 2023-11-25 19:56:32 +07:00
allburov d4d94ffe0e [core] Add empty line linter 2023-11-25 19:44:16 +07:00
allburov d984382a33 [core] Run linter in pre-commit hook 2023-11-25 19:41:41 +07:00
allburov 02d05812d2 [core] Update prettier 2023-11-25 19:09:25 +07:00
allburov 1dbf568bac [core] Add more props 2023-11-25 19:09:25 +07:00
allburov 6bc3aed348 [core] print width 2023-11-25 19:03:58 +07:00
allburov c1e8e0f09c [core] tab 2023-11-25 19:03:58 +07:00
allburov 8f8bcfc474 [core] Don't use tabs 2023-11-25 19:03:58 +07:00
allburov b386df982d [core] bracketSpacing 2023-11-25 19:03:58 +07:00
allburov fa846ddf9b [core] arrowParens always 2023-11-25 19:03:58 +07:00
allburov 16685ed8ea [core] Add endOfLine 2023-11-25 19:03:53 +07:00
allburov 4addccbd55 [core] Update node version in nvm 2023-11-25 19:03:53 +07:00
allburov e9a20c4326 [core] Run eslint 2023-11-25 19:03:53 +07:00
Alex f073aeef13 Update issue templates 2023-11-25 18:43:22 +07:00
allburov eb08739eea [core] Send 404 if file does not exist
fix #134
2023-11-25 18:16:51 +07:00
allburov aff3b01e39 [core] Hide mentions 2023-11-25 18:03:49 +07:00
allburov 2d64b26e86 [core] Hide mentions from send message 2023-11-25 17:37:38 +07:00
allburov 7b7bd02503 [core] Media improvements
- Disable downloading files
- Add 'media' field
2023-11-25 17:25:19 +07:00
allburov 7904516c97 [core] Changelog for filename 2023-11-24 17:47:29 +07:00
allburov 6e0bafdd89 [core] Add doc about new filename field 2023-11-24 17:47:29 +07:00
allburov 2b1e605e5f [core] Add filename property - NOWEB 2023-11-24 17:47:29 +07:00
allburov f454310a09 [core] Add filename property - WEBJS 2023-11-24 17:47:29 +07:00
allburov b6579b5b96 [core] Add filename property 2023-11-24 17:47:29 +07:00
allburov 4ef06d7b92 [docs] Add doc for GET /info-admin-only 2023-11-20 16:25:21 +07:00
allburov e0c594a71b [core] Add GET /info-admin-only 2023-11-20 16:23:23 +07:00
allburov a48d386d8b [core] Update WEBJS 2023-11-20 16:23:21 +07:00
allburov d592858a90 [core] Add name to job 2023-11-05 20:19:42 +07:00
allburov a3cb3e983a [core] No chrome on arm
Release / docker-build (chrome, amd64, buildjet-4vcpu-ubuntu-2204, chrome) (push) Waiting to run
Release / docker-build (chromium, amd64, buildjet-4vcpu-ubuntu-2204, latest) (push) Waiting to run
Release / docker-build (chromium, linux/arm64, buildjet-4vcpu-ubuntu-2204-arm, arm) (push) Waiting to run
Release / docker-build (none, amd64, buildjet-4vcpu-ubuntu-2204, noweb) (push) Waiting to run
Release / docker-build (none, linux/arm64, buildjet-4vcpu-ubuntu-2204-arm, noweb-arm) (push) Waiting to run
2023-11-05 20:16:02 +07:00
allburov 4eb9029b2c [core] Add build-all 2023-11-05 18:28:34 +07:00
allburov b3835b0aa0 [core] echo USE_BROWSER 2023-11-05 18:28:29 +07:00
allburov b2db58a922 [core] Document docker images 2023-11-05 18:24:03 +07:00
allburov acb6b8e0d3 [core] Install fonts if using a browser 2023-11-05 18:14:28 +07:00
allburov 21c6e1e860 [core] Add chrome\noweb builds 2023-11-05 18:10:11 +07:00
allburov 571b65c423 [core] Specify browser args 2023-11-05 18:08:33 +07:00
allburov 1631a62abe [core] Bump version to 2023.11.1 2023-11-05 18:01:09 +07:00
allburov e88a7ca8ce [core] Use github actions matrix 2023-11-05 17:59:44 +07:00
allburov d54f64a9cc [core] Add changelog record for send video 2023-11-05 17:44:30 +07:00
allburov 03dbd5db82 [core] Add docs for send video 2023-11-05 17:31:43 +07:00
allburov 2446c292bf [core] Add /sendVideo API 2023-11-05 17:31:40 +07:00
allburov 5ab99dfd69 [core] Add video example 2023-11-05 16:04:13 +07:00
allburov 605f46fda8 [core] Bump version to 2023.10.18
Release / docker-amd64 (push) Waiting to run
Release / docker-arm (push) Waiting to run
2023-10-18 14:55:32 +07:00
allburov e53f1eafe8 [core] up WEBJS engine 2023-10-18 14:55:16 +07:00
allburov 1457185e84 [core] Add session.status as default event 2023-10-15 00:18:00 +07:00
allburov ad43bec18d [core] Bump version to 2023.10.15 2023-10-15 00:03:16 +07:00
allburov c0a4b223ea [core] add session.status 2023-10-15 00:03:13 +07:00
allburov 65917e1957 [core] Add types for environment (aka version) 2023-10-13 18:54:30 +07:00
allburov a19cede60d [core] Document revoked webhook in swagger 2023-10-13 18:54:30 +07:00
allburov a3ead95ea4 [core] Add engine to version (fix #156) 2023-10-13 18:54:30 +07:00
allburov c46bc1b923 [core] Add me and version to webhook 2023-10-12 16:54:45 +07:00
allburov b327212cbe [core] Bump versio nto 2023.10.12 2023-10-12 16:40:10 +07:00
allburov 4f348c7e48 [core][webjs] Add message.revoked (fix #190) 2023-10-12 16:38:43 +07:00
allburov f2d0001b11 [core] Update openapi.json 2023-09-18 11:55:50 +07:00
allburov 66a224a0e3 [core] Patreon first 2023-09-18 11:54:49 +07:00
allburov 1fa1206568 [core] Adjust header for swagger 2023-09-18 11:54:41 +07:00
allburov 87eea28ac2 [core] Mention feature matrix in docs 2023-09-18 11:42:26 +07:00
allburov 29ca0217b3 [core] Remove "only" engines 2023-09-18 11:31:53 +07:00
allburov 306f75ff3b [core] Fix text 2023-09-18 11:20:29 +07:00
allburov 6ecb203570 [core] Add webhooks 2023-09-18 11:17:22 +07:00
allburov 2e7a3a6b61 [core] Add presence endpoints 2023-09-18 11:13:18 +07:00
allburov 86bc4a92ba [core] Add groups endpoints 2023-09-18 11:11:48 +07:00
allburov f652277e18 [core] Init features by engines 2023-09-18 11:05:53 +07:00
allburov 14a3535439 [core] throw NotImplemented by default 2023-09-18 10:39:21 +07:00
allburov edce7424de [core] Update static swagger for site 2023-09-17 19:09:45 +07:00
allburov 0fa121bbe2 [core] Update openapi.json 2023-09-17 18:50:37 +07:00
allburov 9c046a92be [core] Document webhooks in Swagger 2023-09-17 18:48:23 +07:00
allburov e4506e14da [core] Update next/swagger 2023-09-17 17:31:26 +07:00
allburov 515a00346c [core] Adjust current engine doc 2023-09-17 16:44:06 +07:00
allburov 399e27e24e [core] Name endpoints and webhooks 2023-09-17 15:59:27 +07:00
allburov 9413376138 [core] Bump WAHA version 2023-09-11 15:26:24 +07:00
allburov 3caec14783 [core] Update swagger 2023-09-11 15:26:14 +07:00
124 changed files with 4662 additions and 13188 deletions

No files matched your search

+25 -22
View File
@@ -1,33 +1,36 @@
module.exports = {
parser: "@typescript-eslint/parser",
parser: '@typescript-eslint/parser',
parserOptions: {
project: "tsconfig.json",
sourceType: "module"
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: [
"@typescript-eslint/eslint-plugin",
"simple-import-sort"
],
plugins: ['@typescript-eslint/eslint-plugin', 'simple-import-sort'],
extends: [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
],
root: true,
env: {
node: true,
jest: true
jest: true,
},
rules: {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/ban-ts-comment": "off",
}
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'lines-between-class-members': [
'error',
'always',
{ exceptAfterSingleLine: true },
],
},
};
+61
View File
@@ -0,0 +1,61 @@
---
name: Bug report
about: Create a report to help us improve
title: '[BUG][WEBJS] - '
labels: bug
assignees: ''
---
**Describe the bug**
> A clear and concise description of what the bug is. Feel free to remove
> sections that you don't feel to make the text shorter!
**Version**
```json
{
"version": "2023.11.1",
"engine": "NOWEB",
"tier": "PLUS",
"browser": "/usr/bin/google-chrome-stable"
}
```
> You can get the WAHA version by calling `GET /api/version` Try to update to
> [the latest version](https://github.com/devlikeapro/whatsapp-http-api/releases)
> before creating an issue!
**To Reproduce** Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
> A clear and concise description of what you expected to happen.
**Engine** I'm using **WEBJS** engine.
> If you set `WHATSAPP_DEFAULT_ENGINE` explicitly to
> [one of the engine](https://waha.devlike.pro/docs/how-to/engines/) - please
> provide that information here and in the issue title.
**Requests - Responses**
> Please attach all sent requests, responses that you sent.
**Docker Logs**
> Collect and attach related docker logs if you have any
> https://waha.devlike.pro/docs/how-to/deploy/#viewing-the-logs
**Screenshots**
> If applicable, add screenshots to help explain your problem.
**Additional context**
> Add any other context about the problem here.
+24
View File
@@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: '[Feature Request]'
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.** I'm always
frustrated when [...]
> A clear and concise description of what the problem is. Ex.
**Describe the solution you'd like**
> A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
> A clear and concise description of any alternative solutions or features
> you've considered.
**Additional context** Add any other context or screenshots about the feature
request here.
+15
View File
@@ -0,0 +1,15 @@
ignore:
teams:
- no-labels
users:
- allburov
teamLabels:
- team: waha-patrons-pro
label: patron:PRO
comment: '[![patron:PRO](https://img.shields.io/badge/patron-PRO-188a42)](https://waha.devlike.pro/docs/how-to/plus-version/#tiers)'
- team: waha-patrons-advanced
label: patron:ADVANCED
comment: '[![patron:ADVANCED](https://img.shields.io/badge/patron-ADVANCED-4cd07d)](https://waha.devlike.pro/docs/how-to/plus-version/#tiers)'
- team: waha-patrons-plus
label: patron:PLUS
comment: '[![patron:PLUS](https://img.shields.io/badge/patron-PLUS-a0e6ba)](https://waha.devlike.pro/docs/how-to/plus-version/#tiers)'
+39 -40
View File
@@ -3,11 +3,43 @@ name: Release
on:
push:
tags:
- "*"
- '*'
jobs:
docker-amd64:
runs-on: buildjet-4vcpu-ubuntu-2204
docker-build:
runs-on: ${{ matrix.runner }}
name: ${{ matrix.platform }} - ${{ matrix.browser }} - ${{ matrix.tag }}
strategy:
matrix:
include:
# Chromium
- runner: 'buildjet-4vcpu-ubuntu-2204'
tag: 'latest'
platform: 'amd64'
browser: 'chromium'
- runner: 'buildjet-4vcpu-ubuntu-2204-arm'
tag: 'arm'
platform: 'linux/arm64'
browser: 'chromium'
# Chrome
- runner: 'buildjet-4vcpu-ubuntu-2204'
tag: 'chrome'
platform: 'amd64'
browser: 'chrome'
# Chrome is not supported on arm64
# - runner: "buildjet-4vcpu-ubuntu-2204-arm"
# tag: "chrome-arm"
# platform: "linux/arm64"
# browser: "chrome"
# No browser
- runner: 'buildjet-4vcpu-ubuntu-2204'
tag: 'noweb'
platform: 'amd64'
browser: 'none'
- runner: 'buildjet-4vcpu-ubuntu-2204-arm'
tag: 'noweb-arm'
platform: 'linux/arm64'
browser: 'none'
steps:
- name: Checkout
@@ -22,7 +54,7 @@ jobs:
images: ${{ secrets.DOCKER_IMAGE }}
flavor: latest=false
tags: |
type=raw,value=latest
type=raw,value=${{ matrix.tag }}
- name: Login to image repository
if: github.ref_type == 'tag'
@@ -36,42 +68,9 @@ jobs:
with:
context: .
file: Dockerfile
platforms: 'amd64'
push: ${{ github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
docker-arm:
runs-on: buildjet-4vcpu-ubuntu-2204-arm
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ secrets.DOCKER_IMAGE }}
flavor: latest=false
tags: |
type=raw,value=arm
- name: Login to image repository
if: github.ref_type == 'tag'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
platforms: 'linux/arm64'
platforms: ${{ matrix.platform }}
build-args: |
USE_BROWSER=${{ matrix.browser }}
push: ${{ github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+1 -1
View File
@@ -1 +1 @@
v18.12.0
v20.5.0
+16 -4
View File
@@ -1,13 +1,25 @@
repos:
- repo: https://github.com/pre-commit/mirrors-prettier
rev: 'v2.7.1'
- repo: local
hooks:
- id: prettier
types_or: [ javascript, ts ]
- id: lint
name: lint
language: system
entry: bash -c '$HOME/.nvm/nvm-exec npm run lint'
pass_filenames: false
files: |
(?x)^(
src/.*|
)$
- repo: https://github.com/pre-commit/mirrors-prettier
rev: 'v3.1.0'
hooks:
- id: prettier
exclude: |
(?x)^(
docs/.*|
README.md|
)$
- repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs
rev: v1.1.2
hooks:
+11 -2
View File
@@ -1,4 +1,13 @@
{
"singleQuote": true,
"trailingComma": "all"
}
"trailingComma": "all",
"endOfLine": "auto",
"arrowParens": "always",
"bracketSpacing": true,
"useTabs": false,
"tabWidth": 2,
"semi": true,
"quoteProps": "as-needed",
"proseWrap": "always",
"printWidth": 80
}
+3 -1
View File
@@ -1,2 +1,4 @@
# Changelog
You can find changelog on [the changelog page](https://waha.devlike.pro/docs/help/changelog/)
You can find changelog on
[the changelog page](https://waha.devlike.pro/docs/help/changelog/)
+14 -5
View File
@@ -5,16 +5,21 @@ FROM node:20-bullseye as build
ENV PUPPETEER_SKIP_DOWNLOAD=True
# npm packages
RUN apt-get update \
&& apt-get install -y openssh-client
RUN apt install openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
WORKDIR /src
COPY package.json .
COPY yarn.lock .
RUN yarn set version 3.6.3
RUN yarn install
RUN --mount=type=ssh yarn install
# App
WORKDIR /src
ADD . /src
RUN yarn install
RUN --mount=type=ssh yarn install
RUN yarn build && find ./dist -name "*.d.ts" -delete
#
@@ -24,11 +29,15 @@ FROM node:20-bullseye as release
ENV PUPPETEER_SKIP_DOWNLOAD=True
ARG USE_BROWSER=chromium
# Install fonts
RUN apt-get update \
RUN echo "USE_BROWSER=$USE_BROWSER"
# Install fonts if using either chromium or chrome
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
apt-get update \
&& apt-get install -y fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/*; \
fi
# Install Chromium
RUN if [ "$USE_BROWSER" = "chromium" ]; then \
+15
View File
@@ -1,9 +1,24 @@
build:
docker build . -t devlikeapro/whatsapp-http-api
build-chrome:
docker build . -t devlikeapro/whatsapp-http-api:chrome --build-arg USE_BROWSER=chrome
build-noweb:
docker build . -t devlikeapro/whatsapp-http-api:noweb --build-arg USE_BROWSER=none
build-all: build build-chrome build-noweb
build-plus:
docker build . -t devlikeapro/whatsapp-http-api-plus
build-ssh:
# check IMAGE provided
@[ "${IMAGE}" ] || ( echo "Add APP: make build-ssh image=devlikeapro/whatsapp-http-api"; exit 1 );
eval $(ssh-agent) && \
ssh-add ~/.ssh/id_rsa && \
docker buildx build --ssh default=${SSH_AUTH_SOCK} . -t ${IMAGE} --build-arg USE_BROWSER=none
stop:
docker stop whatsapp-http-api
+15 -3
View File
@@ -4,7 +4,7 @@ services:
image: devlikeapro/whatsapp-http-api
container_name: whatsapp-http-api
ports:
- "3000:3000/tcp"
- '3000:3000/tcp'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
- WHATSAPP_HOOK_URL=https://httpbin.org/post
@@ -16,9 +16,9 @@ services:
image: devlikeapro/whatsapp-http-api-plus
container_name: whatsapp-http-api-plus
ports:
- "3000:3000/tcp"
- '3000:3000/tcp'
volumes:
- "./.sessions:/app/.sessions"
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
- WHATSAPP_RESTART_ALL_SESSIONS=True
@@ -30,3 +30,15 @@ services:
- WHATSAPP_SWAGGER_PASSWORD=123
- WHATSAPP_API_HOSTNAME=localhost
restart: always
mongodb:
image: mongo
container_name: mongodb
ports:
- '27017:27017/tcp'
volumes:
- mongodb_data:/data/db
restart: always
volumes:
mongodb_data: {}
+11 -4
View File
@@ -78,17 +78,24 @@
parent = "waha-plus"
[[main]]
name = "Get on Boosty ->"
weight = 50
url = "https://boosty.to/wa-http-api"
name = "Patron Portal ->"
weight = 20
url = "https://portal.devlike.pro/"
parent = "waha-plus"
[[main]]
name = "Get on Patreon ->"
weight = 60
weight = 50
url = "https://patreon.com/wa_http_api"
parent = "waha-plus"
[[main]]
name = "Get on Boosty ->"
weight = 60
url = "https://boosty.to/wa-http-api"
parent = "waha-plus"
[[main]]
name = "Examples"
weight = 20
+1 -1
View File
@@ -1,7 +1,7 @@
---
title : "WAHA"
description: "WAHA - WhatsApp HTTP API that you can run in a click!"
lead: "WAHA - WhatsApp HTTP API that you can run in a click!"
lead: "WAHA - <b>WhatsApp HTTP API</b> that you can run in a click!"
date: 2020-10-06T08:47:36+00:00
lastmod: 2020-10-06T08:47:36+00:00
draft: false
@@ -15,7 +15,9 @@ Parameters in path that you can find in below endpoints:
- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/session/start` endpoint
- `{chatId}` - chat id in format `123123123123@[c.us|g.us]`, `c.us` for direct chats and `g.us` for groups.
## Methods
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Get all chats
Get all chats
`GET /api/{session}/chats`
@@ -38,10 +38,17 @@ The following environment variables can be used to configure the WAHA.
response.
- `WHATSAPP_START_SESSION=session1,session2`: This variable can be used to start sessions with the specified names right
after launching the API. Separate session names with a comma.
- Also read more about [Sessions ->]({{< relref "/docs/how-to/sessions" >}})
- Also read more about [Session Storages on the dedicated page ->]({{< relref "/docs/how-to/storages#sessions" >}})
### Swagger
- `WHATSAPP_SWAGGER_CONFIG_ADVANCED=true` - enables advanced configuration options for Swagger documentation - you can customize host, port and base URL for the requests.
Disabled by default.
- `WHATSAPP_SWAGGER_ENABLED=false` - disables Swagger documentation. Enabled by default. Available in **WAHA Plus** only.
- `WHATSAPP_SWAGGER_USERNAME=admin` and `WHATSAPP_SWAGGER_PASSWORD=admin` - these variables can be used to protect the Swagger panel
with `admin / admin` credentials. This does not affect API access. Available in **WAHA Plus** only.
Read more about security settings for Swagger and API on [**Security page** ->]({{< relref "/docs/how-to/security" >}}).
### Proxy
#### Global proxy configuration
@@ -61,24 +68,59 @@ Read more about it on [**Session page** ->]({{< relref "/docs/how-to/sessions#co
Keep in mind that session's proxy configuration takes precedence over proxy configuration set by environment variables!
### Security ![](/images/versions/plus.png)
### Security
<b>Security is available in [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
- `WHATSAPP_API_KEY=mysecret`: If you set this variable, you must include the `X-Api-Key: mysecret` header in all
requests to the API. This will protect the API with a secret code.
- `WHATSAPP_SWAGGER_USERNAME=admin` and `WHATSAPP_SWAGGER_PASSWORD=admin`: These variables can be used to protect the
Swagger panel with `admin / admin` credentials. This does not affect API access.
Read more about security settings for Swagger and API on [**Security page** ->]({{< relref "/docs/how-to/security" >}}).
### Files ![](/images/versions/plus.png)
### Files
<b>Files configuration is available in [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
The following environment variables can be used to configure the file storage options for the WAHA:
- `WHATSAPP_FILES_MIMETYPES`: This variable can be used to download only specific mimetypes from messages. By default,
all files are downloaded. The mimetypes must be separated by a comma, without spaces. For
example: `audio,image/png,image/gif`. To choose a specific type, use a prefix (like `audio,image`).
- `WHATSAPP_FILES_MIMETYPES`: This variable can be used to download only specific mimetypes from messages.
By default, all files are downloaded. The mimetypes must be separated by a comma, without spaces.
For example: `audio,image/png,image/gif`. To choose a specific type, use a prefix (like `audio,image`). See usage below.
- `WHATSAPP_DOWNLOAD_MEDIA=true` - this variable can be used to **completely** disable downloading media files. By default, all files are downloaded.
Set this variable to `WHATSAPP_DOWNLOAD_MEDIA=false` to disable downloading media files.
- Under the hood, it sets `WHATSAPP_FILES_MIMETYPES=mimetype/ignore-all-media` to ignore all media files.
- `WHATSAPP_FILES_LIFETIME`: This variable can be used to set the time (in seconds) after which files will be removed to
free up space. The default value is `180`.
- Set this variable to `0` to disable the file lifetime.
- `WHATSAPP_FILES_FOLDER`: This variable can be used to set the folder where files from chats (images, voice messages)
will be stored. The default value is `/tmp/whatsapp-files`.
- The folder must be mounted to the host machine to keep the files between container restarts. [ Read more about how to persist files ->]({{< relref "/docs/how-to/storages#media" >}})
- Also read more about [Media Storages on the dedicated page ->]({{< relref "/docs/how-to/storages#media" >}})
💡 Even if WAHA doesn't process the message media because of `WHATSAPP_FILES_MIMETYPES` or `WHATSAPP_DOWNLOAD_MEDIA`
you'll get a webhook event with `hasMedia: True` field, but with no `media.url`.
```json
{
"event": "message",
"session": "default",
"payload": {
"hasMedia": true,
"media": {
"url": null,
"mimetype": "video/mp4",
"filename": null
}
}
}
```
### Health Check
<b>Health check is available in [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
The following environment variables can be used to configure the [Health Check ->]({{< relref "/docs/how-to/other" >}}):
- `WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB` - the threshold in MB for the media files storage. The default value is `100`.
- `WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB` - the threshold in MB for the sessions files storage. The default value is `100`.
- `WHATSAPP_HEALTH_MONGODB_TIMEOUT` - the timeout in milliseconds for the MongoDB health check. The default value is `5000`.
## Examples
@@ -138,6 +180,13 @@ comma-separated list of mimetypes:
WHATSAPP_FILES_MIMETYPES=audio,image/png,image/gif
```
#### Disable Downloading Media Files
To disable downloading media files, set the `WHATSAPP_DOWNLOAD_MEDIA` environment variable to `false`:
```
WHATSAPP_DOWNLOAD_MEDIA=false
```
#### Setting the File Lifetime
To set the time (in seconds) after which files will be removed to free up space, set the `WHATSAPP_FILES_LIFETIME`
@@ -13,7 +13,10 @@ Methods for contacts.
{{< alert icon="👉" text="WhatsApp Web does not support adding contacts, so the API doesn't support it too." />}}
## Get all contacts
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Get all contacts
Get your contacts - `GET /api/contacts/all`
@@ -34,7 +37,7 @@ Get your contacts - `GET /api/contacts/all`
]
```
## Get contact
### Get contact
Get contact
@@ -56,19 +59,32 @@ Get contact
}
```
## Check phone number exists
### Check phone number exists
If you want to check if phone number is registered in WhatsApp (even if the number is not in your contact list) - use
this endpoint for that.
- `GET /api/contacts/check-exists?phone=11231231231&session=default`
```bash
GET /api/contacts/check-exists?phone=11231231231&session=default
```
It returns `numberExists` field with `true` or `false` value and `chatId` field with chat ID of the number (if exists).
```json
{
"numberExists": true
"numberExists": true,
"chatId": "123123123@c.us"
}
```
**Note for Brazilian Phone Numbers**
## Get "about" contact
You should use the `GET /api/contacts/check-exists` endpoint **before sending a message to a new phone number**
to get the correct chatId because of the additional 9-digit number added after 2012.
Read more about
[error sending text to half of Brazilian numbers (every number registered before 2012) ->](https://github.com/devlikeapro/whatsapp-http-api/issues/238)
It's fine to send the response to `chatId` for incoming messages, though - the payload already has the correct `chatId`.
### Get "about" contact
- `GET /api/contacts/about?contactId=11231231231&session=default`
@@ -78,7 +94,7 @@ this endpoint for that.
}
```
## Get contact profile picture
### Get contact profile picture
- `GET /api/contacts/profile-picture?contactId=11231231231&session=default`
@@ -88,7 +104,7 @@ this endpoint for that.
}
```
## Block (unblock) contact
### Block (unblock) contact
- To block contact - `POST /api/contacts/block`
- To unblock contact - `POST /api/contacts/unblock`
+173 -14
View File
@@ -9,7 +9,9 @@ images: [ ]
weight: 800
---
Under the hood **WAHA** allows you to use two different engines. You can control what you want to run by settings
## Engines
Under the hood **WAHA** allows you to use different engines. You can control what you want to run by settings
`WHATSAPP_DEFAULT_ENGINE` environment variables.
```bash
@@ -18,35 +20,192 @@ docker run -it -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/whatsapp-http-api
If you have any problems with one engine - try another!
{{< alert icon="👉" text="API responses and webhook payloads may differ significantly! We do our best to keep requests body stable between engines." />}}
{{< alert icon="👉" text="API responses and webhook payloads may differ significantly, test everything before changing the engine" />}}
All engines are available in Core version ![](/images/versions/core.png)
All engines are available in both
Core ![](/images/versions/core.png) and
[Plus ![](/images/versions/plus.png) versions]({{< relref "/docs/how-to/plus-version" >}}).
## WEBJS
### WEBJS
- `WHATSAPP_DEFAULT_ENGINE=WEBJS`
- [https://github.com/pedroslopez/whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js)
A WhatsApp API client that connects through the WhatsApp Web browser app.
It uses Puppeteer to run a real instance of Whatsapp Web to avoid getting blocked.
**WAHA** uses **WhatsApp WebJS** engine by default.
- `WHATSAPP_DEFAULT_ENGINE=WEBJS`
- https://github.com/pedroslopez/whatsapp-web.js
### NOWEB
## NOWEB
- `WHATSAPP_DEFAULT_ENGINE=NOWEB`
- [https://github.com/WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys)
**NOWEB** engine does not require a browser to work with WhatsApp Web, it does so directly using a WebSocket.
**NOWEB** engine **does not require a browser** to work with WhatsApp Web, it does so directly using a WebSocket.
Not running Chromium saves you CPU and Memory, so you can run more instances on a single server!
️Working with the engine requires more attention, because it's easy to be blocked with it!
⚠ Read the article before using **NOWEB** engine [How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}).
⚠ Read the article before using **NOWEB** engine
[How to avoid blocking ->]({{< relref " /docs/overview/how-to-avoid-blocking" >}}).
- `WHATSAPP_DEFAULT_ENGINE=NOWEB`
- https://github.com/WhiskeySockets/Baileys
### MOBILE (experimental)
{{< alert icon="👉" text="<b>Experimental engine!</b><br/>Please contact us on <a href='https://www.patreon.com/wa_http_api' target='_blank'>Patreon -></a> or <a href='https://boosty.to/wa-http-api' target='_blank'>Boosty -></a> if you're interested in using it.<br>Available for <a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>PRO</a> subscribers only" />}}
## VENOM
- `WHATSAPP_DEFAULT_ENGINE=MOBILE`
- [https://github.com/WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys)
It's a high-performance system developed with JavaScript to create a bot for WhatsApp
**MOBILE** engine **does not require a browser and a mobile device** to work with WhatsApp, it does so directly using a WebSocket.
You don't have to use a mobile device to run this engine.
### VENOM
- `WHATSAPP_DEFAULT_ENGINE=VENOM`
- https://github.com/orkestral/venom
- [https://github.com/orkestral/venom](https://github.com/orkestral/venom)
It's a high-performance system developed with JavaScript to create a bot for WhatsApp.
It uses Puppeteer to run a real instance of Whatsapp Web to avoid getting blocked.
## Docker images
WAHA provides few docker images with different setup.
{{< alert icon="👉" text="Use `devlikeapro/whatsapp-http-api` instead of `devlikeapro/whatsapp-http-api-plus` to get **WAHA Plus** version." />}}
For **x86** processors use following images:
- `devlikeapro/whatsapp-http-api:latest` - latest version of WAHA, using **Chromium** (does not support video receiving and receiving in Plus version)
- `devlikeapro/whatsapp-http-api:chrome` - latest version of WAHA, using **Chrome** (supports video receiving and receiving in Plus version)
- `devlikeapro/whatsapp-http-api:noweb`- latest version of WAHA, **no browser installed** - use it only for **NOWEB** engine
For **ARM** processors use following images:
- `devlikeapro/whatsapp-http-api:arm` - **Chromium**
- `devlikeapro/whatsapp-http-api:noweb-arm`- **no browser installed**
{{< alert icon="💡" text="Chrome version is not available in ARM" />}}
## Features
Some engines may not support certain features.
Here, you will find a list of supported endpoints and webhooks per engine.
| Symbol | Meaning |
|:------------------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ✔️ | The engines supports the feature. |
| ➖ | The engine does **not** support this feature. <br/>Please search for the issue about the endpoint in [the project's issue](https://github.com/devlikeapro/whatsapp-http-api/issues) and upvote it by using the "👍" reaction on the issue's description. This will help us determine the level of interest in the feature. <br/>If you are unable to find the issue, please create a new one. |
| ![](/images/versions/plus.png) | The feature available in [WAHA Plus]({{< relref "/docs/how-to/plus-version" >}}). |
If you don't specify `WHATSAPP_DEFAULT_ENGINE` environment variable - look at **WEBJS** engine,
it's the engine WAHA runs by default.
### Engine
| | WEBJS | NOWEB | VENOM |
|--------------------------------------------------------------|:-----:|:-----:|:-----:|
| Run a browser (chromium\chrome) to communicate with WhatsApp | ✔️ | ➖ | ✔️ |
| Communicate with WhatsApp via websocket (no browser) | ➖ | ✔️ | ➖ |
### Endpoints
If you find any inconsistency with actual endpoints -
please [create an issue](https://github.com/devlikeapro/whatsapp-http-api/issues/new?title=Error+in+engine+features )
| | WEBJS | NOWEB | VENOM |
|-------------------------------------------------------------------|:-----:|:-------------------------------------------------------------------------:|:-----:|
| **Session** | | | |
| `POST /api/sessions/start` | ✔️ | ✔️ | ✔️ |
| `POST /api/sessions/stop` | ✔️ | ✔️ | ✔️ |
| `POST /api/sessions/logout` | ✔️ | ✔️ | ✔️ |
| `GET /api/sessions/` | ✔️ | ✔️ | ✔️ |
| `GET /api/sessions/{session}/me` | ✔️ | ✔️ | ➖ |
| **Authentication** | | | |
| `POST /api/{session}/auth/qr` | ✔️ | ✔️ | ✔️ |
| `POST /api/{session}/auth/request-code` | ➖ | ✔️ | ➖ |
| `POST /api/{session}/auth/authorize-code` | ➖ | ➖️<br>[#113](https://github.com/devlikeapro/whatsapp-http-api/issues/113) | ➖ |
| `GET /api/{session}/auth/captcha` <br>Only in **MOBILE** engine | ➖ | ➖ | ➖ |
| `POST /api/{session}/auth/captcha` <br>Only in **MOBILE** engine | ➖ | ➖ | ➖ |
| **Screenshot** | | | |
| `POST /api/screenshot` | ✔️ | ➖ | ✔️ |
| **Chatting** | WEBJS | NOWEB | VENOM |
|------------------------------------------------------|:-----:|:-----:|:-----:|
| `GET /api/checkNumberStatus` | ✔️ | ✔️ | ✔️ |
| `GET /api/sendContactVcard` | ➖ | ➖ | ✔️ |
| `GET /api/sendText` | ✔️ | ✔️ | ✔️ |
| `POST /api/sendText` | ✔️ | ✔️ | ✔️ |
| `POST /api/sendPoll` | ➖ | ✔️ | ➖ |
| `POST /api/sendLocation` | ✔️ | ✔️ | ✔️ |
| `POST /api/sendLinkPreview` | ➖ | ✔️ | ✔️ |
| `POST /api/sendImage` ![](/images/versions/plus.png) | ✔️ | ✔️ | ✔️ |
| `POST /api/sendFile` ![](/images/versions/plus.png) | ✔️ | ✔️ | ✔️ |
| `POST /api/sendVoice` ![](/images/versions/plus.png) | ✔️ | ✔️ | ✔️ |
| `POST /api/sendVideo` ![](/images/versions/plus.png) | ✔️ | ✔️ | ➖ |
| `POST /api/reply` | ✔️ | ✔️ | ✔️ |
| `POST /api/sendSeen` | ✔️ | ✔️ | ✔️ |
| `POST /api/startTyping` | ✔️ | ✔️ | ✔️ |
| `POST /api/stopTyping` | ✔️ | ✔️ | ➖ |
| `POST /api/reaction` | ✔️ | ✔️ | ➖ |
| `GET /api/messages` | ✔️ | ➖ | ✔️ |
| | WEBJS | NOWEB | VENOM |
|-------------------------------------------------------------------|:-----:|:-----:|:-----:|
| **Status** | | | |
| `POST /api/{session}/status/text` | ➖ | ✔️ | ➖ |
| `POST /api/{session}/status/image` ![](/images/versions/plus.png) | ➖ | ✔️ | ➖ |
| `POST /api/{session}/status/voice` ![](/images/versions/plus.png) | ➖ | ✔️ | ➖ |
| `POST /api/{session}/status/video` ![](/images/versions/plus.png) | ➖ | ✔️ | ➖ |
| **Chats** | | | |
| `GET /api/{session}/chats` | ✔️ | ➖ | ➖ |
| `DELETE /api/{session}/chats/{chatId}` | ✔️ | ➖ | ➖ |
| `GET /api/{session}/chats/{chatId}/messages` | ✔️ | ➖ | ✔️ |
| `DELETE /api/{session}/chats/{chatId}/messages` | ✔️ | ➖ | ➖ |
| **Contacts** | | | |
| `GET /api/contacts` | ✔️ | ➖ | ➖ |
| `GET /api/contacts/all` | ✔️ | ➖ | ➖ |
| `GET /api/contacts/check-exists` | ✔️ | ✔️ | ✔️ |
| `GET /api/contacts/about` | ✔️ | ➖ | ➖ |
| `GET /api/contacts/profile-picture` | ✔️ | ➖ | ➖ |
| `POST /api/contacts/block` | ✔️ | ➖ | ➖ |
| `POST /api/contacts/unblock` | ✔️ | ➖ | ➖ |
| **Groups** | WEBJS | NOWEB | VENOM |
|--------------------------------------------------------------------|:-----:|:-----:|:-----:|
| `POST /api/{session}/groups` | ✔️ | ✔️ | ➖ |
| `GET /api/{session}/groups` | ✔️ | ✔️ | ➖ |
| `GET /api/{session}/groups/{id}` | ✔️ | ✔️ | ➖ |
| `DELETE /api/{session}/groups/{id}` | ✔️ | ➖ | ➖ |
| `GET /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
| `PUT /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
| `POST /api/{session}/groups/{id}/leave` | ✔️ | ✔️ | ➖ |
| `PUT /api/{session}/groups/{id}/description` | ✔️ | ✔️ | ➖ |
| `PUT /api/{session}/groups/{id}/subject` | ✔️ | ✔️ | ➖ |
| `GET /api/{session}/groups/{id}/invite-code` | ✔️ | ✔️ | ➖ |
| `POST /api/{session}/groups/{id}/invite-code/revoke` | ✔️ | ✔️ | ➖ |
| `GET /api/{session}/groups/{id}/participants` | ✔️ | ✔️ | ➖ |
| `POST /api/{session}/groups/{id}/participants/add` | ✔️ | ✔️ | ➖ |
| `POST /api/{session}/groups/{id}/participants/remove` | ✔️ | ✔️ | ➖ |
| `POST /api/{session}/groups/{id}/admin/promote` | ✔️ | ✔️ | ➖ |
| `POST /api/{session}/groups/{id}/admin/demote` | ✔️ | ✔️ | ➖ |
| | WEBJS | NOWEB | VENOM |
|---------------------------------------------------|:-----:|:-----:|:-----:|
| **Presence** | | | |
| `POST /api/{session}/presence` | ✔️ | ✔️ | ➖ |
| `GET /api/{session}/presence` | ➖ | ✔️ | ➖ |
| `GET /api/{session}/presence/{chatId}` | ➖ | ✔️ | ➖ |
| `POST /api/{session}/presence/{chatId}/subscribe` | ➖ | ✔️ | ➖ |
| **Other** | | | |
| `GET /api/version` | ➖ | ✔️ | ➖ |
| `GET /health` ![](/images/versions/plus.png) | ✔️ | ✔️ | ✔️ |
| **Webhooks** | WEBJS | NOWEB | VENOM |
|-----------------------------------------------------|:-----:|:-----:|:-----:|
| `message` | ✔️ | ✔️ | ✔️ |
| `message` with files ![](/images/versions/plus.png) | ✔️ | ✔️ | ✔️ |
| `message.any` | ✔️ | ✔️ | ✔️ |
| `message.ack` | ✔️ | ✔️ | ✔️ |
| `message.revoked` | ✔️ | ➖ | ➖ |
| `state.change` | ✔️ | ✔️ | ✔️ |
| `group.join` | ✔️ | ✔️ | ✔️ |
| `group.leave` | ✔️ | ➖ | ➖ |
| `presence.update` | ➖ | ✔️ | ➖ |
| `poll.vote` | ➖ | ✔️ | ➖ |
| `poll.vote.failed` | ➖ | ✔️ | ➖ |
@@ -9,7 +9,10 @@ images: []
weight: 140
---
Methods for groups. Please look at swagger for details.
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
Endpoints for groups. Please look at swagger for details.
- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/session/start` endpoint
- `{groupId}` - group id in format `123123123123@g.us`. You can get the id in a few ways:
@@ -17,7 +20,7 @@ Methods for groups. Please look at swagger for details.
- By getting all groups (see below).
- By creating a new group and saving the id.
## Create a new group
### Create a new group
`POST /api/{session}/groups`
@@ -34,23 +37,23 @@ Request:
}
```
## Get all groups
### Get all groups
`GET /api/{session}/groups`
## Get the group
### Get the group
`GET /api/{session}/groups/{groupId}`
## Delete the group
### Delete the group
`DELETE /api/{session}/groups/{groupId}`
## Leave the group
### Leave the group
`POST /api/{session}/groups/{groupId}/leave`
## Set group subject
### Set group subject
Updates the group subject.
@@ -67,7 +70,7 @@ Request:
}
```
## Set group description
### Set group description
Updates the group description.
@@ -84,10 +87,15 @@ Request:
}
```
## Settings
### Security for group info
### Settings
#### Security for group info
Updates the group settings to only allow admins to edit group info (title, description, photo).
`GET /api/{session}/groups/{groupId}/settings/security/info-admin-only`
```json
{
"adminsOnly": true
}
```
`PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only`
The request doesn't require any request's body and
@@ -95,13 +103,13 @@ The request doesn't require any request's body and
If you wish to have that ability - please [create an issue](https://github.com/devlikeapro/whatsapp-http-api/issues)
## Participants
### Participants
### Get participants
#### Get participants
`GET /api/{session}/groups/{groupId}/participants`
### Add participants
#### Add participants
`POST /api/{session}/groups/{groupId}/participants/add`
@@ -115,7 +123,7 @@ If you wish to have that ability - please [create an issue](https://github.com/d
}
```
### Remove participants
#### Remove participants
`POST /api/{session}/groups/{groupId}/participants/remove`
@@ -129,9 +137,9 @@ If you wish to have that ability - please [create an issue](https://github.com/d
}
```
## Admin
### Admin
### Promote to admin
#### Promote to admin
Promote participants to admin users.
@@ -147,7 +155,7 @@ Promote participants to admin users.
}
```
### Demote to regular users
#### Demote to regular users
Demote participants by to regular users.
@@ -163,17 +171,45 @@ Demote participants by to regular users.
}
```
## Invite code
### Invite code
### Get invite code
#### Get invite code
`GET /api/{session}/groups/{groupId}/invite-code`
Then you can put it in the url `https://chat.whatsapp.com/{inviteCode}` and send it to contacts.
### Revoke invite code
#### Revoke invite code
Invalidates the current group invite code and generates a new one.
`POST /api/{session}/groups/{groupId}/invite-code/revoke`
## Webhooks
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### group.join
```json
{
"event": "group.join",
"session": "default",
"engine": "WEBJS",
"payload": {
...
}
}
```
### group.leave
```json
{
"event": "group.left",
"session": "default",
"engine": "WEBJS",
"payload": {
...
}
}
```
@@ -0,0 +1,192 @@
---
title: "Other"
description: "Other features and API"
lead: ""
date: 2020-10-06T08:48:45+00:00
lastmod: 2020-10-06T08:48:45+00:00
draft: false
images: [ ]
weight: 802
---
This page provides useful information about other features and API that are not covered in the other sections.
## Health Check
<b>Health check is available in [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
The health check endpoint is used to determine the health of the service.
```
GET /health
```
It returns a **200 OK** status code if the service is healthy.
The response format:
```json
{
"status": "ok",
"info": {
"metric1": {
"field": "value"
},
"metric2": {
"field": "value"
}
},
"error": {},
"details": {}
}
```
Where:
- `status`: `'error' | 'ok' | 'shutting_down'` - If any health indicator failed the status will be `'error'`. If the app is shutting down but still accepting HTTP requests, the health check will have the `'shutting_down'` status.
- `info`: Object containing information of each health indicator which is of status `'up'`, or in other words "healthy".
- `error`: Object containing information of each health indicator which is of status `'down'`, or in other words "unhealthy".
- `details`: Object containing detailed information of each health indicator.
### Health Check Indicators
Few things we check in the health check:
- Media files storage space - `mediaFiles.space`
- Sessions files storage space - `sessionsFiles.space`
- MongoDB connection - `mongodb`
### Configuration
The following environment variables can be used to configure the health check:
- `WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB` - the threshold in MB for the media files storage. The default value is `100`.
- `WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB` - the threshold in MB for the sessions files storage. The default value is `100`.
- `WHATSAPP_HEALTH_MONGODB_TIMEOUT` - the timeout in milliseconds for the MongoDB health check. The default value is `5000`.
### Examples
**Healthy response** when you use [Local Storage]({{< relref "/docs/how-to/storages#sessions" >}}) for session authentication:
**200 OK**
```json
{
"status": "ok",
"info": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132979355648,
"threshold": 104857600
},
"sessionsFiles.space": {
"status": "up",
"path": "/app/.sessions",
"diskPath": "/",
"free": 132979355648,
"threshold": 104857600
}
},
"error": {},
"details": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132979355648,
"threshold": 104857600
},
"sessionsFiles.space": {
"status": "up",
"path": "/app/.sessions",
"diskPath": "/",
"free": 132979355648,
"threshold": 104857600
}
}
}
```
**Healthy response** when you use [MongoDB Storage]({{< relref "/docs/how-to/storages#sessions" >}}) for session authentication:
**200 OK**
```json
{
"status": "ok",
"info": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132977496064,
"threshold": 104857600
},
"mongodb": {
"status": "up",
"message": "Up and running"
}
},
"error": {},
"details": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132977496064,
"threshold": 104857600
},
"mongodb": {
"status": "up",
"message": "Up and running"
}
}
}
```
**Unhealthy response example**
**503 Service Unavailable**
```json
{
"status": "error",
"info": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132976623616,
"threshold": 104857600
}
},
"error": {
"mongodb": {
"status": "down",
"error": "Timeout"
}
},
"details": {
"mediaFiles.space": {
"status": "up",
"path": "/tmp/whatsapp-files",
"diskPath": "/",
"free": 132976623616,
"threshold": 104857600
},
"mongodb": {
"status": "down",
"error": "Timeout"
}
}
}
```
## Get version
Returns the version of the installed docker image.
```
GET /api/version
```
```json
{
"version": "2024.2.3",
"engine": "NOWEB",
"tier": "PLUS",
"browser": "/usr/bin/google-chrome-stable"
}
```
@@ -17,17 +17,17 @@ weight: 900
2. Plus ![](/images/versions/plus.png) the version with advanced messages, security, and reliability features.
You support the project and get **WAHA Plus** on
<a href="https://boosty.to/wa-http-api" target="_blank">
<b>
Boosty ->
</b>
</a>
or
<a href="https://patreon.com/wa_http_api" target="_blank">
<b>
Patreon ->
</b>
</a>
or
<a href="https://boosty.to/wa-http-api" target="_blank">
<b>
Boosty ->
</b>
</a>
.
### Donations
@@ -49,17 +49,35 @@ Treat **WAHA Plus** it as an additional episode, behind-the-scenes videos, our n
We donate most of the donations down to the stream to the underlying libraries and tools - JS-community, Node, other libraries authors, personal contributors.
By donating to the **WAHA** you donate to the Open Source world!
### Features
### Tiers
The Plus additional features are:
The more you support the project - the more you get!
| | Core | Plus | Advanced | Pro |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------|---------|:--------:|:-------:|
| Messages limit | **∞** | **∞** | **∞** | **∞** |
| [Send and receive text messages ->]({{< relref "/docs/how-to/send-messages" >}}) | ✔️ | ✔️ | ✔️ | ✔️ |
| No license checks on installed instances | ✔️ | ✔️ | ✔️ | ✔️ |
| [Sessions limit ->]({{< relref "/docs/how-to/sessions" >}}) | **1** | **∞** | **∞** | **∞** |
| [Send and receive files ->]({{< relref "/docs/how-to/send-messages" >}}) | ➖️ | ✔️ | ✔️ | ✔️ |
| [Built-in Security ->]({{< relref "/docs/how-to/security" >}}) | ➖️ | ✔️ | ✔️ | ✔️ |
| [**Webhook retries** →]({{< relref "/docs/how-to/receive-messages#retries" >}}) | ➖️ | ✔️ | ✔️ | ✔️ |
| [MongoDB support ->]({{< relref "/docs/how-to/storages" >}}) | ➖️ | ✔️ | ✔️ | ✔️ |
| Access to **WAHA Plus** ![](/images/versions/plus.png) docker image with a personal key. | ➖️ | ✔️ | ✔️ | ✔️ |
| Special badge ([![patron:TIER](https://img.shields.io/badge/patron-TIER-188a42)](https://waha.devlike.pro/docs/how-to/plus-version/#tiers)) and labels (`patron:TIER`) on [project's issues, PRs and Discussion](https://github.com/devlikeapro/whatsapp-http-api) to highlight your support to the project! | | ✔️ | ✔️ | ✔️ |
| An invitation to **a private Github repository** so you have the **WAHA Plus** source code. | ➖️ | ➖️ | ✔️ | ✔️️ |
| Access to a Telegram group where we provide support and assistance. | ➖️ | ➖️ | ➖ | ✔️ |
| Access to an [experimental MOBILE engine]({{< relref "/docs/how-to/plus-version#tiers" >}})!. | ➖️ | ➖️ | ➖ | ✔️ |
| **Donation** | **FREE** | **$19** | **$39** | **$99** |
For **$19** donation you get:
1. **Secret password** for Docker Hub to download Plus image: `devlikeapro/whatsapp-http-api-plus`.
2. **All updates for one month** for the Plus image.
3. **NO LICENSE CHECKS** on installed instances!
4. **NO LICENSE EXPIRATION** on installed instances! We repeated it twice to make sure that you've got it 😊
{{< alert icon="💡" text="If you stay subscribed - the donation amount will never change for you and always be $19 to get monthly updates!" />}}
1. [**Send images\files\voices** →]({{< relref "/docs/how-to/send-messages" >}})
2. [**Receive images\files\voices** →]({{< relref "/docs/how-to/receive-messages" >}})
3. [**Webhook retries** →]({{< relref "/docs/how-to/receive-messages#retries" >}})
4. [**Security** →]({{< relref "/docs/how-to/security" >}})
5. [**Saving sessions** →]({{< relref "/docs/how-to/sessions" >}})
6. [**Support multiple sessions** →]({{< relref "/docs/how-to/sessions" >}})
7. **Priority in support** - on both bugs and features
### Why WAHA?
@@ -77,42 +95,6 @@ What is the difference between **WAHA Plus** and **other SaaS solutions** for Wh
## Get Plus ![](/images/versions/plus.png)
The more you support the project - the more you get!
Here's available tiers for our supporters:
| | Plus | Advanced | Pro |
|-------------------------------------------------------------------------------------|---------|:--------:|:-------:|
| Access to WAHA Plus ![](/images/versions/plus.png) docker image. | ✔️ | ✔️ | ✔️ |
| An invitation to a private Github repository so you have the WAHA Plus source code. | ➖️ | ✔️ | ✔️️ |
| Access to a Telegram group where we provide support and assistance. | ➖️ | ➖ | ✔️ |
| Personal key to Docker Hub. | ➖️ | ➖ | ✔️ |
| **Donation** | **$19** | **$39** | **$99** |
For **$19** donation you get:
1. **Secret password** for Docker Hub to download Plus image: `devlikeapro/whatsapp-http-api-plus`.
2. **All updates for one month** for the Plus image.
3. **NO LICENSE CHECKS** on installed instances!
4. **NO LICENSE EXPIRATION** on installed instances! We repeated it twice to make sure that you've got it 😊
{{< alert icon="💡" text="If you stay subscribed - the donation amount will never change for you and always be $19 to get monthly updates!" />}}
### Boosty
<p align="center">
<img src="boosty.svg" alt="Patreon" />
<br/>
<br/>
</p>
Support the project and get WAHA Plus version on
<a href="https://boosty.to/wa-http-api" target="_blank">
<b>
Boosty ->
</b>
</a>
Go ahead and get your own WhatsApp HTTP API!
### Patreon
<p align="center">
@@ -128,9 +110,25 @@ Support the project and get WAHA Plus version on
Go ahead and get your own WhatsApp HTTP API!
### Boosty
<p align="center">
<img src="boosty.svg" alt="Patreon" />
<br/>
<br/>
</p>
### Install Plus
After you get the password, use it to login and download docker image:
Support the project and get WAHA Plus version on
<a href="https://boosty.to/wa-http-api" target="_blank">
<b>
Boosty ->
</b>
</a>
Go ahead and get your own WhatsApp HTTP API!
## Install Plus
After you get the password, get your login to Docker Hub in [Patron Portal ->](https://portal.devlike.pro/)
and run the commands:
```bash
docker login -u devlikeapro -p {KEY}
docker pull devlikeapro/whatsapp-http-api-plus
@@ -9,13 +9,13 @@ images: [ ]
weight: 126
---
**Available on NOWEB engine only**.
Waiting for WEBJS engine to support it, and we'll add it ASAP!
![poll-example.jpg](poll-example.jpg)
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Send poll
@@ -54,7 +54,8 @@ The response you get back:
You must save the `id` field from the response in your database so that you can identify the poll for which you receive
a vote (see webhook events below).
## Events
## Webhooks
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### poll.vote
@@ -21,12 +21,14 @@ Possible presence statuses that you can set or get for chats:
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Set presence
You can set your global or chat-related presence with `POST /api/{session}/presence` endpoint
Start typing to a chat (you can use `POST /startTyping` instead)
```json
```
POST /api/{session}/presence
{
"chatId": "111111111@c.us",
"presence": "typing"
@@ -34,7 +36,8 @@ Start typing to a chat (you can use `POST /startTyping` instead)
```
Clear "typing" state (you can use `POST /stopTyping` instead)
```json
```
POST /api/{session}/presence
{
"chatId": "111111111@c.us",
"presence": "paused"
@@ -42,7 +45,8 @@ Clear "typing" state (you can use `POST /stopTyping` instead)
```
Set global "online", all contacts will see it
```json
```
POST /api/{session}/presence
{
"presence": "online"
}
@@ -52,7 +56,8 @@ Set global "online", all contacts will see it
to the device.
If you would like to receive said notifications - you need to mark a session's presence as `offline`.
```json
```
POST /api/{session}/presence
{
"presence": "offline"
}
@@ -60,9 +65,6 @@ If you would like to receive said notifications - you need to mark a session's p
### Get all chats presence
{{< alert icon="👉" text="Get presence endpoints and webhook is available only in **NOWEB** engine." />}}
[Read more about engines to choose right for you ->]({{< relref "/docs/how-to/engines" >}})
Here's few notes about fields:
- `chatId` - either contact id (`213213213@c.us`) or group chat id (`1111111111111@g.us`).
@@ -129,7 +131,9 @@ You can subscribe to presence information by calling `POST /api/{session}/presen
You can get later presence information for the chat with above `GET` endpoints or by listening to `presence.update`
webhook.
## Events
## Webhooks
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### presence.update
You can subscribe to `presence.update` webhook event to get the most recent presence information.
@@ -12,8 +12,6 @@ We consider that you've run docker container and authenticated the session with
If you haven't yet - please follow the steps from [**Quick Start →**]({{< relref "/docs/overview/quick-start" >}}).
## Webhooks
You must use [Webhooks]({{< relref "/docs/how-to/webhooks" >}}) to receive messages from WhatsApp to your application.
Start a new session with configured `message` event in webhooks - call `POST /api/sessions/start` with the payload:
@@ -36,7 +34,9 @@ Start a new session with configured `message` event in webhooks - call `POST /ap
After that WAHA'll send events (see below) about new messages to an endpoint you provided.
## Events
## Webhooks
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
Here's examples of message-related events.
Read [Webhooks ->]({{< relref "/docs/how-to/webhooks" >}}) to find how to set them up.
@@ -128,12 +128,36 @@ Receive events when server or recipient gets the message, read or played it.
}
```
### message.revoked
[See details on Webhooks page ->]({{< relref "webhooks#messageack" >}}).
```json
{
"event": "message.ack",
"session": "default",
"payload": {
"before": {
"id": "some-id-here",
"timestamp": "some-timestamp-here",
"body": "Hi there!"
},
"after": {
"id": "some-id-here",
"timestamp": "some-timestamp-here",
"body": ""
}
}
}
```
## Files ![](/images/versions/plus.png)
When people send you files - images, voice messages, and documents - WAHA saves it in the file storage.
In your application you must download it and use it as you want to. You can find the URL in `mediaUrl` field
When people send you media - images, voice messages, and documents - WAHA saves it in the file storage.
In your application you must download it and use it as you want to. You can find the URL in `media.url` field.
For example, you can get the webhook like this with `mediaUrl` value (we've skipped other fields):
For example, you can get the webhook like this with `media` value (we've skipped other fields):
```json
{
@@ -143,12 +167,35 @@ For example, you can get the webhook like this with `mediaUrl` value (we've skip
"id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"timestamp": 1667561485,
"from": "11111111111@c.us",
"mediaUrl": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg"
"hasMedia": true,
"media": {
"url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg",
"mimetype": "image/jpeg",
"filename": null
}
}
}
```
Then you can use the link to download the file `http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg`.
For documents (file attachments) there's also `filename` field with the original file name.
```json
{
"event": "message",
"session": "default",
"payload": {
"id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"timestamp": 1667561485,
"from": "11111111111@c.us",
"media": {
"url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.pdf",
"filename": "some-file.pdf",
"mimetype": "application/pdf"
}
}
}
```
To configure the url you can use environment variables `WHATSAPP_API_HOSTNAME` and `WHATSAPP_API_PORT`.
By default, WAHA download all files that the account receive.
@@ -156,6 +203,7 @@ If you want to limit files lifetime, specify file types for download or change d
[read more about file storage configuration and variables ->]({{< relref "config" >}}).
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Get messages
Read messages from the history - use `GET /api/messages` endpoint.
@@ -16,6 +16,7 @@ Either protect the API with [Api Key](https://www.fortinet.com/resources/cybergl
firewalls.
## Swagger Security ![](/images/versions/plus.png)
### Username and password
If you want to hide the project Swagger panel under the password - run the following command to hide under `admin/admin`
login and password.
@@ -29,6 +30,12 @@ Open http://localhost:3000/ and enter `admin / admin` in the inputs:
{{< alert icon="👉" text="Protecting Swagger under the password does not protect your API from other request! Use both techniques to protect your API and Swagger!" />}}
### Disable Swagger
You also can hide swagger completely by setting `WHATSAPP_SWAGGER_ENABLED=false` environment variable.
{{< alert icon="👉" text="Disabling Swagger does not protect the API, please use API security as well" />}}
## API security ![](/images/versions/plus.png)
You can protect the API by requiring Api Key in a request's headers.
@@ -15,21 +15,38 @@ If you haven't yet - please follow the steps from [**Quick Start →**]({{< relr
## Fields
There are common fields that you can find in almost all requests:
- `session` - a session name from which account you're sending the message. We use `default` in the examples.
- Core ![](/images/versions/core.png) version supports only `default` session.
- Plus ![](/images/versions/plus.png) allows you to run multiple sessions inside one container to save your memory and CPU resources!
```json
{
"session": "default",
"chatId": "12132132130@c.us",
"file": "..."
}
```
### session
`session` - a session name from which account you're sending the message. We use `default` in the examples.
- Core ![](/images/versions/core.png) version supports only `default` session.
- Plus ![](/images/versions/plus.png) allows you to run multiple sessions inside one container to save your memory and CPU resources!
Read more about [multiple sessions →]({{< relref "/docs/how-to/sessions" >}})
- `chatId` - it's a phone number or Group identifier where you're sending the message.
- **Phone numbers** accounts use international phone number without + at the start and add `@c.us` at the end.
For phone number `12132132131` the `chatId` is `12132132131@c.us`.
- **Groups** use random number with `@g.us` at the end.
### chatId
`chatId` - it's a phone number or Group identifier where you're sending the message.
- **Phone numbers** accounts use international phone number without + at the start and add `@c.us` at the end.
For phone number `12132132131` the `chatId` is `12132132131@c.us`.
- **Groups** use random number with `@g.us` at the end.
> To get the actual `chatId` for **Brazilian phone number** - use `chatId` field from
> [Check phone number exists ->]({{< relref "/docs/how-to/contacts#check-phone-number-exists" >}})
> response.
### file
When sending media (images, voice, files) you can either use:
- `file.data` field with base64 encoded file (https://base64.guru/converter/encode/file)
- `file.data` field [with base64 encoded file](https://base64.guru/converter/encode/file)
- `file.url` field with public available URL for that file
## Endpoints
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Send text
To send text message - use `POST /api/sendText` with example payload.
@@ -168,6 +185,44 @@ You can send voice messages in two ways:
}
```
### Send video ![](/images/versions/plus.png)
Use `POST /api/sendVideo` to send a message with a video attached.
For **WEBJS** engine please use `devlikeapro/whatsapp-http-api-plus:chrome` docker image.
Read more about [**Docker images and engines →**]({{< relref "/docs/how-to/engines" >}}).
You can send voice messages in two ways:
1. Provide a URL for the file and the API will download it and send it in the request body.
2. Provide the file as a base64 string in the request body.
#### URL
```json
{
"session": "default",
"chatId": "11111111111@c.us",
"caption": "Watch this video!",
"file": {
"mimetype": "video/mp4",
"filename": "video.mp4",
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.mp3"
}
}
```
#### Base64
```json
{
"chatId": "11111111111@c.us",
"caption": "Watch this video!",
"file": {
"mimetype": "video/mp4",
"filename": "video.mp4",
"data": "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 truncated
},
"session": "default"
}
```
### Send file ![](/images/versions/plus.png)
Use `POST /api/sendFile` to send a file as a document.
@@ -204,7 +259,7 @@ You can send files in two ways:
### Send status (aka stories)
With [NOWEB engine]({{< relref "/docs/how-to/engines" >}}) you can send statuses (aka stories)!
You can send statuses (aka stories)!
It is always necessary to inform the list of `contacts` that will have access to the posted status!
@@ -9,7 +9,8 @@ images: [ ]
weight: 125
---
## Sessions
## Endpoints
See the list of engines [**that support the features ->**]({{< relref "/docs/how-to/engines#features" >}}).
### Start
@@ -127,6 +128,32 @@ In order to log out the session - call `POST /api/sessions/logout`
"logout": true
}
```
### Get screenshot
Get screenshot of the session's screen.
```bash
GET /api/screenshot?session=default
```
#### Get screenshot in Base64
You can get screenshot in base64 format by adding `Accept: application/json` header to the request.
```bash
GET /api/screenshot?session=default
Accept: application/json
```
```json
{
"mimetype": "image/png",
"data": "base64-encoded-data"
}
```
You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**:
![](/images/swagger-media-type.png)
### Get me
@@ -150,17 +177,66 @@ null
## Authentication
### Get QR
See the list of engines [**that support the features ->**]({{< relref "/docs/how-to/engines#features" >}}).
The simplest way to authenticate a new session - get QR code and scan it on your device.
```bash
GET /api/{session}/auth/qr
```
You'll get QR image that you can scan and get authenticated
#### QR formats
You can get QR in different formats:
1. **binary image** - `GET /api/{session}/auth/qr`
2. **base64 image** - `GET /api/{session}/auth/qr` and set `Accept: application/json` header
3. **raw** - `GET /api/{session}/auth/qr?format=raw`
Here's detailed information about each format:
1. **binary image**, binary image - **default** format, you'll get image in response
```bash
# Get image - binary
GET /api/{session}/auth/qr
# OR
GET /api/{session}/auth/qr?format=image
# OR specify Accept header as well
GET /api/{session}/auth/qr?format=image
Accept: image/png
```
2. **base64 image** - you'll get image in base64 format in response if you set `Accept: application/json` header.
```bash
GET /api/{session}/auth/qr?format=image
Accept: application/json
```
```json
{
"mimetype": "image/png",
"data": "base64-encoded-data"
}
```
You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**:
![](/images/swagger-media-type.png)
3. **raw** - you'll get raw data in response, you can use it to generate QR code on your side
```bash
GET /api/{session}/auth/qr?format=raw
```
```json
{
"value": "value-that-you-need-to-use-to-generate-qr-code"
}
```
### Get pairing code
{{< alert icon="👉" text="Available in **NOWEB** engine only." />}}
See the list of engines [**that support the features ->**]({{< relref "/docs/how-to/engines#features" >}}).
You can [link a session with phone number](https://faq.whatsapp.com/1324084875126592) - make a request to the endpoint.
```bash
@@ -182,6 +258,37 @@ You'll get code in the response that you can use on your WhatsApp app to connect
```
## Webhooks
See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}).
### session.status
The `session.status` event is triggered when the session status changes.
- `STOPPED` - session is stopped
- `STARTING` - session is starting
- `SCAN_QR_CODE` - session is required to scan QR code or login via phone number
- `WORKING` - session is working and ready to use
- `FAILED` - session is failed due to some error. It's likely that authorization is required again or device has been disconnected from that account.
Try to restart the session and if it doesn't help - logout and start the session again.
```json
{
"event": "session.status",
"session": "default",
"me": {
"id": "7911111@c.us",
"pushName": "~"
},
"payload": {
"status": "WORKING"
},
"engine": "WEBJS",
"environment": {
"version": "2023.10.12",
"engine": "WEBJS",
"tier": "PLUS"
}
}
```
## Advanced sessions ![](/images/versions/plus.png)
@@ -191,28 +298,8 @@ configure autostart options so when the docker container restarts - it restores
### Session persistent
#### File storage
If you want to save your session and do not scan QR code everytime when you launch WAHA - connect a local file storage
to the container. WAHA stores authentication information in the directory and reuses it after restart.
[Attach volume](https://docs.docker.com/storage/volumes/) part to the command:
```bash
-v `pwd`/.sessions:/app/.sessions
```
The full command would be:
```bash
docker run --rm -d -v `pwd`/.sessions:/app/.sessions -p 3000:3000/tcp --name whatsapp-http-api devlikeapro/whatsapp-http-api-plus
```
#### Remote storage ![](/images/versions/soon.png)
If you're interested in using some "remote" storage (like Redis or other Databases) to save sessions - please create an
issue on GitHub.
For instances, it may be useful if you run WAHA in a cluster of servers and do not have shared file storage
If you want to save your session and do not scan QR code everytime when you launch WAHA -
[connect the session storage to the container ->]({{< relref "/docs/how-to/storages#sessions" >}})
### Autostart
If you don't want to call `POST /api/sessions/start` for every session each time when the container restart -
@@ -0,0 +1,149 @@
---
title: "Storages"
description: "Storages"
lead: ""
date: 2020-10-06T08:48:45+00:00
lastmod: 2020-10-06T08:48:45+00:00
draft: false
images: [ ]
weight: 700
---
There are several storages that are used by the WAHA, below you can find the list of them and the way to configure them.
1. [Sessions](#sessions) - used to store the session data, such as authentication information, configuration, and other data that is required to keep the session alive and connected to WhatsApp.
2. [Media](#media) - used to store the media files, such as images, videos, and other files that are received from the WhatsApp instance.
<b>Storages are available in [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
## Sessions
The "Sessions" storage is used to store the session data, such as authentication information, configuration,
and other data that is required to keep the session alive and connected to WhatsApp.
If you want to save your session and do not scan QR code everytime when you launch WAHA -
connect the session storage to the container.
For the session storage, you can use the following options:
1. [Local (files)](#local-files) - the default option, stores the session data in the local storage using files.
2. [MongoDB](#mongodb) - stores the session data in the MongoDB database.
The following table shows the compatibility of the session storage with the engines:
| | WEBJS | NOWEB | VENOM |
|---------------|:-----:|:-----:|:-----:|
| Local (files) | ✔️ | ✔️ | ✔️ |
| MongoDB | ✔️ | ✔️ | ➖ |
## Sessions - Local (files)
By default, the WAHA uses the **local storage (files)** to store the session data.
{{< alert icon="💡" text="It's <b>well tested solution</b> even for production" />}}
In order to use the local storage and save the session data between the container restarts,
you need to mount the volume to the `/app/.sessions` directory using the `-v` option in `docker run` command:
```bash
-v /path/to/on/host/.sessions:/app/.sessions
```
The full command to run the WAHA with the local storage and save the session data
in the current directory and `.sessions` directory:
```bash
docker run -v `pwd`/.sessions:/app/.sessions -p 3000:3000/tcp devlikeapro/whatsapp-http-api-plus
```
This is the only action you need to do to use the local storage - all session data will be available between the container restarts.
### How it works
In the host machine, the session data will be stored in the current directory in the `.sessions` directory.
Under the hood, the WAHA stores the session data in the following directory structure:
```
.sessions/{engine}/{sessionName}/...
```
when you "logout" the session using [POST /api/sessions/logout]({{< relref "/docs/how-to/sessions#logout">}}) or providing `logout: True` in [POST /api/sessions/stop]({{< relref "/docs/how-to/sessions#stop">}})
it removes the directory with the session data.
### Health Check
The [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the local storage.
## Sessions - MongoDB
If you want to use the MongoDB to store the session data, you need to:
1. Start the MongoDB server (using docker or any other way). You can either start your own MongoDB server or use the one of cloud providers, like [MongoDB Atlas](https://www.mongodb.com/atlas/database).
2. Set `WHATSAPP_SESSIONS_MONGO_URL=mongodb://user:password@host:port/` environment variable to connect to the MongoDB server.
**We recommend using your own MongoDB server as close as possible to WAHA server** for the best performance and security reasons.
{{< alert icon="💡" text="For <b>WEBJS</b> engine it can take up to 1 minute to save credentials in Mongo Database" />}}
### Example
First, you need to start MongoDB server:
```bash
docker run -d -p 27017:27017 --name mongodb mongo
```
Then, you need to run the WAHA with the `WHATSAPP_SESSIONS_MONGO_URL` environment variable (please note using `--network host` option as well)
```bash
docker run -e WHATSAPP_SESSIONS_MONGO_URL=mongodb://localhost:27017/ --network host devlikeapro/whatsapp-http-api-plus
```
This is the only action you need to do to use the MongoDB storage -
all session authentication data will be stored in the MongoDB database.
### How it works
When you start a session, it stores the session data in the MongoDB database in two databases:
1. `waha_{engine}` - it saves the session configuration in `sessions` collection with `name: {sessionName}` field.
2. `waha_{engine}_{sessionName}` - it saves the WhatsApp authentication data and other session data. Each engine saves different data in this database.
When you "logout" the session using [POST /api/sessions/logout]({{< relref "/docs/how-to/sessions#logout">}}) or providing `logout: True` in [POST /api/sessions/stop]({{< relref "/docs/how-to/sessions#stop">}}) it removes those databases or elements from them.
For dealing and troubleshooting with the MongoDB, we recommend using [MongoDB Compass](https://www.mongodb.com/products/tools/compass).
![](waha-mongodb.png)
### MongoDB Atlas
If you use the [MongoDB Atlas](https://www.mongodb.com/atlas/database) you must grant
`Atlas Admin` role in **Security => Database Access** before you connect to the database.
For production please consider running the MongoDB server close to the WAHA server for the best performance and security reasons.
### Health Check
The [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the MongoDB connection.
## Media
When your WhatsApp instance receives media files, it stores them in the media storage.
You can use the following options to store the media files:
1. [Local](#local) - the default option, stores the media files in the local storage using files.
2. [S3](#s3) - stores the media files in the S3 storage.
Read more about [available configuration options ->]({{<relref "/docs/how-to/config#files">}}).
The following table shows the compatibility of the storage with the engines:
| | WEBJS | NOWEB | VENOM |
|-------|:-----:|:-----:|:-----:|
| Local | ✔️ | ✔️ | ✔️ |
| S3 | 🕒 | 🕒 | ➖ |
## Media - Local
By default, the WAHA uses the **local file storage** to store the media files and those files has a short lifetime (180 seconds).
So it's your app responsibility to download and store them in a safe persistent place during this time.
### Save media files between the container restarts
If you want to use the local storage and **save the media files between the container restarts for a long time** - you need to:
1. Specify a dedicated folder to store the media files using `WHATSAPP_FILES_FOLDER=/app/.media` environment variable
2. Disable automatic media files cleanup using `WHATSAPP_FILES_LIFETIME=0` environment variable
3. Connect the volume to the specified folder using the `-v /path/to/files/on/host:/app/.media` option in `docker run` command to the folder specified in `WHATSAPP_FILES_FOLDER` environment variable.
Read more about [available configuration options ->]({{<relref "/docs/how-to/config#files">}}).
Here's all the steps in one command:
```bash
docker run -v /path/to/on/host/.media:/app/.media -e WHATSAPP_FILES_FOLDER=/app/.media -e WHATSAPP_FILES_LIFETIME=0 -p 3000:3000/tcp devlikeapro/whatsapp-http-api-plus
```
### Health Check
The [WAHA Plus ![](/images/versions/plus.png)]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the local storage.
## Media - S3
If you're interested in using the S3 storage or any other cloud storage (like [self-hosted S3 - Minio](https://min.io/)),
please create an issue or vote for the S3 issue in [the GitHub repository](https://github.com/devlikeapro/whatsapp-http-api/issues?q=is%3Aissue+is%3Aopen+S3).
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

@@ -88,8 +88,15 @@ On the URL that you set you'll receive **HTTP POST** request with a JSON string
"event": "message",
"session": "default",
"engine": "WEBJS",
"environment": {
"tier": "PLUS",
"version": "2023.10.12"
},
"me": {
"id": "71111111111@c.us",
"pushName": "~"
},
"payload": {
...
}
}
```
@@ -108,7 +115,37 @@ docker run -it -e "WHATSAPP_HOOK_EVENTS=*" -e WHATSAPP_HOOK_URL=https://httpbin.
## Events
## Webhooks
See the list of engines [**that support the features ->**]({{< relref "/docs/how-to/engines#features" >}}).
### session.status
The `session.status` event is triggered when the session status changes.
- `STOPPED` - session is stopped
- `STARTING` - session is starting
- `SCAN_QR_CODE` - session is required to scan QR code or login via phone number
- `WORKING` - session is working and ready to use
- `FAILED` - session is failed due to some error. It's likely that authorization is required again or device has been disconnected from that account.
Try to restart the session and if it doesn't help - logout and start the session again.
```json
{
"event": "session.status",
"session": "default",
"me": {
"id": "7911111@c.us",
"pushName": "~"
},
"payload": {
"status": "WORKING"
},
"engine": "WEBJS",
"environment": {
"version": "2023.10.12",
"engine": "WEBJS",
"tier": "PLUS"
}
}
```
### message
@@ -220,6 +257,35 @@ The payload may have more fields, it depends on the engine you use, but here's a
}
```
### message.revoked
The `message.revoked` event is triggered when a user, whether it be you or any other participant,
revokes a previously sent message.
```json
{
"event": "message.revoked",
"session": "default",
"payload": {
"before": {
"id": "some-id-here",
"timestamp": "some-timestamp-here",
"body": "Hi there!"
},
"after": {
"id": "some-id-here",
"timestamp": "some-timestamp-here",
"body": ""
}
}
}
```
**Important notes**:
1. The above messages' ids don't match any of the ids you'll receive in the `message` event, it's a different id.
2. In order to find the message that was revoked, you'll need to search for the message with
the same timestamp and chat id as the one in the `after` object.
3. `before` field can be null in some cases.
### state.change
It's an internal engine's state, not **session** `status`.
@@ -19,6 +19,66 @@ If you wish to get and read Release Notes - read them on one of our platforms, *
You even can **subscribe to get new updates** there!
## 2024.2
- Add support for [MongoDB as storage for Session data]({{< relref "/docs/how-to/storages" >}})
- Support persistent file storage for media files - [now you can save media files between container restarts]({{< relref "/docs/how-to/storages#media" >}})
- If you set `WHATSAPP_FILES_LIFETIME=0` environment variable - media files will be never deleted.
- Add `GET /api/health` endpoint to [check the health of the service](https://waha.devlike.pro/docs/how-to/other/)
## 2024.1
- Implement [Patron Portal](https://portal.devlike.pro/) where you can get your personal API key and manage your perks.
- Read more on [Patreon ->](https://www.patreon.com/posts/waha-patron-97637416)
- Read more on [Boosty ->](https://boosty.to/wa-http-api/posts/8319079f-dac1-4179-b954-fcc559097c76)
## 2024.2
- Listen for browser disconnected and page close events in **WEBJS** engine [#262](https://github.com/devlikeapro/whatsapp-http-api/issues/262)
## 2023.12
December 2023
- Add `chatId` field to `GET /api/contacts/check-exists` to help get the right `chatId` for Brazilian numbers.
Read more about
[error sending text to half of Brazilian numbers (every number registered before 2012) ->](https://github.com/devlikeapro/whatsapp-http-api/issues/238)
## 2023.11
November 2023
- Add different formats for QR code:
1. **binary image** - `GET /api/{session}/auth/qr`
2. **base64 image** - `GET /api/{session}/auth/qr` and set `Accept: application/json` header
3. **raw** - `GET /api/{session}/auth/qr?format=raw`
- Add different formats for the screenshot:
1. **binary image** - `GET /api/{session}/screenshot`
2. **base64 image** - `GET /api/{session}/screenshot` and set `Accept: application/json` header
- Add `WHATSAPP_SWAGGER_ENABLED=false` so you can hide Swagger documentation (available only in Plus version). [#185](https://github.com/devlikeapro/whatsapp-http-api/issues/185)
- Add dedicated `media` field in webhook payload - now you can know which media is attached to the message.
```json
{
"event": "message",
"session": "default",
"payload": {
"hasMedia": true,
"media": {
"url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.pdf",
"mimetype": "application/pdf",
"filename": "file.pdf"
}
}
}
```
- Add `WHATSAPP_DOWNLOAD_MEDIA` environment variable to control media download. Available only in Plus version.
- `WHATSAPP_DOWNLOAD_MEDIA=True` - download media
- `WHATSAPP_DOWNLOAD_MEDIA=False` - do not download media at all.
- Add `filename` field for document (file attachments) - the original filename of the document.
- Add `/api/sendVideo` endpoint to **NOWEB** and **WEBJS** engines. Available only in Plus version.
- Add security settings for edit group info `GET /api/{session}/groups/{groupId}/settings/security/info-admin-only` - updates the group settings to only allow admins to edit group info (title, description, photo).
## 2023.10
October 2023
- Add `session.status` event for all engines! Now you can get the latest session's status immediately after it changes.
- Add `message.revoked` event in **WEBJS** engine
- Add `me` field in webhook payload - now you can know which number is associated with the session
- Add `enviroment` field in webhook payload - now you can know which environment is used for the session
## 2023.9
September 2023
- Add `GET /api/sessions/{session/me` endpoint so you [can get the phone number associated with the session](https://waha.devlike.pro/docs/how-to/sessions/#get-me)
@@ -14,6 +14,7 @@ toc: true
---
## How much CPU and Memory does WhatsApp HTTP API consume?
### WEBJS
The benchmark has been made on **Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz**.
It may differ from case to case, it depends on usage pattern - how many messages you get, how many send, etc.
@@ -26,4 +27,10 @@ It may differ from case to case, it depends on usage pattern - how many messages
The nature of WhatsApp HTTP API and its underlying engines - is to run **real** WhatsApp Web version in Chrome and
communicate with it to prevent blocking from WhatsApp. It's the reason why it's so demanding on resources.
### NOWEB
If you're looking for less resource demanded engine - [have a look at **NOWEB** engine ->]({{< relref "/docs/how-to/engines" >}})
The quote from the user:
> The server has 2 CPU and 8GB of memory.
> Today we have 85 session in this instance.
@@ -27,6 +27,9 @@ When developing a bot for WhatsApp, you **should never initiate a conversation**
Instead, your bot **should only reply** to messages that it receives.
This will prevent your bot from being flagged as spam by WhatsApp's users and algorithms.
> You can use a short link http://wa.me/7911111111?text=Hi
> so a user can click on it and start the dialog with the bot first
### 2. Avoid Spamming and Sending Unnecessary Content
Sending too many messages or sending content that the user did not request can also lead to your bot being blocked. Make
@@ -56,3 +59,34 @@ Here's a recommended process to follow:
By following these steps, you can ensure that your bot processes messages in a way that's compliant with WhatsApp's
guidelines and reduces the risk of being blocked.
## How to not get Banned?
WhatsApp knows that it's uncommon for someone to send so many messages or bulk messages to people they've never talked to each other before so it is considered spam/marketing junk pretty fast. There are some tips before sending a message to WhatsApp
**Dos and Don'ts:**
1. Important: Do NOT send messages which get you a report. As long as you don't get reports from users who you sent a message, your account will be mostly fine.
2. Having real content, a survey that the person agreed with is different from a marketing message on a Saturday night.
3. Send messages written in different ways, you could make a script that places spacebars randomly on your string AND includes the person's (first) name
4. Never use fixed times, always go for sending the first message, wait a random time between 30 ~ and 60 seconds and then send the second message
5. Always try to group contacts by their area code, WhatsApp expects a regular person to talk mostly with contacts that are within the same area of your phone number.
6. Have a profile picture, this is not related to WhatsApp Bots Catcher® but sending a new message for someone not having a picture/name/status will elevate your chances of being manually tagged as spam.
7. Send "seen" confirmation to messages or disable it on WhatsApp
8. Avoid sending links that were previously marked as spam on WhatsApp or non-HTTPS. A URL shortener is a good idea
9. IMPORTANT: It's terrible if you send messages 24/7 without giving it some time to wait. Random delays between messages are not enough, send a reasonable amount of messages keeping in mind your conversion rate, For example: for one hour send a maximum of 4 messages per contact that have replied to your message, and stop sending messages for one hour, then start again. Again, don't send messages without stopping for a while between every "package"
10. Send only one short message when starting a conversation, one should not send long texts or multiple messages without the user consenting
**Have in mind:**
1. For every one you send a message that doesn't have your number on their contact list asked if it's spam, being tagged as spam a few times (5 - 10) will get you banned
2. WhatsApp records every movement you do, you can even check the logs when sending simple support email, it contains all kinds of information, this said: act as human as possible
3. Try to engage in conversations, as long as you send a message and the person doesn't automatically block you it'll be quite okay. People constantly talking to you and adding you to their contact list will make your number stronger against a ban
4. Think about that like a points system, you start with zero points (negative if your device was previously blacklisted), if you reach below zero you are out, if you engage in conversations you get a point, if you are tagged as spam you lose some points, if you are blocked you may lose more points
5. Finally, If your content is spam, it doesn't matter if you are using a broadcast list, group, or direct contact, you will still be banned
As API, we say all that's left to do right now is to agree with WhatsApp's policy, not send spam messages, and always wait for the other person to contact you first.
You could make it by sending an SMS to the person with a link to start a chat on WhatsApp with you by link [https://wa.me/12132132131?text=Hi](https://wa.me/12132132131?text=Hi).
@@ -30,6 +30,8 @@ WAHA is distributed in two versions:
- Core ![](/images/versions/core.png) - the basic version that meet almost 80% people's needs. 100% free and [open source ->](https://github.com/devlikeapro/whatsapp-http-api).
- Plus ![](/images/versions/plus.png) - the version with advanced messages, security, and reliability features. Donations, no license expiration, quick updates, read more about [Plus Version →]({{< relref "plus-version" >}})
See the list of engines [**that support the features ->**]({{< relref "/docs/how-to/engines#features" >}}).
Here's the available features:
### Messages
+71 -46
View File
@@ -1,79 +1,104 @@
{{ define "main" }}
<section class="section container-fluid mt-n3 pb-3">
<div class="row justify-content-center">
<div class="col-lg-12 text-center">
<h1 class="mt-0">{{ .Title }}</h1>
<section class='section container-fluid mt-n3 pb-3'>
<div class='row justify-content-center'>
<div class='col-lg-12 text-center'>
<h1 class='mt-0'>{{ .Title }}</h1>
</div>
<div class="col-lg-9 col-xl-9 text-center">
<div class="mb-4">
<img src="/images/logo.png" title="WhatsApp HTTP API" alt="logo" width="100"/>
<div class='col-lg-9 col-xl-9 text-center'>
<div class='mb-4'>
<img src='/images/logo.png' title='WhatsApp HTTP API' alt='logo' width='100' />
</div>
<p class="lead">{{ .Params.lead | safeHTML }}</p>
<p class='lead'>{{ .Params.lead | safeHTML }}</p>
<code>
docker run -it -p 3000:3000/tcp devlikeapro/whatsapp-http-api
</code>
<br/>
<br/>
<a class="btn btn-primary btn-lg px-4 mb-2"
href="/docs/{{ if .Site.Params.options.docsVersioning }}{{ .Site.Params.docsVersion }}/{{ end }}overview/introduction/"
role="button">Get Started</a>
<p class="meta"><a href="https://github.com/devlikeapro/whatsapp-http-api">Source code in GitHub.</a></p>
<br />
<br />
<a class='btn btn-primary btn-lg px-4 mb-2'
href='/docs/{{ if .Site.Params.options.docsVersioning }}{{ .Site.Params.docsVersion }}/{{ end }}overview/introduction/'
role='button'>Get Started</a>
<p class='meta'><a href='https://github.com/devlikeapro/whatsapp-http-api'>Source code in GitHub.</a></p>
</div>
</div>
</section>
{{ end }}
{{ define "sidebar-prefooter" }}
<section class="section section-sm">
<div class="container">
<div class="row justify-content-center text-center">
<div class="col-lg-5">
<h2 class="h4">It's free!</h2>
<section class='section section-sm'>
<div class='container'>
<div class='row justify-content-center text-center'>
<div class='col-lg-5'>
<img src='/images/icons/free.png' alt='Free' style='width: 5rem'>
<h2 class='h4'>It's free!</h2>
<p>
<b>WAHA Core</b> version is always free!
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>
<b>WAHA Core</b>
</a>
version is always free!
<br>
Even <b>WAHA Plus</b> version have no licence expiration!
Even
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>
<b>WAHA Plus</b>
</a>
version have no licence expiration!
</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Language agnostic</h2>
<div class='col-lg-5'>
<img src='/images/icons/api.png' alt='API' style='width: 5rem'>
<h2 class='h4'>Language agnostic</h2>
<p>
Use your own favorite language - Python, JavaScript, PHP, C#, Clojure, or PowerShell.
<br/>
<small class="text-muted">
<br />
<small class='text-muted'>
PowerShell, really? Are you insane?! Choose another language, dude.
</small>
</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Well documented</h2>
<p>Documentation has a lof examples and how-to guides.</p>
<div class='col-lg-5'>
<img src='/images/icons/document.png' alt='Document' style='width: 5rem'>
<h2 class='h4'>Well documented</h2>
<p>
<a href='https://waha.devlike.pro/docs/overview/introduction/' target='_blank'>
Documentation
</a>
has a lof examples and how-to guides.</p>
</div>
</div>
<div class="row justify-content-center text-center">
<div class="col-lg-5">
<h2 class="h4">Self hosted</h2>
<div class='row justify-content-center text-center'>
<div class='col-lg-5'>
<img src='/images/icons/servers.png' alt='Servers' style='width: 5rem'>
<h2 class='h4'>Self-hosted solution</h2>
<p>
No strings to suspicious SaaS WhatsApp HTTP API solutions. Install it on your own server!
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#why-waha' target='_blank'>
No strings to suspicious SaaS WhatsApp HTTP API solutions.
</a>
Install it on your own server!
</p>
</div>
<div class="col-lg-5">
<h2 class="h4">Easy installation</h2>
<div class='col-lg-5'>
<img src='/images/icons/easy.png' alt='Easy' style='width: 5rem'>
<h2 class='h4'>Quick installation</h2>
<p>
You need to install <a href="https://docs.docker.com/engine/install/">Docker</a> and can run the API in a
click!
<br/>
<small class="text-muted">
You need to install Docker and
<a href='https://waha.devlike.pro/docs/how-to/install/' target='_blank'>
run the API in a click!
</a>
<br />
<small class='text-muted'>
It's actually "a command", not a click.
</small>
</p>
</div>
<div class="col-lg-5">
<h2 class="h4">No blocking</h2>
<div class='col-lg-5'>
<img src='/images/icons/checked.png' alt='Checked' style='width: 5rem'>
<h2 class='h4'>No blocking</h2>
<p>
Under the hood it runs a real instance of Whatsapp Web to avoid getting blocked.
<br/>
<small class="text-muted">
<a href='https://waha.devlike.pro/docs/how-to/engines/' target='_blank'>
Under the hood
</a>
it runs a real instance of Whatsapp Web to avoid getting blocked.
<br />
<small class='text-muted'>
WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered
totally safe.
</small>
@@ -85,9 +110,9 @@
{{ end }}
{{ define "sidebar-footer" }}
<section class="section section-sm container-fluid">
<div class="row justify-content-center text-center">
<div class="col-lg-9">
<section class='section section-sm container-fluid'>
<div class='row justify-content-center text-center'>
<div class='col-lg-9'>
{{- .Content -}}
</div>
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+16
View File
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
+13 -51
View File
@@ -1,57 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8">
<title>WAHA - WhatsApp HTTP API</title>
<link href="./swagger-ui.css" rel="stylesheet" type="text/css">
<link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/>
<link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/>
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
<title>WAHA | Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script charset="UTF-8" src="./swagger-ui-bundle.js"></script>
<script charset="UTF-8" src="./swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function () {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
+26 -24
View File
@@ -4,45 +4,41 @@
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
</body>
</html>
<script>
'use strict';
function run() {
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
arr = qp.split("&")
arr.forEach(function (v, i, _arr) {
_arr[i] = '"' + v.replace('=', '":"') + '"';
})
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value)
}
) : {}
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState
isValid = qp.state === sentState;
if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode"
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}
@@ -51,18 +47,18 @@
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "[" + qp.error + "]: " +
(qp.error_description ? qp.error_description + ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: " + qp.error_uri : "");
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
@@ -71,7 +67,13 @@
window.close();
}
window.addEventListener('DOMContentLoaded', function () {
if (document.readyState !== 'loading') {
run();
});
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>
+1 -1
View File
@@ -1 +1 @@
{"openapi":"3.0.0","paths":{"/api/{session}/auth/qr":{"get":{"operationId":"AuthController_getQR","summary":"Get QR code for pairing WhatsApp Web.","parameters":[{"name":"session","required":true,"in":"path","description":"WhatsApp session name","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/request-code":{"post":{"operationId":"AuthController_requestCode","summary":"Request authentication code. NOWEB and NOWEB_MOBILE engines only","parameters":[{"name":"session","required":true,"in":"path","description":"WhatsApp session name","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCodeRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/authorize-code":{"post":{"operationId":"AuthController_authorizeCode","summary":"Send OTP authentication code. NOWEB_MOBILE engine only","parameters":[{"name":"session","required":true,"in":"path","description":"WhatsApp session name","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OTPRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/sessions/start":{"post":{"operationId":"SessionsController_start","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDTO"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/stop":{"post":{"operationId":"SessionsController_stop","summary":"Stop session","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStopRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/logout":{"post":{"operationId":"SessionsController_clean","summary":"Logout from session.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogoutRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions":{"get":{"operationId":"SessionsController_list","parameters":[{"name":"all","required":false,"in":"query","example":false,"description":"Return all sessions, including those that are in the STOPPED state.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionDTO"}}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/checkNumberStatus":{"get":{"operationId":"ChattingController_checkNumberStatus","summary":"Check number status","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WANumberExistResult"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendContactVcard":{"post":{"operationId":"ChattingController_sendContactVcard","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageContactVcardRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendText":{"get":{"operationId":"ChattingController_sendTextGet","summary":"Send a text message","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"text","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]},"post":{"operationId":"ChattingController_sendText","summary":"Send a text message","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageTextRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WAMessage"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendTextButtons":{"post":{"operationId":"ChattingController_sendTextButtons","summary":"Send a text message with buttons","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageTextButtonsRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"taLine truncated
{"openapi":"3.1.0","paths":{"/api/{session}/auth/qr":{"get":{"operationId":"AuthController_getQR","summary":"Get QR code for pairing WhatsApp Web.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"},{"name":"format","required":true,"in":"query","schema":{"default":"image","enum":["image","raw"],"type":"string"}}],"responses":{"200":{"content":{"image/png":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Base64File"},{"$ref":"#/components/schemas/QRCodeValue"}]}}},"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/request-code":{"post":{"operationId":"AuthController_requestCode","summary":"Request authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCodeRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/authorize-code":{"post":{"operationId":"AuthController_authorizeCode","summary":"Send OTP authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OTPRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/sessions/start":{"post":{"operationId":"SessionsController_start","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDTO"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/stop":{"post":{"operationId":"SessionsController_stop","summary":"Stop session","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStopRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/logout":{"post":{"operationId":"SessionsController_clean","summary":"Logout from session.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogoutRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions":{"get":{"operationId":"SessionsController_list","parameters":[{"name":"all","required":false,"in":"query","example":false,"description":"Return all sessions, including those that are in the STOPPED state.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionInfo"}}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/{session}/me":{"get":{"operationId":"SessionController_getMe","summary":"Get information about the authenticated account","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeInfo"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/checkNumberStatus":{"get":{"operationId":"ChattingController_checkNumberStatus","summary":"Check number status","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WANumberExistResult"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendContactVcard":{"post":{"operationId":"ChattingController_sendContactVcard","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageContactVcardRequest"}}}},"responses":{"201":{"description":""}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendText":{"get":{"operationId":"ChattingController_sendTextGet","summary":"Send a text message","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"text","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]},"post":{"operationId":"ChattingController_sendText","summary":"Send a text message","parameters":[],"requestBody":{"required":true,Line truncated
@@ -0,0 +1,20 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};
@@ -1,3 +1,3 @@
/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(function(){try{return require("esprima")}catch(e){}}()):"function"==typeof define&&define.amd?define(["esprima"],t):"object"==typeof exports?exports.SwaggerUIBundle=t(function(){try{return require("esprima")}catch(e){}}()):e.SwaggerUIBundle=t(e.esprima)}(this,(function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=544)}([function(e,t,n){"use strict";e.exports=n(129)},function(e,t,n){e.exports=function(){"use strict";var e=Array.prototype.slice;function t(e,t){t&&(e.prototype=Object.create(t.prototype)),e.prototype.constructor=e}function n(e){return i(e)?e:J(e)}function r(e){return s(e)?e:K(e)}function o(e){return u(e)?e:Y(e)}function a(e){return i(e)&&!c(e)?e:G(e)}function i(e){return!(!e||!e[p])}function s(e){return!(!e||!e[f])}function u(e){return!(!e||!e[h])}function c(e){return s(e)||u(e)}function l(e){return!(!e||!e[d])}t(r,n),t(o,n),t(a,n),n.isIterable=i,n.isKeyed=s,n.isIndexed=u,n.isAssociative=c,n.isOrdered=l,n.Keyed=r,n.Indexed=o,n.Set=a;var p="@@__IMMUTABLE_ITERABLE__@@",f="@@__IMMUTABLE_KEYED__@@",h="@@__IMMUTABLE_INDEXED__@@",d="@@__IMMUTABLE_ORDERED__@@",m="delete",v=5,g=1<<v,y=g-1,b={},_={value:!1},w={value:!1};function x(e){return e.value=!1,e}function E(e){e&&(e.value=!0)}function S(){}function C(e,t){t=t||0;for(var n=Math.max(0,e.length-t),r=new Array(n),o=0;o<n;o++)r[o]=e[o+t];return r}function A(e){return void 0===e.size&&(e.size=e.__iterate(O)),e.size}function k(e,t){if("number"!=typeof t){var n=t>>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?A(e)+t:t}function O(){return!0}function j(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function T(e,t){return N(e,t,0)}function I(e,t){return N(e,t,t)}function N(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}var P=0,M=1,R=2,D="function"==typeof Symbol&&Symbol.iterator,L="@@iterator",B=D||L;function F(e){this.next=e}function U(e,t,n,r){var o=0===e?t:1===e?n:[t,n];return r?r.value=o:r={value:o,done:!1},r}function q(){return{value:void 0,done:!0}}function z(e){return!!H(e)}function V(e){return e&&"function"==typeof e.next}function W(e){var t=H(e);return t&&t.call(e)}function H(e){var t=e&&(D&&e[D]||e[L]);if("function"==typeof t)return t}function $(e){return e&&"number"==typeof e.length}function J(e){return null==e?ie():i(e)?e.toSeq():ce(e)}function K(e){return null==e?ie().toKeyedSeq():i(e)?s(e)?e.toSeq():e.fromEntrySeq():se(e)}function Y(e){return null==e?ie():i(e)?s(e)?e.entrySeq():e.toIndexedSeq():ue(e)}function G(e){return(null==e?ie():i(e)?s(e)?e.entrySeq():e:ue(e)).toSetSeq()}F.prototype.toString=function(){return"[Iterator]"},F.KEYS=P,F.VALUES=M,F.ENTRIES=R,F.prototype.inspect=F.prototype.toSource=function(){return this.toString()},F.prototype[B]=function(){return this},t(J,n),J.of=function(){return J(arguments)},J.prototype.toSeq=function(){return this},J.prototype.toString=function(){return this.__toString("Seq {","}")},J.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},J.prototype.__iterate=function(e,t){return pe(this,e,t,!0)},J.prototype.__iterator=function(e,t){return fe(this,e,t,!0)},t(K,J),K.prototype.toKeyedSeq=function(){return this},t(Y,J),Y.of=function(){return Y(arguments)},Y.prototype.toIndexedSeq=function(){return this},Y.prototype.toString=function(){return this.__toString("Seq [","]")},Y.prototype.__iterate=function(e,t){return pe(this,e,t,!1)},Y.prototype.__iterator=function(e,t){return fe(this,e,t,!1)},t(G,J),G.of=function(){return G(arguments)},G.prototype.toSetSeq=function(){return this},J.isSeq=ae,J.Keyed=K,J.Set=G,J.Indexed=Y;var Z,X,Q,ee="@@__IMMUTABLE_SEQ__@@";function te(e){this._array=e,this.size=e.length}function ne(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function re(e){this._iterable=e,this.size=e.length||e.size}function oe(e){this._iterator=e,this._iteratorCache=[]}function ae(e){return!(!e||!e[ee])}function ie(){return Z||(Z=new te([]))}function se(e){var t=Array.isArray(Line truncated
//# sourceMappingURL=swagger-ui-bundle.js.map
!function webpackUniversalModuleDefinition(i,s){"object"==typeof exports&&"object"==typeof module?module.exports=s():"function"==typeof define&&define.amd?define([],s):"object"==typeof exports?exports.SwaggerUIBundle=s():i.SwaggerUIBundle=s()}(this,(()=>(()=>{var i={17967:(i,s)=>{"use strict";s.Nm=s.Rq=void 0;var u=/^([^\w]*)(javascript|data|vbscript)/im,m=/&#(\w+)(^\w|;)?/g,v=/&(newline|tab);/gi,_=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,j=/^.+(:|&colon;)/gim,M=[".","/"];s.Rq="about:blank",s.Nm=function sanitizeUrl(i){if(!i)return s.Rq;var $=function decodeHtmlCharacters(i){return i.replace(_,"").replace(m,(function(i,s){return String.fromCharCode(s)}))}(i).replace(v,"").replace(_,"").trim();if(!$)return s.Rq;if(function isRelativeUrlWithoutProtocol(i){return M.indexOf(i[0])>-1}($))return $;var W=$.match(j);if(!W)return $;var X=W[0];return u.test(X)?s.Rq:$}},79742:(i,s)=>{"use strict";s.byteLength=function byteLength(i){var s=getLens(i),u=s[0],m=s[1];return 3*(u+m)/4-m},s.toByteArray=function toByteArray(i){var s,u,_=getLens(i),j=_[0],M=_[1],$=new v(function _byteLength(i,s,u){return 3*(s+u)/4-u}(0,j,M)),W=0,X=M>0?j-4:j;for(u=0;u<X;u+=4)s=m[i.charCodeAt(u)]<<18|m[i.charCodeAt(u+1)]<<12|m[i.charCodeAt(u+2)]<<6|m[i.charCodeAt(u+3)],$[W++]=s>>16&255,$[W++]=s>>8&255,$[W++]=255&s;2===M&&(s=m[i.charCodeAt(u)]<<2|m[i.charCodeAt(u+1)]>>4,$[W++]=255&s);1===M&&(s=m[i.charCodeAt(u)]<<10|m[i.charCodeAt(u+1)]<<4|m[i.charCodeAt(u+2)]>>2,$[W++]=s>>8&255,$[W++]=255&s);return $},s.fromByteArray=function fromByteArray(i){for(var s,m=i.length,v=m%3,_=[],j=16383,M=0,$=m-v;M<$;M+=j)_.push(encodeChunk(i,M,M+j>$?$:M+j));1===v?(s=i[m-1],_.push(u[s>>2]+u[s<<4&63]+"==")):2===v&&(s=(i[m-2]<<8)+i[m-1],_.push(u[s>>10]+u[s>>4&63]+u[s<<2&63]+"="));return _.join("")};for(var u=[],m=[],v="undefined"!=typeof Uint8Array?Uint8Array:Array,_="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",j=0;j<64;++j)u[j]=_[j],m[_.charCodeAt(j)]=j;function getLens(i){var s=i.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var u=i.indexOf("=");return-1===u&&(u=s),[u,u===s?0:4-u%4]}function encodeChunk(i,s,m){for(var v,_,j=[],M=s;M<m;M+=3)v=(i[M]<<16&16711680)+(i[M+1]<<8&65280)+(255&i[M+2]),j.push(u[(_=v)>>18&63]+u[_>>12&63]+u[_>>6&63]+u[63&_]);return j.join("")}m["-".charCodeAt(0)]=62,m["_".charCodeAt(0)]=63},48764:(i,s,u)=>{"use strict";const m=u(79742),v=u(80645),_="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;s.Buffer=Buffer,s.SlowBuffer=function SlowBuffer(i){+i!=i&&(i=0);return Buffer.alloc(+i)},s.INSPECT_MAX_BYTES=50;const j=2147483647;function createBuffer(i){if(i>j)throw new RangeError('The value "'+i+'" is invalid for option "size"');const s=new Uint8Array(i);return Object.setPrototypeOf(s,Buffer.prototype),s}function Buffer(i,s,u){if("number"==typeof i){if("string"==typeof s)throw new TypeError('The "string" argument must be of type string. Received type number');return allocUnsafe(i)}return from(i,s,u)}function from(i,s,u){if("string"==typeof i)return function fromString(i,s){"string"==typeof s&&""!==s||(s="utf8");if(!Buffer.isEncoding(s))throw new TypeError("Unknown encoding: "+s);const u=0|byteLength(i,s);let m=createBuffer(u);const v=m.write(i,s);v!==u&&(m=m.slice(0,v));return m}(i,s);if(ArrayBuffer.isView(i))return function fromArrayView(i){if(isInstance(i,Uint8Array)){const s=new Uint8Array(i);return fromArrayBuffer(s.buffer,s.byteOffset,s.byteLength)}return fromArrayLike(i)}(i);if(null==i)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof i);if(isInstance(i,ArrayBuffer)||i&&isInstance(i.buffer,ArrayBuffer))return fromArrayBuffer(i,s,u);if("undefined"!=typeof SharedArrayBuffer&&(isInstance(i,SharedArrayBuffer)||i&&isInstance(i.buffer,SharedArrayBuffer)))return fromArrayBuffer(i,s,u);if("number"==typeof i)throw new TypeError('The "value" argument must not be of type number. Received type number');const m=i.valueOf&&i.valueOf();if(null!=m&&m!==i)return Buffer.from(m,s,u);const v=function fromObject(i){if(Buffer.isBuffer(i)){const s=0|checked(i.length),u=createBuffer(s);return 0===u.length||i.copy(u,0,0,s),u}if(void 0!==i.length)return"number"!=typeof i.length||numberIsNaN(i.length)?createBuffer(0):fromArrayLike(i);if("Buffer"===i.type&&Array.isArray(i.data))return fromArrayLike(i.data)}(i);if(v)return v;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof i[Symbol.toPrimitive])return Buffer.from(i[Symbol.toPrimitive]("string"),s,u);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof i)}function assertSize(i){if("number"!=typeof i)throw new TypeError('"size" argument must be of type number');if(i<0)throw new RangeError('The value "'+i+'" is invalid for option "size"')}function allocUnsafe(i){return assertSize(i),createBuffer(i<0Line truncated
//# sourceMappingURL=swagger-ui-bundle.js.map
@@ -1 +1 @@
{"version":3,"sources":["webpack://SwaggerUIBundle/webpack/universalModuleDefinition","webpack://SwaggerUIBundle/webpack/bootstrap","webpack://SwaggerUIBundle/./node_modules/react/react.js","webpack://SwaggerUIBundle/./node_modules/immutable/dist/immutable.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/defineProperty.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createClass.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/classCallCheck.js","webpack://SwaggerUIBundle/./src/core/utils.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/inherits.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createSuper.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/assertThisInitialized.js","webpack://SwaggerUIBundle/./node_modules/prop-types/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/slicedToArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/keys.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/toConsumableArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js","webpack://SwaggerUIBundle/./node_modules/reselect/es/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/typeof.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/export.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectSpread2.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/invariant.js","webpack://SwaggerUIBundle/./src/core/window.js","webpack://SwaggerUIBundle/./node_modules/react-immutable-proptypes/dist/ImmutablePropTypes.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/extends.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js","webpack://SwaggerUIBundle/./node_modules/react-dom/lib/reactProdInvariant.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/path.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/warning.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/fails.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js","webpack://SwaggerUIBundle/./src/core/plugins/oas3/helpers.jsx","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/object-assign/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/regenerator/index.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/global.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/entry-virtual.js","webpack://SwaggerUIBundle/./node_modules/react-dom/lib/ReactDOMComponentTree.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/is-object.js","webpack://SwaggerUIBundle/./node_modules/lodash/get.js","webpack://SwaggerUIBundle/./src/core/plugins/spec/actions.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/descriptors.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/define-well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/js-yaml/lib/js-yaml/type.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createForOfIteratorHelper.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/has.js","webpack://SwaggerUIBundle/./node_modules/lodash/isArray.js","webpack://SwaggerUIBundle/(webpack)/buildin/global.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/an-object.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectWithoutProperties.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/ExecutionEnvironment.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3Line truncated
{"version":3,"file":"swagger-ui-bundle.js","mappings":"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 truncated
@@ -1,3 +1,3 @@
/*! For license information please see swagger-ui-es-bundle-core.js.LICENSE.txt */
module.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=410)}([function(e,t){e.exports=require("react")},function(e,t){e.exports=require("immutable")},function(e,t,n){e.exports=n(449)},function(e,t,n){var r=n(191);e.exports=function(e,t,n){return t in e?r(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){e.exports=n(452)},function(e,t,n){var r=n(191);function a(e,t){for(var n=0;n<t.length;n++){var a=t[n];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),r(e,a.key,a)}}e.exports=function(e,t,n){return t&&a(e.prototype,t),n&&a(e,n),e}},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";(function(e){n.d(t,"t",(function(){return me})),n.d(t,"A",(function(){return ve})),n.d(t,"i",(function(){return ge})),n.d(t,"w",(function(){return ye})),n.d(t,"r",(function(){return be})),n.d(t,"u",(function(){return Ee})),n.d(t,"s",(function(){return xe})),n.d(t,"p",(function(){return Se})),n.d(t,"v",(function(){return we})),n.d(t,"y",(function(){return je})),n.d(t,"z",(function(){return Ce})),n.d(t,"K",(function(){return Oe})),n.d(t,"f",(function(){return _e})),n.d(t,"n",(function(){return Ae})),n.d(t,"h",(function(){return ke})),n.d(t,"E",(function(){return Ie})),n.d(t,"L",(function(){return Fe})),n.d(t,"o",(function(){return Ye})),n.d(t,"D",(function(){return Ke})),n.d(t,"a",(function(){return Ge})),n.d(t,"I",(function(){return Ze})),n.d(t,"b",(function(){return Xe})),n.d(t,"H",(function(){return Qe})),n.d(t,"G",(function(){return et})),n.d(t,"F",(function(){return tt})),n.d(t,"k",(function(){return nt})),n.d(t,"d",(function(){return rt})),n.d(t,"g",(function(){return at})),n.d(t,"m",(function(){return ot})),n.d(t,"l",(function(){return it})),n.d(t,"e",(function(){return ct})),n.d(t,"J",(function(){return st})),n.d(t,"x",(function(){return ut})),n.d(t,"B",(function(){return lt})),n.d(t,"C",(function(){return pt})),n.d(t,"j",(function(){return ft})),n.d(t,"c",(function(){return dt})),n.d(t,"q",(function(){return mt}));var r=n(82),a=n.n(r),o=n(130),i=n.n(o),c=n(50),s=n.n(c),u=n(13),l=n.n(u),p=n(30),f=n.n(p),d=n(17),h=n.n(d),m=(n(34),n(32)),v=n.n(m),g=(n(24),n(15),n(157)),y=n.n(g),b=n(21),E=n.n(b),x=n(22),S=n.n(x),w=(n(29),n(16)),j=n.n(w),C=n(12),O=n.n(C),_=n(18),A=n.n(_),k=n(2),I=n.n(k),P=n(45),T=n.n(P),N=n(71),R=n.n(N),M=n(4),D=n.n(M),q=n(14),L=n.n(q),B=n(20),U=n.n(B),V=n(1),z=n.n(V),F=n(375),J=n(376),W=n.n(J),H=n(207),$=n.n(H),Y=n(208),K=n.n(Y),G=n(158),Z=n.n(G),X=n(266),Q=n.n(X),ee=n(102),te=n.n(ee),ne=n(58),re=n.n(ne),ae=n(112),oe=n(26),ie=n(378),ce=n.n(ie),se=n(114),ue=n(379),le=n.n(ue),pe=n(380),fe=n.n(pe),de="default",he=function(e){return z.a.Iterable.isIterable(e)};function me(e){try{var t=JSON.parse(e);if(t&&"object"===U()(t))return t}catch(e){}return!1}function ve(e){return Ee(e)?he(e)?e.toJS():e:{}}function ge(e){var t,n;if(he(e))return e;if(e instanceof oe.a.File)return e;if(!Ee(e))return e;if(L()(e))return D()(n=z.a.Seq(e)).call(n,ge).toList();if(re()(R()(e))){var r,a=function(e){if(!re()(R()(e)))return e;var t,n={},r="_**[]",a={},o=T()(R()(e).call(e));try{for(o.s();!(t=o.n()).done;){var i=t.value;if(n[i[0]]||a[i[0]]&&a[i[0]].containsMultiple){var c,s,u,l;if(!a[i[0]])a[i[0]]={containsMultiple:!0,length:1},n[I()(u=I()(l="".concat(i[0])).call(l,r)).call(u,a[i[0]].length)]=n[i[0]],delete n[i[0]];a[i[0]].length+=1,n[I()(c=I()(s="".concat(i[0])).call(s,r)).call(c,a[i[0]].length)]=i[1]}else n[i[0]]=i[1]}}catch(e){o.e(e)}finally{o.f()}return n}(e);return D()(r=z.a.OrderedMap(a)).call(r,ge)}return D()(t=z.a.OrderedMap(e)).call(t,ge)}function ye(e){return L()(e)?e:[e]}function be(e){return"function"==typeof e}function Ee(e){return!!e&&"object"===U()(e)}function xe(e){return"function"==typeof e}function Se(e){return L()(e)}var we=K.a;function je(e,t){var n;return S()(n=j()(e)).call(n,(function(n,r){return n[r]=t(e[r],r),n}),{})}function Ce(e,t){var n;return S()(n=j()(e)).call(n,(function(n,r){var a=t(e[r],r);return a&&"object"===U()(a)&&E()(n,a),n}),{})}function Oe(e){return function(t){t.dispatch,t.getStateLine truncated
//# sourceMappingURL=swagger-ui-es-bundle-core.js.map
import*as e from"base64-js";import*as t from"ieee754";import*as r from"repeat-string";import*as n from"react";import*as a from"redux";import*as o from"immutable";import*as s from"redux-immutable";import*as l from"serialize-error";import*as i from"lodash/merge";import*as c from"@braintree/sanitize-url";import*as u from"lodash/camelCase";import*as d from"lodash/upperFirst";import*as p from"lodash/memoize";import*as m from"lodash/find";import*as f from"lodash/some";import*as h from"lodash/eq";import*as g from"lodash/isFunction";import*as y from"css.escape";import*as v from"url-parse";import*as S from"reselect";import*as _ from"prop-types";import*as b from"lodash/omit";import*as w from"js-yaml";import*as C from"zenscroll";import*as x from"react-immutable-proptypes";import*as O from"lodash/reduce";import*as k from"lodash/get";import*as N from"@babel/runtime-corejs3/helpers/extends";import*as A from"react-copy-to-clipboard";import*as I from"react-syntax-highlighter/dist/esm/light";import*as R from"react-syntax-highlighter/dist/esm/languages/hljs/javascript";import*as T from"react-syntax-highlighter/dist/esm/languages/hljs/json";import*as B from"react-syntax-highlighter/dist/esm/languages/hljs/bash";import*as j from"react-syntax-highlighter/dist/esm/languages/hljs/yaml";import*as P from"react-syntax-highlighter/dist/esm/languages/hljs/http";import*as M from"react-syntax-highlighter/dist/esm/languages/hljs/powershell";import*as q from"react-syntax-highlighter/dist/esm/styles/hljs/agate";import*as L from"react-syntax-highlighter/dist/esm/styles/hljs/arta";import*as D from"react-syntax-highlighter/dist/esm/styles/hljs/monokai";import*as U from"react-syntax-highlighter/dist/esm/styles/hljs/nord";import*as $ from"react-syntax-highlighter/dist/esm/styles/hljs/obsidian";import*as J from"react-syntax-highlighter/dist/esm/styles/hljs/tomorrow-night";import*as V from"react-syntax-highlighter/dist/esm/styles/hljs/idea";import*as K from"randexp";import*as z from"lodash/isEmpty";import*as F from"lodash/isString";import*as W from"lodash/debounce";import*as H from"lodash/set";import*as G from"lodash/fp/assocPath";import*as X from"lodash/constant";import*as Y from"swagger-client/es/resolver/strategies/generic";import*as Q from"swagger-client/es/resolver/strategies/openapi-2";import*as Z from"swagger-client/es/resolver/strategies/openapi-3-0";import*as ee from"swagger-client/es/resolver/strategies/openapi-3-1-apidom";import*as te from"swagger-client/es/resolver";import*as re from"swagger-client/es/execute";import*as ne from"swagger-client/es/http";import*as ae from"swagger-client/es/subtree-resolver";import*as oe from"swagger-client/es/helpers";import*as se from"react-dom";import*as le from"react-redux";import*as ie from"lodash/identity";import*as ce from"lodash/zipObject";import*as ue from"lodash/toString";import*as de from"classnames";import*as pe from"js-file-download";import*as me from"lodash/toLower";import*as fe from"react-immutable-pure-component";import*as he from"remarkable";import*as ge from"remarkable/linkify";import*as ye from"dompurify";import*as Ee from"react-debounce-input";import*as ve from"lodash/isPlainObject";var Se={764:function(e,t,r){const n=r(780),a=r(294),o="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=Buffer,t.SlowBuffer=function SlowBuffer(e){+e!=e&&(e=0);return Buffer.alloc(+e)},t.INSPECT_MAX_BYTES=50;const s=2147483647;function createBuffer(e){if(e>s)throw new RangeError('The value "'+e+'" is invalid for option "size"');const t=new Uint8Array(e);return Object.setPrototypeOf(t,Buffer.prototype),t}function Buffer(e,t,r){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return allocUnsafe(e)}return from(e,t,r)}function from(e,t,r){if("string"==typeof e)return function fromString(e,t){"string"==typeof t&&""!==t||(t="utf8");if(!Buffer.isEncoding(t))throw new TypeError("Unknown encoding: "+t);const r=0|byteLength(e,t);let n=createBuffer(r);const a=n.write(e,t);a!==r&&(n=n.slice(0,a));return n}(e,t);if(ArrayBuffer.isView(e))return function fromArrayView(e){if(isInstance(e,Uint8Array)){const t=new Uint8Array(e);return fromArrayBuffer(t.buffer,t.byteOffset,t.byteLength)}return fromArrayLike(e)}(e);if(null==e)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(isInstance(e,ArrayBuffer)||e&&isInstance(e.buffer,ArrayBuffer))return fromArrayBuffer(e,t,r);if("undefined"!=typeof SharedArrayBuffer&&(isInstance(e,SharedArrayBuffer)||e&&isInstance(e.buffer,SharedArrayBuffer)))return fromArrayBuffer(e,t,r);if("number"==typeof e)throw new TypeError('The "value" argument must not be of type number. Received type number');const n=e.valueOf&&e.valueOf();if(null!=n&&n!==e)return Buffer.from(n,t,r);const a=function fromObject(e){if(Buffer.isBuffer(e)){const t=0|checked(e.length),r=creaLine truncated
//# sourceMappingURL=swagger-ui-es-bundle-core.js.map
@@ -1 +1 @@
{"version":3,"sources":["webpack://SwaggerUIBundle/webpack/bootstrap","webpack://SwaggerUIBundle/external \"react\"","webpack://SwaggerUIBundle/external \"immutable\"","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/defineProperty.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createClass.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/classCallCheck.js","webpack://SwaggerUIBundle/./src/core/utils.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/inherits.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createSuper.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/assertThisInitialized.js","webpack://SwaggerUIBundle/external \"prop-types\"","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/slicedToArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/keys.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/toConsumableArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js","webpack://SwaggerUIBundle/external \"reselect\"","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/typeof.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/export.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectSpread2.js","webpack://SwaggerUIBundle/./src/core/window.js","webpack://SwaggerUIBundle/external \"react-immutable-proptypes\"","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/extends.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/path.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/fails.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js","webpack://SwaggerUIBundle/./src/core/plugins/oas3/helpers.jsx","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/regenerator/index.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/global.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/entry-virtual.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/is-object.js","webpack://SwaggerUIBundle/./node_modules/lodash/get.js","webpack://SwaggerUIBundle/./src/core/plugins/spec/actions.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/descriptors.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/define-well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createForOfIteratorHelper.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/has.js","webpack://SwaggerUIBundle/./node_modules/lodash/isArray.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/an-object.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectWithoutProperties.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/find.js","webpack://SwaggerUIBundle/./src/core/plugins/oas3/actions.js","webpack://SwaggerUIBundle/./node_modules/lodash/isObject.js","webpack://SwaggerUIBundle/./node_modules/swagger-client/es/helpers.js","webpack://SwaggerUIBundle/./src/core/plugins/err/actions.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/object-define-property.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/array-method-uses-to-length.js","webpack://SwaggerUIBundle/external \"classnames\"","webpack://SwaggerUIBundle/./node_modules/lodash/isFunction.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/promise.js","webpack://SwagLine truncated
{"version":3,"file":"swagger-ui-es-bundle-core.js","mappings":"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 truncated
@@ -1,3 +1,3 @@
/*! For license information please see swagger-ui-es-bundle.js.LICENSE.txt */
module.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=544)}([function(e,t,n){"use strict";e.exports=n(129)},function(e,t,n){e.exports=function(){"use strict";var e=Array.prototype.slice;function t(e,t){t&&(e.prototype=Object.create(t.prototype)),e.prototype.constructor=e}function n(e){return i(e)?e:J(e)}function r(e){return s(e)?e:K(e)}function o(e){return u(e)?e:Y(e)}function a(e){return i(e)&&!c(e)?e:G(e)}function i(e){return!(!e||!e[p])}function s(e){return!(!e||!e[f])}function u(e){return!(!e||!e[h])}function c(e){return s(e)||u(e)}function l(e){return!(!e||!e[d])}t(r,n),t(o,n),t(a,n),n.isIterable=i,n.isKeyed=s,n.isIndexed=u,n.isAssociative=c,n.isOrdered=l,n.Keyed=r,n.Indexed=o,n.Set=a;var p="@@__IMMUTABLE_ITERABLE__@@",f="@@__IMMUTABLE_KEYED__@@",h="@@__IMMUTABLE_INDEXED__@@",d="@@__IMMUTABLE_ORDERED__@@",m="delete",v=5,g=1<<v,y=g-1,b={},_={value:!1},w={value:!1};function x(e){return e.value=!1,e}function E(e){e&&(e.value=!0)}function S(){}function C(e,t){t=t||0;for(var n=Math.max(0,e.length-t),r=new Array(n),o=0;o<n;o++)r[o]=e[o+t];return r}function A(e){return void 0===e.size&&(e.size=e.__iterate(O)),e.size}function k(e,t){if("number"!=typeof t){var n=t>>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?A(e)+t:t}function O(){return!0}function j(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function T(e,t){return N(e,t,0)}function I(e,t){return N(e,t,t)}function N(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}var P=0,M=1,R=2,D="function"==typeof Symbol&&Symbol.iterator,L="@@iterator",B=D||L;function F(e){this.next=e}function U(e,t,n,r){var o=0===e?t:1===e?n:[t,n];return r?r.value=o:r={value:o,done:!1},r}function q(){return{value:void 0,done:!0}}function z(e){return!!H(e)}function V(e){return e&&"function"==typeof e.next}function W(e){var t=H(e);return t&&t.call(e)}function H(e){var t=e&&(D&&e[D]||e[L]);if("function"==typeof t)return t}function $(e){return e&&"number"==typeof e.length}function J(e){return null==e?ie():i(e)?e.toSeq():ce(e)}function K(e){return null==e?ie().toKeyedSeq():i(e)?s(e)?e.toSeq():e.fromEntrySeq():se(e)}function Y(e){return null==e?ie():i(e)?s(e)?e.entrySeq():e.toIndexedSeq():ue(e)}function G(e){return(null==e?ie():i(e)?s(e)?e.entrySeq():e:ue(e)).toSetSeq()}F.prototype.toString=function(){return"[Iterator]"},F.KEYS=P,F.VALUES=M,F.ENTRIES=R,F.prototype.inspect=F.prototype.toSource=function(){return this.toString()},F.prototype[B]=function(){return this},t(J,n),J.of=function(){return J(arguments)},J.prototype.toSeq=function(){return this},J.prototype.toString=function(){return this.__toString("Seq {","}")},J.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},J.prototype.__iterate=function(e,t){return pe(this,e,t,!0)},J.prototype.__iterator=function(e,t){return fe(this,e,t,!0)},t(K,J),K.prototype.toKeyedSeq=function(){return this},t(Y,J),Y.of=function(){return Y(arguments)},Y.prototype.toIndexedSeq=function(){return this},Y.prototype.toString=function(){return this.__toString("Seq [","]")},Y.prototype.__iterate=function(e,t){return pe(this,e,t,!1)},Y.prototype.__iterator=function(e,t){return fe(this,e,t,!1)},t(G,J),G.of=function(){return G(arguments)},G.prototype.toSetSeq=function(){return this},J.isSeq=ae,J.Keyed=K,J.Set=G,J.Indexed=Y;var Z,X,Q,ee="@@__IMMUTABLE_SEQ__@@";function te(e){this._array=e,this.size=e.length}function ne(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function re(e){this._iterable=e,this.size=e.length||e.size}function oe(e){this._iterator=e,this._iteratorCache=[]}function ae(e){return!(!e||!e[ee])}function ie(){return Z||(Z=new te([]))}function se(e){var t=Array.isArray(e)?new te(e).fromEntrySeq():V(e)?new oe(e).fromEntrySeq():z(e)?new re(e).fromEntrySeq():"object"==typeof e?new ne(e):void 0;if(!t)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+e);return t}function ue(e){var t=le(e);if(!t)throw new TypeError("Expected Array or iterable object of values: "+e);return tLine truncated
//# sourceMappingURL=swagger-ui-es-bundle.js.map
(()=>{var i={17967:(i,s)=>{"use strict";s.Nm=s.Rq=void 0;var u=/^([^\w]*)(javascript|data|vbscript)/im,m=/&#(\w+)(^\w|;)?/g,v=/&(newline|tab);/gi,_=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,j=/^.+(:|&colon;)/gim,M=[".","/"];s.Rq="about:blank",s.Nm=function sanitizeUrl(i){if(!i)return s.Rq;var $=function decodeHtmlCharacters(i){return i.replace(_,"").replace(m,(function(i,s){return String.fromCharCode(s)}))}(i).replace(v,"").replace(_,"").trim();if(!$)return s.Rq;if(function isRelativeUrlWithoutProtocol(i){return M.indexOf(i[0])>-1}($))return $;var W=$.match(j);if(!W)return $;var X=W[0];return u.test(X)?s.Rq:$}},79742:(i,s)=>{"use strict";s.byteLength=function byteLength(i){var s=getLens(i),u=s[0],m=s[1];return 3*(u+m)/4-m},s.toByteArray=function toByteArray(i){var s,u,_=getLens(i),j=_[0],M=_[1],$=new v(function _byteLength(i,s,u){return 3*(s+u)/4-u}(0,j,M)),W=0,X=M>0?j-4:j;for(u=0;u<X;u+=4)s=m[i.charCodeAt(u)]<<18|m[i.charCodeAt(u+1)]<<12|m[i.charCodeAt(u+2)]<<6|m[i.charCodeAt(u+3)],$[W++]=s>>16&255,$[W++]=s>>8&255,$[W++]=255&s;2===M&&(s=m[i.charCodeAt(u)]<<2|m[i.charCodeAt(u+1)]>>4,$[W++]=255&s);1===M&&(s=m[i.charCodeAt(u)]<<10|m[i.charCodeAt(u+1)]<<4|m[i.charCodeAt(u+2)]>>2,$[W++]=s>>8&255,$[W++]=255&s);return $},s.fromByteArray=function fromByteArray(i){for(var s,m=i.length,v=m%3,_=[],j=16383,M=0,$=m-v;M<$;M+=j)_.push(encodeChunk(i,M,M+j>$?$:M+j));1===v?(s=i[m-1],_.push(u[s>>2]+u[s<<4&63]+"==")):2===v&&(s=(i[m-2]<<8)+i[m-1],_.push(u[s>>10]+u[s>>4&63]+u[s<<2&63]+"="));return _.join("")};for(var u=[],m=[],v="undefined"!=typeof Uint8Array?Uint8Array:Array,_="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",j=0;j<64;++j)u[j]=_[j],m[_.charCodeAt(j)]=j;function getLens(i){var s=i.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var u=i.indexOf("=");return-1===u&&(u=s),[u,u===s?0:4-u%4]}function encodeChunk(i,s,m){for(var v,_,j=[],M=s;M<m;M+=3)v=(i[M]<<16&16711680)+(i[M+1]<<8&65280)+(255&i[M+2]),j.push(u[(_=v)>>18&63]+u[_>>12&63]+u[_>>6&63]+u[63&_]);return j.join("")}m["-".charCodeAt(0)]=62,m["_".charCodeAt(0)]=63},48764:(i,s,u)=>{"use strict";const m=u(79742),v=u(80645),_="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;s.Buffer=Buffer,s.SlowBuffer=function SlowBuffer(i){+i!=i&&(i=0);return Buffer.alloc(+i)},s.INSPECT_MAX_BYTES=50;const j=2147483647;function createBuffer(i){if(i>j)throw new RangeError('The value "'+i+'" is invalid for option "size"');const s=new Uint8Array(i);return Object.setPrototypeOf(s,Buffer.prototype),s}function Buffer(i,s,u){if("number"==typeof i){if("string"==typeof s)throw new TypeError('The "string" argument must be of type string. Received type number');return allocUnsafe(i)}return from(i,s,u)}function from(i,s,u){if("string"==typeof i)return function fromString(i,s){"string"==typeof s&&""!==s||(s="utf8");if(!Buffer.isEncoding(s))throw new TypeError("Unknown encoding: "+s);const u=0|byteLength(i,s);let m=createBuffer(u);const v=m.write(i,s);v!==u&&(m=m.slice(0,v));return m}(i,s);if(ArrayBuffer.isView(i))return function fromArrayView(i){if(isInstance(i,Uint8Array)){const s=new Uint8Array(i);return fromArrayBuffer(s.buffer,s.byteOffset,s.byteLength)}return fromArrayLike(i)}(i);if(null==i)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof i);if(isInstance(i,ArrayBuffer)||i&&isInstance(i.buffer,ArrayBuffer))return fromArrayBuffer(i,s,u);if("undefined"!=typeof SharedArrayBuffer&&(isInstance(i,SharedArrayBuffer)||i&&isInstance(i.buffer,SharedArrayBuffer)))return fromArrayBuffer(i,s,u);if("number"==typeof i)throw new TypeError('The "value" argument must not be of type number. Received type number');const m=i.valueOf&&i.valueOf();if(null!=m&&m!==i)return Buffer.from(m,s,u);const v=function fromObject(i){if(Buffer.isBuffer(i)){const s=0|checked(i.length),u=createBuffer(s);return 0===u.length||i.copy(u,0,0,s),u}if(void 0!==i.length)return"number"!=typeof i.length||numberIsNaN(i.length)?createBuffer(0):fromArrayLike(i);if("Buffer"===i.type&&Array.isArray(i.data))return fromArrayLike(i.data)}(i);if(v)return v;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof i[Symbol.toPrimitive])return Buffer.from(i[Symbol.toPrimitive]("string"),s,u);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof i)}function assertSize(i){if("number"!=typeof i)throw new TypeError('"size" argument must be of type number');if(i<0)throw new RangeError('The value "'+i+'" is invalid for option "size"')}function allocUnsafe(i){return assertSize(i),createBuffer(i<0?0:0|checked(i))}function fromArrayLike(i){const s=i.length<0?0:0|checked(i.length),u=createBuffer(s);for(let m=0;m<s;m+=1)u[m]=255&i[m];return u}function fromArrayBuffer(i,s,u){if(s<0||i.byteLength<s)throw new RangeError('"offset" is outside of buffer bLine truncated
//# sourceMappingURL=swagger-ui-es-bundle.js.map
@@ -1 +1 @@
{"version":3,"sources":["webpack://SwaggerUIBundle/webpack/bootstrap","webpack://SwaggerUIBundle/./node_modules/react/react.js","webpack://SwaggerUIBundle/./node_modules/immutable/dist/immutable.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/defineProperty.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createClass.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/classCallCheck.js","webpack://SwaggerUIBundle/./src/core/utils.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/inherits.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createSuper.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/assertThisInitialized.js","webpack://SwaggerUIBundle/./node_modules/prop-types/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/slicedToArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/keys.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/toConsumableArray.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js","webpack://SwaggerUIBundle/./node_modules/reselect/es/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/typeof.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/export.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectSpread2.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/invariant.js","webpack://SwaggerUIBundle/./src/core/window.js","webpack://SwaggerUIBundle/./node_modules/react-immutable-proptypes/dist/ImmutablePropTypes.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/extends.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js","webpack://SwaggerUIBundle/./node_modules/react-dom/lib/reactProdInvariant.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/path.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/warning.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/fails.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js","webpack://SwaggerUIBundle/./src/core/plugins/oas3/helpers.jsx","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/object-assign/index.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/regenerator/index.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/global.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/entry-virtual.js","webpack://SwaggerUIBundle/./node_modules/react-dom/lib/ReactDOMComponentTree.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/is-object.js","webpack://SwaggerUIBundle/./node_modules/lodash/get.js","webpack://SwaggerUIBundle/./src/core/plugins/spec/actions.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/descriptors.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/define-well-known-symbol.js","webpack://SwaggerUIBundle/./node_modules/js-yaml/lib/js-yaml/type.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/createForOfIteratorHelper.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/has.js","webpack://SwaggerUIBundle/./node_modules/lodash/isArray.js","webpack://SwaggerUIBundle/(webpack)/buildin/global.js","webpack://SwaggerUIBundle/./node_modules/core-js-pure/internals/an-object.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/helpers/objectWithoutProperties.js","webpack://SwaggerUIBundle/./node_modules/fbjs/lib/ExecutionEnvironment.js","webpack://SwaggerUIBundle/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/find.js","webpack://SwaggerUIBundle/.Line truncated
{"version":3,"file":"swagger-ui-es-bundle.js","mappings":"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 truncated
@@ -1,3 +1,3 @@
/*! For license information please see swagger-ui-standalone-preset.js.LICENSE.txt */
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(function(){try{return require("esprima")}catch(t){}}()):"function"==typeof define&&define.amd?define(["esprima"],e):"object"==typeof exports?exports.SwaggerUIStandalonePreset=e(function(){try{return require("esprima")}catch(t){}}()):t.SwaggerUIStandalonePreset=e(t.esprima)}(this,(function(t){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/dist",n(n.s=241)}([function(t,e,n){t.exports=function(){"use strict";var t=Array.prototype.slice;function e(t,e){e&&(t.prototype=Object.create(e.prototype)),t.prototype.constructor=t}function n(t){return u(t)?t:J(t)}function r(t){return s(t)?t:Z(t)}function i(t){return a(t)?t:V(t)}function o(t){return u(t)&&!c(t)?t:X(t)}function u(t){return!(!t||!t[l])}function s(t){return!(!t||!t[p])}function a(t){return!(!t||!t[h])}function c(t){return s(t)||a(t)}function f(t){return!(!t||!t[d])}e(r,n),e(i,n),e(o,n),n.isIterable=u,n.isKeyed=s,n.isIndexed=a,n.isAssociative=c,n.isOrdered=f,n.Keyed=r,n.Indexed=i,n.Set=o;var l="@@__IMMUTABLE_ITERABLE__@@",p="@@__IMMUTABLE_KEYED__@@",h="@@__IMMUTABLE_INDEXED__@@",d="@@__IMMUTABLE_ORDERED__@@",y="delete",v=5,g=1<<v,w=g-1,M={},m={value:!1},_={value:!1};function L(t){return t.value=!1,t}function x(t){t&&(t.value=!0)}function b(){}function j(t,e){e=e||0;for(var n=Math.max(0,t.length-e),r=new Array(n),i=0;i<n;i++)r[i]=t[i+e];return r}function N(t){return void 0===t.size&&(t.size=t.__iterate(D)),t.size}function S(t,e){if("number"!=typeof e){var n=e>>>0;if(""+n!==e||4294967295===n)return NaN;e=n}return e<0?N(t)+e:e}function D(){return!0}function I(t,e,n){return(0===t||void 0!==n&&t<=-n)&&(void 0===e||void 0!==n&&e>=n)}function A(t,e){return C(t,e,0)}function E(t,e){return C(t,e,e)}function C(t,e,n){return void 0===t?n:t<0?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}var O=0,T=1,z=2,k="function"==typeof Symbol&&Symbol.iterator,U="@@iterator",Y=k||U;function P(t){this.next=t}function R(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function Q(){return{value:void 0,done:!0}}function F(t){return!!W(t)}function B(t){return t&&"function"==typeof t.next}function G(t){var e=W(t);return e&&e.call(t)}function W(t){var e=t&&(k&&t[k]||t[U]);if("function"==typeof e)return e}function q(t){return t&&"number"==typeof t.length}function J(t){return null==t?ut():u(t)?t.toSeq():ct(t)}function Z(t){return null==t?ut().toKeyedSeq():u(t)?s(t)?t.toSeq():t.fromEntrySeq():st(t)}function V(t){return null==t?ut():u(t)?s(t)?t.entrySeq():t.toIndexedSeq():at(t)}function X(t){return(null==t?ut():u(t)?s(t)?t.entrySeq():t:at(t)).toSetSeq()}P.prototype.toString=function(){return"[Iterator]"},P.KEYS=O,P.VALUES=T,P.ENTRIES=z,P.prototype.inspect=P.prototype.toSource=function(){return this.toString()},P.prototype[Y]=function(){return this},e(J,n),J.of=function(){return J(arguments)},J.prototype.toSeq=function(){return this},J.prototype.toString=function(){return this.__toString("Seq {","}")},J.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},J.prototype.__iterate=function(t,e){return lt(this,t,e,!0)},J.prototype.__iterator=function(t,e){return pt(this,t,e,!0)},e(Z,J),Z.prototype.toKeyedSeq=function(){return this},e(V,J),V.of=function(){return V(arguments)},V.prototype.toIndexedSeq=function(){return this},V.prototype.toString=function(){return this.__toString("Seq [","]")},V.prototype.__iterate=function(t,e){return lt(this,t,e,!1)},V.prototype.__iterator=function(t,e){return pt(this,t,e,!1)},e(X,J),X.of=function(){return X(arguments)},X.prototype.toSetSeq=function(){return this},J.isSeq=ot,J.Keyed=Z,J.Set=X,J.Indexed=V;var H,K,$,tt="@@__IMMUTABLE_SEQ__@@";function et(t){this._array=t,this.size=t.length}function nt(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function rt(t){this._iterable=t,this.size=t.length||t.size}function it(t){this._iterator=t,this._iteratorCache=[]}function ot(t){return!(!t||!t[tt])}function ut(){return H||(H=new et([]))}function st(t){var e=Array.isArray(t)?new et(t).fromEntrySeq()Line truncated
//# sourceMappingURL=swagger-ui-standalone-preset.js.map
!function webpackUniversalModuleDefinition(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIStandalonePreset=t():e.SwaggerUIStandalonePreset=t()}(this,(()=>(()=>{var e={7967:(e,t)=>{"use strict";t.Rq=void 0;var r=/^([^\w]*)(javascript|data|vbscript)/im,n=/&#(\w+)(^\w|;)?/g,i=/&(newline|tab);/gi,o=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,a=/^.+(:|&colon;)/gim,s=[".","/"];t.Rq="about:blank"},9742:(e,t)=>{"use strict";t.byteLength=function byteLength(e){var t=getLens(e),r=t[0],n=t[1];return 3*(r+n)/4-n},t.toByteArray=function toByteArray(e){var t,r,o=getLens(e),a=o[0],s=o[1],u=new i(function _byteLength(e,t,r){return 3*(t+r)/4-r}(0,a,s)),c=0,f=s>0?a-4:a;for(r=0;r<f;r+=4)t=n[e.charCodeAt(r)]<<18|n[e.charCodeAt(r+1)]<<12|n[e.charCodeAt(r+2)]<<6|n[e.charCodeAt(r+3)],u[c++]=t>>16&255,u[c++]=t>>8&255,u[c++]=255&t;2===s&&(t=n[e.charCodeAt(r)]<<2|n[e.charCodeAt(r+1)]>>4,u[c++]=255&t);1===s&&(t=n[e.charCodeAt(r)]<<10|n[e.charCodeAt(r+1)]<<4|n[e.charCodeAt(r+2)]>>2,u[c++]=t>>8&255,u[c++]=255&t);return u},t.fromByteArray=function fromByteArray(e){for(var t,n=e.length,i=n%3,o=[],a=16383,s=0,u=n-i;s<u;s+=a)o.push(encodeChunk(e,s,s+a>u?u:s+a));1===i?(t=e[n-1],o.push(r[t>>2]+r[t<<4&63]+"==")):2===i&&(t=(e[n-2]<<8)+e[n-1],o.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return o.join("")};for(var r=[],n=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0;a<64;++a)r[a]=o[a],n[o.charCodeAt(a)]=a;function getLens(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=e.indexOf("=");return-1===r&&(r=t),[r,r===t?0:4-r%4]}function encodeChunk(e,t,n){for(var i,o,a=[],s=t;s<n;s+=3)i=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(255&e[s+2]),a.push(r[(o=i)>>18&63]+r[o>>12&63]+r[o>>6&63]+r[63&o]);return a.join("")}n["-".charCodeAt(0)]=62,n["_".charCodeAt(0)]=63},8764:(e,t,r)=>{"use strict";const n=r(9742),i=r(645),o="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=Buffer,t.SlowBuffer=function SlowBuffer(e){+e!=e&&(e=0);return Buffer.alloc(+e)},t.INSPECT_MAX_BYTES=50;const a=2147483647;function createBuffer(e){if(e>a)throw new RangeError('The value "'+e+'" is invalid for option "size"');const t=new Uint8Array(e);return Object.setPrototypeOf(t,Buffer.prototype),t}function Buffer(e,t,r){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return allocUnsafe(e)}return from(e,t,r)}function from(e,t,r){if("string"==typeof e)return function fromString(e,t){"string"==typeof t&&""!==t||(t="utf8");if(!Buffer.isEncoding(t))throw new TypeError("Unknown encoding: "+t);const r=0|byteLength(e,t);let n=createBuffer(r);const i=n.write(e,t);i!==r&&(n=n.slice(0,i));return n}(e,t);if(ArrayBuffer.isView(e))return function fromArrayView(e){if(isInstance(e,Uint8Array)){const t=new Uint8Array(e);return fromArrayBuffer(t.buffer,t.byteOffset,t.byteLength)}return fromArrayLike(e)}(e);if(null==e)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(isInstance(e,ArrayBuffer)||e&&isInstance(e.buffer,ArrayBuffer))return fromArrayBuffer(e,t,r);if("undefined"!=typeof SharedArrayBuffer&&(isInstance(e,SharedArrayBuffer)||e&&isInstance(e.buffer,SharedArrayBuffer)))return fromArrayBuffer(e,t,r);if("number"==typeof e)throw new TypeError('The "value" argument must not be of type number. Received type number');const n=e.valueOf&&e.valueOf();if(null!=n&&n!==e)return Buffer.from(n,t,r);const i=function fromObject(e){if(Buffer.isBuffer(e)){const t=0|checked(e.length),r=createBuffer(t);return 0===r.length||e.copy(r,0,0,t),r}if(void 0!==e.length)return"number"!=typeof e.length||numberIsNaN(e.length)?createBuffer(0):fromArrayLike(e);if("Buffer"===e.type&&Array.isArray(e.data))return fromArrayLike(e.data)}(e);if(i)return i;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof e[Symbol.toPrimitive])return Buffer.from(e[Symbol.toPrimitive]("string"),t,r);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}function assertSize(e){if("number"!=typeof e)throw new TypeError('"size" argument must be of type number');if(e<0)throw new RangeError('The value "'+e+'" is invalid for option "size"')}function allocUnsafe(e){return assertSize(e),createBuffer(e<0?0:0|checked(e))}function fromArrayLike(e){const t=e.length<0?0:0|checked(e.length),r=createBuffer(t);for(let n=0;n<t;n+=1)r[n]=255&e[n];return r}function fromArrayBuffer(e,t,r){if(t<0||e.byteLength<t)throw new RangeError('"offset" is outside of buffer bounds');if(e.byteLength<t+(r||0))throw new RangeError('"length" is outside of buffer bounds');let n;return n=voiLine truncated
//# sourceMappingURL=swagger-ui-standalone-preset.js.map
@@ -1 +0,0 @@
{"version":3,"sources":["webpack://SwaggerUIStandalonePreset/webpack/universalModuleDefinition","webpack://SwaggerUIStandalonePreset/webpack/bootstrap","webpack://SwaggerUIStandalonePreset/./node_modules/immutable/dist/immutable.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/export.js","webpack://SwaggerUIStandalonePreset/./node_modules/react/react.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/define-well-known-symbol.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/fails.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/well-known-symbol.js","webpack://SwaggerUIStandalonePreset/./node_modules/js-yaml/lib/js-yaml/type.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/entry-virtual.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/path.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/helpers/typeof.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/helpers/defineProperty.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/global.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/is-object.js","webpack://SwaggerUIStandalonePreset/./node_modules/inherits/inherits_browser.js","webpack://SwaggerUIStandalonePreset/./node_modules/safe-buffer/index.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/has.js","webpack://SwaggerUIStandalonePreset/./src/core/utils.js","webpack://SwaggerUIStandalonePreset/(webpack)/buildin/global.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/descriptors.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/to-object.js","webpack://SwaggerUIStandalonePreset/./node_modules/lodash/isArray.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/create-non-enumerable-property.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/array-method-uses-to-length.js","webpack://SwaggerUIStandalonePreset/./node_modules/lodash/_root.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/helpers/assertThisInitialized.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/object/keys.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/an-object.js","webpack://SwaggerUIStandalonePreset/./node_modules/es5-ext/object/valid-callable.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js","webpack://SwaggerUIStandalonePreset/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/to-indexed-object.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/object-define-property.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/to-length.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/iterators.js","webpack://SwaggerUIStandalonePreset/./node_modules/process/browser.js","webpack://SwaggerUIStandalonePreset/./node_modules/readable-stream/lib/_stream_duplex.js","webpack://SwaggerUIStandalonePreset/./node_modules/es5-ext/object/is-value.js","webpack://SwaggerUIStandalonePreset/./node_modules/es5-ext/number/to-pos-integer.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/require-object-coercible.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/classof.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/modules/web.dom-collections.iterator.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/array-iteration.js","webpack://SwaggerUIStandalonePreset/./node_modules/react/lib/ReactElement.js","webpack://SwaggerUIStandalonePreset/./node_modules/lodash/_getNative.js","webpack://SwaggerUIStandalonePreset/./node_modules/es5-ext/object/valid-value.js","webpack://SwaggerUIStandalonePreset/./node_modules/sha.js/hash.js","webpack://SwaggerUIStandalonePreset/./node_modules/js-yaml/lib/js-yaml/common.js","webpack://SwaggerUIStandalonePreset/./node_modules/js-yaml/lib/js-yaml/schema.js","webpack://SwaggerUIStandalonePreset/./node_modules/lodash/eq.js","webpack://SwaggerUIStandalonePreset/./node_modules/lodash/isEmpty.js","webpack://SwaggerUIStandalonePreset/./node_modules/core-js-pure/internals/create-property-descriptor.js","webpack://SwaggerUIStandalonePreset/./node_moduLine truncated
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack:///./src/style/main.scss","webpack:///./node_modules/tachyons-sass/scss/_normalize.scss","webpack:///./src/style/_type.scss","webpack:///./node_modules/tachyons-sass/scss/_debug-children.scss","webpack:///./node_modules/tachyons-sass/scss/_debug-grid.scss","webpack:///./node_modules/tachyons-sass/scss/_box-sizing.scss","webpack:///./node_modules/tachyons-sass/scss/_aspect-ratios.scss","webpack:///./node_modules/tachyons-sass/scss/_images.scss","webpack:///./node_modules/tachyons-sass/scss/_background-size.scss","webpack:///./node_modules/tachyons-sass/scss/_background-position.scss","webpack:///./node_modules/tachyons-sass/scss/_outlines.scss","webpack:///./node_modules/tachyons-sass/scss/_borders.scss","webpack:///./node_modules/tachyons-sass/scss/_border-colors.scss","webpack:///./node_modules/tachyons-sass/scss/_border-radius.scss","webpack:///./node_modules/tachyons-sass/scss/_border-style.scss","webpack:///./node_modules/tachyons-sass/scss/_border-widths.scss","webpack:///./node_modules/tachyons-sass/scss/_box-shadow.scss","webpack:///./node_modules/tachyons-sass/scss/_code.scss","webpack:///./node_modules/tachyons-sass/scss/_coordinates.scss","webpack:///./node_modules/tachyons-sass/scss/_clears.scss","webpack:///./node_modules/tachyons-sass/scss/_flexbox.scss","webpack:///./node_modules/tachyons-sass/scss/_display.scss","webpack:///./node_modules/tachyons-sass/scss/_floats.scss","webpack:///./node_modules/tachyons-sass/scss/_font-family.scss","webpack:///./node_modules/tachyons-sass/scss/_font-style.scss","webpack:///./node_modules/tachyons-sass/scss/_font-weight.scss","webpack:///./node_modules/tachyons-sass/scss/_forms.scss","webpack:///./node_modules/tachyons-sass/scss/_heights.scss","webpack:///./node_modules/tachyons-sass/scss/_letter-spacing.scss","webpack:///./node_modules/tachyons-sass/scss/_line-height.scss","webpack:///./node_modules/tachyons-sass/scss/_links.scss","webpack:///./node_modules/tachyons-sass/scss/_lists.scss","webpack:///./node_modules/tachyons-sass/scss/_max-widths.scss","webpack:///./node_modules/tachyons-sass/scss/_widths.scss","webpack:///./node_modules/tachyons-sass/scss/_overflow.scss","webpack:///./node_modules/tachyons-sass/scss/_position.scss","webpack:///./node_modules/tachyons-sass/scss/_opacity.scss","webpack:///./node_modules/tachyons-sass/scss/_rotations.scss","webpack:///./node_modules/tachyons-sass/scss/_skins.scss","webpack:///./node_modules/tachyons-sass/scss/_skins-pseudo.scss","webpack:///./node_modules/tachyons-sass/scss/_spacing.scss","webpack:///./node_modules/tachyons-sass/scss/_variables.scss","webpack:///./node_modules/tachyons-sass/scss/_negative-margins.scss","webpack:///./node_modules/tachyons-sass/scss/_tables.scss","webpack:///./node_modules/tachyons-sass/scss/_text-decoration.scss","webpack:///./node_modules/tachyons-sass/scss/_text-align.scss","webpack:///./node_modules/tachyons-sass/scss/_text-transform.scss","webpack:///./node_modules/tachyons-sass/scss/_type-scale.scss","webpack:///./node_modules/tachyons-sass/scss/_typography.scss","webpack:///./node_modules/tachyons-sass/scss/_utilities.scss","webpack:///./node_modules/tachyons-sass/scss/_visibility.scss","webpack:///./node_modules/tachyons-sass/scss/_white-space.scss","webpack:///./node_modules/tachyons-sass/scss/_vertical-align.scss","webpack:///./node_modules/tachyons-sass/scss/_hovers.scss","webpack:///./node_modules/tachyons-sass/scss/_z-index.scss","webpack:///./node_modules/tachyons-sass/scss/_nested.scss","webpack:///./src/style/_layout.scss","webpack:///./src/style/_variables.scss","webpack:///./src/style/_buttons.scss","webpack:///./src/style/_mixins.scss","webpack:///./src/style/_form.scss","webpack:///./src/style/_modal.scss","webpack:///./src/style/_models.scss","webpack:///./src/style/_servers.scss","webpack:///./src/style/_table.scss","webpack:///./src/style/_topbar.scss","webpack:///./src/style/_information.scss","webpack:///./src/style/_authorize.scss","webpack:///./src/style/_errors.scss","webpack:///./src/style/_split-pane-mode.scss","webpack:///./src/style/_markdown.scss"],"names":[],"mappings":"AAAA;ECOA,4ECLI,sBAAuB,CAEvB,aFmhCJ,CAvhCA,iBCmBE,gBAAiB,CACjB,yBAA0B,CAC1B,6BD2gCF,CAhiCA,iBCgCE,QDogCF,CApiCA,gHC6CE,aDggCF,CA7iCA,eCsDE,aAAc,CACd,cD2/BF,CAljCA,2DCqEE,aDo/BF,CAzjCA,mBC6EE,eDg/BF,CA7jCA,eCsFE,sBAAuB,CACvB,QAAS,CACT,gBD8+BF,CAtkCA,gBCiGE,+BAAiC,CACjC,aD2+BF,CA7kCA,cC8GE,4BAA6B,CAC7B,oCDq+BF,CAplCA,wBCwHE,kBAAmB,CACnB,yBAA0B,CAC1B,wCAAiC,CAAjC,gCDm+BF,CA7lCA,iCCmIE,mBAAoB,CASpB,kBDs9BF,CAlmCA,kDCuJE,+BAAiC,CACjC,aDw9BF,CAhnCA,gBCgKE,iBDo9BF,CApnCA,iBCwKE,qBAAsB,CACtB,UDg9BF,CAznCA,kBCiLE,aD48BF,CA7nCA,gCC2LE,aAAc,CACd,aAAc,CACd,iBAAkB,CAClB,uBDu8BF,CAroCA,gBCkME,aDu8BF,CAzoCA,gBCsME,SDu8BF,CA7oCA,oCCkNE,oBDg8BF,CAlpCA,kCC0NE,YAAa,CACb,QD47BF,CAvpCA,gBCmOE,iBDw7BF,CA3pCA,2BC2OE,eDo7BF,CA/pCA,kGC2PE,sBAAuB,CACvB,cAAe,CACf,gBAAiB,CACjB,QDg7BF,CA9qCA,qCCwQE,gBD46BF,CAprCA,sCCkRE,mBDw6BF,CA1rCA,qGC+RE,yBDm6BF,CAlsCA,wKC0SE,iBAAkB,CACLine truncated
{"version":3,"file":"swagger-ui.css","mappings":"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,CDrDb,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,oDC8BW,CD7BX,qDC8BW,CD7BX,uDC8BY,CD7BZ,wDC8Ba,CD5Bb,6CCyCW,CDxCX,wCCyCM,CDxCN,8CCyCY,CDxCZ,2CCyCS,CDxCT,yCCyCO,CDxCP,wCCyCS,CDxCT,iDCyCe,CDxCf,2CCyCS,CDxCT,iDCyCe,CDxCf,8CCyCY,CDxCZ,6CCyCW,CDxCX,yCCyCO,CDxCP,+CCyCa,CDxCb,+CCyCa,CDxCb,0CCyCQ,CDxCR,gDCyCc,CDxCd,yCCyCO,CDxCP,8CCyCY,CDxCZ,yCCyCO,CDxCP,+CCyCa,CDxCb,kDCyCgB,CDxChB,gDCyCc,CDxCd,iDCyCe,CDxCf,kDCyCgB,CDxChB,+CCyCa,CDvCb,oDCVc,CDWd,6CE3DE,gCDmBmB,CClBnB,sCDmBgB,CClBhB,qCDmBgB,CClBhB,oCDmBgB,CClBhB,mCDmBgB,CClBhB,sCDmBqB,CClBrB,yCDmBmB,CClBnB,wBACI,yBACA,0BAEJ,qBACI,4BACA,6BAEJ,uBAEI,4BADA,wBACA,CAEJ,sBAEI,6BADA,yBACA,CAGN,mCACE,mCDNmB,CCOnB,yCDNgB,CCOhB,wCDNgB,CCOhB,uCDNgB,CCOhB,sCDNgB,CCOhB,yCDNqB,CCOrB,4CDNmB,CCOnB,2BACI,yBACA,0BAEJ,wBACI,4BACA,6BAEJ,0BAEI,4BADA,wBACA,CAEJ,yBAEI,6BADA,yBACA,EAIN,uDACE,kCDhCmB,CCiCnB,wCDhCgB,CCiChB,uCDhCgB,CCiChB,sCDhCgB,CCiChB,qCDhCgB,CCiChB,wCDhCqB,CCiCrB,2CDhCmB,CCiCnB,0BACI,yBACA,0BAEJ,uBACI,4BACA,6BAEJ,yBAEI,4BADA,wBACA,CAEJ,wBAEI,6BADA,yBACA,EAIN,mCACE,kCD1DmB,CC2DnB,wCD1DgB,CC2DhB,uCD1DgB,CC2DhB,sCD1DgB,CC2DhB,qCD1DgB,CC2DhB,wCD1DqB,CC2DrB,2CD1DmB,CC2DnB,0BACI,yBACA,0BAEJ,uBACI,4BACA,6BAEJ,yBAEI,4BADA,wBACA,CAEJ,wBAEI,6BADA,yBACA,ECrGN,2CACA,2CACA,yCACA,uCAEA,mCACE,8CACA,8CACA,4CACA,2CAGF,uDACE,6CACA,6CACA,2CACA,0CAGF,mCACE,6CACA,6CACA,2CACA,0CCvBF,+BH6BoB,CG5BpB,qCH6BiB,CG5BjB,oCH6BiB,CG5BjB,mCH6BiB,CG5BjB,kCH6BiB,CG5BjB,kCH6BiB,CG1BjB,oCHqBoB,CGpBpB,sCHoBoB,CGnBpB,uCHmBoB,CGlBpB,qCHkBoB,CGhBpB,mCACE,kCHekB,CGdlB,wCHee,CGdf,uCHee,CGdf,sCHee,CGdf,qCHee,CGdf,qCHee,CGdf,uCHSkB,CGRlB,yCHQkB,CGPlB,0CHOkB,CGNlB,wCHMkB,EGHpB,uDACE,iCHEkB,CGDlB,uCHEe,CGDf,sCHEe,CGDf,qCHEe,CGDf,oCHEe,CGDf,oCHEe,CGDf,sCHJkB,CGKlB,wCHLkB,CGMlB,yCHNkB,CGOlB,uCHPkB,EGUpB,mCACE,iCHXkB,CGYlB,uCHXe,CGYf,sCHXe,CGYf,qCHXe,CGYf,oCHXe,CGYf,oCHXe,CGYf,sCHjBkB,CGkBlB,wCHlBkB,CGmBlB,yCHnBkB,CGoBlB,uCHpBkB,EIxCpB,2DJ8Ce,CI7Cf,2DJ8Ce,CI7Cf,+DJ8Ce,CI7Cf,6DJ8Ce,CI7Cf,6DJ8Ce,CI5Cf,mCACE,8DJuCa,CItCb,8DJuCa,CItCb,kEJuCa,CItCb,gEJuCa,CItCb,gEJuCa,EIpCf,uDACE,6DJ+Ba,CI9Bb,6DJ+Ba,CI9Bb,iEJ+Ba,CI9Bb,+DJ+Ba,CI9Bb,+DJ+Ba,EI5Bf,mCACE,6DJuBa,CItBb,6DJuBa,CItBb,iEJuBa,CItBb,+DJuBa,CItBb,+DJuBa,EKxDf,iBACE,gBACA,kBACA,gBCkBF,yBACA,6BACA,+BACA,2BAEA,4BACA,gCACA,kCACA,8BAEA,4BACA,gCACA,kCACA,8BAEA,8BACA,kCACA,oCACA,gCAEA,8BACA,kCACA,oCACA,gCAGA,4BAGE,SACA,OAFA,QADA,KAGA,CAGF,mCACE,4BACA,8BACA,gCACA,kCACA,+BACA,iCACA,mCACA,qCACA,+BACA,iCACA,mCACA,qCACA,iCACA,qCACA,uCACA,mCACA,iCACA,qCACA,uCACA,mCACA,+BAGE,SACA,OAFA,QADA,KAGA,EAIJ,uDACE,2BACA,6BACA,+BACA,iLine truncated
+2 -3
View File
@@ -1,3 +1,2 @@
/*! For license information please see swagger-ui.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUICore=t():e.SwaggerUICore=t()}(this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=410)}([function(e,t){e.exports=require("react")},function(e,t){e.exports=require("immutable")},function(e,t,n){e.exports=n(449)},function(e,t,n){var r=n(191);e.exports=function(e,t,n){return t in e?r(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){e.exports=n(452)},function(e,t,n){var r=n(191);function a(e,t){for(var n=0;n<t.length;n++){var a=t[n];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),r(e,a.key,a)}}e.exports=function(e,t,n){return t&&a(e.prototype,t),n&&a(e,n),e}},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";(function(e){n.d(t,"t",(function(){return me})),n.d(t,"A",(function(){return ve})),n.d(t,"i",(function(){return ge})),n.d(t,"w",(function(){return ye})),n.d(t,"r",(function(){return be})),n.d(t,"u",(function(){return Ee})),n.d(t,"s",(function(){return xe})),n.d(t,"p",(function(){return Se})),n.d(t,"v",(function(){return we})),n.d(t,"y",(function(){return je})),n.d(t,"z",(function(){return Ce})),n.d(t,"K",(function(){return Oe})),n.d(t,"f",(function(){return _e})),n.d(t,"n",(function(){return Ae})),n.d(t,"h",(function(){return ke})),n.d(t,"E",(function(){return Ie})),n.d(t,"L",(function(){return Fe})),n.d(t,"o",(function(){return Ye})),n.d(t,"D",(function(){return Ke})),n.d(t,"a",(function(){return Ge})),n.d(t,"I",(function(){return Ze})),n.d(t,"b",(function(){return Xe})),n.d(t,"H",(function(){return Qe})),n.d(t,"G",(function(){return et})),n.d(t,"F",(function(){return tt})),n.d(t,"k",(function(){return nt})),n.d(t,"d",(function(){return rt})),n.d(t,"g",(function(){return at})),n.d(t,"m",(function(){return ot})),n.d(t,"l",(function(){return it})),n.d(t,"e",(function(){return ct})),n.d(t,"J",(function(){return st})),n.d(t,"x",(function(){return ut})),n.d(t,"B",(function(){return lt})),n.d(t,"C",(function(){return pt})),n.d(t,"j",(function(){return ft})),n.d(t,"c",(function(){return dt})),n.d(t,"q",(function(){return mt}));var r=n(82),a=n.n(r),o=n(130),i=n.n(o),c=n(50),s=n.n(c),u=n(13),l=n.n(u),p=n(30),f=n.n(p),d=n(17),h=n.n(d),m=(n(34),n(32)),v=n.n(m),g=(n(24),n(15),n(157)),y=n.n(g),b=n(21),E=n.n(b),x=n(22),S=n.n(x),w=(n(29),n(16)),j=n.n(w),C=n(12),O=n.n(C),_=n(18),A=n.n(_),k=n(2),I=n.n(k),P=n(45),T=n.n(P),N=n(71),R=n.n(N),M=n(4),D=n.n(M),q=n(14),L=n.n(q),B=n(20),U=n.n(B),V=n(1),z=n.n(V),F=n(375),J=n(376),W=n.n(J),H=n(207),$=n.n(H),Y=n(208),K=n.n(Y),G=n(158),Z=n.n(G),X=n(266),Q=n.n(X),ee=n(102),te=n.n(ee),ne=n(58),re=n.n(ne),ae=n(112),oe=n(26),ie=n(378),ce=n.n(ie),se=n(114),ue=n(379),le=n.n(ue),pe=n(380),fe=n.n(pe),de="default",he=function(e){return z.a.Iterable.isIterable(e)};function me(e){try{var t=JSON.parse(e);if(t&&"object"===U()(t))return t}catch(e){}return!1}function ve(e){return Ee(e)?he(e)?e.toJS():e:{}}function ge(e){var t,n;if(he(e))return e;if(e instanceof oe.a.File)return e;if(!Ee(e))return e;if(L()(e))return D()(n=z.a.Seq(e)).call(n,ge).toList();if(re()(R()(e))){var r,a=function(e){if(!re()(R()(e)))return e;var t,n={},r="_**[]",a={},o=T()(R()(e).call(e));try{for(o.s();!(t=o.n()).done;){var i=t.value;if(n[i[0]]||a[i[0]]&&a[i[0]].containsMultiple){var c,s,u,l;if(!a[i[0]])a[i[0]]={containsMultiple:!0,length:1},n[I()(u=I()(l="".concat(i[0])).call(l,r)).call(u,a[i[0]].length)]=n[i[0]],delete n[i[0]];a[i[0]].length+=1,n[I()(c=I()(s="".concat(i[0])).call(s,r)).call(c,a[i[0]].length)]=i[1]}else n[i[0]]=i[1]}}catch(e){o.e(e)}finally{o.f()}return n}(e);return D()(r=z.a.OrderedMap(a)).call(r,ge)}return D()(t=z.a.OrderedMap(e)).call(t,ge)}function ye(e){return L()(e)?e:[e]}function be(e){return"function"==typeof e}function Ee(e){return!!e&&"object"===U()(e)}function xe(e){return"function"==typeof e}function Se(e){return L()(e)}var we=K.a;function je(e,t){var n;return S()(n=j()(e)).call(n,(function(n,Line truncated
//# sourceMappingURL=swagger-ui.js.map
!function webpackUniversalModuleDefinition(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUICore=t():e.SwaggerUICore=t()}(this,(()=>(()=>{"use strict";var e={871:e=>{e.exports=require("buffer")}},t={};function __webpack_require__(r){var n=t[r];if(void 0!==n)return n.exports;var a=t[r]={exports:{}};return e[r](a,a.exports,__webpack_require__),a.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var r={};return(()=>{__webpack_require__.d(r,{default:()=>Do});var e={};__webpack_require__.r(e),__webpack_require__.d(e,{CLEAR:()=>D,CLEAR_BY:()=>L,NEW_AUTH_ERR:()=>K,NEW_SPEC_ERR:()=>$,NEW_SPEC_ERR_BATCH:()=>V,NEW_THROWN_ERR:()=>T,NEW_THROWN_ERR_BATCH:()=>J,clear:()=>clear,clearBy:()=>clearBy,newAuthErr:()=>newAuthErr,newSpecErr:()=>newSpecErr,newSpecErrBatch:()=>newSpecErrBatch,newThrownErr:()=>newThrownErr,newThrownErrBatch:()=>newThrownErrBatch});var t={};__webpack_require__.r(t),__webpack_require__.d(t,{AUTHORIZE:()=>ge,AUTHORIZE_OAUTH2:()=>Se,CONFIGURE_AUTH:()=>ve,LOGOUT:()=>ye,PRE_AUTHORIZE_OAUTH2:()=>fe,RESTORE_AUTHORIZATION:()=>_e,SHOW_AUTH_POPUP:()=>he,VALIDATE:()=>Ee,authPopup:()=>authPopup,authorize:()=>authorize,authorizeAccessCodeWithBasicAuthentication:()=>authorizeAccessCodeWithBasicAuthentication,authorizeAccessCodeWithFormParams:()=>authorizeAccessCodeWithFormParams,authorizeApplication:()=>authorizeApplication,authorizeOauth2:()=>authorizeOauth2,authorizeOauth2WithPersistOption:()=>authorizeOauth2WithPersistOption,authorizePassword:()=>authorizePassword,authorizeRequest:()=>authorizeRequest,authorizeWithPersistOption:()=>authorizeWithPersistOption,configureAuth:()=>configureAuth,logout:()=>logout,logoutWithPersistOption:()=>logoutWithPersistOption,persistAuthorizationIfNeeded:()=>persistAuthorizationIfNeeded,preAuthorizeImplicit:()=>preAuthorizeImplicit,restoreAuthorization:()=>restoreAuthorization,showDefinitions:()=>showDefinitions});var n={};__webpack_require__.r(n),__webpack_require__.d(n,{authorized:()=>Oe,definitionsForRequirements:()=>definitionsForRequirements,definitionsToAuthorize:()=>xe,getConfigs:()=>Ne,getDefinitionsByNames:()=>getDefinitionsByNames,isAuthorized:()=>isAuthorized,shownDefinitions:()=>Ce});var a={};__webpack_require__.r(a),__webpack_require__.d(a,{TOGGLE_CONFIGS:()=>Je,UPDATE_CONFIGS:()=>Te,loaded:()=>actions_loaded,toggle:()=>toggle,update:()=>update});var s={};__webpack_require__.r(s),__webpack_require__.d(s,{downloadConfig:()=>downloadConfig,getConfigByUrl:()=>getConfigByUrl});var o={};__webpack_require__.r(o),__webpack_require__.d(o,{get:()=>get});var l={};__webpack_require__.r(l),__webpack_require__.d(l,{transform:()=>transform});var c={};__webpack_require__.r(c),__webpack_require__.d(c,{transform:()=>parameter_oneof_transform});var i={};__webpack_require__.r(i),__webpack_require__.d(i,{allErrors:()=>Ze,lastError:()=>et});var p={};__webpack_require__.r(p),__webpack_require__.d(p,{SHOW:()=>dt,UPDATE_FILTER:()=>mt,UPDATE_LAYOUT:()=>pt,UPDATE_MODE:()=>ut,changeMode:()=>changeMode,show:()=>actions_show,updateFilter:()=>updateFilter,updateLayout:()=>updateLayout});var m={};__webpack_require__.r(m),__webpack_require__.d(m,{current:()=>current,currentFilter:()=>currentFilter,isShown:()=>isShown,showSummary:()=>gt,whatMode:()=>whatMode});var u={};__webpack_require__.r(u),__webpack_require__.d(u,{taggedOperations:()=>taggedOperations});var d={};__webpack_require__.r(d),__webpack_require__.d(d,{requestSnippetGenerator_curl_bash:()=>requestSnippetGenerator_curl_bash,requestSnippetGenerator_curl_cmd:()=>requestSnippetGenerator_curl_cmd,requestSnippetGenerator_curl_powershell:()=>requestSnippetGenerator_curl_powershell});var h={};__webpack_require__.r(h),__webpack_require__.d(h,{getActiveLanguage:()=>St,getDefaultExpanded:()=>Et,getGenerators:()=>ft,getSnippetGenerators:()=>getSnippetGenerators});var g={};__webpack_require__.r(g),__webpack_require__.d(g,{allowTryItOutFor:()=>allowTryItOutFor,basePath:()=>$r,canExecuteScheme:()=>canExecuteScheme,consumes:()=>Pr,consumesOptionsFor:()=>consumesOptionsFor,contentTypeValues:()=>contentTypeValues,currentProducesFor:()=>currentProducesFor,definitions:()=>Jr,externalDocs:()=>Nr,findDefinition:()=>findDefinition,getOAS3RequiredRequestBodyContentType:()=>getOAS3RequiredRequestBodyContentType,getParameter:()=>getParameter,hasHost:()=>Wr,host:()=>Vr,info:()=>Or,isMediaTypeSchemaPropertiesEqual:()=>isMediaTypeSchemaPropertiesEqual,isOAS3:()=>xr,lastError:()Line truncated
//# sourceMappingURL=swagger-ui.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack://SwaggerUICore/webpack/universalModuleDefinition","webpack://SwaggerUICore/webpack/bootstrap","webpack://SwaggerUICore/external \"react\"","webpack://SwaggerUICore/external \"immutable\"","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/defineProperty.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/createClass.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/classCallCheck.js","webpack://SwaggerUICore/./src/core/utils.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/inherits.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/createSuper.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/assertThisInitialized.js","webpack://SwaggerUICore/external \"prop-types\"","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/slicedToArray.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/object/keys.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/toConsumableArray.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js","webpack://SwaggerUICore/external \"reselect\"","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/typeof.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/export.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/objectSpread2.js","webpack://SwaggerUICore/./src/core/window.js","webpack://SwaggerUICore/external \"react-immutable-proptypes\"","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/extends.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/path.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/fails.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js","webpack://SwaggerUICore/./src/core/plugins/oas3/helpers.jsx","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/well-known-symbol.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/regenerator/index.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/global.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/entry-virtual.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/is-object.js","webpack://SwaggerUICore/./node_modules/lodash/get.js","webpack://SwaggerUICore/./src/core/plugins/spec/actions.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/descriptors.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/define-well-known-symbol.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/createForOfIteratorHelper.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/has.js","webpack://SwaggerUICore/./node_modules/lodash/isArray.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/an-object.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/helpers/objectWithoutProperties.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/instance/find.js","webpack://SwaggerUICore/./src/core/plugins/oas3/actions.js","webpack://SwaggerUICore/./node_modules/lodash/isObject.js","webpack://SwaggerUICore/./node_modules/swagger-client/es/helpers.js","webpack://SwaggerUICore/./src/core/plugins/err/actions.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/object-define-property.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/array-method-uses-to-length.js","webpack://SwaggerUICore/external \"classnames\"","webpack://SwaggerUICore/./node_modules/lodash/isFunction.js","webpack://SwaggerUICore/./node_modules/@babel/runtime-corejs3/core-js-stable/promise.js","webpack://SwaggerUICore/./node_modules/core-js-pure/internals/to-indexed-objLine truncated
{"version":3,"file":"swagger-ui.js","mappings":"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 truncated
+30 -20
View File
@@ -9,10 +9,11 @@ We assume that you have installed software:
### Download and start image
First of all, you must run WhatsApp HTTP API locally (which under the hood it runs real WhatsApp Web instance and expose
HTTP API for interaction).
First of all, you must run WhatsApp HTTP API locally (which under the hood it
runs real WhatsApp Web instance and expose HTTP API for interaction).
Here are the steps from [Quick Start](https://waha.devlike.pro/docs/overview/quick-start/):
Here are the steps from
[Quick Start](https://waha.devlike.pro/docs/overview/quick-start/):
Download and start WhatsApp HTTP API docker container
@@ -28,9 +29,11 @@ docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bo
#### Download image - ARM
If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following commands to download the image
If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following
commands to download the image
![](/images/versions/core.png) For Core version the command is
```bash
# Download the image
docker pull devlikeapro/whatsapp-http-api:arm
@@ -47,12 +50,16 @@ docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bo
2. Open Swagger API in the browser http://localhost:3000/
3. Start session and scan QR code in swagger
1. Find `POST /api/session/start` request press **Try it out** and **Execute** it with `default` session name
2. Find `GET /api/screenshot` and execute it - it must show QR code
3. Scan QR code on your mobile WhatsApp application (that installed on your phone)
4. Execute `GET /api/screenshot` once again - it must show the screenshot from WhatsApp Web.
4. Send test text message - find `POST /api/sendText` and execute it with payload (change `12132132130` in the `chatId`
to phone number that is registered in WhatsApp).
1. Find `POST /api/session/start` request press **Try it out** and
**Execute** it with `default` session name
2. Find `GET /api/screenshot` and execute it - it must show QR code
3. Scan QR code on your mobile WhatsApp application (that installed on your
phone)
4. Execute `GET /api/screenshot` once again - it must show the screenshot
from WhatsApp Web.
4. Send test text message - find `POST /api/sendText` and execute it with
payload (change `12132132130` in the `chatId` to phone number that is
registered in WhatsApp).
```json
{
@@ -66,9 +73,9 @@ If you see **Hi there!** message then you're ready to run bots!
## WhatsApp Echo Bot
The WhatsApp Echo Bot is a sample flask webhook server application that echoes back to you whatever you send it. It can
serve
as a basic reference for how to set up webhooks and reply to incoming messages.
The WhatsApp Echo Bot is a sample flask webhook server application that echoes
back to you whatever you send it. It can serve as a basic reference for how to
set up webhooks and reply to incoming messages.
```bash
# Clone the git repository with example
@@ -81,16 +88,19 @@ python -mpip install -r requirements.txt
FLASK_APP=whatsapp_echo_bot.py flask run
```
Open http://127.0.0.1:5000/bot - if you see **WhatsApp Echo Bot is ready!** then the bot is ready to receive message!
Open http://127.0.0.1:5000/bot - if you see **WhatsApp Echo Bot is ready!** then
the bot is ready to receive message!
Send message to the WhatsApp (that you used to scan QR code) and it'll echo text back to you!
Send message to the WhatsApp (that you used to scan QR code) and it'll echo text
back to you!
## WhatsApp Download Files Bot
The WhatsApp Download Image Bot downloads all files people send to your WhatsApp and log the path for the file.
The WhatsApp Download Image Bot downloads all files people send to your WhatsApp
and log the path for the file.
**The bot works only with WAHA Plus version** available with donations.
Visit [read more about difference between Core and Plus versions](https://waha.devlike.pro/docs/how-to/plus-version/).
**The bot works only with WAHA Plus version** available with donations. Visit
[read more about difference between Core and Plus versions](https://waha.devlike.pro/docs/how-to/plus-version/).
Download **WAHA Plus** version:
@@ -114,5 +124,5 @@ python -mpip install -r requirements.txt
FLASK_APP=whatsapp_download_files_bot.py flask run
```
Open http://127.0.0.1:5000/bot - if you see **WhatsApp Download Files Bot!** then the bot is ready to receive message
with files!
Open http://127.0.0.1:5000/bot - if you see **WhatsApp Download Files Bot!**
then the bot is ready to receive message with files!
+36 -1
View File
@@ -1,4 +1,6 @@
import random
from pprint import pprint
from time import sleep
import requests
from flask import Flask
@@ -49,6 +51,30 @@ def send_seen(chat_id, message_id, participant):
)
response.raise_for_status()
def start_typing(chat_id):
response = requests.post(
"http://localhost:3000/api/startTyping",
json={
"session": "default",
"chatId": chat_id,
},
)
response.raise_for_status()
def stop_typing(chat_id):
response = requests.post(
"http://localhost:3000/api/stopTyping",
json={
"session": "default",
"chatId": chat_id,
},
)
response.raise_for_status()
def typing(chat_id, seconds):
start_typing(chat_id=chat_id)
sleep(seconds)
stop_typing(chat_id=chat_id)
@app.route("/")
def whatsapp_echo():
@@ -69,7 +95,12 @@ def whatsapp_webhook():
# Payload that we've got
payload = data["payload"]
# The text
text = payload["body"]
text = payload.get("body")
if not text:
# We can't process non-text messages yet
print("No text in message")
print(payload)
return "OK"
# Number in format 1231231231@c.us or @g.us for group
chat_id = payload["from"]
# Message ID - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -79,9 +110,13 @@ def whatsapp_webhook():
# IMPORTANT - Always send seen before sending new message
send_seen(chat_id=chat_id, message_id=message_id, participant=participant)
# Send a text back via WhatsApp HTTP API
typing(chat_id=chat_id, seconds=random.random() * 3)
send_message(chat_id=chat_id, text=text)
# OR reply on the message
typing(chat_id=chat_id, seconds=random.random() * 3)
reply(chat_id=chat_id, message_id=message_id, text=text)
# Send OK back
Binary file not shown.
+1 -3
View File
@@ -2,8 +2,6 @@
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": [
"@nestjs/swagger"
]
"plugins": ["@nestjs/swagger"]
}
}
+7 -3
View File
@@ -14,7 +14,7 @@
"start:debug": "nest start --debug --watch",
"start:prod": "node --unhandled-rejections=none dist/main",
"start:prod-exit": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --max-warnings=0",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
@@ -24,15 +24,18 @@
"dependencies": {
"@adiwajshing/baileys": "github:WhiskeySockets/Baileys",
"@adiwajshing/keyed-db": "^0.2.4",
"@nestjs/axios": "^3.0.2",
"@nestjs/common": "^9.0.9",
"@nestjs/config": "^0.5.0",
"@nestjs/core": "^9.0.9",
"@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.0.9",
"@nestjs/serve-static": "^2.1.3",
"@nestjs/swagger": "^6.0.5",
"@nestjs/swagger": "^7.1.11",
"@nestjs/terminus": "^10.2.3",
"@types/lodash": "^4.14.194",
"@types/ws": "^8.5.4",
"check-disk-space": "^3.4.0",
"class-validator": "^0.12.2",
"del": "^6.0.0",
"express-basic-auth": "^1.2.1",
@@ -42,6 +45,7 @@
"link-preview-js": "^3.0.4",
"lodash": "^4.17.21",
"mime-types": "^2.1.27",
"mongodb": "^6.3.0",
"passport": "^0.6.0",
"passport-headerapikey": "^1.2.2",
"qrcode": "^1.5.1",
@@ -53,7 +57,7 @@
"rxjs": "^7.1.0",
"swagger-ui-express": "^4.1.4",
"venom-bot": "5.0.1",
"whatsapp-web.js": "https://github.com/elhumbertoz/whatsapp-web.js#patch-2"
"whatsapp-web.js": "https://github.com/devlikeapro/whatsapp-web.js#main-fork"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
+54
View File
@@ -0,0 +1,54 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
StreamableFile,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Base64File } from '../structures/files.dto';
@Injectable()
/**
* Interceptor to convert Buffer response to Base64File or StreamableFile
* based on Accept header.
* It should go together with @ApiFileAcceptHeader in controller method
* So we have proper Swagger documentation
*/
export class BufferResponseInterceptor<T>
implements NestInterceptor<Buffer, Base64File | StreamableFile>
{
intercept(
context: ExecutionContext,
next: CallHandler,
): Observable<Base64File | StreamableFile> {
const ctx = context.switchToHttp();
const request = ctx.getRequest<Request>();
const response = ctx.getResponse<Response>();
return next.handle().pipe(map(processBuffer));
function processBuffer(buffer: Buffer) {
// Check buffer is Buffer
if (!Buffer.isBuffer(buffer)) {
return buffer;
}
const accept = request.headers['accept'];
if (accept == 'application/json') {
return {
mimetype: 'image/png',
data: buffer.toString('base64'),
};
}
const file = new StreamableFile(buffer);
response.set({
'Content-Type': 'image/png',
'Content-Length': buffer.length,
});
return file;
}
}
}
+59 -22
View File
@@ -1,14 +1,28 @@
import { Body, Controller, Get, Post, Res } from '@nestjs/common';
import {
Body,
Controller,
Get,
Post,
Query,
UseInterceptors,
} from '@nestjs/common';
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { OTPRequest, RequestCodeRequest } from '../structures/auth.dto';
import { SessionApiParam, SessionParam } from './helpers';
import {
CaptchaBody,
OTPRequest,
QRCodeFormat,
QRCodeQuery,
QRCodeValue,
RequestCodeRequest,
} from '../structures/auth.dto';
import { WAHASessionStatus } from '../structures/enums.dto';
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import { Readable } from 'stream';
import { Response } from 'express';
import { Base64File } from '../structures/files.dto';
import { BufferResponseInterceptor } from './BufferResponseInterceptor';
import { ApiFileAcceptHeader, SessionApiParam, SessionParam } from './helpers';
@ApiSecurity('api_key')
@Controller('api/:session/auth')
@@ -17,44 +31,43 @@ class AuthController {
constructor(private manager: SessionManager) {}
@Get('qr')
@SessionApiParam
@ApiOperation({
summary: 'Get QR code for pairing WhatsApp Web.',
})
async getQR(@Res() res: Response, @SessionParam session: WhatsappSession) {
@SessionApiParam
@ApiFileAcceptHeader(Base64File, QRCodeValue)
@UseInterceptors(new BufferResponseInterceptor())
async getQR(
@SessionParam session: WhatsappSession,
@Query() query: QRCodeQuery,
): Promise<Buffer | QRCodeValue> {
if (session.status != WAHASessionStatus.SCAN_QR_CODE) {
const err = `Can get QR code only in SCAN_QR_CODE status. The current status is '${session.status}'`;
throw new UnprocessableEntityException(err);
}
const buffer = await session.getQR();
const stream = new Readable();
stream.push(buffer);
stream.push(null);
res.set({
'Content-Type': 'image/png',
'Content-Length': buffer.length,
});
stream.pipe(res);
const qr = session.getQR();
if (query.format == QRCodeFormat.RAW) {
return { value: qr.raw };
}
return qr.get();
}
@Post('request-code')
@SessionApiParam
@ApiOperation({
summary: 'Request authentication code. NOWEB and NOWEB_MOBILE engines only',
summary: 'Request authentication code.',
})
requestCode(
@SessionParam session: WhatsappSession,
@Body() request: RequestCodeRequest,
) {
return session.requestCode(request.phoneNumber, request.method);
return session.requestCode(request.phoneNumber, request.method, request);
}
@Post('authorize-code')
@SessionApiParam
@ApiOperation({
summary: 'Send OTP authentication code. NOWEB_MOBILE engine only',
summary: 'Send OTP authentication code.',
})
authorizeCode(
@SessionParam session: WhatsappSession,
@@ -62,6 +75,30 @@ class AuthController {
) {
return session.authorizeCode(request.code);
}
@Get('captcha')
@SessionApiParam
@ApiFileAcceptHeader()
@UseInterceptors(new BufferResponseInterceptor())
@ApiOperation({
summary: 'Get captcha image.',
})
async getCaptcha(@SessionParam session: WhatsappSession): Promise<Buffer> {
const image = await session.getCaptcha();
return image.get();
}
@Post('captcha')
@SessionApiParam
@ApiOperation({
summary: 'Enter captcha code.',
})
saveCaptcha(
@SessionParam session: WhatsappSession,
@Body() body: CaptchaBody,
) {
return session.saveCaptcha(body.code);
}
}
export { AuthController };
+2 -2
View File
@@ -3,9 +3,9 @@ import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { SessionApiParam, SessionParam } from './helpers';
import { GetChatMessagesQuery } from '../structures/chats.dto';
import { parseBool } from '../helpers';
import { GetChatMessagesQuery } from '../structures/chats.dto';
import { SessionApiParam, SessionParam } from './helpers';
@ApiSecurity('api_key')
@Controller('api/:session/chats')
+11
View File
@@ -16,6 +16,7 @@ import {
MessageReplyRequest,
MessageTextQuery,
MessageTextRequest,
MessageVideoRequest,
MessageVoiceRequest,
SendSeenRequest,
WANumberExistResult,
@@ -111,6 +112,16 @@ export class ChattingController {
return whatsapp.sendVoice(request);
}
@Post('/sendVideo')
@ApiOperation({
summary:
'Send a video. Either from an URL or base64 data - look at the request schemas for details.',
})
sendVideo(@Body() request: MessageVideoRequest) {
const whatsapp = this.manager.getSession(request.session);
return whatsapp.sendVideo(request);
}
@Post('/reply')
@ApiOperation({ summary: 'Reply to a text message' })
reply(@Body() request: MessageReplyRequest) {
+1
View File
@@ -67,6 +67,7 @@ export class ContactsController {
const whatsapp = this.manager.getSession(request.session);
return whatsapp.blockContact(request);
}
@Post('/unblock')
@ApiOperation({ summary: 'Unblock contact' })
unblock(@Body() request: ContactRequest) {
+27 -1
View File
@@ -23,16 +23,42 @@ export function serializeError(err: unknown) {
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: HttpException | Error, host: ArgumentsHost): void {
catch(exception: any | Error, host: ArgumentsHost): void {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
/**
* If file not found - we get weird 500 error
* So we convert that exception manually to 404 and send appropriate JSON response
* @issue https://github.com/devlikeapro/whatsapp-http-api/issues/134
* @solution https://github.com/nestjs/serve-static/issues/139#issuecomment-612429557
*/
if (exception.code === 'ENOENT') {
response.status(HttpStatus.NOT_FOUND).json({
error: {
code: 404,
key: 'FILE_NOT_FOUND',
message: 'File not found',
details: 'File not found or no longer available',
},
});
response.send();
return;
}
/**
* If it's HttpException - pass it as is
*/
if (exception instanceof HttpException) {
response.status(exception.getStatus()).json(exception.getResponse());
return;
}
/**
* If it's not HttpException - pass it as 500 error
* And send JSON response with error details
*/
const httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
response.status(httpStatus).json({
statusCode: httpStatus,
+14
View File
@@ -15,6 +15,7 @@ import {
CreateGroupRequest,
DescriptionRequest,
ParticipantsRequest,
SettingsSecurityChangeInfo,
SubjectRequest,
} from '../structures/groups.dto';
import { SessionApiParam, SessionParam } from './helpers';
@@ -62,6 +63,19 @@ export class GroupsController {
return session.setInfoAdminsOnly(id, true);
}
@Get(':id/settings/security/info-admin-only')
@SessionApiParam
@ApiOperation({
summary:
'Gets the group settings to only allow admins to edit group info (title, description, photo).',
})
getInfoAdminOnly(
@SessionParam session: WhatsappSession,
@Param('id') id: string,
): Promise<SettingsSecurityChangeInfo> {
return session.getInfoAdminsOnly(id);
}
@Delete(':id')
@SessionApiParam
@ApiOperation({ summary: 'Delete the group.' })
+17
View File
@@ -0,0 +1,17 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { HealthCheck } from '@nestjs/terminus';
import { WAHAHealthCheckService } from '../core/abc/WAHAHealthCheckService';
@Controller('health')
@ApiTags('other')
export class HealthController {
constructor(private wahaHealth: WAHAHealthCheckService) {}
@Get()
@HealthCheck()
async check() {
return this.wahaHealth.check();
}
}
+47 -2
View File
@@ -1,8 +1,19 @@
import { Injectable, Param, PipeTransform } from '@nestjs/common';
import { ApiParam } from '@nestjs/swagger';
import {
applyDecorators,
Injectable,
Param,
PipeTransform,
} from '@nestjs/common';
import {
ApiExtraModels,
ApiParam,
ApiResponse,
getSchemaPath,
} from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { Base64File } from '../structures/files.dto';
/**
* Get session name and return Whatsapp session back (if exists)
@@ -25,6 +36,9 @@ export const SessionApiParam = ApiParam({
name: 'session',
required: true,
type: 'string',
schema: {
default: 'default',
},
description: 'WhatsApp session name',
});
@@ -33,3 +47,34 @@ export const SessionApiParam = ApiParam({
@SessionParam session: WhatsappSession,
*/
export const SessionParam = Param('session', SessionPipe);
function getRefSchemaPaths(models) {
return models.map((model) => {
return { $ref: getSchemaPath(model) };
});
}
export function ApiFileAcceptHeader(...models) {
models = models.length ? models : [Base64File];
return applyDecorators(
// Add extra models, otherwise it'll give a error
// $ref not found
ApiExtraModels(...models),
ApiResponse({
status: 200,
content: {
'image/png': {
schema: {
type: 'string',
format: 'binary',
},
},
'application/json': {
schema: {
oneOf: getRefSchemaPaths(models),
},
},
},
}),
);
}
+1 -1
View File
@@ -10,12 +10,12 @@ import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { WAHAPresenceStatus } from '../structures/enums.dto';
import {
WAHAChatPresences,
WAHASessionPresence,
} from '../structures/presence.dto';
import { SessionApiParam, SessionParam } from './helpers';
import { WAHAPresenceStatus } from '../structures/enums.dto';
@ApiSecurity('api_key')
@Controller('api/:session/presence')
+17 -13
View File
@@ -1,10 +1,18 @@
import { Controller, Get, Query, Res } from '@nestjs/common';
import {
Controller,
Get,
Query,
Res,
StreamableFile,
UseInterceptors,
} from '@nestjs/common';
import { ApiSecurity, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import { Readable } from 'stream';
import { SessionManager } from '../core/abc/manager.abc';
import { SessionQuery } from '../structures/base.dto';
import { BufferResponseInterceptor } from './BufferResponseInterceptor';
import { ApiFileAcceptHeader } from './helpers';
@ApiSecurity('api_key')
@Controller('api')
@@ -13,17 +21,13 @@ export class ScreenshotController {
constructor(private manager: SessionManager) {}
@Get('/screenshot')
async screenshot(@Res() res: Response, @Query() sessionQuery: SessionQuery) {
@UseInterceptors(new BufferResponseInterceptor())
@ApiFileAcceptHeader()
async screenshot(
@Res({ passthrough: true }) res: Response,
@Query() sessionQuery: SessionQuery,
) {
const whatsappService = this.manager.getSession(sessionQuery.session);
const buffer = await whatsappService.getScreenshot();
const stream = new Readable();
stream.push(buffer);
stream.push(null);
res.set({
'Content-Type': 'image/png',
'Content-Length': buffer.length,
});
stream.pipe(res);
return await whatsappService.getScreenshot();
}
}
+10 -7
View File
@@ -1,8 +1,13 @@
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import {
ApiExtraModels,
ApiOperation,
ApiSecurity,
ApiTags,
} from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { parseBool } from '../helpers';
import {
ListSessionsQuery,
@@ -14,8 +19,6 @@ import {
SessionStopRequest,
} from '../structures/sessions.dto';
import { SessionApiParam, SessionParam } from './helpers';
import { WhatsappSession } from '../core/abc/session.abc';
import { WAHAChatPresences } from '../structures/presence.dto';
@ApiSecurity('api_key')
@Controller('api/sessions')
@@ -26,9 +29,9 @@ class SessionsController {
@Post('/start/')
async start(@Body() request: SessionStartRequest): Promise<SessionDTO> {
const result = await this.manager.start(request);
await this.manager.sessionStorage.configRepository.save(
await this.manager.sessionConfigRepository.save(
request.name,
request.config,
request.config || null,
);
return result;
}
@@ -65,7 +68,7 @@ class SessionController {
@Get('me')
@SessionApiParam
@ApiOperation({ summary: 'Get information about the authenticated account' })
getMe(@SessionParam session: WhatsappSession): Promise<MeInfo> {
getMe(@SessionParam session: WhatsappSession): Promise<MeInfo | null> {
return session.getSessionMeInfo();
}
}
+1 -1
View File
@@ -11,13 +11,13 @@ import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { SessionManager } from '../core/abc/manager.abc';
import { WhatsappSession } from '../core/abc/session.abc';
import { SessionApiParam, SessionParam } from './helpers';
import {
ImageStatus,
TextStatus,
VideoStatus,
VoiceStatus,
} from '../structures/status.dto';
import { SessionApiParam, SessionParam } from './helpers';
@ApiSecurity('api_key')
@Controller('api/:session/status')
+3 -2
View File
@@ -1,6 +1,7 @@
import { Controller, Get } from '@nestjs/common';
import { ApiSecurity, ApiTags } from '@nestjs/swagger';
import { ApiExtraModels, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { WAHAEnvironment } from '../structures/environment.dto';
import { VERSION } from '../version';
@ApiSecurity('api_key')
@@ -8,7 +9,7 @@ import { VERSION } from '../version';
@ApiTags('other')
export class VersionController {
@Get('')
async get() {
get(): WAHAEnvironment {
return VERSION;
}
}
+45 -5
View File
@@ -4,6 +4,7 @@ import { ConfigService } from '@nestjs/config';
import { parseBool } from './helpers';
import { WAHAEngine } from './structures/enums.dto';
import { WebhookConfig } from './structures/webhooks.config.dto';
import { getEngineName } from './version';
@Injectable()
export class WhatsappConfigService {
@@ -35,9 +36,17 @@ export class WhatsappConfigService {
return this.configService.get<number>('WHATSAPP_FILES_LIFETIME', 180);
}
get mimetypes(): string[] | null {
get mimetypes(): string[] {
if (!this.shouldDownloadMedia) {
return ['mimetype/ignore-all-media'];
}
const types = this.configService.get('WHATSAPP_FILES_MIMETYPES', '');
return types ? types.split(',') : null;
return types ? types.split(',') : [];
}
get shouldDownloadMedia(): boolean {
const value = this.configService.get('WHATSAPP_DOWNLOAD_MEDIA', 'true');
return parseBool(value);
}
get startSessions(): string[] {
@@ -99,17 +108,22 @@ export class WhatsappConfigService {
return value ? value.split(',') : [];
}
getSessionMongoUrl(): string | undefined {
return this.configService.get('WHATSAPP_SESSIONS_MONGO_URL', undefined);
}
getDefaultEngineName(): WAHAEngine {
const value = this.get('WHATSAPP_DEFAULT_ENGINE', WAHAEngine.WEBJS);
const value = getEngineName();
if (value in WAHAEngine) {
return WAHAEngine[value];
}
console.log(
`Unknown WhatsApp default engine, using WEBJS. WHATSAPP_DEFAULT_ENGINE=${value}`,
`Unknown WhatsApp default engine WHATSAPP_DEFAULT_ENGINE=${value}. Using WEBJS`,
);
return WAHAEngine.WEBJS;
}
get(name: string, defaultValue = undefined): any {
get(name: string, defaultValue: any = undefined): any {
return this.configService.get(name, defaultValue);
}
@@ -117,6 +131,11 @@ export class WhatsappConfigService {
return this.configService.get('WHATSAPP_API_KEY', '');
}
getSwaggerEnabled(): boolean {
const value = this.configService.get('WHATSAPP_SWAGGER_ENABLED', 'true');
return parseBool(value);
}
getSwaggerUsernamePassword(): [string, string] | undefined {
const user = this.configService.get('WHATSAPP_SWAGGER_USERNAME', undefined);
const password = this.configService.get(
@@ -136,4 +155,25 @@ export class WhatsappConfigService {
getSwaggerAdvancedConfigEnabled(): boolean {
return this.configService.get('WHATSAPP_SWAGGER_CONFIG_ADVANCED', false);
}
getHealthMediaFilesThreshold(): number {
return this.configService.get<number>(
'WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB',
100,
);
}
getHealthSessionFilesThreshold(): number {
return this.configService.get<number>(
'WHATSAPP_HEALTH_SESSION_FILES_THRESHOLD_MB',
100,
);
}
getHealthMongoTimeout(): number {
return this.configService.get<number>(
'WHATSAPP_HEALTH_MONGO_TIMEOUT_MS',
3000,
);
}
}
+3 -1
View File
@@ -1,8 +1,10 @@
export class QR {
private base64: string;
public raw?: string;
save(base64) {
save(base64: string, raw?: string) {
this.base64 = base64.replace(/^data:image\/png;base64,/, '');
this.raw = raw;
}
get(): Buffer {
+1
View File
@@ -0,0 +1 @@
export abstract class DataStore {}
+18
View File
@@ -0,0 +1,18 @@
import { ConsoleLogger, Injectable } from '@nestjs/common';
import { DiskHealthIndicator, HealthCheckService } from '@nestjs/terminus';
import type { HealthCheckResult } from '@nestjs/terminus/dist/health-check/health-check-result.interface';
import { WhatsappConfigService } from '../../config.service';
import { SessionManager } from './manager.abc';
@Injectable()
export abstract class WAHAHealthCheckService {
constructor(
protected sessionManager: SessionManager,
protected health: HealthCheckService,
protected log: ConsoleLogger,
protected config: WhatsappConfigService,
) {}
abstract check(): Promise<HealthCheckResult>;
}
+6 -5
View File
@@ -8,12 +8,15 @@ import {
SessionStartRequest,
SessionStopRequest,
} from '../../structures/sessions.dto';
import { ISessionAuthRepository } from '../storage/ISessionAuthRepository';
import { ISessionConfigRepository } from '../storage/ISessionConfigRepository';
import { WhatsappSession } from './session.abc';
import { LocalSessionStorage, MediaStorage } from './storage.abc';
import { WebhookConductor } from './webhooks.abc';
export abstract class SessionManager implements OnApplicationShutdown {
public sessionStorage: LocalSessionStorage;
public store: any;
public sessionAuthRepository: ISessionAuthRepository;
public sessionConfigRepository: ISessionConfigRepository;
protected abstract getEngine(engine: WAHAEngine): typeof WhatsappSession;
@@ -21,8 +24,6 @@ export abstract class SessionManager implements OnApplicationShutdown {
protected abstract get WebhookConductorClass(): typeof WebhookConductor;
protected abstract get MediaStorageClass(): typeof MediaStorage;
abstract onApplicationShutdown(signal?: string);
//
@@ -34,7 +35,7 @@ export abstract class SessionManager implements OnApplicationShutdown {
abstract logout(request: SessionLogoutRequest): Promise<void>;
abstract getSession(name: string, error?: boolean): WhatsappSession;
abstract getSession(name: string): WhatsappSession;
abstract getSessions(all: boolean): Promise<SessionInfo[]>;
}
+28
View File
@@ -0,0 +1,28 @@
abstract class MediaStorage {
abstract save(
messageId: string,
mimetype: string,
buffer: Buffer,
): Promise<string>;
}
interface IEngineMediaProcessor<Message> {
hasMedia(message: Message): boolean;
getFilename(message: Message): string | null;
getMimetype(message: Message): string;
getMessageId(message: Message): string;
getMediaBuffer(message: Message): Promise<Buffer | null>;
}
interface MediaManager {
processMedia<Message>(
processor: IEngineMediaProcessor<Message>,
message: Message,
): Promise<Message>;
}
export { IEngineMediaProcessor, MediaManager, MediaStorage };
+81 -24
View File
@@ -16,6 +16,7 @@ import {
MessageReactionRequest,
MessageReplyRequest,
MessageTextRequest,
MessageVideoRequest,
MessageVoiceRequest,
} from '../../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../../structures/contacts.dto';
@@ -28,6 +29,7 @@ import {
import {
CreateGroupRequest,
ParticipantsRequest,
SettingsSecurityChangeInfo,
} from '../../structures/groups.dto';
import { WAHAChatPresences } from '../../structures/presence.dto';
import {
@@ -35,15 +37,17 @@ import {
ProxyConfig,
SessionConfig,
} from '../../structures/sessions.dto';
import { NotImplementedByEngineError } from '../exceptions';
import { LocalSessionStorage, MediaStorage } from './storage.abc';
import { OTPRequest, RequestCodeRequest } from '../../structures/auth.dto';
import {
ImageStatus,
TextStatus,
VideoStatus,
VoiceStatus,
} from '../../structures/status.dto';
import { WASessionStatusBody } from '../../structures/webhooks.dto';
import { NotImplementedByEngineError } from '../exceptions';
import { QR } from '../QR';
import { DataStore } from './DataStore';
import { MediaManager } from './media.abc';
const CHROME_PATH = '/usr/bin/google-chrome-stable';
const CHROMIUM_PATH = '/usr/bin/chromium';
@@ -64,48 +68,58 @@ export function ensureSuffix(phone) {
}
export enum WAHAInternalEvent {
engine_start = 'engine.start',
ENGINE_START = 'engine.start',
SESSION_STATUS_CHANGED = 'session.status.changed',
}
export interface SessionParams {
name: string;
storage: MediaStorage;
mediaManager: MediaManager;
log: ConsoleLogger;
sessionStorage: LocalSessionStorage;
sessionStore: DataStore;
proxyConfig?: ProxyConfig;
sessionConfig: SessionConfig;
sessionConfig?: SessionConfig;
}
export abstract class WhatsappSession {
public status: WAHASessionStatus;
public events: EventEmitter;
public engine: WAHAEngine;
public name: string;
protected storage: MediaStorage;
protected mediaManager: MediaManager;
protected log: ConsoleLogger;
protected sessionStorage: LocalSessionStorage;
protected sessionStore: DataStore;
protected proxyConfig?: ProxyConfig;
public sessionConfig: SessionConfig;
public sessionConfig?: SessionConfig;
private _status: WAHASessionStatus;
public constructor({
name,
log,
sessionStorage,
sessionStore,
proxyConfig,
storage,
mediaManager,
sessionConfig,
}: SessionParams) {
this.events = new EventEmitter();
this.name = name;
this.proxyConfig = proxyConfig;
this.status = WAHASessionStatus.STARTING;
this.log = log;
this.sessionStorage = sessionStorage;
this.events = new EventEmitter();
this.storage = storage;
this.sessionStore = sessionStore;
this.mediaManager = mediaManager;
this.sessionConfig = sessionConfig;
}
protected set status(value: WAHASessionStatus) {
this._status = value;
this.events.emit(WAHAInternalEvent.SESSION_STATUS_CHANGED, value);
}
public get status() {
return this._status;
}
getBrowserExecutablePath() {
return getBrowserExecutablePath();
}
@@ -140,14 +154,37 @@ export abstract class WhatsappSession {
];
}
protected isDebugEnabled() {
return this.log.isLevelEnabled('debug');
}
/** Start the session */
abstract start();
/** Stop the session */
abstract stop(): void;
abstract stop(): Promise<void>;
/** Subscribe the handler to specific hook */
abstract subscribe(hook: WAHAEvents | string, handler: (message) => void);
subscribeSessionEvent(
hook: WAHAEvents | string,
handler: (message) => void,
): boolean {
switch (hook) {
case WAHAEvents.SESSION_STATUS:
this.events.on(WAHAInternalEvent.SESSION_STATUS_CHANGED, (value) => {
const body: WASessionStatusBody = { name: this.name, status: value };
handler(body);
});
return true;
default:
return false;
}
}
abstract subscribeEngineEvent(
hook: WAHAEvents | string,
handler: (message) => void,
): boolean;
/**
* START - Methods for API
@@ -157,11 +194,11 @@ export abstract class WhatsappSession {
* Auth methods
*/
public getQR(): Promise<Buffer> {
public getQR(): QR {
throw new NotImplementedByEngineError();
}
public requestCode(phoneNumber: string, method: string) {
public requestCode(phoneNumber: string, method: string, params?: any) {
throw new NotImplementedByEngineError();
}
@@ -169,12 +206,20 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError();
}
abstract getScreenshot(): Promise<Buffer | string>;
abstract getScreenshot(): Promise<Buffer>;
public getSessionMeInfo(): Promise<MeInfo | null> {
throw new NotImplementedByEngineError();
}
public getCaptcha(): Promise<QR> {
throw new NotImplementedByEngineError();
}
public saveCaptcha(code: string) {
throw new NotImplementedByEngineError();
}
/**
* Other methods
*/
@@ -182,7 +227,9 @@ export abstract class WhatsappSession {
abstract sendText(request: MessageTextRequest);
abstract sendContactVCard(request: MessageContactVcardRequest);
sendContactVCard(request: MessageContactVcardRequest) {
throw new NotImplementedByEngineError();
}
sendPoll(request: MessagePollRequest) {
throw new NotImplementedByEngineError();
@@ -190,7 +237,9 @@ export abstract class WhatsappSession {
abstract sendLocation(request: MessageLocationRequest);
abstract sendLinkPreview(request: MessageLinkPreviewRequest);
sendLinkPreview(request: MessageLinkPreviewRequest) {
throw new NotImplementedByEngineError();
}
abstract sendImage(request: MessageImageRequest);
@@ -198,6 +247,10 @@ export abstract class WhatsappSession {
abstract sendVoice(request: MessageVoiceRequest);
sendVideo(request: MessageVideoRequest) {
throw new NotImplementedByEngineError();
}
abstract reply(request: MessageReplyRequest);
abstract sendSeen(chat: ChatRequest);
@@ -277,6 +330,10 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError();
}
public getInfoAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
throw new NotImplementedByEngineError();
}
public setInfoAdminsOnly(id, value) {
throw new NotImplementedByEngineError();
}
-40
View File
@@ -1,40 +0,0 @@
import { SessionConfig } from '../../structures/sessions.dto';
abstract class MediaStorage {
abstract save(
messageId: string,
mimetype: string,
buffer: Buffer,
): Promise<string>;
}
abstract class SessionConfigRepository {
abstract save(sessionName: string, config: SessionConfig): Promise<void>;
abstract get(sessionName: string): Promise<SessionConfig>;
}
abstract class SessionStorage {
protected constructor(public engine: string) {
this.engine = engine;
}
abstract init(sessionName?: string): Promise<void>;
abstract clean(sessionName: string): Promise<void>;
abstract getAll(): Promise<string[]>;
//
// Repositories
//
abstract get configRepository(): SessionConfigRepository;
}
abstract class LocalSessionStorage extends SessionStorage {
public sessionsFolder: string;
abstract getFolderPath(sessionName: string): string;
}
export { LocalSessionStorage, MediaStorage, SessionConfigRepository };
+13 -3
View File
@@ -2,23 +2,27 @@ import { ConsoleLogger, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { PassportModule } from '@nestjs/passport';
import { ServeStaticModule } from '@nestjs/serve-static';
import { TerminusModule } from '@nestjs/terminus';
import { AuthController } from '../api/auth.controller';
import { ChatsController } from '../api/chats.controller';
import { ChattingController } from '../api/chatting.controller';
import { ContactsController } from '../api/contacts.controller';
import { GroupsController } from '../api/groups.controller';
import { HealthController } from '../api/health.controller';
import { PresenceController } from '../api/presence.controller';
import { ScreenshotController } from '../api/screenshot.controller';
import {
SessionController,
SessionsController,
} from '../api/sessions.controller';
import { StatusController } from '../api/status.controller';
import { VersionController } from '../api/version.controller';
import { WhatsappConfigService } from '../config.service';
import { SessionManager } from './abc/manager.abc';
import { WAHAHealthCheckService } from './abc/WAHAHealthCheckService';
import { WAHAHealthCheckServiceCore } from './health/WAHAHealthCheckServiceCore';
import { SessionManagerCore } from './manager.core';
import { AuthController } from '../api/auth.controller';
import { ChatsController } from '../api/chats.controller';
import { StatusController } from '../api/status.controller';
export const IMPORTS = [
ConfigModule.forRoot({
@@ -38,6 +42,7 @@ export const IMPORTS = [
},
}),
PassportModule,
TerminusModule,
];
export const CONTROLLERS = [
AuthController,
@@ -51,12 +56,17 @@ export const CONTROLLERS = [
PresenceController,
ScreenshotController,
VersionController,
HealthController,
];
const PROVIDERS = [
{
provide: SessionManager,
useClass: SessionManagerCore,
},
{
provide: WAHAHealthCheckService,
useClass: WAHAHealthCheckServiceCore,
},
WhatsappConfigService,
ConsoleLogger,
];
@@ -0,0 +1,19 @@
import { useMultiFileAuthState } from '@adiwajshing/baileys';
import { Store } from 'whatsapp-web.js';
import { DataStore } from '../../abc/DataStore';
import { LocalStore } from '../../storage/LocalStore';
export class NowebAuthFactoryCore {
buildAuth(store: DataStore, name: string) {
if (store instanceof LocalStore) return this.buildLocalAuth(store, name);
throw new Error(`Unsupported store type '${store.constructor.name}'`);
}
protected async buildLocalAuth(store: LocalStore, name: string) {
await store.init(name);
const authFolder = store.getSessionDirectory(name);
const { state, saveCreds } = await useMultiFileAuthState(authFolder);
return { state, saveCreds };
}
}
@@ -5,6 +5,7 @@ import makeWASocket, {
getKeyAuthor,
isJidGroup,
jidNormalizedUser,
makeCacheableSignalKeyStore,
makeInMemoryStore,
PresenceData,
proto,
@@ -13,19 +14,16 @@ import makeWASocket, {
WAMessageKey,
} from '@adiwajshing/baileys';
import { UnprocessableEntityException } from '@nestjs/common';
import { request } from 'express';
import * as Buffer from 'buffer';
import * as fs from 'fs/promises';
import { Agent } from 'https';
import * as lodash from 'lodash';
import { update } from 'lodash';
import { PairingCodeResponse } from 'src/structures/auth.dto';
import { Message } from 'whatsapp-web.js';
import { flipObject, splitAt } from '../helpers';
import { flipObject, splitAt } from '../../../helpers';
import {
ChatRequest,
CheckNumberStatusQuery,
MessageContactVcardRequest,
MessageDestination,
MessageFileRequest,
MessageImageRequest,
@@ -38,8 +36,8 @@ import {
MessageVoiceRequest,
SendSeenRequest,
WANumberExistResult,
} from '../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
} from '../../../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
import {
ACK_UNKNOWN,
SECOND,
@@ -48,34 +46,36 @@ import {
WAHAPresenceStatus,
WAHASessionStatus,
WAMessageAck,
} from '../structures/enums.dto';
} from '../../../structures/enums.dto';
import {
CreateGroupRequest,
ParticipantsRequest,
} from '../structures/groups.dto';
} from '../../../structures/groups.dto';
import {
WAHAChatPresences,
WAHAPresenceData,
} from '../structures/presence.dto';
import { WAMessage } from '../structures/responses.dto';
import { BROADCAST_ID, TextStatus } from '../structures/status.dto';
} from '../../../structures/presence.dto';
import { WAMessage } from '../../../structures/responses.dto';
import { MeInfo } from '../../../structures/sessions.dto';
import { BROADCAST_ID, TextStatus } from '../../../structures/status.dto';
import {
PollVote,
PollVotePayload,
WAMessageAckBody,
} from '../structures/webhooks.dto';
} from '../../../structures/webhooks.dto';
import { IEngineMediaProcessor } from '../../abc/media.abc';
import {
ensureSuffix,
WAHAInternalEvent,
WhatsappSession,
} from './abc/session.abc';
} from '../../abc/session.abc';
import {
AvailableInPlusVersion,
NotImplementedByEngineError,
} from './exceptions';
import { createAgentProxy } from './helpers.proxy';
import { QR } from './QR';
import { MeInfo } from '../structures/sessions.dto';
} from '../../exceptions';
import { createAgentProxy } from '../../helpers.proxy';
import { QR } from '../../QR';
import { NowebAuthFactoryCore } from './NowebAuthFactoryCore';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const QRCode = require('qrcode');
@@ -103,6 +103,11 @@ const ToEnginePresenceStatus = flipObject(PresenceStatuses);
export class WhatsappSessionNoWebCore extends WhatsappSession {
engine = WAHAEngine.NOWEB;
authFactory = new NowebAuthFactoryCore();
get listenConnectionEventsFromTheStart() {
return true;
}
sock: any;
store: any;
@@ -114,14 +119,19 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
start() {
return this.buildClient();
this.status = WAHASessionStatus.STARTING;
this.buildClient();
}
getSocketConfig(agent, state) {
return {
agent: agent,
fetchAgent: agent,
auth: state,
auth: {
creds: state.creds,
/** caching makes the store faster to send/recv messages */
keys: makeCacheableSignalKeyStore(state.keys, logger),
},
printQRInTerminal: true,
browser: Browsers.macOS('Chrome'),
logger: logger,
@@ -132,14 +142,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
async makeSocket() {
const authFolder = this.sessionStorage.getFolderPath(this.name);
await fs.mkdir(authFolder, { recursive: true });
const { state, saveCreds } = await useMultiFileAuthState(authFolder);
const { state, saveCreds } = await this.authFactory.buildAuth(
this.sessionStore,
this.name,
);
const agent = this.makeAgent();
const socketConfig = this.getSocketConfig(agent, state);
const sock: any = makeWASocket(socketConfig);
sock.ev.on(BaileysEvents.CREDS_UPDATE, saveCreds);
this.debugLogEnginesEvents(sock);
return sock;
}
@@ -169,8 +179,13 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
async buildClient() {
this.sock = await this.makeSocket();
this.connectStore();
this.listenConnectionEvents();
this.events.emit(WAHAInternalEvent.engine_start);
if (this.isDebugEnabled()) {
this.listenEngineEventsInDebugMode();
}
if (this.listenConnectionEventsFromTheStart) {
this.listenConnectionEvents();
this.events.emit(WAHAInternalEvent.ENGINE_START);
}
}
protected async getMessage(
@@ -179,15 +194,21 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
if (!this.store) {
return proto.Message.fromObject({});
}
const msg = await this.store.loadMessage(key.remoteJid!, key.id!);
const msg = await this.store.loadMessage(key.remoteJid, key.id);
return msg?.message || undefined;
}
protected listenEngineEventsInDebugMode() {
this.sock.ev.process((events) => {
this.log.debug(`Received NOWEB events`, events);
});
}
protected listenConnectionEvents() {
this.log.debug(`Start listening ${BaileysEvents.CONNECTION_UPDATE}...`);
this.sock.ev.on(BaileysEvents.CONNECTION_UPDATE, async (update) => {
const { connection, lastDisconnect, qr } = update;
if (connection === 'connecting') {
if (connection === 'open') {
this.qr.save('');
this.status = WAHASessionStatus.WORKING;
this.resubscribeToKnownPresences();
@@ -203,10 +224,11 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
shouldReconnect,
);
this.qr.save('');
this.status = WAHASessionStatus.FAILED;
// reconnect if not logged out
if (shouldReconnect) {
setTimeout(() => this.buildClient(), 2 * SECOND);
} else {
this.status = WAHASessionStatus.FAILED;
}
}
@@ -214,29 +236,17 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
if (qr) {
this.status = WAHASessionStatus.SCAN_QR_CODE;
QRCode.toDataURL(qr).then((url) => {
this.qr.save(url);
this.qr.save(url, qr);
});
}
});
}
protected debugLogEnginesEvents(sock) {
if (!process.env.DEBUG) {
return;
}
sock.ev.process((events) => {
this.log.debug('Engine events');
this.log.debug('=============');
console.log(JSON.stringify(events));
this.log.debug('=============');
});
}
stop() {
this.sock.ev.removeAllListeners();
this.sock.ws.removeAllListeners();
this.sock.ws.close();
async stop() {
this.sock?.ev?.removeAllListeners();
this.sock?.ws?.removeAllListeners();
this.sock?.ws?.close();
this.status = WAHASessionStatus.STOPPED;
return;
}
@@ -260,13 +270,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
/**
* Auth methods
*/
public async getQR(): Promise<Buffer> {
return Promise.resolve(this.qr.get());
public getQR(): QR {
return this.qr;
}
public async requestCode(
phoneNumber: string,
method: string,
params?: any,
): Promise<PairingCodeResponse> {
if (method) {
const err = `NOWEB engine doesn't support any 'method', remove it and try again`;
@@ -283,16 +294,16 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
throw new UnprocessableEntityException(err);
}
this.log.debug('Requesting pairing code...');
this.log.log(`Requesting pairing code for '${phoneNumber}'...`);
const code: string = await this.sock.requestPairingCode(phoneNumber);
// show it as ABCD-ABCD
const parts = splitAt(code, 4);
const codeRepr = parts.join('-');
this.log.debug(`Your code: ${codeRepr}`);
this.log.log(`Your code: ${codeRepr}`);
return { code: codeRepr };
}
async getScreenshot(): Promise<Buffer | string> {
async getScreenshot(): Promise<Buffer> {
if (this.status === WAHASessionStatus.STARTING) {
throw new UnprocessableEntityException(
`The session is starting, please try again after few seconds`,
@@ -316,10 +327,13 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
): Promise<WANumberExistResult> {
const phone = request.phone.split('@')[0];
const [result] = await this.sock.onWhatsApp(phone);
if (!result) {
if (!result || !result.exists) {
return { numberExists: false };
}
return { numberExists: result.exists };
return {
numberExists: true,
chatId: toCusFormat(result.jid),
};
}
sendText(request: MessageTextRequest) {
@@ -346,10 +360,6 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
return this.toWAMessage(result);
}
sendContactVCard(request: MessageContactVcardRequest) {
throw new NotImplementedByEngineError();
}
async reply(request: MessageReplyRequest) {
const { id } = parseMessageId(request.reply_to);
const quotedMessage = await this.store.loadMessage(
@@ -568,55 +578,61 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
* END - Methods for API
*/
subscribe(event, handler) {
if (event === WAHAEvents.MESSAGE) {
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) => {
this.handleIncomingMessages(messages, handler, false);
});
} else if (event === WAHAEvents.MESSAGE_ANY) {
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) =>
this.handleIncomingMessages(messages, handler, true),
);
} else if (event === WAHAEvents.MESSAGE_ACK) {
// Direct message ack
this.sock.ev.on(BaileysEvents.MESSAGES_UPDATE, (events) => {
events
.filter(isMine)
.filter(isAckUpdateMessageEvent)
.map(this.convertMessageUpdateToMessageAck)
.forEach(handler);
});
// Group message ack
this.sock.ev.on(BaileysEvents.MESSAGE_RECEIPT_UPDATE, (events) => {
events
.filter(isMine)
.map(this.convertMessageReceiptUpdateToMessageAck)
.forEach(handler);
});
} else if (event === WAHAEvents.STATE_CHANGE) {
this.sock.ev.on(BaileysEvents.CONNECTION_UPDATE, handler);
} else if (event === WAHAEvents.GROUP_JOIN) {
this.sock.ev.on(BaileysEvents.GROUPS_UPSERT, handler);
} else if (event === WAHAEvents.PRESENCE_UPDATE) {
this.sock.ev.on(BaileysEvents.PRESENCE_UPDATE, (data) =>
handler(this.toWahaPresences(data.id, data.presences)),
);
} else if (event === WAHAEvents.POLL_VOTE) {
this.sock.ev.on(BaileysEvents.MESSAGES_UPDATE, (events) => {
events.forEach((event) =>
this.handleMessagesUpdatePollVote(event, handler),
subscribeEngineEvent(event, handler): boolean {
switch (event) {
case WAHAEvents.MESSAGE:
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) => {
this.handleIncomingMessages(messages, handler, false);
});
return true;
case WAHAEvents.MESSAGE_ANY:
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) =>
this.handleIncomingMessages(messages, handler, true),
);
});
} else if (event === WAHAEvents.POLL_VOTE_FAILED) {
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) => {
messages.forEach((message) =>
this.handleMessageUpsertPollVoteFailed(message, handler),
return true;
case WAHAEvents.MESSAGE_ACK: // Direct message ack
this.sock.ev.on(BaileysEvents.MESSAGES_UPDATE, (events) => {
events
.filter(isMine)
.filter(isAckUpdateMessageEvent)
.map(this.convertMessageUpdateToMessageAck)
.forEach(handler);
});
// Group message ack
this.sock.ev.on(BaileysEvents.MESSAGE_RECEIPT_UPDATE, (events) => {
events
.filter(isMine)
.map(this.convertMessageReceiptUpdateToMessageAck)
.forEach(handler);
});
return true;
case WAHAEvents.STATE_CHANGE:
this.sock.ev.on(BaileysEvents.CONNECTION_UPDATE, handler);
return true;
case WAHAEvents.GROUP_JOIN:
this.sock.ev.on(BaileysEvents.GROUPS_UPSERT, handler);
return true;
case WAHAEvents.PRESENCE_UPDATE:
this.sock.ev.on(BaileysEvents.PRESENCE_UPDATE, (data) =>
handler(this.toWahaPresences(data.id, data.presences)),
);
});
} else {
throw new NotImplementedByEngineError(
`Engine does not support webhook event: ${event}`,
);
return true;
case WAHAEvents.POLL_VOTE:
this.sock.ev.on(BaileysEvents.MESSAGES_UPDATE, (events) => {
events.forEach((event) =>
this.handleMessagesUpdatePollVote(event, handler),
);
});
return true;
case WAHAEvents.POLL_VOTE_FAILED:
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) => {
messages.forEach((message) =>
this.handleMessageUpsertPollVoteFailed(message, handler),
);
});
return true;
default:
return false;
}
}
@@ -662,10 +678,10 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
body: body,
to: toCusFormat(fromToParticipant.to),
participant: toCusFormat(fromToParticipant.participant),
// @ts-ignore
hasMedia: Boolean(message.mediaUrl),
// @ts-ignore
mediaUrl: message.mediaUrl,
// Media
hasMedia: Boolean(message.media),
media: message.media,
mediaUrl: message.media?.url,
// @ts-ignore
ack: message.ack,
// @ts-ignore
@@ -758,6 +774,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
handler(payload);
}
}
protected async handleMessageUpsertPollVoteFailed(message, handler) {
const pollUpdateMessage = message.message?.pollUpdateMessage;
if (!pollUpdateMessage) {
@@ -813,14 +830,39 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
return { id: chatId, presences: presences };
}
protected async downloadMedia(message: Message) {
if (!message.hasMedia) {
return message;
}
protected downloadMedia(message) {
const processor = new EngineMediaProcessor(this);
return this.mediaManager.processMedia(processor, message);
}
}
// @ts-ignore
message.mediaUrl = await this.storage.save(message.key.id, '', undefined);
return message;
export class EngineMediaProcessor implements IEngineMediaProcessor<any> {
constructor(public session: WhatsappSessionNoWebCore) {}
hasMedia(message: any): boolean {
const messageType = Object.keys(message.message)[0];
const hasMedia =
messageType === 'imageMessage' ||
messageType == 'audioMessage' ||
messageType == 'documentMessage' ||
messageType == 'videoMessage';
return hasMedia;
}
getMessageId(message: any): string {
return '';
}
getMimetype(message: any): string {
return '';
}
getMediaBuffer(message: any): Promise<Buffer | null> {
return Promise.resolve(undefined);
}
getFilename(message: any): string | null {
return message.message?.documentMessage?.fileName || null;
}
}
@@ -1,4 +1,5 @@
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import * as Buffer from 'buffer';
import { create, CreateConfig, Message, Whatsapp } from 'venom-bot';
import {
@@ -14,16 +15,17 @@ import {
MessageReplyRequest,
MessageTextRequest,
WANumberExistResult,
} from '../structures/chatting.dto';
} from '../../../structures/chatting.dto';
import {
WAHAEngine,
WAHAEvents,
WAHASessionStatus,
} from '../structures/enums.dto';
import { WAMessage } from '../structures/responses.dto';
import { WAHAInternalEvent, WhatsappSession } from './abc/session.abc';
import { NotImplementedByEngineError } from './exceptions';
import { QR } from './QR';
} from '../../../structures/enums.dto';
import { WAMessage } from '../../../structures/responses.dto';
import { IEngineMediaProcessor } from '../../abc/media.abc';
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
import { NotImplementedByEngineError } from '../../exceptions';
import { QR } from '../../QR';
export class WhatsappSessionVenomCore extends WhatsappSession {
engine = WAHAEngine.VENOM;
@@ -65,7 +67,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
protected getCatchQR() {
return (base64Qrimg, asciiQR, attempts, urlCode) => {
this.qr.save(base64Qrimg);
this.qr.save(base64Qrimg, urlCode);
this.status = WAHASessionStatus.SCAN_QR_CODE;
this.log.debug('Number of attempts to read the qrcode: ', attempts);
this.log.log('Terminal qrcode:');
@@ -75,6 +77,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
}
async start() {
this.status = WAHASessionStatus.STARTING;
try {
this.whatsapp = await this.buildClient();
} catch (error) {
@@ -85,40 +88,53 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
}
this.status = WAHASessionStatus.WORKING;
this.events.emit(WAHAInternalEvent.engine_start);
this.events.emit(WAHAInternalEvent.ENGINE_START);
return this;
}
stop() {
return this.whatsapp.close();
async stop() {
await this.whatsapp.close();
this.status = WAHASessionStatus.STOPPED;
}
subscribe(event: WAHAEvents | string, handler: (message) => void) {
if (event === WAHAEvents.MESSAGE) {
return this.whatsapp.onMessage((message: Message) =>
this.processIncomingMessage(message).then(handler),
);
} else if (event === WAHAEvents.MESSAGE_ANY) {
return this.whatsapp.onAnyMessage((message: Message) =>
this.processIncomingMessage(message).then(handler),
);
} else if (event === WAHAEvents.STATE_CHANGE) {
return this.whatsapp.onStateChange(handler);
} else if (event === WAHAEvents.MESSAGE_ACK) {
return this.whatsapp.onAck(handler);
} else if (event === WAHAEvents.GROUP_JOIN) {
return this.whatsapp.onAddedToGroup(handler);
} else {
throw new NotImplementedByEngineError(
`Engine does not support webhook event: ${event}`,
);
subscribeEngineEvent(event: WAHAEvents | string, handler: (message) => void) {
switch (event) {
case WAHAEvents.MESSAGE:
this.whatsapp.onMessage((message: Message) =>
this.processIncomingMessage(message).then(handler),
);
return true;
case WAHAEvents.MESSAGE_ANY:
this.whatsapp.onAnyMessage((message: Message) =>
this.processIncomingMessage(message).then(handler),
);
return true;
case WAHAEvents.STATE_CHANGE:
this.whatsapp.onStateChange(handler);
return true;
case WAHAEvents.MESSAGE_ACK:
this.whatsapp.onAck(handler);
return true;
case WAHAEvents.GROUP_JOIN:
this.whatsapp.onAddedToGroup(handler);
return true;
default:
return false;
}
}
/**
* START - Methods for API
*/
getScreenshot(): Promise<Buffer | string> {
/**
* Auth methods
*/
public getQR(): QR {
return this.qr;
}
getScreenshot(): Promise<Buffer> {
if (this.status === WAHASessionStatus.STARTING) {
throw new UnprocessableEntityException(
`The session is starting, please try again after few seconds`,
@@ -240,17 +256,13 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
* END - Methods for API
*/
protected async downloadAndDecryptMedia(message: Message) {
if (!message.isMMS || !message.isMedia) {
return message;
}
// @ts-ignore
message.mediaUrl = await this.storage.save(message.id, '', undefined);
return message;
protected downloadMedia(message: Message) {
const processor = new EngineMediaProcessor(this);
return this.mediaManager.processMedia(processor, message);
}
private processIncomingMessage(message: Message) {
return this.downloadAndDecryptMedia(message).then(this.toWAMessage);
return this.downloadMedia(message).then(this.toWAMessage);
}
protected toWAMessage(message: Message): Promise<WAMessage> {
@@ -262,10 +274,13 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
fromMe: message.fromMe,
to: message.to,
body: message.body,
// Media
// @ts-ignore
hasMedia: Boolean(message.mediaUrl),
hasMedia: Boolean(message.media),
// @ts-ignore
mediaUrl: message.mediaUrl,
media: message.media,
// @ts-ignore
mediaUrl: message.media?.url,
// @ts-ignore
ack: message.ack,
location: undefined,
@@ -274,3 +289,29 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
});
}
}
export class EngineMediaProcessor implements IEngineMediaProcessor<Message> {
constructor(public session: WhatsappSessionVenomCore) {}
hasMedia(message: any): boolean {
if (!message.isMMS || !message.isMedia) {
return message;
}
}
getMessageId(message: any): string {
return '';
}
getMimetype(message: any): string {
return '';
}
getMediaBuffer(message: any): Promise<Buffer | null> {
return Promise.resolve(undefined);
}
getFilename(message: Message): string | null {
return null;
}
}
@@ -15,10 +15,8 @@ import {
ChatRequest,
CheckNumberStatusQuery,
GetMessageQuery,
MessageContactVcardRequest,
MessageFileRequest,
MessageImageRequest,
MessageLinkPreviewRequest,
MessageLocationRequest,
MessageReactionRequest,
MessageReplyRequest,
@@ -26,8 +24,8 @@ import {
MessageVoiceRequest,
SendSeenRequest,
WANumberExistResult,
} from '../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
} from '../../../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
import {
ACK_UNKNOWN,
WAHAEngine,
@@ -35,20 +33,22 @@ import {
WAHAPresenceStatus,
WAHASessionStatus,
WAMessageAck,
} from '../structures/enums.dto';
} from '../../../structures/enums.dto';
import {
CreateGroupRequest,
ParticipantsRequest,
} from '../structures/groups.dto';
import { WAMessage } from '../structures/responses.dto';
import { WAHAInternalEvent, WhatsappSession } from './abc/session.abc';
SettingsSecurityChangeInfo,
} from '../../../structures/groups.dto';
import { WAMessage } from '../../../structures/responses.dto';
import { MeInfo } from '../../../structures/sessions.dto';
import { WAMessageRevokedBody } from '../../../structures/webhooks.dto';
import { IEngineMediaProcessor } from '../../abc/media.abc';
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
import {
AvailableInPlusVersion,
NotImplementedByEngineError,
} from './exceptions';
import { QR } from './QR';
import { MeInfo } from '../structures/sessions.dto';
import { jidNormalizedUser } from '@adiwajshing/baileys';
} from '../../exceptions';
import { QR } from '../../QR';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const QRCode = require('qrcode');
@@ -67,7 +67,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
this.qr = new QR();
}
protected buildClient() {
protected async buildClient() {
const clientOptions: ClientOptions = {
puppeteer: {
headless: true,
@@ -97,19 +97,38 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
}
async start() {
this.whatsapp = this.buildClient();
this.whatsapp.initialize().catch((error) => {
this.status = WAHASessionStatus.FAILED;
this.log.error(error);
return;
});
this.status = WAHASessionStatus.STARTING;
this.whatsapp = await this.buildClient();
this.whatsapp
.initialize()
.then(() => {
// Listen for browser disconnected event
this.whatsapp.pupBrowser.on('disconnected', () => {
this.status = WAHASessionStatus.FAILED;
this.log.error('The browser has been disconnected');
});
// Listen for page close event
this.whatsapp.pupPage.on('close', () => {
this.status = WAHASessionStatus.FAILED;
this.log.error('The WhatsApp Web page has been closed');
});
})
.catch((error) => {
this.status = WAHASessionStatus.FAILED;
this.log.error(error);
return;
});
if (this.isDebugEnabled()) {
this.listenEngineEventsInDebugMode();
}
this.listenConnectionEvents();
this.events.emit(WAHAInternalEvent.engine_start);
this.events.emit(WAHAInternalEvent.ENGINE_START);
return this;
}
stop() {
return this.whatsapp.destroy();
async stop() {
await this.whatsapp.destroy();
this.status = WAHASessionStatus.STOPPED;
}
async getSessionMeInfo(): Promise<MeInfo | null> {
@@ -125,23 +144,40 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return meInfo;
}
protected listenEngineEventsInDebugMode() {
// Iterate over Events enum and log with debug level all incoming events
// This is useful for debugging
for (const key in Events) {
const event = Events[key];
this.whatsapp.on(event, (...data: any[]) => {
this.log.debug(`Received WEBJS event`, { event: event, data: data });
});
}
}
protected listenConnectionEvents() {
this.whatsapp.on(Events.QR_RECEIVED, (qr) => {
this.log.debug('QR received');
// Convert to image and save
QRCode.toDataURL(qr).then((url) => {
this.qr.save(url);
this.qr.save(url, qr);
});
// Print in terminal
qrcode.generate(qr, { small: true });
this.status = WAHASessionStatus.SCAN_QR_CODE;
});
this.whatsapp.on(Events.AUTHENTICATED, () => {
this.whatsapp.on(Events.READY, () => {
this.status = WAHASessionStatus.WORKING;
this.qr.save('');
this.log.log(`Session '${this.name}' has been authenticated!`);
});
this.whatsapp.on(Events.DISCONNECTED, () => {
this.status = WAHASessionStatus.FAILED;
this.qr.save('');
this.log.log(`Session '${this.name}' has been disconnected!`);
});
}
/**
@@ -151,32 +187,42 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
/**
* Auth methods
*/
public async getQR(): Promise<Buffer> {
return Promise.resolve(this.qr.get());
public getQR(): QR {
return this.qr;
}
async getScreenshot(): Promise<Buffer | string> {
async getScreenshot(): Promise<Buffer> {
if (this.status === WAHASessionStatus.FAILED) {
throw new UnprocessableEntityException(
`The session under FAILED status. Please try to restart it.`,
);
}
return await this.whatsapp.pupPage.screenshot();
const screenshot = await this.whatsapp.pupPage.screenshot({
encoding: 'binary',
});
return screenshot as Buffer;
}
async checkNumberStatus(
request: CheckNumberStatusQuery,
): Promise<WANumberExistResult> {
const exist = await this.whatsapp.isRegisteredUser(
this.ensureSuffix(request.phone),
);
return { numberExists: exist };
const phone = request.phone.split('@')[0];
const result = await this.whatsapp.getNumberId(phone);
if (!result) {
return {
numberExists: false,
};
}
return {
numberExists: true,
chatId: result._serialized,
};
}
sendText(request: MessageTextRequest) {
const options = {
// It's fine to sent just ids instead of Contact object
mentions: request.mentions as unknown as Contact[],
mentions: request.mentions as unknown as string[],
};
return this.whatsapp.sendMessage(
this.ensureSuffix(request.chatId),
@@ -185,15 +231,11 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
);
}
sendContactVCard(request: MessageContactVcardRequest) {
throw new NotImplementedByEngineError();
}
reply(request: MessageReplyRequest) {
const options = {
quotedMessageId: request.reply_to,
// It's fine to sent just ids instead of Contact object
mentions: request.mentions as unknown as Contact[],
mentions: request.mentions as unknown as string[],
};
return this.whatsapp.sendMessage(request.chatId, request.text, options);
}
@@ -211,18 +253,12 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
}
async sendLocation(request: MessageLocationRequest) {
const location = new Location(
request.latitude,
request.longitude,
request.title,
);
const location = new Location(request.latitude, request.longitude, {
name: request.title,
});
return this.whatsapp.sendMessage(request.chatId, location);
}
sendLinkPreview(request: MessageLinkPreviewRequest) {
throw new NotImplementedByEngineError();
}
async sendSeen(request: SendSeenRequest) {
const chat: Chat = await this.whatsapp.getChatById(request.chatId);
await chat.sendSeen();
@@ -338,6 +374,14 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return this.whatsapp.createGroup(request.name, participantIds);
}
public async getInfoAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
return {
// @ts-ignore
adminsOnly: groupChat.groupMetadata.restrict,
};
}
public async setInfoAdminsOnly(id, value) {
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
return groupChat.setInfoAdminsOnly(value);
@@ -453,30 +497,51 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
* END - Methods for API
*/
subscribe(event, handler) {
if (event === WAHAEvents.MESSAGE) {
this.whatsapp.on(Events.MESSAGE_RECEIVED, (message) =>
this.processIncomingMessage(message).then(handler),
);
} else if (event === WAHAEvents.MESSAGE_ANY) {
this.whatsapp.on(Events.MESSAGE_CREATE, (message) =>
this.processIncomingMessage(message).then(handler),
);
} else if (event === WAHAEvents.STATE_CHANGE) {
this.whatsapp.on(Events.STATE_CHANGED, handler);
} else if (event === WAHAEvents.MESSAGE_ACK) {
// We do not download media here
this.whatsapp.on(Events.MESSAGE_ACK, (message) =>
this.toWAMessage(message).then(handler),
);
} else if (event === WAHAEvents.GROUP_JOIN) {
this.whatsapp.on(Events.GROUP_JOIN, handler);
} else if (event === WAHAEvents.GROUP_LEAVE) {
this.whatsapp.on(Events.GROUP_LEAVE, handler);
} else {
throw new NotImplementedByEngineError(
`Engine does not support webhook event: ${event}`,
);
subscribeEngineEvent(event, handler): boolean {
switch (event) {
case WAHAEvents.MESSAGE:
this.whatsapp.on(Events.MESSAGE_RECEIVED, (message) =>
this.processIncomingMessage(message).then(handler),
);
return true;
case WAHAEvents.MESSAGE_REVOKED:
this.whatsapp.on(
Events.MESSAGE_REVOKED_EVERYONE,
async (after, before) => {
const afterMessage = after ? await this.toWAMessage(after) : null;
const beforeMessage = before
? await this.toWAMessage(before)
: null;
const body: WAMessageRevokedBody = {
after: afterMessage,
before: beforeMessage,
};
handler(body);
},
);
return true;
case WAHAEvents.MESSAGE_ANY:
this.whatsapp.on(Events.MESSAGE_CREATE, (message) =>
this.processIncomingMessage(message).then(handler),
);
return true;
case WAHAEvents.STATE_CHANGE:
this.whatsapp.on(Events.STATE_CHANGED, handler);
return true;
case WAHAEvents.MESSAGE_ACK:
// We do not download media here
this.whatsapp.on(Events.MESSAGE_ACK, (message) =>
this.toWAMessage(message).then(handler),
);
return true;
case WAHAEvents.GROUP_JOIN:
this.whatsapp.on(Events.GROUP_JOIN, handler);
return true;
case WAHAEvents.GROUP_LEAVE:
this.whatsapp.on(Events.GROUP_LEAVE, handler);
return true;
default:
return false;
}
}
@@ -501,10 +566,14 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
fromMe: message.fromMe,
to: message.to,
body: message.body,
// Media
// @ts-ignore
hasMedia: Boolean(message.mediaUrl),
hasMedia: Boolean(message.media),
// @ts-ignore
media: message.media,
// @ts-ignore
mediaUrl: message.media?.url,
// @ts-ignore
mediaUrl: message.mediaUrl,
ack: message.ack,
ackName: WAMessageAck[message.ack] || ACK_UNKNOWN,
location: message.location,
@@ -519,17 +588,35 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return contact;
}
protected async downloadMedia(message: Message) {
protected downloadMedia(message: Message) {
const processor = new EngineMediaProcessor();
return this.mediaManager.processMedia(processor, message);
}
}
export class EngineMediaProcessor implements IEngineMediaProcessor<Message> {
hasMedia(message: Message): boolean {
if (!message.hasMedia) {
return message;
return false;
}
// Can't get media for revoked messages
return message.type !== 'revoked';
}
getMessageId(message: Message): string {
return '';
}
getMimetype(message: Message): string {
return '';
}
getMediaBuffer(message: Message): Promise<Buffer | null> {
return Promise.resolve(undefined);
}
getFilename(message: Message): string | null {
// @ts-ignore
message.mediaUrl = await this.storage.save(
message.id._serialized,
'',
undefined,
);
return message;
return message.rawData?.filename || null;
}
}
@@ -0,0 +1,12 @@
import { Injectable } from '@nestjs/common';
import { HealthCheckResult } from '@nestjs/terminus';
import { WAHAHealthCheckService } from '../abc/WAHAHealthCheckService';
import { AvailableInPlusVersion } from '../exceptions';
@Injectable()
export class WAHAHealthCheckServiceCore extends WAHAHealthCheckService {
check(): Promise<HealthCheckResult> {
throw new AvailableInPlusVersion();
}
}
+4 -4
View File
@@ -9,7 +9,7 @@ import { WhatsappSession } from './abc/session.abc';
export function getProxyConfig(
config: WhatsappConfigService,
sessions: Record<string, WhatsappSession>,
sessionName?: string,
sessionName: string,
): ProxyConfig | undefined {
// Single proxy server configuration
if (typeof config.proxyServer === 'string') {
@@ -23,7 +23,7 @@ export function getProxyConfig(
// Multiple proxy server configuration
if (Array.isArray(config.proxyServer)) {
const prefix = config.proxyServerIndexPrefix;
let indexToUse: number = undefined;
let indexToUse: number | undefined = undefined;
if (prefix && sessionName.includes(prefix)) {
// match numbers at the end of the string
const matches = sessionName.match(/\d+$/);
@@ -66,8 +66,8 @@ function getAuthenticatedUrl(
export function createAgentProxy(proxyConfig: ProxyConfig): Agent | undefined {
const url = getAuthenticatedUrl(
proxyConfig.server,
proxyConfig.username,
proxyConfig.password,
proxyConfig.username || '',
proxyConfig.password || '',
);
return new HttpsProxyAgent(url);
}
+38 -32
View File
@@ -6,6 +6,7 @@ import {
} from '@nestjs/common';
import { WhatsappConfigService } from '../config.service';
import { getLogLevels } from '../helpers';
import { WAHAEngine, WAHASessionStatus } from '../structures/enums.dto';
import {
ProxyConfig,
@@ -17,17 +18,16 @@ import {
} from '../structures/sessions.dto';
import { WebhookConfig } from '../structures/webhooks.config.dto';
import { SessionManager } from './abc/manager.abc';
import {
SessionParams,
WAHAInternalEvent,
WhatsappSession,
} from './abc/session.abc';
import { SessionParams, WhatsappSession } from './abc/session.abc';
import { WhatsappSessionNoWebCore } from './engines/noweb/session.noweb.core';
import { WhatsappSessionVenomCore } from './engines/venom/session.venom.core';
import { WhatsappSessionWebJSCore } from './engines/webjs/session.webjs.core';
import { DOCS_URL } from './exceptions';
import { getProxyConfig } from './helpers.proxy';
import { WhatsappSessionNoWebCore } from './session.noweb.core';
import { WhatsappSessionVenomCore } from './session.venom.core';
import { WhatsappSessionWebJSCore } from './session.webjs.core';
import { MediaStorageCore, SessionStorageCore } from './storage.core';
import { CoreMediaManager, MediaStorageCore } from './media.core';
import { LocalSessionAuthRepository } from './storage/LocalSessionAuthRepository';
import { LocalSessionConfigRepository } from './storage/LocalSessionConfigRepository';
import { LocalStoreCore } from './storage/LocalStoreCore';
import { WebhookConductorCore } from './webhooks.core';
export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
@@ -38,13 +38,15 @@ export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
}
}
export function buildLogger(name) {
return new ConsoleLogger(name, { logLevels: getLogLevels() });
}
@Injectable()
export class SessionManagerCore extends SessionManager {
private session: WhatsappSession;
private session?: WhatsappSession;
DEFAULT = 'default';
// @ts-ignore
protected MediaStorageClass = MediaStorageCore;
// @ts-ignore
protected WebhookConductorClass = WebhookConductorCore;
protected readonly EngineClass: typeof WhatsappSession;
@@ -59,8 +61,9 @@ export class SessionManagerCore extends SessionManager {
this.session = undefined;
const engineName = this.config.getDefaultEngineName();
this.EngineClass = this.getEngine(engineName);
this.sessionStorage = new SessionStorageCore(engineName.toLowerCase());
this.store = new LocalStoreCore(engineName.toLowerCase());
this.sessionAuthRepository = new LocalSessionAuthRepository(this.store);
this.sessionConfigRepository = new LocalSessionConfigRepository(this.store);
this.startPredefinedSessions();
}
@@ -104,29 +107,30 @@ export class SessionManagerCore extends SessionManager {
const name = request.name;
this.log.log(`'${name}' - starting session...`);
const log = new ConsoleLogger(`WhatsappSession - ${name}`);
const storage = new this.MediaStorageClass();
const webhookLog = new ConsoleLogger(`Webhook - ${name}`);
const log = buildLogger(`WhatsappSession - ${name}`);
const mediaManager = new CoreMediaManager(
new MediaStorageCore(),
this.config.mimetypes,
);
const webhookLog = buildLogger(`Webhook - ${name}`);
const webhook = new this.WebhookConductorClass(webhookLog);
const proxyConfig = this.getProxyConfig(request);
const sessionConfig: SessionParams = {
name,
storage,
mediaManager,
log,
sessionStorage: this.sessionStorage,
sessionStore: this.store,
proxyConfig: proxyConfig,
sessionConfig: request.config,
};
await this.sessionStorage.init(name);
await this.sessionAuthRepository.init(name);
// @ts-ignore
const session = new this.EngineClass(sessionConfig);
this.session = session;
// configure webhooks
const webhooks = this.getWebhooks(request);
session.events.on(WAHAInternalEvent.engine_start, () =>
webhook.configure(session, webhooks),
);
webhook.configure(session, webhooks);
// start session
await session.start();
@@ -146,7 +150,9 @@ export class SessionManagerCore extends SessionManager {
webhooks = webhooks.concat(request.config.webhooks);
}
const globalWebhookConfig = this.config.getWebhookConfig();
webhooks.push(globalWebhookConfig);
if (globalWebhookConfig) {
webhooks.push(globalWebhookConfig);
}
return webhooks;
}
@@ -159,6 +165,9 @@ export class SessionManagerCore extends SessionManager {
if (request.config?.proxy) {
return request.config.proxy;
}
if (!this.session) {
return undefined;
}
const sessions = { [request.name]: this.session };
return getProxyConfig(this.config, sessions, request.name);
}
@@ -175,19 +184,16 @@ export class SessionManagerCore extends SessionManager {
}
async logout(request: SessionLogoutRequest) {
await this.sessionStorage.clean(request.name);
await this.sessionAuthRepository.clean(request.name);
}
getSession(name: string, error = true): WhatsappSession {
getSession(name: string): WhatsappSession {
this.onlyDefault(name);
const session = this.session;
if (!session) {
if (error) {
throw new NotFoundException(
`We didn't find a session with name '${name}'. Please start it first by using POST /sessions/start request`,
);
}
return;
throw new NotFoundException(
`We didn't find a session with name '${name}'. Please start it first by using POST /sessions/start request`,
);
}
return session;
}
+47
View File
@@ -0,0 +1,47 @@
import { WAMedia } from '../structures/responses.dto';
import {
IEngineMediaProcessor,
MediaManager,
MediaStorage,
} from './abc/media.abc';
import { DOCS_URL } from './exceptions';
export class MediaStorageCore implements MediaStorage {
async save(
messageId: string,
mimetype: string,
buffer: Buffer,
): Promise<string> {
return Promise.resolve(
`Media attachment's available only in WAHA Plus version. ${DOCS_URL}`,
);
}
}
export class CoreMediaManager implements MediaManager {
constructor(
private storage: MediaStorage,
private mimetypes: string[],
) {}
async processMedia<Message>(
processor: IEngineMediaProcessor<Message>,
message: Message,
): Promise<Message> {
if (!processor.hasMedia(message)) {
return message;
}
const mimetype = '';
const filename = processor.getFilename(message);
const url = await this.storage.save('', mimetype, Buffer.from(''));
const media: WAMedia = {
mimetype: mimetype,
filename: filename,
url: url,
};
// @ts-ignore
message.media = media;
return message;
}
}
-111
View File
@@ -1,111 +0,0 @@
import * as crypto from 'crypto';
import * as fs from 'fs/promises';
import * as os from 'os';
import * as path from 'path';
import { SessionConfig } from '../structures/sessions.dto';
import {
LocalSessionStorage,
MediaStorage,
SessionConfigRepository,
} from './abc/storage.abc';
import { DOCS_URL } from './exceptions';
export class MediaStorageCore implements MediaStorage {
async save(
messageId: string,
mimetype: string,
buffer: Buffer,
): Promise<string> {
return Promise.resolve(
`Media attachment's available only in WAHA Plus version. ${DOCS_URL}`,
);
}
}
class LocalSessionConfigRepository extends SessionConfigRepository {
FILENAME = '.waha.session.config.json';
constructor(private storage: LocalSessionStorage) {
super();
}
async get(sessionName: string): Promise<SessionConfig> {
const filepath = this.getFilePath(sessionName);
// Check file exists
try {
await fs.access(filepath, fs.constants.F_OK);
} catch (error) {
return undefined;
}
// Try to load config
let content;
try {
content = await fs.readFile(filepath, 'utf-8');
} catch (error) {
return undefined;
}
return JSON.parse(content);
}
async save(sessionName: string, config: SessionConfig) {
// Create folder if not exist
const folder = this.storage.getFolderPath(sessionName);
await fs.mkdir(folder, { recursive: true });
// Save config
const filepath = this.getFilePath(sessionName);
const content = JSON.stringify(config || null);
await fs.writeFile(filepath, content);
}
private getFilePath(sessionName): string {
const folder = this.storage.getFolderPath(sessionName);
return path.join(folder, this.FILENAME);
}
}
export class SessionStorageCore extends LocalSessionStorage {
public sessionsFolder: string;
constructor(engine: string) {
super(engine);
this.sessionsFolder = path.join(os.tmpdir(), 'waha-sessions');
}
get engineFolder() {
return path.join(this.sessionsFolder, this.engine);
}
async init(sessionName?: string) {
const folder = sessionName
? this.getFolderPath(sessionName)
: this.engineFolder;
await fs.mkdir(folder, { recursive: true });
}
getFolderPath(name: string): string {
const suffix = crypto.createHash('md5').update(name).digest('hex');
return path.join(this.engineFolder, `${name}-${suffix}`);
}
async clean(sessionName: string) {
const folder = this.getFolderPath(sessionName);
await fs.rm(folder, { recursive: true });
}
async getAll(): Promise<string[]> {
await this.init();
const content = await fs.readdir(this.engineFolder, {
withFileTypes: true,
});
return content
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
}
get configRepository(): LocalSessionConfigRepository {
return new LocalSessionConfigRepository(this);
}
}
@@ -0,0 +1,7 @@
export abstract class ISessionAuthRepository {
abstract init(sessionName?: string): Promise<void>;
abstract clean(sessionName: string): Promise<void>;
abstract getAll(): Promise<string[]>;
}
@@ -0,0 +1,12 @@
import { SessionConfig } from '../../structures/sessions.dto';
export abstract class ISessionConfigRepository {
abstract save(
sessionName: string,
config: SessionConfig | null,
): Promise<void>;
abstract get(sessionName: string): Promise<SessionConfig | null>;
abstract delete(sessionName: string): Promise<void>;
}
@@ -0,0 +1,32 @@
import * as fs from 'fs/promises';
import { ISessionAuthRepository } from './ISessionAuthRepository';
import { LocalStore } from './LocalStore';
export class LocalSessionAuthRepository extends ISessionAuthRepository {
private store: LocalStore;
constructor(store: LocalStore) {
super();
this.store = store;
}
async init(sessionName?: string) {
await this.store.init(sessionName);
}
async clean(sessionName: string) {
const folder = this.store.getSessionDirectory(sessionName);
await fs.rm(folder, { recursive: true });
}
async getAll(): Promise<string[]> {
await this.init();
const content = await fs.readdir(this.store.getEngineDirectory(), {
withFileTypes: true,
});
return content
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
}
}
@@ -0,0 +1,66 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import { SessionConfig } from '../../structures/sessions.dto';
import { ISessionConfigRepository } from './ISessionConfigRepository';
import { LocalStore } from './LocalStore';
export class LocalSessionConfigRepository extends ISessionConfigRepository {
FILENAME = '.waha.session.config.json';
private store: LocalStore;
constructor(store: LocalStore) {
super();
this.store = store;
}
private async fileExists(filepath: string) {
try {
await fs.access(filepath, fs.constants.F_OK);
} catch (error) {
return false;
}
return true;
}
async get(sessionName: string): Promise<SessionConfig | null> {
const filepath = this.getFilePath(sessionName);
// Check file exists
if (!(await this.fileExists(filepath))) {
return null;
}
// Try to load config
let content;
try {
content = await fs.readFile(filepath, 'utf-8');
} catch (error) {
return null;
}
return JSON.parse(content);
}
async save(sessionName: string, config: SessionConfig | null) {
// Create folder if not exist
const folder = this.store.getSessionDirectory(sessionName);
await fs.mkdir(folder, { recursive: true });
// Save config
const filepath = this.getFilePath(sessionName);
const content = JSON.stringify(config || null);
await fs.writeFile(filepath, content);
}
private getFilePath(sessionName): string {
const folder = this.store.getSessionDirectory(sessionName);
return path.join(folder, this.FILENAME);
}
async delete(sessionName: string): Promise<void> {
const filepath = this.getFilePath(sessionName);
if (!(await this.fileExists(filepath))) {
return;
}
await fs.unlink(filepath);
}
}
Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff. Show more