From 3c1eb2621bc7d228c4cce145aaa36d6fe0ea8dfe Mon Sep 17 00:00:00 2001 From: Exe16Kishan Date: Thu, 7 Aug 2025 13:17:12 +0530 Subject: [PATCH] fix : CSS --- assets/js/custom.js | 2 +- assets/js/docsearch.js | 32 +- assets/jsconfig.json | 16 +- assets/scss/common/_custom.scss | 228 +- assets/scss/common/_variables-custom.scss | 2 +- assets/scss/common/_variables-docsearch.scss | 122 +- .../scss/common/highlight-http-request.scss | 91 +- config/babel.config.js | 34 +- config/postcss.config.js | 133 +- content/_index.md | 17 +- content/blog/_index.md | 18 +- .../blog/apps-chatwoot-0-overview/index.md | 221 +- .../-ssh-port-forwarding.md | 23 +- content/blog/apps-chatwoot-1-install/index.md | 459 +- content/blog/apps-chatwoot-2-config/index.md | 308 +- content/blog/apps-chatwoot-3-https/index.md | 490 +- .../apps-chatwoot-4-how-it-works/index.md | 67 +- content/blog/crypto-how-to/index.md | 227 +- .../how-to-send-messages-to-channels/index.md | 358 +- content/blog/security-alert/index.md | 203 +- content/blog/waha-2024-10/index.md | 198 +- content/blog/waha-2024-11/index.md | 406 +- content/blog/waha-2024-12/index.md | 179 +- content/blog/waha-2024-4/index.md | 111 +- content/blog/waha-2024-5/index.md | 94 +- content/blog/waha-2024-6/index.md | 95 +- content/blog/waha-2024-7/index.md | 72 +- content/blog/waha-2024-8/index.md | 277 +- content/blog/waha-2024-9/index.md | 386 +- content/blog/waha-2025-1/index.md | 141 +- content/blog/waha-2025-2/index.md | 280 +- content/blog/waha-2025-3/index.md | 115 +- content/blog/waha-2025-4/index.md | 202 +- content/blog/waha-2025-5/index.md | 119 +- content/blog/waha-2025-6/index.md | 95 +- content/blog/waha-2025-7/index.md | 109 +- content/blog/waha-docker-image-name/index.md | 44 +- content/blog/waha-geonode/index.md | 297 +- content/blog/waha-https/index.md | 387 +- content/blog/waha-n8n/index.md | 304 +- content/blog/waha-ngrok/index.md | 140 +- content/blog/waha-scaling/index.md | 395 +- content/contact/_index.md | 21 +- content/contributors/_index.md | 19 +- content/contributors/devlikeapro/_index.md | 23 +- content/docs/_index.md | 17 +- content/docs/apps/_index.md | 27 +- content/docs/apps/about/-config.md | 56 +- content/docs/apps/about/-how-it-works.md | 149 +- .../docs/apps/about/apps-vs-integrations.md | 14 +- content/docs/apps/about/index.md | 79 +- .../docs/apps/chatwoot/-chatwoot-articles.md | 26 +- content/docs/apps/chatwoot/-disclaimer.md | 12 +- content/docs/apps/chatwoot/index.md | 98 +- content/docs/engines/_index.md | 31 +- content/docs/engines/gows.md | 59 +- content/docs/engines/noweb/index.md | 457 +- content/docs/engines/venom.md | 80 +- content/docs/engines/webjs.md | 82 +- content/docs/how-to/_index.md | 33 +- content/docs/how-to/calls/features-events.md | 20 +- content/docs/how-to/calls/index.md | 80 +- .../how-to/calls/webhooks-call-accepted.md | 29 +- .../how-to/calls/webhooks-call-received.md | 28 +- .../how-to/calls/webhooks-call-rejected.md | 28 +- content/docs/how-to/channels/features.md | 71 +- content/docs/how-to/channels/index.md | 1035 +- content/docs/how-to/chats/features-events.md | 16 +- content/docs/how-to/chats/features.md | 52 +- content/docs/how-to/chats/index.md | 784 +- .../how-to/chats/webhooks-chat-archive.md | 28 +- content/docs/how-to/config/index.md | 660 +- content/docs/how-to/contacts/features.md | 60 +- content/docs/how-to/contacts/index.md | 651 +- content/docs/how-to/dashboard/index.md | 181 +- content/docs/how-to/engines/index.md | 501 +- .../events-event-response-failed.md | 70 +- .../event-message/events-event-response.md | 99 +- .../how-to/event-message/features-events.md | 18 +- content/docs/how-to/event-message/features.md | 16 +- content/docs/how-to/event-message/index.md | 161 +- content/docs/how-to/events/features-events.md | 32 +- content/docs/how-to/events/index.md | 1643 +- .../docs/how-to/groups/events-group.join.md | 24 +- .../docs/how-to/groups/events-group.leave.md | 24 +- .../how-to/groups/events-group.v2.join.md | 78 +- .../how-to/groups/events-group.v2.leave.md | 39 +- .../groups/events-group.v2.participants.md | 77 +- .../how-to/groups/events-group.v2.update.md | 42 +- content/docs/how-to/groups/features-events.md | 26 +- content/docs/how-to/groups/features.md | 66 +- content/docs/how-to/groups/index.md | 918 +- content/docs/how-to/install/-the-hosting.md | 14 +- content/docs/how-to/install/download-image.md | 113 +- content/docs/how-to/install/index.md | 908 +- content/docs/how-to/labels/features-events.md | 22 +- content/docs/how-to/labels/features.md | 32 +- content/docs/how-to/labels/index.md | 533 +- content/docs/how-to/observability/index.md | 780 +- content/docs/how-to/polls/features-events.md | 18 +- content/docs/how-to/polls/features.md | 20 +- content/docs/how-to/polls/index.md | 458 +- .../docs/how-to/presence/features-events.md | 17 +- content/docs/how-to/presence/features.md | 26 +- content/docs/how-to/presence/index.md | 401 +- content/docs/how-to/profile/features.md | 26 +- content/docs/how-to/profile/index.md | 262 +- content/docs/how-to/proxy/index.md | 254 +- .../receive-messages/features-events.md | 28 +- content/docs/how-to/receive-messages/index.md | 698 +- .../security/how-to-generate-api-key.md | 32 +- content/docs/how-to/security/index.md | 286 +- .../set-x-api-key-http-header-code.md | 133 +- .../how-to/security/use-nginx-for-https.md | 16 +- .../send-messages/api-deleteMessage-code.md | 133 +- .../send-messages/api-editMessage-code.md | 175 +- .../send-messages/api-forwardMessage-code.md | 183 +- .../how-to/send-messages/api-reaction-code.md | 183 +- .../send-messages/api-sendButtons-code.md | 407 +- .../api-sendButtonsReply-code.md | 199 +- .../api-sendContactVcard-code.md | 239 +- .../send-messages/api-sendEvent-code.md | 223 +- .../how-to/send-messages/api-sendFile-code.md | 223 +- .../send-messages/api-sendImage-code.md | 223 +- .../api-sendLinkCustomPreview-code.md | 255 +- .../send-messages/api-sendLocation-code.md | 199 +- .../how-to/send-messages/api-sendPoll-code.md | 243 +- .../how-to/send-messages/api-sendSeen-code.md | 175 +- .../how-to/send-messages/api-sendText-code.md | 183 +- .../send-messages/api-sendVideo-code.md | 239 +- .../send-messages/api-sendVoice-code.md | 215 +- .../how-to/send-messages/api-star-code.md | 191 +- content/docs/how-to/send-messages/features.md | 68 +- content/docs/how-to/send-messages/index.md | 1949 +- .../send-messages/media-video-convert.md | 129 +- .../send-messages/media-video-format.md | 60 +- .../send-messages/media-voice-convert.md | 130 +- .../send-messages/media-voice-format.md | 45 +- .../how-to/sessions/api-session-create.md | 245 +- .../how-to/sessions/api-session-delete.md | 139 +- .../docs/how-to/sessions/api-session-get.md | 137 +- .../docs/how-to/sessions/api-session-list.md | 242 +- .../how-to/sessions/api-session-logout.md | 141 +- .../docs/how-to/sessions/api-session-me.md | 137 +- .../sessions/api-session-pairing-code.md | 167 +- .../docs/how-to/sessions/api-session-qr.md | 338 +- .../how-to/sessions/api-session-restart.md | 141 +- .../how-to/sessions/api-session-screenshot.md | 252 +- .../docs/how-to/sessions/api-session-start.md | 141 +- .../docs/how-to/sessions/api-session-stop.md | 141 +- .../how-to/sessions/api-session-update.md | 245 +- .../docs/how-to/sessions/features-events.md | 21 +- content/docs/how-to/sessions/features.md | 44 +- content/docs/how-to/sessions/index.md | 1637 +- content/docs/how-to/status/features.md | 30 +- content/docs/how-to/status/index.md | 812 +- .../docs/how-to/storages/docker-compose.md | 19 +- content/docs/how-to/storages/features.md | 28 +- content/docs/how-to/storages/index.md | 802 +- content/docs/how-to/swagger/index.md | 134 +- content/docs/how-to/waha-plus/index.md | 167 +- content/docs/integrations/_index.md | 29 +- content/docs/integrations/about/index.md | 38 +- content/docs/integrations/chatwoot/index.md | 72 +- .../integrations/live-helper-chat/index.md | 74 +- content/docs/integrations/n8n/index.md | 201 +- content/docs/integrations/typebot/index.md | 58 +- .../docs/integrations/uptime-kuma/index.md | 102 +- .../docs/integrations/waha+csharp/index.md | 95 +- content/docs/integrations/waha+go/index.md | 47 +- content/docs/integrations/waha+java/index.md | 47 +- content/docs/integrations/waha+js/index.md | 50 +- .../docs/integrations/waha+kotlin/index.md | 244 +- content/docs/integrations/waha+php/index.md | 47 +- .../docs/integrations/waha+python/index.md | 311 +- content/docs/overview/_index.md | 32 +- content/docs/overview/changelog.md | 2440 +- content/docs/overview/faq.md | 212 +- .../docs/overview/how-to-avoid-blocking.md | 182 +- content/docs/overview/introduction.md | 82 +- content/docs/overview/quick-start/index.md | 431 +- content/docs/overview/quick-start/links.md | 74 +- content/gpt/_index.md | 92 +- content/privacy-policy/index.md | 71 +- content/support-us/_index.md | 23 +- content/versions.md | 22 +- content/waha-uptime-kuma/_index.md | 19 +- content/whatsapp-channels/_index.md | 20 +- content/whatsapp-chatwoot/_index.md | 20 +- content/whatsapp-groups/_index.md | 22 +- content/whatsapp-low-code/_index.md | 20 +- content/whatsapp-plus-csharp/_index.md | 20 +- content/whatsapp-plus-go/_index.md | 20 +- content/whatsapp-plus-java/_index.md | 20 +- content/whatsapp-plus-javascript/_index.md | 20 +- content/whatsapp-plus-kotlin/_index.md | 20 +- content/whatsapp-plus-php/_index.md | 20 +- content/whatsapp-plus-python/_index.md | 20 +- content/whatsapp-status/_index.md | 20 +- content/whatsapp-typebot/_index.md | 20 +- data/docs-versions.yml | 120 +- functions/hi-from-lambda.js | 22 +- hugo_stats.json | 8 +- i18n/de.yaml | 10 +- i18n/en.yaml | 34 +- i18n/nl.yaml | 34 +- layouts/code/events/message.channel.md | 24 +- layouts/code/events/message.group.md | 24 +- layouts/code/index/docker-run.md | 6 +- .../language/csharp/install-dependencies.md | 8 +- .../code/language/csharp/receive-message.md | 43 +- layouts/code/language/csharp/send-message.md | 35 +- .../code/language/go/install-dependencies.md | 8 +- layouts/code/language/go/receive-message.md | 55 +- layouts/code/language/go/send-message.md | 55 +- .../language/java/install-dependencies.md | 10 +- layouts/code/language/java/receive-message.md | 53 +- layouts/code/language/java/send-message.md | 39 +- .../javascript/install-dependencies.md | 8 +- .../language/javascript/receive-message.md | 33 +- .../code/language/javascript/send-message.md | 30 +- .../language/kotlin/install-dependencies.md | 18 +- .../code/language/kotlin/receive-message.md | 65 +- layouts/code/language/kotlin/send-message.md | 44 +- .../code/language/php/install-dependencies.md | 10 +- layouts/code/language/php/receive-message.md | 25 +- layouts/code/language/php/send-message.md | 42 +- .../language/python/install-dependencies.md | 10 +- .../code/language/python/receive-message.md | 32 +- layouts/code/language/python/send-message.md | 26 +- layouts/code/requests/Channel.SendText.md | 22 +- layouts/code/requests/Channels.List.md | 30 +- layouts/code/requests/Chat.SendText.md | 22 +- layouts/code/requests/Groups.Create.md | 21 +- layouts/code/requests/Groups.List.md | 27 +- layouts/code/requests/Groups.SendText.md | 21 +- layouts/code/requests/Status.SendImage.md | 25 +- layouts/code/requests/Status.SendText.md | 21 +- layouts/code/requests/Status.SendVideo.md | 25 +- layouts/include/why-waha-section.html | 20 +- layouts/index.html | 6 +- layouts/whatsapp-channels/list.html | 4 +- layouts/whatsapp-groups/list.html | 4 +- layouts/whatsapp-plus-csharp/list.html | 22 +- layouts/whatsapp-plus-go/list.html | 22 +- layouts/whatsapp-plus-java/list.html | 22 +- layouts/whatsapp-plus-javascript/list.html | 24 +- layouts/whatsapp-plus-kotlin/list.html | 21 +- layouts/whatsapp-plus-php/list.html | 21 +- layouts/whatsapp-plus-python/list.html | 20 +- static/site.webmanifest | 12 +- static/swagger/index.css | 32 +- static/swagger/openapi.json | 23283 ++++---- static/swagger/swagger-initializer.js | 35 +- static/swagger/swagger-ui-bundle.js | 49265 +++++++++++++++- static/swagger/swagger-ui-es-bundle-core.js | 13556 ++++- static/swagger/swagger-ui-es-bundle.js | 49256 ++++++++++++++- .../swagger/swagger-ui-standalone-preset.js | 9316 ++- static/swagger/swagger-ui.css | 9244 ++- static/swagger/swagger-ui.js | 8796 ++- 260 files changed, 170819 insertions(+), 32507 deletions(-) diff --git a/assets/js/custom.js b/assets/js/custom.js index b1746116f..c5525d04e 100644 --- a/assets/js/custom.js +++ b/assets/js/custom.js @@ -1 +1 @@ -// Put your custom JS code here +// Put your custom JS code here diff --git a/assets/js/docsearch.js b/assets/js/docsearch.js index 432f78fc7..5e9c60d64 100644 --- a/assets/js/docsearch.js +++ b/assets/js/docsearch.js @@ -1,16 +1,16 @@ -import docsearch from "@docsearch/js"; - -docsearch({ - container: "#docsearch", - appId: "OV9LGQBN5C", - apiKey: "7005679dc522e856719f3270aac826a1", - indexName: "wahalike", - insights: true -}); - -const onClick = function () { - document.getElementsByClassName("DocSearch-Button")[0].click(); -}; - -document.getElementById("searchToggleMobileDocSearch").onclick = onClick; -document.getElementById("searchToggleDesktopDocSearch").onclick = onClick; \ No newline at end of file +import docsearch from '@docsearch/js'; + +docsearch({ + container: '#docsearch', + appId: 'OV9LGQBN5C', + apiKey: '7005679dc522e856719f3270aac826a1', + indexName: 'wahalike', + insights: true +}); + +const onClick = function () { + document.getElementsByClassName('DocSearch-Button')[0].click(); +}; + +document.getElementById('searchToggleMobileDocSearch').onclick = onClick; +document.getElementById('searchToggleDesktopDocSearch').onclick = onClick; diff --git a/assets/jsconfig.json b/assets/jsconfig.json index d4ee6dcbf..7a19b7145 100644 --- a/assets/jsconfig.json +++ b/assets/jsconfig.json @@ -1,8 +1,8 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "*": ["*", "..\\node_modules\\@thulite\\doks-core\\assets\\*"] - } - } -} +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": ["*", "..\\node_modules\\@thulite\\doks-core\\assets\\*"] + } + } +} diff --git a/assets/scss/common/_custom.scss b/assets/scss/common/_custom.scss index c46364d23..3f8e41261 100644 --- a/assets/scss/common/_custom.scss +++ b/assets/scss/common/_custom.scss @@ -1,112 +1,116 @@ -// Card shortcode - -.card-icon { - padding: 0.2em; - border-radius: 0.25rem; -} - -.icon-yellow { - border: 1px solid var(--sl-color-orange); - background-color: var(--sl-color-orange-high); -} - -.icon-purple { - border: 1px solid var(--sl-color-purple); - background-color: var(--sl-color-purple-high); -} - -.icon-green { - border: 1px solid var(--sl-color-green); - background-color: var(--sl-color-green-high); -} - -.icon-red { - border: 1px solid var(--sl-color-red); - background-color: var(--sl-color-red-high); -} - -.icon-blue { - border: 1px solid var(--sl-color-blue); - background-color: var(--sl-color-blue-high); -} - -.card-nav .card-box svg { - stroke: $db-bluishCyan-100; -} - -@include color-mode(dark) { - .icon-yellow { - border: 1px solid var(--sl-color-orange); - background-color: var(--sl-color-orange-low); - } - - .icon-purple { - border: 1px solid var(--sl-color-purple); - background-color: var(--sl-color-purple-low); - } - - .icon-green { - border: 1px solid var(--sl-color-green); - background-color: var(--sl-color-green-low); - } - - .icon-red { - border: 1px solid var(--sl-color-red); - background-color: var(--sl-color-red-low); - } - - .icon-blue { - border: 1px solid var(--sl-color-blue); - background-color: var(--sl-color-blue-low); - } - - .card-nav .card-box svg { - stroke: $white; - } -} - -.card-nav .card-box { - border-radius: 0; - padding: 1rem 1rem 0; -} - -.card-nav .card-box:hover { - border: 1px solid $card-border-color; - background-color: transparent; -} - -@include color-mode(dark) { - .card-nav .card-box { - border: 1px solid hsl(224deg, 10%, 23%); - } - - .card-nav .card-box:hover { - border: 1px solid hsl(224deg, 10%, 23%); - background-color: transparent; - } -} - -// DocSearch - -.DocSearch-Container { - z-index: 2000 !important; -} - -.DocSearch-Hit-icon { - display: flex; - align-items: center; -} - -.DocSearch-Hits mark { - padding: 0; -} - -@media (max-width: 768px) { - .DocSearch-Modal { - position: fixed !important; - } -} - -// DocSearch -@import "./variables-docsearch"; -@import "@docsearch/css/dist/modal"; +// Card shortcode + +.card-icon { + padding: 0.2em; + border-radius: 0.25rem; +} + +.icon-yellow { + border: 1px solid var(--sl-color-orange); + background-color: var(--sl-color-orange-high); +} + +.icon-purple { + border: 1px solid var(--sl-color-purple); + background-color: var(--sl-color-purple-high); +} + +.icon-green { + border: 1px solid var(--sl-color-green); + background-color: var(--sl-color-green-high); +} + +.icon-red { + border: 1px solid var(--sl-color-red); + background-color: var(--sl-color-red-high); +} + +.icon-blue { + border: 1px solid var(--sl-color-blue); + background-color: var(--sl-color-blue-high); +} + +.card-nav .card-box svg { + stroke: $db-bluishCyan-100; +} + +@include color-mode(dark) { + .icon-yellow { + border: 1px solid var(--sl-color-orange); + background-color: var(--sl-color-orange-low); + } + + .icon-purple { + border: 1px solid var(--sl-color-purple); + background-color: var(--sl-color-purple-low); + } + + .icon-green { + border: 1px solid var(--sl-color-green); + background-color: var(--sl-color-green-low); + } + + .icon-red { + border: 1px solid var(--sl-color-red); + background-color: var(--sl-color-red-low); + } + + .icon-blue { + border: 1px solid var(--sl-color-blue); + background-color: var(--sl-color-blue-low); + } + + .card-nav .card-box svg { + stroke: $white; + } + + .color-accent { + color: rgb(68, 66, 66); + } +} + +.card-nav .card-box { + border-radius: 0; + padding: 1rem 1rem 0; +} + +.card-nav .card-box:hover { + border: 1px solid $card-border-color; + background-color: transparent; +} + +@include color-mode(dark) { + .card-nav .card-box { + border: 1px solid hsl(224deg, 10%, 23%); + } + + .card-nav .card-box:hover { + border: 1px solid hsl(224deg, 10%, 23%); + background-color: transparent; + } +} + +// DocSearch + +.DocSearch-Container { + z-index: 2000 !important; +} + +.DocSearch-Hit-icon { + display: flex; + align-items: center; +} + +.DocSearch-Hits mark { + padding: 0; +} + +@media (max-width: 768px) { + .DocSearch-Modal { + position: fixed !important; + } +} + +// DocSearch +@import "./variables-docsearch"; +@import "@docsearch/css/dist/modal"; diff --git a/assets/scss/common/_variables-custom.scss b/assets/scss/common/_variables-custom.scss index 56c9eb79e..d2280ccd4 100644 --- a/assets/scss/common/_variables-custom.scss +++ b/assets/scss/common/_variables-custom.scss @@ -1 +1 @@ -// Put your custom SCSS variables here +// Put your custom SCSS variables here diff --git a/assets/scss/common/_variables-docsearch.scss b/assets/scss/common/_variables-docsearch.scss index b776a86ba..f9cd1c4bd 100644 --- a/assets/scss/common/_variables-docsearch.scss +++ b/assets/scss/common/_variables-docsearch.scss @@ -1,61 +1,61 @@ -/* DocSearch Variables */ - -:root { - --docsearch-primary-color: rgb(84, 104, 255); - --docsearch-text-color: rgb(28, 30, 33); - --docsearch-spacing: 12px; - --docsearch-icon-stroke-width: 1.4; - --docsearch-highlight-color: var(--docsearch-primary-color); - --docsearch-muted-color: rgb(150, 159, 175); - --docsearch-container-background: rgba(101, 108, 133, 0.8); - --docsearch-logo-color: rgba(84, 104, 255); - - /* modal */ - --docsearch-modal-width: 560px; - --docsearch-modal-height: 600px; - --docsearch-modal-background: rgb(245, 246, 247); - --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px 8px 0 rgba(85, 90, 100, 1); - - /* searchbox */ - --docsearch-searchbox-height: 56px; - --docsearch-searchbox-background: rgb(235, 237, 240); - --docsearch-searchbox-focus-background: #fff; - --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color); - - /* hit */ - --docsearch-hit-height: 56px; - --docsearch-hit-color: rgb(68, 73, 80); - --docsearch-hit-active-color: #fff; - --docsearch-hit-background: #fff; - --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225); - - /* key */ - --docsearch-key-gradient: linear-gradient(-225deg, rgb(213, 219, 228) 0%, rgb(248, 248, 248) 100%); - --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4); - --docsearch-key-pressed-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff, 0 1px 1px 0 rgba(30, 35, 90, 0.4); - /* footer */ - --docsearch-footer-height: 44px; - --docsearch-footer-background: #fff; - --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12); -} - -/* Darkmode */ - -html[data-bs-theme="dark"] { - --docsearch-text-color: rgb(245, 246, 247); - --docsearch-container-background: rgba(9, 10, 17, 0.8); - --docsearch-modal-background: rgb(21, 23, 42); - --docsearch-modal-shadow: inset 1px 1px 0 0 rgb(44, 46, 64), 0 3px 8px 0 rgb(0, 3, 9); - --docsearch-searchbox-background: rgb(9, 10, 17); - --docsearch-searchbox-focus-background: #000; - --docsearch-hit-color: rgb(190, 195, 201); - --docsearch-hit-shadow: none; - --docsearch-hit-background: rgb(9, 10, 17); - --docsearch-key-gradient: linear-gradient(-26.5deg, rgb(86, 88, 114) 0%, rgb(49, 53, 91) 100%); - --docsearch-key-shadow: inset 0 -2px 0 0 rgb(40, 45, 85), inset 0 0 1px 1px rgb(81, 87, 125), 0 2px 2px 0 rgba(3, 4, 9, 0.3); - --docsearch-key-pressed-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 1px 1px 0 #0304094d; - --docsearch-footer-background: rgb(30, 33, 54); - --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2); - --docsearch-logo-color: rgb(255, 255, 255); - --docsearch-muted-color: rgb(127, 132, 151); -} \ No newline at end of file +/* DocSearch Variables */ + +:root { + --docsearch-primary-color: rgb(84, 104, 255); + --docsearch-text-color: rgb(28, 30, 33); + --docsearch-spacing: 12px; + --docsearch-icon-stroke-width: 1.4; + --docsearch-highlight-color: var(--docsearch-primary-color); + --docsearch-muted-color: rgb(150, 159, 175); + --docsearch-container-background: rgba(101, 108, 133, 0.8); + --docsearch-logo-color: rgba(84, 104, 255); + + /* modal */ + --docsearch-modal-width: 560px; + --docsearch-modal-height: 600px; + --docsearch-modal-background: rgb(245, 246, 247); + --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px 8px 0 rgba(85, 90, 100, 1); + + /* searchbox */ + --docsearch-searchbox-height: 56px; + --docsearch-searchbox-background: rgb(235, 237, 240); + --docsearch-searchbox-focus-background: #fff; + --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color); + + /* hit */ + --docsearch-hit-height: 56px; + --docsearch-hit-color: rgb(68, 73, 80); + --docsearch-hit-active-color: #fff; + --docsearch-hit-background: #fff; + --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225); + + /* key */ + --docsearch-key-gradient: linear-gradient(-225deg, rgb(213, 219, 228) 0%, rgb(248, 248, 248) 100%); + --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4); + --docsearch-key-pressed-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff, 0 1px 1px 0 rgba(30, 35, 90, 0.4); + /* footer */ + --docsearch-footer-height: 44px; + --docsearch-footer-background: #fff; + --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12); +} + +/* Darkmode */ + +html[data-bs-theme="dark"] { + --docsearch-text-color: rgb(245, 246, 247); + --docsearch-container-background: rgba(9, 10, 17, 0.8); + --docsearch-modal-background: rgb(21, 23, 42); + --docsearch-modal-shadow: inset 1px 1px 0 0 rgb(44, 46, 64), 0 3px 8px 0 rgb(0, 3, 9); + --docsearch-searchbox-background: rgb(9, 10, 17); + --docsearch-searchbox-focus-background: #000; + --docsearch-hit-color: rgb(190, 195, 201); + --docsearch-hit-shadow: none; + --docsearch-hit-background: rgb(9, 10, 17); + --docsearch-key-gradient: linear-gradient(-26.5deg, rgb(86, 88, 114) 0%, rgb(49, 53, 91) 100%); + --docsearch-key-shadow: inset 0 -2px 0 0 rgb(40, 45, 85), inset 0 0 1px 1px rgb(81, 87, 125), 0 2px 2px 0 rgba(3, 4, 9, 0.3); + --docsearch-key-pressed-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 1px 1px 0 #0304094d; + --docsearch-footer-background: rgb(30, 33, 54); + --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2); + --docsearch-logo-color: rgb(255, 255, 255); + --docsearch-muted-color: rgb(127, 132, 151); +} diff --git a/assets/scss/common/highlight-http-request.scss b/assets/scss/common/highlight-http-request.scss index baee4a68c..2d81496ec 100644 --- a/assets/scss/common/highlight-http-request.scss +++ b/assets/scss/common/highlight-http-request.scss @@ -1,46 +1,45 @@ -// -// highlight - http request -// - -.http-method { - font-weight: bold !important; - padding: 0.25rem 0.7rem !important; - border-radius: 4px !important; - color: white !important; -} - -// Define Swagger-like colors -$swagger-colors: ( - "GET": #61affe, - "POST": #49cc90, - "PUT": #fca130, - "DELETE": #f93e3e, - "PATCH": #50e3c2, - "OPTIONS": #0d5aa7, - "HEAD": #9012fe -); - -// Apply colors to HTTP method classes -@each $method, $color in $swagger-colors { - .http-method-#{$method} { - background-color: $color !important; - } -} - -code.language-http[data-lang="http"] { - font-weight: bold; -} - -// General styles for the pre element -pre.chroma { -} - -// Apply color based on HTTP method class inside pre.chroma -@each $method, $color in $swagger-colors { - pre.chroma:has(.http-method-#{$method}) { - background-color: rgba($color, 0.1); - border-color: rgba($color, 1); - border-radius: 0.25rem; - } -} - +// +// highlight - http request +// + +.http-method { + font-weight: bold !important; + padding: 0.25rem 0.7rem !important; + border-radius: 4px !important; + color: white !important; +} + +// Define Swagger-like colors +$swagger-colors: ( + "GET": #61affe, + "POST": #49cc90, + "PUT": #fca130, + "DELETE": #f93e3e, + "PATCH": #50e3c2, + "OPTIONS": #0d5aa7, + "HEAD": #9012fe +); + +// Apply colors to HTTP method classes +@each $method, $color in $swagger-colors { + .http-method-#{$method} { + background-color: $color !important; + } +} + +code.language-http[data-lang="http"] { + font-weight: bold; +} + +// General styles for the pre element +pre.chroma { +} + +// Apply color based on HTTP method class inside pre.chroma +@each $method, $color in $swagger-colors { + pre.chroma:has(.http-method-#{$method}) { + background-color: rgba($color, 0.1); + border-color: rgba($color, 1); + border-radius: 0.25rem; + } +} diff --git a/config/babel.config.js b/config/babel.config.js index 8482b9c15..9a65c09a6 100644 --- a/config/babel.config.js +++ b/config/babel.config.js @@ -1,17 +1,17 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: [ - // Best practice: https://github.com/babel/babel/issues/7789 - '>=1%', - 'not ie 11', - 'not op_mini all' - ] - } - } - ] - ] -}; +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + browsers: [ + // Best practice: https://github.com/babel/babel/issues/7789 + '>=1%', + 'not ie 11', + 'not op_mini all' + ] + } + } + ] + ] +}; diff --git a/config/postcss.config.js b/config/postcss.config.js index 686b64d5e..d18682612 100644 --- a/config/postcss.config.js +++ b/config/postcss.config.js @@ -1,66 +1,67 @@ -const autoprefixer = require('autoprefixer'); -const purgecss = require('@fullhuman/postcss-purgecss'); -const whitelister = require('purgecss-whitelister'); - -module.exports = { - plugins: [ - autoprefixer(), - purgecss({ - content: ['./hugo_stats.json'], - extractors: [ - { - extractor: (content) => { - const els = JSON.parse(content).htmlElements; - return els.tags.concat(els.classes, els.ids); - }, - extensions: ['json'] - } - ], - dynamicAttributes: [ - "aria-selected", - 'aria-expanded', - 'data-bs-popper', - 'data-bs-target', - 'data-bs-theme', - 'data-dark-mode', - 'data-global-alert', - 'data-pane', // tabs.js - 'data-popper-placement', - 'data-sizes', - 'data-toggle-tab', // tabs.js - 'id', - 'size', - 'type' - ], - safelist: [ - ...whitelister(["./node_modules/@docsearch/css/dist/modal.css"]), - 'active', - 'btn-clipboard', // clipboards.js - 'clipboard', // clipboards.js - 'disabled', - 'hidden', - 'modal-backdrop', // search-modal.js - 'selected', // search-modal.js - 'show', - 'img-fluid', - 'blur-up', - 'lazyload', - 'lazyloaded', - 'alert-link', - 'container-fw ', - 'container-lg', - 'container-fluid', - 'offcanvas-backdrop', - 'figcaption', - 'dt', - 'dd', - 'showing', - 'hiding', - 'page-item', - 'page-link', - 'not-content', - ...whitelister(['./assets/scss/**/*.scss', './node_modules/@thulite/doks-core/assets/scss/components/_code.scss', './node_modules/@thulite/doks-core/assets/scss/components/_expressive-code.scss', './node_modules/@thulite/doks-core/assets/scss/common/_syntax.scss']) - ] - }) - ] -}; +const autoprefixer = require('autoprefixer'); +const purgecss = require('@fullhuman/postcss-purgecss'); +const whitelister = require('purgecss-whitelister'); + +module.exports = { + plugins: [ + autoprefixer(), + purgecss({ + content: ['./hugo_stats.json'], + extractors: [ + { + extractor: (content) => { + const els = JSON.parse(content).htmlElements; + return els.tags.concat(els.classes, els.ids); + }, + extensions: ['json'] + } + ], + dynamicAttributes: [ + 'aria-selected', + 'aria-expanded', + 'data-bs-popper', + 'data-bs-target', + 'data-bs-theme', + 'data-dark-mode', + 'data-global-alert', + 'data-pane', // tabs.js + 'data-popper-placement', + 'data-sizes', + 'data-toggle-tab', // tabs.js + 'id', + 'size', + 'type' + ], + safelist: [ + ...whitelister(['./node_modules/@docsearch/css/dist/modal.css']), + 'active', + 'color-accent', + 'btn-clipboard', // clipboards.js + 'clipboard', // clipboards.js + 'disabled', + 'hidden', + 'modal-backdrop', // search-modal.js + 'selected', // search-modal.js + 'show', + 'img-fluid', + 'blur-up', + 'lazyload', + 'lazyloaded', + 'alert-link', + 'container-fw ', + 'container-lg', + 'container-fluid', + 'offcanvas-backdrop', + 'figcaption', + 'dt', + 'dd', + 'showing', + 'hiding', + 'page-item', + 'page-link', + 'not-content', + ...whitelister(['./assets/scss/**/*.scss', './node_modules/@thulite/doks-core/assets/scss/components/_code.scss', './node_modules/@thulite/doks-core/assets/scss/components/_expressive-code.scss', './node_modules/@thulite/doks-core/assets/scss/common/_syntax.scss']) + ] + }) + ] +}; diff --git a/content/_index.md b/content/_index.md index d6c4c3df5..bf2b5adf0 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,9 +1,8 @@ ---- -title : "WhatsApp HTTP API" -description: "WAHA - WhatsApp API that you can run in a click!" -lead: "WAHA - WhatsApp API 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 - ---- +--- +title: "WhatsApp HTTP API" +description: "WAHA - WhatsApp API that you can run in a click!" +lead: "WAHA - WhatsApp API 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 +--- diff --git a/content/blog/_index.md b/content/blog/_index.md index 267abe6c8..97f12fb58 100644 --- a/content/blog/_index.md +++ b/content/blog/_index.md @@ -1,9 +1,9 @@ ---- -title: "Blog" -description: "WAHA - WhatsApp API that you can install on your own server and run in less than 5 minutes!" -date: 2020-10-06T08:49:55+00:00 -lastmod: 2020-10-06T08:49:55+00:00 -draft: false - ---- -👉 You can filter the blog posts by [**Categories**](/categories) 👈 +--- +title: "Blog" +description: "WAHA - WhatsApp API that you can install on your own server and run in less than 5 minutes!" +date: 2020-10-06T08:49:55+00:00 +lastmod: 2020-10-06T08:49:55+00:00 +draft: false +--- + +👉 You can filter the blog posts by [**Categories**](/categories) 👈 diff --git a/content/blog/apps-chatwoot-0-overview/index.md b/content/blog/apps-chatwoot-0-overview/index.md index c08fab370..9798b1f1a 100644 --- a/content/blog/apps-chatwoot-0-overview/index.md +++ b/content/blog/apps-chatwoot-0-overview/index.md @@ -1,110 +1,111 @@ ---- -title: "WhatsApp + ChatWoot - Overview" -description: "WhatsApp + ChatWoot - Overview" -excerpt: "WhatsApp + ChatWoot - Overview" -date: 2025-07-12T08:48:45+00:00 -draft: false -images: [ "waha-chatwoot.png" ] -categories: [ "Apps", "ChatWoot" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: apps-chatwoot-overview ---- - -## Overview -**WAHA** provides a seamless integration with **Chatwoot**, allowing you to manage your WhatsApp communications through a powerful customer service platform. This overview highlights the key features and capabilities of the integration. - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -

- -

- - -## Contacts Sync -**Contact information** is displayed in **Chatwoot** from **WhatsApp**: - -![](screenshots/contact-info.png) - -## Messages - -Send and receive **text messages**: - -![Text Messages](screenshots/messages/text.png) -

- -**Reply** to specific messages: - -![Reply to Messages](screenshots/messages/reply.png) -

- -**Receive media** files from WhatsApp: - -![Receive Media](screenshots/messages/receive-media.png) -

- -**Send media files** through **Chatwoot** -(available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}})) - -![Send Media](screenshots/messages/send-media.png) -

- -View message **reactions** from WhatsApp: - -![Message Reactions](screenshots/messages/reactions.png) -

- -**Messages from WhatsApp** are displayed in Chatwoot: - -![Messages from WhatsApp](screenshots/messages/message-from-whatsapp.png) -

- -**Deleted messages** in **WhatsApp** are marked accordingly: - -![Deleted Messages in WhatsApp](screenshots/messages/deleted-messages-on-whatsapp.png) -

- -**Delete messages** in **Chatwoot**: - -![Delete Messages in Chatwoot](screenshots/messages/delete-message-on-chatwoot.png) -

- -Add **private notes** visible only to agents: - -![Private Notes](screenshots/messages/private-note.png) - - -## Languages - -You can set your language when creating a **Chatwoot App** in the **WAHA Dashboard**: - -![WAHA Languages](screenshots/dashboard/cw-languages-waha.png) - -You'll receive notification messages in the selected language in **Chatwoot**: - -![Chatwoot Languages](screenshots/dashboard/cw-languages-chatwoot.png) - -## Commands -Use the `help` command to see available commands in **WhatsApp Integration (WAHA)** conversation: - -![Help Command](screenshots/commands/help.png) - -**Scan QR code** to connect WhatsApp: - -![Scan QR Command](screenshots/commands/scan-qr.png) - -Get session status updates in Chatwoot: - -![Status Updates Command](screenshots/commands/status-updates.png) - - -## Error Handling -In case of any errors, WAHA retries a few times and then gives detailed information about the error: - -![Error Reports and Retries](screenshots/messages/error-reports-and-retries.png) - -You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: - -![WAHA Jobs Dashboard](screenshots/dashboard/waha-jobs-dashboard.png) +--- +title: "WhatsApp + ChatWoot - Overview" +description: "WhatsApp + ChatWoot - Overview" +excerpt: "WhatsApp + ChatWoot - Overview" +date: 2025-07-12T08:48:45+00:00 +draft: false +images: ["waha-chatwoot.png"] +categories: ["Apps", "ChatWoot"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: apps-chatwoot-overview +--- + +## Overview + +**WAHA** provides a seamless integration with **Chatwoot**, allowing you to manage your WhatsApp communications through a powerful customer service platform. This overview highlights the key features and capabilities of the integration. + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +

+ +

+ +## Contacts Sync + +**Contact information** is displayed in **Chatwoot** from **WhatsApp**: + +![](screenshots/contact-info.png) + +## Messages + +Send and receive **text messages**: + +![Text Messages](screenshots/messages/text.png) +

+ +**Reply** to specific messages: + +![Reply to Messages](screenshots/messages/reply.png) +

+ +**Receive media** files from WhatsApp: + +![Receive Media](screenshots/messages/receive-media.png) +

+ +**Send media files** through **Chatwoot** +(available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}})) + +![Send Media](screenshots/messages/send-media.png) +

+ +View message **reactions** from WhatsApp: + +![Message Reactions](screenshots/messages/reactions.png) +

+ +**Messages from WhatsApp** are displayed in Chatwoot: + +![Messages from WhatsApp](screenshots/messages/message-from-whatsapp.png) +

+ +**Deleted messages** in **WhatsApp** are marked accordingly: + +![Deleted Messages in WhatsApp](screenshots/messages/deleted-messages-on-whatsapp.png) +

+ +**Delete messages** in **Chatwoot**: + +![Delete Messages in Chatwoot](screenshots/messages/delete-message-on-chatwoot.png) +

+ +Add **private notes** visible only to agents: + +![Private Notes](screenshots/messages/private-note.png) + +## Languages + +You can set your language when creating a **Chatwoot App** in the **WAHA Dashboard**: + +![WAHA Languages](screenshots/dashboard/cw-languages-waha.png) + +You'll receive notification messages in the selected language in **Chatwoot**: + +![Chatwoot Languages](screenshots/dashboard/cw-languages-chatwoot.png) + +## Commands + +Use the `help` command to see available commands in **WhatsApp Integration (WAHA)** conversation: + +![Help Command](screenshots/commands/help.png) + +**Scan QR code** to connect WhatsApp: + +![Scan QR Command](screenshots/commands/scan-qr.png) + +Get session status updates in Chatwoot: + +![Status Updates Command](screenshots/commands/status-updates.png) + +## Error Handling + +In case of any errors, WAHA retries a few times and then gives detailed information about the error: + +![Error Reports and Retries](screenshots/messages/error-reports-and-retries.png) + +You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: + +![WAHA Jobs Dashboard](screenshots/dashboard/waha-jobs-dashboard.png) diff --git a/content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md b/content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md index d31c9bfa3..e0759d86e 100644 --- a/content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md +++ b/content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md @@ -1,11 +1,12 @@ -
-{{< callout icon="outline/server" title="Using a VPS or VM via SSH?" >}} - -You need to **forward ports** so you can access remote server ports from your laptop. - -Connect to the server using the command: - -```bash { title="Connect to server with port forwarding" } -ssh -L 3000:localhost:3000 -L 3009:localhost:3009 {user}@{server} -``` -{{< /callout >}} +
+{{< callout icon="outline/server" title="Using a VPS or VM via SSH?" >}} + +You need to **forward ports** so you can access remote server ports from your laptop. + +Connect to the server using the command: + +```bash { title="Connect to server with port forwarding" } +ssh -L 3000:localhost:3000 -L 3009:localhost:3009 {user}@{server} +``` + +{{< /callout >}} diff --git a/content/blog/apps-chatwoot-1-install/index.md b/content/blog/apps-chatwoot-1-install/index.md index 50e26f58c..6719e31af 100644 --- a/content/blog/apps-chatwoot-1-install/index.md +++ b/content/blog/apps-chatwoot-1-install/index.md @@ -1,216 +1,243 @@ ---- -title: "WhatsApp + ChatWoot - Installation Guide" -description: "WhatsApp + ChatWoot - Installation Guide" -excerpt: "WhatsApp + ChatWoot - Installation Guide" -date: 2025-07-11T08:48:45+00:00 -draft: false -images: [ "waha-chatwoot.png" ] -categories: [ "Apps", "ChatWoot" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: apps-chatwoot-install ---- - -## Overview -Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -After completing the installation guide, you'll have: -- **WAHA** on [**http://localhost:3000**](http://localhost:3000) -- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) - -{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} - -## Requirements -- **Hardware**: VM, VPS, or laptop with minimum **2 CPU** and **4GB RAM** -- **Operating System**: **Debian** or **Ubuntu** based distributions. - -{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} - -## Steps to Deploy -### Step 0: Add DNS Aliases -First, we need to add **DNS Aliases** so everything works as inside docker containers. - -👉 **Run the below commands on YOUR LAPTOP/PC**, NOT on the **VPS or VM**: - -{{< tabs "dns-aliases" >}} -{{< tab "MacOS" >}} -```bash { title="Add DNS Aliases (MacOS)" } -# Add -echo "127.0.0.1 chatwoot" | sudo tee -a /etc/hosts -echo "127.0.0.1 waha" | sudo tee -a /etc/hosts - -# Check it worked - you must see the line like: -# 64 bytes from localhost (127.0.0.1): ... -ping chatwoot -ping waha -``` -{{< /tab >}} - -{{< tab "Linux" >}} -```bash { title="Add DNS Aliases (Linux)" } -# Add -echo "127.0.0.1 chatwoot" | sudo tee -a /etc/hosts -echo "127.0.0.1 waha" | sudo tee -a /etc/hosts - -# Check it worked - you must see the line like: -# 64 bytes from localhost (127.0.0.1): ... -ping chatwoot -ping waha -``` -{{< /tab >}} -{{< tab "Windows" >}} -Run **PowerShell as Admin** and execute: -```bash { title="Add DNS Aliases (Windows, PowerShell as Admin)" } -Add-Content -Path "$env:SystemRoot\System32\drivers\etc\hosts" -Value "`n127.0.0.1 chatwoot" -Add-Content -Path "$env:SystemRoot\System32\drivers\etc\hosts" -Value "`n127.0.0.1 waha" - -ping chatwoot -ping waha -``` -{{< /tab >}} -{{< /tabs >}} - -### Step 1: Install Docker -```bash { title="Install Docker" } -# example in ubuntu -apt-get update -apt-get upgrade -curl -fsSL https://get.docker.com -o get-docker.sh -sudo sh get-docker.sh -apt install docker-compose-plugin -``` - -### Step 2: Download the Required Files -```bash { title="Download files" } -# Download the env files -wget -O .waha.env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/.waha.env -wget -O .chatwoot.env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/.chatwoot.env -# Download docker-compose -wget -O docker-compose.yaml https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/docker-compose.yaml -``` - -### Step 3: Configure Environment Variables -Now you can tweak `.waha.env`, `.chatwoot.env` and `docker-compose.yaml` according to your preferences. - -Here are a few environment variables we suggest that you change before going forward (in this guide we'll use **the default values**): -```env { title=".waha.env" } -WAHA_API_KEY_PLAIN=00000000000000000000000000000000 -WAHA_API_KEY=sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 -WAHA_DASHBOARD_USERNAME=admin -WAHA_DASHBOARD_PASSWORD=11111111111111111111111111111111 -WHATSAPP_SWAGGER_USERNAME=admin -WHATSAPP_SWAGGER_PASSWORD=11111111111111111111111111111111 -``` - -{{< callout context="danger" title="Do Not Use Default API Keys or Passwords!" icon="outline/shield-check" >}} -Even if you're running WAHA on a private server and think the IP is unknown - it's -straightforward for attackers to find and exploit it to send spam or abuse your WhatsApp sessions. - -Always set strong, random values (see a guide below) for: -- `WAHA_API_KEY` -- `WAHA_DASHBOARD_PASSWORD` -- `WHATSAPP_SWAGGER_PASSWORD` - you can the same as for `WAHA_DASHBOARD_PASSWORD` - -**👉 How to Generate and Hash Api-Key** -{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} -{{< /callout >}} - -{{< details "👉 How to Generate and Hash Api-Key" >}} -{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} -{{< /details >}} - -### Step 4: Pull Docker Images -{{< tabs "download-docker-image" >}} - -{{< tab "➕ WAHA Plus" >}} -If you got the -[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) -, use the following commands: - -```bash { title="Pull Docker Images: WAHA Plus" } -docker login -u devlikeapro -p {KEY} -docker compose pull -docker logout -``` - -👉 Go to -[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) -to generate the command with the right version. -{{< /tab >}} - -{{< tab "WAHA Core" >}} -1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha` -2. Run the command: -```bash { title="Pull Docker Images: WAHA Core" } -docker compose pull -``` - -{{< /tab >}} - -{{< tab "WAHA (ARM)" >}} -If you're using **ARM CPU** (like Apple M1/M2, Raspberry Pi etc.). - -If you got the -[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}): -1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha-plus:arm` -2. Run the commands: - -```bash { title="Pull Docker Images: WAHA Plus (ARM)" } -docker login -u devlikeapro -p {KEY} -docker pull devlikeapro/waha-plus:arm -docker logout -``` - -👉 Go to -[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) -to generate the command with the right version. - ---- - -If you want to run **WAHA Core**: -1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha:arm` -2. Run the commands: -```bash { title="Pull Docker Images: WAHA Core (ARM)" } -docker compose pull -``` -{{< /tab >}} - -{{< /tabs >}} - -### Step 5: Prepare ChatWoot Database -```bash { title="Prepare ChatWoot Database" } -docker compose run --rm chatwoot bundle exec rails db:chatwoot_prepare -``` - -### Step 6: Start the Services -```bash { title="Start Services" } -docker compose up -d -``` - -### Step 7: Access Your WAHA -**Open** [**http://localhost:3000/dashboard**](http://localhost:3000/dashboard) with credentials: -- User: `admin` -- Password: `11111111111111111111111111111111` - -**Add Api Key** to your worker: -- Api-Key: `00000000000000000000000000000000` - -![](waha-dashboard-key.png) - - -### Step 8: Access Your ChatWoot -**Open** and **finish** the onboarding guide on [**http://localhost:3009/**](http://localhost:3009/) - -![](chatwoot-onboarding.png) - - -## What is next? - -👉 Connect **WhatsApp** to **ChatWoot** in -[**WhatsApp + ChatWoot - Configuration Guide**]({{< relref "/blog/apps-chatwoot-2-config" >}}) - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} +--- +title: "WhatsApp + ChatWoot - Installation Guide" +description: "WhatsApp + ChatWoot - Installation Guide" +excerpt: "WhatsApp + ChatWoot - Installation Guide" +date: 2025-07-11T08:48:45+00:00 +draft: false +images: ["waha-chatwoot.png"] +categories: ["Apps", "ChatWoot"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: apps-chatwoot-install +--- + +## Overview + +Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +After completing the installation guide, you'll have: + +- **WAHA** on [**http://localhost:3000**](http://localhost:3000) +- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) + +{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} + +## Requirements + +- **Hardware**: VM, VPS, or laptop with minimum **2 CPU** and **4GB RAM** +- **Operating System**: **Debian** or **Ubuntu** based distributions. + +{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} + +## Steps to Deploy + +### Step 0: Add DNS Aliases + +First, we need to add **DNS Aliases** so everything works as inside docker containers. + +👉 **Run the below commands on YOUR LAPTOP/PC**, NOT on the **VPS or VM**: + +{{< tabs "dns-aliases" >}} +{{< tab "MacOS" >}} + +```bash { title="Add DNS Aliases (MacOS)" } +# Add +echo "127.0.0.1 chatwoot" | sudo tee -a /etc/hosts +echo "127.0.0.1 waha" | sudo tee -a /etc/hosts + +# Check it worked - you must see the line like: +# 64 bytes from localhost (127.0.0.1): ... +ping chatwoot +ping waha +``` + +{{< /tab >}} + +{{< tab "Linux" >}} + +```bash { title="Add DNS Aliases (Linux)" } +# Add +echo "127.0.0.1 chatwoot" | sudo tee -a /etc/hosts +echo "127.0.0.1 waha" | sudo tee -a /etc/hosts + +# Check it worked - you must see the line like: +# 64 bytes from localhost (127.0.0.1): ... +ping chatwoot +ping waha +``` + +{{< /tab >}} +{{< tab "Windows" >}} +Run **PowerShell as Admin** and execute: + +```bash { title="Add DNS Aliases (Windows, PowerShell as Admin)" } +Add-Content -Path "$env:SystemRoot\System32\drivers\etc\hosts" -Value "`n127.0.0.1 chatwoot" +Add-Content -Path "$env:SystemRoot\System32\drivers\etc\hosts" -Value "`n127.0.0.1 waha" + +ping chatwoot +ping waha +``` + +{{< /tab >}} +{{< /tabs >}} + +### Step 1: Install Docker + +```bash { title="Install Docker" } +# example in ubuntu +apt-get update +apt-get upgrade +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +apt install docker-compose-plugin +``` + +### Step 2: Download the Required Files + +```bash { title="Download files" } +# Download the env files +wget -O .waha.env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/.waha.env +wget -O .chatwoot.env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/.chatwoot.env +# Download docker-compose +wget -O docker-compose.yaml https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose/chatwoot/docker-compose.yaml +``` + +### Step 3: Configure Environment Variables + +Now you can tweak `.waha.env`, `.chatwoot.env` and `docker-compose.yaml` according to your preferences. + +Here are a few environment variables we suggest that you change before going forward (in this guide we'll use **the default values**): + +```env { title=".waha.env" } +WAHA_API_KEY_PLAIN=00000000000000000000000000000000 +WAHA_API_KEY=sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 +WAHA_DASHBOARD_USERNAME=admin +WAHA_DASHBOARD_PASSWORD=11111111111111111111111111111111 +WHATSAPP_SWAGGER_USERNAME=admin +WHATSAPP_SWAGGER_PASSWORD=11111111111111111111111111111111 +``` + +{{< callout context="danger" title="Do Not Use Default API Keys or Passwords!" icon="outline/shield-check" >}} +Even if you're running WAHA on a private server and think the IP is unknown - it's +straightforward for attackers to find and exploit it to send spam or abuse your WhatsApp sessions. + +Always set strong, random values (see a guide below) for: + +- `WAHA_API_KEY` +- `WAHA_DASHBOARD_PASSWORD` +- `WHATSAPP_SWAGGER_PASSWORD` - you can the same as for `WAHA_DASHBOARD_PASSWORD` + +**👉 How to Generate and Hash Api-Key** +{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} +{{< /callout >}} + +{{< details "👉 How to Generate and Hash Api-Key" >}} +{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} +{{< /details >}} + +### Step 4: Pull Docker Images + +{{< tabs "download-docker-image" >}} + +{{< tab "➕ WAHA Plus" >}} +If you got the +[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) +, use the following commands: + +```bash { title="Pull Docker Images: WAHA Plus" } +docker login -u devlikeapro -p {KEY} +docker compose pull +docker logout +``` + +👉 Go to +[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) +to generate the command with the right version. +{{< /tab >}} + +{{< tab "WAHA Core" >}} + +1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha` +2. Run the command: + +```bash { title="Pull Docker Images: WAHA Core" } +docker compose pull +``` + +{{< /tab >}} + +{{< tab "WAHA (ARM)" >}} +If you're using **ARM CPU** (like Apple M1/M2, Raspberry Pi etc.). + +If you got the +[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}): + +1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha-plus:arm` +2. Run the commands: + +```bash { title="Pull Docker Images: WAHA Plus (ARM)" } +docker login -u devlikeapro -p {KEY} +docker pull devlikeapro/waha-plus:arm +docker logout +``` + +👉 Go to +[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) +to generate the command with the right version. + +--- + +If you want to run **WAHA Core**: + +1. In `docker-compose.yaml` change `image: devlikeapro/waha-plus` to `image: devlikeapro/waha:arm` +2. Run the commands: + +```bash { title="Pull Docker Images: WAHA Core (ARM)" } +docker compose pull +``` + +{{< /tab >}} + +{{< /tabs >}} + +### Step 5: Prepare ChatWoot Database + +```bash { title="Prepare ChatWoot Database" } +docker compose run --rm chatwoot bundle exec rails db:chatwoot_prepare +``` + +### Step 6: Start the Services + +```bash { title="Start Services" } +docker compose up -d +``` + +### Step 7: Access Your WAHA + +**Open** [**http://localhost:3000/dashboard**](http://localhost:3000/dashboard) with credentials: + +- User: `admin` +- Password: `11111111111111111111111111111111` + +**Add Api Key** to your worker: + +- Api-Key: `00000000000000000000000000000000` + +![](waha-dashboard-key.png) + +### Step 8: Access Your ChatWoot + +**Open** and **finish** the onboarding guide on [**http://localhost:3009/**](http://localhost:3009/) + +![](chatwoot-onboarding.png) + +## What is next? + +👉 Connect **WhatsApp** to **ChatWoot** in +[**WhatsApp + ChatWoot - Configuration Guide**]({{< relref "/blog/apps-chatwoot-2-config" >}}) + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} diff --git a/content/blog/apps-chatwoot-2-config/index.md b/content/blog/apps-chatwoot-2-config/index.md index d93d59dfb..ebe4c35ca 100644 --- a/content/blog/apps-chatwoot-2-config/index.md +++ b/content/blog/apps-chatwoot-2-config/index.md @@ -1,146 +1,162 @@ ---- -title: "WhatsApp + ChatWoot - Configuration Guide" -description: "WhatsApp + ChatWoot - Configuration Guide" -excerpt: "WhatsApp + ChatWoot - Configuration Guide" -date: 2025-07-10T08:48:45+00:00 -draft: false -images: [ "waha-chatwoot.png" ] -categories: [ "Apps", "ChatWoot" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: apps-chatwoot-config ---- - -## Overview -Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -After completing the configuration guide, you'll have: -- **WhatsApp** connected to [**ChatWoot Inbox**](https://www.chatwoot.com/hc/user-guide/articles/1677492191-adding-inboxes) using **WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! -- **WAHA** on [**http://localhost:3000**](http://localhost:3000) -- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) - -{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} - -## Requirements -At this point you should have: -- **WAHA** on [**http://localhost:3000**](http://localhost:3000) -- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) - -If you don't have it - kindly follow -[**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) - -{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} - -## Steps to Configure ChatWoot App -Now you're ready to setup **WhatsApp** to **ChatWoot** connection using -**WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! - -### Step 1: Create Session in WAHA -{{< tabs "waha-create-session" >}} -{{< tab "➕ WAHA Plus" >}} -- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) -- Create a new **default** session - - ⚠️ Hit **Create**, not **Create & Start** - -![](waha-create-default-session.png) -{{< /tab >}} - -{{< tab "WAHA Core" >}} -- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) -- Make sure there's **default** session - -![](waha-core-default-session.png) -{{< /tab >}} - -{{< /tabs >}} - -### Step 2: Copy Webhook URL in WAHA -- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) -- Click **Apps** -- Click **Add App** -- Copy **Webhook URL** -- Keep the tab open, we'll fill the fields - -![](waha-add-chatwoot-app.png) - -### Step 3: Create API Inbox in ChatWoot -- Go to **ChatWoot** [http://localhost:3009](http://localhost:3009) -- Open **Settings → Inboxes** -- Click **Add Inbox**, choose **API** -- Set fields as: - - **Name**: `WhatsApp - default` (name can be anything, doesn't have to follow that pattern) - - **Webhook URL**: `http://waha:3009/webhook/chatwoot/...` - Webhook URL from WAHA -- **Finish** creation guide - -![](chatwoot-create-inbox.png) - - -### Step 4: Collect ChatWoot Fields for WAHA -Now we'll need to find those fields in **ChatWoot** - -![](waha-chatwoot-fields.png) - -Check the screenshots below, but here's the path how you can find the values: -- **ChatWoot URL** - put `http://chatwoot:3009` - - 👉 Note that it's not `localhost`, it's `chatwoot`! -- **Account ID** - find it on **Settings → Account Settings** -- **Account Token** - find it on **(click on profile) → Profile settings** -- **Inbox ID** - find it on **Settings → Inboxes → (inspect browser url, the last part)** -- **Inbox Identifier** - find it on **Settings → Inboxes → {Inbox} → Configuration** - -![](chatwoot-account-id.png) -{{< img-sign text="Account ID: Settings → Account Settings" >}} - -![](chatwoot-account-token.png) -{{< img-sign text="Account Token: (click on profile) → Profile settings" >}} - -![](chatwoot-inbox-fields.png) -{{< img-sign text="Inbox ID, Inbox Identifier: Settings → Inboxes → {Inbox} → Configuration" >}} - -### Step 5: Save App Configuration in WAHA -Click **Save** after you finish all fields. - -![](waha-chatwoot-fields.png) - -### Step 6: Test Integration in ChatWoot -Now you can open a new conversation created by WAHA and send `status` or `help` to check that integration is working. - -- Go to **ChatWoot** [http://localhost:3009](http://localhost:3009) -- Find new `WhatsApp Integration (WAHA)` conversation -- Send `status` or `help` to test **WAHA <=> ChatWoot** connection - -![](chatwoot-send-status.png) - -### Step 7: Start Session and Scan QR in ChatWoot -{{< callout context="caution" title="Get your phone with WhatsApp App" icon="outline/shield-check" >}} -Now we're ready to connect your phone with WAHA and ChatWoot. - -For that you'll need to -[**Link a device**](https://faq.whatsapp.com/1317564962315842/?helpref=uf_share) on your mobile phone using QR code. - -Open **WhatsApp** on the phone and click on three dots at the right and **Linked Devices** and be ready to scan QR code -{{< /callout >}} - -- In `WhatsApp Integration (WAHA)` conversation **send** `start` message -- Open **WhatsApp** on your phone, click **More** (three dots), **Linked Devices**, **Link a device** -- **Scan QR** code from ChatWoot - -![](chatwoot-start-session.png) - -### Step 8: Test WhatsApp Integration in ChatWoot -Now let's see how ChatWoot WhatsApp integration works! - -- Send a message from **another** phone to **a connected** account using **WhatsApp** -- Send a response from **ChatWoot** - -![](chatwoot-test-whatsapp.png) -## What is next? - -👉 Setup **HTTPS** for **ChatWoot** in -[**WhatsApp + ChatWoot - HTTPS Guide**]({{< relref "/blog/apps-chatwoot-3-https" >}}) - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} +--- +title: "WhatsApp + ChatWoot - Configuration Guide" +description: "WhatsApp + ChatWoot - Configuration Guide" +excerpt: "WhatsApp + ChatWoot - Configuration Guide" +date: 2025-07-10T08:48:45+00:00 +draft: false +images: ["waha-chatwoot.png"] +categories: ["Apps", "ChatWoot"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: apps-chatwoot-config +--- + +## Overview + +Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +After completing the configuration guide, you'll have: + +- **WhatsApp** connected to [**ChatWoot Inbox**](https://www.chatwoot.com/hc/user-guide/articles/1677492191-adding-inboxes) using **WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! +- **WAHA** on [**http://localhost:3000**](http://localhost:3000) +- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) + +{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} + +## Requirements + +At this point you should have: + +- **WAHA** on [**http://localhost:3000**](http://localhost:3000) +- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) + +If you don't have it - kindly follow +[**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) + +{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} + +## Steps to Configure ChatWoot App + +Now you're ready to setup **WhatsApp** to **ChatWoot** connection using +**WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! + +### Step 1: Create Session in WAHA + +{{< tabs "waha-create-session" >}} +{{< tab "➕ WAHA Plus" >}} + +- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) +- Create a new **default** session + - ⚠️ Hit **Create**, not **Create & Start** + +![](waha-create-default-session.png) +{{< /tab >}} + +{{< tab "WAHA Core" >}} + +- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) +- Make sure there's **default** session + +![](waha-core-default-session.png) +{{< /tab >}} + +{{< /tabs >}} + +### Step 2: Copy Webhook URL in WAHA + +- Open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) +- Click **Apps** +- Click **Add App** +- Copy **Webhook URL** +- Keep the tab open, we'll fill the fields + +![](waha-add-chatwoot-app.png) + +### Step 3: Create API Inbox in ChatWoot + +- Go to **ChatWoot** [http://localhost:3009](http://localhost:3009) +- Open **Settings → Inboxes** +- Click **Add Inbox**, choose **API** +- Set fields as: + - **Name**: `WhatsApp - default` (name can be anything, doesn't have to follow that pattern) + - **Webhook URL**: `http://waha:3009/webhook/chatwoot/...` - Webhook URL from WAHA +- **Finish** creation guide + +![](chatwoot-create-inbox.png) + +### Step 4: Collect ChatWoot Fields for WAHA + +Now we'll need to find those fields in **ChatWoot** + +![](waha-chatwoot-fields.png) + +Check the screenshots below, but here's the path how you can find the values: + +- **ChatWoot URL** - put `http://chatwoot:3009` + - 👉 Note that it's not `localhost`, it's `chatwoot`! +- **Account ID** - find it on **Settings → Account Settings** +- **Account Token** - find it on **(click on profile) → Profile settings** +- **Inbox ID** - find it on **Settings → Inboxes → (inspect browser url, the last part)** +- **Inbox Identifier** - find it on **Settings → Inboxes → {Inbox} → Configuration** + +![](chatwoot-account-id.png) +{{< img-sign text="Account ID: Settings → Account Settings" >}} + +![](chatwoot-account-token.png) +{{< img-sign text="Account Token: (click on profile) → Profile settings" >}} + +![](chatwoot-inbox-fields.png) +{{< img-sign text="Inbox ID, Inbox Identifier: Settings → Inboxes → {Inbox} → Configuration" >}} + +### Step 5: Save App Configuration in WAHA + +Click **Save** after you finish all fields. + +![](waha-chatwoot-fields.png) + +### Step 6: Test Integration in ChatWoot + +Now you can open a new conversation created by WAHA and send `status` or `help` to check that integration is working. + +- Go to **ChatWoot** [http://localhost:3009](http://localhost:3009) +- Find new `WhatsApp Integration (WAHA)` conversation +- Send `status` or `help` to test **WAHA <=> ChatWoot** connection + +![](chatwoot-send-status.png) + +### Step 7: Start Session and Scan QR in ChatWoot + +{{< callout context="caution" title="Get your phone with WhatsApp App" icon="outline/shield-check" >}} +Now we're ready to connect your phone with WAHA and ChatWoot. + +For that you'll need to +[**Link a device**](https://faq.whatsapp.com/1317564962315842/?helpref=uf_share) on your mobile phone using QR code. + +Open **WhatsApp** on the phone and click on three dots at the right and **Linked Devices** and be ready to scan QR code +{{< /callout >}} + +- In `WhatsApp Integration (WAHA)` conversation **send** `start` message +- Open **WhatsApp** on your phone, click **More** (three dots), **Linked Devices**, **Link a device** +- **Scan QR** code from ChatWoot + +![](chatwoot-start-session.png) + +### Step 8: Test WhatsApp Integration in ChatWoot + +Now let's see how ChatWoot WhatsApp integration works! + +- Send a message from **another** phone to **a connected** account using **WhatsApp** +- Send a response from **ChatWoot** + +![](chatwoot-test-whatsapp.png) + +## What is next? + +👉 Setup **HTTPS** for **ChatWoot** in +[**WhatsApp + ChatWoot - HTTPS Guide**]({{< relref "/blog/apps-chatwoot-3-https" >}}) + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} diff --git a/content/blog/apps-chatwoot-3-https/index.md b/content/blog/apps-chatwoot-3-https/index.md index 0b4128f9d..c9caeedc6 100644 --- a/content/blog/apps-chatwoot-3-https/index.md +++ b/content/blog/apps-chatwoot-3-https/index.md @@ -1,231 +1,259 @@ ---- -title: "WhatsApp + ChatWoot - HTTPS Guide" -description: "WhatsApp + ChatWoot - HTTPS Guide" -excerpt: "WhatsApp + ChatWoot - HTTPS Guide" -date: 2025-07-07T08:48:45+00:00 -draft: false -images: [ "waha-chatwoot.png" ] -categories: [ "Apps", "ChatWoot" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: apps-chatwoot-3-https ---- - -## Overview -Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -After completing the configuration guide, you'll have: -- **WAHA** on `https://waha.{yourdomain}` -- **ChatWoot** on `https://chatwoot.{yourdomain}` - -{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} - -## Requirements -At this point you should have: -- **WAHA** on [**http://localhost:3000**](http://localhost:3000) -- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) -- **WhatsApp** connected to [**ChatWoot Inbox**](https://www.chatwoot.com/hc/user-guide/articles/1677492191-adding-inboxes) using **WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! - -If you don't have it - kindly follow **the previous guides in the series above ☝️**. - -{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} - -Now you're ready to publish your **ChatWoot** and **WAHA** instances on the internet! - -## Configure DNS -If you have VPS with a Public IP address, you need to configure DNS - add **A** records to point those domains: -1. `waha.` => `YOUR_VPS_IP_ADDRESS` -2. `chatwoot.` => `YOUR_VPS_IP_ADDRESS` - -## Configure HTTPS for ChatWoot -### Step 1: Install Nginx -```bash { title="Install Nginx" } -sudo apt-get install nginx -``` -### Step 2: Add Nginx Config -```bash { title="Add Nginx config" } -cd /etc/nginx/sites-enabled -nano chatwoot..conf -``` - -```yaml { title="chatwoot..conf" } -server { - server_name chatwoot.; - - # Point upstream to Chatwoot App Server - set $upstream 127.0.0.1:3009; - - # Nginx strips out underscore in headers by default - # Chatwoot relies on underscore in headers for API - # Make sure that the config is set to on. - underscores_in_headers on; - location /.well-known { - alias /var/www/ssl-proof/chatwoot/.well-known; - } - - location / { - proxy_pass_header Authorization; - proxy_pass http://$upstream; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Ssl on; # Optional - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_buffering off; - - client_max_body_size 0; - proxy_read_timeout 36000s; - proxy_redirect off; - } - listen 80; -} -``` -### Step 3: Verify and Reload Nginx Config -```bash { title="Verify and reload Nginx config" } -nginx -t -systemctl reload nginx -``` - -### Step 4: Run Let's Encrypt to configure SSL certificate -```bash { title="Run Let's Encrypt to configure SSL certificate" } -apt install certbot -apt-get install python3-certbot-nginx -mkdir -p /var/www/ssl-proof/chatwoot/.well-known -certbot --webroot -w /var/www/ssl-proof/chatwoot/ -d chatwoot. -i nginx -``` - -### Step 5: Update env variables -Update `FRONTEND_URL` in `.chatwoot.env` -```bash -nano .chatwoot.env -``` - -```env { title=".chatwoot.env" } -FRONTEND_URL=https://chatwoot. -``` - -Apply the changes: -```bash -docker compose up -d -``` - -### Step 6: Access your installation -- Open `https://chatwoot.` -- Make sure it's working - -### Step 7: Update ChatWoot URL in WAHA -- Open **WAHA** [http://localhost:3000](http://localhost:3000) -- Open **Apps** and **Edit App** -- Update **ChatWoot URL** from `http://chatwoot:3009` to `https://chatwoot.` -- Hit **Save** -- Open **ChatWoot** `https://chatwoot.` -- Send `status` message to **WhatsApp Integration (WAHA)** conversation to test **WAHA <=> ChatWoot** connection - -## Configure HTTPS for WAHA -It's **optional** step - follow it if you need access to -[**📊 Dashboard**]({{< relref "dashboard" >}}) from the internet. - -Otherwise - use ssh port forwarding to manage WAHA, it's usually enough. - -{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} - -### Step 1: Install Nginx -```bash { title="Install Nginx" } -sudo apt-get install nginx -``` - -### Step 2: Add Nginx config -```bash { title="Add Nginx config" } -cd /etc/nginx/sites-enabled -nano waha..conf -``` - -```yaml { title="waha..conf" } -server { - server_name waha.; - - # Point upstream to WAHA Server - set $upstream 127.0.0.1:3000; - - location /.well-known { - alias /var/www/ssl-proof/waha/.well-known; - } - - location / { - proxy_pass_header Authorization; - proxy_pass http://$upstream; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Ssl on; # Optional - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_buffering off; - - client_max_body_size 0; - proxy_read_timeout 36000s; - proxy_redirect off; - } - listen 80; -} -``` -### Step 3: Verify and reload Nginx config -```bash { title="Verify and reload Nginx config" } -nginx -t -systemctl reload nginx -``` - -### Step 4: Run Let's Encrypt to configure SSL certificate -```bash { title="Run Let's Encrypt to configure SSL certificate" } -apt install certbot -apt-get install python3-certbot-nginx -mkdir -p /var/www/ssl-proof/waha/.well-known -certbot --webroot -w /var/www/ssl-proof/waha/ -d waha. -i nginx -``` - -### Step 5: Update env variables -Update `WAHA_BASE_URL` in `.waha.env` -```bash -nano .waha.env -``` - -```env { title=".waha.env" } -WAHA_BASE_URL=https://waha. -``` - -Apply the changes: -```bash -docker compose up -d -``` - -### Step 6: Access your installation -- Open `https://waha.` -- Make sure it's working - -### Step 7: Update Webhook URL in ChatWoot -- Open **ChatWoot** `https://chatwoot.` -- Go to **Settings → Inboxes → {Inbox}** -- Update **Webhook URL** from `http://waha:3000/{WEBHOOKURL}` to `https://waha./{WEBHOOKURL}` -- Click **Save** -- Send `status` message to **WhatsApp Integration (WAHA)** conversation to test **WAHA <=> ChatWoot** connection - - -## What is next? - -[**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) -to see features available for **WhatsApp ChatWoot** integration using **WAHA**. - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} \ No newline at end of file +--- +title: "WhatsApp + ChatWoot - HTTPS Guide" +description: "WhatsApp + ChatWoot - HTTPS Guide" +excerpt: "WhatsApp + ChatWoot - HTTPS Guide" +date: 2025-07-07T08:48:45+00:00 +draft: false +images: ["waha-chatwoot.png"] +categories: ["Apps", "ChatWoot"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: apps-chatwoot-3-https +--- + +## Overview + +Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +After completing the configuration guide, you'll have: + +- **WAHA** on `https://waha.{yourdomain}` +- **ChatWoot** on `https://chatwoot.{yourdomain}` + +{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} + +## Requirements + +At this point you should have: + +- **WAHA** on [**http://localhost:3000**](http://localhost:3000) +- **ChatWoot** on [**http://localhost:3009**](http://localhost:3009) +- **WhatsApp** connected to [**ChatWoot Inbox**](https://www.chatwoot.com/hc/user-guide/articles/1677492191-adding-inboxes) using **WAHA** [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! + +If you don't have it - kindly follow **the previous guides in the series above ☝️**. + +{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} + +Now you're ready to publish your **ChatWoot** and **WAHA** instances on the internet! + +## Configure DNS + +If you have VPS with a Public IP address, you need to configure DNS - add **A** records to point those domains: + +1. `waha.` => `YOUR_VPS_IP_ADDRESS` +2. `chatwoot.` => `YOUR_VPS_IP_ADDRESS` + +## Configure HTTPS for ChatWoot + +### Step 1: Install Nginx + +```bash { title="Install Nginx" } +sudo apt-get install nginx +``` + +### Step 2: Add Nginx Config + +```bash { title="Add Nginx config" } +cd /etc/nginx/sites-enabled +nano chatwoot..conf +``` + +```yaml { title="chatwoot..conf" } +server { + server_name chatwoot.; + + # Point upstream to Chatwoot App Server + set $upstream 127.0.0.1:3009; + + # Nginx strips out underscore in headers by default + # Chatwoot relies on underscore in headers for API + # Make sure that the config is set to on. + underscores_in_headers on; + location /.well-known { + alias /var/www/ssl-proof/chatwoot/.well-known; + } + + location / { + proxy_pass_header Authorization; + proxy_pass http://$upstream; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Ssl on; # Optional + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_http_version 1.1; + proxy_buffering off; + + client_max_body_size 0; + proxy_read_timeout 36000s; + proxy_redirect off; + } + listen 80; +} +``` + +### Step 3: Verify and Reload Nginx Config + +```bash { title="Verify and reload Nginx config" } +nginx -t +systemctl reload nginx +``` + +### Step 4: Run Let's Encrypt to configure SSL certificate + +```bash { title="Run Let's Encrypt to configure SSL certificate" } +apt install certbot +apt-get install python3-certbot-nginx +mkdir -p /var/www/ssl-proof/chatwoot/.well-known +certbot --webroot -w /var/www/ssl-proof/chatwoot/ -d chatwoot. -i nginx +``` + +### Step 5: Update env variables + +Update `FRONTEND_URL` in `.chatwoot.env` + +```bash +nano .chatwoot.env +``` + +```env { title=".chatwoot.env" } +FRONTEND_URL=https://chatwoot. +``` + +Apply the changes: + +```bash +docker compose up -d +``` + +### Step 6: Access your installation + +- Open `https://chatwoot.` +- Make sure it's working + +### Step 7: Update ChatWoot URL in WAHA + +- Open **WAHA** [http://localhost:3000](http://localhost:3000) +- Open **Apps** and **Edit App** +- Update **ChatWoot URL** from `http://chatwoot:3009` to `https://chatwoot.` +- Hit **Save** +- Open **ChatWoot** `https://chatwoot.` +- Send `status` message to **WhatsApp Integration (WAHA)** conversation to test **WAHA <=> ChatWoot** connection + +## Configure HTTPS for WAHA + +It's **optional** step - follow it if you need access to +[**📊 Dashboard**]({{< relref "dashboard" >}}) from the internet. + +Otherwise - use ssh port forwarding to manage WAHA, it's usually enough. + +{{< include file="content/blog/apps-chatwoot-1-install/-ssh-port-forwarding.md" >}} + +### Step 1: Install Nginx + +```bash { title="Install Nginx" } +sudo apt-get install nginx +``` + +### Step 2: Add Nginx config + +```bash { title="Add Nginx config" } +cd /etc/nginx/sites-enabled +nano waha..conf +``` + +```yaml { title="waha..conf" } +server { + server_name waha.; + + # Point upstream to WAHA Server + set $upstream 127.0.0.1:3000; + + location /.well-known { + alias /var/www/ssl-proof/waha/.well-known; + } + + location / { + proxy_pass_header Authorization; + proxy_pass http://$upstream; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Ssl on; # Optional + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_http_version 1.1; + proxy_buffering off; + + client_max_body_size 0; + proxy_read_timeout 36000s; + proxy_redirect off; + } + listen 80; +} +``` + +### Step 3: Verify and reload Nginx config + +```bash { title="Verify and reload Nginx config" } +nginx -t +systemctl reload nginx +``` + +### Step 4: Run Let's Encrypt to configure SSL certificate + +```bash { title="Run Let's Encrypt to configure SSL certificate" } +apt install certbot +apt-get install python3-certbot-nginx +mkdir -p /var/www/ssl-proof/waha/.well-known +certbot --webroot -w /var/www/ssl-proof/waha/ -d waha. -i nginx +``` + +### Step 5: Update env variables + +Update `WAHA_BASE_URL` in `.waha.env` + +```bash +nano .waha.env +``` + +```env { title=".waha.env" } +WAHA_BASE_URL=https://waha. +``` + +Apply the changes: + +```bash +docker compose up -d +``` + +### Step 6: Access your installation + +- Open `https://waha.` +- Make sure it's working + +### Step 7: Update Webhook URL in ChatWoot + +- Open **ChatWoot** `https://chatwoot.` +- Go to **Settings → Inboxes → {Inbox}** +- Update **Webhook URL** from `http://waha:3000/{WEBHOOKURL}` to `https://waha./{WEBHOOKURL}` +- Click **Save** +- Send `status` message to **WhatsApp Integration (WAHA)** conversation to test **WAHA <=> ChatWoot** connection + +## What is next? + +[**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) +to see features available for **WhatsApp ChatWoot** integration using **WAHA**. + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} diff --git a/content/blog/apps-chatwoot-4-how-it-works/index.md b/content/blog/apps-chatwoot-4-how-it-works/index.md index 72ff8ee7f..3fcf3db75 100644 --- a/content/blog/apps-chatwoot-4-how-it-works/index.md +++ b/content/blog/apps-chatwoot-4-how-it-works/index.md @@ -1,33 +1,34 @@ ---- -title: "WhatsApp + ChatWoot - How It Works" -description: "WhatsApp + ChatWoot - How It Works" -excerpt: "WhatsApp + ChatWoot - How It Works" -date: 2025-07-06T08:48:45+00:00 -draft: false -images: [ "waha-chatwoot.png" ] -categories: [ "Apps", "ChatWoot" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: apps-chatwoot-4-how-it-works ---- - -## Overview -Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! - -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -## How it works - -{{< include file="content/docs/apps/about/-how-it-works.md" >}} - -## Error Handling -In case of any errors, WAHA retries a few times and then gives detailed information about the error: - -![Error Reports and Retries](screenshots/error-reports-and-retries.png) - -You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: - -![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) - +--- +title: "WhatsApp + ChatWoot - How It Works" +description: "WhatsApp + ChatWoot - How It Works" +excerpt: "WhatsApp + ChatWoot - How It Works" +date: 2025-07-06T08:48:45+00:00 +draft: false +images: ["waha-chatwoot.png"] +categories: ["Apps", "ChatWoot"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: apps-chatwoot-4-how-it-works +--- + +## Overview + +Complete guide to install and set up production-ready **WAHA** and **Chatwoot** instances on your own infrastructure! + +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +## How it works + +{{< include file="content/docs/apps/about/-how-it-works.md" >}} + +## Error Handling + +In case of any errors, WAHA retries a few times and then gives detailed information about the error: + +![Error Reports and Retries](screenshots/error-reports-and-retries.png) + +You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: + +![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) diff --git a/content/blog/crypto-how-to/index.md b/content/blog/crypto-how-to/index.md index 595dcca31..d43efa584 100644 --- a/content/blog/crypto-how-to/index.md +++ b/content/blog/crypto-how-to/index.md @@ -1,107 +1,120 @@ ---- -title: "How to support WAHA using Crypto" -description: "⚡50% OFF Yearly Crypto Offer!⚡" -excerpt: "Step-by-step guide how to support WAHA using Crypto and get WAHA Plus or PRO versions." -date: 2024-07-01T08:48:45+00:00 -draft: false -images: ["tether-usdt-logo.png"] -categories: ["Donations"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -In this article, we're going to cover different techniques for those who not familiar with crypto payments how you can still support the project -and get [WAHA Plus and WAHA PRO](/support-us). - -If you have any questions during this journey, kindly contact us at -crypto@devlike.pro, -we'll find a way to help you! - -## Get Crypto Address and Amount -### Step 1 - Login to WAHA Portal - -First, go to -WAHA Patron Portal -> -and **Login with Email** or any other available options. -![alt](crypto-0-login.png) - -### Step 2 - Get payment link -- Go to -Donate page, -- Select **Support with Crypto** -- Click on desired tier (we kindly suggest using **YEARly** tiers due to lower fees) -![alt](crypto-1-portal.png) - -### Step 3 - Select USDT and TRC -On payment page, select **USDT** currency and **TRC** network -![alt](crypto-2-usdt-trc.png) - -### Step 4 - Copy Address and Amount -Those two things we'll need later soon, so kindly copy or remember it. -- **Address**: in `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg` format -- **Amount to pay**: `$111.4` - -⚠️ Few things to keep in mind: -- **Do not close this page till the full process is finished** - - If you closed it - kindly check your email and open it from there (we always send the link to email). -- **If the payment link expired (after 24 hours)** - go to [**WAHA Patron Portal ->**](https://portal.devlike.pro) and get a new one. DO NOT USE EXPIRED **Address**! -![alt](crypto-3-address.png) - - -## Option 1 - Buy Crypto using CryptoCloud -You can buy crypto using. **No wallet required**, it'll be sent directly to payment link above! -CryptoCloud ->. - -Go to the page and enter: -- **You receive** section - select **USDT TRC-20** currency -- **You receive** section - set `111.4` (or different amount) -- **You send** - choose appropriate YOUR currency - -![alt](crypto-4-buy-crypto.png) - -- Click **Continue** and select available operator. -- Click **Continue** and put **Address** copied from the previous section (the link from WAHA Patron Portal, in `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg` format) -![alt](crypto-5-put-address.png) - -- Click **Proceed to Payment** and go to the operator payment page - -On the operator page **validate Address and Amount** -![alt](crypto-6-validate-amount.png) - -**Finish the payment on operator page** using regular Credit or Debit card! 🎉 - -## Option 2 - Paying using Binance -If you're new to using Binance and want to pay using USDT TRC-20, but are unsure where to start, don't worry - we've got you covered with this step-by-step guide! - -### Step 1: Setting Up Your Binance Account -- If you don't already have a Binance account, you'll need to sign up for one. Visit [Binance](https://www.binance.com/) and follow the instructions to create an account. -- Make sure to complete the necessary verification steps as required by Binance. - -### Step 2: Acquiring USDT TRC-20 -In order to pay using **USDT TRC-20**, you will need to acquire some first. You can do this by: -- Buying **USDT TRC-20** on Binance using fiat currency or other cryptocurrencies. -- Using **Binance's peer-to-peer (P2P)** trading platform to buy **USDT TRC-20** from other users. - -For detailed instructions on how to buy USDT on Binance or using P2P, you can refer to this [guide on buying cryptocurrency on Binance](https://www.binance.com/en/support/faq). - -### Step 3: Paying with Binance and USDT TRC-20 -Once you have the USDT TRC-20 in your Binance wallet, and you have the recipient's address and the amount you need to pay, follow these steps to make the payment: -1. Log in to your Binance account. -2. Go to the wallet section and click on the "Withdraw" option. -3. Select USDT TRC-20. -4. Enter the recipient's wallet address in the designated field - **Address* you copied before, in format `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg`. -5. Input the amount of USDT TRC-20 you wish to send. -6. Double-check the address and amount to ensure accuracy. -7. Click on the "Withdraw" button to initiate the payment. - -And there you have it! You've successfully made a payment using Binance and USDT TRC-20. Remember to always double-check the recipient's address to avoid any errors in transactions. - -If you encounter any difficulties or have further questions, don't hesitate to reach out to Binance's customer support for assistance. - - -## Option 3 - Paying using Bit by -The same steps as for Binance applied to [BitBy](https://www.bybit.com/en/) platform, just make sure you're using BitBy app and web site. - -It has additional payment method for countries that is under the sanctions. +--- +title: "How to support WAHA using Crypto" +description: "⚡50% OFF Yearly Crypto Offer!⚡" +excerpt: "Step-by-step guide how to support WAHA using Crypto and get WAHA Plus or PRO versions." +date: 2024-07-01T08:48:45+00:00 +draft: false +images: ["tether-usdt-logo.png"] +categories: ["Donations"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +In this article, we're going to cover different techniques for those who not familiar with crypto payments how you can still support the project +and get [WAHA Plus and WAHA PRO](/support-us). + +If you have any questions during this journey, kindly contact us at +crypto@devlike.pro, +we'll find a way to help you! + +## Get Crypto Address and Amount + +### Step 1 - Login to WAHA Portal + +First, go to +WAHA Patron Portal -> +and **Login with Email** or any other available options. +![alt](crypto-0-login.png) + +### Step 2 - Get payment link + +- Go to + Donate page, +- Select **Support with Crypto** +- Click on desired tier (we kindly suggest using **YEARly** tiers due to lower fees) + ![alt](crypto-1-portal.png) + +### Step 3 - Select USDT and TRC + +On payment page, select **USDT** currency and **TRC** network +![alt](crypto-2-usdt-trc.png) + +### Step 4 - Copy Address and Amount + +Those two things we'll need later soon, so kindly copy or remember it. + +- **Address**: in `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg` format +- **Amount to pay**: `$111.4` + +⚠️ Few things to keep in mind: + +- **Do not close this page till the full process is finished** + - If you closed it - kindly check your email and open it from there (we always send the link to email). +- **If the payment link expired (after 24 hours)** - go to [**WAHA Patron Portal ->**](https://portal.devlike.pro) and get a new one. DO NOT USE EXPIRED **Address**! + ![alt](crypto-3-address.png) + +## Option 1 - Buy Crypto using CryptoCloud + +You can buy crypto using. **No wallet required**, it'll be sent directly to payment link above! +CryptoCloud ->. + +Go to the page and enter: + +- **You receive** section - select **USDT TRC-20** currency +- **You receive** section - set `111.4` (or different amount) +- **You send** - choose appropriate YOUR currency + +![alt](crypto-4-buy-crypto.png) + +- Click **Continue** and select available operator. +- Click **Continue** and put **Address** copied from the previous section (the link from WAHA Patron Portal, in `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg` format) + ![alt](crypto-5-put-address.png) + +- Click **Proceed to Payment** and go to the operator payment page + +On the operator page **validate Address and Amount** +![alt](crypto-6-validate-amount.png) + +**Finish the payment on operator page** using regular Credit or Debit card! 🎉 + +## Option 2 - Paying using Binance + +If you're new to using Binance and want to pay using USDT TRC-20, but are unsure where to start, don't worry - we've got you covered with this step-by-step guide! + +### Step 1: Setting Up Your Binance Account + +- If you don't already have a Binance account, you'll need to sign up for one. Visit [Binance](https://www.binance.com/) and follow the instructions to create an account. +- Make sure to complete the necessary verification steps as required by Binance. + +### Step 2: Acquiring USDT TRC-20 + +In order to pay using **USDT TRC-20**, you will need to acquire some first. You can do this by: + +- Buying **USDT TRC-20** on Binance using fiat currency or other cryptocurrencies. +- Using **Binance's peer-to-peer (P2P)** trading platform to buy **USDT TRC-20** from other users. + +For detailed instructions on how to buy USDT on Binance or using P2P, you can refer to this [guide on buying cryptocurrency on Binance](https://www.binance.com/en/support/faq). + +### Step 3: Paying with Binance and USDT TRC-20 + +Once you have the USDT TRC-20 in your Binance wallet, and you have the recipient's address and the amount you need to pay, follow these steps to make the payment: + +1. Log in to your Binance account. +2. Go to the wallet section and click on the "Withdraw" option. +3. Select USDT TRC-20. +4. Enter the recipient's wallet address in the designated field - \*_Address_ you copied before, in format `TQHuXAR8KxhBs59pa59AK7NeUbuSH9vTkg`. +5. Input the amount of USDT TRC-20 you wish to send. +6. Double-check the address and amount to ensure accuracy. +7. Click on the "Withdraw" button to initiate the payment. + +And there you have it! You've successfully made a payment using Binance and USDT TRC-20. Remember to always double-check the recipient's address to avoid any errors in transactions. + +If you encounter any difficulties or have further questions, don't hesitate to reach out to Binance's customer support for assistance. + +## Option 3 - Paying using Bit by + +The same steps as for Binance applied to [BitBy](https://www.bybit.com/en/) platform, just make sure you're using BitBy app and web site. + +It has additional payment method for countries that is under the sanctions. diff --git a/content/blog/how-to-send-messages-to-channels/index.md b/content/blog/how-to-send-messages-to-channels/index.md index fe307a202..f656f6c3d 100644 --- a/content/blog/how-to-send-messages-to-channels/index.md +++ b/content/blog/how-to-send-messages-to-channels/index.md @@ -1,175 +1,183 @@ ---- -title: "How to send a post to WhatsApp Channel via API" -description: "How to send a post to WhatsApp Channel via API - Step By Step Guide" -excerpt: "How to send a post to WhatsApp Channel via API - Step By Step Guide" -date: 2024-07-16T08:48:45+00:00 -draft: false -images: [ "whatsapp-channels.png" ] -categories: [ "Tips" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -toc: true ---- - - -[WAHA](/), Free Self-Hosted WhatsApp API, supports -[**WhatsApp Channels**]({{< relref "/whatsapp-channels" >}}) -, a brand-new feature introduced by WhatsApp. -It is a one-way broadcast tool that allows administrators to send various content types such as text, photos, videos, -and polls. -Users receive push notifications from the channel, similar to a private message. - -In this article, we give you a **Step-By-Step guide how to send messages to WhatsApp Channels** using -[**WAHA**](/) - free, self-hosted WhatsApp API! - -We'll install it on **your own server**, so no suspicious services have access to your WhatsApp account. - -
- logo -
- -## Step 0. Requirements - -WAHA works on top of **Docker**, that's the only think you'll need! -
- logo -
- -👉 Please follow the - -Docker official guides to install it on Linux, Windows, and macOS - - -{{< details "Why Docker?" >}} -Docker makes it easy to ship all-in-one solution with the runtime and dependencies. You don't have to worry about -language-specific libraries or chrome installation. - -Also, Docker makes installation and update processes so simple, just one command! -{{< /details >}} - -## Step 1. Run WAHA -After you installed Docker - you're ready to run WAHA! - -```bash -docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -It may take time to download the image, depending on your internet speed. - -If you're using **ARM** processor (like **Apple M1/M2**, **Raspberry Pi**) run the following commands instead: -```bash -# Download the image -docker pull devlikeapro/waha:arm -# Rename it, so you can use devlikeapro/waha image in other place -docker tag devlikeapro/waha:arm devlikeapro/waha -# Run the same command! -docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -👉 Now, open [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) at - -http://localhost:3000/dashboard - - -You'll see WAHA Dashboard: -![alt](dashboard.png) - - -## Step 2. Run session -Now you start **default** session (current status should be `STOPPED`). - -You can leave all configuration parameters by default: -![alt](dashboard-start-session.png) - -## Step 3. Scan QR -Wait until the session status is `SCAN_QR` and click on "camera" icon: -
-![alt](dashboard-qr.png) -👉 If instead of QR you see **Click to reload QR** - **stop** the session and **start** it again. - -
- -You'll see QR code from WhatsApp Web app, now get **your phone** with installed WhatsApp application and **scan the QR**: -![alt](whatsapp-link-devices.jpeg) - -The session status will move to `WORKING` status: -![alt](dashboard-working.png) - -## Step 4. Get Channel ID -One step before you can send a message to you Channel - you need to get Channel ID in format `123123123@newsletter` -to know where to send a message. - -You can just execute the following curl command: -```bash -curl -X 'GET' \ - 'http://localhost:3000/api/default/channels?role=OWNER' \ - -H 'accept: application/json' -``` - -In the response you'll see all channels, choose one and copy `id`: - -```json -[ - { - "id": "111111111111111111@newsletter", // <========= copy that - "name": "Channel Name", - "role": "OWNER", - ... - } -] -``` - - -As alternative to `curl`, you can use [WAHA Swagger]({{< relref "/docs/how-to/swagger" >}}) for that, open it at - -http://localhost:3000/#/channels -, scroll down to **Channels** section. - -- Find `GET /api/{session}/channels` endpoint and expand it -- Click **Try it out** -- Choose `role=OWNER` if you have your own channels or `role=ADMIN` if you're admin in the channel (you can not send messages if you're `SUBSCRIBER` in the channel) -- Click **Execute** -![alt](swagger-channels-list.png) - - -## Step 5. Send a message to WhatsApp Channel -Now we're ready to send first messages to WhatsApp Channel via API! - -Replace `123123@newsletter` with **your newsletter id**, like `29847512@newsletter` in the bellow command: -```bash -curl -X 'POST' \ - 'http://localhost:3000/api/sendText' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "chatId": "123123123123@newsletter", - "text": "Hi there!", - "session": "default" -}' -``` - -As alternative to `curl`, you can use [WAHA Swagger]({{< relref "/docs/how-to/swagger" >}}) for that, open it at - -http://localhost:3000/#/chatting -, scroll down to **chatting** section. -- Find `POST /api/sendText` endpoint and expand it -- Click **Try it out** -- Replace `123123@newsletter` with **your** newsletter id, like `29847512@newsletter` in the bellow command -- Click **Execute** -![alt](swagger-send-text.png) - -## What is next? -🎉 You've sent the first message to WhatsApp Channel using WhatsApp API! 🎉 - -Here's what you can lear next: -- Check the full [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) documentation -- Learn more about how to send images [**📤 Send messages**]({{< relref "/docs/how-to/send-messages" >}}) to WhatsApp Channel via API -- Learn how to [**📥 Receive messages**]({{< relref "/docs/how-to/receive-messages" >}}) from WhatsApp Channels via [**🔄 Webhooks**]({{< relref "/docs/how-to/events" >}}) +--- +title: "How to send a post to WhatsApp Channel via API" +description: "How to send a post to WhatsApp Channel via API - Step By Step Guide" +excerpt: "How to send a post to WhatsApp Channel via API - Step By Step Guide" +date: 2024-07-16T08:48:45+00:00 +draft: false +images: ["whatsapp-channels.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +toc: true +--- + +[WAHA](/), Free Self-Hosted WhatsApp API, supports +[**WhatsApp Channels**]({{< relref "/whatsapp-channels" >}}) +, a brand-new feature introduced by WhatsApp. +It is a one-way broadcast tool that allows administrators to send various content types such as text, photos, videos, +and polls. +Users receive push notifications from the channel, similar to a private message. + +In this article, we give you a **Step-By-Step guide how to send messages to WhatsApp Channels** using +[**WAHA**](/) - free, self-hosted WhatsApp API! + +We'll install it on **your own server**, so no suspicious services have access to your WhatsApp account. + +
+ logo +
+ +## Step 0. Requirements + +WAHA works on top of **Docker**, that's the only think you'll need! + +
+ logo +
+ +👉 Please follow the + +Docker official guides to install it on Linux, Windows, and macOS + + +{{< details "Why Docker?" >}} +Docker makes it easy to ship all-in-one solution with the runtime and dependencies. You don't have to worry about +language-specific libraries or chrome installation. + +Also, Docker makes installation and update processes so simple, just one command! +{{< /details >}} + +## Step 1. Run WAHA + +After you installed Docker - you're ready to run WAHA! + +```bash +docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +It may take time to download the image, depending on your internet speed. + +If you're using **ARM** processor (like **Apple M1/M2**, **Raspberry Pi**) run the following commands instead: + +```bash +# Download the image +docker pull devlikeapro/waha:arm +# Rename it, so you can use devlikeapro/waha image in other place +docker tag devlikeapro/waha:arm devlikeapro/waha +# Run the same command! +docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +👉 Now, open [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) at + +http://localhost:3000/dashboard + + +You'll see WAHA Dashboard: +![alt](dashboard.png) + +## Step 2. Run session + +Now you start **default** session (current status should be `STOPPED`). + +You can leave all configuration parameters by default: +![alt](dashboard-start-session.png) + +## Step 3. Scan QR + +Wait until the session status is `SCAN_QR` and click on "camera" icon: +
+![alt](dashboard-qr.png) +👉 If instead of QR you see **Click to reload QR** - **stop** the session and **start** it again. + +
+ +You'll see QR code from WhatsApp Web app, now get **your phone** with installed WhatsApp application and **scan the QR**: +![alt](whatsapp-link-devices.jpeg) + +The session status will move to `WORKING` status: +![alt](dashboard-working.png) + +## Step 4. Get Channel ID + +One step before you can send a message to you Channel - you need to get Channel ID in format `123123123@newsletter` +to know where to send a message. + +You can just execute the following curl command: + +```bash +curl -X 'GET' \ + 'http://localhost:3000/api/default/channels?role=OWNER' \ + -H 'accept: application/json' +``` + +In the response you'll see all channels, choose one and copy `id`: + +```json +[ + { + "id": "111111111111111111@newsletter", // <========= copy that + "name": "Channel Name", + "role": "OWNER", + ... + } +] +``` + +As alternative to `curl`, you can use [WAHA Swagger]({{< relref "/docs/how-to/swagger" >}}) for that, open it at + +http://localhost:3000/#/channels +, scroll down to **Channels** section. + +- Find `GET /api/{session}/channels` endpoint and expand it +- Click **Try it out** +- Choose `role=OWNER` if you have your own channels or `role=ADMIN` if you're admin in the channel (you can not send messages if you're `SUBSCRIBER` in the channel) +- Click **Execute** + ![alt](swagger-channels-list.png) + +## Step 5. Send a message to WhatsApp Channel + +Now we're ready to send first messages to WhatsApp Channel via API! + +Replace `123123@newsletter` with **your newsletter id**, like `29847512@newsletter` in the bellow command: + +```bash +curl -X 'POST' \ + 'http://localhost:3000/api/sendText' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "chatId": "123123123123@newsletter", + "text": "Hi there!", + "session": "default" +}' +``` + +As alternative to `curl`, you can use [WAHA Swagger]({{< relref "/docs/how-to/swagger" >}}) for that, open it at + +http://localhost:3000/#/chatting +, scroll down to **chatting** section. + +- Find `POST /api/sendText` endpoint and expand it +- Click **Try it out** +- Replace `123123@newsletter` with **your** newsletter id, like `29847512@newsletter` in the bellow command +- Click **Execute** + ![alt](swagger-send-text.png) + +## What is next? + +🎉 You've sent the first message to WhatsApp Channel using WhatsApp API! 🎉 + +Here's what you can lear next: + +- Check the full [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) documentation +- Learn more about how to send images [**📤 Send messages**]({{< relref "/docs/how-to/send-messages" >}}) to WhatsApp Channel via API +- Learn how to [**📥 Receive messages**]({{< relref "/docs/how-to/receive-messages" >}}) from WhatsApp Channels via [**🔄 Webhooks**]({{< relref "/docs/how-to/events" >}}) diff --git a/content/blog/security-alert/index.md b/content/blog/security-alert/index.md index f580f0b86..fbb5bf25a 100644 --- a/content/blog/security-alert/index.md +++ b/content/blog/security-alert/index.md @@ -1,102 +1,101 @@ ---- -title: "🚨 WAHA Security Alert" -description: "🚨 WAHA Security Alert - check your API Key if your API is public!" -excerpt: "🚨 WAHA Security Alert - check your API Key if your API is public!" -date: 2025-04-29T08:48:45+00:00 -draft: false -images: ["security-alert.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: security-alert ---------------- - -## 🚨 WAHA Security Alert - -We’ve recently seen a disturbing trend: users running WAHA with the **API publicly exposed** and **without any form of protection**. - -Unfortunately, a few of them learned the hard way — their sessions were compromised, and their accounts got hacked. - ---- - -### ❗ What Happened? - -Some WAHA users deployed the API and made it accessible over the internet — **but forgot to secure it**. No API keys. No reverse proxies. Just a raw, open API ready-to-take commands from anyone who knew the endpoint. - -It didn’t take long for bots and malicious actors to find those ports. Once they did — they used sessions, hijacked WhatsApp accounts, sent spam messages. -
-{{< img lqip="21x webp q20" src="whatsapp-spam.png" alt="WhatsApp Spam" >}} -
-
- -⚠️ **This IS NOT just a theoretical risk**. We had multiple cases this month alone. If your API is open, **you are exposed**. - - -### 👥 Who Is Affected? - -This vulnerability affects **anyone who is running WAHA or WAHA Plus** and: - -* Exposes the `/api` port directly to the internet, -* Has **no API key** set in the `.env` or Docker environment, -* Don’t use HTTPS or any firewall/reverse proxy to restrict access. - -This includes Docker deployments, VPS installs, even cloud setups that skip security steps. - - -### 🛠️ How to Fix It - -{{< callout context="caution" title="Do not expose WhatsApp API on public networks!" icon="outline/shield-check" >}} -- Use at **least 64 symbols random string** as `WHATSAPP_API_KEY` string that contains letters (a-z, A-Z) and numbers (1-9) -- Read more [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) -{{< /callout >}} - -Here's how you can immediately protect your setup: - -1. **Use API Key Authentication** - WAHA requires an `api_key` for all endpoints. Make sure you set and enforce it in your environment: - -```bash -WHATSAPP_API_KEY=your_strong_key_here -``` - -2. **Don’t expose your API directly to the internet!** - Keep it behind: - - * A VPN - * A reverse proxy with authentication - * A firewall that limits access to trusted IPs - -3. **Enable HTTPS** - Use Let's Encrypt or self-signed certificates to ensure traffic is encrypted. - - -### ❓ FAQ - -#### 🔒 Changing ports will not save you! - -Obscuring your API behind a “random” port like `39823`? Doesn’t matter. Bots scan all ports. If it’s open and unprotected — they’ll find it. - -#### 🧱 I don't have WAHA Plus, how can I still be secure? - -You still have options: - -* **Do not expose the API port to the internet** - Only bind the container to `localhost` or your internal network. - -* **Use third-party software to protect your API** - Tools like [Ngrok](/blog/waha-ngrok) can tunnel securely, and you can wrap requests with basic auth or tokens. - -* **Use a firewall to restrict access** - Restrict incoming traffic to your trusted IPs only. Tools like `ufw` or `iptables` can help with that. - - -### 🚨 Final Word - -Leaving your API exposed is like leaving your house door wide open with a sign saying “not using locks.” WAHA gives you the tools to be secure. **Use them**. - - ----- - -**Stay safe 🛡️** +--- +title: "🚨 WAHA Security Alert" +description: "🚨 WAHA Security Alert - check your API Key if your API is public!" +excerpt: "🚨 WAHA Security Alert - check your API Key if your API is public!" +date: 2025-04-29T08:48:45+00:00 +draft: false +images: ["security-alert.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: security-alert +--- + +--- + +## 🚨 WAHA Security Alert + +We’ve recently seen a disturbing trend: users running WAHA with the **API publicly exposed** and **without any form of protection**. + +Unfortunately, a few of them learned the hard way — their sessions were compromised, and their accounts got hacked. + +--- + +### ❗ What Happened? + +Some WAHA users deployed the API and made it accessible over the internet — **but forgot to secure it**. No API keys. No reverse proxies. Just a raw, open API ready-to-take commands from anyone who knew the endpoint. + +It didn’t take long for bots and malicious actors to find those ports. Once they did — they used sessions, hijacked WhatsApp accounts, sent spam messages. + +
+{{< img lqip="21x webp q20" src="whatsapp-spam.png" alt="WhatsApp Spam" >}} +
+
+ +⚠️ **This IS NOT just a theoretical risk**. We had multiple cases this month alone. If your API is open, **you are exposed**. + +### 👥 Who Is Affected? + +This vulnerability affects **anyone who is running WAHA or WAHA Plus** and: + +- Exposes the `/api` port directly to the internet, +- Has **no API key** set in the `.env` or Docker environment, +- Don’t use HTTPS or any firewall/reverse proxy to restrict access. + +This includes Docker deployments, VPS installs, even cloud setups that skip security steps. + +### 🛠️ How to Fix It + +{{< callout context="caution" title="Do not expose WhatsApp API on public networks!" icon="outline/shield-check" >}} + +- Use at **least 64 symbols random string** as `WHATSAPP_API_KEY` string that contains letters (a-z, A-Z) and numbers (1-9) +- Read more [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) + {{< /callout >}} + +Here's how you can immediately protect your setup: + +1. **Use API Key Authentication** + WAHA requires an `api_key` for all endpoints. Make sure you set and enforce it in your environment: + +```bash +WHATSAPP_API_KEY=your_strong_key_here +``` + +2. **Don’t expose your API directly to the internet!** + Keep it behind: + + - A VPN + - A reverse proxy with authentication + - A firewall that limits access to trusted IPs + +3. **Enable HTTPS** + Use Let's Encrypt or self-signed certificates to ensure traffic is encrypted. + +### ❓ FAQ + +#### 🔒 Changing ports will not save you! + +Obscuring your API behind a “random” port like `39823`? Doesn’t matter. Bots scan all ports. If it’s open and unprotected — they’ll find it. + +#### 🧱 I don't have WAHA Plus, how can I still be secure? + +You still have options: + +- **Do not expose the API port to the internet** + Only bind the container to `localhost` or your internal network. + +- **Use third-party software to protect your API** + Tools like [Ngrok](/blog/waha-ngrok) can tunnel securely, and you can wrap requests with basic auth or tokens. + +- **Use a firewall to restrict access** + Restrict incoming traffic to your trusted IPs only. Tools like `ufw` or `iptables` can help with that. + +### 🚨 Final Word + +Leaving your API exposed is like leaving your house door wide open with a sign saying “not using locks.” WAHA gives you the tools to be secure. **Use them**. + +--- + +**Stay safe 🛡️** diff --git a/content/blog/waha-2024-10/index.md b/content/blog/waha-2024-10/index.md index 198548dd1..2a03f869f 100644 --- a/content/blog/waha-2024-10/index.md +++ b/content/blog/waha-2024-10/index.md @@ -1,97 +1,101 @@ ---- -title: "WAHA 2024.10" -description: "WAHA 2024.10 - WAHA Core - Receive Media, n8n Low Code Integration, TypeBot Integration, ChatWoot Integration, Workflow Templates, Stability fixes" -excerpt: "WAHA 2024.10 - WAHA Core - Receive Media, n8n Low Code Integration, TypeBot Integration, ChatWoot Integration, Workflow Templates, Stability fixes" -date: 2024-09-30T08:48:45+00:00 -draft: false -images: ["WAHA 2024.10.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2024-10 ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.10**]({{< relref "/docs/overview/changelog#202410" >}}) 🎉 - -## WAHA Core - Receive Media - -We published [**📥 Receive messages** ]({{}}) -in free **WAHA Core** version, so you can receive media files in your WhatsApp API for free! - -We'll continue to publish features from -[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) -to WAHA Core, so you can use them for free! - -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "body": "Check this out (caption for the media)!", - "from": "11111111111@c.us", - "hasMedia": true, - "media": { - "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", - "mimetype": "image/jpeg", - "filename": null - } - } -} -``` - -## n8n Low Code Integration - -

- -

- -Meat the new **WAHA** integration with **n8n**! - -You can build your WhatsApp automation with using n8n and WAHA in pair! - -For that we've built [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha/) -directly from our [Swagger](/swagger) specification, so all available API calls are available in n8n. - -Install it on your n8n instance and start building your first workflow: -``` -@devlikeapro/n8n-nodes-waha -``` - -Read more about -[**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) - -### TypeBot Integration -

- -

- -Using the n8n workflow you can integrate **TypeBot** with **WAHA**! - -👉 Checkout out [**🔌 TypeBot Integration**]({{< relref "/docs/integrations/typebot" >}}) - -### ChatWoot Integration -

- -

- -Using the n8n workflow you can integrate **ChatWoot** with **WAHA**! - -👉 Checkout out [**🔌 ChatWoot Integration**]({{< relref "/docs/integrations/chatwoot" >}}) - -### Workflow Templates -👉 Check out -[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) -for workflow templates! - -{{< imgo src="/images/n8n/waha-n8n.png" >}} - - -## Stability fixes -We're working on internal things to stabilize the product, to avoid any issues with the API. - -Check the full [**🆕 Changelog**]({{< relref "/docs/overview/changelog#202410" >}}) -for more details! +--- +title: "WAHA 2024.10" +description: "WAHA 2024.10 - WAHA Core - Receive Media, n8n Low Code Integration, TypeBot Integration, ChatWoot Integration, Workflow Templates, Stability fixes" +excerpt: "WAHA 2024.10 - WAHA Core - Receive Media, n8n Low Code Integration, TypeBot Integration, ChatWoot Integration, Workflow Templates, Stability fixes" +date: 2024-09-30T08:48:45+00:00 +draft: false +images: ["WAHA 2024.10.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2024-10 +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.10**]({{< relref "/docs/overview/changelog#202410" >}}) 🎉 + +## WAHA Core - Receive Media + +We published [**📥 Receive messages** ]({{}}) +in free **WAHA Core** version, so you can receive media files in your WhatsApp API for free! + +We'll continue to publish features from +[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) +to WAHA Core, so you can use them for free! + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "body": "Check this out (caption for the media)!", + "from": "11111111111@c.us", + "hasMedia": true, + "media": { + "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", + "mimetype": "image/jpeg", + "filename": null + } + } +} +``` + +## n8n Low Code Integration + +

+ +

+ +Meat the new **WAHA** integration with **n8n**! + +You can build your WhatsApp automation with using n8n and WAHA in pair! + +For that we've built [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha/) +directly from our [Swagger](/swagger) specification, so all available API calls are available in n8n. + +Install it on your n8n instance and start building your first workflow: + +``` +@devlikeapro/n8n-nodes-waha +``` + +Read more about +[**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) + +### TypeBot Integration + +

+ +

+ +Using the n8n workflow you can integrate **TypeBot** with **WAHA**! + +👉 Checkout out [**🔌 TypeBot Integration**]({{< relref "/docs/integrations/typebot" >}}) + +### ChatWoot Integration + +

+ +

+ +Using the n8n workflow you can integrate **ChatWoot** with **WAHA**! + +👉 Checkout out [**🔌 ChatWoot Integration**]({{< relref "/docs/integrations/chatwoot" >}}) + +### Workflow Templates + +👉 Check out +[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) +for workflow templates! + +{{< imgo src="/images/n8n/waha-n8n.png" >}} + +## Stability fixes + +We're working on internal things to stabilize the product, to avoid any issues with the API. + +Check the full [**🆕 Changelog**]({{< relref "/docs/overview/changelog#202410" >}}) +for more details! diff --git a/content/blog/waha-2024-11/index.md b/content/blog/waha-2024-11/index.md index 066580e48..2ec04c893 100644 --- a/content/blog/waha-2024-11/index.md +++ b/content/blog/waha-2024-11/index.md @@ -1,199 +1,207 @@ ---- -title: "WAHA 2024.11" -description: "WAHA 2024.11 - What Have We Done 😱" -excerpt: "WAHA 2024.11 - What Have We Done 😱" -date: 2024-11-30T08:48:45+00:00 -draft: false -images: ["WAHA 2024.11.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2024-11 ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.11**]({{< relref "/docs/overview/changelog#202411" >}}) 🎉 - -## Event Monitor - -Now you can observe the -[**Events**]({{< relref "/docs/how-to/events" >}}) -happening in your WAHA instance in real-time with the new -[**Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) -feature! - -{{< imgo src="/images/waha/dashboard/dashboard-event-monitor.png" >}} - -Open -[dashboard/event-monitor](/dashboard/event-monitor) or at your local instance -[http://localhost:3000/dashboard/event-monitor](http://localhost:3000/dashboard/event-monitor) - - -## Websockets - -![websockets](websockets.png) - -WAHA now has full support for [Websockets]({{< relref "/docs/how-to/events#websockets" >}})! - -Here's how you can listen to it using [websocat](https://github.com/vi/websocat?tab=readme-ov-file#installation) - -```bash -# Listen all sessions and events -# -E to end the connection when the server closes it -websocat -E ws://localhost:3000/ws -``` - -{{< details "Or JavaScript" >}} -```js -// Configuration -const apiKey = '123'; // Replace with your API key -const baseUrl = 'ws://localhost:3000/ws'; -const session = '*'; // Use '*' to listen to all sessions -const events = ['session.status', 'message']; // List of events to listen to - -// Construct the WebSocket URL with query parameters -const queryParams = new URLSearchParams({ - 'x-api-key': apiKey, - session, - ...events.reduce((acc, event) => ({ ...acc, events: event }), {}) // Add multiple 'events' params -}); -const wsUrl = `${baseUrl}?${queryParams.toString()}`; - -// Initialize WebSocket connection -const socket = new WebSocket(wsUrl); - -// Handle incoming messages -socket.onmessage = (event) => { - console.log('Received:', event.data); -}; - -// Handle errors -socket.onerror = (error) => { - console.error('WebSocket Error:', error); -}; - -// Handle connection open -socket.onopen = () => { - console.log('WebSocket connection established:', wsUrl); -}; - -// Handle connection close -socket.onclose = () => { - console.log('WebSocket connection closed'); -}; -``` -{{< /details >}} - - -## Manage Labels - -Now you can manage (create, update, delete) [**🏷️ Labels**](/docs/how-to/labels) using WAHA API! - -![labels](whatsapp-labels.png) - -{{< details "Create Label" >}} - -```http request -POST /api/{session}/labels -``` - -Using `color` -```json -{ - "name": "New Client", - "color": 1 -} -``` - -Using `colorHex` -```json -{ - "name": "New Client", - "colorHex" : "#64c4ff" -} -``` - -{{< /details >}} - -{{< details "Update Label" >}} - -```http request -PUT /api/{session}/labels/{labelId} -``` - -Using `color` -```json -{ - "name": "New Client", - "color": 1 -} -``` - -Using `colorHex` -```json -{ - "name": "New Client", - "colorHex" : "#64c4ff" -} -``` - -{{< /details >}} - -{{< details "Delete Label" >}} - -```http request -DELETE /api/{session}/labels/{labelId} -``` - -{{< /details >}} - -## Pin Message - -You can [**💬 Pin and Unpin Messages**](/docs/how-to/chats#pin-message) in WAHA now! - -![alt](whatsapp-pin-message.png) - -{{< details "Pin message" >}} - -```http request -POST /api/{session}/chats/{chatId}/messages/{messageId}/pin -``` - -Payload: -```json -{ - "duration": 86400 -} -``` - -- 24 hours - `duration=86400` -- 7 days - `duration=604800` -- 30 days - `duration=2592000` - -Response: -```json -{ - "success": true -} -``` - - -{{< /details >}} - -{{< details "Unpin message" >}} - -```http request -POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin -``` - -Response: -```json -{ - "success": true -} -``` -{{< /details >}} - -## And More! -Check out the full [**WAHA 2024.11 🆕 Changelog**]({{< relref "/docs/overview/changelog#202411" >}}) for more details! \ No newline at end of file +--- +title: "WAHA 2024.11" +description: "WAHA 2024.11 - What Have We Done 😱" +excerpt: "WAHA 2024.11 - What Have We Done 😱" +date: 2024-11-30T08:48:45+00:00 +draft: false +images: ["WAHA 2024.11.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2024-11 +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.11**]({{< relref "/docs/overview/changelog#202411" >}}) 🎉 + +## Event Monitor + +Now you can observe the +[**Events**]({{< relref "/docs/how-to/events" >}}) +happening in your WAHA instance in real-time with the new +[**Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) +feature! + +{{< imgo src="/images/waha/dashboard/dashboard-event-monitor.png" >}} + +Open +[dashboard/event-monitor](/dashboard/event-monitor) or at your local instance +[http://localhost:3000/dashboard/event-monitor](http://localhost:3000/dashboard/event-monitor) + +## Websockets + +![websockets](websockets.png) + +WAHA now has full support for [Websockets]({{< relref "/docs/how-to/events#websockets" >}})! + +Here's how you can listen to it using [websocat](https://github.com/vi/websocat?tab=readme-ov-file#installation) + +```bash +# Listen all sessions and events +# -E to end the connection when the server closes it +websocat -E ws://localhost:3000/ws +``` + +{{< details "Or JavaScript" >}} + +```js +// Configuration +const apiKey = "123"; // Replace with your API key +const baseUrl = "ws://localhost:3000/ws"; +const session = "*"; // Use '*' to listen to all sessions +const events = ["session.status", "message"]; // List of events to listen to + +// Construct the WebSocket URL with query parameters +const queryParams = new URLSearchParams({ + "x-api-key": apiKey, + session, + ...events.reduce((acc, event) => ({ ...acc, events: event }), {}) // Add multiple 'events' params +}); +const wsUrl = `${baseUrl}?${queryParams.toString()}`; + +// Initialize WebSocket connection +const socket = new WebSocket(wsUrl); + +// Handle incoming messages +socket.onmessage = (event) => { + console.log("Received:", event.data); +}; + +// Handle errors +socket.onerror = (error) => { + console.error("WebSocket Error:", error); +}; + +// Handle connection open +socket.onopen = () => { + console.log("WebSocket connection established:", wsUrl); +}; + +// Handle connection close +socket.onclose = () => { + console.log("WebSocket connection closed"); +}; +``` + +{{< /details >}} + +## Manage Labels + +Now you can manage (create, update, delete) [**🏷️ Labels**](/docs/how-to/labels) using WAHA API! + +![labels](whatsapp-labels.png) + +{{< details "Create Label" >}} + +```http request +POST /api/{session}/labels +``` + +Using `color` + +```json +{ + "name": "New Client", + "color": 1 +} +``` + +Using `colorHex` + +```json +{ + "name": "New Client", + "colorHex": "#64c4ff" +} +``` + +{{< /details >}} + +{{< details "Update Label" >}} + +```http request +PUT /api/{session}/labels/{labelId} +``` + +Using `color` + +```json +{ + "name": "New Client", + "color": 1 +} +``` + +Using `colorHex` + +```json +{ + "name": "New Client", + "colorHex": "#64c4ff" +} +``` + +{{< /details >}} + +{{< details "Delete Label" >}} + +```http request +DELETE /api/{session}/labels/{labelId} +``` + +{{< /details >}} + +## Pin Message + +You can [**💬 Pin and Unpin Messages**](/docs/how-to/chats#pin-message) in WAHA now! + +![alt](whatsapp-pin-message.png) + +{{< details "Pin message" >}} + +```http request +POST /api/{session}/chats/{chatId}/messages/{messageId}/pin +``` + +Payload: + +```json +{ + "duration": 86400 +} +``` + +- 24 hours - `duration=86400` +- 7 days - `duration=604800` +- 30 days - `duration=2592000` + +Response: + +```json +{ + "success": true +} +``` + +{{< /details >}} + +{{< details "Unpin message" >}} + +```http request +POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin +``` + +Response: + +```json +{ + "success": true +} +``` + +{{< /details >}} + +## And More! + +Check out the full [**WAHA 2024.11 🆕 Changelog**]({{< relref "/docs/overview/changelog#202411" >}}) for more details! diff --git a/content/blog/waha-2024-12/index.md b/content/blog/waha-2024-12/index.md index 49a81b91e..a650554d4 100644 --- a/content/blog/waha-2024-12/index.md +++ b/content/blog/waha-2024-12/index.md @@ -1,87 +1,92 @@ ---- -title: "WAHA 2024.12" -description: "WAHA 2024.12 - Chat UI API, Join Group, And More! 🎉" -excerpt: "WAHA 2024.12 - Chat UI API, Join Group, And More! 🎉" -date: 2024-12-30T08:48:45+00:00 -draft: false -images: ["WAHA 2024.12.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2024-12 ---- - -🎉🎉🎉 First of all, **Happy New Year!** We wish you all the best in the New 2025 Year! 🎉🎉🎉 - -We are thrilled to announce the release of [**WAHA 2024.12**]({{< relref "/docs/overview/changelog#202412" >}})! - -## Chat Overview API -We've added [**💬 Chats Overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) -to help you build your custom UI clients! - -{{< imgo src="/images/waha/dashboard/waha-dashboard-chat-ui.png" >}} - -Get chats "overview" - the API that almost all -[**Chat UI**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) -client needs! - -```http request -GET /api/{session}/chats/overview?limit=20&offset=0 -``` - -**Response** contains the main info you need to show in the chat list: -1. `id` - chat id -2. `name` - chat name (if any) -3. `picture` - chat picture (if any) -4. `lastMessage` - last message in the chat (if any). -5. `_chat` - the structure depends on engine you're using - -## Join Groups API -Now you can -[**👥 Join Group**]({{< relref "/docs/how-to/groups#join-group" >}}) -by link -and get -[**👥 Group Info**]({{< relref "/docs/how-to/groups#get-join-info-for-group" >}}) -before joining! - -If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can - -```http request -POST /api/{session}/groups/join -``` - -**Body** -```json -{ - "code": "invitecode" -} -``` - -or using full link: -```json -{ - "code": "https://chat.whatsapp.com/invitecode" -} -``` - -```json { title="Response" } -{ - "id": "123123123@g.us" -} -``` - -## Profile Picture API improvements -We've added optimizations in -[**💬 Get Chat Picture**]({{< relref "/docs/how-to/chats#get-chat-picture" >}}) -and -[**👤 Get Contact Profile Picture**]({{< relref "/docs/how-to/contacts#get-contact-profile-picture" >}}) -API! - -Before it could give rate-overlimit error, now it's optimized and faster! - -## And More! -Check out the full [**WAHA 2024.12 🆕 Changelog**]({{< relref "/docs/overview/changelog#202412" >}}) for more details! - - +--- +title: "WAHA 2024.12" +description: "WAHA 2024.12 - Chat UI API, Join Group, And More! 🎉" +excerpt: "WAHA 2024.12 - Chat UI API, Join Group, And More! 🎉" +date: 2024-12-30T08:48:45+00:00 +draft: false +images: ["WAHA 2024.12.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2024-12 +--- + +🎉🎉🎉 First of all, **Happy New Year!** We wish you all the best in the New 2025 Year! 🎉🎉🎉 + +We are thrilled to announce the release of [**WAHA 2024.12**]({{< relref "/docs/overview/changelog#202412" >}})! + +## Chat Overview API + +We've added [**💬 Chats Overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) +to help you build your custom UI clients! + +{{< imgo src="/images/waha/dashboard/waha-dashboard-chat-ui.png" >}} + +Get chats "overview" - the API that almost all +[**Chat UI**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) +client needs! + +```http request +GET /api/{session}/chats/overview?limit=20&offset=0 +``` + +**Response** contains the main info you need to show in the chat list: + +1. `id` - chat id +2. `name` - chat name (if any) +3. `picture` - chat picture (if any) +4. `lastMessage` - last message in the chat (if any). +5. `_chat` - the structure depends on engine you're using + +## Join Groups API + +Now you can +[**👥 Join Group**]({{< relref "/docs/how-to/groups#join-group" >}}) +by link +and get +[**👥 Group Info**]({{< relref "/docs/how-to/groups#get-join-info-for-group" >}}) +before joining! + +If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can + +```http request +POST /api/{session}/groups/join +``` + +**Body** + +```json +{ + "code": "invitecode" +} +``` + +or using full link: + +```json +{ + "code": "https://chat.whatsapp.com/invitecode" +} +``` + +```json { title="Response" } +{ + "id": "123123123@g.us" +} +``` + +## Profile Picture API improvements + +We've added optimizations in +[**💬 Get Chat Picture**]({{< relref "/docs/how-to/chats#get-chat-picture" >}}) +and +[**👤 Get Contact Profile Picture**]({{< relref "/docs/how-to/contacts#get-contact-profile-picture" >}}) +API! + +Before it could give rate-overlimit error, now it's optimized and faster! + +## And More! + +Check out the full [**WAHA 2024.12 🆕 Changelog**]({{< relref "/docs/overview/changelog#202412" >}}) for more details! diff --git a/content/blog/waha-2024-4/index.md b/content/blog/waha-2024-4/index.md index 5bdc278ae..fc15b2a56 100644 --- a/content/blog/waha-2024-4/index.md +++ b/content/blog/waha-2024-4/index.md @@ -1,56 +1,55 @@ ---- -title: "WAHA 2024.4 - Dashboard to manage your sessions!" -description: "WAHA 2024.4 - Dashboard to manage your sessions in easy way without additional tools!" -excerpt: "WAHA 2024.4 - Dashboard to manage your sessions in easy way without additional tools!" -date: 2024-04-01T08:48:45+00:00 -draft: false -images: ["WAHA 2024.4.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - - - -We are thrilled to introduce the latest addition to WAHA - -[the brand new **Dashboard**]({{< relref "/docs/how-to/dashboard" >}}), -exclusively available in -[**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) version! - -🌟 Dashboard allows you to do: - -1. **Monitor Sessions**: The Dashboard displays the total number of sessions on the server along with their statuses. It conveniently highlights sessions that require actions, allowing you to address any issues promptly. -2. **Session Management**: Take full control of your sessions with the Dashboard. Start a new session, view session information, generate QR codes, adjust settings, and stop/start or log out from sessions with ease. -3. **Secure Server Connection**: Easily connect to a server using your API key, ensuring a secure and seamless interaction with WAHA. -4. **Version Comparison**: Keep track of the latest project version and compare it to your current version. The Dashboard makes it easy to see when updates are available, empowering you to stay up-to-date with the latest features and improvements. - -🔍 Accessing the Dashboard is as simple as running (remember to update it before!) the project and opening http://localhost:3000/dashboard (or a similar URL with /dashboard appended)I. - -🔑 **Default username and password**: `waha / waha` - -If you’re using API Key, remember to set up the key in the dashboard: -![API Key](dashboard-key.png) - -⚙️ Environment Variables: - -- `WAHA_DASHBOARD_ENABLED=true`: Toggle to enable or disable the dashboard (default is true; set to false to disable). -- `WAHA_DASHBOARD_USERNAME=waha`: Default username for login (default: waha). -- `WAHA_DASHBOARD_PASSWORD=waha`: Default password for login (default: waha). - -ℹ️ If you encounter any issues or wish to request a new feature, please head over to our GitHub repository and create an issue at: -🔗 [WAHA GitHub Issues](https://github.com/devlikeapro/waha/issues) - - -Thank you for your continued support and enthusiasm for the project! We appreciate each and every one of our patrons! 🙏 - -If you don't have access to -[WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) - subscribe to one of our tiers on -the platforms and get the key to get WAHA Plus on -our portal! [https://portal.devlike.pro/](https://portal.devlike.pro/) - -You can find all changes for the WAHA 2024.4 in [🆕 Changelog]({{< relref "/docs/overview/changelog" >}}) +--- +title: "WAHA 2024.4 - Dashboard to manage your sessions!" +description: "WAHA 2024.4 - Dashboard to manage your sessions in easy way without additional tools!" +excerpt: "WAHA 2024.4 - Dashboard to manage your sessions in easy way without additional tools!" +date: 2024-04-01T08:48:45+00:00 +draft: false +images: ["WAHA 2024.4.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + + + +We are thrilled to introduce the latest addition to WAHA - +[the brand new **Dashboard**]({{< relref "/docs/how-to/dashboard" >}}), +exclusively available in +[**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) version! + +🌟 Dashboard allows you to do: + +1. **Monitor Sessions**: The Dashboard displays the total number of sessions on the server along with their statuses. It conveniently highlights sessions that require actions, allowing you to address any issues promptly. +2. **Session Management**: Take full control of your sessions with the Dashboard. Start a new session, view session information, generate QR codes, adjust settings, and stop/start or log out from sessions with ease. +3. **Secure Server Connection**: Easily connect to a server using your API key, ensuring a secure and seamless interaction with WAHA. +4. **Version Comparison**: Keep track of the latest project version and compare it to your current version. The Dashboard makes it easy to see when updates are available, empowering you to stay up-to-date with the latest features and improvements. + +🔍 Accessing the Dashboard is as simple as running (remember to update it before!) the project and opening http://localhost:3000/dashboard (or a similar URL with /dashboard appended)I. + +🔑 **Default username and password**: `waha / waha` + +If you’re using API Key, remember to set up the key in the dashboard: +![API Key](dashboard-key.png) + +⚙️ Environment Variables: + +- `WAHA_DASHBOARD_ENABLED=true`: Toggle to enable or disable the dashboard (default is true; set to false to disable). +- `WAHA_DASHBOARD_USERNAME=waha`: Default username for login (default: waha). +- `WAHA_DASHBOARD_PASSWORD=waha`: Default password for login (default: waha). + +ℹ️ If you encounter any issues or wish to request a new feature, please head over to our GitHub repository and create an issue at: +🔗 [WAHA GitHub Issues](https://github.com/devlikeapro/waha/issues) + +Thank you for your continued support and enthusiasm for the project! We appreciate each and every one of our patrons! 🙏 + +If you don't have access to +[WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) - subscribe to one of our tiers on +the platforms and get the key to get WAHA Plus on +our portal! [https://portal.devlike.pro/](https://portal.devlike.pro/) + +You can find all changes for the WAHA 2024.4 in [🆕 Changelog]({{< relref "/docs/overview/changelog" >}}) diff --git a/content/blog/waha-2024-5/index.md b/content/blog/waha-2024-5/index.md index a8c64b575..fb943cb97 100644 --- a/content/blog/waha-2024-5/index.md +++ b/content/blog/waha-2024-5/index.md @@ -1,45 +1,49 @@ ---- -title: "WAHA 2024.5 - Swagger White Label and stability improvements" -description: "WAHA 2024.5 has been released with Swagger White Label and stability improvements!" -excerpt: "WAHA 2024.5 has been released with Swagger White Label and stability improvements!" -date: 2024-05-30T08:48:45+00:00 -draft: false -images: ["WAHA 2024.5.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -We are excited to announce the release of **WAHA 2024.5**! -This version introduces the [Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) -feature and includes several stability improvements. - -Check the [🆕 Changelog]({{< relref "/docs/overview/changelog#20245" >}}) for a full list of changes. - -# 🌟 NEW - Swagger White Label - -👉 Swagger White Label is available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version only. - -If you're running SaaS or want to show your brand in the Swagger documentation, -you can now customize the Swagger documentation with your own brand! - -![Swagger White Label](swagger-white-label.png) - -Use the following environment variables to customize the Swagger documentation: -- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. -- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. -- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. - -**Example** (consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml#L15-L38) or other methods to store these settings): -```bash -docker run -it -p 3000:3000 -e WHATSAPP_SWAGGER_TITLE="AwesomeCRM" -e 'WHATSAPP_SWAGGER_DESCRIPTION=

FantasticFindz - Discover unique treasures from around the world at unbelievable prices!
Read more about us!

' -e "WHATSAPP_SWAGGER_EXTERNAL_DOC_URL=https://google.com" devlikeapro/waha-plus -``` - -# 🛠️ Stability Improvements -We've made several stability improvements to WEBJS and NOWEB engines, check the -[🆕 Changelog]({{< relref "/docs/overview/changelog#20245" >}}) for more details. - -# Thank you for your support! -We appreciate your [continued support](/support-us) and enthusiasm for the project! +--- +title: "WAHA 2024.5 - Swagger White Label and stability improvements" +description: "WAHA 2024.5 has been released with Swagger White Label and stability improvements!" +excerpt: "WAHA 2024.5 has been released with Swagger White Label and stability improvements!" +date: 2024-05-30T08:48:45+00:00 +draft: false +images: ["WAHA 2024.5.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +We are excited to announce the release of **WAHA 2024.5**! +This version introduces the [Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) +feature and includes several stability improvements. + +Check the [🆕 Changelog]({{< relref "/docs/overview/changelog#20245" >}}) for a full list of changes. + +# 🌟 NEW - Swagger White Label + +👉 Swagger White Label is available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version only. + +If you're running SaaS or want to show your brand in the Swagger documentation, +you can now customize the Swagger documentation with your own brand! + +![Swagger White Label](swagger-white-label.png) + +Use the following environment variables to customize the Swagger documentation: + +- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. +- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. +- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. + +**Example** (consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml#L15-L38) or other methods to store these settings): + +```bash +docker run -it -p 3000:3000 -e WHATSAPP_SWAGGER_TITLE="AwesomeCRM" -e 'WHATSAPP_SWAGGER_DESCRIPTION=

FantasticFindz - Discover unique treasures from around the world at unbelievable prices!
Read more about us!

' -e "WHATSAPP_SWAGGER_EXTERNAL_DOC_URL=https://google.com" devlikeapro/waha-plus +``` + +# 🛠️ Stability Improvements + +We've made several stability improvements to WEBJS and NOWEB engines, check the +[🆕 Changelog]({{< relref "/docs/overview/changelog#20245" >}}) for more details. + +# Thank you for your support! + +We appreciate your [continued support](/support-us) and enthusiasm for the project! diff --git a/content/blog/waha-2024-6/index.md b/content/blog/waha-2024-6/index.md index eb3089cc5..c5cfcbe6a 100644 --- a/content/blog/waha-2024-6/index.md +++ b/content/blog/waha-2024-6/index.md @@ -1,46 +1,49 @@ ---- -title: "WAHA 2024.6 - NOWEB Store, Dashboard for Core, HTTPS" -description: "Introducing NOWEB store for contacts, chats, and messages, Dashboard available in Core version, and built-in HTTPS support!" -excerpt: "Introducing NOWEB store for contacts, chats, and messages, Dashboard available in Core version, and built-in HTTPS support!" -date: 2024-06-30T08:48:45+00:00 -draft: false -images: ["WAHA 2024.6.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.6**]({{< relref "/docs/overview/changelog" >}}) 🎉 - -Here's the list of main changes we've made: - -## NOWEB Store - -You asked it, we did it - **contacts, chats, and messages** endpoints are now available in NOWEB engine! -- [`GET /api/contacts/all`]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}) -- [`GET /api/{session}/chats`]({{< relref "/docs/how-to/chats#get-all-chats" >}}) -- [`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) - -👉 Please make sure to [**🏭 Enable NOWEB Store before using these endpoints**]({{< relref "/docs/engines/NOWEB#store" >}})! - - -## Dashboard now available in WAHA Core -[📊 WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) -a web interface to easily manage your WhatsApp sessions now is available in Free WAHA Core version! - - - -## Built-in HTTPS Support -WAHA supports [🔒 HTTPS out of the box now]({{< relref "/docs/how-to/security#https" >}})! - -👉 Here's [**Step-by-step guide on how to set up HTTPS for WAHA**]({{< relref "/blog/waha-https" >}}) -![alt](https_icon.png) - -## And MORE! -Read the [**Full Changelog for 2024.6**]({{< relref "/docs/overview/changelog" >}}) to get all updates we've made -in 2024.6 version! +--- +title: "WAHA 2024.6 - NOWEB Store, Dashboard for Core, HTTPS" +description: "Introducing NOWEB store for contacts, chats, and messages, Dashboard available in Core version, and built-in HTTPS support!" +excerpt: "Introducing NOWEB store for contacts, chats, and messages, Dashboard available in Core version, and built-in HTTPS support!" +date: 2024-06-30T08:48:45+00:00 +draft: false +images: ["WAHA 2024.6.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.6**]({{< relref "/docs/overview/changelog" >}}) 🎉 + +Here's the list of main changes we've made: + +## NOWEB Store + +You asked it, we did it - **contacts, chats, and messages** endpoints are now available in NOWEB engine! + +- [`GET /api/contacts/all`]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}) +- [`GET /api/{session}/chats`]({{< relref "/docs/how-to/chats#get-all-chats" >}}) +- [`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) + +👉 Please make sure to [**🏭 Enable NOWEB Store before using these endpoints**]({{< relref "/docs/engines/NOWEB#store" >}})! + +## Dashboard now available in WAHA Core + +[📊 WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) +a web interface to easily manage your WhatsApp sessions now is available in Free WAHA Core version! + + + +## Built-in HTTPS Support + +WAHA supports [🔒 HTTPS out of the box now]({{< relref "/docs/how-to/security#https" >}})! + +👉 Here's [**Step-by-step guide on how to set up HTTPS for WAHA**]({{< relref "/blog/waha-https" >}}) +![alt](https_icon.png) + +## And MORE! + +Read the [**Full Changelog for 2024.6**]({{< relref "/docs/overview/changelog" >}}) to get all updates we've made +in 2024.6 version! diff --git a/content/blog/waha-2024-7/index.md b/content/blog/waha-2024-7/index.md index 25d5a776d..8fa7c34cc 100644 --- a/content/blog/waha-2024-7/index.md +++ b/content/blog/waha-2024-7/index.md @@ -1,35 +1,37 @@ ---- -title: "WAHA 2024.7 - WhatsApp Channels API, JSON logs" -description: "Introducing WAHA 2024.7 - WhatsApp Channels API, JSON logs" -excerpt: "Introducing WAHA 2024.7 - WhatsApp Channels API, JSON logs" -date: 2024-07-20T08:48:45+00:00 -draft: false -images: ["WAHA 2024.7.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.7**]({{< relref "/docs/overview/changelog" >}}) 🎉 - - -## WhatsApp Channels API -![alt](whatsapp-channels.png) - -WAHA now supports [**WhatsApp Channels**]({{< relref "/whatsapp-channels" >}}) - a brand-new feature introduced by WhatsApp. -You can manage, read and send messages to **WhatsApp Channels** (aka Newsletters) via API. - -👉 Read more about available features on [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) documentation page. - -💡 If you're completely new with the project, we wrote a -[**Step-By-Step Guide on How to send a post to WhatsApp Channel via API**]({{< relref "/blog/how-to-send-messages-to-channels" >}}) - -## JSON logs -WAHA now supports JSON logs. You can enable it by setting `WAHA_LOG_FORMAT=JSON` environment variable. -`WAHA_LOG_FORMAT` - supports formats: - - `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format - - `WAHA_LOG_FORMAT=JSON` - can be useful if you're using central logging management system - -👉 Learn more about logging configuration on [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) page. +--- +title: "WAHA 2024.7 - WhatsApp Channels API, JSON logs" +description: "Introducing WAHA 2024.7 - WhatsApp Channels API, JSON logs" +excerpt: "Introducing WAHA 2024.7 - WhatsApp Channels API, JSON logs" +date: 2024-07-20T08:48:45+00:00 +draft: false +images: ["WAHA 2024.7.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.7**]({{< relref "/docs/overview/changelog" >}}) 🎉 + +## WhatsApp Channels API + +![alt](whatsapp-channels.png) + +WAHA now supports [**WhatsApp Channels**]({{< relref "/whatsapp-channels" >}}) - a brand-new feature introduced by WhatsApp. +You can manage, read and send messages to **WhatsApp Channels** (aka Newsletters) via API. + +👉 Read more about available features on [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) documentation page. + +💡 If you're completely new with the project, we wrote a +[**Step-By-Step Guide on How to send a post to WhatsApp Channel via API**]({{< relref "/blog/how-to-send-messages-to-channels" >}}) + +## JSON logs + +WAHA now supports JSON logs. You can enable it by setting `WAHA_LOG_FORMAT=JSON` environment variable. +`WAHA_LOG_FORMAT` - supports formats: + +- `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format +- `WAHA_LOG_FORMAT=JSON` - can be useful if you're using central logging management system + +👉 Learn more about logging configuration on [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) page. diff --git a/content/blog/waha-2024-8/index.md b/content/blog/waha-2024-8/index.md index 6ee0f213f..21b2298aa 100644 --- a/content/blog/waha-2024-8/index.md +++ b/content/blog/waha-2024-8/index.md @@ -1,136 +1,141 @@ ---- -title: "WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" -description: "Introducing WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" -excerpt: "Introducing WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" -date: 2024-08-01T08:48:45+00:00 -draft: false -images: ["WAHA 2024.8.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.8**]({{< relref "/docs/overview/changelog#20248" >}}) 🎉 - - -## WhatsApp Business Labels API -You can now work with **WhatsApp Labels** available in WhatsApp Business using the API! - -![alt](whatsapp-labels.png) - -### Labels API - -Here's **Get labels** API example: - -```http request -GET /api/{session}/labels -``` - -Response: - -```json -[ - { - "id": "1", - "name": "New Client", - "color": 1, - "colorHex": "#64c4ff" - }, - ... -] -``` - -👉 Read more about the WhatsApp Business Labels API on [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) page! - -### Labels Events -You can now receive information about label creation, update, and deletion using webhooks! - -```json { title="label.upsert" } -{ - "event": "label.upsert", - "session": "default", - "payload": { - "id": "10", - "name": "Label Name", - "color": 14, - "colorHex": "#00a0f2" - }, - "engine": "NOWEB", - ... -} - -``` -👉 Read more about the Labels Events on [**🏷️ Labels**]({{< relref "docs/how-to/labels#webhooks" >}}) page! - -## Chat archive/unarchive -You can now **archive and unarchive** WhatsApp Chats using API and -receive events about chat archive in WhatsApp using webhooks! - -![alt](whatsapp-archive.jpeg) -### Chat archive API - -Use the method to **archive** chat -```http request -POST /api/{session}/chats/{chatId}/archive -``` - -Use the method to **unarchive** chat - -```http request -POST /api/{session}/chats/{chatId}/unarchive -``` - - -👉 Read more about the endpoints on [**💬 Chats**]({{< relref "docs/how-to/chats#archive-chat" >}}) page! - -### Chat archive Events -Enable `chat.archive` event when starting a new session -and receive information about chat archive in WhatsApp using events: - -```json { title="chat.archive" } -{ - "event": "chat.archive", - "session": "default", - "payload": { - "id": "123123123@c.us", - "timestamp": 1667561485, - "archived": true <== or false - }, - ... -} -``` - -👉 Read more about the events on [**🔄 Webhooks**]({{< relref "docs/how-to/events#chatarchive" >}}) page! - - -## Calls Events -Now when the WhatsApp account receives (rejects and accepts) a new call - you can receive information about -that using new `call.*` webhooks! - -![alt](whatsapp-phone-call.png) - -Enable `call.*` events when starting a new session -and receive information about calls in WhatsApp using events: - -```json { title="call.received" } -{ - "event": "call.received", - "session": "default", - "payload": { - "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "from": "22222222222@c.us", - "timestamp": 1721374000, - "isVideo": false, - "isGroup": false - }, - ... -} -``` - -👉 Read more about the events on [**📞 Calls**]({{< relref "docs/how-to/calls" >}}) page! - -## And more! - -👉 Read the full [**🆕 Changelog**]({{< relref "/docs/overview/changelog#20248" >}}) for WAHA 2024.8 release! +--- +title: "WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" +description: "Introducing WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" +excerpt: "Introducing WAHA 2024.8 - WhatsApp Business Labels API, Chat Archive and more!" +date: 2024-08-01T08:48:45+00:00 +draft: false +images: ["WAHA 2024.8.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.8**]({{< relref "/docs/overview/changelog#20248" >}}) 🎉 + +## WhatsApp Business Labels API + +You can now work with **WhatsApp Labels** available in WhatsApp Business using the API! + +![alt](whatsapp-labels.png) + +### Labels API + +Here's **Get labels** API example: + +```http request +GET /api/{session}/labels +``` + +Response: + +```json +[ + { + "id": "1", + "name": "New Client", + "color": 1, + "colorHex": "#64c4ff" + }, + ... +] +``` + +👉 Read more about the WhatsApp Business Labels API on [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) page! + +### Labels Events + +You can now receive information about label creation, update, and deletion using webhooks! + +```json { title="label.upsert" } +{ + "event": "label.upsert", + "session": "default", + "payload": { + "id": "10", + "name": "Label Name", + "color": 14, + "colorHex": "#00a0f2" + }, + "engine": "NOWEB", + ... +} + +``` + +👉 Read more about the Labels Events on [**🏷️ Labels**]({{< relref "docs/how-to/labels#webhooks" >}}) page! + +## Chat archive/unarchive + +You can now **archive and unarchive** WhatsApp Chats using API and +receive events about chat archive in WhatsApp using webhooks! + +![alt](whatsapp-archive.jpeg) + +### Chat archive API + +Use the method to **archive** chat + +```http request +POST /api/{session}/chats/{chatId}/archive +``` + +Use the method to **unarchive** chat + +```http request +POST /api/{session}/chats/{chatId}/unarchive +``` + +👉 Read more about the endpoints on [**💬 Chats**]({{< relref "docs/how-to/chats#archive-chat" >}}) page! + +### Chat archive Events + +Enable `chat.archive` event when starting a new session +and receive information about chat archive in WhatsApp using events: + +```json { title="chat.archive" } +{ + "event": "chat.archive", + "session": "default", + "payload": { + "id": "123123123@c.us", + "timestamp": 1667561485, + "archived": true <== or false + }, + ... +} +``` + +👉 Read more about the events on [**🔄 Webhooks**]({{< relref "docs/how-to/events#chatarchive" >}}) page! + +## Calls Events + +Now when the WhatsApp account receives (rejects and accepts) a new call - you can receive information about +that using new `call.*` webhooks! + +![alt](whatsapp-phone-call.png) + +Enable `call.*` events when starting a new session +and receive information about calls in WhatsApp using events: + +```json { title="call.received" } +{ + "event": "call.received", + "session": "default", + "payload": { + "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "from": "22222222222@c.us", + "timestamp": 1721374000, + "isVideo": false, + "isGroup": false + }, + ... +} +``` + +👉 Read more about the events on [**📞 Calls**]({{< relref "docs/how-to/calls" >}}) page! + +## And more! + +👉 Read the full [**🆕 Changelog**]({{< relref "/docs/overview/changelog#20248" >}}) for WAHA 2024.8 release! diff --git a/content/blog/waha-2024-9/index.md b/content/blog/waha-2024-9/index.md index fd91043f3..9f543e531 100644 --- a/content/blog/waha-2024-9/index.md +++ b/content/blog/waha-2024-9/index.md @@ -1,190 +1,196 @@ ---- -title: "WAHA 2024.9 - S3, Session API, Metadata, Dashboard and more!" -description: "We are thrilled to announce the release of WAHA 2024.9" -excerpt: "We are thrilled to announce the release of WAHA 2024.9 🎉" -date: 2024-08-27T08:48:45+00:00 -draft: false -images: ["WAHA 2024.9.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2024-9 -aliases: - - /blog/waha-2024.9-session-api-metadata-dashboard-and-more - - /blog/waha-2024.9-s3-session-api-metadata-dashboard-and-more/ ---- - -🎉 We are thrilled to announce the release of [**WAHA 2024.9**]({{< relref "/docs/overview/changelog#20249" >}}) 🎉 - -The release has a lot of changes, but we'll cover only few of them in this blog post, -kindly check the [**🆕 Changelog**]({{< relref "/docs/overview/changelog#20249" >}}) -for the full list of changes. - -## Session API -{{< imgo src="/images/waha/waha-session-lifecycle.png" >}} - -We've added a new [**🖥️ Sessions API**]({{< relref "/docs/how-to/sessions" >}}) -to manage the session lifecycle. - -Now you can change configuration after the session is created, -you can log out the session without removing it, and more! - - -## Session Metadata -`metadata` is an attribute on Session objects that lets you store more information, -structured as key-value pairs, -to sessions for your own use and reference. -For example, you can store your user’s unique identifier from your system. - -Associated `metadata` field is available in: -1. [List Sessions](#list-sessions) and [Get Session](#get-session) responses -2. [**🔄 Webhooks**]({{< relref "events#metadata" >}}) events -3. [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata - - -```json -{ - "name": "default", - "config": { - "metadata": { - "user.id": "123", - "user.email": "email@example.com" - } - } -} -``` - -Sample `metadata` use cases: -- **Link IDs**: Attach your system’s unique IDs to a Session object to simplify lookups. For example, add your user or tenant id. -- **Customer details**: Annotate a customer by storing an internal information (email, customer name) for your future - use, so you don't have to look into two systems. - -WAHA does not use metadata for any internal purposes, it's up to you how to use it. - -👉 Read more -[**🖥️ Sessions - Metadata**]({{< relref "/docs/how-to/sessions#metadata" >}}) - -## Media S3 Storage -You can use the S3 storage to store the media files. - -{{< imgo src="/images/waha/storages/waha-storages.drawio.png" >}} - -Any **S3 Compatible** storage can be used, such as AWS S3, MinIO, DigitalOcean Spaces, etc. For in-house solutions, you can use [**MinIO**](https://min.io/). - -{{< include file="content/docs/how-to/storages/docker-compose.md" >}} - -
- -After you enabled S3 here's example for [**message**]({{< relref "/docs/how-to/events#message" >}}) webhook payload: -```json { title="message" } -{ - "event": "message", - "session": "default", - "engine": "WEBJS", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "hasMedia": true, - "media": { - "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", - "mimetype": "image/jpeg", - "filename": null, - "s3": { - "Bucket": "bucket-name", - "Key": "/default/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg" - }, - "error": null // if there was an error during file download - } - ... - } -} -``` - -in addition to `media.*` field it will have `media.s3.*` field with the S3 bucket information. - - -👉 Read more [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) - - -## Dashboard -Here's a quick overview of new features available in Dashboard: - -{{< imgo src="/images/blog/waha-2024-9/dashboard-overview.png" >}} -- **Server Uptime** - see how long your server is running -- **Server Restart** - restart the server -- **Session Metadata** - see the metadata of the session -- **Session Actions** - see the actions available for the session -- **Session Bulk Actions** - see the bulk actions available for the session - - -{{< imgo src="/images/blog/waha-2024-9/dashboard-server.png" >}} -- **Server Environment Variables** - see the environment variables of the server -- **Server Uptime** - -{{< imgo src="/images/blog/waha-2024-9/dashboard-session.png" >}} -- **Session Metadata** - add metadata to the session - -## Reply on Message -You can reply on a message with any type of message now by adding `reply_to` in the request! -```http request -POST /api/sendText -``` - -```json -{ - "session": "default", - "chatId": "11111111111@c.us", - "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "text": "Reply text" -} - -``` - -Read more about [**📤 Send messages - reply_to**]({{< relref "/docs/how-to/send-messages#reply_to" >}}) - -## Server API -### Get server status - -Returns the server status, start timestamp, and uptime. - -```http request -GET /api/server/status -``` - -```json -{ - "startTimestamp": 1723788847247, - "uptime": 3600000 -} -``` - -### Restart (stop) server - -You can stop the server by calling - -```http request -POST /api/server/stop -``` - -```json -{ - // By default, it gracefully stop all sessions and connections - // but you can force it to stop immediately - "force": false -} -``` -👉 If you're using Docker and followed [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide, -Docker will **automatically restart** the server, so you can use this endpoint to **restart** the server. - - - -## Thank you all for your support! 🙏 -All these changes were made possible by the amazing community of supporters! - -We are grateful for your contributions and feedback. 🚀 - -

-🫶 -

- +--- +title: "WAHA 2024.9 - S3, Session API, Metadata, Dashboard and more!" +description: "We are thrilled to announce the release of WAHA 2024.9" +excerpt: "We are thrilled to announce the release of WAHA 2024.9 🎉" +date: 2024-08-27T08:48:45+00:00 +draft: false +images: ["WAHA 2024.9.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2024-9 +aliases: + - /blog/waha-2024.9-session-api-metadata-dashboard-and-more + - /blog/waha-2024.9-s3-session-api-metadata-dashboard-and-more/ +--- + +🎉 We are thrilled to announce the release of [**WAHA 2024.9**]({{< relref "/docs/overview/changelog#20249" >}}) 🎉 + +The release has a lot of changes, but we'll cover only few of them in this blog post, +kindly check the [**🆕 Changelog**]({{< relref "/docs/overview/changelog#20249" >}}) +for the full list of changes. + +## Session API + +{{< imgo src="/images/waha/waha-session-lifecycle.png" >}} + +We've added a new [**🖥️ Sessions API**]({{< relref "/docs/how-to/sessions" >}}) +to manage the session lifecycle. + +Now you can change configuration after the session is created, +you can log out the session without removing it, and more! + +## Session Metadata + +`metadata` is an attribute on Session objects that lets you store more information, +structured as key-value pairs, +to sessions for your own use and reference. +For example, you can store your user’s unique identifier from your system. + +Associated `metadata` field is available in: + +1. [List Sessions](#list-sessions) and [Get Session](#get-session) responses +2. [**🔄 Webhooks**]({{< relref "events#metadata" >}}) events +3. [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata + +```json +{ + "name": "default", + "config": { + "metadata": { + "user.id": "123", + "user.email": "email@example.com" + } + } +} +``` + +Sample `metadata` use cases: + +- **Link IDs**: Attach your system’s unique IDs to a Session object to simplify lookups. For example, add your user or tenant id. +- **Customer details**: Annotate a customer by storing an internal information (email, customer name) for your future + use, so you don't have to look into two systems. + +WAHA does not use metadata for any internal purposes, it's up to you how to use it. + +👉 Read more +[**🖥️ Sessions - Metadata**]({{< relref "/docs/how-to/sessions#metadata" >}}) + +## Media S3 Storage + +You can use the S3 storage to store the media files. + +{{< imgo src="/images/waha/storages/waha-storages.drawio.png" >}} + +Any **S3 Compatible** storage can be used, such as AWS S3, MinIO, DigitalOcean Spaces, etc. For in-house solutions, you can use [**MinIO**](https://min.io/). + +{{< include file="content/docs/how-to/storages/docker-compose.md" >}} + +
+ +After you enabled S3 here's example for [**message**]({{< relref "/docs/how-to/events#message" >}}) webhook payload: + +```json { title="message" } +{ + "event": "message", + "session": "default", + "engine": "WEBJS", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "hasMedia": true, + "media": { + "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", + "mimetype": "image/jpeg", + "filename": null, + "s3": { + "Bucket": "bucket-name", + "Key": "/default/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg" + }, + "error": null // if there was an error during file download + } + ... + } +} +``` + +in addition to `media.*` field it will have `media.s3.*` field with the S3 bucket information. + +👉 Read more [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) + +## Dashboard + +Here's a quick overview of new features available in Dashboard: + +{{< imgo src="/images/blog/waha-2024-9/dashboard-overview.png" >}} + +- **Server Uptime** - see how long your server is running +- **Server Restart** - restart the server +- **Session Metadata** - see the metadata of the session +- **Session Actions** - see the actions available for the session +- **Session Bulk Actions** - see the bulk actions available for the session + +{{< imgo src="/images/blog/waha-2024-9/dashboard-server.png" >}} + +- **Server Environment Variables** - see the environment variables of the server +- **Server Uptime** + +{{< imgo src="/images/blog/waha-2024-9/dashboard-session.png" >}} + +- **Session Metadata** - add metadata to the session + +## Reply on Message + +You can reply on a message with any type of message now by adding `reply_to` in the request! + +```http request +POST /api/sendText +``` + +```json +{ + "session": "default", + "chatId": "11111111111@c.us", + "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "text": "Reply text" +} +``` + +Read more about [**📤 Send messages - reply_to**]({{< relref "/docs/how-to/send-messages#reply_to" >}}) + +## Server API + +### Get server status + +Returns the server status, start timestamp, and uptime. + +```http request +GET /api/server/status +``` + +```json +{ + "startTimestamp": 1723788847247, + "uptime": 3600000 +} +``` + +### Restart (stop) server + +You can stop the server by calling + +```http request +POST /api/server/stop +``` + +```json +{ + // By default, it gracefully stop all sessions and connections + // but you can force it to stop immediately + "force": false +} +``` + +👉 If you're using Docker and followed [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide, +Docker will **automatically restart** the server, so you can use this endpoint to **restart** the server. + +## Thank you all for your support! 🙏 + +All these changes were made possible by the amazing community of supporters! + +We are grateful for your contributions and feedback. 🚀 + +

+🫶 +

diff --git a/content/blog/waha-2025-1/index.md b/content/blog/waha-2025-1/index.md index a949baa3a..818d9a4cf 100644 --- a/content/blog/waha-2025-1/index.md +++ b/content/blog/waha-2025-1/index.md @@ -1,69 +1,72 @@ ---- -title: "WAHA 2025.1" -description: "WAHA 2025.1 - PostgreSQL support, GOWS engine and more! 🎉" -excerpt: "WAHA 2025.1 - PostgreSQL support, GOWS engine and more! 🎉" -date: 2025-01-30T08:48:45+00:00 -draft: false -images: ["WAHA 2025.1.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2025-1 ---- - - -🎉 We are thrilled to announce the changes we made during the [**WAHA 2025.1**]({{< relref "/docs/overview/changelog#20251" >}}) 🎉 - -## GOWS engine -Meet **GOWS** - new, fast, super-reliable and stable [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) for your WAHA instance! - -**GOWS** engine **does not require a browser** to work with WhatsApp Web, it does so directly using a WebSocket. - -🚀 It's new generation engine written in **Golang**, future replacement for **NOWEB** engine. - -You can test it by setting `WHATSAPP_DEFAULT_ENGINE=GOWS` environment variable. -```bash -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha -``` - -👉 [Read more about **GOWS**]({{< relref "/docs/how-to/engines" >}}), it doesn't support all features yet, but we're working on it! - - -## PostgreSQL support - -Now you can use **PostgreSQL** as a [**🗄️ Storage**]({{< relref "/docs/how-to/storages" >}}) for your WAHA instance! - -| Storage | WEBJS | NOWEB | GOWS | -|-----------------------------------|:-----:|:-----:|:----:| -| **🖥️ Session** - **PostgresSQL** | ✔️ | ✔️ | ✔️ | -| **🖼️ Media** - **PostgresSQL** | ✔️ | ✔️ | ✔️ | - -It works with both -[**🖥️ Session** Storage]({{< relref "/docs/how-to/storages#session-storage" >}}) -and -[**🖼️ Media** Storage]({{< relref "/docs/how-to/storages#media-storage" >}}), -support all engines and available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) - -How to connect to your **PostgresSQL** instance? - -Connect **🖥️ Session** Storage: -```bash -docker run -p 3000:3000 -it -e WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable devlikeapro/waha-plus -``` -- Set `WHATSAPP_SESSIONS_POSTGRESQL_URL` with your credentials and database name. - -Connect **🖼️ Media** Storage: -```bash -docker run -p 3000:3000 -it -e WAHA_MEDIA_STORAGE=POSTGRESQL WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable devlikeapro/waha-plus -``` -- Set `WAHA_MEDIA_POSTGRESQL_URL` with your credentials and database name. -- Set `WAHA_MEDIA_STORAGE=POSTGRESQL` to enable **PostgresSQL** as a media storage. - -💡 You can use the same connection URL for `WAHA_MEDIA_POSTGRESQL_URL` and `WHATSAPP_SESSIONS_POSTGRESQL_URL` if you want to use the same database for both storages. - -## And More! -Check out the full [**WAHA 2025.1 🆕 Changelog**]({{< relref "/docs/overview/changelog#20251" >}}) for more details! - - +--- +title: "WAHA 2025.1" +description: "WAHA 2025.1 - PostgreSQL support, GOWS engine and more! 🎉" +excerpt: "WAHA 2025.1 - PostgreSQL support, GOWS engine and more! 🎉" +date: 2025-01-30T08:48:45+00:00 +draft: false +images: ["WAHA 2025.1.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-1 +--- + +🎉 We are thrilled to announce the changes we made during the [**WAHA 2025.1**]({{< relref "/docs/overview/changelog#20251" >}}) 🎉 + +## GOWS engine + +Meet **GOWS** - new, fast, super-reliable and stable [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) for your WAHA instance! + +**GOWS** engine **does not require a browser** to work with WhatsApp Web, it does so directly using a WebSocket. + +🚀 It's new generation engine written in **Golang**, future replacement for **NOWEB** engine. + +You can test it by setting `WHATSAPP_DEFAULT_ENGINE=GOWS` environment variable. + +```bash +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha +``` + +👉 [Read more about **GOWS**]({{< relref "/docs/how-to/engines" >}}), it doesn't support all features yet, but we're working on it! + +## PostgreSQL support + +Now you can use **PostgreSQL** as a [**🗄️ Storage**]({{< relref "/docs/how-to/storages" >}}) for your WAHA instance! + +| Storage | WEBJS | NOWEB | GOWS | +| -------------------------------- | :---: | :---: | :--: | +| **🖥️ Session** - **PostgresSQL** | ✔️ | ✔️ | ✔️ | +| **🖼️ Media** - **PostgresSQL** | ✔️ | ✔️ | ✔️ | + +It works with both +[**🖥️ Session** Storage]({{< relref "/docs/how-to/storages#session-storage" >}}) +and +[**🖼️ Media** Storage]({{< relref "/docs/how-to/storages#media-storage" >}}), +support all engines and available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) + +How to connect to your **PostgresSQL** instance? + +Connect **🖥️ Session** Storage: + +```bash +docker run -p 3000:3000 -it -e WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable devlikeapro/waha-plus +``` + +- Set `WHATSAPP_SESSIONS_POSTGRESQL_URL` with your credentials and database name. + +Connect **🖼️ Media** Storage: + +```bash +docker run -p 3000:3000 -it -e WAHA_MEDIA_STORAGE=POSTGRESQL WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable devlikeapro/waha-plus +``` + +- Set `WAHA_MEDIA_POSTGRESQL_URL` with your credentials and database name. +- Set `WAHA_MEDIA_STORAGE=POSTGRESQL` to enable **PostgresSQL** as a media storage. + +💡 You can use the same connection URL for `WAHA_MEDIA_POSTGRESQL_URL` and `WHATSAPP_SESSIONS_POSTGRESQL_URL` if you want to use the same database for both storages. + +## And More! + +Check out the full [**WAHA 2025.1 🆕 Changelog**]({{< relref "/docs/overview/changelog#20251" >}}) for more details! diff --git a/content/blog/waha-2025-2/index.md b/content/blog/waha-2025-2/index.md index 5a9680683..91fbd6e52 100644 --- a/content/blog/waha-2025-2/index.md +++ b/content/blog/waha-2025-2/index.md @@ -1,136 +1,144 @@ ---- -title: "WAHA 2025.2" -description: "WAHA 2025.2 - Search Channels API, Profile API and more! 🎉" -excerpt: "WAHA 2025.2 - Search Channels API, Profile API and more! 🎉" -date: 2025-02-27T08:48:45+00:00 -draft: false -images: [ "waha-2025-2.png" ] -categories: [ "Releases" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: waha-2025-2 ---- - - -🎉 We are thrilled to announce the changes we made during the -[**WAHA 2025.2**]({{< relref "/docs/overview/changelog#20252" >}}) 🎉 - -## 🆔 Profile API -Managing your WhatsApp profile has never been easier. - -With the new -[**🆔 Profile API**]({{< relref "/docs/how-to/profile" >}}) -, you can customize your profile details! - -{{< imgo src="/images/whatsapp/whatsapp-profile.jpg" full="false" >}} - -**Retrieve your profile details** - -```http request -GET /api/{SESSION}/profile -``` - -**Set Your Profile Name** - -```http request -PUT /api/{session}/profile/name -``` - -**Set a custom status ("About")** - -```http request -PUT /api/{session}/profile/status -``` - -**Update a profile picture** - -```http request -PUT /api/{session}/profile/picture -``` - -```http request -DELETE /api/{session}/profile/picture -``` - -## 📢🔎 Search Channels API - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. -{{< /callout >}} - -Discovering public channels is now **effortless** with the -[**📢 Channels - Search API**]({{< relref "/docs/how-to/channels#search-api" >}})! - -### Search channels by view - -{{< imgo src="/images/whatsapp/channels/channels-views.png" full="false" >}} - -You can search **public** (not subscribed yet) channels **by view**: - -```http request -POST /api/{session}/channels/search/by-view -``` - -### Search channels by text -{{< imgo src="/images/whatsapp/channels/channels-text.png" full="false" >}} - -You can search **public** (not subscribed yet) channels **by text**: -```http request -POST /api/{session}/channels/search/by-text -``` - - -## 👥 Update Group Picture API -Added [**👥 Set Group Picture API**]({{< relref "/docs/how-to/groups#set-group-picture" >}}) to update the group picture. - -**Set Group Picture** -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. -{{< /callout >}} - -```http request -PUT /api/{SESSION}/groups/{ID}/picture -``` - -- `{SESSION}` - session name -- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` - -```json { title="Body" } -{ - "file": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } -} -``` - -## 👥 Groups API - NOWEB, GOWS -**NOWEB** and **GOWS** engines now support the -[**👥 Groups API**]({{< relref "/docs/how-to/groups" >}})! - -{{< include file="content/docs/how-to/groups/features.md" >}} - -## 🔄 group.v2.* events -We added new `group.v2.*` events and made `payload` body **the same** across of all engines! - -Check -[**🔄 Webhooks**]({{< relref "/docs/how-to/events" >}}) or -[**👥 Groups API**]({{< relref "/docs/how-to/groups" >}}) for more details. - - -### group.v2.join -{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} - -### group.v2.leave -{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} - -### group.v2.participants -{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} - -### group.v2.update -{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} - -## And More! -Check out the full list of changes in the -[**WAHA 2025.2**]({{< relref "/docs/overview/changelog#20252" >}}) 🎉 +--- +title: "WAHA 2025.2" +description: "WAHA 2025.2 - Search Channels API, Profile API and more! 🎉" +excerpt: "WAHA 2025.2 - Search Channels API, Profile API and more! 🎉" +date: 2025-02-27T08:48:45+00:00 +draft: false +images: ["waha-2025-2.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-2 +--- + +🎉 We are thrilled to announce the changes we made during the +[**WAHA 2025.2**]({{< relref "/docs/overview/changelog#20252" >}}) 🎉 + +## 🆔 Profile API + +Managing your WhatsApp profile has never been easier. + +With the new +[**🆔 Profile API**]({{< relref "/docs/how-to/profile" >}}) +, you can customize your profile details! + +{{< imgo src="/images/whatsapp/whatsapp-profile.jpg" full="false" >}} + +**Retrieve your profile details** + +```http request +GET /api/{SESSION}/profile +``` + +**Set Your Profile Name** + +```http request +PUT /api/{session}/profile/name +``` + +**Set a custom status ("About")** + +```http request +PUT /api/{session}/profile/status +``` + +**Update a profile picture** + +```http request +PUT /api/{session}/profile/picture +``` + +```http request +DELETE /api/{session}/profile/picture +``` + +## 📢🔎 Search Channels API + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. +{{< /callout >}} + +Discovering public channels is now **effortless** with the +[**📢 Channels - Search API**]({{< relref "/docs/how-to/channels#search-api" >}})! + +### Search channels by view + +{{< imgo src="/images/whatsapp/channels/channels-views.png" full="false" >}} + +You can search **public** (not subscribed yet) channels **by view**: + +```http request +POST /api/{session}/channels/search/by-view +``` + +### Search channels by text + +{{< imgo src="/images/whatsapp/channels/channels-text.png" full="false" >}} + +You can search **public** (not subscribed yet) channels **by text**: + +```http request +POST /api/{session}/channels/search/by-text +``` + +## 👥 Update Group Picture API + +Added [**👥 Set Group Picture API**]({{< relref "/docs/how-to/groups#set-group-picture" >}}) to update the group picture. + +**Set Group Picture** +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. +{{< /callout >}} + +```http request +PUT /api/{SESSION}/groups/{ID}/picture +``` + +- `{SESSION}` - session name +- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` + +```json { title="Body" } +{ + "file": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } +} +``` + +## 👥 Groups API - NOWEB, GOWS + +**NOWEB** and **GOWS** engines now support the +[**👥 Groups API**]({{< relref "/docs/how-to/groups" >}})! + +{{< include file="content/docs/how-to/groups/features.md" >}} + +## 🔄 group.v2.\* events + +We added new `group.v2.*` events and made `payload` body **the same** across of all engines! + +Check +[**🔄 Webhooks**]({{< relref "/docs/how-to/events" >}}) or +[**👥 Groups API**]({{< relref "/docs/how-to/groups" >}}) for more details. + +### group.v2.join + +{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} + +### group.v2.leave + +{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} + +### group.v2.participants + +{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} + +### group.v2.update + +{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} + +## And More! + +Check out the full list of changes in the +[**WAHA 2025.2**]({{< relref "/docs/overview/changelog#20252" >}}) 🎉 diff --git a/content/blog/waha-2025-3/index.md b/content/blog/waha-2025-3/index.md index 9d409b984..72cbbd564 100644 --- a/content/blog/waha-2025-3/index.md +++ b/content/blog/waha-2025-3/index.md @@ -1,57 +1,58 @@ ---- -title: "WAHA 2025.3" -description: "WAHA 2025.3 - GOWS 1.0, NOWEB stability, and More!" -excerpt: "WAHA 2025.3 - GOWS 1.0, NOWEB stability, and More!" -date: 2025-03-26T08:48:45+00:00 -draft: false -images: [ "waha-2025-3.png" ] -categories: [ "Releases" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: waha-2025-3 ---- - -We’re excited to roll out [**WAHA 2025.3**]({{< relref "/docs/overview/changelog#202503" >}})! - -## GOWS 1.0 - -[**GOWS Engine**]({{< relref "/docs/how-to/engines#gows" >}}) just got its **1.0** moment! - -Here’s what’s new: -- Enable Link Previews - {{< issue 763 >}} -- Delete Status Message - {{< issue 754 >}} -- Delete Message - {{< issue 796 >}} -- Edit Message - {{< issue 797 >}} -- Reply To Message - {{< issue 799 >}} -- Add `filename` on `/api/sendFile` - {{< issue 853 >}} -- Extract `replyTo` - {{< issue 876 >}} - -## NOWEB Stability -If you faced any issues with the NOWEB engine, like -{{< issue 821 >}}, {{< issue 860 >}}, {{< issue 869 >}} -we have fixed them in this release! - -No more container restarts due to Out of Memory errors and sessions restarts! - -## Status to 50K Contacts - -You can now send [**WhatsApp Status updates to up to 50,000 contacts**]({{< relref "/docs/how-to/status" >}}) at once! - -Need more control? - -👉 Use the guide: [**Send Status to 10K Contacts Manually**]({{< relref "/docs/how-to/status#send-status-to-10k-contacts-manually" >}}) - -## Disappearing Messages - -Under the hood, WAHA now supports for WhatsApp! {{< issue 736 >}} - - -## Full Changelog - -Catch all the updates and minor releases in the [**🆕 2025.3 Changelog**]({{< relref "/docs/overview/changelog#202503" >}}) - ---- - -Thanks for being part of WAHA community! 🙌 \ No newline at end of file +--- +title: "WAHA 2025.3" +description: "WAHA 2025.3 - GOWS 1.0, NOWEB stability, and More!" +excerpt: "WAHA 2025.3 - GOWS 1.0, NOWEB stability, and More!" +date: 2025-03-26T08:48:45+00:00 +draft: false +images: ["waha-2025-3.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-3 +--- + +We’re excited to roll out [**WAHA 2025.3**]({{< relref "/docs/overview/changelog#202503" >}})! + +## GOWS 1.0 + +[**GOWS Engine**]({{< relref "/docs/how-to/engines#gows" >}}) just got its **1.0** moment! + +Here’s what’s new: + +- Enable Link Previews - {{< issue 763 >}} +- Delete Status Message - {{< issue 754 >}} +- Delete Message - {{< issue 796 >}} +- Edit Message - {{< issue 797 >}} +- Reply To Message - {{< issue 799 >}} +- Add `filename` on `/api/sendFile` - {{< issue 853 >}} +- Extract `replyTo` - {{< issue 876 >}} + +## NOWEB Stability + +If you faced any issues with the NOWEB engine, like +{{< issue 821 >}}, {{< issue 860 >}}, {{< issue 869 >}} +we have fixed them in this release! + +No more container restarts due to Out of Memory errors and sessions restarts! + +## Status to 50K Contacts + +You can now send [**WhatsApp Status updates to up to 50,000 contacts**]({{< relref "/docs/how-to/status" >}}) at once! + +Need more control? + +👉 Use the guide: [**Send Status to 10K Contacts Manually**]({{< relref "/docs/how-to/status#send-status-to-10k-contacts-manually" >}}) + +## Disappearing Messages + +Under the hood, WAHA now supports for WhatsApp! {{< issue 736 >}} + +## Full Changelog + +Catch all the updates and minor releases in the [**🆕 2025.3 Changelog**]({{< relref "/docs/overview/changelog#202503" >}}) + +--- + +Thanks for being part of WAHA community! 🙌 diff --git a/content/blog/waha-2025-4/index.md b/content/blog/waha-2025-4/index.md index 9485913e9..02d6c7909 100644 --- a/content/blog/waha-2025-4/index.md +++ b/content/blog/waha-2025-4/index.md @@ -1,99 +1,103 @@ ---- -title: "WAHA 2025.4 - Read Chat Messages, Group Acks, and Engines Stability!" -description: "WAHA 2025.4 - Mark messages as read, track receipts in groups, stability fixes and more!" -excerpt: "WAHA 2025.4 - Mark messages as read, track receipts in groups, stability fixes and more!" -date: 2025-04-29T08:48:45+00:00 -draft: false -images: ["waha-2025-4.png"] -categories: ["Releases"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-2025-4 ---------------- - -We’re excited to introduce [**WAHA 2025.4**]({{< relref "/docs/overview/changelog#20254" >}}), packed with new API capabilities, group handling improvements, and crucial bug fixes across all engines! - ---- - -## 🆕 What's New? - -### ✅ Mark Messages as Read! - -You can now use the brand new [**💬 Read Messages API**]({{< relref "/docs/how-to/chats/#read-messages" >}}) to mark unread messages as read! - -Works across **WEBJS**, **NOWEB**, and **GOWS**! -[#783](https://github.com/devlikeapro/waha/issues/783) - ---- - -### 📥 Group Receipts Tracking - -**WEBJS** now includes: - -* `message.ack` events for group & status messages -* `message._data.receipts` in [**Get Message by ID**]({{< relref "/docs/how-to/chats/#get-message-by-id" >}}) - -You can now **track delivery for each participant**! -[#495](https://github.com/devlikeapro/waha/issues/495), [#900](https://github.com/devlikeapro/waha/issues/900) - ---- - -### 👁️‍🗨️ Bulk Read Support - -Use `messageIds` in [**Send Seen API**]({{< relref "/docs/how-to/send-messages/#send-seen" >}}) to mark **multiple messages as read** in one request. -**NOWEB**, **GOWS** - ---- - -### 🧰 Filter by Ack - -New `filter.ack` option in [**Get Messages API**]({{< relref "/docs/how-to/chats/#get-messages" >}}) — filter messages based on delivery status. -**All engines** - -### 🟢 Send Reaction to Channels - -[**Send Reaction to Channels**]({{< relref "/docs/how-to/channels/#send-reaction-to-the-channel" >}}) is now fixed for **GOWS** and **NOWEB** engines. -[#889](https://github.com/devlikeapro/waha/issues/889) - -### 🌐 Send Link Custom Preview - -[**Send Link Custom Preview**]({{< relref "/docs/how-to/send-messages/#send-link-custom-preview" >}}) has been improved for **GOWS** and **NOWEB** engines. -[#880](https://github.com/devlikeapro/waha/issues/880), [#596](https://github.com/devlikeapro/waha/issues/596) - -![Custom Link Preview](whatsapp-link-preview.png) - ---- - -## 🛠️ Fixes & Stability - -* **NOWEB**: - - * Fix for `protocolMessage` crash [#932](https://github.com/devlikeapro/waha/issues/932) - * Message status updated on `/api/sendSeen` [#635](https://github.com/devlikeapro/waha/issues/635) - * Correct `ack` for new messages (`DEVICE` instead of `UNKNOWN`) - * Fix sending/receiving in **anonymous groups** and **status** -* **WEBJS**: - - * Auto-restart browser on `ProtocolError` & other errors - [#244](https://github.com/devlikeapro/waha/issues/244), [#936](https://github.com/devlikeapro/waha/issues/936) -* **GOWS**: - - * Group `message.ack` now sent for **all participants** - * Stability improvements for group/status messages - * Fix sending reactions to other users' messages [#894](https://github.com/devlikeapro/waha/issues/894) - ---- - -## ⚙️ Engine Updates - -* Updated engines: - - * **NOWEB** - latest version - * **GOWS** - latest version - * **WEBJS** - updated **puppeteer** and **chrome** images - ---- - -Check out the full list of updates in the [**🆕 WAHA 2025.4 Changelog**]({{< relref "/docs/overview/changelog#20254" >}}) and stay tuned for more! +--- +title: "WAHA 2025.4 - Read Chat Messages, Group Acks, and Engines Stability!" +description: "WAHA 2025.4 - Mark messages as read, track receipts in groups, stability fixes and more!" +excerpt: "WAHA 2025.4 - Mark messages as read, track receipts in groups, stability fixes and more!" +date: 2025-04-29T08:48:45+00:00 +draft: false +images: ["waha-2025-4.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-4 +--- + +--- + +We’re excited to introduce [**WAHA 2025.4**]({{< relref "/docs/overview/changelog#20254" >}}), packed with new API capabilities, group handling improvements, and crucial bug fixes across all engines! + +--- + +## 🆕 What's New? + +### ✅ Mark Messages as Read! + +You can now use the brand new [**💬 Read Messages API**]({{< relref "/docs/how-to/chats/#read-messages" >}}) to mark unread messages as read! + +Works across **WEBJS**, **NOWEB**, and **GOWS**! +[#783](https://github.com/devlikeapro/waha/issues/783) + +--- + +### 📥 Group Receipts Tracking + +**WEBJS** now includes: + +- `message.ack` events for group & status messages +- `message._data.receipts` in [**Get Message by ID**]({{< relref "/docs/how-to/chats/#get-message-by-id" >}}) + +You can now **track delivery for each participant**! +[#495](https://github.com/devlikeapro/waha/issues/495), [#900](https://github.com/devlikeapro/waha/issues/900) + +--- + +### 👁️‍🗨️ Bulk Read Support + +Use `messageIds` in [**Send Seen API**]({{< relref "/docs/how-to/send-messages/#send-seen" >}}) to mark **multiple messages as read** in one request. +**NOWEB**, **GOWS** + +--- + +### 🧰 Filter by Ack + +New `filter.ack` option in [**Get Messages API**]({{< relref "/docs/how-to/chats/#get-messages" >}}) — filter messages based on delivery status. +**All engines** + +### 🟢 Send Reaction to Channels + +[**Send Reaction to Channels**]({{< relref "/docs/how-to/channels/#send-reaction-to-the-channel" >}}) is now fixed for **GOWS** and **NOWEB** engines. +[#889](https://github.com/devlikeapro/waha/issues/889) + +### 🌐 Send Link Custom Preview + +[**Send Link Custom Preview**]({{< relref "/docs/how-to/send-messages/#send-link-custom-preview" >}}) has been improved for **GOWS** and **NOWEB** engines. +[#880](https://github.com/devlikeapro/waha/issues/880), [#596](https://github.com/devlikeapro/waha/issues/596) + +![Custom Link Preview](whatsapp-link-preview.png) + +--- + +## 🛠️ Fixes & Stability + +- **NOWEB**: + + - Fix for `protocolMessage` crash [#932](https://github.com/devlikeapro/waha/issues/932) + - Message status updated on `/api/sendSeen` [#635](https://github.com/devlikeapro/waha/issues/635) + - Correct `ack` for new messages (`DEVICE` instead of `UNKNOWN`) + - Fix sending/receiving in **anonymous groups** and **status** + +- **WEBJS**: + + - Auto-restart browser on `ProtocolError` & other errors + [#244](https://github.com/devlikeapro/waha/issues/244), [#936](https://github.com/devlikeapro/waha/issues/936) + +- **GOWS**: + + - Group `message.ack` now sent for **all participants** + - Stability improvements for group/status messages + - Fix sending reactions to other users' messages [#894](https://github.com/devlikeapro/waha/issues/894) + +--- + +## ⚙️ Engine Updates + +- Updated engines: + + - **NOWEB** - latest version + - **GOWS** - latest version + - **WEBJS** - updated **puppeteer** and **chrome** images + +--- + +Check out the full list of updates in the [**🆕 WAHA 2025.4 Changelog**]({{< relref "/docs/overview/changelog#20254" >}}) and stay tuned for more! diff --git a/content/blog/waha-2025-5/index.md b/content/blog/waha-2025-5/index.md index beea55c5c..6829725eb 100644 --- a/content/blog/waha-2025-5/index.md +++ b/content/blog/waha-2025-5/index.md @@ -1,59 +1,60 @@ ---- -title: "WAHA 2025.5 - Presence, Polls, Labels and More!" -description: "WAHA 2025.5 - Presence, Polls, Labels and More!" -excerpt: "WAHA 2025.5 - Presence, Polls, Labels and More!" -date: 2025-05-29T08:48:45+00:00 -draft: false -images: [ "waha-2025-5.png" ] -categories: [ "Releases" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: waha-2025-5 ---- - -## 🆕 What's New? - -### ✅ Presence (WEBJS) - -In **WEBJS**, you can now use the -[**✅ Presence**]({{}}) API and Events -to track your customers' online status! - -### 📶 Polls (GOWS) - -We've added [**📶 Polls**]({{< relref "docs/how-to/polls" >}}) support to **GOWS** - -including API to send polls and Events to receive poll answers! - -### 🏷️ Labels (GOWS) - -Added [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support in the **GOWS** engine. - -### 👤 @lid to @c.us API - -Introduced new -[**👤 Contacts - Lids API**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) -to convert `@lid` format to phone numbers (`@c.us`). - -Available in all engines: **WEBJS**, **GOWS**, **NOWEB**! - -### 💬 Filter Chats by IDs - -You can now filter chats by `ids` in the -[**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API. - -Available in all engines: **WEBJS**, **GOWS**, **NOWEB**! - -## 🛠️ Key Fixes - -- Fixed media fetching from S3/PostgreSQL -- Improved presence subscription handling -- Fixed pairing for Business Accounts connected to Meta API -- Added `tini` to Docker to handle zombie processes -- Fixed empty session name issues in Local Storage - ---- - -## 🆕 Changelog -Check out the full list of updates in the [**🆕 WAHA 2025.5 Changelog**]({{< relref "/docs/overview/changelog#20255" >}}) and stay tuned for more! +--- +title: "WAHA 2025.5 - Presence, Polls, Labels and More!" +description: "WAHA 2025.5 - Presence, Polls, Labels and More!" +excerpt: "WAHA 2025.5 - Presence, Polls, Labels and More!" +date: 2025-05-29T08:48:45+00:00 +draft: false +images: ["waha-2025-5.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-5 +--- + +## 🆕 What's New? + +### ✅ Presence (WEBJS) + +In **WEBJS**, you can now use the +[**✅ Presence**]({{}}) API and Events +to track your customers' online status! + +### 📶 Polls (GOWS) + +We've added [**📶 Polls**]({{< relref "docs/how-to/polls" >}}) support to **GOWS** - +including API to send polls and Events to receive poll answers! + +### 🏷️ Labels (GOWS) + +Added [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support in the **GOWS** engine. + +### 👤 @lid to @c.us API + +Introduced new +[**👤 Contacts - Lids API**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) +to convert `@lid` format to phone numbers (`@c.us`). + +Available in all engines: **WEBJS**, **GOWS**, **NOWEB**! + +### 💬 Filter Chats by IDs + +You can now filter chats by `ids` in the +[**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API. + +Available in all engines: **WEBJS**, **GOWS**, **NOWEB**! + +## 🛠️ Key Fixes + +- Fixed media fetching from S3/PostgreSQL +- Improved presence subscription handling +- Fixed pairing for Business Accounts connected to Meta API +- Added `tini` to Docker to handle zombie processes +- Fixed empty session name issues in Local Storage + +--- + +## 🆕 Changelog + +Check out the full list of updates in the [**🆕 WAHA 2025.5 Changelog**]({{< relref "/docs/overview/changelog#20255" >}}) and stay tuned for more! diff --git a/content/blog/waha-2025-6/index.md b/content/blog/waha-2025-6/index.md index 4cb31f7dc..4651bb825 100644 --- a/content/blog/waha-2025-6/index.md +++ b/content/blog/waha-2025-6/index.md @@ -1,48 +1,47 @@ ---- -title: "WAHA 2025.6 - Security in WAHA Core, Message Edit Event, and Media Conversion" -description: "Enhanced security, message edit tracking, and simplified media conversion in WAHA 2025.6" -excerpt: "Secure API keys, message edit events, and built-in media conversion without manual setup." -date: 2025-06-29T08:48:45+00:00 -draft: false -images: [ "waha-2025-6.png" ] -categories: [ "Releases" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: waha-2025-6 ---- - -## 🆕 What's New? - -### 🔒 Security in WAHA Core - -**WAHA Core** now comes with robust, built-in security features! -You can protect your API with an **API Key** - and now, for even greater security, you can store only the hash of your key using `WAHA_API_KEY=sha512:{HASH}`. -This means your API key is never stored in plain text, reducing the risk if your environment variables are exposed. - -[**🔒 Security →**]({{< relref "/docs/how-to/security" >}}) - -### ✏️ Message Edit Event - -You can now track when a message is edited! -The new [`message.edited`]({{< relref "/docs/how-to/events#messageedited" >}}) event is available in **WEBJS**, **GOWS**, and **NOWEB** engines. - -- **NOWEB note**: Edited protocol messages are now only available via `message.edited` (not in `message` or `message.any`). - -### 🖼️ Media Conversion for WAHA Plus (Voice/Video) - -Sending voice or video files just got easier! - -**WAHA Plus** now supports **built-in media conversion** - no more manual `ffmpeg` setup required. - -- **Voice**: Send any audio file, set `"convert": true`, and WAHA will convert it to WhatsApp’s required OPUS/OGG format. -- **Video**: Send any video file, set `"convert": true`, and WAHA will convert it to WhatsApp’s required MP4 format. -- **APIs**: - - [**POST /api/{session}/media/convert/voice**]({{< relref "/docs/how-to/send-messages#media---convert-voice" >}}) - - [**POST /api/{session}/media/convert/video**]({{< relref "/docs/how-to/send-messages#media---convert-video" >}}) - - -## 🆕 Changelog - -Check out the full list of updates in the [**🆕 WAHA 2025.6 Changelog**]({{< relref "/docs/overview/changelog#20256" >}}) and stay tuned for more! +--- +title: "WAHA 2025.6 - Security in WAHA Core, Message Edit Event, and Media Conversion" +description: "Enhanced security, message edit tracking, and simplified media conversion in WAHA 2025.6" +excerpt: "Secure API keys, message edit events, and built-in media conversion without manual setup." +date: 2025-06-29T08:48:45+00:00 +draft: false +images: ["waha-2025-6.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-6 +--- + +## 🆕 What's New? + +### 🔒 Security in WAHA Core + +**WAHA Core** now comes with robust, built-in security features! +You can protect your API with an **API Key** - and now, for even greater security, you can store only the hash of your key using `WAHA_API_KEY=sha512:{HASH}`. +This means your API key is never stored in plain text, reducing the risk if your environment variables are exposed. + +[**🔒 Security →**]({{< relref "/docs/how-to/security" >}}) + +### ✏️ Message Edit Event + +You can now track when a message is edited! +The new [`message.edited`]({{< relref "/docs/how-to/events#messageedited" >}}) event is available in **WEBJS**, **GOWS**, and **NOWEB** engines. + +- **NOWEB note**: Edited protocol messages are now only available via `message.edited` (not in `message` or `message.any`). + +### 🖼️ Media Conversion for WAHA Plus (Voice/Video) + +Sending voice or video files just got easier! + +**WAHA Plus** now supports **built-in media conversion** - no more manual `ffmpeg` setup required. + +- **Voice**: Send any audio file, set `"convert": true`, and WAHA will convert it to WhatsApp’s required OPUS/OGG format. +- **Video**: Send any video file, set `"convert": true`, and WAHA will convert it to WhatsApp’s required MP4 format. +- **APIs**: + - [**POST /api/{session}/media/convert/voice**]({{< relref "/docs/how-to/send-messages#media---convert-voice" >}}) + - [**POST /api/{session}/media/convert/video**]({{< relref "/docs/how-to/send-messages#media---convert-video" >}}) + +## 🆕 Changelog + +Check out the full list of updates in the [**🆕 WAHA 2025.6 Changelog**]({{< relref "/docs/overview/changelog#20256" >}}) and stay tuned for more! diff --git a/content/blog/waha-2025-7/index.md b/content/blog/waha-2025-7/index.md index 894035089..09f577ee3 100644 --- a/content/blog/waha-2025-7/index.md +++ b/content/blog/waha-2025-7/index.md @@ -1,54 +1,55 @@ ---- -title: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" -description: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" -excerpt: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" -date: 2025-07-29T08:48:45+00:00 -draft: false -images: [ "waha-2025-7.png" ] -categories: [ "Releases" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -slug: waha-2025-7 ---- - -## 🧩 ChatWoot App -Meet the first built-in app in WAHA - [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! - -![](chatwoot-overview.png) - - -WAHA now provides a built-in app to integrate your **WhatsApp** account with **ChatWoot**, -eliminating the need to run n8n or use other third-party products! - -We cover all installation and configuration aspects in the following series of articles: -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -## 👤 Update Contact on Phone -You can now use the -[**👤 Update Contact API**]({{< relref "/docs/how-to/contacts#update-contact" >}}) -to **update contacts** in **your phone address book** (and in WhatsApp)! - -```http request -PUT /api/{session}/contacts/{chatId} -``` - -```json { title="Body" } -{ - "firstName": "John", - "lastName": "Doe" -} -``` - -See details: {{< issue 1124 >}} - -## 📊 Dashboard i18n - -[**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) now has language options available! - -![](dashboard-languages.png) - -## 🆕 And More! - -Check out the full list of updates in the [**🆕 WAHA 2025.7 Changelog**]({{< relref "/docs/overview/changelog#20257" >}}) and stay tuned for more! +--- +title: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" +description: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" +excerpt: "WAHA 2025.7 - ChatWoot App, Dashboard i18n, and more!" +date: 2025-07-29T08:48:45+00:00 +draft: false +images: ["waha-2025-7.png"] +categories: ["Releases"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-2025-7 +--- + +## 🧩 ChatWoot App + +Meet the first built-in app in WAHA - [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! + +![](chatwoot-overview.png) + +WAHA now provides a built-in app to integrate your **WhatsApp** account with **ChatWoot**, +eliminating the need to run n8n or use other third-party products! + +We cover all installation and configuration aspects in the following series of articles: +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +## 👤 Update Contact on Phone + +You can now use the +[**👤 Update Contact API**]({{< relref "/docs/how-to/contacts#update-contact" >}}) +to **update contacts** in **your phone address book** (and in WhatsApp)! + +```http request +PUT /api/{session}/contacts/{chatId} +``` + +```json { title="Body" } +{ + "firstName": "John", + "lastName": "Doe" +} +``` + +See details: {{< issue 1124 >}} + +## 📊 Dashboard i18n + +[**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) now has language options available! + +![](dashboard-languages.png) + +## 🆕 And More! + +Check out the full list of updates in the [**🆕 WAHA 2025.7 Changelog**]({{< relref "/docs/overview/changelog#20257" >}}) and stay tuned for more! diff --git a/content/blog/waha-docker-image-name/index.md b/content/blog/waha-docker-image-name/index.md index ffcd6b06c..12bae772b 100644 --- a/content/blog/waha-docker-image-name/index.md +++ b/content/blog/waha-docker-image-name/index.md @@ -1,22 +1,22 @@ ---- -title: "📣 Docker Image has been renamed to devlikeapro/waha! 📣" -description: "We have renamed docker image to devlikeapro/waha! 🎉" -excerpt: "We have renamed docker image to devlikeapro/waha! 🎉" -date: 2024-05-30T08:48:45+00:00 -draft: false -images: ["new-name.jpg"] -categories: ["News"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false ---- - -We have renamed docker image from `devlikeapro/whatsapp-http-api` to `devlikeapro/waha`! 🎉 - -You can find the image on Docker Hub by the new name. -- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#docker-images" >}}) -- `devlikeapro/waha` - for the Core version -- `devlikeapro/waha-plus` - for the Plus version -- Build: `2024.6.2` - +--- +title: "📣 Docker Image has been renamed to devlikeapro/waha! 📣" +description: "We have renamed docker image to devlikeapro/waha! 🎉" +excerpt: "We have renamed docker image to devlikeapro/waha! 🎉" +date: 2024-05-30T08:48:45+00:00 +draft: false +images: ["new-name.jpg"] +categories: ["News"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +We have renamed docker image from `devlikeapro/whatsapp-http-api` to `devlikeapro/waha`! 🎉 + +You can find the image on Docker Hub by the new name. + +- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#docker-images" >}}) +- `devlikeapro/waha` - for the Core version +- `devlikeapro/waha-plus` - for the Plus version +- Build: `2024.6.2` diff --git a/content/blog/waha-geonode/index.md b/content/blog/waha-geonode/index.md index 265aec413..341e43009 100644 --- a/content/blog/waha-geonode/index.md +++ b/content/blog/waha-geonode/index.md @@ -1,149 +1,148 @@ ---- -title: "WAHA + Geonode Proxy - bypassing errors on Cloud or VPS" -description: "Step-by-step guide on how to use Geonode proxy with WAHA" -excerpt: "Step-by-step guide on how to use Geonode proxy with WAHA" -date: 2024-06-11T08:48:45+00:00 -draft: false -images: [ "proxy.png" ] -categories: [ "Tips" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -toc: true ---- - -## WAHA + Geonode Proxy - -If you see the below error, you can use -the Geonode proxies to solve this issue. - -Read more about [Proxies]({{< relref "/docs/how-to/proxy" >}}). - -> Could not log in. Check your phone's internet connection and try again. -> ![Could not login](could-not-login.png) - -Unfortunately, that issue is caused by the WhatsApp server blocking your IP address - likely you're using Cloud or VPS. -The Geonode proxy is a solution that allows you to bypass this block and continue using WAHA. - -**The issue has nothing to do with WAHA** itself, but with the WhatsApp server blocking your IP address. - -Using -Geonode proxy -you can bypass the block and continue using WAHA in Cloud or VPS. - -💡 **Alternative** is to run [**WAHA locally and expose it with Ngrok**]({{< relref "waha-ngrok" >}}) to bypass the block. - -## Step 1: Register on Geonode - -Go ahead and [Sign Up on Geonode](https://geonode.com/?ref=90920)! - -## Step 2: Get Premium Residential Proxy - -Now you need to get a Premium Residential Proxy from Geonode. - -![alt](geonode-residental-proxy-start.png) - -
- -**1GB ($4)** is enough for the start and tests, but you can get more if you need it -(it depends on your usage and how many sessions you want to run). - -![alt](geonode-purchase.png) - -## Step 3: Setup sticky session - -After you've purchased the proxy, you need to set up a sticky session. - -Go to [Premium Residential Proxy](https://app.geonode.com/pay-as-you-go-residential) and scroll down to **Proxy -Configuration** and select: - -- **Proxy type: Sticky** -- **Protocol: HTTP/HTTPS** -- **Rotating Interval: 24 hours** - -![alt](geonode-proxy-configuration.png) -
-
- -Now let's configure **Country Targeting (Optional)** (it's not optional for us). - -- Select **Country** where YOUR ACCOUNTS (phone numbers) from. -- (Optional) - select **State** if you want to target a specific state -- (Optional) - select **City** if you want to target a specific city -- Select any available **Ports** (one is enough for tests), like `10000` -- Click **Add** - -![alt](geonode-target.png) - -Now you can check the proxy works - copy `curl` command at the top of the page and change port to `10000` (or any you've -selected). - -![alt](test-proxy-curl.png) - -```bash -curl -x premium-residential.geonode.com:10000 -U geonode_1111111111:11111111-1111-1111-1111-111111111111 http://ip-api.com -``` - -![alt](proxy-works.png) - -> If it doesn't work, check the proxy targeting configuration and try again with different ports. - -## Step 4: Start WAHA session with Geonode proxy - -Copy those values from the Geonode dashboard: - -- Username -- Password - -### Option 1 - Start a session using WAHA Dashboard - -Start a session using [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}). - -![alt](waha-proxy.png) - -### Option 2 - Start a session using Swagger - -Or you can use swagger or `curl` to send `POST /api/sessions/` request with payload - -```json -{ - "name": "default", - "start": true, - "config": { - "proxy": { - "server": "premium-residential.geonode.com:10000", - "username": "geonode_1111111111", - "password": "11111111-1111-1111-1111-111111111111" - } - } -} -``` - -After that - scan a QR code and it should work! - -👉 If you see "Could not connect device, try aging later" - **stop** and **start** session again and scan a new QR. - -## Step 5 (optional): Disable proxy for a session - -After you got the session working and **waited for 2 minutes** - you can **stop** a session and **start** it again -**without a proxy**. - -```json -{ - "name": "default" -} -``` - -**Why disable proxy?** - -1. It looks that WA checks the IP address at the start of the session, so you can start a session with a proxy and then - disable it. -2. Proxy is not super stable, so you can disable it and enable it again if you see issues. -3. Proxy is not free, so you can disable it when you don't need it. - -## Alternative - -If that doesn't work for you - you can run [WAHA on your local network and use Ngrok to expose it to the internet]({{< -relref "waha-ngrok" >}}). - +--- +title: "WAHA + Geonode Proxy - bypassing errors on Cloud or VPS" +description: "Step-by-step guide on how to use Geonode proxy with WAHA" +excerpt: "Step-by-step guide on how to use Geonode proxy with WAHA" +date: 2024-06-11T08:48:45+00:00 +draft: false +images: ["proxy.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +toc: true +--- + +## WAHA + Geonode Proxy + +If you see the below error, you can use +the Geonode proxies to solve this issue. + +Read more about [Proxies]({{< relref "/docs/how-to/proxy" >}}). + +> Could not log in. Check your phone's internet connection and try again. +> ![Could not login](could-not-login.png) + +Unfortunately, that issue is caused by the WhatsApp server blocking your IP address - likely you're using Cloud or VPS. +The Geonode proxy is a solution that allows you to bypass this block and continue using WAHA. + +**The issue has nothing to do with WAHA** itself, but with the WhatsApp server blocking your IP address. + +Using +Geonode proxy +you can bypass the block and continue using WAHA in Cloud or VPS. + +💡 **Alternative** is to run [**WAHA locally and expose it with Ngrok**]({{< relref "waha-ngrok" >}}) to bypass the block. + +## Step 1: Register on Geonode + +Go ahead and [Sign Up on Geonode](https://geonode.com/?ref=90920)! + +## Step 2: Get Premium Residential Proxy + +Now you need to get a Premium Residential Proxy from Geonode. + +![alt](geonode-residental-proxy-start.png) + +
+ +**1GB ($4)** is enough for the start and tests, but you can get more if you need it +(it depends on your usage and how many sessions you want to run). + +![alt](geonode-purchase.png) + +## Step 3: Setup sticky session + +After you've purchased the proxy, you need to set up a sticky session. + +Go to [Premium Residential Proxy](https://app.geonode.com/pay-as-you-go-residential) and scroll down to **Proxy +Configuration** and select: + +- **Proxy type: Sticky** +- **Protocol: HTTP/HTTPS** +- **Rotating Interval: 24 hours** + +![alt](geonode-proxy-configuration.png) +
+
+ +Now let's configure **Country Targeting (Optional)** (it's not optional for us). + +- Select **Country** where YOUR ACCOUNTS (phone numbers) from. +- (Optional) - select **State** if you want to target a specific state +- (Optional) - select **City** if you want to target a specific city +- Select any available **Ports** (one is enough for tests), like `10000` +- Click **Add** + +![alt](geonode-target.png) + +Now you can check the proxy works - copy `curl` command at the top of the page and change port to `10000` (or any you've +selected). + +![alt](test-proxy-curl.png) + +```bash +curl -x premium-residential.geonode.com:10000 -U geonode_1111111111:11111111-1111-1111-1111-111111111111 http://ip-api.com +``` + +![alt](proxy-works.png) + +> If it doesn't work, check the proxy targeting configuration and try again with different ports. + +## Step 4: Start WAHA session with Geonode proxy + +Copy those values from the Geonode dashboard: + +- Username +- Password + +### Option 1 - Start a session using WAHA Dashboard + +Start a session using [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}). + +![alt](waha-proxy.png) + +### Option 2 - Start a session using Swagger + +Or you can use swagger or `curl` to send `POST /api/sessions/` request with payload + +```json +{ + "name": "default", + "start": true, + "config": { + "proxy": { + "server": "premium-residential.geonode.com:10000", + "username": "geonode_1111111111", + "password": "11111111-1111-1111-1111-111111111111" + } + } +} +``` + +After that - scan a QR code and it should work! + +👉 If you see "Could not connect device, try aging later" - **stop** and **start** session again and scan a new QR. + +## Step 5 (optional): Disable proxy for a session + +After you got the session working and **waited for 2 minutes** - you can **stop** a session and **start** it again +**without a proxy**. + +```json +{ + "name": "default" +} +``` + +**Why disable proxy?** + +1. It looks that WA checks the IP address at the start of the session, so you can start a session with a proxy and then + disable it. +2. Proxy is not super stable, so you can disable it and enable it again if you see issues. +3. Proxy is not free, so you can disable it when you don't need it. + +## Alternative + +If that doesn't work for you - you can run [WAHA on your local network and use Ngrok to expose it to the internet]({{< +relref "waha-ngrok" >}}). diff --git a/content/blog/waha-https/index.md b/content/blog/waha-https/index.md index ed9c6c47c..72365b513 100644 --- a/content/blog/waha-https/index.md +++ b/content/blog/waha-https/index.md @@ -1,191 +1,196 @@ ---- -title: "Setting up HTTPS for WAHA" -description: "Step-by-step guide on how to set up HTTPS for WAHA" -excerpt: "Step-by-step guide on how to set up HTTPS for WAHA" -date: 2024-06-17T08:48:45+00:00 -draft: false -images: [ "https_icon.png" ] -categories: [ "Tips" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -toc: true ---- - -## Why bother with HTTPS? - -Even if you have set up WAHA and protected it with an API key and username/password -(as we recommend on [**🔒 Security**]({{< relref "/docs/how-to/security" >}})) - it's still not enough, because of -[Man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). -![alt](mitm.png) - -If you're exposing WAHA to the internet, you should **always use HTTPS** to protect your data from being intercepted. - -{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} - -You can set up the following environment variables to enable HTTPS: - -1. [**Let's Encrypt**](#lets-encrypt-certbot--waha) - use [Certbot](https://certbot.eff.org/) to get a free certificate from Let's Encrypt. -2. [**Self-signed certificate**](#self-signed-certificate--waha) - generate a self-signed certificate and use it for HTTPS. -3. [**Using reverse proxy**](#using-external-reverse-proxy) - use Nginx as a reverse proxy and set up HTTPS there. -4. [**Using Ngrok**](#using-ngrok) - expose your WAHA safely on internet, even without Public IP or DNS name. - -## Configuration - - -WAHA supports HTTPS out of the box if you don't want to use a reverse proxy like Nginx. - -You can set up the following environment variables to enable HTTPS: - -- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. -- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` -- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` -- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` - -## Let's Encrypt (Certbot) + WAHA - -![alt](lets-encrypt-certbot.png) - -[**Certbot**](https://certbot.eff.org/) is a free and open-source tool that can be used to get a free certificate -from [Let's Encrypt](https://letsencrypt.org/). - -WAHA can use the certificate generated by Certbot to enable HTTPS. - -### Step 0: Requirements - -Here's assumptions for this guide: - -1. **Dedicated server or VPS** with Public IP ( - like [DigitalOcean DropLet](https://www.digitalocean.com/products/droplets/)) -2. **Ubuntu 22.04** - clean installation -3. **Public IP** assigned to the server (like `109.71.242.111`) -4. **Domain** pointed to the Public IP (like `waha.example.pro`) - -You can get the updated [Certbot documentation](https://certbot.eff.org/instructions?ws=other&os=ubuntufocal), -and **Step 7: Install your certificate** - this is where we need to configure WAHA to use the certificates. - -### Step 1: Install Certbot - -```bash -sudo snap install --classic certbot -sudo ln -s /snap/bin/certbot /usr/bin/certbot -``` - -### Step 2: Issuing certificate - -Choose how you'd like to run Certbot - Are you ok with temporarily stopping your website? - -- **Yes, my web server is not currently running on this machine.** - -Stop your webserver, then run this command to get a certificate. Certbot will temporarily spin up a webserver on your -machine. - -```bash -sudo systemctl stop nginx -sudo certbot certonly --standalone -d waha.example.com # <=== change to your domain -``` - -- **No, I need to keep my web server running.** - -```bash -sudo certbot certonly --webroot -# sudo certbot certonly --webroot /var/www/html -``` - -### Step 3: Run WAHA - -After you get the certificates, you can run it - -👇 Few notes: -- Change `waha.example.pro` to your domain -- We're running it with `-it` flag to see the logs, in production you need to run it with `docker run -d` instead. -- We map the whole `/etc/letsencrypt` folder because of the way how letsencrypt works with "live" keys (it's symlinks to "archive" directory files) - -```bash -DOMAIN=waha.example.pro # Change it to your domain! - -docker run -it \ - -p 3000:3000 \ - -v $(pwd)/.sessions:/app/.sessions \ - -v /etc/letsencrypt:/etc/letsencrypt \ - --env WAHA_HTTPS_ENABLED=true \ - --env WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem \ - --env WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/$DOMAIN/cert.pem \ - --env WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/$DOMAIN/chain.pem \ - --env WHATSAPP_API_SCHEMA=https, - --env WHATSAPP_API_PORT=3000, - --env WHATSAPP_API_HOSTNAME=$DOMAIN \ - --restart always \ - devlikeapro/waha-plus -``` - -Now open [https://waha.example.com:3000](https://waha.example.com:3000) -and check the HTTPS connection. - -If it works - consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) -file for running the project, it can be hard to write such long command or using sh scripts for that. - -### Step 4: Test auto renewal - -When Certbot renew the certificate - WAHA automatically updates HTTPS server and use new certificate with no restart. - -```bash -sudo certbot renew --dry-run -``` - -## Self-signed certificate + WAHA - -As an alternative, you can issue self-signed certificate (for instance, to test the connection on localhost). - -It'll show you an error on browser, so you need to accept it before accessing the site, -but it won't show expose the API key during network communication even in public networks. -![alt](self-signed-certificate-warning.png) - -### Step 1: Generate certificates -```bash -mkdir .secrets -openssl genpkey -algorithm RSA -out .secrets/privkey.pem -pkeyopt rsa_keygen_bits:2048 -openssl req -new -key .secrets/privkey.pem -out .secrets/cert.csr -subj "/" -openssl req -x509 -days 3650 -key .secrets/privkey.pem -in .secrets/cert.csr -out .secrets/cert.pem -cp .secrets/cert.pem .secrets/chain.pem -echo "DONE!" -``` - -### Step 2: Run WAHA -👇 Few notes: -- We're running it with `-it` flag to see the logs, in production you need to run it with `docker run -d` instead. - -```bash -docker run -it \ - -p 3000:3000 \ - -v $(pwd)/.sessions:/app/.sessions \ - -v $(pwd)/.secrets:/app/.secrets \ - -e WAHA_HTTPS_ENABLED=true \ - -e WAHA_HTTPS_PATH_KEY=.secrets/privkey.pem \ - -e WAHA_HTTPS_PATH_CERT=.secrets/cert.pem \ - -e WAHA_HTTPS_PATH_CA=.secrets/chain.pem \ - devlikeapro/waha-plus -``` - -Open [https://localhost:3000](https://localhost:3000) and accept self-signed certificate in your browser. - -If it works - consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) -file for running the project, it can be hard to write such long command or using sh scripts for that. - -## Using External Reverse Proxy - -![alt](ssl-reverse-2.png) -The best way to set up HTTPS is to use a reverse proxy like Nginx. -The idea is WAHA exposes the HTTP port and Nginx handles the HTTPS part and forwards the requests to WAHA. -It distributes the load and make it easier to manage the HTTPS part. - -Unfortunately, it's a bit more complicated than the previous options, so we don't cover it in the guide. - -Here's some articles that can help you set up HTTPS with Nginx and docker-compose: -1. [**Certbot + Nginx + Docker**](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04) - -## Using Ngrok -WAHA + Ngrok - Running WAHA on local network -You also can set up [**WAHA to use Ngrok**]({{< relref "/blog/waha-ngrok" >}}) -so it handles HTTPS for you, even if you're running it NOT on local server! +--- +title: "Setting up HTTPS for WAHA" +description: "Step-by-step guide on how to set up HTTPS for WAHA" +excerpt: "Step-by-step guide on how to set up HTTPS for WAHA" +date: 2024-06-17T08:48:45+00:00 +draft: false +images: ["https_icon.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +toc: true +--- + +## Why bother with HTTPS? + +Even if you have set up WAHA and protected it with an API key and username/password +(as we recommend on [**🔒 Security**]({{< relref "/docs/how-to/security" >}})) - it's still not enough, because of +[Man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). +![alt](mitm.png) + +If you're exposing WAHA to the internet, you should **always use HTTPS** to protect your data from being intercepted. + +{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} + +You can set up the following environment variables to enable HTTPS: + +1. [**Let's Encrypt**](#lets-encrypt-certbot--waha) - use [Certbot](https://certbot.eff.org/) to get a free certificate from Let's Encrypt. +2. [**Self-signed certificate**](#self-signed-certificate--waha) - generate a self-signed certificate and use it for HTTPS. +3. [**Using reverse proxy**](#using-external-reverse-proxy) - use Nginx as a reverse proxy and set up HTTPS there. +4. [**Using Ngrok**](#using-ngrok) - expose your WAHA safely on internet, even without Public IP or DNS name. + +## Configuration + +WAHA supports HTTPS out of the box if you don't want to use a reverse proxy like Nginx. + +You can set up the following environment variables to enable HTTPS: + +- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. +- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` +- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` +- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` + +## Let's Encrypt (Certbot) + WAHA + +![alt](lets-encrypt-certbot.png) + +[**Certbot**](https://certbot.eff.org/) is a free and open-source tool that can be used to get a free certificate +from [Let's Encrypt](https://letsencrypt.org/). + +WAHA can use the certificate generated by Certbot to enable HTTPS. + +### Step 0: Requirements + +Here's assumptions for this guide: + +1. **Dedicated server or VPS** with Public IP ( + like [DigitalOcean DropLet](https://www.digitalocean.com/products/droplets/)) +2. **Ubuntu 22.04** - clean installation +3. **Public IP** assigned to the server (like `109.71.242.111`) +4. **Domain** pointed to the Public IP (like `waha.example.pro`) + +You can get the updated [Certbot documentation](https://certbot.eff.org/instructions?ws=other&os=ubuntufocal), +and **Step 7: Install your certificate** - this is where we need to configure WAHA to use the certificates. + +### Step 1: Install Certbot + +```bash +sudo snap install --classic certbot +sudo ln -s /snap/bin/certbot /usr/bin/certbot +``` + +### Step 2: Issuing certificate + +Choose how you'd like to run Certbot - Are you ok with temporarily stopping your website? + +- **Yes, my web server is not currently running on this machine.** + +Stop your webserver, then run this command to get a certificate. Certbot will temporarily spin up a webserver on your +machine. + +```bash +sudo systemctl stop nginx +sudo certbot certonly --standalone -d waha.example.com # <=== change to your domain +``` + +- **No, I need to keep my web server running.** + +```bash +sudo certbot certonly --webroot +# sudo certbot certonly --webroot /var/www/html +``` + +### Step 3: Run WAHA + +After you get the certificates, you can run it + +👇 Few notes: + +- Change `waha.example.pro` to your domain +- We're running it with `-it` flag to see the logs, in production you need to run it with `docker run -d` instead. +- We map the whole `/etc/letsencrypt` folder because of the way how letsencrypt works with "live" keys (it's symlinks to "archive" directory files) + +```bash +DOMAIN=waha.example.pro # Change it to your domain! + +docker run -it \ + -p 3000:3000 \ + -v $(pwd)/.sessions:/app/.sessions \ + -v /etc/letsencrypt:/etc/letsencrypt \ + --env WAHA_HTTPS_ENABLED=true \ + --env WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem \ + --env WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/$DOMAIN/cert.pem \ + --env WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/$DOMAIN/chain.pem \ + --env WHATSAPP_API_SCHEMA=https, + --env WHATSAPP_API_PORT=3000, + --env WHATSAPP_API_HOSTNAME=$DOMAIN \ + --restart always \ + devlikeapro/waha-plus +``` + +Now open [https://waha.example.com:3000](https://waha.example.com:3000) +and check the HTTPS connection. + +If it works - consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) +file for running the project, it can be hard to write such long command or using sh scripts for that. + +### Step 4: Test auto renewal + +When Certbot renew the certificate - WAHA automatically updates HTTPS server and use new certificate with no restart. + +```bash +sudo certbot renew --dry-run +``` + +## Self-signed certificate + WAHA + +As an alternative, you can issue self-signed certificate (for instance, to test the connection on localhost). + +It'll show you an error on browser, so you need to accept it before accessing the site, +but it won't show expose the API key during network communication even in public networks. +![alt](self-signed-certificate-warning.png) + +### Step 1: Generate certificates + +```bash +mkdir .secrets +openssl genpkey -algorithm RSA -out .secrets/privkey.pem -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key .secrets/privkey.pem -out .secrets/cert.csr -subj "/" +openssl req -x509 -days 3650 -key .secrets/privkey.pem -in .secrets/cert.csr -out .secrets/cert.pem +cp .secrets/cert.pem .secrets/chain.pem +echo "DONE!" +``` + +### Step 2: Run WAHA + +👇 Few notes: + +- We're running it with `-it` flag to see the logs, in production you need to run it with `docker run -d` instead. + +```bash +docker run -it \ + -p 3000:3000 \ + -v $(pwd)/.sessions:/app/.sessions \ + -v $(pwd)/.secrets:/app/.secrets \ + -e WAHA_HTTPS_ENABLED=true \ + -e WAHA_HTTPS_PATH_KEY=.secrets/privkey.pem \ + -e WAHA_HTTPS_PATH_CERT=.secrets/cert.pem \ + -e WAHA_HTTPS_PATH_CA=.secrets/chain.pem \ + devlikeapro/waha-plus +``` + +Open [https://localhost:3000](https://localhost:3000) and accept self-signed certificate in your browser. + +If it works - consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) +file for running the project, it can be hard to write such long command or using sh scripts for that. + +## Using External Reverse Proxy + +![alt](ssl-reverse-2.png) +The best way to set up HTTPS is to use a reverse proxy like Nginx. +The idea is WAHA exposes the HTTP port and Nginx handles the HTTPS part and forwards the requests to WAHA. +It distributes the load and make it easier to manage the HTTPS part. + +Unfortunately, it's a bit more complicated than the previous options, so we don't cover it in the guide. + +Here's some articles that can help you set up HTTPS with Nginx and docker-compose: + +1. [**Certbot + Nginx + Docker**](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04) + +## Using Ngrok + +WAHA + Ngrok - Running WAHA on local network +You also can set up [**WAHA to use Ngrok**]({{< relref "/blog/waha-ngrok" >}}) +so it handles HTTPS for you, even if you're running it NOT on local server! diff --git a/content/blog/waha-n8n/index.md b/content/blog/waha-n8n/index.md index 4e0e77931..53279a390 100644 --- a/content/blog/waha-n8n/index.md +++ b/content/blog/waha-n8n/index.md @@ -1,143 +1,161 @@ ---- -title: "WAHA + n8n: No Code Low Code WhatsApp Automation Step-By-Step Guide" -description: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" -excerpt: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" -date: 2024-08-27T08:48:45+00:00 -draft: false -images: ["waha-n8n.png"] -categories: ["Tips"] -tags: [] -contributors: ["devlikeapro"] -pinned: false -homepage: false -slug: waha-n8n -aliases: - - /blog/waha-n8n ---- - -

- -

- -Here's how you can start developing your WhatsApp automation with using **n8n** and **WAHA** in pair so you can create -your own no-code or low-code **WhatsApp automation**: - -{{< imgo src="/images/n8n/waha-n8n.png" >}} - -## Installation -Here's a quick docker-compose we have prepared for you to start using **n8n** with **WAHA**: - -```bash -wget https://raw.githubusercontent.com/devlikeapro/waha/core/docker-compose/n8n/docker-compose.yaml -``` - - -- If you're using [**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) (donation version) - kindly go to -[https://portal.devlike.pro](https://portal.devlike.pro) -and docker pull the image with your credentials: -```bash -docker login -u devlikeapro -p -docker pull devlikeapro/waha-plus -docker logout -``` - -- If you're using **WAHA Core** (free version) - you can use the image from Docker Hub: -```bash -sed -i 's/devlikeapro\/waha-plus/devlikeapro\/waha/g' docker-compose.yaml -``` - -Now you're ready to run: -```bash -docker compose up -# to run in background: -# docker compose up -d -``` - -After that, open: -1. **n8n** at [https://localhost:5678](https://localhost:5678) and set up your email/password -2. **WAHA** at [https://localhost:3000/dashboard](https://localhost:3000/dashboard) (`admin/admin`) - -### Install WAHA n8n node -We provide WAHA Node, which you can install at your n8n installation. - -Go to your **n8n** => **Settings** => **Community nodes** and install: -```bash -@devlikeapro/n8n-nodes-waha -``` - -If you need help with that, check the -[**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) - - -## First WhatsApp workflow -We'll build simple workflow - when your WhatsApp account got any message, -it responds with **"Hi there"** message - -### Step 1: Add WAHA API credentials -Before starting using the node, you need to add **WAHA API** credentials. -1. Go to your **n8n** => **Home** => **Credentials** => **Add first credential** -2. Find **WAHA API** in dropdown -3. **Host URL** - `http://waha:3000` or use your domain -4. **API Key** - `admin` or your API key set in `docker-compose.yaml` -5. Click **Save** - it'll check the connection and save the credentials - -{{< imgo src="/images/blog/waha-n8n/waha-n8n-credentials.png" >}} - -If you need help with that, check the -[**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) - -### Step 2: Create a new workflow -1. Go to **n8n** => **Home** => **Workflows** => **Create new workflow**. -2. Remove **Manual trigger** - -{{< imgo src="/images/blog/waha-n8n/waha-n8n-init-workflow.png" >}} - -### Step 3: Add WAHA Trigger -Add **WAHA Trigger** node. - -{{< imgo src="/images/blog/waha-n8n/waha-n8n-WAHATrigger.png" >}} - -### Step 4: Add Send a text message action -Add **Send a text message** **WAHA Action** and connect it to `message` **WAHA Trigger** output: -{{< imgo src="/images/blog/waha-n8n/waha-n8n-actions.png" >}} - -### Step 5: Activate the workflow -Click **Save** and **Activate** the workflow: -{{< imgo src="/images/blog/waha-n8n/waha-n8n-activate-workflow.png" >}} - -### Step 6: Start a new session -Open the **WAHA Trigger** and expand **Webhook URLs** => **Production URL** -{{< imgo src="/images/blog/waha-n8n/waha-n8n-WAHATrigger-url.png" >}} - -Go to [http://localhost:3000/dashboard/](http://localhost:3000/dashboard/) (`admin/admin`) and -**Start New** session with the URL you got from the **WAHA Trigger**: -{{< imgo src="/images/blog/waha-n8n/waha-n8n-dashboard-session.png" >}} - -**Scan QR** and wait till session in `WORKING` state: -{{< imgo src="/images/blog/waha-n8n/waha-n8n-dashboard-scan-qr.png" >}} - -### Step 7: Send a message -Now you can **send any message** to your WhatsApp account, and it'll respond with **"Hi there"** message! - -## Workflow Templates -👉 Check out -[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) -for workflow templates! - -{{< imgo src="/images/n8n/waha-n8n.png" >}} - -## Troubleshooting -If you're experiencing any issues or have a feature request, please check the below resources: -**WAHA**: -- [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) -- [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) -- [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) - -**n8n**: -- [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) -- [**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) -- [**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) - -If that doesn't help - kindly open an issue in the -[**devlikeapro/n8n-nodes-waha**](https://github.com/devlikeapro/n8n-nodes-waha/) -GitHub repository, we're happy to help you out! +--- +title: "WAHA + n8n: No Code Low Code WhatsApp Automation Step-By-Step Guide" +description: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" +excerpt: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" +date: 2024-08-27T08:48:45+00:00 +draft: false +images: ["waha-n8n.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +slug: waha-n8n +aliases: + - /blog/waha-n8n +--- + +

+ +

+ +Here's how you can start developing your WhatsApp automation with using **n8n** and **WAHA** in pair so you can create +your own no-code or low-code **WhatsApp automation**: + +{{< imgo src="/images/n8n/waha-n8n.png" >}} + +## Installation + +Here's a quick docker-compose we have prepared for you to start using **n8n** with **WAHA**: + +```bash +wget https://raw.githubusercontent.com/devlikeapro/waha/core/docker-compose/n8n/docker-compose.yaml +``` + +- If you're using [**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) (donation version) - kindly go to + [https://portal.devlike.pro](https://portal.devlike.pro) + and docker pull the image with your credentials: + +```bash +docker login -u devlikeapro -p +docker pull devlikeapro/waha-plus +docker logout +``` + +- If you're using **WAHA Core** (free version) - you can use the image from Docker Hub: + +```bash +sed -i 's/devlikeapro\/waha-plus/devlikeapro\/waha/g' docker-compose.yaml +``` + +Now you're ready to run: + +```bash +docker compose up +# to run in background: +# docker compose up -d +``` + +After that, open: + +1. **n8n** at [https://localhost:5678](https://localhost:5678) and set up your email/password +2. **WAHA** at [https://localhost:3000/dashboard](https://localhost:3000/dashboard) (`admin/admin`) + +### Install WAHA n8n node + +We provide WAHA Node, which you can install at your n8n installation. + +Go to your **n8n** => **Settings** => **Community nodes** and install: + +```bash +@devlikeapro/n8n-nodes-waha +``` + +If you need help with that, check the +[**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) + +## First WhatsApp workflow + +We'll build simple workflow - when your WhatsApp account got any message, +it responds with **"Hi there"** message + +### Step 1: Add WAHA API credentials + +Before starting using the node, you need to add **WAHA API** credentials. + +1. Go to your **n8n** => **Home** => **Credentials** => **Add first credential** +2. Find **WAHA API** in dropdown +3. **Host URL** - `http://waha:3000` or use your domain +4. **API Key** - `admin` or your API key set in `docker-compose.yaml` +5. Click **Save** - it'll check the connection and save the credentials + +{{< imgo src="/images/blog/waha-n8n/waha-n8n-credentials.png" >}} + +If you need help with that, check the +[**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) + +### Step 2: Create a new workflow + +1. Go to **n8n** => **Home** => **Workflows** => **Create new workflow**. +2. Remove **Manual trigger** + +{{< imgo src="/images/blog/waha-n8n/waha-n8n-init-workflow.png" >}} + +### Step 3: Add WAHA Trigger + +Add **WAHA Trigger** node. + +{{< imgo src="/images/blog/waha-n8n/waha-n8n-WAHATrigger.png" >}} + +### Step 4: Add Send a text message action + +Add **Send a text message** **WAHA Action** and connect it to `message` **WAHA Trigger** output: +{{< imgo src="/images/blog/waha-n8n/waha-n8n-actions.png" >}} + +### Step 5: Activate the workflow + +Click **Save** and **Activate** the workflow: +{{< imgo src="/images/blog/waha-n8n/waha-n8n-activate-workflow.png" >}} + +### Step 6: Start a new session + +Open the **WAHA Trigger** and expand **Webhook URLs** => **Production URL** +{{< imgo src="/images/blog/waha-n8n/waha-n8n-WAHATrigger-url.png" >}} + +Go to [http://localhost:3000/dashboard/](http://localhost:3000/dashboard/) (`admin/admin`) and +**Start New** session with the URL you got from the **WAHA Trigger**: +{{< imgo src="/images/blog/waha-n8n/waha-n8n-dashboard-session.png" >}} + +**Scan QR** and wait till session in `WORKING` state: +{{< imgo src="/images/blog/waha-n8n/waha-n8n-dashboard-scan-qr.png" >}} + +### Step 7: Send a message + +Now you can **send any message** to your WhatsApp account, and it'll respond with **"Hi there"** message! + +## Workflow Templates + +👉 Check out +[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) +for workflow templates! + +{{< imgo src="/images/n8n/waha-n8n.png" >}} + +## Troubleshooting + +If you're experiencing any issues or have a feature request, please check the below resources: +**WAHA**: + +- [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) +- [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) +- [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) + +**n8n**: + +- [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) +- [**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) +- [**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) + +If that doesn't help - kindly open an issue in the +[**devlikeapro/n8n-nodes-waha**](https://github.com/devlikeapro/n8n-nodes-waha/) +GitHub repository, we're happy to help you out! diff --git a/content/blog/waha-ngrok/index.md b/content/blog/waha-ngrok/index.md index c8050fef5..a4177e947 100644 --- a/content/blog/waha-ngrok/index.md +++ b/content/blog/waha-ngrok/index.md @@ -1,70 +1,70 @@ ---- -title: "WAHA + Ngrok - Running WAHA on local network" -description: "Step-by-step guide on how to run WAHA on local network using Ngrok" -excerpt: "Step-by-step guide on how to run WAHA on local network using Ngrok (so you can use it on Cloud or VPS)" -date: 2024-06-11T08:48:45+00:00 -draft: false -images: [ "ngrok.png" ] -categories: [ "Tips" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false -toc: true ---- - -## WAHA + Ngrok - -If you see the below error, you can use -the Geonode proxies to solve this issue. - -> Could not log in. Check your phone's internet connection and try again. -> ![Could not login](could-not-login.png) - -Unfortunately, that issue is caused by the WhatsApp server blocking your IP address - likely you're using Cloud or VPS. -The Geonode proxy is a solution that allows you to bypass this block and continue using WAHA. - -**The issue has nothing to do with WAHA** itself, but with the WhatsApp server blocking your IP address. - -You can bypass the block and continue using WAHA in Cloud or VPS by hosting it on your local network and using Ngrok to -expose it to the internet. - -💡 **Alternative** is to [**use Geonode proxy with WAHA**]({{< relref "waha-geonode" >}}) to bypass the block. - -## Step 1: Run WAHA on local network - -Run WAHA on local network (like dedicated home server, spare laptop): - -```bash -docker run -d --name waha -v `pwd`/.sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus -# Or WAHA Core -# docker run -p 3000:3000 devlikeapro/waha -``` - -Start and scan the QR code to connect to WhatsApp. - -## Step 2: Expose WAHA with Ngrok - -Download and install [Ngrok](https://ngrok.com/). - -{{< callout context="note" icon="outline/info-circle" >}} -You can test it with a free account, but you'll need a paid account to use a static name. -{{< /callout >}} - -Run Ngrok and expose the WAHA port: - -```bash -ngrok http 3000 -``` - -Now you can see the Ngrok URL that you can use to access WAHA from the internet. -![alt](ngrok-3000.png) - -## Step 3: Use Ngrok URL in your app - -Now you can use the Ngrok URL in your app to connect to WAHA! - -## Alternative - -If you don't want to run WAHA on your local network, you can [use Geonode proxy]({{< relref "waha-geonode" >}}) to -bypass the block. +--- +title: "WAHA + Ngrok - Running WAHA on local network" +description: "Step-by-step guide on how to run WAHA on local network using Ngrok" +excerpt: "Step-by-step guide on how to run WAHA on local network using Ngrok (so you can use it on Cloud or VPS)" +date: 2024-06-11T08:48:45+00:00 +draft: false +images: ["ngrok.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +toc: true +--- + +## WAHA + Ngrok + +If you see the below error, you can use +the Geonode proxies to solve this issue. + +> Could not log in. Check your phone's internet connection and try again. +> ![Could not login](could-not-login.png) + +Unfortunately, that issue is caused by the WhatsApp server blocking your IP address - likely you're using Cloud or VPS. +The Geonode proxy is a solution that allows you to bypass this block and continue using WAHA. + +**The issue has nothing to do with WAHA** itself, but with the WhatsApp server blocking your IP address. + +You can bypass the block and continue using WAHA in Cloud or VPS by hosting it on your local network and using Ngrok to +expose it to the internet. + +💡 **Alternative** is to [**use Geonode proxy with WAHA**]({{< relref "waha-geonode" >}}) to bypass the block. + +## Step 1: Run WAHA on local network + +Run WAHA on local network (like dedicated home server, spare laptop): + +```bash +docker run -d --name waha -v `pwd`/.sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus +# Or WAHA Core +# docker run -p 3000:3000 devlikeapro/waha +``` + +Start and scan the QR code to connect to WhatsApp. + +## Step 2: Expose WAHA with Ngrok + +Download and install [Ngrok](https://ngrok.com/). + +{{< callout context="note" icon="outline/info-circle" >}} +You can test it with a free account, but you'll need a paid account to use a static name. +{{< /callout >}} + +Run Ngrok and expose the WAHA port: + +```bash +ngrok http 3000 +``` + +Now you can see the Ngrok URL that you can use to access WAHA from the internet. +![alt](ngrok-3000.png) + +## Step 3: Use Ngrok URL in your app + +Now you can use the Ngrok URL in your app to connect to WAHA! + +## Alternative + +If you don't want to run WAHA on your local network, you can [use Geonode proxy]({{< relref "waha-geonode" >}}) to +bypass the block. diff --git a/content/blog/waha-scaling/index.md b/content/blog/waha-scaling/index.md index 05790dbb0..fa2bf7002 100644 --- a/content/blog/waha-scaling/index.md +++ b/content/blog/waha-scaling/index.md @@ -1,197 +1,198 @@ ---- -title: "WAHA Scaling - How To Handle 500+ Sessions" -description: "WAHA Scaling - how to scale WAHA for >500 sessions with Vertical and Horizontal scaling" -excerpt: "WAHA Scaling - how to scale WAHA for >500 sessions with Vertical and Horizontal scaling" -date: 2024-08-14T08:48:45+00:00 -draft: false -images: [ "horizontal-vs-vertical-scaling.png" ] -categories: [ "Tips" ] -tags: [ ] -contributors: [ "devlikeapro" ] -pinned: false -homepage: false ---- - -## Overview - -This article is for people who want to scale their WhatsApp API for customers, like CRM, SaaS, or other services and -who need to handle a lot (**>100**) of [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) (WhatsApp Accounts). - -If you're using WAHA for **1-10** sessions - just make sure to follow the -[**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide. -It handles all the necessary steps to make it work. 🚀 - -There are two ways to scale WAHA: - -1. [**Vertical Scaling**](#vertical-scaling) - adding more resources (CPU, RAM) to **a single server** to - handle more sessions. That's a good way to go if you need to handle up to **50** sessions (**WEBJS**) or **500** - sessions (**NOWEB**). -2. [**Horizontal Scaling**](#horizontal-scaling---sharding) - adding more servers to handle more sessions. - Requires a bit more work to set up, but it's the best way to go if you need to handle more than **500** sessions. - -## Vertical Scaling - -![alt](waha-scaling-up.drawio.png) - -**Vertical Scaling** is the process of adding more resources (CPU, RAM) to a single server to handle more sessions. - -Assuming you've followed the guide [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) and -you have something like this architecture: - -{{< imgo src="/images/waha/scaling/waha-vertical-scaling.drawio.png" >}} - -**How many sessions can you run by adding more resources (CPU and RAM) to a single WAHA server?** - -Here's an -[approximate example of how many sessions you can run on a single server]({{< relref "/docs/overview/faq#system-requirements" >}}) -using the **Vertical Scaling** approach: - -| [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) | Sessions | CPU | Memory | -|:-------------------------------------------------------|----------|-------|--------| -| **WEBJS** | 10 | 270% | 2.5GB | -| **WEBJS** | 50 | 1500% | 20GB | -| **NOWEB** | 50 | 150% | 4GB | -| **NOWEB** | 500 | 300% | 30GB | - -👉 The benchmark may differ from case to case, depending on usage patterns - how many messages you receive, -how many you send, etc. - -So if you need to run up to **50** sessions on the **WEBJS** engine or up to **500** sessions on **NOWEB** - you -can just keep adding more resources (CPU and RAM) to the single server! -Fast to scale, easy to manage. 🎉 - -If you want to run more sessions - you need to consider **Horizontal Scaling**. -It's not safe to run more than the above numbers on a single server! - -## Horizontal Scaling - Sharding - -![alt](waha-scaling-hor.drawio.png) - -**Horizontal Scaling** is the process of adding **more servers** to handle more sessions. - -Right now, the only way to do it is to run multiple WAHA instances and distribute the sessions between them in -**Your Application** logic using the **Sharding** technique: - -{{< imgo src="/images/waha/scaling/waha-horizontal-scaling.drawio.png" >}} - -Here are the key points for setting up **Horizontal Scaling** using the **Sharding** technique: - -1. You run **multiple WAHA** instances listening on different **hostnames** -(`http://waha1.example.com`, `http://waha2.example.com`, etc.) or **ports** -(`http://waha.example.com:3001`, `http://waha.example.com:3002`, etc.). -2. You save the list of `url`, `api-key`, `capacity` to **Your Application Database** - -[**Entities Schema**](#entities-schema) -3. When a new user asks to run a new session - you follow the [**Where to run a new session?**](#where-to-run-a-new-session) - logic to find a suitable WAHA instance and save the `user <-> session <-> server` association to **Your Application Database**. -4. When you need to send a request to WhatsApp API - you follow the - [**Where to find the session?**](#where-to-find-the-session) logic to find the WAHA instance to send the request. -5. All webhooks come to **Your Application** directly from the WAHA instance, so you don't need to worry about it. - -We'll guide you through the process of setting up **Horizontal Scaling** -using the **Sharding** technique in the next sections. - -👉 Please note that each **WAHA Worker** must have its own database or `WAHA_WORKER_ID=waha{N}` environment variable set -for either **File Storage** or **MongoDB** URL (not a database). - -### Entities Schema - -In order to save WAHA instances and session associations, you -need to have the following entities in **Your Application Database**: -![alt](entities-schema.png) - -#### Worker - -**Worker** represents a single WAHA instance that can handle sessions. - -- `id` - unique identifier -- `url` - URL of the WAHA instance, `http://waha1.example.com`, `http://waha2.example.com`, etc. -- `api_key` - API Key to authorize requests -- `capacity` - how many sessions can be run on the WAHA instance (for simplicity, we're using a single field, - but it can be a new model **AvailableSession** or similar). - -By setting `capacity`, you can manage the WAHA Worker usage and prevent overloading. - -#### User - -**User** is a user of **Your Application** that can run sessions. - -- `id` - unique identifier - -👉 You can use either **User** or **Tenant** or **Organization** - it completely depends on your application logic -and business model. -We'll use **User** for simplicity with a single field: - -#### WAHASession - -**WAHASession** represents a single session that is running on the WAHA **Worker** associated with the **User**. - -- `id` - unique identifier -- `name` - WAHA session `name` -- `user_id` - reference to the **User** -- `worker_id` - reference to the **Worker** - -### Where to run a new session? - -When a new user asks to **run a new session** - you need to find a suitable WAHA instance to run it. -You can simply get a list of sessions with `capacity>0` and pick the one with the highest `capacity`. -{{< imgo src="/images/waha/scaling/waha-run-session.png" >}} - -This is just an example with simple logic. You can adjust it and distribute WhatsApp sessions based on **country**, **proxy -settings**, -customer level, etc. - -### Where to find the session? - -When you need to **send a request** to WhatsApp API - you need to find the WAHA instance to send the request. -You can simply get the `worker_id` from the **WAHASession** and send the request to the WAHA instance using -the `url` and `api_key`. -{{< imgo src="/images/waha/scaling/waha-send-request.png" >}} - -### Why this way? - -**WAHA** is not a stateless application, it has **a runtime state** (not technically a state as in database, but still a -state) - **the connection to WhatsApp** (either browser or websocket connection) which cannot be moved automatically, -so all HTTP requests MUST be **"sticky"**, meaning they **MUST** go only to the certain "worker" - **one with a "running" session**. - -This is why we cannot simply run more containers using Kubernetes Deployment/AWS ECS -(though you can use [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) for k8s). -We need to care about WHERE we run the session and WHERE we send the request. - -And a few more reasons: - -- **Simple** - you don't need to worry about the load balancer, k8s, docker, etc. -- **Independent** - you can run WAHA instances on different servers, different cloud providers, bare-metal, etc. -- **No single point of failure** - if one WAHA instance goes down - the others are still working. -- **Flexible** - you can configure HOW you distribute sessions across different servers based on your business logic. -- **Frees our hands** - we can focus on building the best WhatsApp API and adding new features, - and you can focus on building the best application. 😊 - -### Single Dashboard - Multiple Servers -If you're running multiple servers, -you can run a dedicated WAHA [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) just to have a single place from which you can manage all servers: - -{{< imgo src="/images/waha/dashboard/waha-dashboard-servers.drawio.png" >}} - -After that, you can connect all servers to the single dashboard: - -{{< imgo src="/images/waha/dashboard/waha-single-dashboard-multiple-servers.png" >}} - -## Horizontal Scaling - Auto-Scaling - -🚧🔨⏳ Auto-Scaling **IS NOT AVAILABLE** out-of-the-box in WAHA yet! ⏳🔨🚧 - -We're working on it, but it's not ready yet, so we're just giving you a future vision of how it will work. - -The idea is to build **WAHA Hub** that will handle all API requests and distribute them to the **WAHA Workers** -based on information about where each session is running. - -It'll also control (using underlying k8s or docker infrastructure) the number of workers based on the load. - -{{< imgo src="/images/waha/scaling/waha-hub.png" >}} - -Kindly [**support the project**]({{< relref "/support-us" >}}) on the **PRO** tier if you wish to -use this feature in the future! 🙏 - -For now, [**Vertical Scaling**](#vertical-scaling) and -[**Horizontal Scaling - Sharding**](#horizontal-scaling---sharding) -are the ways to go. +--- +title: "WAHA Scaling - How To Handle 500+ Sessions" +description: "WAHA Scaling - how to scale WAHA for >500 sessions with Vertical and Horizontal scaling" +excerpt: "WAHA Scaling - how to scale WAHA for >500 sessions with Vertical and Horizontal scaling" +date: 2024-08-14T08:48:45+00:00 +draft: false +images: ["horizontal-vs-vertical-scaling.png"] +categories: ["Tips"] +tags: [] +contributors: ["devlikeapro"] +pinned: false +homepage: false +--- + +## Overview + +This article is for people who want to scale their WhatsApp API for customers, like CRM, SaaS, or other services and +who need to handle a lot (**>100**) of [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) (WhatsApp Accounts). + +If you're using WAHA for **1-10** sessions - just make sure to follow the +[**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide. +It handles all the necessary steps to make it work. 🚀 + +There are two ways to scale WAHA: + +1. [**Vertical Scaling**](#vertical-scaling) - adding more resources (CPU, RAM) to **a single server** to + handle more sessions. That's a good way to go if you need to handle up to **50** sessions (**WEBJS**) or **500** + sessions (**NOWEB**). +2. [**Horizontal Scaling**](#horizontal-scaling---sharding) - adding more servers to handle more sessions. + Requires a bit more work to set up, but it's the best way to go if you need to handle more than **500** sessions. + +## Vertical Scaling + +![alt](waha-scaling-up.drawio.png) + +**Vertical Scaling** is the process of adding more resources (CPU, RAM) to a single server to handle more sessions. + +Assuming you've followed the guide [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) and +you have something like this architecture: + +{{< imgo src="/images/waha/scaling/waha-vertical-scaling.drawio.png" >}} + +**How many sessions can you run by adding more resources (CPU and RAM) to a single WAHA server?** + +Here's an +[approximate example of how many sessions you can run on a single server]({{< relref "/docs/overview/faq#system-requirements" >}}) +using the **Vertical Scaling** approach: + +| [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) | Sessions | CPU | Memory | +| :----------------------------------------------------- | -------- | ----- | ------ | +| **WEBJS** | 10 | 270% | 2.5GB | +| **WEBJS** | 50 | 1500% | 20GB | +| **NOWEB** | 50 | 150% | 4GB | +| **NOWEB** | 500 | 300% | 30GB | + +👉 The benchmark may differ from case to case, depending on usage patterns - how many messages you receive, +how many you send, etc. + +So if you need to run up to **50** sessions on the **WEBJS** engine or up to **500** sessions on **NOWEB** - you +can just keep adding more resources (CPU and RAM) to the single server! +Fast to scale, easy to manage. 🎉 + +If you want to run more sessions - you need to consider **Horizontal Scaling**. +It's not safe to run more than the above numbers on a single server! + +## Horizontal Scaling - Sharding + +![alt](waha-scaling-hor.drawio.png) + +**Horizontal Scaling** is the process of adding **more servers** to handle more sessions. + +Right now, the only way to do it is to run multiple WAHA instances and distribute the sessions between them in +**Your Application** logic using the **Sharding** technique: + +{{< imgo src="/images/waha/scaling/waha-horizontal-scaling.drawio.png" >}} + +Here are the key points for setting up **Horizontal Scaling** using the **Sharding** technique: + +1. You run **multiple WAHA** instances listening on different **hostnames** + (`http://waha1.example.com`, `http://waha2.example.com`, etc.) or **ports** + (`http://waha.example.com:3001`, `http://waha.example.com:3002`, etc.). +2. You save the list of `url`, `api-key`, `capacity` to **Your Application Database** - + [**Entities Schema**](#entities-schema) +3. When a new user asks to run a new session - you follow the [**Where to run a new session?**](#where-to-run-a-new-session) + logic to find a suitable WAHA instance and save the `user <-> session <-> server` association to **Your Application Database**. +4. When you need to send a request to WhatsApp API - you follow the + [**Where to find the session?**](#where-to-find-the-session) logic to find the WAHA instance to send the request. +5. All webhooks come to **Your Application** directly from the WAHA instance, so you don't need to worry about it. + +We'll guide you through the process of setting up **Horizontal Scaling** +using the **Sharding** technique in the next sections. + +👉 Please note that each **WAHA Worker** must have its own database or `WAHA_WORKER_ID=waha{N}` environment variable set +for either **File Storage** or **MongoDB** URL (not a database). + +### Entities Schema + +In order to save WAHA instances and session associations, you +need to have the following entities in **Your Application Database**: +![alt](entities-schema.png) + +#### Worker + +**Worker** represents a single WAHA instance that can handle sessions. + +- `id` - unique identifier +- `url` - URL of the WAHA instance, `http://waha1.example.com`, `http://waha2.example.com`, etc. +- `api_key` - API Key to authorize requests +- `capacity` - how many sessions can be run on the WAHA instance (for simplicity, we're using a single field, + but it can be a new model **AvailableSession** or similar). + +By setting `capacity`, you can manage the WAHA Worker usage and prevent overloading. + +#### User + +**User** is a user of **Your Application** that can run sessions. + +- `id` - unique identifier + +👉 You can use either **User** or **Tenant** or **Organization** - it completely depends on your application logic +and business model. +We'll use **User** for simplicity with a single field: + +#### WAHASession + +**WAHASession** represents a single session that is running on the WAHA **Worker** associated with the **User**. + +- `id` - unique identifier +- `name` - WAHA session `name` +- `user_id` - reference to the **User** +- `worker_id` - reference to the **Worker** + +### Where to run a new session? + +When a new user asks to **run a new session** - you need to find a suitable WAHA instance to run it. +You can simply get a list of sessions with `capacity>0` and pick the one with the highest `capacity`. +{{< imgo src="/images/waha/scaling/waha-run-session.png" >}} + +This is just an example with simple logic. You can adjust it and distribute WhatsApp sessions based on **country**, **proxy +settings**, +customer level, etc. + +### Where to find the session? + +When you need to **send a request** to WhatsApp API - you need to find the WAHA instance to send the request. +You can simply get the `worker_id` from the **WAHASession** and send the request to the WAHA instance using +the `url` and `api_key`. +{{< imgo src="/images/waha/scaling/waha-send-request.png" >}} + +### Why this way? + +**WAHA** is not a stateless application, it has **a runtime state** (not technically a state as in database, but still a +state) - **the connection to WhatsApp** (either browser or websocket connection) which cannot be moved automatically, +so all HTTP requests MUST be **"sticky"**, meaning they **MUST** go only to the certain "worker" - **one with a "running" session**. + +This is why we cannot simply run more containers using Kubernetes Deployment/AWS ECS +(though you can use [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) for k8s). +We need to care about WHERE we run the session and WHERE we send the request. + +And a few more reasons: + +- **Simple** - you don't need to worry about the load balancer, k8s, docker, etc. +- **Independent** - you can run WAHA instances on different servers, different cloud providers, bare-metal, etc. +- **No single point of failure** - if one WAHA instance goes down - the others are still working. +- **Flexible** - you can configure HOW you distribute sessions across different servers based on your business logic. +- **Frees our hands** - we can focus on building the best WhatsApp API and adding new features, + and you can focus on building the best application. 😊 + +### Single Dashboard - Multiple Servers + +If you're running multiple servers, +you can run a dedicated WAHA [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) just to have a single place from which you can manage all servers: + +{{< imgo src="/images/waha/dashboard/waha-dashboard-servers.drawio.png" >}} + +After that, you can connect all servers to the single dashboard: + +{{< imgo src="/images/waha/dashboard/waha-single-dashboard-multiple-servers.png" >}} + +## Horizontal Scaling - Auto-Scaling + +🚧🔨⏳ Auto-Scaling **IS NOT AVAILABLE** out-of-the-box in WAHA yet! ⏳🔨🚧 + +We're working on it, but it's not ready yet, so we're just giving you a future vision of how it will work. + +The idea is to build **WAHA Hub** that will handle all API requests and distribute them to the **WAHA Workers** +based on information about where each session is running. + +It'll also control (using underlying k8s or docker infrastructure) the number of workers based on the load. + +{{< imgo src="/images/waha/scaling/waha-hub.png" >}} + +Kindly [**support the project**]({{< relref "/support-us" >}}) on the **PRO** tier if you wish to +use this feature in the future! 🙏 + +For now, [**Vertical Scaling**](#vertical-scaling) and +[**Horizontal Scaling - Sharding**](#horizontal-scaling---sharding) +are the ways to go. diff --git a/content/contact/_index.md b/content/contact/_index.md index 5aaa2adc2..8edfcb34f 100644 --- a/content/contact/_index.md +++ b/content/contact/_index.md @@ -1,12 +1,9 @@ ---- -title: "Contact" -description: "Drop us an email." -date: 2020-08-27T19:25:12+02:00 -lastmod: 2020-08-27T19:25:12+02:00 -draft: false - ---- - -Get In Touch With The Team! - - +--- +title: "Contact" +description: "Drop us an email." +date: 2020-08-27T19:25:12+02:00 +lastmod: 2020-08-27T19:25:12+02:00 +draft: false +--- + +Get In Touch With The Team! diff --git a/content/contributors/_index.md b/content/contributors/_index.md index 1a7e2654c..a98ac51d7 100644 --- a/content/contributors/_index.md +++ b/content/contributors/_index.md @@ -1,10 +1,9 @@ ---- -title: "Contributors" -description: "The WAHA contributors." -date: 2020-10-06T08:50:29+00:00 -lastmod: 2020-10-06T08:50:29+00:00 -draft: false - ---- - -The WAHA contributors. +--- +title: "Contributors" +description: "The WAHA contributors." +date: 2020-10-06T08:50:29+00:00 +lastmod: 2020-10-06T08:50:29+00:00 +draft: false +--- + +The WAHA contributors. diff --git a/content/contributors/devlikeapro/_index.md b/content/contributors/devlikeapro/_index.md index 98eaabded..3864d256b 100644 --- a/content/contributors/devlikeapro/_index.md +++ b/content/contributors/devlikeapro/_index.md @@ -1,12 +1,11 @@ ---- -title: "devlikeapro" -description: "Creator of WAHA." -date: 2020-10-06T08:50:45+00:00 -lastmod: 2020-10-06T08:50:45+00:00 -draft: false - ---- - -Creator of WAHA - -[@devlikeapro](https://github.com/devlikeapro) +--- +title: "devlikeapro" +description: "Creator of WAHA." +date: 2020-10-06T08:50:45+00:00 +lastmod: 2020-10-06T08:50:45+00:00 +draft: false +--- + +Creator of WAHA + +[@devlikeapro](https://github.com/devlikeapro) diff --git a/content/docs/_index.md b/content/docs/_index.md index 635f9376f..ad33e0241 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -1,9 +1,8 @@ ---- -title : "Docs" -description: "Docs Doks." -lead: "" -date: 2020-10-06T08:48:23+00:00 -lastmod: 2020-10-06T08:48:23+00:00 -draft: false - ---- +--- +title: "Docs" +description: "Docs Doks." +lead: "" +date: 2020-10-06T08:48:23+00:00 +lastmod: 2020-10-06T08:48:23+00:00 +draft: false +--- diff --git a/content/docs/apps/_index.md b/content/docs/apps/_index.md index 2c10637a2..7aa137c6f 100644 --- a/content/docs/apps/_index.md +++ b/content/docs/apps/_index.md @@ -1,14 +1,13 @@ ---- -title: "🧩 Apps" -description: "Apps" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 300 -sidebar: - collapsed: true ---- - - -Here you can find detailed information about apps. \ No newline at end of file +--- +title: "🧩 Apps" +description: "Apps" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 300 +sidebar: + collapsed: true +--- + +Here you can find detailed information about apps. diff --git a/content/docs/apps/about/-config.md b/content/docs/apps/about/-config.md index fa4be0480..d714e50c9 100644 --- a/content/docs/apps/about/-config.md +++ b/content/docs/apps/about/-config.md @@ -1,28 +1,28 @@ -
- -To use -[**🧩 Apps**]({{< relref "/docs/apps/about" >}}) -, you need to configure the following environment variables in addition to the standard -[**⚙️ Configuration**]({{< relref "/docs/how-to/config" >}}): - -**Apps**: - -- `WAHA_APPS_ENABLED=True` - Enables the [**🧩 Apps**]({{< relref "/docs/apps/about" >}}) functionality -- `REDIS_URL=redis://:redis@redis:6379` - Specifies the Redis URL required for processing background jobs -- `WHATSAPP_DEFAULT_ENGINE=GOWS` - Sets the recommended engine for reliable **WhatsApp** automation -- `WAHA_API_KEY_PLAIN=0000000000000000` - plain password **required** for Apps in environment variables - - It's a quick solution, we're working on removing it so you can use `sha512` version as in `WAHA_API_KEY` - -**Jobs**: - -You can configure a background worker [http://localhost:3000/jobs](http://localhost:3000/jobs) - -- `WAHA_APPS_JOBS_CONCURRENCY=50` - Maximum number of jobs processed concurrently -- `WAHA_APPS_JOBS_REMOVE_ON_COMPLETE_AGE=259200` - Remove completed jobs after 3 days (in seconds) -- `WAHA_APPS_JOBS_REMOVE_ON_COMPLETE_COUNT=1000` - Maximum number of completed jobs to keep -- `WAHA_APPS_JOBS_REMOVE_ON_FAIL_AGE=2678400` - Remove failed jobs after 31 days (in seconds) -- `WAHA_APPS_JOBS_REMOVE_ON_FAIL_COUNT=1000` - Maximum number of failed jobs to keep - -Note: `*_AGE` parameters are specified in **seconds** by default. - -Under the hood it uses [bullmq](https://docs.bullmq.io/). +
+ +To use +[**🧩 Apps**]({{< relref "/docs/apps/about" >}}) +, you need to configure the following environment variables in addition to the standard +[**⚙️ Configuration**]({{< relref "/docs/how-to/config" >}}): + +**Apps**: + +- `WAHA_APPS_ENABLED=True` - Enables the [**🧩 Apps**]({{< relref "/docs/apps/about" >}}) functionality +- `REDIS_URL=redis://:redis@redis:6379` - Specifies the Redis URL required for processing background jobs +- `WHATSAPP_DEFAULT_ENGINE=GOWS` - Sets the recommended engine for reliable **WhatsApp** automation +- `WAHA_API_KEY_PLAIN=0000000000000000` - plain password **required** for Apps in environment variables + - It's a quick solution, we're working on removing it so you can use `sha512` version as in `WAHA_API_KEY` + +**Jobs**: + +You can configure a background worker [http://localhost:3000/jobs](http://localhost:3000/jobs) + +- `WAHA_APPS_JOBS_CONCURRENCY=50` - Maximum number of jobs processed concurrently +- `WAHA_APPS_JOBS_REMOVE_ON_COMPLETE_AGE=259200` - Remove completed jobs after 3 days (in seconds) +- `WAHA_APPS_JOBS_REMOVE_ON_COMPLETE_COUNT=1000` - Maximum number of completed jobs to keep +- `WAHA_APPS_JOBS_REMOVE_ON_FAIL_AGE=2678400` - Remove failed jobs after 31 days (in seconds) +- `WAHA_APPS_JOBS_REMOVE_ON_FAIL_COUNT=1000` - Maximum number of failed jobs to keep + +Note: `*_AGE` parameters are specified in **seconds** by default. + +Under the hood it uses [bullmq](https://docs.bullmq.io/). diff --git a/content/docs/apps/about/-how-it-works.md b/content/docs/apps/about/-how-it-works.md index a5d4f0bdc..7dbb1e089 100644 --- a/content/docs/apps/about/-how-it-works.md +++ b/content/docs/apps/about/-how-it-works.md @@ -1,73 +1,76 @@ -
- -**Apps** connect **WhatsApp** with **external services** using **Redis** as a message broker. - -**Apps** architecture consists of: -- **HTTP API**, **Worker**, and **Session** on **WAHA** side -- **Redis** acts as the central message broker. -- **External Services**, like **ChatWoot** - -```kroki {type=mermaid} -architecture-beta - group waha(cloud)[WAHA] - service api(server)[HTTP API] in waha - service worker(server)[Worker] in waha - service session(internet)[Session] in waha - service redis(database)[Redis] - - group app(cloud)[ChatWoot] - service 3api(internet)[HTTP API] in app - - api:L --> R:session - redis:R <--> B:worker - redis:T <-- B:session - 3api:L --> R:api - worker:R --> B:3api - worker:T --> B:api -``` - -**WhatsApp to External Service Flow**: -- When a new message arrives in **WhatsApp**, **WAHA** captures it and publishes a **message event** to **Redis**. -- The **Worker** then picks up this event, processes it, and forwards the message to **ChatWoot** via its **API**. -- After successful delivery, the job is marked as processed in **Redis**. - -```kroki {type=mermaid} -sequenceDiagram - participant WA_Session as WhatsApp - participant Redis as Redis - participant Worker as Worker - participant ChatWoot as ChatWoot API - - WA_Session ->> WA_Session: Receive a new message - WA_Session ->> Redis: 'message.any' event - Redis ->> Worker: Fire Job - Worker ->> ChatWoot: Send message via ChatWoot API - ChatWoot -->> Worker: 200 OK - Worker -->> Redis: Mark job as processed -``` - -**External Service to WhatsApp Flow**: -- When a new message is created in **ChatWoot**, it calls the **WAHA API** webhook. -- The **API** saves this job to the **Redis** queue, from which the **Worker** retrieves it. -- The **Worker** then requests the **WAHA API** to send the message to **WhatsApp**. -- After **WhatsApp** confirms delivery, the **API** acknowledges the **Worker**, which then marks the job as processed in **Redis**. - -```kroki {type=mermaid} -sequenceDiagram - participant ChatWoot as ChatWoot API - participant WA_API as WAHA API - participant Redis as Redis - participant Worker as Worker - participant WA_Session as WhatsApp - - ChatWoot ->> ChatWoot: New message created - ChatWoot ->> WA_API: Call Webhook - WA_API -->> ChatWoot: 200 OK - WA_API ->> Redis: 'message_created' event - Redis ->> Worker: Fire Job - Worker ->> WA_API: /api/sendText - WA_API ->> WA_Session: Send message to WhatsApp - WA_Session -->> WA_API: ACK: Server - WA_API -->> Worker: 200 OK - Worker -->> Redis: Mark job as processed -``` +
+ +**Apps** connect **WhatsApp** with **external services** using **Redis** as a message broker. + +**Apps** architecture consists of: + +- **HTTP API**, **Worker**, and **Session** on **WAHA** side +- **Redis** acts as the central message broker. +- **External Services**, like **ChatWoot** + +```kroki {type=mermaid} +architecture-beta + group waha(cloud)[WAHA] + service api(server)[HTTP API] in waha + service worker(server)[Worker] in waha + service session(internet)[Session] in waha + service redis(database)[Redis] + + group app(cloud)[ChatWoot] + service 3api(internet)[HTTP API] in app + + api:L --> R:session + redis:R <--> B:worker + redis:T <-- B:session + 3api:L --> R:api + worker:R --> B:3api + worker:T --> B:api +``` + +**WhatsApp to External Service Flow**: + +- When a new message arrives in **WhatsApp**, **WAHA** captures it and publishes a **message event** to **Redis**. +- The **Worker** then picks up this event, processes it, and forwards the message to **ChatWoot** via its **API**. +- After successful delivery, the job is marked as processed in **Redis**. + +```kroki {type=mermaid} +sequenceDiagram + participant WA_Session as WhatsApp + participant Redis as Redis + participant Worker as Worker + participant ChatWoot as ChatWoot API + + WA_Session ->> WA_Session: Receive a new message + WA_Session ->> Redis: 'message.any' event + Redis ->> Worker: Fire Job + Worker ->> ChatWoot: Send message via ChatWoot API + ChatWoot -->> Worker: 200 OK + Worker -->> Redis: Mark job as processed +``` + +**External Service to WhatsApp Flow**: + +- When a new message is created in **ChatWoot**, it calls the **WAHA API** webhook. +- The **API** saves this job to the **Redis** queue, from which the **Worker** retrieves it. +- The **Worker** then requests the **WAHA API** to send the message to **WhatsApp**. +- After **WhatsApp** confirms delivery, the **API** acknowledges the **Worker**, which then marks the job as processed in **Redis**. + +```kroki {type=mermaid} +sequenceDiagram + participant ChatWoot as ChatWoot API + participant WA_API as WAHA API + participant Redis as Redis + participant Worker as Worker + participant WA_Session as WhatsApp + + ChatWoot ->> ChatWoot: New message created + ChatWoot ->> WA_API: Call Webhook + WA_API -->> ChatWoot: 200 OK + WA_API ->> Redis: 'message_created' event + Redis ->> Worker: Fire Job + Worker ->> WA_API: /api/sendText + WA_API ->> WA_Session: Send message to WhatsApp + WA_Session -->> WA_API: ACK: Server + WA_API -->> Worker: 200 OK + Worker -->> Redis: Mark job as processed +``` diff --git a/content/docs/apps/about/apps-vs-integrations.md b/content/docs/apps/about/apps-vs-integrations.md index 4d746eae6..0556d9c5a 100644 --- a/content/docs/apps/about/apps-vs-integrations.md +++ b/content/docs/apps/about/apps-vs-integrations.md @@ -1,7 +1,7 @@ -
-{{< callout context="tip" icon="outline/bulb" title="🧩 Apps vs 🔌 Integrations" >}} -- [**🧩 Apps**]({{< relref "/docs/apps/about" >}}) -are **built-in WAHA connections** supported by the WAHA team -- [**🔌 Integrations**]({{< relref "/docs/integrations/about" >}}) -are **external ecosystem tools** that **may or may not** be directly supported by the WAHA team. -{{< /callout >}} +
+{{< callout context="tip" icon="outline/bulb" title="🧩 Apps vs 🔌 Integrations" >}} +- [**🧩 Apps**]({{< relref "/docs/apps/about" >}}) +are **built-in WAHA connections** supported by the WAHA team +- [**🔌 Integrations**]({{< relref "/docs/integrations/about" >}}) +are **external ecosystem tools** that **may or may not** be directly supported by the WAHA team. +{{< /callout >}} diff --git a/content/docs/apps/about/index.md b/content/docs/apps/about/index.md index f764c9387..896fd0ac5 100644 --- a/content/docs/apps/about/index.md +++ b/content/docs/apps/about/index.md @@ -1,39 +1,40 @@ ---- -title: "Apps" -description: "Understanding WAHA 🧩 Apps" -lead: "Understanding WAHA 🧩 Apps" -date: 2024-07-13T12:00:00+00:00 -lastmod: 2024-07-13T12:00:00+00:00 -draft: false -weight: 301 -images: [] -toc: true -slug: "about" ---- - -**🧩 Apps** are **built-in connections** that integrate **WAHA** with **other services** in a few steps. - -**WAHA Team** fully supports **🧩 Apps**. - -{{< include file="content/docs/apps/about/apps-vs-integrations.md" >}} - -## Available Apps -Apps available to connect: -- [**ChatWoot**]({{< relref "/docs/apps/chatwoot" >}}) - use your **WhatsApp** in **ChatWoot CRM** - -## Configuration - -{{< include file="content/docs/apps/about/-config.md" >}} - -## How it works - -{{< include file="content/docs/apps/about/-how-it-works.md" >}} - -You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring **Worker** and it's jobs: - -![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) - -## Apps SDK - -> This section is currently under development. Check back soon for detailed information about the integration architecture and workflow. - +--- +title: "Apps" +description: "Understanding WAHA 🧩 Apps" +lead: "Understanding WAHA 🧩 Apps" +date: 2024-07-13T12:00:00+00:00 +lastmod: 2024-07-13T12:00:00+00:00 +draft: false +weight: 301 +images: [] +toc: true +slug: "about" +--- + +**🧩 Apps** are **built-in connections** that integrate **WAHA** with **other services** in a few steps. + +**WAHA Team** fully supports **🧩 Apps**. + +{{< include file="content/docs/apps/about/apps-vs-integrations.md" >}} + +## Available Apps + +Apps available to connect: + +- [**ChatWoot**]({{< relref "/docs/apps/chatwoot" >}}) - use your **WhatsApp** in **ChatWoot CRM** + +## Configuration + +{{< include file="content/docs/apps/about/-config.md" >}} + +## How it works + +{{< include file="content/docs/apps/about/-how-it-works.md" >}} + +You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring **Worker** and it's jobs: + +![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) + +## Apps SDK + +> This section is currently under development. Check back soon for detailed information about the integration architecture and workflow. diff --git a/content/docs/apps/chatwoot/-chatwoot-articles.md b/content/docs/apps/chatwoot/-chatwoot-articles.md index 2a22fd3e8..9e4220e9b 100644 --- a/content/docs/apps/chatwoot/-chatwoot-articles.md +++ b/content/docs/apps/chatwoot/-chatwoot-articles.md @@ -1,13 +1,13 @@ -
-{{< callout context="tip" title="ChatWoot Articles" icon="outline/article" >}} -Series of articles about **WhatsApp** and **ChatWoot** integration using [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}): - -0. [**WhatsApp + ChatWoot - Overview**]({{< relref "/blog/apps-chatwoot-0-overview" >}}) -1. [**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) -2. [**WhatsApp + ChatWoot - Configuration Guide**]({{< relref "/blog/apps-chatwoot-2-config" >}}) -3. [**WhatsApp + ChatWoot - HTTPS Guide**]({{< relref "/blog/apps-chatwoot-3-https" >}}) -4. [**WhatsApp + ChatWoot - How It Works**]({{< relref "/blog/apps-chatwoot-4-how-it-works" >}}) - -You can follow them **one by one** or skip some parts if you don't need them. - -{{< /callout >}} +
+{{< callout context="tip" title="ChatWoot Articles" icon="outline/article" >}} +Series of articles about **WhatsApp** and **ChatWoot** integration using [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}): + +0. [**WhatsApp + ChatWoot - Overview**]({{< relref "/blog/apps-chatwoot-0-overview" >}}) +1. [**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) +2. [**WhatsApp + ChatWoot - Configuration Guide**]({{< relref "/blog/apps-chatwoot-2-config" >}}) +3. [**WhatsApp + ChatWoot - HTTPS Guide**]({{< relref "/blog/apps-chatwoot-3-https" >}}) +4. [**WhatsApp + ChatWoot - How It Works**]({{< relref "/blog/apps-chatwoot-4-how-it-works" >}}) + +You can follow them **one by one** or skip some parts if you don't need them. + +{{< /callout >}} diff --git a/content/docs/apps/chatwoot/-disclaimer.md b/content/docs/apps/chatwoot/-disclaimer.md index 5727b2bad..0f3404e8b 100644 --- a/content/docs/apps/chatwoot/-disclaimer.md +++ b/content/docs/apps/chatwoot/-disclaimer.md @@ -1,6 +1,6 @@ -
-{{< callout context="info" title="Disclaimer" icon="outline/gavel" >}} -This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with **WhatsApp**, **ChatWoot**, or any of their respective subsidiaries or affiliates. The official websites can be found at [https://whatsapp.com](https://whatsapp.com) and [https://chatwoot.com](https://chatwoot.com). - -For businesses seeking to integrate with WhatsApp for critical applications, we strongly recommend using [officially supported methods](https://www.chatwoot.com/hc/user-guide/articles/1677832735-how-to-setup-a-whats_app-channel). -{{< /callout >}} +
+{{< callout context="info" title="Disclaimer" icon="outline/gavel" >}} +This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with **WhatsApp**, **ChatWoot**, or any of their respective subsidiaries or affiliates. The official websites can be found at [https://whatsapp.com](https://whatsapp.com) and [https://chatwoot.com](https://chatwoot.com). + +For businesses seeking to integrate with WhatsApp for critical applications, we strongly recommend using [officially supported methods](https://www.chatwoot.com/hc/user-guide/articles/1677832735-how-to-setup-a-whats_app-channel). +{{< /callout >}} diff --git a/content/docs/apps/chatwoot/index.md b/content/docs/apps/chatwoot/index.md index e5df6e5bc..7bbed95a5 100644 --- a/content/docs/apps/chatwoot/index.md +++ b/content/docs/apps/chatwoot/index.md @@ -1,49 +1,49 @@ ---- -title: "Chatwoot" -description: "Chatwoot App" -lead: "Chatwoot App" -date: 2025-07-10T08:49:31+00:00 -lastmod: 2024-07-10T08:49:31+00:00 -draft: false -menu: -docs: -weight: 302 -images: ["waha-chatwoot.png"] -toc: true ---- - -

- -

- -**WAHA** provides a built-in **WhatsApp** integration for -[**Chatwoot**](https://www.chatwoot.com/) that you can configure in a few steps using -[**🧩 Apps**]({{< relref "/docs/apps/about" >}})! - -![Chatwoot Overview](screenshots/overview.png) -

- -{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} - - -## Installation -We cover all installation and configuration aspects in the following series of articles: -{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} - -## Configuration - -{{< include file="content/docs/apps/about/-config.md" >}} - -## How it works - -{{< include file="content/docs/apps/about/-how-it-works.md" >}} - -### Error Handling -In case of any errors, WAHA retries a few times and then gives detailed information about the error: - -![Error Reports and Retries](screenshots/error-reports-and-retries.png) - -You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: - -![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) - +--- +title: "Chatwoot" +description: "Chatwoot App" +lead: "Chatwoot App" +date: 2025-07-10T08:49:31+00:00 +lastmod: 2024-07-10T08:49:31+00:00 +draft: false +menu: +docs: +weight: 302 +images: ["waha-chatwoot.png"] +toc: true +--- + +

+ +

+ +**WAHA** provides a built-in **WhatsApp** integration for +[**Chatwoot**](https://www.chatwoot.com/) that you can configure in a few steps using +[**🧩 Apps**]({{< relref "/docs/apps/about" >}})! + +![Chatwoot Overview](screenshots/overview.png) +

+ +{{< include file="content/docs/apps/chatwoot/-disclaimer.md" >}} + +## Installation + +We cover all installation and configuration aspects in the following series of articles: +{{< include file="content/docs/apps/chatwoot/-chatwoot-articles.md" >}} + +## Configuration + +{{< include file="content/docs/apps/about/-config.md" >}} + +## How it works + +{{< include file="content/docs/apps/about/-how-it-works.md" >}} + +### Error Handling + +In case of any errors, WAHA retries a few times and then gives detailed information about the error: + +![Error Reports and Retries](screenshots/error-reports-and-retries.png) + +You can use the **WAHA Jobs Dashboard** at [http://localhost:3000/jobs](http://localhost:3000/jobs) for monitoring: + +![WAHA Jobs Dashboard](screenshots/waha-jobs-dashboard.png) diff --git a/content/docs/engines/_index.md b/content/docs/engines/_index.md index 4c1163899..0d80c6ffa 100644 --- a/content/docs/engines/_index.md +++ b/content/docs/engines/_index.md @@ -1,16 +1,15 @@ ---- -title: "🏭 Engines" -description: "Engines" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 400 -sidebar: - collapsed: true ---- - - -Here you can find detailed information about engines. - -👉 Read overview on [**🏭 Engines page**]({{< relref "/docs/how-to/engines" >}}). +--- +title: "🏭 Engines" +description: "Engines" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 400 +sidebar: + collapsed: true +--- + +Here you can find detailed information about engines. + +👉 Read overview on [**🏭 Engines page**]({{< relref "/docs/how-to/engines" >}}). diff --git a/content/docs/engines/gows.md b/content/docs/engines/gows.md index c1d851cab..0315fcb43 100644 --- a/content/docs/engines/gows.md +++ b/content/docs/engines/gows.md @@ -1,30 +1,29 @@ ---- -title: "GOWS" -description: "Lightweight golang based engine" -lead: "" -date: 2025-01-06T08:48:45+00:00 -lastmod: 2025-01-06T08:48:45+00:00 -draft: false - -weight: 411 ---- - -## Overview - -**GOWS** 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! - -## Run GOWS - -```bash -# Plus -docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha-plus - -# Core -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha -``` - -## Links - -- [https://github.com/devlikeapro/gows](https://github.com/devlikeapro/gows) - +--- +title: "GOWS" +description: "Lightweight golang based engine" +lead: "" +date: 2025-01-06T08:48:45+00:00 +lastmod: 2025-01-06T08:48:45+00:00 +draft: false + +weight: 411 +--- + +## Overview + +**GOWS** 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! + +## Run GOWS + +```bash +# Plus +docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha-plus + +# Core +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=GOWS" devlikeapro/waha +``` + +## Links + +- [https://github.com/devlikeapro/gows](https://github.com/devlikeapro/gows) diff --git a/content/docs/engines/noweb/index.md b/content/docs/engines/noweb/index.md index 9ec91f2b9..f77525341 100644 --- a/content/docs/engines/noweb/index.md +++ b/content/docs/engines/noweb/index.md @@ -1,225 +1,232 @@ ---- -title: "NOWEB" -description: "Lightweight, fast, and flexible." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false - -weight: 411 ---- - -## Overview - -**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! - -⚠ Read the article before using **NOWEB** engine -[How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). - -## Run NOWEB - -```bash -# Plus -docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=NOWEB" devlikeapro/waha-plus - -# Core -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=NOWEB" devlikeapro/waha - -``` - -## Configuration -- `markOnline: true` - send `online` **presence** when session starts (default `true`). - - Required if you want to get notifications in your phone - - Read more about [**✅ Presence**]({{< relref "/docs/how-to/presence" >}}) - - -```json -{ - "name": "default", - "config": { - "noweb": { - "markOnline": false, - "store": { - ... - } - } - } -} -``` - -## Store -By default, **NOWEB** doesn't store any contacts, chats, or messages, so it's your application's responsibility to store them. -It's fine for CRM cases like "appointment reminders" or "order notifications" where you don't need to store the chat history. - -These endpoints doesn't work by default in **NOWEB** engine. -- [`GET /api/contacts/all`]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}) -- [`GET /api/{session}/chats`]({{< relref "/docs/how-to/chats#get-all-chats" >}}) -- [`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) - -Here's how you can enable the store feature: - -### Enable store -If you want to get the **contacts, chats or messages** you need to enable it explicitly by settings additional fields -in `config` at [POST /api/sessions/]({{< relref "/docs/how-to/sessions#create-session" >}}) body. - -👉 Do not change the values after you scanned QR, it can lead to the loss of the chat history. - -```json -{ - "name": "default", - "config": { - "noweb": { - "store": { - "enabled": true, - "fullSync": false - } - } - } -} -``` - -- `config.noweb.enabled.store=true` - to enable the store feature (`false` by default) -- `config.noweb.enabled.fullSync=true` - emulate a desktop connection (and receive more message history). - - `fullSync=false` you'll get about 3 months of message history. - - `fullSync=true` you'll get about 1 year of message history (max 100K messages per chat). - - -Or enable it on [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) when **starting a new session**: -![alt](dashboard-noweb-store.png) - - - -### Get messages -When you enabled store - you can [**Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}), it's the store with some additional fields in `_data`: -- `reactions` - reactions to the message -- `pollUpdates` - encrypted votes to the polls -(not decrypted yet, please create [an issue](https://github.com/devlikeapro/waha/issues) if you wish to get the summary of polls in the response. -- `userReceipt` - **broadcast and group messages** - the user receipt of the message (aka ACK flag, green checkmarks) for - -**Reactions** -```json -[ - { - "id": "true_111111@c.us_AAAAAAAAAAAAAA", - // Regular fields here, - "_data": { - "key": { - "remoteJid": "111111@s.whatsapp.net", - "fromMe": true, - "id": "AAAAAAAAAAAAAA" - }, - "messageTimestamp": 1718265764, - "pushName": "Sim2", - "broadcast": false, - "status": 2, - "reactions": [ // <==== Reactions - { - "key": { - "remoteJid": "111111@s.whatsapp.net", - "fromMe": true, - "id": "11111111111111111111111111111111" - }, - "text": "❤️", - "senderTimestampMs": 1718265740788 - } - ] - } - } -] -``` - -**Poll votes** -```json -[ - { - "id": "true_111111@c.us_AAAAAAAAAAAAAA", - // Regular fields here, - "_data": { - "key": { - "remoteJid": "111111@s.whatsapp.net", - "fromMe": true, - "id": "AAAAAAAAAAAAAA" - }, - "messageTimestamp": 1718265764, - "pushName": "Sim2", - "broadcast": false, - "status": 2, - "pollUpdates": [ - { - /// Encrypted poll votes - } - ] - } - } -] - -``` - -**User receipt** for group messages and `status@broadcast` messages (aka [Status]({{< relref "/docs/how-to/send-messages#status" >}}) field) -```json -[ - { - "id": "true_111111111111111111111@g.us_AAAAAAAAAAAAAAAAA", - "timestamp": 1718266155, - "from": "111111111111111111111@g.us", - "fromMe": true, - "body": "Hdhf", - "to": "111111111111111111111@g.us", - "participant": "33333@c.us", - "hasMedia": false, - "ack": 1, - "ackName": "SERVER", - "_data": { - "key": { - "remoteJid": "111111111111111111111@g.us", - "fromMe": true, - "id": "AAAAAAAAAAAAAAAAA", - "participant": "33333@s.whatsapp.net" - }, - "messageTimestamp": 1718266155, - "pushName": "Sim2", - "broadcast": false, - "status": 2, - "message": { - "conversation": "Test" - }, - "userReceipt": [ // <<<==== User receipt - { - "userJid": "1111111@s.whatsapp.net", - "readTimestamp": 1718266160 // aka ackName: READ - }, - { - "userJid": "22222@s.whatsapp.net", - "receiptTimestamp": 1718266162 // aka ackName: DEVICE - } - ] - } - } -] -``` - -### Get chats and contacts -When you enabled store - you can [**Get all chats**]({{< relref "/docs/how-to/chats#get-all-chats" >}}) and [**Get all contacts**]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}). - -Here's some ids you can meet there: -- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at the end. - For phone number `12132132131` the `chatId` is `12132132131@c.us` -- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**, just convert it to `@c.us` to work - with that properly. Kindly don't use it in `chatId` when sending messages -- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. -- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that type of ID along with communities functionality. -- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). - -### Store under the hood -Under the hood, the **NOWEB** stores the session data in database based on [**🗄️ Storage**]({{< relref "/docs/how-to/storages" >}}) you choose - either in files or in MongoDB. - -- For [File local storage]({{< relref "/docs/how-to/storages#sessions---local-files" >}}) it creates sqlite3 database at `.sessions/noweb/{sessionName}/store.sqlite3` store with `chats`, `contacts`, `messages` tables with proper indexes. - - 👉 **We don't recommend opening it manually when the session is running**, even for reading, it can lead to the loss of the chat history. -- For [MongoDB]({{< relref "/docs/how-to/storages#sessions---mongodb" >}}) in `waha_{engine}_{sessionName}` it creates `chats`, `contacts`, `messages` collections with proper indexes. - - 👉 You can safely READ from the database, but **DO NOT WRITE** to it manually, it can lead to the loss of the chat history. - - -## Links - -- [https://github.com/devlikeapro/Baileys](https://github.com/devlikeapro/Baileys) - +--- +title: "NOWEB" +description: "Lightweight, fast, and flexible." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false + +weight: 411 +--- + +## Overview + +**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! + +⚠ Read the article before using **NOWEB** engine +[How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). + +## Run NOWEB + +```bash +# Plus +docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=NOWEB" devlikeapro/waha-plus + +# Core +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=NOWEB" devlikeapro/waha + +``` + +## Configuration + +- `markOnline: true` - send `online` **presence** when session starts (default `true`). + - Required if you want to get notifications in your phone + - Read more about [**✅ Presence**]({{< relref "/docs/how-to/presence" >}}) + +```json +{ + "name": "default", + "config": { + "noweb": { + "markOnline": false, + "store": { + ... + } + } + } +} +``` + +## Store + +By default, **NOWEB** doesn't store any contacts, chats, or messages, so it's your application's responsibility to store them. +It's fine for CRM cases like "appointment reminders" or "order notifications" where you don't need to store the chat history. + +These endpoints doesn't work by default in **NOWEB** engine. + +- [`GET /api/contacts/all`]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}) +- [`GET /api/{session}/chats`]({{< relref "/docs/how-to/chats#get-all-chats" >}}) +- [`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) + +Here's how you can enable the store feature: + +### Enable store + +If you want to get the **contacts, chats or messages** you need to enable it explicitly by settings additional fields +in `config` at [POST /api/sessions/]({{< relref "/docs/how-to/sessions#create-session" >}}) body. + +👉 Do not change the values after you scanned QR, it can lead to the loss of the chat history. + +```json +{ + "name": "default", + "config": { + "noweb": { + "store": { + "enabled": true, + "fullSync": false + } + } + } +} +``` + +- `config.noweb.enabled.store=true` - to enable the store feature (`false` by default) +- `config.noweb.enabled.fullSync=true` - emulate a desktop connection (and receive more message history). + - `fullSync=false` you'll get about 3 months of message history. + - `fullSync=true` you'll get about 1 year of message history (max 100K messages per chat). + - Or enable it on [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) when **starting a new session**: + ![alt](dashboard-noweb-store.png) + +### Get messages + +When you enabled store - you can [**Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}), it's the store with some additional fields in `_data`: + +- `reactions` - reactions to the message +- `pollUpdates` - encrypted votes to the polls + (not decrypted yet, please create [an issue](https://github.com/devlikeapro/waha/issues) if you wish to get the summary of polls in the response. +- `userReceipt` - **broadcast and group messages** - the user receipt of the message (aka ACK flag, green checkmarks) for + +**Reactions** + +```json +[ + { + "id": "true_111111@c.us_AAAAAAAAAAAAAA", + // Regular fields here, + "_data": { + "key": { + "remoteJid": "111111@s.whatsapp.net", + "fromMe": true, + "id": "AAAAAAAAAAAAAA" + }, + "messageTimestamp": 1718265764, + "pushName": "Sim2", + "broadcast": false, + "status": 2, + "reactions": [ + // <==== Reactions + { + "key": { + "remoteJid": "111111@s.whatsapp.net", + "fromMe": true, + "id": "11111111111111111111111111111111" + }, + "text": "❤️", + "senderTimestampMs": 1718265740788 + } + ] + } + } +] +``` + +**Poll votes** + +```json +[ + { + "id": "true_111111@c.us_AAAAAAAAAAAAAA", + // Regular fields here, + "_data": { + "key": { + "remoteJid": "111111@s.whatsapp.net", + "fromMe": true, + "id": "AAAAAAAAAAAAAA" + }, + "messageTimestamp": 1718265764, + "pushName": "Sim2", + "broadcast": false, + "status": 2, + "pollUpdates": [ + { + /// Encrypted poll votes + } + ] + } + } +] +``` + +**User receipt** for group messages and `status@broadcast` messages (aka [Status]({{< relref "/docs/how-to/send-messages#status" >}}) field) + +```json +[ + { + "id": "true_111111111111111111111@g.us_AAAAAAAAAAAAAAAAA", + "timestamp": 1718266155, + "from": "111111111111111111111@g.us", + "fromMe": true, + "body": "Hdhf", + "to": "111111111111111111111@g.us", + "participant": "33333@c.us", + "hasMedia": false, + "ack": 1, + "ackName": "SERVER", + "_data": { + "key": { + "remoteJid": "111111111111111111111@g.us", + "fromMe": true, + "id": "AAAAAAAAAAAAAAAAA", + "participant": "33333@s.whatsapp.net" + }, + "messageTimestamp": 1718266155, + "pushName": "Sim2", + "broadcast": false, + "status": 2, + "message": { + "conversation": "Test" + }, + "userReceipt": [ + // <<<==== User receipt + { + "userJid": "1111111@s.whatsapp.net", + "readTimestamp": 1718266160 // aka ackName: READ + }, + { + "userJid": "22222@s.whatsapp.net", + "receiptTimestamp": 1718266162 // aka ackName: DEVICE + } + ] + } + } +] +``` + +### Get chats and contacts + +When you enabled store - you can [**Get all chats**]({{< relref "/docs/how-to/chats#get-all-chats" >}}) and [**Get all contacts**]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}). + +Here's some ids you can meet there: + +- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at the end. + For phone number `12132132131` the `chatId` is `12132132131@c.us` +- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**, just convert it to `@c.us` to work + with that properly. Kindly don't use it in `chatId` when sending messages +- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. +- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that type of ID along with communities functionality. +- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). + +### Store under the hood + +Under the hood, the **NOWEB** stores the session data in database based on [**🗄️ Storage**]({{< relref "/docs/how-to/storages" >}}) you choose - either in files or in MongoDB. + +- For [File local storage]({{< relref "/docs/how-to/storages#sessions---local-files" >}}) it creates sqlite3 database at `.sessions/noweb/{sessionName}/store.sqlite3` store with `chats`, `contacts`, `messages` tables with proper indexes. + - 👉 **We don't recommend opening it manually when the session is running**, even for reading, it can lead to the loss of the chat history. +- For [MongoDB]({{< relref "/docs/how-to/storages#sessions---mongodb" >}}) in `waha_{engine}_{sessionName}` it creates `chats`, `contacts`, `messages` collections with proper indexes. + - 👉 You can safely READ from the database, but **DO NOT WRITE** to it manually, it can lead to the loss of the chat history. + +## Links + +- [https://github.com/devlikeapro/Baileys](https://github.com/devlikeapro/Baileys) diff --git a/content/docs/engines/venom.md b/content/docs/engines/venom.md index 97c94c34a..b323438dc 100644 --- a/content/docs/engines/venom.md +++ b/content/docs/engines/venom.md @@ -1,41 +1,39 @@ ---- -title: "VENOM" -description: "DEPRECATED" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false - -weight: 419 ---- - -## Overview - -{{< callout context="caution" title="VENOM engine is DEPRECATED" icon="outline/alert-triangle" >}} - -Use -[**GOWS**]({{< relref "/docs/engines/gows" >}}), -[**WEBJS**]({{< relref "/docs/engines/webjs" >}}), -or -[**NOWEB**]({{< relref "/docs/engines/noweb" >}}) -instead. -{{< /callout >}} - - -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. - -## Run VENOM - -```bash -# Core -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=VENOM" devlikeapro/waha - -# Plus -docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=VENOM" devlikeapro/waha-plus -``` - -## Links - -- [https://github.com/devlikeapro/venom](https://github.com/devlikeapro/venom) - +--- +title: "VENOM" +description: "DEPRECATED" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false + +weight: 419 +--- + +## Overview + +{{< callout context="caution" title="VENOM engine is DEPRECATED" icon="outline/alert-triangle" >}} + +Use +[**GOWS**]({{< relref "/docs/engines/gows" >}}), +[**WEBJS**]({{< relref "/docs/engines/webjs" >}}), +or +[**NOWEB**]({{< relref "/docs/engines/noweb" >}}) +instead. +{{< /callout >}} + +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. + +## Run VENOM + +```bash +# Core +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=VENOM" devlikeapro/waha + +# Plus +docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=VENOM" devlikeapro/waha-plus +``` + +## Links + +- [https://github.com/devlikeapro/venom](https://github.com/devlikeapro/venom) diff --git a/content/docs/engines/webjs.md b/content/docs/engines/webjs.md index d4851b8b8..da69439c4 100644 --- a/content/docs/engines/webjs.md +++ b/content/docs/engines/webjs.md @@ -1,40 +1,42 @@ ---- -title: "WEBJS" -description: "Stable, reliable, and predictable." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false - -weight: 410 ---- - -## Overview - -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 (if you don't set `WHATSAPP_DEFAULT_ENGINE` environment variable to -another engine). - -⚠ Read the article before using **WEBJS** engine -[How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). - -## Run WEBJS - -```bash -# Plus -docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha-plus - -# Core -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha -``` - -## Configuration -You can use some of the following environment variables to configure the [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) session: -- `WAHA_WEBJS_CACHE_TYPE=local` - enable cache (aka use the latest version) for the **web page** in the browser. By default, it's `none` (no cache) -- `WAHA_WEBJS_WEB_VERSION=2.3000.XXXX` - set the version of the WhatsApp Web to use. By default, we're using the latest compatible version. Only works with `local` cache type. - -## Links - -- [https://github.com/devlikeapro/whatsapp-web.js](https://github.com/devlikeapro/whatsapp-web.js) +--- +title: "WEBJS" +description: "Stable, reliable, and predictable." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false + +weight: 410 +--- + +## Overview + +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 (if you don't set `WHATSAPP_DEFAULT_ENGINE` environment variable to +another engine). + +⚠ Read the article before using **WEBJS** engine +[How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). + +## Run WEBJS + +```bash +# Plus +docker run -v `pwd`/.sessions:/app/.sessions -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha-plus + +# Core +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha +``` + +## Configuration + +You can use some of the following environment variables to configure the [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) session: + +- `WAHA_WEBJS_CACHE_TYPE=local` - enable cache (aka use the latest version) for the **web page** in the browser. By default, it's `none` (no cache) +- `WAHA_WEBJS_WEB_VERSION=2.3000.XXXX` - set the version of the WhatsApp Web to use. By default, we're using the latest compatible version. Only works with `local` cache type. + +## Links + +- [https://github.com/devlikeapro/whatsapp-web.js](https://github.com/devlikeapro/whatsapp-web.js) diff --git a/content/docs/how-to/_index.md b/content/docs/how-to/_index.md index 48d527171..6c6c66f91 100644 --- a/content/docs/how-to/_index.md +++ b/content/docs/how-to/_index.md @@ -1,17 +1,16 @@ ---- -title: "🔍 How-to guides" -description: "How-to guides" -lead: "" -date: 2020-10-06T08:49:15+00:00 -lastmod: 2020-10-06T08:49:15+00:00 -draft: false -weight: 200 -slug: how-to -sidebar: - collapsed: true ---- - -How-to guides for **WAHA** - WhatsApp API. - -Discover how to use the WAHA, what you can do with it, and how to configure it right for your needs. - +--- +title: "🔍 How-to guides" +description: "How-to guides" +lead: "" +date: 2020-10-06T08:49:15+00:00 +lastmod: 2020-10-06T08:49:15+00:00 +draft: false +weight: 200 +slug: how-to +sidebar: + collapsed: true +--- + +How-to guides for **WAHA** - WhatsApp API. + +Discover how to use the WAHA, what you can do with it, and how to configure it right for your needs. diff --git a/content/docs/how-to/calls/features-events.md b/content/docs/how-to/calls/features-events.md index a37eef25f..99e24faf4 100644 --- a/content/docs/how-to/calls/features-events.md +++ b/content/docs/how-to/calls/features-events.md @@ -1,10 +1,10 @@ -
-{{< details "**📞 Calls - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|-----------------|:-----:|:-----:|:-----| -| `call.received` | ✔️ | ✔️ | | -| `call.accepted` | | ✔️ | | -| `call.rejected` | | ✔️ | | - -{{< /details >}} +
+{{< details "**📞 Calls - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| --------------- | :---: | :---: | :--- | +| `call.received` | ✔️ | ✔️ | | +| `call.accepted` | | ✔️ | | +| `call.rejected` | | ✔️ | | + +{{< /details >}} diff --git a/content/docs/how-to/calls/index.md b/content/docs/how-to/calls/index.md index bc39d005b..804f57b83 100644 --- a/content/docs/how-to/calls/index.md +++ b/content/docs/how-to/calls/index.md @@ -1,40 +1,40 @@ ---- -title: "📞 Calls" -description: "Calls" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 293 -slug: calls -images: [ "whatsapp-phone-call.png" ] ---- -You can receive events about calls in WhatsApp using API! - -
-{{< img lqip="21x webp q20" src="whatsapp-calls.png" alt="WhatsApp Calls" >}} -
- -## Features -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/calls/features-events.md" >}} - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### call.received - -{{< include file="content/docs/how-to/calls/webhooks-call-received.md" >}} - -### call.accepted - -{{< include file="content/docs/how-to/calls/webhooks-call-accepted.md" >}} - -### call.rejected - -{{< include file="content/docs/how-to/calls/webhooks-call-rejected.md" >}} - - - +--- +title: "📞 Calls" +description: "Calls" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 293 +slug: calls +images: ["whatsapp-phone-call.png"] +--- + +You can receive events about calls in WhatsApp using API! + +
+{{< img lqip="21x webp q20" src="whatsapp-calls.png" alt="WhatsApp Calls" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/calls/features-events.md" >}} + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### call.received + +{{< include file="content/docs/how-to/calls/webhooks-call-received.md" >}} + +### call.accepted + +{{< include file="content/docs/how-to/calls/webhooks-call-accepted.md" >}} + +### call.rejected + +{{< include file="content/docs/how-to/calls/webhooks-call-rejected.md" >}} diff --git a/content/docs/how-to/calls/webhooks-call-accepted.md b/content/docs/how-to/calls/webhooks-call-accepted.md index f990c4e81..37e758dea 100644 --- a/content/docs/how-to/calls/webhooks-call-accepted.md +++ b/content/docs/how-to/calls/webhooks-call-accepted.md @@ -1,15 +1,14 @@ -```json { title="call.accepted" } -{ - "event": "call.accepted", - "session": "default", - "payload": { - "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "from": "22222222222@c.us", - "timestamp": 1721374000, - "isVideo": false, - "isGroup": false - }, - ... -} -``` - +```json { title="call.accepted" } +{ + "event": "call.accepted", + "session": "default", + "payload": { + "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "from": "22222222222@c.us", + "timestamp": 1721374000, + "isVideo": false, + "isGroup": false + }, + ... +} +``` diff --git a/content/docs/how-to/calls/webhooks-call-received.md b/content/docs/how-to/calls/webhooks-call-received.md index 03abdaf4a..b2bbec7ae 100644 --- a/content/docs/how-to/calls/webhooks-call-received.md +++ b/content/docs/how-to/calls/webhooks-call-received.md @@ -1,14 +1,14 @@ -```json { title="call.received" } -{ - "event": "call.received", - "session": "default", - "payload": { - "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "from": "22222222222@c.us", - "timestamp": 1721374000, - "isVideo": false, - "isGroup": false - }, - ... -} -``` +```json { title="call.received" } +{ + "event": "call.received", + "session": "default", + "payload": { + "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "from": "22222222222@c.us", + "timestamp": 1721374000, + "isVideo": false, + "isGroup": false + }, + ... +} +``` diff --git a/content/docs/how-to/calls/webhooks-call-rejected.md b/content/docs/how-to/calls/webhooks-call-rejected.md index e192bc1f1..6b647ec05 100644 --- a/content/docs/how-to/calls/webhooks-call-rejected.md +++ b/content/docs/how-to/calls/webhooks-call-rejected.md @@ -1,14 +1,14 @@ -```json { title="call.rejected" } -{ - "event": "call.rejected", - "session": "default", - "payload": { - "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "from": "22222222222@c.us", - "timestamp": 1721374000, - "isVideo": false, - "isGroup": false - }, - ... -} -``` +```json { title="call.rejected" } +{ + "event": "call.rejected", + "session": "default", + "payload": { + "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "from": "22222222222@c.us", + "timestamp": 1721374000, + "isVideo": false, + "isGroup": false + }, + ... +} +``` diff --git a/content/docs/how-to/channels/features.md b/content/docs/how-to/channels/features.md index f6433a904..f17cbe458 100644 --- a/content/docs/how-to/channels/features.md +++ b/content/docs/how-to/channels/features.md @@ -1,35 +1,36 @@ -
-{{< details "**📢 Channels - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|---------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|----------------------------------------------------------------|:-----| -| **Search public channels**
`POST /api/{session}/channels/search/by-view`
`POST /api/{session}/channels/search/by-text` | ➕ | ➕ | ➕ | -| **"Views" for Search**
`GET /api/{session}/channels/search/views` | ➕ | ➕ | ➕ | -| **"Countries" for Search**
`GET /api/{session}/channels/search/countries` | ➕ | ➕ | ➕ | -| **"Categories" for Search**
`GET /api/{session}/channels/search/categories` | ➕ | ➕ | ➕ | -| **Get Messages from Channels (preview)**
`GET /api/{session}/channels/{invite}/messages/preview` | ➕ | ➕ | ➕ | -| **Create Channel**
`POST /api/{session}/channels` | [#439](https://github.com/devlikeapro/waha/issues/439) | ✔️ | ✔️ | -| **Get channel - by id and invite code**
`GET /api/{session}/channels/{ChannelID}` | ✔️ | ✔️ | ✔️ | -| **List channels**
`GET /api/{session}/channels` | ✔️ | ✔️ | ✔️ | -| **Delete channel**
`DELETE /api/{session}/channels/{ChannelID}` | | ✔️ | | -| **Get messages**
`GET /api/{session}/chats/{ChannelID}/messages` | ✔️ | ✔️
[#433](https://github.com/devlikeapro/waha/issues/433) | | -| **Send messages - Text**
`POST /api/sendText` | ✔️ | ✔️ | ✔️ | -| **Send messages - Image**
`POST /api/sendImage` | ✔️ | ✔️ | ✔️ | -| **Send messages - Video**
`POST /api/sendVideo` | ✔️ | ✔️ | ✔️ | -| **Send messages - Poll**
`POST /api/sendPoll` | | | | -| **Receive messages - Text**
`message` event | ✔️ | ✔️ | ✔️ | -| **Receive messages - Media**
`message` event | ✔️ | ✔️ | ✔️ | -| **Receive messages - Polls** | | ✔️ | | -| **Receive messages - Polls Votes (in my channel)** | | | | -| **Receive messages - Reactions (in my channel)** | | | | -| **Channels - follow, unfollow** | | | ✔️ | -| **Channels - mute, unmute** | | | ✔️ | -| **Admins - Send Invite** | | | | -| **Admins - Revoke Invite** | | | | -| **Admins - Accept Invite** | | | | -| **Admins - Demote Admin** | | | | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ -- ➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) - -{{< /details >}} +
+{{< details "**📢 Channels - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------------------- | :--- | +| **Search public channels**
`POST /api/{session}/channels/search/by-view`
`POST /api/{session}/channels/search/by-text` | ➕ | ➕ | ➕ | +| **"Views" for Search**
`GET /api/{session}/channels/search/views` | ➕ | ➕ | ➕ | +| **"Countries" for Search**
`GET /api/{session}/channels/search/countries` | ➕ | ➕ | ➕ | +| **"Categories" for Search**
`GET /api/{session}/channels/search/categories` | ➕ | ➕ | ➕ | +| **Get Messages from Channels (preview)**
`GET /api/{session}/channels/{invite}/messages/preview` | ➕ | ➕ | ➕ | +| **Create Channel**
`POST /api/{session}/channels` | [#439](https://github.com/devlikeapro/waha/issues/439) | ✔️ | ✔️ | +| **Get channel - by id and invite code**
`GET /api/{session}/channels/{ChannelID}` | ✔️ | ✔️ | ✔️ | +| **List channels**
`GET /api/{session}/channels` | ✔️ | ✔️ | ✔️ | +| **Delete channel**
`DELETE /api/{session}/channels/{ChannelID}` | | ✔️ | | +| **Get messages**
`GET /api/{session}/chats/{ChannelID}/messages` | ✔️ | ✔️
[#433](https://github.com/devlikeapro/waha/issues/433) | | +| **Send messages - Text**
`POST /api/sendText` | ✔️ | ✔️ | ✔️ | +| **Send messages - Image**
`POST /api/sendImage` | ✔️ | ✔️ | ✔️ | +| **Send messages - Video**
`POST /api/sendVideo` | ✔️ | ✔️ | ✔️ | +| **Send messages - Poll**
`POST /api/sendPoll` | | | | +| **Receive messages - Text**
`message` event | ✔️ | ✔️ | ✔️ | +| **Receive messages - Media**
`message` event | ✔️ | ✔️ | ✔️ | +| **Receive messages - Polls** | | ✔️ | | +| **Receive messages - Polls Votes (in my channel)** | | | | +| **Receive messages - Reactions (in my channel)** | | | | +| **Channels - follow, unfollow** | | | ✔️ | +| **Channels - mute, unmute** | | | ✔️ | +| **Admins - Send Invite** | | | | +| **Admins - Revoke Invite** | | | | +| **Admins - Accept Invite** | | | | +| **Admins - Demote Admin** | | | | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +- ➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) + +{{< /details >}} diff --git a/content/docs/how-to/channels/index.md b/content/docs/how-to/channels/index.md index d0773eaf0..7d30c6467 100644 --- a/content/docs/how-to/channels/index.md +++ b/content/docs/how-to/channels/index.md @@ -1,511 +1,524 @@ ---- -title: "📢 Channels" -description: "Channels (aka Newsletter)" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 231 -images: [ "channels.png" ] -slug: channels ---- - -Here's complete information about **WhatsApp Channels** (aka _Newsletters_) and how to use them. - -
-{{< img lqip="21x webp q20" src="channels.png" alt="WhatsApp Channels" >}} -
- -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/channels/features.md" >}} - -## Channels API - -💡 Channels have a special `@newsletter` prefix, so you can distinguish them from regular chats and groups. - -- `123123123@newsletter` - channel ID - -### Get your channels - -You can get list of **subscribed or owned** channels: - -Get all (your and subscribed) channels: -```http request -GET /api/{session}/channels -``` - -Filter channels by your role: -```http request -GET /api/{session}/channels?role=OWNER -``` -- `role` can be `OWNER`, `ADMIN`, `SUBSCRIBER` - -```json -[ - { - "id": "111111111111111111@newsletter", - "name": "Channel - Owner - Picture", - "description": "Hi there, I'm new here", - "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", - "preview": "https://mmg.whatsapp.net/m1/v/t24/123", - "picture": "https://mmg.whatsapp.net/m1/v/t24/123", - "verified": false, - "role": "OWNER" - }, - { - "id": "111111111111111111@newsletter", - "name": "Channel - Subscriber - No Picture", - "description": "", - "invite": "https://whatsapp.com/channel/111111111111111111111111", - "preview": null, - "picture": null, - "verified": false, - "role": "SUBSCRIBER" - } -] -``` - -### Create a new channel - -You can create a new channel: - -```http request -POST /api/{session}/channels -``` - -```json { title="Body" } -{ - "name": "Channel Name", - "description": "Channel Description", - "picture": { - "mimetype": "image/jpeg", - "filename": "filename.jpg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" - } -} -``` - -### Delete a channel - -You can delete a channel `DELETE /api/{session}/channels/123123%40newsletter` -```http request -DELETE /api/{session}/channels/{ID} -``` - -- 👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. -- Allowing to delete only channels where you're `OWNER`. - -### Get channel by Id - -You can get a channel by ID - -```http request -GET /api/{SESSION}/channels/{ID} -``` - -- 👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. - -```json {title="Response"} -{ - "id": "111111111111111111@newsletter", - "name": "Channel - Owner - Picture", - "description": "Hi there, I'm new here", - "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", - "preview": "https://mmg.whatsapp.net/m1/v/t24/123", - "picture": "https://mmg.whatsapp.net/m1/v/t24/123", - "verified": false, - "role": "OWNER", - "subscribersCount": 12323 -} -``` - -### Get channel by Invite Code - -You can get a channel information by Invite Code - -```http request -GET /api/{session}/channels/{inviteCode} -``` - -- `inviteCode` here is the last part in invite URL `https://whatsapp.com/channel/111111111111111111GdZ60l` - - `111111111111111111GdZ60l` - -💡 To get full `picture` you need to get channel by ID after you get the invite code. - -```json {title="Response"} -{ - "id": "111111111111111111@newsletter", - "name": "Channel - Owner - Picture", - "description": "Hi there, I'm new here", - "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", - "preview": "https://mmg.whatsapp.net/m1/v/t24/123", - "picture": "https://mmg.whatsapp.net/m1/v/t24/123", - "verified": false, - "role": "OWNER" -} -``` - -## Search API - -### Search channels by view - -{{< imgo src="/images/whatsapp/channels/channels-views.png" full="false" >}} - -You can search **public** (not subscribed yet) channels **by view**: - -```http request -POST /api/{session}/channels/search/by-view -``` - - -```json { title="Body" } -{ - "view": "RECOMMENDED", - "countries": [ - "US" - ], - "categories": [], - "limit": 50, - "startCursor": "" -} -``` - -- `view` - Use `value` from [get available views](#get-search-views) -- `countries` - use `code` from [get available countries](#get-search-countries) -- `categories` - use `id` from [get available categories](#get-search-categories) -- `limit` - we recommend using default `50` value, it's the way official clients work -- `startCursor` - use `endCursor` from the previous response (if any data available on the next page) - -```json { title="Response" } -{ - "page": { - "startCursor": null, - "endCursor": "base64encodedstring", - "hasNextPage": true, - "hasPreviousPage": false - }, - "channels": [ - { - "id": "123123123123@newsletter", - "name": "Channel Name", - "invite": "https://www.whatsapp.com/channel/111111111111111111111111", - "preview": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10", - "picture": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10", - "description": "string", - "verified": true, - "subscribersCount": 0 - } - ] -} -``` - -### Search channels by text -{{< imgo src="/images/whatsapp/channels/channels-text.png" full="false" >}} - -You can search **public** (not subscribed yet) channels **by text**: -```http request -POST /api/{session}/channels/search/by-text -``` - -```json { title="Body" } -{ - "text": "Donald Trump", - "categories": [], - "limit": 50, - "startCursor": "" -} -``` -- `text` - search text -- `categories` - use `id` from [get available categories](#get-search-categories) -- `limit` - we recommend using default `50` value, it's the way official clients work -- `startCursor` - use `endCursor` from the previous response (if any data available on the next page) - -### Get Search Views -List of available views for search: - -```http request -GET /api/{session}/channels/search/views -``` - -```json { title="Response" } -[ - { - "value": "RECOMMENDED", - "name": "Explore" - } -] -``` - -### Get Search Countries -List of available countries for search (not full one, you can try different `code` values if you don't see your country): - -```http request -GET /api/{session}/channels/search/countries -``` - -```json { title="Response" } -[ - { - "code": "US", - "name": "United States" - } -] -``` - -### Get Search Categories -List of available categories for search: - -```http request -GET /api/{session}/channels/search/categories -``` - -```json { title="Response" } -[ - { - "value": "BUSINESS", - "name": "Business" - }, - { - "value": "ENTERTAINMENT", - "name": "Entertainment" - } -] -``` - -### Get Messages (Preview) for Channel -You can get latest messages from **public** channels (not subscribed yet) by invite code (or channel id). -Returns only **preview** messages (one that you'll see on channel preview). - -```http request -GET /api/{SESSION}/channels/{INVITE}/messages/preview?downloadMedia=false&limit=100 -``` - -**Query parameters**: -- `{SESSION}` - your session -- `{INVITE}` - invite code (123123123) or channel id (123132123@newsletter). **Invite code is recommended**. -- `downloadMedia` - whether to download media or not -- `limit` - limit of messages to return. **100 is recommended**. - -```json -[ - { - "reactions": { - "👍": 10, - "❤️": 5 - }, - "viewCount": 0, - "message": { - "id": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "timestamp": 1666943582, - "body": "string", - "media": { - ... - } - } - } -] -``` -- `reactions` - reactions for the message -- `viewCount` - views count for the message -- `message` - message object - the same as in `payload` field [**message**]({{< relref "/docs/how-to/events#message" >}}) event - -## How-to - -### Send Text to the channel - -You can use regular [`POST /api/sendText`]({{< relref "/docs/how-to/send-messages#send-text" >}}) endpoint to send a -text message into the channel - -👉 Make sure you're `OWNER` or `ADMIN` for the channel - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@newsletter", - "text": "Hi there!" -} -``` - -### Send Image to the channel - -You can use regular [`POST /api/sendImage`]({{< relref "/docs/how-to/send-messages#send-image" >}}) endpoint -to send an image into the channel - -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@newsletter", - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - "filename": "filename.jpeg" - }, - "caption": "string" -} -``` - -### Send Video to the channel - -You can use regular [`POST /api/sendVideo`]({{< relref "/docs/how-to/send-messages#send-video" >}}) endpoint -to send a video message into the channel - -```json { title="Body" } -{ - "chatId": "111111111111111111@newsletter", - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "caption": "Just watch at this!", - "session": "default" -} -``` - -### Send Reaction to the channel - -```http request -PUT /api/reaction -``` - -```json { title="Body" } -{ - "messageId": "false_11111111111@newsletter_AAAAAAAAAAAAAAAAAAAA", - "reaction": "👍", - "session": "default" -} -``` - -`messageId` can be in 2 format: -1. `false_11111111111@newsletter_AAAAAAAAAAAAAAAAAAAA` - using characters. Works if you're subscribed to the channel. -2. `false_11111111111@newsltter_123` - using `server_id`. If you're not subscribed to the channel, you can use this format. - -You can find `server_id` in message: -{{< tabs "channel-message-id-for-reaction" >}} -{{< tab "NOWEB" >}} -Find `_data.key.server_id` value: -```json -{ - "event": "message.any", - "payload": { - ... - "_data": { - "key": { - "remoteJid": "120363417343416222@newsletter", - ... - "server_id": "101" # <=== this one - }, - ... - } - }, - ... -} -``` -{{< /tab >}} - -{{< tab "GOWS" >}} -Find `_data.Info.ServerID` value: -```json -{ - "event": "message.any", - "payload": { - ... - "_data": { - "Info": { - "Chat": "111111111111111111@newsletter", - ... - "ServerID": 105, # <=== this one - ... - }, - ... - } - } -} -``` -{{< /tab >}} - -{{< tab "WEBJS" >}} -Not supported -{{< /tab >}} -{{< /tabs >}} - - - -### Get messages from the channel - -You can use regular -[`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) -to fetch messages from the channel - -```http request -GET /api/default/chats/123%40newsletter/messages?downloadMedia=true&limit=100 -``` - -```json -[ - { - "id": "true_111111111111111111@newsletter_1111111111111111111111", - "timestamp": 1720775833, - "from": "111111111111111111@newsletter", - "fromMe": true, - "body": "Caption", - "hasMedia": true, - "media": { - "mimetype": "image/jpeg", - "filename": null, - "url": "http://localhost:3000/api/files/1111111111111111111111.jpeg", - "error": null // if there was an error during file download - }, - "mediaUrl": "http://localhost:3000/api/files/1111111111111111111111.jpeg", - "ack": 0, - "ackName": "PENDING", - "_data": { - ... - } - } -] - -``` - -### Receive messages from the channel - -For all incoming messages in your own and subscribed channels you'll receive - -- [`message`]({{< relref "/docs/how-to/receive-messages#message" >}}) event for a message from the channel (send by - someone else) -- [`message.any`]({{< relref "/docs/how-to/receive-messages#message.any" >}}) event for a message from the channel ( - including your messages) - -```json { title="message" } -{ - "event": "message", - "session": "default", - "me": { - "id": "111111111111@c.us", - "pushName": "Slovakia WAHA" - }, - "payload": { - "id": "false_123123@newsletter_11111111111111111111111111111111", - "timestamp": 1720776511, - "from": "111111111111111111@newsletter", - "fromMe": false, - "body": "How are you all?! ❤️", - "hasMedia": false, - "ack": null, - "ackName": "UNKNOWN", - "_data": { - ... - } - }, - "engine": "NOWEB", - "environment": { - "version": "2024.7.4", - "engine": "NOWEB", - "tier": "PLUS", - "browser": "/usr/bin/google-chrome-stable" - } -} -``` +--- +title: "📢 Channels" +description: "Channels (aka Newsletter)" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 231 +images: ["channels.png"] +slug: channels +--- + +Here's complete information about **WhatsApp Channels** (aka _Newsletters_) and how to use them. + +
+{{< img lqip="21x webp q20" src="channels.png" alt="WhatsApp Channels" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/channels/features.md" >}} + +## Channels API + +💡 Channels have a special `@newsletter` prefix, so you can distinguish them from regular chats and groups. + +- `123123123@newsletter` - channel ID + +### Get your channels + +You can get list of **subscribed or owned** channels: + +Get all (your and subscribed) channels: + +```http request +GET /api/{session}/channels +``` + +Filter channels by your role: + +```http request +GET /api/{session}/channels?role=OWNER +``` + +- `role` can be `OWNER`, `ADMIN`, `SUBSCRIBER` + +```json +[ + { + "id": "111111111111111111@newsletter", + "name": "Channel - Owner - Picture", + "description": "Hi there, I'm new here", + "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", + "preview": "https://mmg.whatsapp.net/m1/v/t24/123", + "picture": "https://mmg.whatsapp.net/m1/v/t24/123", + "verified": false, + "role": "OWNER" + }, + { + "id": "111111111111111111@newsletter", + "name": "Channel - Subscriber - No Picture", + "description": "", + "invite": "https://whatsapp.com/channel/111111111111111111111111", + "preview": null, + "picture": null, + "verified": false, + "role": "SUBSCRIBER" + } +] +``` + +### Create a new channel + +You can create a new channel: + +```http request +POST /api/{session}/channels +``` + +```json { title="Body" } +{ + "name": "Channel Name", + "description": "Channel Description", + "picture": { + "mimetype": "image/jpeg", + "filename": "filename.jpg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" + } +} +``` + +### Delete a channel + +You can delete a channel `DELETE /api/{session}/channels/123123%40newsletter` + +```http request +DELETE /api/{session}/channels/{ID} +``` + +- 👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. +- Allowing to delete only channels where you're `OWNER`. + +### Get channel by Id + +You can get a channel by ID + +```http request +GET /api/{SESSION}/channels/{ID} +``` + +- 👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. + +```json {title="Response"} +{ + "id": "111111111111111111@newsletter", + "name": "Channel - Owner - Picture", + "description": "Hi there, I'm new here", + "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", + "preview": "https://mmg.whatsapp.net/m1/v/t24/123", + "picture": "https://mmg.whatsapp.net/m1/v/t24/123", + "verified": false, + "role": "OWNER", + "subscribersCount": 12323 +} +``` + +### Get channel by Invite Code + +You can get a channel information by Invite Code + +```http request +GET /api/{session}/channels/{inviteCode} +``` + +- `inviteCode` here is the last part in invite URL `https://whatsapp.com/channel/111111111111111111GdZ60l` - + `111111111111111111GdZ60l` + +💡 To get full `picture` you need to get channel by ID after you get the invite code. + +```json {title="Response"} +{ + "id": "111111111111111111@newsletter", + "name": "Channel - Owner - Picture", + "description": "Hi there, I'm new here", + "invite": "https://whatsapp.com/channel/111111111111111111GdZ60l", + "preview": "https://mmg.whatsapp.net/m1/v/t24/123", + "picture": "https://mmg.whatsapp.net/m1/v/t24/123", + "verified": false, + "role": "OWNER" +} +``` + +## Search API + +### Search channels by view + +{{< imgo src="/images/whatsapp/channels/channels-views.png" full="false" >}} + +You can search **public** (not subscribed yet) channels **by view**: + +```http request +POST /api/{session}/channels/search/by-view +``` + +```json { title="Body" } +{ + "view": "RECOMMENDED", + "countries": ["US"], + "categories": [], + "limit": 50, + "startCursor": "" +} +``` + +- `view` - Use `value` from [get available views](#get-search-views) +- `countries` - use `code` from [get available countries](#get-search-countries) +- `categories` - use `id` from [get available categories](#get-search-categories) +- `limit` - we recommend using default `50` value, it's the way official clients work +- `startCursor` - use `endCursor` from the previous response (if any data available on the next page) + +```json { title="Response" } +{ + "page": { + "startCursor": null, + "endCursor": "base64encodedstring", + "hasNextPage": true, + "hasPreviousPage": false + }, + "channels": [ + { + "id": "123123123123@newsletter", + "name": "Channel Name", + "invite": "https://www.whatsapp.com/channel/111111111111111111111111", + "preview": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10", + "picture": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10", + "description": "string", + "verified": true, + "subscribersCount": 0 + } + ] +} +``` + +### Search channels by text + +{{< imgo src="/images/whatsapp/channels/channels-text.png" full="false" >}} + +You can search **public** (not subscribed yet) channels **by text**: + +```http request +POST /api/{session}/channels/search/by-text +``` + +```json { title="Body" } +{ + "text": "Donald Trump", + "categories": [], + "limit": 50, + "startCursor": "" +} +``` + +- `text` - search text +- `categories` - use `id` from [get available categories](#get-search-categories) +- `limit` - we recommend using default `50` value, it's the way official clients work +- `startCursor` - use `endCursor` from the previous response (if any data available on the next page) + +### Get Search Views + +List of available views for search: + +```http request +GET /api/{session}/channels/search/views +``` + +```json { title="Response" } +[ + { + "value": "RECOMMENDED", + "name": "Explore" + } +] +``` + +### Get Search Countries + +List of available countries for search (not full one, you can try different `code` values if you don't see your country): + +```http request +GET /api/{session}/channels/search/countries +``` + +```json { title="Response" } +[ + { + "code": "US", + "name": "United States" + } +] +``` + +### Get Search Categories + +List of available categories for search: + +```http request +GET /api/{session}/channels/search/categories +``` + +```json { title="Response" } +[ + { + "value": "BUSINESS", + "name": "Business" + }, + { + "value": "ENTERTAINMENT", + "name": "Entertainment" + } +] +``` + +### Get Messages (Preview) for Channel + +You can get latest messages from **public** channels (not subscribed yet) by invite code (or channel id). +Returns only **preview** messages (one that you'll see on channel preview). + +```http request +GET /api/{SESSION}/channels/{INVITE}/messages/preview?downloadMedia=false&limit=100 +``` + +**Query parameters**: + +- `{SESSION}` - your session +- `{INVITE}` - invite code (123123123) or channel id (123132123@newsletter). **Invite code is recommended**. +- `downloadMedia` - whether to download media or not +- `limit` - limit of messages to return. **100 is recommended**. + +```json +[ + { + "reactions": { + "👍": 10, + "❤️": 5 + }, + "viewCount": 0, + "message": { + "id": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "timestamp": 1666943582, + "body": "string", + "media": { + ... + } + } + } +] +``` + +- `reactions` - reactions for the message +- `viewCount` - views count for the message +- `message` - message object - the same as in `payload` field [**message**]({{< relref "/docs/how-to/events#message" >}}) event + +## How-to + +### Send Text to the channel + +You can use regular [`POST /api/sendText`]({{< relref "/docs/how-to/send-messages#send-text" >}}) endpoint to send a +text message into the channel + +👉 Make sure you're `OWNER` or `ADMIN` for the channel + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@newsletter", + "text": "Hi there!" +} +``` + +### Send Image to the channel + +You can use regular [`POST /api/sendImage`]({{< relref "/docs/how-to/send-messages#send-image" >}}) endpoint +to send an image into the channel + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@newsletter", + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + "filename": "filename.jpeg" + }, + "caption": "string" +} +``` + +### Send Video to the channel + +You can use regular [`POST /api/sendVideo`]({{< relref "/docs/how-to/send-messages#send-video" >}}) endpoint +to send a video message into the channel + +```json { title="Body" } +{ + "chatId": "111111111111111111@newsletter", + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "caption": "Just watch at this!", + "session": "default" +} +``` + +### Send Reaction to the channel + +```http request +PUT /api/reaction +``` + +```json { title="Body" } +{ + "messageId": "false_11111111111@newsletter_AAAAAAAAAAAAAAAAAAAA", + "reaction": "👍", + "session": "default" +} +``` + +`messageId` can be in 2 format: + +1. `false_11111111111@newsletter_AAAAAAAAAAAAAAAAAAAA` - using characters. Works if you're subscribed to the channel. +2. `false_11111111111@newsltter_123` - using `server_id`. If you're not subscribed to the channel, you can use this format. + +You can find `server_id` in message: +{{< tabs "channel-message-id-for-reaction" >}} +{{< tab "NOWEB" >}} +Find `_data.key.server_id` value: + +```json +{ + "event": "message.any", + "payload": { + ... + "_data": { + "key": { + "remoteJid": "120363417343416222@newsletter", + ... + "server_id": "101" # <=== this one + }, + ... + } + }, + ... +} +``` + +{{< /tab >}} + +{{< tab "GOWS" >}} +Find `_data.Info.ServerID` value: + +```json +{ + "event": "message.any", + "payload": { + ... + "_data": { + "Info": { + "Chat": "111111111111111111@newsletter", + ... + "ServerID": 105, # <=== this one + ... + }, + ... + } + } +} +``` + +{{< /tab >}} + +{{< tab "WEBJS" >}} +Not supported +{{< /tab >}} +{{< /tabs >}} + +### Get messages from the channel + +You can use regular +[`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) +to fetch messages from the channel + +```http request +GET /api/default/chats/123%40newsletter/messages?downloadMedia=true&limit=100 +``` + +```json +[ + { + "id": "true_111111111111111111@newsletter_1111111111111111111111", + "timestamp": 1720775833, + "from": "111111111111111111@newsletter", + "fromMe": true, + "body": "Caption", + "hasMedia": true, + "media": { + "mimetype": "image/jpeg", + "filename": null, + "url": "http://localhost:3000/api/files/1111111111111111111111.jpeg", + "error": null // if there was an error during file download + }, + "mediaUrl": "http://localhost:3000/api/files/1111111111111111111111.jpeg", + "ack": 0, + "ackName": "PENDING", + "_data": { + ... + } + } +] + +``` + +### Receive messages from the channel + +For all incoming messages in your own and subscribed channels you'll receive + +- [`message`]({{< relref "/docs/how-to/receive-messages#message" >}}) event for a message from the channel (send by + someone else) +- [`message.any`]({{< relref "/docs/how-to/receive-messages#message.any" >}}) event for a message from the channel ( + including your messages) + +```json { title="message" } +{ + "event": "message", + "session": "default", + "me": { + "id": "111111111111@c.us", + "pushName": "Slovakia WAHA" + }, + "payload": { + "id": "false_123123@newsletter_11111111111111111111111111111111", + "timestamp": 1720776511, + "from": "111111111111111111@newsletter", + "fromMe": false, + "body": "How are you all?! ❤️", + "hasMedia": false, + "ack": null, + "ackName": "UNKNOWN", + "_data": { + ... + } + }, + "engine": "NOWEB", + "environment": { + "version": "2024.7.4", + "engine": "NOWEB", + "tier": "PLUS", + "browser": "/usr/bin/google-chrome-stable" + } +} +``` diff --git a/content/docs/how-to/chats/features-events.md b/content/docs/how-to/chats/features-events.md index b466a27a8..301c73483 100644 --- a/content/docs/how-to/chats/features-events.md +++ b/content/docs/how-to/chats/features-events.md @@ -1,8 +1,8 @@ -
-{{< details "**💬 Chats - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|----------------|:-----:|:-----:|:----:| -| `chat.archive` | ✔️ | | | - -{{< /details >}} +
+{{< details "**💬 Chats - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| -------------- | :---: | :---: | :--: | +| `chat.archive` | ✔️ | | | + +{{< /details >}} diff --git a/content/docs/how-to/chats/features.md b/content/docs/how-to/chats/features.md index 21476ab56..6426d6caa 100644 --- a/content/docs/how-to/chats/features.md +++ b/content/docs/how-to/chats/features.md @@ -1,26 +1,26 @@ -
-{{< details "**💬 Chats - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|----------------------------------------------------------------------------------------|:-----:|:-----:|:-----:| -| **Get all chats**
`GET /api/{session}/chats` | ✔️ | ✔️¹ | ✔️ | -| **Get chats overview**
`GET /api/{session}/chats/overview` | ✔️ | ✔️¹ | ✔️ | -| **Get chat picture**
`GET /api/{session}/chats/{chatId}/picture` | ✔️ | ✔️¹ | ✔️ | -| **Unread chat**
`POST /api/{session}/chats/{chatId}/unread` | ✔️ | ✔️¹ | | -| **Archive chat**
`POST /api/{session}/chats/{chatId}/archive` | ✔️ | ✔️¹ | | -| **Unarchive chat**
`POST /api/{session}/chats/{chatId}/unarchive` | ✔️ | ✔️¹ | | -| **Delete chat**
`DELETE /api/{session}/chats/{chatId}` | ✔️ | | | -| **Read messages**
`POST /api/{session}/chats/{chatId}/messages/read` | ✔️ | ✔️¹ | ✔️ | -| **Get messages**
`GET /api/{session}/chats/{chatId}/messages` | ✔️ | ✔️¹ | ✔️ | -| **Get message by id**
`GET /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️¹ | ✔️ | -| **Pin message**
`POST /api/{session}/chats/{chatId}/messages/{messageId}/pin` | ✔️ | ✔️ | | -| **Unpin message**
`POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin` | ✔️ | ✔️ | | -| **Edit message**
`PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | | -| **Delete message**
`DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | | -| **Delete all messages**
`DELETE /api/{session}/chats/{chatId}/messages` | ✔️ | | | - -1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**💬 Chats - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| -------------------------------------------------------------------------------------- | :---: | :---: | :--: | +| **Get all chats**
`GET /api/{session}/chats` | ✔️ | ✔️¹ | ✔️ | +| **Get chats overview**
`GET /api/{session}/chats/overview` | ✔️ | ✔️¹ | ✔️ | +| **Get chat picture**
`GET /api/{session}/chats/{chatId}/picture` | ✔️ | ✔️¹ | ✔️ | +| **Unread chat**
`POST /api/{session}/chats/{chatId}/unread` | ✔️ | ✔️¹ | | +| **Archive chat**
`POST /api/{session}/chats/{chatId}/archive` | ✔️ | ✔️¹ | | +| **Unarchive chat**
`POST /api/{session}/chats/{chatId}/unarchive` | ✔️ | ✔️¹ | | +| **Delete chat**
`DELETE /api/{session}/chats/{chatId}` | ✔️ | | | +| **Read messages**
`POST /api/{session}/chats/{chatId}/messages/read` | ✔️ | ✔️¹ | ✔️ | +| **Get messages**
`GET /api/{session}/chats/{chatId}/messages` | ✔️ | ✔️¹ | ✔️ | +| **Get message by id**
`GET /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️¹ | ✔️ | +| **Pin message**
`POST /api/{session}/chats/{chatId}/messages/{messageId}/pin` | ✔️ | ✔️ | | +| **Unpin message**
`POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin` | ✔️ | ✔️ | | +| **Edit message**
`PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | | +| **Delete message**
`DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | | +| **Delete all messages**
`DELETE /api/{session}/chats/{chatId}/messages` | ✔️ | | | + +1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/chats/index.md b/content/docs/how-to/chats/index.md index 8ee55465d..d52919ea3 100644 --- a/content/docs/how-to/chats/index.md +++ b/content/docs/how-to/chats/index.md @@ -1,379 +1,405 @@ ---- -title : "💬 Chats" -description: "Chats" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 227 -images: ["chats.jpg"] -slug: chats ---- - -Chats methods. - -
-{{< img lqip="21x webp q20" src="chats.jpg" alt="WhatsApp Chats" >}} -
- -## Features -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/chats/features.md" >}} - -{{< include file="content/docs/how-to/chats/features-events.md" >}} - -## API -Parameters in path that you can find in below endpoints: -- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/sessions` endpoint -- `{chatId}` - chat id in format `123123123123@[c.us|g.us]`, `c.us` for direct chats and `g.us` for groups. - -### Get all chats -Get all chats -```http request -GET /api/{session}/chats -``` - -#### Chats Pagination -If you see timeout or the request takes too long - consider using `limit` parameter to get chats in smaller chunks - -```http request -GET /api/{session}/chats?limit=100&offset=0&sortBy=messageTimestamp&sortOrder=desc -``` - -- `limit=100` - limit the number of chats to return -- `offset=0` - skip the number of chats from the start -- `sortBy={field}` - sort by field - - `sortBy=messageTimestamp` - sort by last message timestamp - - `sortBy=id` - sort by chat id - - `sortBy=name` - sort by chat name -- `sortOrder=desc|asc` - sort order - - `desc` - descending order (New first, A-Z) - - `asc` - ascending order (Old first, Z-A) - -### Get chats overview -Get chats "overview" - the API that almost all -[**Chat UI**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) -client needs! - -```http request -GET /api/{session}/chats/overview?limit=20&offset=0 -``` - -**Query Parameters**: -- `limit=100` - limit the number of chats to return -- `offset=0` - skip the number of chats from the start -- `ids=11111&ids=9999@c.us` - optional, filter result by chat id or phone number - - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Use `POST` request if you have a lot of chats (>400) in `ids` filter -{{< /callout >}} - -```http request -POST /api/{session}/chats/overview -``` - -```json { title="Request (POST)" } -{ - "pagination": { - "limit": 20, - "offset": 0 - }, - "filter": { - "ids": ["111111@c.us"] - } -} -``` - -**Response** contains the main info you need to show in the chat list: -1. `id` - chat id -2. `name` - chat name (if any) -3. `picture` - chat picture (if any) -4. `lastMessage` - last message in the chat (if any). -5. `_chat` - the structure depends on engine you're using - -⚠️ `lastMessage` doesn't have media attachments, you need to [get message by id]({{< relref "#get-message-by-id" >}}) to get media attachments. - -```json { title="Response" } -[ - { - "id": "12312l123@c.us", - "name": "John Doe", - "picture": "https://example.com/picture.jpg", - "lastMessage": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "fromMe": true, - "to": "11111111111@c.us", - "body": "Hi there!", - ... - }, - "_chat": { - ... - } - } -] - -``` - - -### Get chat picture -Get chat picture (avatar, profile picture, group image) by chat id -```http request -GET /api/{session}/chats/{chatId}/picture[?refresh=True] -``` - -**Query** -- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. - -```json { title="Response" } -{ - "url": "https://example.com/picture.jpg" -} -``` -- `url` can be `null` if there's no picture for the chat - -### Archive chat - -Use the method to archive chat -```http request -POST /api/{session}/chats/{chatId}/archive -``` - -### Unarchive chat - -Use the method to unarchive chat - -```http request -POST /api/{session}/chats/{chatId}/unarchive -``` - -### Unread chat -Mark chat as unread - -```http request -POST /api/{session}/chats/{chatId}/unread -``` - -### Delete chat -Use the method to delete chat - -```http request -DELETE /api/{session}/chats/{chatId} -``` - -### Read messages -You can mark all **unread** messages in the chat as **read** (double blue checkmark) using one query: - -It'll find all unread messages in the chat and mark them as read. - -```http request -POST /api/{SESSION}/chats/{chatId}/messages/read -``` - -```json { title="Body" } -{} -``` - -```json { title="Response" } -{ - "ids": [ - "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "true_99999999999@c.us_AAAAAAAAAAAAAAAAAAAA" - ] -} -``` -- `ids` - list of message ids that were marked as read - -{{< callout context="note" icon="outline/info-circle" >}} -👉 **NOWEB**: Please make sure to [**🏭 Enable NOWEB Store before using this API**]({{< relref "/docs/engines/NOWEB#store" >}})! -{{< /callout >}} - -Optionally, you can control how many messages you need to read: - -```json { title="Body" } -{ - "messages": 30, - "days": 7 -} -``` -- `messages: 30` - how many messages you need to read - - defaults is `30` for **direct chats** and `100` for **groups** -- `days: 7` - how many days you need to read - - default is `7` - -For more granular control, you can use the -[**POST /api/sendSeen**]({{< relref "/docs/how-to/send-messages#send-seen" >}}) -API. - -### Get messages -Get **10 messages** from the chat - -```http request -GET /api/{session}/chats/{chatId}/messages?limit=10 -``` - -Available parameters: -- `downloadMedia=true` - download media files (images, files) or not -- `chatId=123@c.us` - chatId, phone number - - `chatId=all` - get messages from all chats (works on [**NOWEB**]({{< relref "/docs/how-to/engines#noweb" >}}) engine only) -- `limit=100` - limit the number of chats to return -- `offset=0` - skip the number of chats from the start -- `filter.timestamp.lte=1727745026` - filter messages by timestamp less than or equal to `1727745026` -- `filter.timestamp.gte=1727745026` - filter messages by timestamp greater than or equal to `1727745026` -- `filter.fromMe=false` - filter messages from me (by default, shows all messages) -- `filter.ack=DEVICE` - filter messages by ack - - `ERROR, ack: -1` - error occurred - - `PENDING, ack: 0` - message is pending - - `SERVER, ack: 1` - message was sent to server - - `DEVICE, ack: 2` - message was sent to the device - - `READ, ack: 3` - recipient read message - - `PLAYED, ack: 4` - recipient played the message - -Get **10 messages** from the chat, skip **downloading media** (images, files) - -```http request -GET /api/{session}/chats/{chatId}/messages?limit=10&downloadMedia=false -``` - -```json -[ - { - "id": "false_123123@c.us_AAAAAA", - "timestamp": 1727745026, - "from": "123123@c.us", - "fromMe": false, - "body": "I'm good!", - "hasMedia": false, - "ack": 3, - "ackName": "READ", - "replyTo": null, - "_data": { - ... // Raw Engine Data - } - } -] -``` - -Get **10 messages** from 1727745026 timestamp, not from me - -```http request -GET /api/{session}/chats/{chatId}/messages?limit=10&filter.timestamp.gte=1727745026&filter.fromMe=false -``` - -👉 If you have more messages - you can set `offset` flag -(increase it always for `limit` amount, even if you get less messages) -```http request -GET /api/{session}/chats/{chatId}/messages?limit=10&offset=10&filter.timestamp.gte=1727745026&filter.fromMe=false -``` - - -### Get message by id -Get message by id -```http request -GET /api/{session}/chats/{chatId}/messages/{messageId}?downloadMedia=true -``` - -```json { title="Response" } -{ - "id": "false_123123@c.us_AAAAAA", - "timestamp": 1727745026, - "from": "123123@c.us", - "fromMe": false, - "body": "I'm good!", - "hasMedia": false, - "ack": 3, - "ackName": "READ", - "replyTo": null, - "_data": { - ... // Raw Engine Data - } -} -``` - -- `chatId` - in format `123123123@c.us` -- `messageId` - must be in format `{true|false}_213213@c.us_AAAAAAA`) -- `downloadMedia` - download media files (images, files) or not - -### Pin message - -```http request -POST /api/{session}/chats/{chatId}/messages/{messageId}/pin -``` - -```json { title="Body" } -{ - "duration": 86400 -} -``` - -- 24 hours - `duration=86400` -- 7 days - `duration=604800` -- 30 days - `duration=2592000` - -```json { title="Response" } -{ - "success": true -} -``` - -### Unpin message - -```http request -POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin -``` - -```json { title="Response" } -{ - "success": true -} -``` - -### Edit message -You can edit **text** messages or **"caption"** in media messages. - -```http request -PUT /api/{session}/chats/{chatId}/messages/{messageId} -``` -👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. - -So if you want to edit `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: -```http request -PUT /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA -``` - -```json { title="Body" } -{ - "text": "Hello, world!" -} -``` - -### Delete message -You can delete messages from the chat. - -```http request -DELETE /api/{session}/chats/{chatId}/messages/{messageId} -``` - -👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. - -So if you want to delete `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: -```http request -DELETE /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA -``` - -### Delete all messages -Use the method to clear all messages from the chat - -```http request -DELETE /api/{session}/chats/{chatId}/messages -``` - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### chat.archive -{{< include file="content/docs/how-to/chats/webhooks-chat-archive.md" >}} +--- +title: "💬 Chats" +description: "Chats" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 227 +images: ["chats.jpg"] +slug: chats +--- + +Chats methods. + +
+{{< img lqip="21x webp q20" src="chats.jpg" alt="WhatsApp Chats" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/chats/features.md" >}} + +{{< include file="content/docs/how-to/chats/features-events.md" >}} + +## API + +Parameters in path that you can find in below endpoints: + +- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/sessions` endpoint +- `{chatId}` - chat id in format `123123123123@[c.us|g.us]`, `c.us` for direct chats and `g.us` for groups. + +### Get all chats + +Get all chats + +```http request +GET /api/{session}/chats +``` + +#### Chats Pagination + +If you see timeout or the request takes too long - consider using `limit` parameter to get chats in smaller chunks + +```http request +GET /api/{session}/chats?limit=100&offset=0&sortBy=messageTimestamp&sortOrder=desc +``` + +- `limit=100` - limit the number of chats to return +- `offset=0` - skip the number of chats from the start +- `sortBy={field}` - sort by field + - `sortBy=messageTimestamp` - sort by last message timestamp + - `sortBy=id` - sort by chat id + - `sortBy=name` - sort by chat name +- `sortOrder=desc|asc` - sort order + - `desc` - descending order (New first, A-Z) + - `asc` - ascending order (Old first, Z-A) + +### Get chats overview + +Get chats "overview" - the API that almost all +[**Chat UI**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) +client needs! + +```http request +GET /api/{session}/chats/overview?limit=20&offset=0 +``` + +**Query Parameters**: + +- `limit=100` - limit the number of chats to return +- `offset=0` - skip the number of chats from the start +- `ids=11111&ids=9999@c.us` - optional, filter result by chat id or phone number + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Use `POST` request if you have a lot of chats (>400) in `ids` filter +{{< /callout >}} + +```http request +POST /api/{session}/chats/overview +``` + +```json { title="Request (POST)" } +{ + "pagination": { + "limit": 20, + "offset": 0 + }, + "filter": { + "ids": ["111111@c.us"] + } +} +``` + +**Response** contains the main info you need to show in the chat list: + +1. `id` - chat id +2. `name` - chat name (if any) +3. `picture` - chat picture (if any) +4. `lastMessage` - last message in the chat (if any). +5. `_chat` - the structure depends on engine you're using + +⚠️ `lastMessage` doesn't have media attachments, you need to [get message by id]({{< relref "#get-message-by-id" >}}) to get media attachments. + +```json { title="Response" } +[ + { + "id": "12312l123@c.us", + "name": "John Doe", + "picture": "https://example.com/picture.jpg", + "lastMessage": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "fromMe": true, + "to": "11111111111@c.us", + "body": "Hi there!", + ... + }, + "_chat": { + ... + } + } +] + +``` + +### Get chat picture + +Get chat picture (avatar, profile picture, group image) by chat id + +```http request +GET /api/{session}/chats/{chatId}/picture[?refresh=True] +``` + +**Query** + +- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. + +```json { title="Response" } +{ + "url": "https://example.com/picture.jpg" +} +``` + +- `url` can be `null` if there's no picture for the chat + +### Archive chat + +Use the method to archive chat + +```http request +POST /api/{session}/chats/{chatId}/archive +``` + +### Unarchive chat + +Use the method to unarchive chat + +```http request +POST /api/{session}/chats/{chatId}/unarchive +``` + +### Unread chat + +Mark chat as unread + +```http request +POST /api/{session}/chats/{chatId}/unread +``` + +### Delete chat + +Use the method to delete chat + +```http request +DELETE /api/{session}/chats/{chatId} +``` + +### Read messages + +You can mark all **unread** messages in the chat as **read** (double blue checkmark) using one query: + +It'll find all unread messages in the chat and mark them as read. + +```http request +POST /api/{SESSION}/chats/{chatId}/messages/read +``` + +```json { title="Body" } +{} +``` + +```json { title="Response" } +{ + "ids": ["false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", "true_99999999999@c.us_AAAAAAAAAAAAAAAAAAAA"] +} +``` + +- `ids` - list of message ids that were marked as read + +{{< callout context="note" icon="outline/info-circle" >}} +👉 **NOWEB**: Please make sure to [**🏭 Enable NOWEB Store before using this API**]({{< relref "/docs/engines/NOWEB#store" >}})! +{{< /callout >}} + +Optionally, you can control how many messages you need to read: + +```json { title="Body" } +{ + "messages": 30, + "days": 7 +} +``` + +- `messages: 30` - how many messages you need to read + - defaults is `30` for **direct chats** and `100` for **groups** +- `days: 7` - how many days you need to read + - default is `7` + +For more granular control, you can use the +[**POST /api/sendSeen**]({{< relref "/docs/how-to/send-messages#send-seen" >}}) +API. + +### Get messages + +Get **10 messages** from the chat + +```http request +GET /api/{session}/chats/{chatId}/messages?limit=10 +``` + +Available parameters: + +- `downloadMedia=true` - download media files (images, files) or not +- `chatId=123@c.us` - chatId, phone number + - `chatId=all` - get messages from all chats (works on [**NOWEB**]({{< relref "/docs/how-to/engines#noweb" >}}) engine only) +- `limit=100` - limit the number of chats to return +- `offset=0` - skip the number of chats from the start +- `filter.timestamp.lte=1727745026` - filter messages by timestamp less than or equal to `1727745026` +- `filter.timestamp.gte=1727745026` - filter messages by timestamp greater than or equal to `1727745026` +- `filter.fromMe=false` - filter messages from me (by default, shows all messages) +- `filter.ack=DEVICE` - filter messages by ack + - `ERROR, ack: -1` - error occurred + - `PENDING, ack: 0` - message is pending + - `SERVER, ack: 1` - message was sent to server + - `DEVICE, ack: 2` - message was sent to the device + - `READ, ack: 3` - recipient read message + - `PLAYED, ack: 4` - recipient played the message + +Get **10 messages** from the chat, skip **downloading media** (images, files) + +```http request +GET /api/{session}/chats/{chatId}/messages?limit=10&downloadMedia=false +``` + +```json +[ + { + "id": "false_123123@c.us_AAAAAA", + "timestamp": 1727745026, + "from": "123123@c.us", + "fromMe": false, + "body": "I'm good!", + "hasMedia": false, + "ack": 3, + "ackName": "READ", + "replyTo": null, + "_data": { + ... // Raw Engine Data + } + } +] +``` + +Get **10 messages** from 1727745026 timestamp, not from me + +```http request +GET /api/{session}/chats/{chatId}/messages?limit=10&filter.timestamp.gte=1727745026&filter.fromMe=false +``` + +👉 If you have more messages - you can set `offset` flag +(increase it always for `limit` amount, even if you get less messages) + +```http request +GET /api/{session}/chats/{chatId}/messages?limit=10&offset=10&filter.timestamp.gte=1727745026&filter.fromMe=false +``` + +### Get message by id + +Get message by id + +```http request +GET /api/{session}/chats/{chatId}/messages/{messageId}?downloadMedia=true +``` + +```json { title="Response" } +{ + "id": "false_123123@c.us_AAAAAA", + "timestamp": 1727745026, + "from": "123123@c.us", + "fromMe": false, + "body": "I'm good!", + "hasMedia": false, + "ack": 3, + "ackName": "READ", + "replyTo": null, + "_data": { + ... // Raw Engine Data + } +} +``` + +- `chatId` - in format `123123123@c.us` +- `messageId` - must be in format `{true|false}_213213@c.us_AAAAAAA`) +- `downloadMedia` - download media files (images, files) or not + +### Pin message + +```http request +POST /api/{session}/chats/{chatId}/messages/{messageId}/pin +``` + +```json { title="Body" } +{ + "duration": 86400 +} +``` + +- 24 hours - `duration=86400` +- 7 days - `duration=604800` +- 30 days - `duration=2592000` + +```json { title="Response" } +{ + "success": true +} +``` + +### Unpin message + +```http request +POST /api/{session}/chats/{chatId}/messages/{messageId}/unpin +``` + +```json { title="Response" } +{ + "success": true +} +``` + +### Edit message + +You can edit **text** messages or **"caption"** in media messages. + +```http request +PUT /api/{session}/chats/{chatId}/messages/{messageId} +``` + +👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. + +So if you want to edit `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: + +```http request +PUT /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA +``` + +```json { title="Body" } +{ + "text": "Hello, world!" +} +``` + +### Delete message + +You can delete messages from the chat. + +```http request +DELETE /api/{session}/chats/{chatId}/messages/{messageId} +``` + +👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. + +So if you want to delete `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: + +```http request +DELETE /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA +``` + +### Delete all messages + +Use the method to clear all messages from the chat + +```http request +DELETE /api/{session}/chats/{chatId}/messages +``` + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### chat.archive + +{{< include file="content/docs/how-to/chats/webhooks-chat-archive.md" >}} diff --git a/content/docs/how-to/chats/webhooks-chat-archive.md b/content/docs/how-to/chats/webhooks-chat-archive.md index 73301169a..bb001aa05 100644 --- a/content/docs/how-to/chats/webhooks-chat-archive.md +++ b/content/docs/how-to/chats/webhooks-chat-archive.md @@ -1,14 +1,14 @@ -The `chat.archive` event is triggered when a chat is archived or unarchived. - -```json { title="chat.archive" } -{ - "event": "chat.archive", - "session": "default", - "payload": { - "id": "123123123@c.us", - "timestamp": 1667561485, - "archived": true <== or false - }, - ... -} -``` +The `chat.archive` event is triggered when a chat is archived or unarchived. + +```json { title="chat.archive" } +{ + "event": "chat.archive", + "session": "default", + "payload": { + "id": "123123123@c.us", + "timestamp": 1667561485, + "archived": true <== or false + }, + ... +} +``` diff --git a/content/docs/how-to/config/index.md b/content/docs/how-to/config/index.md index 52a4c58d0..42e8e9e24 100644 --- a/content/docs/how-to/config/index.md +++ b/content/docs/how-to/config/index.md @@ -1,321 +1,339 @@ ---- -title: "⚙️ Configuration" -description: "Configuration" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 299 -slug: config ---- - -You can configure WhatsApp API behavior via environment variables. - -{{< tabs "config-methods" >}} - -{{< tab "docker run" >}} -You can add environment variables by adding `-e WHATSAPP_VARNAME=value` at the -beginning of the command line or by using [other options](https://docs.docker.com/engine/reference/commandline/run/) - -```bash -docker run -it -e "WAHA_WORKER_ID=waha" -e WAHA_PRINT_QR=False devlikeapro/waha-plus -``` -{{< /tab >}} - -{{< tab "docker compose" >}} -It's not necessary to always run such a long command - you can save all data in -[docker-compose.yaml](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) -file as described on [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}). - -```yaml { title="docker-compose.yaml" } -version: '3' - -services: - waha: - image: devlikeapro/waha-plus - container_name: waha - restart: unless-stopped - ports: - - "127.0.0.1:3000:3000" - environment: - - WAHA_WORKER_ID=waha - - WAHA_PRINT_QR=False -``` - -```bash -docker compose up -d -``` -{{< /tab >}} - -{{< tab ".env" >}} -You can also use a `.env` file to set environment variables. Create a `.env` file in the same directory as your docker-compose.yaml file. - -```json { title=".env" } -WAHA_WORKER_ID=waha -WAHA_PRINT_QR=False -``` - -Then reference it in your docker-compose.yaml file: - -```yaml { title="docker-compose.yaml" } -version: '3' - -services: - waha: - image: devlikeapro/waha-plus - container_name: waha - restart: unless-stopped - ports: - - "127.0.0.1:3000:3000" - env_file: - - .env -``` - -```bash -docker compose up -d -``` -{{< /tab >}} - -{{< /tabs >}} - - -## Common -- `WHATSAPP_API_PORT=3000`: The port number that the HTTP server will listen on. The default value is `3000`. - - `PORT=3000` is also supported (for Heroku compatibility) -- `WHATSAPP_API_HOSTNAME=localhost`: The hostname for the HTTP server. The default value is `localhost`. -- `WHATSAPP_API_SCHEMA=https` - it just changes `media.url` schema when you receive media (with files) messages. -- `WAHA_BASE_URL` - will be used to construct the `media.url` field in the webhook events. - - By default, it's `{WHATSAPP_API_SCHEMA}://{WHATSAPP_API_HOSTNAME}:{WHATSAPP_API_PORT}`. -- `TZ=Europe/Warsaw` - set the timezone for the container. The default value is `UTC`. Find [your timezone in the list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). -- `WAHA_DEBUG_MODE=false` - enables some API only for development or troubleshooting purposes. Disabled by default. - - Read more on [**🔍 Observability**]({{< relref "/docs/how-to/observability#waha-debug-mode" >}}) page. - - -## Logging - -Read more about [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - -Options you can use to control how WAHA outputs logs: -- `WAHA_LOG_FORMAT` - supports formats: - - `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format - - `WAHA_LOG_FORMAT=JSON` - can be useful if you're using a central logging management system -- `WAHA_LOG_LEVEL` - how much information to log `error | warn | info | debug | trace`. - - 👉 Do not set `debug` and `trace` in production, as these levels generate excessive log output. -- `WAHA_HTTP_LOG_LEVEL=info` - controls the level of `request completed` log (HTTP access). You can set it to `error | warn | info | debug | trace`. -- `DEBUG=1` - you can set this environment variable as a shortcut for `WAHA_LOG_LEVEL=debug`, `DEBUG=1` overrides the `WAHA_LOG_LEVEL` to `debug` if both defined. -👉 Learn more about logging configuration on [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) page. - - -## Engines -Read more about [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) - -- `WHATSAPP_DEFAULT_ENGINE=WEBJS` - set the default engine for all sessions. Available options: `WEBJS`, `NOWEB`, `GOWS`. By default, it's `WEBJS`. - -### WEBJS -You can use some of the following environment variables to configure the [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) session: -- `WAHA_WEBJS_CACHE_TYPE=local` - enable cache (aka use the latest version) for the **web page** in the browser. By default, it's `none` (no cache) -- `WAHA_WEBJS_WEB_VERSION=2.3000.XXXX` - set the version of the WhatsApp Web to use. By default, we're using the latest compatible version. Only works with `local` cache type. - -## Sessions - -Read more about [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) and [**🗄️ Storages**]({{< relref "/docs/how-to/storages#sessions" >}}) - -- `WAHA_AUTO_START_DELAY_SECONDS=0` - when docker-container restarts, WAHA starts all `STOPPED` sessions (or all sessions if you set `WAHA_RESTART_ALL_SESSIONS=True`). You can set the delay between session restarts in seconds. - - By default, it's `0`. - - **WEBJS** - consider setting it to `5` if you have many sessions - - **NOWEB** - it's fine to leave to `0` or you can increase to `1` if you experience issues with starting sessions. -- `WAHA_PRINT_QR=True` - set this variable to `False` to disable printing QR codes to the console. By default, `True`. -- `WAHA_WORKER_ID=waha1` - set the worker ID for the session. - - Workers restore sessions if worker got restarted. If you have multiple workers, each worker will restore its own sessions. -- `WHATSAPP_RESTART_ALL_SESSIONS=True`: Set this variable to `True` to start all **STOPPED** sessions after container - restarts. By default, this variable is set to `False`. - -Rarely used: -- `WAHA_WORKER_RESTART_SESSIONS=True` - restart all sessions when the worker is restarted. By default, `True`. -- `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. -- `WAHA_ZIPPER=ZIPUNZIP` - use `zip` and `unzip` system binaries to pack **WEBJS** authentication data. Disabled by default. - - It's relevant if you're using **WEBJS + MongoDB**. Install `zip` and `unzip` if you don't use our official docker image and set the variable - -### Sessions - Local -- `WAHA_LOCAL_STORE_BASE_DIR=/app/.sessions` - Override the base directory for local storage of session data - -### Sessions - PostgreSQL -- `WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable` - PostgreSQL connection URL for storing session data - -### Sessions - MongoDB -- `WHATSAPP_SESSIONS_MONGO_URL=mongodb://user:password@host:port/` - MongoDB connection URL for storing session data - -## Apps - -{{< include file="content/docs/apps/about/-config.md" >}} - -## Webhooks - -Read more about [**🔄 Events & Webhooks**]({{< relref "/docs/how-to/events" >}}) - -💡 You can open [https://webhook.site](https://webhook.site) and paste UUID from it to `url` field, -and you'll see all requests immediately in your browser to intercept the webhook's payload. - -### Global webhooks -You can configure webhooks for **all sessions** at once by setting these environment variables: - -- `WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111` - to set up a URL for the webhook -- `WHATSAPP_HOOK_EVENTS=message,message.any,state.change` - specify events. - - `WHATSAPP_HOOK_EVENTS=*` - subscribe to all events. - - We don't suggest using `*` or all events for production, it can generate a lot of requests. -- `WHATSAPP_HOOK_HMAC_KEY=your-secret-key` - the same as `hmac.key` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_POLICY=linear` - the same as `retries.policy` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_DELAY_SECONDS=2` - the same as `retries.delaySeconds` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_ATTEMPTS=4` -- `WHATSAPP_HOOK_CUSTOM_HEADERS=X-My-Custom-Header-1:Value;X-My-Custom-Header-2:Value` - the same as `customHeaders` field in the webhook configuration. - - Use `Header:Value` format and separate them by `;`. - -That webhook configuration **does not appear** in `session.config` field in `GET /api/sessions/` request. - -💡 You can open [https://webhook.site](https://webhook.site) and paste URL from it to `url` field, -and you'll see all requests immediately in your browser to intercept the webhook's payload. - -### Session webhooks -You can configure webhook when you start session by setting `config.webhook` fields. - -Read more about it on [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions#configure-webhook" >}}). - -## Swagger - -Read more about [**📚 Swagger**]({{< relref "/docs/how-to/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. -- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. -- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. -- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. -- `WHATSAPP_SWAGGER_VIDEO_EXAMPLE_URL` - link to the video example. -- `WHATSAPP_SWAGGER_OPUS_EXAMPLE_URL` - link to the opus example. -- `WHATSAPP_SWAGGER_JPG_EXAMPLE_URL` - link to the jpg example. - -## Proxy - -Read more about [**🔌 Proxy**]({{< relref "/docs/how-to/proxy" >}}) - -### Global proxy -If you need to use a proxy, you can set the following environment variables: - -- `WHATSAPP_PROXY_SERVER=localhost:3128`: Use this variable to set the proxy server in the format `host:port`, without http or https. -- `WHATSAPP_PROXY_SERVER_USERNAME=username` and `WHATSAPP_PROXY_SERVER_PASSWORD=password`: Use these variables to set up credentials for the proxy. -- `WHATSAPP_PROXY_SERVER_LIST=host1.example.com:3138,host2.example.com:3138`: Use this variable to set a comma-separated list of addresses to use, using a round-robin algorithm to choose the server for the session. -- `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-`: Use this variable to parse the session name for the prefix and find the appropriate session. - For example, if you have set `WHATSAPP_PROXY_SERVER_LIST=host-first:80,host-second:80,host-third:80` and `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-` and you run `proxy-3` session, the `host-third:80` proxy will be chosen for that session. - This is a way to select a proxy from while you start session. - -### Session proxy -You can configure proxy when you start session by setting `config.proxy` fields. -Read more about it on [**Session page** ->]({{< relref "/docs/how-to/sessions#configure-proxy" >}}). - -Keep in mind that session's proxy configuration takes precedence over proxy configuration set by environment variables! - -## HTTPS - -Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) - -{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} - -Enable HTTPS directly in WAHA by setting the following environment variables: - -- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. -- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` -- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` -- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` - - -## Security - -Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) - -**API** -- `WAHA_API_KEY=sha512:{SHA512_HEX_HASH}`: require `X-Api-Key: {KEY}` header in all requests to the API. - - `WAHA_API_KEY=sha512:c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec`: require `X-Api-Key: admin` header in all requests to the API. - - `WAHA_API_KEY=admin`- plain key works, but it's better to set **SHA512** instead. - - `WHATSAPP_API_KEY=admin` - also works, but it's better to set **SHA512** instead. -- `WHATSAPP_API_KEY_EXCLUDE_PATH=ping,health` - exclude URI from key auth [#451](https://github.com/devlikeapro/waha/issues/451) - -**Dashboard** -- `WAHA_DASHBOARD_ENABLED=true`: Toggle to enable or disable the dashboard. -- `WAHA_DASHBOARD_USERNAME=waha`: Default username for login (default: waha). -- `WAHA_DASHBOARD_PASSWORD=waha`: Default password for login (default: waha). - -**Swagger** -- `WHATSAPP_SWAGGER_ENABLED=true`: Toggle to enable or disable the Swagger. -- `WHATSAPP_SWAGGER_USERNAME=admin` -- `WHATSAPP_SWAGGER_PASSWORD=admin` -Swagger panel with `admin / admin` credentials. This does not affect API access. - - -## Files - -Read more about [**🖼️ Media Storage**]({{< relref "/docs/how-to/storages#media-storage" >}}) and [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) - - -### Files - Local -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`). 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" >}}) - -💡 When media files are not processed due to `WHATSAPP_FILES_MIMETYPES` or `WHATSAPP_DOWNLOAD_MEDIA` settings, -you'll still receive a webhook event with `hasMedia: True` field, but without a `media.url`. -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "hasMedia": true, - "media": { - "url": null, - "mimetype": "video/mp4", - "filename": null, - "error": null // if there was an error during file download - } - } -} -``` - -### Files - S3 -- `WAHA_MEDIA_STORAGE=S3` - enable the S3 storage -- `WAHA_S3_REGION=eu-west-1` - the region of the S3 bucket -- `WAHA_S3_BUCKET=waha` - the name of the S3 bucket -- `WAHA_S3_ACCESS_KEY_ID=minioadmin` - the access key of the S3 bucket -- `WAHA_S3_SECRET_ACCESS_KEY=minioadmin` - the secret access key of the S3 bucket -- `WAHA_S3_ENDPOINT=http://127.0.0.1:9000` - the endpoint of the S3 bucket (not required for AWS S3) -- `WAHA_S3_FORCE_PATH_STYLE=True` - force path style for the S3 bucket (not required for AWS S3) -- `WAHA_S3_PROXY_FILES` - proxy media files through WAHA (`False` by default) - - `WAHA_S3_PROXY_FILES=False` - generate pre-signed URLs for media files and send them to the client in `media.url` - - `WAHA_S3_PROXY_FILES=True` - WAHA will proxy media files through itself in `media.url` - -### Files - PostgreSQL -- `WAHA_MEDIA_STORAGE=POSTGRESQL` - enable the PostgreSQL storage for media files -- `WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable` - PostgreSQL connection URL for storing media files - -## Health Check - -Read more about [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - -Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/waha-plus" >}}) only. - -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`. +--- +title: "⚙️ Configuration" +description: "Configuration" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 299 +slug: config +--- + +You can configure WhatsApp API behavior via environment variables. + +{{< tabs "config-methods" >}} + +{{< tab "docker run" >}} +You can add environment variables by adding `-e WHATSAPP_VARNAME=value` at the +beginning of the command line or by using [other options](https://docs.docker.com/engine/reference/commandline/run/) + +```bash +docker run -it -e "WAHA_WORKER_ID=waha" -e WAHA_PRINT_QR=False devlikeapro/waha-plus +``` + +{{< /tab >}} + +{{< tab "docker compose" >}} +It's not necessary to always run such a long command - you can save all data in +[docker-compose.yaml](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml) +file as described on [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}). + +```yaml { title="docker-compose.yaml" } +version: "3" + +services: + waha: + image: devlikeapro/waha-plus + container_name: waha + restart: unless-stopped + ports: + - "127.0.0.1:3000:3000" + environment: + - WAHA_WORKER_ID=waha + - WAHA_PRINT_QR=False +``` + +```bash +docker compose up -d +``` + +{{< /tab >}} + +{{< tab ".env" >}} +You can also use a `.env` file to set environment variables. Create a `.env` file in the same directory as your docker-compose.yaml file. + +```json { title=".env" } +WAHA_WORKER_ID=waha +WAHA_PRINT_QR=False +``` + +Then reference it in your docker-compose.yaml file: + +```yaml { title="docker-compose.yaml" } +version: "3" + +services: + waha: + image: devlikeapro/waha-plus + container_name: waha + restart: unless-stopped + ports: + - "127.0.0.1:3000:3000" + env_file: + - .env +``` + +```bash +docker compose up -d +``` + +{{< /tab >}} + +{{< /tabs >}} + +## Common + +- `WHATSAPP_API_PORT=3000`: The port number that the HTTP server will listen on. The default value is `3000`. + - `PORT=3000` is also supported (for Heroku compatibility) +- `WHATSAPP_API_HOSTNAME=localhost`: The hostname for the HTTP server. The default value is `localhost`. +- `WHATSAPP_API_SCHEMA=https` - it just changes `media.url` schema when you receive media (with files) messages. +- `WAHA_BASE_URL` - will be used to construct the `media.url` field in the webhook events. + - By default, it's `{WHATSAPP_API_SCHEMA}://{WHATSAPP_API_HOSTNAME}:{WHATSAPP_API_PORT}`. +- `TZ=Europe/Warsaw` - set the timezone for the container. The default value is `UTC`. Find [your timezone in the list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). +- `WAHA_DEBUG_MODE=false` - enables some API only for development or troubleshooting purposes. Disabled by default. + - Read more on [**🔍 Observability**]({{< relref "/docs/how-to/observability#waha-debug-mode" >}}) page. + +## Logging + +Read more about [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) + +Options you can use to control how WAHA outputs logs: + +- `WAHA_LOG_FORMAT` - supports formats: + - `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format + - `WAHA_LOG_FORMAT=JSON` - can be useful if you're using a central logging management system +- `WAHA_LOG_LEVEL` - how much information to log `error | warn | info | debug | trace`. + - 👉 Do not set `debug` and `trace` in production, as these levels generate excessive log output. +- `WAHA_HTTP_LOG_LEVEL=info` - controls the level of `request completed` log (HTTP access). You can set it to `error | warn | info | debug | trace`. +- `DEBUG=1` - you can set this environment variable as a shortcut for `WAHA_LOG_LEVEL=debug`, `DEBUG=1` overrides the `WAHA_LOG_LEVEL` to `debug` if both defined. + 👉 Learn more about logging configuration on [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) page. + +## Engines + +Read more about [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) + +- `WHATSAPP_DEFAULT_ENGINE=WEBJS` - set the default engine for all sessions. Available options: `WEBJS`, `NOWEB`, `GOWS`. By default, it's `WEBJS`. + +### WEBJS + +You can use some of the following environment variables to configure the [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) session: + +- `WAHA_WEBJS_CACHE_TYPE=local` - enable cache (aka use the latest version) for the **web page** in the browser. By default, it's `none` (no cache) +- `WAHA_WEBJS_WEB_VERSION=2.3000.XXXX` - set the version of the WhatsApp Web to use. By default, we're using the latest compatible version. Only works with `local` cache type. + +## Sessions + +Read more about [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) and [**🗄️ Storages**]({{< relref "/docs/how-to/storages#sessions" >}}) + +- `WAHA_AUTO_START_DELAY_SECONDS=0` - when docker-container restarts, WAHA starts all `STOPPED` sessions (or all sessions if you set `WAHA_RESTART_ALL_SESSIONS=True`). You can set the delay between session restarts in seconds. + - By default, it's `0`. + - **WEBJS** - consider setting it to `5` if you have many sessions + - **NOWEB** - it's fine to leave to `0` or you can increase to `1` if you experience issues with starting sessions. +- `WAHA_PRINT_QR=True` - set this variable to `False` to disable printing QR codes to the console. By default, `True`. +- `WAHA_WORKER_ID=waha1` - set the worker ID for the session. + - Workers restore sessions if worker got restarted. If you have multiple workers, each worker will restore its own sessions. +- `WHATSAPP_RESTART_ALL_SESSIONS=True`: Set this variable to `True` to start all **STOPPED** sessions after container + restarts. By default, this variable is set to `False`. + +Rarely used: + +- `WAHA_WORKER_RESTART_SESSIONS=True` - restart all sessions when the worker is restarted. By default, `True`. +- `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. +- `WAHA_ZIPPER=ZIPUNZIP` - use `zip` and `unzip` system binaries to pack **WEBJS** authentication data. Disabled by default. + - It's relevant if you're using **WEBJS + MongoDB**. Install `zip` and `unzip` if you don't use our official docker image and set the variable + +### Sessions - Local + +- `WAHA_LOCAL_STORE_BASE_DIR=/app/.sessions` - Override the base directory for local storage of session data + +### Sessions - PostgreSQL + +- `WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable` - PostgreSQL connection URL for storing session data + +### Sessions - MongoDB + +- `WHATSAPP_SESSIONS_MONGO_URL=mongodb://user:password@host:port/` - MongoDB connection URL for storing session data + +## Apps + +{{< include file="content/docs/apps/about/-config.md" >}} + +## Webhooks + +Read more about [**🔄 Events & Webhooks**]({{< relref "/docs/how-to/events" >}}) + +💡 You can open [https://webhook.site](https://webhook.site) and paste UUID from it to `url` field, +and you'll see all requests immediately in your browser to intercept the webhook's payload. + +### Global webhooks + +You can configure webhooks for **all sessions** at once by setting these environment variables: + +- `WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111` - to set up a URL for the webhook +- `WHATSAPP_HOOK_EVENTS=message,message.any,state.change` - specify events. + - `WHATSAPP_HOOK_EVENTS=*` - subscribe to all events. + - We don't suggest using `*` or all events for production, it can generate a lot of requests. +- `WHATSAPP_HOOK_HMAC_KEY=your-secret-key` - the same as `hmac.key` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_POLICY=linear` - the same as `retries.policy` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_DELAY_SECONDS=2` - the same as `retries.delaySeconds` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_ATTEMPTS=4` +- `WHATSAPP_HOOK_CUSTOM_HEADERS=X-My-Custom-Header-1:Value;X-My-Custom-Header-2:Value` - the same as `customHeaders` field in the webhook configuration. + - Use `Header:Value` format and separate them by `;`. + +That webhook configuration **does not appear** in `session.config` field in `GET /api/sessions/` request. + +💡 You can open [https://webhook.site](https://webhook.site) and paste URL from it to `url` field, +and you'll see all requests immediately in your browser to intercept the webhook's payload. + +### Session webhooks + +You can configure webhook when you start session by setting `config.webhook` fields. + +Read more about it on [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions#configure-webhook" >}}). + +## Swagger + +Read more about [**📚 Swagger**]({{< relref "/docs/how-to/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. +- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. +- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. +- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. +- `WHATSAPP_SWAGGER_VIDEO_EXAMPLE_URL` - link to the video example. +- `WHATSAPP_SWAGGER_OPUS_EXAMPLE_URL` - link to the opus example. +- `WHATSAPP_SWAGGER_JPG_EXAMPLE_URL` - link to the jpg example. + +## Proxy + +Read more about [**🔌 Proxy**]({{< relref "/docs/how-to/proxy" >}}) + +### Global proxy + +If you need to use a proxy, you can set the following environment variables: + +- `WHATSAPP_PROXY_SERVER=localhost:3128`: Use this variable to set the proxy server in the format `host:port`, without http or https. +- `WHATSAPP_PROXY_SERVER_USERNAME=username` and `WHATSAPP_PROXY_SERVER_PASSWORD=password`: Use these variables to set up credentials for the proxy. +- `WHATSAPP_PROXY_SERVER_LIST=host1.example.com:3138,host2.example.com:3138`: Use this variable to set a comma-separated list of addresses to use, using a round-robin algorithm to choose the server for the session. +- `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-`: Use this variable to parse the session name for the prefix and find the appropriate session. + For example, if you have set `WHATSAPP_PROXY_SERVER_LIST=host-first:80,host-second:80,host-third:80` and `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-` and you run `proxy-3` session, the `host-third:80` proxy will be chosen for that session. + This is a way to select a proxy from while you start session. + +### Session proxy + +You can configure proxy when you start session by setting `config.proxy` fields. +Read more about it on [**Session page** ->]({{< relref "/docs/how-to/sessions#configure-proxy" >}}). + +Keep in mind that session's proxy configuration takes precedence over proxy configuration set by environment variables! + +## HTTPS + +Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) + +{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} + +Enable HTTPS directly in WAHA by setting the following environment variables: + +- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. +- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` +- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` +- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` + +## Security + +Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) + +**API** + +- `WAHA_API_KEY=sha512:{SHA512_HEX_HASH}`: require `X-Api-Key: {KEY}` header in all requests to the API. + - `WAHA_API_KEY=sha512:c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec`: require `X-Api-Key: admin` header in all requests to the API. + - `WAHA_API_KEY=admin`- plain key works, but it's better to set **SHA512** instead. + - `WHATSAPP_API_KEY=admin` - also works, but it's better to set **SHA512** instead. +- `WHATSAPP_API_KEY_EXCLUDE_PATH=ping,health` - exclude URI from key auth [#451](https://github.com/devlikeapro/waha/issues/451) + +**Dashboard** + +- `WAHA_DASHBOARD_ENABLED=true`: Toggle to enable or disable the dashboard. +- `WAHA_DASHBOARD_USERNAME=waha`: Default username for login (default: waha). +- `WAHA_DASHBOARD_PASSWORD=waha`: Default password for login (default: waha). + +**Swagger** + +- `WHATSAPP_SWAGGER_ENABLED=true`: Toggle to enable or disable the Swagger. +- `WHATSAPP_SWAGGER_USERNAME=admin` +- `WHATSAPP_SWAGGER_PASSWORD=admin` + Swagger panel with `admin / admin` credentials. This does not affect API access. + +## Files + +Read more about [**🖼️ Media Storage**]({{< relref "/docs/how-to/storages#media-storage" >}}) and [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) + +### Files - Local + +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`). 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" >}}) + +💡 When media files are not processed due to `WHATSAPP_FILES_MIMETYPES` or `WHATSAPP_DOWNLOAD_MEDIA` settings, +you'll still receive a webhook event with `hasMedia: True` field, but without a `media.url`. + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "hasMedia": true, + "media": { + "url": null, + "mimetype": "video/mp4", + "filename": null, + "error": null // if there was an error during file download + } + } +} +``` + +### Files - S3 + +- `WAHA_MEDIA_STORAGE=S3` - enable the S3 storage +- `WAHA_S3_REGION=eu-west-1` - the region of the S3 bucket +- `WAHA_S3_BUCKET=waha` - the name of the S3 bucket +- `WAHA_S3_ACCESS_KEY_ID=minioadmin` - the access key of the S3 bucket +- `WAHA_S3_SECRET_ACCESS_KEY=minioadmin` - the secret access key of the S3 bucket +- `WAHA_S3_ENDPOINT=http://127.0.0.1:9000` - the endpoint of the S3 bucket (not required for AWS S3) +- `WAHA_S3_FORCE_PATH_STYLE=True` - force path style for the S3 bucket (not required for AWS S3) +- `WAHA_S3_PROXY_FILES` - proxy media files through WAHA (`False` by default) + - `WAHA_S3_PROXY_FILES=False` - generate pre-signed URLs for media files and send them to the client in `media.url` + - `WAHA_S3_PROXY_FILES=True` - WAHA will proxy media files through itself in `media.url` + +### Files - PostgreSQL + +- `WAHA_MEDIA_STORAGE=POSTGRESQL` - enable the PostgreSQL storage for media files +- `WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable` - PostgreSQL connection URL for storing media files + +## Health Check + +Read more about [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) + +Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/waha-plus" >}}) only. + +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`. diff --git a/content/docs/how-to/contacts/features.md b/content/docs/how-to/contacts/features.md index 2ae960b6c..93b3b856b 100644 --- a/content/docs/how-to/contacts/features.md +++ b/content/docs/how-to/contacts/features.md @@ -1,30 +1,30 @@ -
-{{< details "**👤 Contacts - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|---------------------------------------------------------------------|:-----:|:----------------:|:----:| -| **Get all contacts**
`GET /api/contacts/all` | ✔️ | ✔️[*1](#heading) | ✔️ | -| **Get contact**
`GET /api/contacts` | ✔️ | ✔️[*1](#heading) | ✔️ | -| **Update contact**
`PUT /api/{session}/contacts/{chatId}` | ✔️ | ✔️ | ✔️ | -| **Check phone number exists**
`GET /api/contacts/check-exists` | ✔️ | ✔️ | ✔️ | -| **Get “about” contact**
`GET /api/contacts/about` | ✔️ | | | -| **Get profile picture**
`GET /api/contacts/profile-picture` | ✔️ | ✔️ | ✔️ | -| **Block contact**
`POST /api/contacts/block` | ✔️ | | | -| **Unblock contact**
`POST /api/contacts/unblock` | ✔️ | | | - -1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** - -{{< /details >}} - -{{< details "**👤 Lids - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|-----------------------------------------------------------------------------|:-----:|:----------------:|:----:| -| **Get Known LIDs**
`GET /api/{session}/lids` | ✔️ | ✔️[*1](#heading) | ✔️ | -| **Get Count of LIDs**
`GET /api/{session}/lids/count` | ✔️ | ✔️[*1](#heading) | ✔️ | -| **Get Phone Number by LID**
`GET /api/{session}/lids/{lid}` | ✔️ | ✔️[*1](#heading) | ✔️ | -| **Get LID by Phone Number**
`GET /api/{session}/lids/pn/{phoneNumber}` | ✔️ | ✔️[*1](#heading) | ✔️ | - -1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** - -{{< /details >}} +
+{{< details "**👤 Contacts - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------------------------- | :---: | :---------------: | :--: | +| **Get all contacts**
`GET /api/contacts/all` | ✔️ | ✔️[\*1](#heading) | ✔️ | +| **Get contact**
`GET /api/contacts` | ✔️ | ✔️[\*1](#heading) | ✔️ | +| **Update contact**
`PUT /api/{session}/contacts/{chatId}` | ✔️ | ✔️ | ✔️ | +| **Check phone number exists**
`GET /api/contacts/check-exists` | ✔️ | ✔️ | ✔️ | +| **Get “about” contact**
`GET /api/contacts/about` | ✔️ | | | +| **Get profile picture**
`GET /api/contacts/profile-picture` | ✔️ | ✔️ | ✔️ | +| **Block contact**
`POST /api/contacts/block` | ✔️ | | | +| **Unblock contact**
`POST /api/contacts/unblock` | ✔️ | | | + +1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** + +{{< /details >}} + +{{< details "**👤 Lids - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| --------------------------------------------------------------------------- | :---: | :---------------: | :--: | +| **Get Known LIDs**
`GET /api/{session}/lids` | ✔️ | ✔️[\*1](#heading) | ✔️ | +| **Get Count of LIDs**
`GET /api/{session}/lids/count` | ✔️ | ✔️[\*1](#heading) | ✔️ | +| **Get Phone Number by LID**
`GET /api/{session}/lids/{lid}` | ✔️ | ✔️[\*1](#heading) | ✔️ | +| **Get LID by Phone Number**
`GET /api/{session}/lids/pn/{phoneNumber}` | ✔️ | ✔️[\*1](#heading) | ✔️ | + +1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** + +{{< /details >}} diff --git a/content/docs/how-to/contacts/index.md b/content/docs/how-to/contacts/index.md index e4522d7f1..f6e86e100 100644 --- a/content/docs/how-to/contacts/index.md +++ b/content/docs/how-to/contacts/index.md @@ -1,314 +1,337 @@ ---- -title : "👤 Contacts" -description: "Contacts" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 230 -images: ["contacts.png"] -slug: contacts ---- - -Methods for contacts. - -
-{{< img lqip="21x webp q20" src="contacts.png" alt="WhatsApp Contacts" >}} -
- -## Features -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/contacts/features.md" >}} - -{{< callout context="note" icon="outline/info-circle" >}} -WhatsApp Web does not support adding contacts, so the API doesn't support it too. -{{< /callout >}} - -## API - Contacts -See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). - -### Get all contacts - -Get your contacts - -```http request -GET /api/contacts/all?session={NAME} -``` - -```json {title="Response"} -[ - { - "id": "11231231231@c.us", - "number": "11231231231", - "name": "Contact Name", - "pushname": "Pushname", - "shortName": "Shortname", - "isMe": true, - "isGroup": false, - "isWAContact": true, - "isMyContact": true, - "isBlocked": false - } -] -``` - -#### Contacts Pagination -If you see timeout or the request takes too long - consider using `limit` parameter to get contacts in smaller chunks - -```http request -GET /api/contacts/all?session={NAME}&limit=100&offset=0&sortBy=id&sortOrder=asc -``` - -- `limit=100` - limit the number of chats to return -- `offset=0` - skip the number of chats from the start -- `sortBy={field}` - sort by field - - `sortBy=id` - sort by contact id - - `sortBy=name` - sort by contact name -- `sortOrder=desc|asc` - sort order - - `desc` - descending order (A-Z) - - `asc` - ascending order (Z-A) - -### Get contact - -Get contact -```http request -GET /api/contacts?contactId={ID}&session={SESSION} -``` - -- `ID` - either phone number (`123123123`) or chat id (`123123@c.us`) - -```json {title="Response"} -{ - "id": "11231231231@c.us", - "number": "11231231231", - "name": "Contact Name", - "pushname": "Pushname", - "shortName": "Shortname", - "isMe": true, - "isGroup": false, - "isWAContact": true, - "isMyContact": true, - "isBlocked": false -} -``` - -### Update contact -**Update contact** on **your phone address book** (and in WhatsApp): - -```http request -PUT /api/{session}/contacts/{chatId} -``` - -```json { title="Body" } -{ - "firstName": "John", - "lastName": "Doe" -} -``` - -**Path Parameters**: -- `{session}` - session name - `default` -- `{chatId}` - chat ID can end with "@c.us" or can be just a phone number - `12132132130` - -{{< callout context="note" icon="outline/address-book" title="Phone Address Book Update Note" >}} -- If you have multiple **WhatsApp** apps installed on your phone, the API might only work with one account. -- You may need to make **a few API requests** with the same parameters and wait **a few seconds** between requests to update your **phone address book**. -{{< /callout >}} - -### 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. -```http request -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 { title="Response" } -{ - "numberExists": true, - "chatId": "123123123@c.us" -} -``` -**Note for 🇧🇷 Brazilian Phone Numbers** - -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/waha/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 - -```http request -GET /api/contacts/about?contactId={ID}&session={SESSION} -``` - -- `ID` - either phone number (`123123123`) or chat id (`123123@c.us`) - -```json { title="Response" } -{ - "about": "Hi, I use WhatsApp!" -} -``` - -### Get contact profile picture -```http request -GET /api/contacts/profile-picture?contactId=11231231231&session=default` -``` - -**Query**: -- `contactId` - contact ID -- `session` - session name -- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. - -```json { title="Response" } -{ - "profilePictureURL": "https://example.com/profile.jpg" -} -``` - -### Block (unblock) contact -Block contact -```http request -POST /api/contacts/block -``` - -Unblock contact -```http request -POST /api/contacts/unblock -``` - -```json { title="Body" } -{ - "contactId": "11231231231", - "session": "default" -} -``` - -## API - Lids - -WhatsApp uses so-called **Linked ID** (`lid`) identifier to hide a user phone number (`pn`) from public groups and other places. - -The API below you can use to map a linked identifier (`@lid`) to a contact phone number (`@c.us`). - -### Get All Known LIDs - -```http request -GET /api/{session}/lids -``` - -Query all known LID-to-phone number mappings for a session. - -**Query Parameters:** - -* `limit`: (optional, default: 100) Number of records to return -* `offset`: (optional, default: 0) Pagination offset - -**Response:** - -```json -[ - { - "lid": "123123123@lid", - "pn": "123456789@c.us" - } -] -``` - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Call -[**Get all groups**]({{< relref "/docs/how-to/groups/#get-all-groups" >}}) -or -[**Refresh groups**]({{< relref "/docs/how-to/groups/#refresh-groups" >}}) to populate lid to phone number mapping for all groups. -{{< /callout >}} - -### Get Count of LIDs - -```http request -GET /api/{session}/lids/count -``` - -Returns the number of known LID mappings for a session. - -**Response:** - -```json -{ - "count": 123 -} -``` - -### Get Phone Number by LID - -```http request -GET /api/{session}/lids/{lid} -``` - -Retrieve the associated phone number for a specific LID. - -👉 Remember to escape `@` in `lid` with `%40` (`123123%40lid`) or use just a number (`123123`) - -{{< tabs "lids-get-pn-response" >}} -{{< tab "Response (Found)" >}} -```json -{ - "lid": "123123123@lid", - "pn": "123456789@c.us" -} -``` -{{< /tab >}} -{{< tab "Response (Not Found)" >}} -```json -{ - "lid": "123123123@lid", - "pn": null -} -``` -{{< /tab >}} -{{< /tabs >}} - -### Get LID by Phone Number - -```http request -GET /api/{session}/lids/pn/{phoneNumber} -``` - -Fetch the LID for a given phone number (chat ID). - -👉 Remember to escape `@` in `phoneNumber` with `%40` (`123123%40lid`) or use just a number (`123123`) - -{{< tabs "lids-get-lid-response" >}} -{{< tab "Response (Found)" >}} -```json -{ - "lid": "123123123@lid", - "pn": "123456789@c.us" -} -``` -{{< /tab >}} -{{< tab "Response (Not Found)" >}} -```json -{ - "lid": null, - "pn": "123456789@c.us" -} -``` -{{< /tab >}} -{{< /tabs >}} - -### Lids FAQ -- If you **don't find a phone number by lid** - you don't have the phone number in your contact list or you're not **admin** in the group. -- For [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) - try [**Refresh groups**]({{< relref "/docs/how-to/groups" >}}) if you don't find the `lid` but you're **admin** in the group. - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -👉 If nothing helped, and **you see phone number for participant on your phone app** - please -[**open an issue**](https://github.com/devlikeapro/waha) -and tell what -[**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) -you're using and what behaviour you see. -{{< /callout >}} +--- +title: "👤 Contacts" +description: "Contacts" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 230 +images: ["contacts.png"] +slug: contacts +--- + +Methods for contacts. + +
+{{< img lqip="21x webp q20" src="contacts.png" alt="WhatsApp Contacts" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/contacts/features.md" >}} + +{{< callout context="note" icon="outline/info-circle" >}} +WhatsApp Web does not support adding contacts, so the API doesn't support it too. +{{< /callout >}} + +## API - Contacts + +See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). + +### Get all contacts + +Get your contacts + +```http request +GET /api/contacts/all?session={NAME} +``` + +```json {title="Response"} +[ + { + "id": "11231231231@c.us", + "number": "11231231231", + "name": "Contact Name", + "pushname": "Pushname", + "shortName": "Shortname", + "isMe": true, + "isGroup": false, + "isWAContact": true, + "isMyContact": true, + "isBlocked": false + } +] +``` + +#### Contacts Pagination + +If you see timeout or the request takes too long - consider using `limit` parameter to get contacts in smaller chunks + +```http request +GET /api/contacts/all?session={NAME}&limit=100&offset=0&sortBy=id&sortOrder=asc +``` + +- `limit=100` - limit the number of chats to return +- `offset=0` - skip the number of chats from the start +- `sortBy={field}` - sort by field + - `sortBy=id` - sort by contact id + - `sortBy=name` - sort by contact name +- `sortOrder=desc|asc` - sort order + - `desc` - descending order (A-Z) + - `asc` - ascending order (Z-A) + +### Get contact + +Get contact + +```http request +GET /api/contacts?contactId={ID}&session={SESSION} +``` + +- `ID` - either phone number (`123123123`) or chat id (`123123@c.us`) + +```json {title="Response"} +{ + "id": "11231231231@c.us", + "number": "11231231231", + "name": "Contact Name", + "pushname": "Pushname", + "shortName": "Shortname", + "isMe": true, + "isGroup": false, + "isWAContact": true, + "isMyContact": true, + "isBlocked": false +} +``` + +### Update contact + +**Update contact** on **your phone address book** (and in WhatsApp): + +```http request +PUT /api/{session}/contacts/{chatId} +``` + +```json { title="Body" } +{ + "firstName": "John", + "lastName": "Doe" +} +``` + +**Path Parameters**: + +- `{session}` - session name - `default` +- `{chatId}` - chat ID can end with "@c.us" or can be just a phone number - `12132132130` + +{{< callout context="note" icon="outline/address-book" title="Phone Address Book Update Note" >}} + +- If you have multiple **WhatsApp** apps installed on your phone, the API might only work with one account. +- You may need to make **a few API requests** with the same parameters and wait **a few seconds** between requests to update your **phone address book**. + {{< /callout >}} + +### 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. + +```http request +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 { title="Response" } +{ + "numberExists": true, + "chatId": "123123123@c.us" +} +``` + +**Note for 🇧🇷 Brazilian Phone Numbers** + +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/waha/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 + +```http request +GET /api/contacts/about?contactId={ID}&session={SESSION} +``` + +- `ID` - either phone number (`123123123`) or chat id (`123123@c.us`) + +```json { title="Response" } +{ + "about": "Hi, I use WhatsApp!" +} +``` + +### Get contact profile picture + +```http request +GET /api/contacts/profile-picture?contactId=11231231231&session=default` +``` + +**Query**: + +- `contactId` - contact ID +- `session` - session name +- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. + +```json { title="Response" } +{ + "profilePictureURL": "https://example.com/profile.jpg" +} +``` + +### Block (unblock) contact + +Block contact + +```http request +POST /api/contacts/block +``` + +Unblock contact + +```http request +POST /api/contacts/unblock +``` + +```json { title="Body" } +{ + "contactId": "11231231231", + "session": "default" +} +``` + +## API - Lids + +WhatsApp uses so-called **Linked ID** (`lid`) identifier to hide a user phone number (`pn`) from public groups and other places. + +The API below you can use to map a linked identifier (`@lid`) to a contact phone number (`@c.us`). + +### Get All Known LIDs + +```http request +GET /api/{session}/lids +``` + +Query all known LID-to-phone number mappings for a session. + +**Query Parameters:** + +- `limit`: (optional, default: 100) Number of records to return +- `offset`: (optional, default: 0) Pagination offset + +**Response:** + +```json +[ + { + "lid": "123123123@lid", + "pn": "123456789@c.us" + } +] +``` + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Call +[**Get all groups**]({{< relref "/docs/how-to/groups/#get-all-groups" >}}) +or +[**Refresh groups**]({{< relref "/docs/how-to/groups/#refresh-groups" >}}) to populate lid to phone number mapping for all groups. +{{< /callout >}} + +### Get Count of LIDs + +```http request +GET /api/{session}/lids/count +``` + +Returns the number of known LID mappings for a session. + +**Response:** + +```json +{ + "count": 123 +} +``` + +### Get Phone Number by LID + +```http request +GET /api/{session}/lids/{lid} +``` + +Retrieve the associated phone number for a specific LID. + +👉 Remember to escape `@` in `lid` with `%40` (`123123%40lid`) or use just a number (`123123`) + +{{< tabs "lids-get-pn-response" >}} +{{< tab "Response (Found)" >}} + +```json +{ + "lid": "123123123@lid", + "pn": "123456789@c.us" +} +``` + +{{< /tab >}} +{{< tab "Response (Not Found)" >}} + +```json +{ + "lid": "123123123@lid", + "pn": null +} +``` + +{{< /tab >}} +{{< /tabs >}} + +### Get LID by Phone Number + +```http request +GET /api/{session}/lids/pn/{phoneNumber} +``` + +Fetch the LID for a given phone number (chat ID). + +👉 Remember to escape `@` in `phoneNumber` with `%40` (`123123%40lid`) or use just a number (`123123`) + +{{< tabs "lids-get-lid-response" >}} +{{< tab "Response (Found)" >}} + +```json +{ + "lid": "123123123@lid", + "pn": "123456789@c.us" +} +``` + +{{< /tab >}} +{{< tab "Response (Not Found)" >}} + +```json +{ + "lid": null, + "pn": "123456789@c.us" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +### Lids FAQ + +- If you **don't find a phone number by lid** - you don't have the phone number in your contact list or you're not **admin** in the group. +- For [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) - try [**Refresh groups**]({{< relref "/docs/how-to/groups" >}}) if you don't find the `lid` but you're **admin** in the group. + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +👉 If nothing helped, and **you see phone number for participant on your phone app** - please +[**open an issue**](https://github.com/devlikeapro/waha) +and tell what +[**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) +you're using and what behaviour you see. +{{< /callout >}} diff --git a/content/docs/how-to/dashboard/index.md b/content/docs/how-to/dashboard/index.md index 38a8e9928..8df715814 100644 --- a/content/docs/how-to/dashboard/index.md +++ b/content/docs/how-to/dashboard/index.md @@ -1,89 +1,92 @@ ---- -title: "📊 Dashboard" -description: "Dashboard - UI to manage your WhatsApp sessions!" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 202 -slug: dashboard -images: ['waha-dashboard.png'] -aliases: - - /docs/how-to/waha-dashboard ---- - -**Dashboard** is a UI to manage your WhatsApp sessions! - - - -You can access **Dashboard** by running the project and opening -http://localhost:3000/dashboard -(or similar, but with /dashboard at the end). - -ℹ️ **Default username and password**: `admin/admin` (or `waha/waha`) - -```bash -docker run -it -p 3000:3000 devlikeapro/waha-plus #waha-plus -``` - -## Configuration - -When running WAHA you can set the following environment variables to configure the dashboard: - -- `WAHA_DASHBOARD_ENABLED=true` - enable or disable the dashboard, by default `true`. Set to `false` to disable the - dashboard. -- `WAHA_DASHBOARD_USERNAME=waha` - username used to log in, by default `admin` or `waha` -- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `admin` or `waha` - -```bash -docker run -it -p 3000:3000 -e WAHA_DASHBOARD_USERNAME=waha -e WAHA_DASHBOARD_PASSWORD=waha devlikeapro/waha-plus -``` - -## Api Key -If you're using [API Key]({{< relref "security" >}}), remember to set up the key in the dashboard. - -![Dashboard with API Key](waha-dashboard-key.png) - -## Event Monitor -You can observe [**Events**]({{< relref "events" >}}) in real-time using **Event Monitor**: - -[http://localhost:3000/dashboard/event-monitor](http://localhost:3000/dashboard/event-monitor) - -![Event Monitor](waha-dashboard-event-monitor.png) - -## Chat UI -We've built a simple **Chat UI** in Dashboard, so you can see what is possible to implement using WAHA! - -{{< imgo src="/images/waha/dashboard/waha-dashboard-chat-ui.png" >}} - -You can implement **Live Chat**, **Multiple Agents**, and more features using -[**WAHA API**](https://waha.devlike.pro/): -- [**💬 Chats API**]({{< relref "/docs/how-to/chats" >}}) - to get chats overview and messages. -- [**📤 Send messages API**]({{< relref "/docs/how-to/send-messages" >}}) - to send messages to chats. -- [**🔄 Message ACK**]({{< relref "/docs/how-to/events#messageack" >}}) - to get message status. -- [**🔄 Websockets**]({{< relref "/docs/how-to/events#websockets" >}}) - to get real-time messages on the client side. - -👉 [**Source Code on Github**](https://github.com/devlikeapro/waha-hub/tree/main/ui/components/chat) -(Vue3 + PrimeVue) available for [WAHA PRO](https://waha.devlike.pro/support-us/#tier-pro) supporters! - - - -## Notes -### Single Dashboard - Multiple Servers -If you're running multiple servers -(like [**using sharding to handle 50+ sessions ->**]({{< relref "/blog/waha-scaling" >}})) -you can run a dedicated WAHA just to have a single place where from you can manage all servers: - -{{< imgo src="/images/waha/dashboard/waha-dashboard-servers.drawio.png" >}} - -After that you can connect all server to the single dashboard: - -{{< imgo src="/images/waha/dashboard/waha-single-dashboard-multiple-servers.png" >}} - +--- +title: "📊 Dashboard" +description: "Dashboard - UI to manage your WhatsApp sessions!" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 202 +slug: dashboard +images: ["waha-dashboard.png"] +aliases: + - /docs/how-to/waha-dashboard +--- + +**Dashboard** is a UI to manage your WhatsApp sessions! + + + +You can access **Dashboard** by running the project and opening +http://localhost:3000/dashboard +(or similar, but with /dashboard at the end). + +ℹ️ **Default username and password**: `admin/admin` (or `waha/waha`) + +```bash +docker run -it -p 3000:3000 devlikeapro/waha-plus #waha-plus +``` + +## Configuration + +When running WAHA you can set the following environment variables to configure the dashboard: + +- `WAHA_DASHBOARD_ENABLED=true` - enable or disable the dashboard, by default `true`. Set to `false` to disable the + dashboard. +- `WAHA_DASHBOARD_USERNAME=waha` - username used to log in, by default `admin` or `waha` +- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `admin` or `waha` + +```bash +docker run -it -p 3000:3000 -e WAHA_DASHBOARD_USERNAME=waha -e WAHA_DASHBOARD_PASSWORD=waha devlikeapro/waha-plus +``` + +## Api Key + +If you're using [API Key]({{< relref "security" >}}), remember to set up the key in the dashboard. + +![Dashboard with API Key](waha-dashboard-key.png) + +## Event Monitor + +You can observe [**Events**]({{< relref "events" >}}) in real-time using **Event Monitor**: + +[http://localhost:3000/dashboard/event-monitor](http://localhost:3000/dashboard/event-monitor) + +![Event Monitor](waha-dashboard-event-monitor.png) + +## Chat UI + +We've built a simple **Chat UI** in Dashboard, so you can see what is possible to implement using WAHA! + +{{< imgo src="/images/waha/dashboard/waha-dashboard-chat-ui.png" >}} + +You can implement **Live Chat**, **Multiple Agents**, and more features using +[**WAHA API**](https://waha.devlike.pro/): + +- [**💬 Chats API**]({{< relref "/docs/how-to/chats" >}}) + to get chats overview and messages. +- [**📤 Send messages API**]({{< relref "/docs/how-to/send-messages" >}}) + to send messages to chats. +- [**🔄 Message ACK**]({{< relref "/docs/how-to/events#messageack" >}}) + to get message status. +- [**🔄 Websockets**]({{< relref "/docs/how-to/events#websockets" >}}) + to get real-time messages on the client side. + +👉 [**Source Code on Github**](https://github.com/devlikeapro/waha-hub/tree/main/ui/components/chat) +(Vue3 + PrimeVue) available for [WAHA PRO](https://waha.devlike.pro/support-us/#tier-pro) supporters! + +## Notes + +### Single Dashboard - Multiple Servers + +If you're running multiple servers +(like [**using sharding to handle 50+ sessions ->**]({{< relref "/blog/waha-scaling" >}})) +you can run a dedicated WAHA just to have a single place where from you can manage all servers: + +{{< imgo src="/images/waha/dashboard/waha-dashboard-servers.drawio.png" >}} + +After that you can connect all server to the single dashboard: + +{{< imgo src="/images/waha/dashboard/waha-single-dashboard-multiple-servers.png" >}} diff --git a/content/docs/how-to/engines/index.md b/content/docs/how-to/engines/index.md index 7e77ff6f9..c21961c50 100644 --- a/content/docs/how-to/engines/index.md +++ b/content/docs/how-to/engines/index.md @@ -1,243 +1,258 @@ ---- -title: "🏭 Engines" -description: "Under the hood WAHA allows you to use different engines." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 295 -images: [] -slug: engines ---- - -## 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 -docker run -it -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha -``` - -If you have any problems with one engine - try another! - -{{< callout context="note" icon="outline/info-circle" >}} -API responses and webhook payloads may differ significantly, test everything before changing the engine -{{< /callout >}} - -All engines are available in both -Core and -[Plus versions]({{< relref "/docs/how-to/waha-plus" >}}). - -| | WEBJS | NOWEB | GOWS | -|------------------------------------------------------------------|:-----:|:-----:|:-----| -| Run a **browser** (chromium\chrome) to communicate with WhatsApp | ✔️ | | | -| Communicate with WhatsApp via **websocket (no browser)** | | ✔️ | ✔️ | - -### WEBJS - -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. - -```bash -WHATSAPP_DEFAULT_ENGINE=WEBJS -``` - -{{< link-card title="👉 Read more about WEBJS" href="/docs/engines/webjs/" >}} - -### GOWS - -**GOWS** engine **does not require a browser** to work with WhatsApp Web, it does so directly using a WebSocket. - -🚀 It's a new generation engine written in **Golang**, a future replacement for **NOWEB** engine. - -```bash -WHATSAPP_DEFAULT_ENGINE=GOWS -``` - -{{< link-card title="👉 Read more about GOWS" href="/docs/engines/gows/" >}} - -### NOWEB - -**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! - -```bash -WHATSAPP_DEFAULT_ENGINE=NOWEB -``` - -{{< link-card title="👉 Read more about NOWEB" href="/docs/engines/noweb/" >}} - - -## Docker images -WAHA provides few docker images with different setup. - -👉 Go to -[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) -to generate the command with the latest version and your key. - -| Image | CPU | Browser | -|----------------------------------------------------------|-----|-------------------------| -| [**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) | | | -| `devlikeapro/waha-plus:latest` | x86 | Chromium | -| `devlikeapro/waha-plus:chrome` | x86 | Chrome (supports video) | -| `devlikeapro/waha-plus:noweb` | x86 | None | -| `devlikeapro/waha-plus:gows` | x86 | None | -| `devlikeapro/waha-plus:arm` | ARM | Chromium | -| `-` | ARM | Chrome | -| `devlikeapro/waha-plus:noweb-arm` | ARM | None | -| **WAHA Core** | | | -| `devlikeapro/waha:latest` | x86 | Chromium | -| `devlikeapro/waha:chrome` | x86 | Chrome | -| `devlikeapro/waha:noweb` | x86 | None | -| `-` | ARM | Chrome | -| `devlikeapro/waha:arm` | ARM | Chromium | -| `devlikeapro/waha:noweb-arm` | ARM | None | - - -```bash -devlikeapro/{image}:{browser}[-cpu][-version] -``` - -`{image}`: -- `waha-plus` - [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) image -- `waha` - **WAHA Core** image - -`{browser}`: -- **Chromium** (`latest`) - is the default browser for **WAHA**. It's a good choice for most cases. -- **Chrome** (`chrome`) - is a good choice if you need to receive videos in Plus version. -- **None** (`noweb`) - is a good choice if you want to use **NOWEB** engine. - -`{cpu}`: -- **x86** - is a good choice for most cases. -- **ARM** (`-arm`) - is a good choice if you're using ARM processors (like **Apple Silicon M1\M2**, **Raspberry Pi**, etc.) - -`{version}`: -- **latest** - is the latest version of WAHA. -- **pinned** - you can pin WAHA version by adding `-{version}` at the end of image tag. - -## 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. | -| [#123](https://github.com/devlikeapro/waha/issues) | Feature request or bug for the endpoint | -| | The feature available in [WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}). | - -If you don't specify `WHATSAPP_DEFAULT_ENGINE` environment variable - look at **WEBJS** engine, -it's the engine WAHA runs by default. - - -### 🖥️ Sessions -Read more about -[**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) - -{{< include file="content/docs/how-to/sessions/features.md" >}} - -{{< include file="content/docs/how-to/sessions/features-events.md" >}} - -### 📤 Messages -Read more about -[**📤 Send Messages**]({{< relref "/docs/how-to/send-messages" >}}) -and -[**📥 Receive Messages**]({{< relref "/docs/how-to/receive-messages" >}}) - -{{< include file="content/docs/how-to/send-messages/features.md" >}} - -{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} - -### 🟢 Status -Read more about -[**🟢 Status**]({{< relref "/docs/how-to/status" >}}) - -{{< include file="content/docs/how-to/status/features.md" >}} - -### 💬 Chats -Read more about -[**💬 Chats**]({{< relref "/docs/how-to/chats" >}}) - -{{< include file="content/docs/how-to/chats/features.md" >}} - -{{< include file="content/docs/how-to/chats/features-events.md" >}} - -### 👤 Contacts -Read more about -[**👤 Contacts**]({{< relref "/docs/how-to/contacts" >}}) - -{{< include file="content/docs/how-to/contacts/features.md" >}} - -### 📢 Channels -Read more about -[**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) - -{{< include file="content/docs/how-to/channels/features.md" >}} - -### 👥 Groups -Read more about -[**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) - -{{< include file="content/docs/how-to/groups/features.md" >}} - -{{< include file="content/docs/how-to/groups/features-events.md" >}} - -### ✅ Presence -Read more about -[**✅ Presence**]({{< relref "/docs/how-to/presence" >}}) - -{{< include file="content/docs/how-to/presence/features.md" >}} - -{{< include file="content/docs/how-to/presence/features-events.md" >}} - -### 🏷️ Labels -Read more about -[**🏷️ Labels**]({{< relref "/docs/how-to/labels" >}}) - -{{< include file="content/docs/how-to/labels/features.md" >}} - -{{< include file="content/docs/how-to/labels/features-events.md" >}} - -### 📅 Event Message -Read more about -[**📅 Event Message**]({{< relref "/docs/how-to/event-message" >}}) - -{{< include file="content/docs/how-to/event-message/features.md" >}} - -{{< include file="content/docs/how-to/event-message/features-events.md" >}} - -### 📶 Polls -Read more about -[**📶 Polls**]({{< relref "/docs/how-to/polls" >}}) - -{{< include file="content/docs/how-to/polls/features.md" >}} - -{{< include file="content/docs/how-to/polls/features-events.md" >}} - -### 📞 Calls -Read more about -[**📞 Calls**]({{< relref "/docs/how-to/calls" >}}) - -{{< include file="content/docs/how-to/calls/features-events.md" >}} - -### 🗄️ Storages -Read more about -[**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) - -
-{{< details "**🗄️ Storages**" >}} -{{< include file="content/docs/how-to/storages/features.md" >}} -{{< /details >}} - -### 🔍 Observability - -Read more about -[**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - -### 🔄 Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -{{< include file="content/docs/how-to/events/features-events.md" >}} - +--- +title: "🏭 Engines" +description: "Under the hood WAHA allows you to use different engines." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 295 +images: [] +slug: engines +--- + +## 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 +docker run -it -e "WHATSAPP_DEFAULT_ENGINE=WEBJS" devlikeapro/waha +``` + +If you have any problems with one engine - try another! + +{{< callout context="note" icon="outline/info-circle" >}} +API responses and webhook payloads may differ significantly, test everything before changing the engine +{{< /callout >}} + +All engines are available in both +Core and +[Plus versions]({{< relref "/docs/how-to/waha-plus" >}}). + +| | WEBJS | NOWEB | GOWS | +| ---------------------------------------------------------------- | :---: | :---: | :--- | +| Run a **browser** (chromium\chrome) to communicate with WhatsApp | ✔️ | | | +| Communicate with WhatsApp via **websocket (no browser)** | | ✔️ | ✔️ | + +### WEBJS + +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. + +```bash +WHATSAPP_DEFAULT_ENGINE=WEBJS +``` + +{{< link-card title="👉 Read more about WEBJS" href="/docs/engines/webjs/" >}} + +### GOWS + +**GOWS** engine **does not require a browser** to work with WhatsApp Web, it does so directly using a WebSocket. + +🚀 It's a new generation engine written in **Golang**, a future replacement for **NOWEB** engine. + +```bash +WHATSAPP_DEFAULT_ENGINE=GOWS +``` + +{{< link-card title="👉 Read more about GOWS" href="/docs/engines/gows/" >}} + +### NOWEB + +**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! + +```bash +WHATSAPP_DEFAULT_ENGINE=NOWEB +``` + +{{< link-card title="👉 Read more about NOWEB" href="/docs/engines/noweb/" >}} + +## Docker images + +WAHA provides few docker images with different setup. + +👉 Go to +[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) +to generate the command with the latest version and your key. + +| Image | CPU | Browser | +| -------------------------------------------------------- | --- | ----------------------- | +| [**WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) | | | +| `devlikeapro/waha-plus:latest` | x86 | Chromium | +| `devlikeapro/waha-plus:chrome` | x86 | Chrome (supports video) | +| `devlikeapro/waha-plus:noweb` | x86 | None | +| `devlikeapro/waha-plus:gows` | x86 | None | +| `devlikeapro/waha-plus:arm` | ARM | Chromium | +| `-` | ARM | Chrome | +| `devlikeapro/waha-plus:noweb-arm` | ARM | None | +| **WAHA Core** | | | +| `devlikeapro/waha:latest` | x86 | Chromium | +| `devlikeapro/waha:chrome` | x86 | Chrome | +| `devlikeapro/waha:noweb` | x86 | None | +| `-` | ARM | Chrome | +| `devlikeapro/waha:arm` | ARM | Chromium | +| `devlikeapro/waha:noweb-arm` | ARM | None | + +```bash +devlikeapro/{image}:{browser}[-cpu][-version] +``` + +`{image}`: + +- `waha-plus` - [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) image +- `waha` - **WAHA Core** image + +`{browser}`: + +- **Chromium** (`latest`) - is the default browser for **WAHA**. It's a good choice for most cases. +- **Chrome** (`chrome`) - is a good choice if you need to receive videos in Plus version. +- **None** (`noweb`) - is a good choice if you want to use **NOWEB** engine. + +`{cpu}`: + +- **x86** - is a good choice for most cases. +- **ARM** (`-arm`) - is a good choice if you're using ARM processors (like **Apple Silicon M1\M2**, **Raspberry Pi**, etc.) + +`{version}`: + +- **latest** - is the latest version of WAHA. +- **pinned** - you can pin WAHA version by adding `-{version}` at the end of image tag. + +## 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. | +| [#123](https://github.com/devlikeapro/waha/issues) | Feature request or bug for the endpoint | +| | The feature available in [WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}). | + +If you don't specify `WHATSAPP_DEFAULT_ENGINE` environment variable - look at **WEBJS** engine, +it's the engine WAHA runs by default. + +### 🖥️ Sessions + +Read more about +[**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) + +{{< include file="content/docs/how-to/sessions/features.md" >}} + +{{< include file="content/docs/how-to/sessions/features-events.md" >}} + +### 📤 Messages + +Read more about +[**📤 Send Messages**]({{< relref "/docs/how-to/send-messages" >}}) +and +[**📥 Receive Messages**]({{< relref "/docs/how-to/receive-messages" >}}) + +{{< include file="content/docs/how-to/send-messages/features.md" >}} + +{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} + +### 🟢 Status + +Read more about +[**🟢 Status**]({{< relref "/docs/how-to/status" >}}) + +{{< include file="content/docs/how-to/status/features.md" >}} + +### 💬 Chats + +Read more about +[**💬 Chats**]({{< relref "/docs/how-to/chats" >}}) + +{{< include file="content/docs/how-to/chats/features.md" >}} + +{{< include file="content/docs/how-to/chats/features-events.md" >}} + +### 👤 Contacts + +Read more about +[**👤 Contacts**]({{< relref "/docs/how-to/contacts" >}}) + +{{< include file="content/docs/how-to/contacts/features.md" >}} + +### 📢 Channels + +Read more about +[**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) + +{{< include file="content/docs/how-to/channels/features.md" >}} + +### 👥 Groups + +Read more about +[**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) + +{{< include file="content/docs/how-to/groups/features.md" >}} + +{{< include file="content/docs/how-to/groups/features-events.md" >}} + +### ✅ Presence + +Read more about +[**✅ Presence**]({{< relref "/docs/how-to/presence" >}}) + +{{< include file="content/docs/how-to/presence/features.md" >}} + +{{< include file="content/docs/how-to/presence/features-events.md" >}} + +### 🏷️ Labels + +Read more about +[**🏷️ Labels**]({{< relref "/docs/how-to/labels" >}}) + +{{< include file="content/docs/how-to/labels/features.md" >}} + +{{< include file="content/docs/how-to/labels/features-events.md" >}} + +### 📅 Event Message + +Read more about +[**📅 Event Message**]({{< relref "/docs/how-to/event-message" >}}) + +{{< include file="content/docs/how-to/event-message/features.md" >}} + +{{< include file="content/docs/how-to/event-message/features-events.md" >}} + +### 📶 Polls + +Read more about +[**📶 Polls**]({{< relref "/docs/how-to/polls" >}}) + +{{< include file="content/docs/how-to/polls/features.md" >}} + +{{< include file="content/docs/how-to/polls/features-events.md" >}} + +### 📞 Calls + +Read more about +[**📞 Calls**]({{< relref "/docs/how-to/calls" >}}) + +{{< include file="content/docs/how-to/calls/features-events.md" >}} + +### 🗄️ Storages + +Read more about +[**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) + +
+{{< details "**🗄️ Storages**" >}} +{{< include file="content/docs/how-to/storages/features.md" >}} +{{< /details >}} + +### 🔍 Observability + +Read more about +[**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) + +### 🔄 Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +{{< include file="content/docs/how-to/events/features-events.md" >}} diff --git a/content/docs/how-to/event-message/events-event-response-failed.md b/content/docs/how-to/event-message/events-event-response-failed.md index d1dc6344d..c7116c51b 100644 --- a/content/docs/how-to/event-message/events-event-response-failed.md +++ b/content/docs/how-to/event-message/events-event-response-failed.md @@ -1,35 +1,35 @@ -Sometimes it happens that we didn't manager to decrypt the response for the event. -In that case you'll get `event.response.failed` event with `eventResponse: null`. - -**Resend the Event Message** one more time if you get this event to get a new response - -```json { title="event.response.failed" } -{ - "id": "evt_00000000000000000000001", - "session": "default", - "event": "event.response.failed", - "payload": { - "id": "false_11111111111111111@c.us_58BBBBBBBBBBBBBBBBBBBBBBBB", - "timestamp": 1747707858, - "from": "11111111111111111@c.us", - "participant": null, - "fromMe": false, - "eventCreationKey": { - "id": "false_999999999999@c.us_3EBAAAAAAAAAAAAAAAAAAAAAAAAAA", - "to": "me", - "from": "999999999999@c.us", - "fromMe": false - }, - "eventResponse": null, // <=== eventResponse will be null in that case - "source": "app", - "ack": null, - "ackName": "UNKNOWN", - "replyTo": null, - "_data": {...}, - } -} -``` - - -**Payload**: -- the same as for `event.response` payload, but with `eventResponse: null` \ No newline at end of file +Sometimes it happens that we didn't manager to decrypt the response for the event. +In that case you'll get `event.response.failed` event with `eventResponse: null`. + +**Resend the Event Message** one more time if you get this event to get a new response + +```json { title="event.response.failed" } +{ + "id": "evt_00000000000000000000001", + "session": "default", + "event": "event.response.failed", + "payload": { + "id": "false_11111111111111111@c.us_58BBBBBBBBBBBBBBBBBBBBBBBB", + "timestamp": 1747707858, + "from": "11111111111111111@c.us", + "participant": null, + "fromMe": false, + "eventCreationKey": { + "id": "false_999999999999@c.us_3EBAAAAAAAAAAAAAAAAAAAAAAAAAA", + "to": "me", + "from": "999999999999@c.us", + "fromMe": false + }, + "eventResponse": null, // <=== eventResponse will be null in that case + "source": "app", + "ack": null, + "ackName": "UNKNOWN", + "replyTo": null, + "_data": {...}, + } +} +``` + +**Payload**: + +- the same as for `event.response` payload, but with `eventResponse: null` diff --git a/content/docs/how-to/event-message/events-event-response.md b/content/docs/how-to/event-message/events-event-response.md index 115bf98e5..577e6ef69 100644 --- a/content/docs/how-to/event-message/events-event-response.md +++ b/content/docs/how-to/event-message/events-event-response.md @@ -1,49 +1,50 @@ -```json { title="event.response" } -{ - "id": "evt_00000000000000000000001", - "session": "default", - "event": "event.response", - "payload": { - "id": "false_11111111111111111@c.us_58BBBBBBBBBBBBBBBBBBBBBBBB", - "timestamp": 1747707858, - "from": "11111111111111111@c.us", - "participant": null, - "fromMe": false, - "eventCreationKey": { - "id": "false_999999999999@c.us_3EBAAAAAAAAAAAAAAAAAAAAAAAAAA", - "to": "me", - "from": "999999999999@c.us", - "fromMe": false - }, - "eventResponse": { - "response": "GOING", - "timestampMs": 1747707858429, - "extraGuestCount": 0 - }, - "source": "app", - "ack": null, - "ackName": "UNKNOWN", - "replyTo": null, - "_data": {...}, - } -} -``` - -**Payload**: -- **Most of the fields** are the same as for `message` and `message.any` events -- `eventCreationKey`: Information about the original event message - - `id`: Unique identifier of the original event message - - Format `{fromMe}_{chatId}_{messageId}[_{participant}]`) - - You need to parse it to get `messageId` and find event that you sent previously, `fromMe` and `chatId` is **from participant**, not yours. - - `to`: Recipient of the original event message (usually "me") - - `from`: WhatsApp ID of the sender of the original event message - - `fromMe`: Boolean indicating if the original event was sent by you -- `eventResponse`: Details of the user's response to the event - - `response`: The selected response option: `GOING`, `NOT_GOING`, `MAYBE` - - `timestampMs`: Unix timestamp in milliseconds when the response was made - - `extraGuestCount`: Number of additional guests the respondent is bringing (`0\1`) -- `source`: Source of the message (usually "app") -- `ack`: Acknowledgment status code -- `ackName`: Human-readable acknowledgment status -- `replyTo`: Reference to a message being replied to (null if not a reply) -- `_data`: Raw data object containing additional information +```json { title="event.response" } +{ + "id": "evt_00000000000000000000001", + "session": "default", + "event": "event.response", + "payload": { + "id": "false_11111111111111111@c.us_58BBBBBBBBBBBBBBBBBBBBBBBB", + "timestamp": 1747707858, + "from": "11111111111111111@c.us", + "participant": null, + "fromMe": false, + "eventCreationKey": { + "id": "false_999999999999@c.us_3EBAAAAAAAAAAAAAAAAAAAAAAAAAA", + "to": "me", + "from": "999999999999@c.us", + "fromMe": false + }, + "eventResponse": { + "response": "GOING", + "timestampMs": 1747707858429, + "extraGuestCount": 0 + }, + "source": "app", + "ack": null, + "ackName": "UNKNOWN", + "replyTo": null, + "_data": {...}, + } +} +``` + +**Payload**: + +- **Most of the fields** are the same as for `message` and `message.any` events +- `eventCreationKey`: Information about the original event message + - `id`: Unique identifier of the original event message + - Format `{fromMe}_{chatId}_{messageId}[_{participant}]`) + - You need to parse it to get `messageId` and find event that you sent previously, `fromMe` and `chatId` is **from participant**, not yours. + - `to`: Recipient of the original event message (usually "me") + - `from`: WhatsApp ID of the sender of the original event message + - `fromMe`: Boolean indicating if the original event was sent by you +- `eventResponse`: Details of the user's response to the event + - `response`: The selected response option: `GOING`, `NOT_GOING`, `MAYBE` + - `timestampMs`: Unix timestamp in milliseconds when the response was made + - `extraGuestCount`: Number of additional guests the respondent is bringing (`0\1`) +- `source`: Source of the message (usually "app") +- `ack`: Acknowledgment status code +- `ackName`: Human-readable acknowledgment status +- `replyTo`: Reference to a message being replied to (null if not a reply) +- `_data`: Raw data object containing additional information diff --git a/content/docs/how-to/event-message/features-events.md b/content/docs/how-to/event-message/features-events.md index 9a4850917..e9d339004 100644 --- a/content/docs/how-to/event-message/features-events.md +++ b/content/docs/how-to/event-message/features-events.md @@ -1,9 +1,9 @@ -
-{{< details "**📅 Event Message - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|-------------------------|:-----:|:-----:|:----:| -| `event.response` | | | ✔️ | -| `event.response.failed` | | | ✔️ | - -{{< /details >}} +
+{{< details "**📅 Event Message - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ----------------------- | :---: | :---: | :--: | +| `event.response` | | | ✔️ | +| `event.response.failed` | | | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/event-message/features.md b/content/docs/how-to/event-message/features.md index 0d09fd17a..4f58d2df6 100644 --- a/content/docs/how-to/event-message/features.md +++ b/content/docs/how-to/event-message/features.md @@ -1,8 +1,8 @@ -
-{{< details "**📅 Event Message - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|----------------------------------------------------------|:-----:|:-----:|:----:| -| **Send Event Message**
`POST /api/{SESSION}/events` | | | ✔️ | - -{{< /details >}} +
+{{< details "**📅 Event Message - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| -------------------------------------------------------- | :---: | :---: | :--: | +| **Send Event Message**
`POST /api/{SESSION}/events` | | | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/event-message/index.md b/content/docs/how-to/event-message/index.md index 0cf461c40..a76e322c7 100644 --- a/content/docs/how-to/event-message/index.md +++ b/content/docs/how-to/event-message/index.md @@ -1,79 +1,82 @@ ---- -title: "📅 Event Message" -description: "Event Message" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 293 -slug: event-message -images: [ "whatsapp-event-message.jpg"] ---- -You can **send Event Message** and **receive responses** in WhatsApp using API . - -Remind clients about their appointments natively: -
-{{< img lqip="21x webp q20" src="whatsapp-event-message.jpg" alt="WhatsApp Event Message" >}} -
- - -## Features -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/event-message/features.md" >}} -{{< include file="content/docs/how-to/event-message/features-events.md" >}} - -## API - -### Send Event Message -```http request -POST /api/{SESSION}/events -``` - -```json { title="Body" } -{ - "chatId": "123123@c.us", - "reply_to": null, - "event": { - "name": "John's Nail Appointment 💅", - "description": "It's time for your nail care session! 🌟\\n\\nYou'll be getting a *classic gel manicure* – clean, polished, and long-lasting. 💖\\n\\n📍 *Location:* Luxe Nail Studio\\nWe're on the *2nd floor of the Plaza Mall*, next to the flower shop. Look for the *pink neon sign*!\\n\\nFeel free to arrive *5–10 mins early* so we can get started on time 😊", - "startTime": 2063137000, - "endTime": null, - "location": { - "name": "Luxe Nail Studio 💅" - }, - "extraGuestsAllowed": false - } -} -``` - -Fields: -- `chatId` - The WhatsApp ID of the chat where you want to send the event message (e.g., "123123@c.us") -- `event` - Object containing event details: - - `name` - The title of the event - - `description` - Detailed description of the event (supports formatting with \n for newlines and * for bold text) - - `startTime` - Event start time in Unix timestamp format (**seconds** since epoch) - - `endTime` - Event end time in Unix timestamp format (optional, can be null) - - `location` - (Optional) Object containing location details - - `name` - Name of the location - - `extraGuestsAllowed` - indicating whether additional guests are allowed (true/false) -- `reply_to` - Message ID to reply to (optional, can be null) - - -## Events -Receive responses for your event using events! - -{{< include file="content/docs/how-to/event-message/features-events.md" >}} - -
-{{< img lqip="21x webp q20" src="whatsapp-event-response.jpg" alt="WhatsApp Event Message" >}} -
- - -### event.response - -{{< include file="content/docs/how-to/event-message/events-event-response.md" >}} - -### event.response.failed - -{{< include file="content/docs/how-to/event-message/events-event-response-failed.md" >}} +--- +title: "📅 Event Message" +description: "Event Message" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 293 +slug: event-message +images: ["whatsapp-event-message.jpg"] +--- + +You can **send Event Message** and **receive responses** in WhatsApp using API . + +Remind clients about their appointments natively: + +
+{{< img lqip="21x webp q20" src="whatsapp-event-message.jpg" alt="WhatsApp Event Message" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/event-message/features.md" >}} +{{< include file="content/docs/how-to/event-message/features-events.md" >}} + +## API + +### Send Event Message + +```http request +POST /api/{SESSION}/events +``` + +```json { title="Body" } +{ + "chatId": "123123@c.us", + "reply_to": null, + "event": { + "name": "John's Nail Appointment 💅", + "description": "It's time for your nail care session! 🌟\\n\\nYou'll be getting a *classic gel manicure* – clean, polished, and long-lasting. 💖\\n\\n📍 *Location:* Luxe Nail Studio\\nWe're on the *2nd floor of the Plaza Mall*, next to the flower shop. Look for the *pink neon sign*!\\n\\nFeel free to arrive *5–10 mins early* so we can get started on time 😊", + "startTime": 2063137000, + "endTime": null, + "location": { + "name": "Luxe Nail Studio 💅" + }, + "extraGuestsAllowed": false + } +} +``` + +Fields: + +- `chatId` - The WhatsApp ID of the chat where you want to send the event message (e.g., "123123@c.us") +- `event` - Object containing event details: + - `name` - The title of the event + - `description` - Detailed description of the event (supports formatting with \n for newlines and \* for bold text) + - `startTime` - Event start time in Unix timestamp format (**seconds** since epoch) + - `endTime` - Event end time in Unix timestamp format (optional, can be null) + - `location` - (Optional) Object containing location details + - `name` - Name of the location + - `extraGuestsAllowed` - indicating whether additional guests are allowed (true/false) +- `reply_to` - Message ID to reply to (optional, can be null) + +## Events + +Receive responses for your event using events! + +{{< include file="content/docs/how-to/event-message/features-events.md" >}} + +
+{{< img lqip="21x webp q20" src="whatsapp-event-response.jpg" alt="WhatsApp Event Message" >}} +
+ +### event.response + +{{< include file="content/docs/how-to/event-message/events-event-response.md" >}} + +### event.response.failed + +{{< include file="content/docs/how-to/event-message/events-event-response-failed.md" >}} diff --git a/content/docs/how-to/events/features-events.md b/content/docs/how-to/events/features-events.md index 17ea11f59..8c90ce7c3 100644 --- a/content/docs/how-to/events/features-events.md +++ b/content/docs/how-to/events/features-events.md @@ -1,16 +1,16 @@ -
-{{< include file="content/docs/how-to/sessions/features-events.md" >}} - -{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} - -{{< include file="content/docs/how-to/chats/features-events.md" >}} - -{{< include file="content/docs/how-to/groups/features-events.md" >}} - -{{< include file="content/docs/how-to/labels/features-events.md" >}} - -{{< include file="content/docs/how-to/presence/features-events.md" >}} - -{{< include file="content/docs/how-to/polls/features-events.md" >}} - -{{< include file="content/docs/how-to/calls/features-events.md" >}} +
+{{< include file="content/docs/how-to/sessions/features-events.md" >}} + +{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} + +{{< include file="content/docs/how-to/chats/features-events.md" >}} + +{{< include file="content/docs/how-to/groups/features-events.md" >}} + +{{< include file="content/docs/how-to/labels/features-events.md" >}} + +{{< include file="content/docs/how-to/presence/features-events.md" >}} + +{{< include file="content/docs/how-to/polls/features-events.md" >}} + +{{< include file="content/docs/how-to/calls/features-events.md" >}} diff --git a/content/docs/how-to/events/index.md b/content/docs/how-to/events/index.md index 8be68cdff..b654b31c2 100644 --- a/content/docs/how-to/events/index.md +++ b/content/docs/how-to/events/index.md @@ -1,807 +1,836 @@ ---- -title : "🔄 Events" -description: "Events - how to set up and handle them using Webhooks and Websockets" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 223 -slug: events -images: [ "webhooks.png" ] -aliases: - - /docs/how-to/events - - /docs/how-to/webhooks - - /docs/how-to/websockets ---- - -In order to notify your application about events in the WhatsApp API, you can use -[**Webhooks**](#webhooks) and [**Websockets**](#websockets). - -👉 See the list of all available events in the [**Events**](#events) section. - -🌟 You can observe **Events** in real-time using -[**📊 Dashboard - Event Monitor**]({{< relref "dashboard#event-monitor" >}})! - -## Webhooks - -
-{{< img lqip="21x webp q20" src="webhooks.png" alt="Webhooks" >}} -
- -**Webhooks** are a way for two different applications to communicate with each other in real-time. -When a certain event happens in one application, it sends a message to another application through a webhook URL. -The receiving application can then take action based on the information received. - -### Session webhooks -You can define webhooks configuration per session when you start it with `POST /api/sessions/` request data. - -Here's a simple example: -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} - -``` - -Here's available configuration options for webhooks -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - "hmac": { - "key": "your-secret-key" - }, - "retries": { - "policy": "constant", - "delaySeconds": 2, - "attempts": 15 - }, - "customHeaders": [ - { - "name": "X-My-Custom-Header", - "value": "Value" - } - ] - } - ] - } -} -``` - -### Global webhooks -There's a way how you can configure -[**🔄 Webhooks**]({{< relref "/docs/how-to/events#webhooks" >}}) -for **all sessions** at once - by settings these environment variables: - -- `WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111` - to set up a URL for the webhook -- `WHATSAPP_HOOK_EVENTS=message,message.any,state.change` - specify events. - - `WHATSAPP_HOOK_EVENTS=*` - subscribe to all events. - - We don't suggest using `*` or all events for production, it can generate a lot of requests. -- `WHATSAPP_HOOK_HMAC_KEY=your-secret-key` - the same as `hmac.key` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_POLICY=linear` - the same as `retries.policy` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_DELAY_SECONDS=2` - the same as `retries.delaySeconds` field in the webhook configuration. -- `WHATSAPP_HOOK_RETRIES_ATTEMPTS=4` -- `WHATSAPP_HOOK_CUSTOM_HEADERS=X-My-Custom-Header-1:Value;X-My-Custom-Header-2:Value` - the same as `customHeaders` field in the webhook configuration. - - Use `Header:Value` format and separate them by `;`. - -That webhook configuration **does not appear** in `session.config` field in `GET /api/sessions/` request. - - -💡 You can open [https://webhook.site](https://webhook.site) and paste URL from it to `url` field, -and you'll see all requests immediately in your browser to intercept the webhook's payload. - -### Retries -You can configure retry policy for webhooks by settings `config.retries` structure when `POST /api/sessions/`: - -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - "retries": { - "policy": "constant", - "delaySeconds": 2, - "attempts": 15 - } - } - ] - } -} - -``` - -Possible `policy`: -- `constant` - retry with the same delay between attempts (2, 2, 2, 2) -- `linear` - retry with linear backoff (2, 4, 6, 8) -- `exponential` - retry with exponential backoff with 20% jitter (2, 4.1, 8.4, 16.3). - -### Headers -When you receive a webhook request to your API endpoint, you'll get **those headers**: -- `X-Webhook-Request-Id` - unique request id for each webhook request. -- `X-Webhook-Timestamp` - Unix timestamp in milliseconds when the webhook was sent. - -If you're using [**HMAC authentication**](#hmac-authentication) you'll get two additional headers: -- `X-Webhook-Hmac` - message authentication code for the raw **body** in HTTP POST request that send to your endpoint. -- `X-Webhook-Hmac-Algorithm` - `sha512` - algorithm that have been used to create `X-Webhook-Hmac` value. - -You can send any **customer headers** by defining `config.webhooks.customHeaders` fields this way: -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - "customHeaders": [ - { - "name": "X-My-Custom-Header", - "value": "Value" - } - ] - } - ] - } -} -``` - - -### HMAC authentication - -You can authenticate webhook sender by using [HMAC Authentication](https://www.okta.com/identity-101/hmac/). - -1. Define you secret key in `config.hmac.key` field when you start session with `POST /api/sessions/`: - -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - "hmac": { - "key": "your-secret-key" - } - } - ] - } -} -``` - -2. After that you'll receive all webhooks payload with two additional headers: -- `X-Webhook-Hmac` - message authentication code for the raw **body** in HTTP POST request that send to your endpoint. -- `X-Webhook-Hmac-Algorithm` - `sha512` - algorithm that have been used to create `X-Webhook-Hmac` value. - -3. Implement the authentication algorithm by hashing body and using secret key and then verifying it with `X-Webhook-Hmac` -value. Please [check your implementation here ->](https://www.devglan.com/online-tools/hmac-sha256-online) - -Here's example for -``` -# Full body -{"event":"message","session":"default","engine":"WEBJS"} -# Secret key -my-secret-key -# X-Webhook-Hmac-Algorithm -sha512 -# X-Webhook-Hmac -208f8a55dde9e05519e898b10b89bf0d0b3b0fdf11fdbf09b6b90476301b98d8097c462b2b17a6ce93b6b47a136cf2e78a33a63f6752c2c1631777076153fa89 -``` - -### Examples -Here's few examples of how to handle webhook in different languages: -1. [Python guide]({{< relref "/docs/integrations/waha+python" >}}) - -**Do you use another language?** - -Please create a short guide how to handle webhook and send message after you finish your setup! -You can create a pull request with your favorite language in the -[GitHub, in examples folder ->](https://github.com/devlikeapro/waha/tree/core/examples). - -## Websockets -You can use Websockets to receive messages in real-time! - -Install [websocat](https://github.com/vi/websocat?tab=readme-ov-file#installation) first. - -```bash -# Listen all sessions and events -# -E to end the connection when the server closes it -websocat -E ws://localhost:3000/ws - -# Use secure (SSL/HTTPS) connection - add wss:// -websocat -E wss://localhost:3000/ws - -# Add your API key -websocat -E ws://localhost:3000/ws?x-api-key=123 - -# Listen all sessions and events -websocat -E ws://localhost:3000/ws?session=*&events=* - -# Listen certain events -websocat -E ws://localhost:3000/ws?session=*&events=session.status&events=message - -# If you want to see the logs and ping the server every 10 seconds -websocat -v --ping-interval=10 -E ws://localhost:3000/ws - -# Listen certain session -websocat -E ws://localhost:3000/ws?session=default&events=session.status - -# With API Key -websocat -E ws://localhost:3000/ws?x-api-key=123 -``` - -Parameters: -- `session` - session name, `*` for all sessions -- `events` - list of events, `*` for all events - - `events=*` doesn't include `engine.event`. You need to specify `events=*&events=engine.event` if you want to listen all events -- `x-api-key` - your API key - -### Examples -#### JavaScript -```javascript -// Configuration -const apiKey = '123'; // Replace with your API key -const baseUrl = 'ws://localhost:3000/ws'; -const session = '*'; // Use '*' to listen to all sessions -const events = ['session.status', 'message']; // List of events to listen to - -// Construct the WebSocket URL with query parameters -const queryParams = new URLSearchParams({ - 'x-api-key': apiKey, - session, - ...events.reduce((acc, event) => ({ ...acc, events: event }), {}) // Add multiple 'events' params -}); -const wsUrl = `${baseUrl}?${queryParams.toString()}`; - -// Initialize WebSocket connection -const socket = new WebSocket(wsUrl); - -// Handle incoming messages -socket.onmessage = (event) => { - console.log('Received:', event.data); -}; - -// Handle errors -socket.onerror = (error) => { - console.error('WebSocket Error:', error); -}; - -// Handle connection open -socket.onopen = () => { - console.log('WebSocket connection established:', wsUrl); -}; - -// Handle connection close -socket.onclose = () => { - console.log('WebSocket connection closed'); -}; -``` - -## Event Payload -### Structure -In [**Webhooks**](#webhooks) or [**Websockets**](#websockets) you'll receive the following payload: - -```json -{ - // lower case ULID - https://github.com/ulid/spec - "id": "evt_1111111111111111111111111111", - // timestamp in milliseconds - "timestamp": 1741249702485, - // event name - "event": "message", - // session name - "session": "default", - // 'metadata' provided when you created the session - "metadata": { - "user.id": "123", - "user.email": "email@example.com" - }, - // me - your own contact, if authenticated and WORKING - "me": { - "id": "71111111111@c.us", - "pushName": "~" - }, - "payload": { - ... // event specific data - }, - "environment": { - "tier": "PLUS", - "version": "2023.10.12" - }, - "engine": "WEBJS" -} -``` - -### Metadata -You can provide additional `metadata` when you start the session with -[**Start Session**]({{< relref "/docs/how-to/sessions#start-session" >}}) -request data. - -```json { title="message" } -{ - "event": "message", - "session": "default", - // 'metadata' provided when you created the session - "metadata": { - "user.id": "123", - "user.email": "email@example.com" - }, - ... -} -``` - -You'll receive the same `metadata` in the webhook payload. - - -## Events -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - - -{{< include file="content/docs/how-to/events/features-events.md" >}} - -### 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 - - When you receive the `session.status` event with `SCAN_QR_CODE` status, you can [**fetch updated QR ->**]({{< relref "/docs/how-to/sessions#get-qr" >}}) - - The `SCAN_QR_CODE` is issued every time when QR updated (WhatsApp requirements) -- `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 { title="session.status" } -{ - "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 - -Incoming message (text/audio/files) - -```json { title="message" } -{ - "event": "message", - "session": "default", - "engine": "WEBJS", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "fromMe": true, - "source": "app", - "to": "11111111111@c.us", - "body": "Hi there!", - "hasMedia": false, - "ack": 1, - "vCards": [], - "_data": { - ... - } - } -} -``` - -Fields: -- `hasMedia: true | false` - indicates if the message has media attached -- `media.url: http://localhost:8000/...` - the URL to download the media -- `_data` - internal **engine** data, can be different for each engine -- `source: app|api` - can be `api` for [message.any](#messageany) event if you send a message via WAHA API. Otherwise, it's `app`. - -It's possible to have `hasMedia: true`, but `media: null` - it means WAHA didn't download media due to configuration. - -### message.any - -Fired on all message creations, including your own. The payload is the same as for [message](#message) event. - -```json { title="message.any" } - "event": "message.any", - "session": "default", - "engine": "WEBJS", - "payload": { - ... - } -} -``` - -Fields: -- `source: app|api` - can be `api` for [message.any](#messageany) event if you send a message via WAHA API. Otherwise, it's `app`. - -### message.reaction -Receive events when a message is reacted to by a user (or **yourself** reacting to a message). -- `payload.reaction.text` - emoji that was used to react to the message. It'll be an empty string if the reaction was removed. -- `payload.reaction.messageId` - id of the message that was reacted to. - -```json { title="message.reaction" } -{ - "event": "message.reaction", - "session": "default", - "me": { - "id": "79222222222@c.us", - "pushName": "WAHA" - }, - "payload": { - "id": "false_79111111@c.us_11111111111111111111111111111111", - "from": "79111111@c.us", - "fromMe": false, - "participant": "79111111@c.us", - "to": "79111111@c.us", - "timestamp": 1710481111.853, - "reaction": { - "text": "🙏", - "messageId": "true_79111111@c.us_11111111111111111111111111111111" - } - }, - "engine": "WEBJS", - "environment": { - "version": "2024.3.3", - "engine": "WEBJS", - "tier": "PLUS", - "browser": "/usr/bin/google-chrome-stable" - } -} -``` - -{{< callout context="note" icon="outline/info-circle" >}} -NOWEB engine note - reactions were sent in 'message' and 'message.any' events, not it's available only in 'message.reaction'!" -{{< /callout >}} - -### message.ack -Receive events when server or recipient gets the message, read or played it. - -`ackName` field contains message status (`ack` has the same meaning, but show the value in int, but we keep it for backward compatability, they much to each other) - -Possible message ack statuses: -- `ackName: ERROR, ack: -1` - error occurred -- `ackName: PENDING, ack: 0` - message is pending -- `ackName: SERVER, ack: 1` - message was sent to server -- `ackName: DEVICE, ack: 2` - message was sent to the device -- `ackName: READ, ack: 3` - recipient read message -- `ackName: PLAYED, ack: 4` - recipient played the message - - -The payload may have more fields, it depends on the engine you use, but here's a minimum amount that all engines send: -```json { title="message.ack" } -{ - "event": "message.ack", - "session": "default", - "engine": "WEBJS", - "payload": { - "id":"true_11111111111@c.us_4CC5EDD64BC22EBA6D639F2AF571346C", - "from":"11111111111@c.us", - "participant": null, - "fromMe":true, - "ack":3, - "ackName":"READ" - } -} -``` - -### message.waiting -Happens when you see -[Waiting for this message. This may take a while.](https://faq.whatsapp.com/3398056720476987) -on your phone. - -![waiting for this message](waiting-for-this-message.jpg) - -```json { title="message.waiting" } -{ - "event": "message.waiting", - "session": "default", - "engine": "WEBJS", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "fromMe": true, - "to": "11111111111@c.us", - ... - "_data": { - ... - } - } -} -``` - -### message.edited -The `message.edited` event is message edited - -```json { title="message.edited" } -{ - "event": "message.edited", - "session": "default", - "payload": { - "id": "false_1231243123@c.us_BBBBBBBBBBBBBBBBBBBBB[_participant]", - ..., - "editedMessageId": "AAAAAAAAAAAAAAAA", - "body": "New body", - "_data": ..., - } -} -``` - -**Fields**: -- `message.id` - message if for **edit action** - - In format `false_{chatId}_{revokeActionMessageId}[_{participant}]` - - It's not the **revoked** message (but it can be the same, for instance, in **WEBJS**) -- `editedMessageId` - the **edited message id** in format `{messageId}`, without `chatId` -- `body` - the new body (text) of the message - -### 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 { title="message.revoked" } -{ - "event": "message.revoked", - "session": "default", - "payload": { - "after": { - "id": "false_1231243123@c.us_BBBBBBBBBBBBBBBBBBBBB[_participant]", - "_data": ..., - ..., - }, - "revokedMessageId": "AAAAAAAAAAAAAAAA", - "before": null - } -} -``` - -**Fields**: -- `after.id` - message if for **revoke action** - - In format `false_{chatId}_{revokeActionMessageId}[_{participant}]` - - It's not the **revoked** message (but it can be the same, for instance, in **WEBJS**) -- `revokedMessageId` - the **revoked message id** in format `{messageId}`, without `chatId` -- `before` - is `null` in most cases. - -### chat.archive -{{< include file="content/docs/how-to/chats/webhooks-chat-archive.md" >}} - -### group.v2.join -{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} - -### group.v2.leave -{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} - -### group.v2.participants -{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} - -### group.v2.update -{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} - -### presence.update - -- `payload.id` indicates the chat - either direct chat with a contact or a group chat. -- `payload.id.[].participant` - certain participant presence status. For a direct chat there's only one participant. - -```json { title="presence.update" } -{ - "event": "presence.update", - "session": "default", - "engine": "NOWEB", - "payload": { - "id": "111111111111111111@g.us", - "presences": [ - { - "participant": "11111111111@c.us", - "lastKnownPresence": "typing", - "lastSeen": null - } - ] - } -} -``` - -### poll.vote -We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})! - -```json { title="poll.vote" } -{ - "event": "poll.vote", - "session": "default", - "payload": { - "vote": { - "id": "false_1111111111@c.us_83ACBE602A05C79B234B54415E95EE8A", - "to": "me", - "from": "1111111@c.us", - "fromMe": false, - "selectedOptions": ["Awesome!"], - "timestamp": 1692861427 - }, - "poll": { - "id": "true_1111111111@c.us_BAE5F2EF5C69001E", - "to": "1111111111@c.us", - "from": "me", - "fromMe": true - } - }, - "engine": "NOWEB" -} -``` - -### poll.vote.failed -We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})! - -```json { title="poll.vote.failed" } -{ - "event": "poll.vote.failed", - "session": "default", - "payload": { - "vote": { - "id": "false_11111111111@c.us_2E8C4CDA89EDE3BC0BC7F605364B8451", - "to": "me", - "from": "111111111@c.us", - "fromMe": false, - "selectedOptions": [], - "timestamp": 1692956972 - }, - "poll": { - "id": "true_1111111111@c.us_BAE595F4E0A2042C", - "to": "111111111@c.us", - "from": "me", - "fromMe": true - } - }, - "engine": "NOWEB" -} -``` - -### label.upsert - -```json { title="label.upsert" } -{ - "event": "label.upsert", - "session": "default", - "payload": { - "id": "10", - "name": "Label Name", - "color": 14, - "colorHex": "#00a0f2" - }, - "engine": "NOWEB", - ... -} - -``` - -### label.deleted - -```json { title="label.deleted" } -{ - "event": "label.deleted", - "session": "default", - "payload": { - "id": "10", - "name": "", - "color": 14, - "colorHex": "#00a0f2" - }, - "engine": "NOWEB", - ... -} - -``` - -### label.chat.added - -```json { title="label.chat.added" } -{ - "event": "label.chat.added", - "session": "default", - "payload": { - "labelId": "6", - "chatId": "11111111111@c.us", - "label": null <=== right after scanning QR it can be null. - }, - "engine": "NOWEB", - ... -} -``` - -### label.chat.deleted - -```json { title="label.chat.deleted" } -{ - "event": "label.chat.deleted", - "session": "default", - "payload": { - "labelId": "6", - "chatId": "11111111111@c.us", - "label": null - }, - "engine": "NOWEB", - ... -} -``` - -### call.received - -{{< include file="content/docs/how-to/calls/webhooks-call-received.md" >}} - -### call.accepted - -{{< include file="content/docs/how-to/calls/webhooks-call-accepted.md" >}} - -### call.rejected - -{{< include file="content/docs/how-to/calls/webhooks-call-rejected.md" >}} - -### engine.event -Low-level engine event, for **debug** and **troubleshooting** purposes. - -```json { title="engine.event" } -{ - "event": "engine.event", - "session": "default", - "engine": "NOWEB", - "payload": { - "event": "messages.upsert", - "data": {"": ""} - } -} -``` - -## Deprecated Events - -### group.join -{{< include file="content/docs/how-to/groups/events-group.join.md" >}} - -### group.leave -{{< include file="content/docs/how-to/groups/events-group.leave.md" >}} - - -### state.change -⚠️ **DEPRECATED**, use `session.status` event instead. - -It's an internal engine's state, not **session** `status`. - -```json { title="state.change" } -{ - "event": "state.change", - "session": "default", - "engine": "WEBJS", - "payload": { - ... - } -} -``` +--- +title: "🔄 Events" +description: "Events - how to set up and handle them using Webhooks and Websockets" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 223 +slug: events +images: ["webhooks.png"] +aliases: + - /docs/how-to/events + - /docs/how-to/webhooks + - /docs/how-to/websockets +--- + +In order to notify your application about events in the WhatsApp API, you can use +[**Webhooks**](#webhooks) and [**Websockets**](#websockets). + +👉 See the list of all available events in the [**Events**](#events) section. + +🌟 You can observe **Events** in real-time using +[**📊 Dashboard - Event Monitor**]({{< relref "dashboard#event-monitor" >}})! + +## Webhooks + +
+{{< img lqip="21x webp q20" src="webhooks.png" alt="Webhooks" >}} +
+ +**Webhooks** are a way for two different applications to communicate with each other in real-time. +When a certain event happens in one application, it sends a message to another application through a webhook URL. +The receiving application can then take action based on the information received. + +### Session webhooks + +You can define webhooks configuration per session when you start it with `POST /api/sessions/` request data. + +Here's a simple example: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"] + } + ] + } +} +``` + +Here's available configuration options for webhooks + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + "hmac": { + "key": "your-secret-key" + }, + "retries": { + "policy": "constant", + "delaySeconds": 2, + "attempts": 15 + }, + "customHeaders": [ + { + "name": "X-My-Custom-Header", + "value": "Value" + } + ] + } + ] + } +} +``` + +### Global webhooks + +There's a way how you can configure +[**🔄 Webhooks**]({{< relref "/docs/how-to/events#webhooks" >}}) +for **all sessions** at once - by settings these environment variables: + +- `WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111` - to set up a URL for the webhook +- `WHATSAPP_HOOK_EVENTS=message,message.any,state.change` - specify events. + - `WHATSAPP_HOOK_EVENTS=*` - subscribe to all events. + - We don't suggest using `*` or all events for production, it can generate a lot of requests. +- `WHATSAPP_HOOK_HMAC_KEY=your-secret-key` - the same as `hmac.key` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_POLICY=linear` - the same as `retries.policy` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_DELAY_SECONDS=2` - the same as `retries.delaySeconds` field in the webhook configuration. +- `WHATSAPP_HOOK_RETRIES_ATTEMPTS=4` +- `WHATSAPP_HOOK_CUSTOM_HEADERS=X-My-Custom-Header-1:Value;X-My-Custom-Header-2:Value` - the same as `customHeaders` field in the webhook configuration. + - Use `Header:Value` format and separate them by `;`. + +That webhook configuration **does not appear** in `session.config` field in `GET /api/sessions/` request. + +💡 You can open [https://webhook.site](https://webhook.site) and paste URL from it to `url` field, +and you'll see all requests immediately in your browser to intercept the webhook's payload. + +### Retries + +You can configure retry policy for webhooks by settings `config.retries` structure when `POST /api/sessions/`: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + "retries": { + "policy": "constant", + "delaySeconds": 2, + "attempts": 15 + } + } + ] + } +} +``` + +Possible `policy`: + +- `constant` - retry with the same delay between attempts (2, 2, 2, 2) +- `linear` - retry with linear backoff (2, 4, 6, 8) +- `exponential` - retry with exponential backoff with 20% jitter (2, 4.1, 8.4, 16.3). + +### Headers + +When you receive a webhook request to your API endpoint, you'll get **those headers**: + +- `X-Webhook-Request-Id` - unique request id for each webhook request. +- `X-Webhook-Timestamp` - Unix timestamp in milliseconds when the webhook was sent. + +If you're using [**HMAC authentication**](#hmac-authentication) you'll get two additional headers: + +- `X-Webhook-Hmac` - message authentication code for the raw **body** in HTTP POST request that send to your endpoint. +- `X-Webhook-Hmac-Algorithm` - `sha512` - algorithm that have been used to create `X-Webhook-Hmac` value. + +You can send any **customer headers** by defining `config.webhooks.customHeaders` fields this way: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + "customHeaders": [ + { + "name": "X-My-Custom-Header", + "value": "Value" + } + ] + } + ] + } +} +``` + +### HMAC authentication + +You can authenticate webhook sender by using [HMAC Authentication](https://www.okta.com/identity-101/hmac/). + +1. Define you secret key in `config.hmac.key` field when you start session with `POST /api/sessions/`: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + "hmac": { + "key": "your-secret-key" + } + } + ] + } +} +``` + +2. After that you'll receive all webhooks payload with two additional headers: + +- `X-Webhook-Hmac` - message authentication code for the raw **body** in HTTP POST request that send to your endpoint. +- `X-Webhook-Hmac-Algorithm` - `sha512` - algorithm that have been used to create `X-Webhook-Hmac` value. + +3. Implement the authentication algorithm by hashing body and using secret key and then verifying it with `X-Webhook-Hmac` + value. Please [check your implementation here ->](https://www.devglan.com/online-tools/hmac-sha256-online) + +Here's example for + +``` +# Full body +{"event":"message","session":"default","engine":"WEBJS"} +# Secret key +my-secret-key +# X-Webhook-Hmac-Algorithm +sha512 +# X-Webhook-Hmac +208f8a55dde9e05519e898b10b89bf0d0b3b0fdf11fdbf09b6b90476301b98d8097c462b2b17a6ce93b6b47a136cf2e78a33a63f6752c2c1631777076153fa89 +``` + +### Examples + +Here's few examples of how to handle webhook in different languages: + +1. [Python guide]({{< relref "/docs/integrations/waha+python" >}}) + +**Do you use another language?** + +Please create a short guide how to handle webhook and send message after you finish your setup! +You can create a pull request with your favorite language in the +[GitHub, in examples folder ->](https://github.com/devlikeapro/waha/tree/core/examples). + +## Websockets + +You can use Websockets to receive messages in real-time! + +Install [websocat](https://github.com/vi/websocat?tab=readme-ov-file#installation) first. + +```bash +# Listen all sessions and events +# -E to end the connection when the server closes it +websocat -E ws://localhost:3000/ws + +# Use secure (SSL/HTTPS) connection - add wss:// +websocat -E wss://localhost:3000/ws + +# Add your API key +websocat -E ws://localhost:3000/ws?x-api-key=123 + +# Listen all sessions and events +websocat -E ws://localhost:3000/ws?session=*&events=* + +# Listen certain events +websocat -E ws://localhost:3000/ws?session=*&events=session.status&events=message + +# If you want to see the logs and ping the server every 10 seconds +websocat -v --ping-interval=10 -E ws://localhost:3000/ws + +# Listen certain session +websocat -E ws://localhost:3000/ws?session=default&events=session.status + +# With API Key +websocat -E ws://localhost:3000/ws?x-api-key=123 +``` + +Parameters: + +- `session` - session name, `*` for all sessions +- `events` - list of events, `*` for all events + - `events=*` doesn't include `engine.event`. You need to specify `events=*&events=engine.event` if you want to listen all events +- `x-api-key` - your API key + +### Examples + +#### JavaScript + +```javascript +// Configuration +const apiKey = "123"; // Replace with your API key +const baseUrl = "ws://localhost:3000/ws"; +const session = "*"; // Use '*' to listen to all sessions +const events = ["session.status", "message"]; // List of events to listen to + +// Construct the WebSocket URL with query parameters +const queryParams = new URLSearchParams({ + "x-api-key": apiKey, + session, + ...events.reduce((acc, event) => ({ ...acc, events: event }), {}) // Add multiple 'events' params +}); +const wsUrl = `${baseUrl}?${queryParams.toString()}`; + +// Initialize WebSocket connection +const socket = new WebSocket(wsUrl); + +// Handle incoming messages +socket.onmessage = (event) => { + console.log("Received:", event.data); +}; + +// Handle errors +socket.onerror = (error) => { + console.error("WebSocket Error:", error); +}; + +// Handle connection open +socket.onopen = () => { + console.log("WebSocket connection established:", wsUrl); +}; + +// Handle connection close +socket.onclose = () => { + console.log("WebSocket connection closed"); +}; +``` + +## Event Payload + +### Structure + +In [**Webhooks**](#webhooks) or [**Websockets**](#websockets) you'll receive the following payload: + +```json +{ + // lower case ULID - https://github.com/ulid/spec + "id": "evt_1111111111111111111111111111", + // timestamp in milliseconds + "timestamp": 1741249702485, + // event name + "event": "message", + // session name + "session": "default", + // 'metadata' provided when you created the session + "metadata": { + "user.id": "123", + "user.email": "email@example.com" + }, + // me - your own contact, if authenticated and WORKING + "me": { + "id": "71111111111@c.us", + "pushName": "~" + }, + "payload": { + ... // event specific data + }, + "environment": { + "tier": "PLUS", + "version": "2023.10.12" + }, + "engine": "WEBJS" +} +``` + +### Metadata + +You can provide additional `metadata` when you start the session with +[**Start Session**]({{< relref "/docs/how-to/sessions#start-session" >}}) +request data. + +```json { title="message" } +{ + "event": "message", + "session": "default", + // 'metadata' provided when you created the session + "metadata": { + "user.id": "123", + "user.email": "email@example.com" + }, + ... +} +``` + +You'll receive the same `metadata` in the webhook payload. + +## Events + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/events/features-events.md" >}} + +### 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 + - When you receive the `session.status` event with `SCAN_QR_CODE` status, you can [**fetch updated QR ->**]({{< relref "/docs/how-to/sessions#get-qr" >}}) + - The `SCAN_QR_CODE` is issued every time when QR updated (WhatsApp requirements) +- `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 { title="session.status" } +{ + "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 + +Incoming message (text/audio/files) + +```json { title="message" } +{ + "event": "message", + "session": "default", + "engine": "WEBJS", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "fromMe": true, + "source": "app", + "to": "11111111111@c.us", + "body": "Hi there!", + "hasMedia": false, + "ack": 1, + "vCards": [], + "_data": { + ... + } + } +} +``` + +Fields: + +- `hasMedia: true | false` - indicates if the message has media attached +- `media.url: http://localhost:8000/...` - the URL to download the media +- `_data` - internal **engine** data, can be different for each engine +- `source: app|api` - can be `api` for [message.any](#messageany) event if you send a message via WAHA API. Otherwise, it's `app`. + +It's possible to have `hasMedia: true`, but `media: null` - it means WAHA didn't download media due to configuration. + +### message.any + +Fired on all message creations, including your own. The payload is the same as for [message](#message) event. + +```json { title="message.any" } + "event": "message.any", + "session": "default", + "engine": "WEBJS", + "payload": { + ... + } +} +``` + +Fields: + +- `source: app|api` - can be `api` for [message.any](#messageany) event if you send a message via WAHA API. Otherwise, it's `app`. + +### message.reaction + +Receive events when a message is reacted to by a user (or **yourself** reacting to a message). + +- `payload.reaction.text` - emoji that was used to react to the message. It'll be an empty string if the reaction was removed. +- `payload.reaction.messageId` - id of the message that was reacted to. + +```json { title="message.reaction" } +{ + "event": "message.reaction", + "session": "default", + "me": { + "id": "79222222222@c.us", + "pushName": "WAHA" + }, + "payload": { + "id": "false_79111111@c.us_11111111111111111111111111111111", + "from": "79111111@c.us", + "fromMe": false, + "participant": "79111111@c.us", + "to": "79111111@c.us", + "timestamp": 1710481111.853, + "reaction": { + "text": "🙏", + "messageId": "true_79111111@c.us_11111111111111111111111111111111" + } + }, + "engine": "WEBJS", + "environment": { + "version": "2024.3.3", + "engine": "WEBJS", + "tier": "PLUS", + "browser": "/usr/bin/google-chrome-stable" + } +} +``` + +{{< callout context="note" icon="outline/info-circle" >}} +NOWEB engine note - reactions were sent in 'message' and 'message.any' events, not it's available only in 'message.reaction'!" +{{< /callout >}} + +### message.ack + +Receive events when server or recipient gets the message, read or played it. + +`ackName` field contains message status (`ack` has the same meaning, but show the value in int, but we keep it for backward compatability, they much to each other) + +Possible message ack statuses: + +- `ackName: ERROR, ack: -1` - error occurred +- `ackName: PENDING, ack: 0` - message is pending +- `ackName: SERVER, ack: 1` - message was sent to server +- `ackName: DEVICE, ack: 2` - message was sent to the device +- `ackName: READ, ack: 3` - recipient read message +- `ackName: PLAYED, ack: 4` - recipient played the message + +The payload may have more fields, it depends on the engine you use, but here's a minimum amount that all engines send: + +```json { title="message.ack" } +{ + "event": "message.ack", + "session": "default", + "engine": "WEBJS", + "payload": { + "id": "true_11111111111@c.us_4CC5EDD64BC22EBA6D639F2AF571346C", + "from": "11111111111@c.us", + "participant": null, + "fromMe": true, + "ack": 3, + "ackName": "READ" + } +} +``` + +### message.waiting + +Happens when you see +[Waiting for this message. This may take a while.](https://faq.whatsapp.com/3398056720476987) +on your phone. + +![waiting for this message](waiting-for-this-message.jpg) + +```json { title="message.waiting" } +{ + "event": "message.waiting", + "session": "default", + "engine": "WEBJS", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "fromMe": true, + "to": "11111111111@c.us", + ... + "_data": { + ... + } + } +} +``` + +### message.edited + +The `message.edited` event is message edited + +```json { title="message.edited" } +{ + "event": "message.edited", + "session": "default", + "payload": { + "id": "false_1231243123@c.us_BBBBBBBBBBBBBBBBBBBBB[_participant]", + ..., + "editedMessageId": "AAAAAAAAAAAAAAAA", + "body": "New body", + "_data": ..., + } +} +``` + +**Fields**: + +- `message.id` - message if for **edit action** + - In format `false_{chatId}_{revokeActionMessageId}[_{participant}]` + - It's not the **revoked** message (but it can be the same, for instance, in **WEBJS**) +- `editedMessageId` - the **edited message id** in format `{messageId}`, without `chatId` +- `body` - the new body (text) of the message + +### 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 { title="message.revoked" } +{ + "event": "message.revoked", + "session": "default", + "payload": { + "after": { + "id": "false_1231243123@c.us_BBBBBBBBBBBBBBBBBBBBB[_participant]", + "_data": ..., + ..., + }, + "revokedMessageId": "AAAAAAAAAAAAAAAA", + "before": null + } +} +``` + +**Fields**: + +- `after.id` - message if for **revoke action** + - In format `false_{chatId}_{revokeActionMessageId}[_{participant}]` + - It's not the **revoked** message (but it can be the same, for instance, in **WEBJS**) +- `revokedMessageId` - the **revoked message id** in format `{messageId}`, without `chatId` +- `before` - is `null` in most cases. + +### chat.archive + +{{< include file="content/docs/how-to/chats/webhooks-chat-archive.md" >}} + +### group.v2.join + +{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} + +### group.v2.leave + +{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} + +### group.v2.participants + +{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} + +### group.v2.update + +{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} + +### presence.update + +- `payload.id` indicates the chat - either direct chat with a contact or a group chat. +- `payload.id.[].participant` - certain participant presence status. For a direct chat there's only one participant. + +```json { title="presence.update" } +{ + "event": "presence.update", + "session": "default", + "engine": "NOWEB", + "payload": { + "id": "111111111111111111@g.us", + "presences": [ + { + "participant": "11111111111@c.us", + "lastKnownPresence": "typing", + "lastSeen": null + } + ] + } +} +``` + +### poll.vote + +We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})! + +```json { title="poll.vote" } +{ + "event": "poll.vote", + "session": "default", + "payload": { + "vote": { + "id": "false_1111111111@c.us_83ACBE602A05C79B234B54415E95EE8A", + "to": "me", + "from": "1111111@c.us", + "fromMe": false, + "selectedOptions": ["Awesome!"], + "timestamp": 1692861427 + }, + "poll": { + "id": "true_1111111111@c.us_BAE5F2EF5C69001E", + "to": "1111111111@c.us", + "from": "me", + "fromMe": true + } + }, + "engine": "NOWEB" +} +``` + +### poll.vote.failed + +We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})! + +```json { title="poll.vote.failed" } +{ + "event": "poll.vote.failed", + "session": "default", + "payload": { + "vote": { + "id": "false_11111111111@c.us_2E8C4CDA89EDE3BC0BC7F605364B8451", + "to": "me", + "from": "111111111@c.us", + "fromMe": false, + "selectedOptions": [], + "timestamp": 1692956972 + }, + "poll": { + "id": "true_1111111111@c.us_BAE595F4E0A2042C", + "to": "111111111@c.us", + "from": "me", + "fromMe": true + } + }, + "engine": "NOWEB" +} +``` + +### label.upsert + +```json { title="label.upsert" } +{ + "event": "label.upsert", + "session": "default", + "payload": { + "id": "10", + "name": "Label Name", + "color": 14, + "colorHex": "#00a0f2" + }, + "engine": "NOWEB", + ... +} + +``` + +### label.deleted + +```json { title="label.deleted" } +{ + "event": "label.deleted", + "session": "default", + "payload": { + "id": "10", + "name": "", + "color": 14, + "colorHex": "#00a0f2" + }, + "engine": "NOWEB", + ... +} + +``` + +### label.chat.added + +```json { title="label.chat.added" } +{ + "event": "label.chat.added", + "session": "default", + "payload": { + "labelId": "6", + "chatId": "11111111111@c.us", + "label": null <=== right after scanning QR it can be null. + }, + "engine": "NOWEB", + ... +} +``` + +### label.chat.deleted + +```json { title="label.chat.deleted" } +{ + "event": "label.chat.deleted", + "session": "default", + "payload": { + "labelId": "6", + "chatId": "11111111111@c.us", + "label": null + }, + "engine": "NOWEB", + ... +} +``` + +### call.received + +{{< include file="content/docs/how-to/calls/webhooks-call-received.md" >}} + +### call.accepted + +{{< include file="content/docs/how-to/calls/webhooks-call-accepted.md" >}} + +### call.rejected + +{{< include file="content/docs/how-to/calls/webhooks-call-rejected.md" >}} + +### engine.event + +Low-level engine event, for **debug** and **troubleshooting** purposes. + +```json { title="engine.event" } +{ + "event": "engine.event", + "session": "default", + "engine": "NOWEB", + "payload": { + "event": "messages.upsert", + "data": { "": "" } + } +} +``` + +## Deprecated Events + +### group.join + +{{< include file="content/docs/how-to/groups/events-group.join.md" >}} + +### group.leave + +{{< include file="content/docs/how-to/groups/events-group.leave.md" >}} + +### state.change + +⚠️ **DEPRECATED**, use `session.status` event instead. + +It's an internal engine's state, not **session** `status`. + +```json { title="state.change" } +{ + "event": "state.change", + "session": "default", + "engine": "WEBJS", + "payload": { + ... + } +} +``` diff --git a/content/docs/how-to/groups/events-group.join.md b/content/docs/how-to/groups/events-group.join.md index dafee34bf..c8a6d64a9 100644 --- a/content/docs/how-to/groups/events-group.join.md +++ b/content/docs/how-to/groups/events-group.join.md @@ -1,12 +1,12 @@ -⚠️ **DEPRECATED**. `payload` has engine specific data. Use [group.v2.leave](#groupv2leave) instead. - -```json { title="group.join" } -{ - "event": "group.join", - "session": "default", - "engine": "WEBJS", - "payload": { - ... - } -} -``` +⚠️ **DEPRECATED**. `payload` has engine specific data. Use [group.v2.leave](#groupv2leave) instead. + +```json { title="group.join" } +{ + "event": "group.join", + "session": "default", + "engine": "WEBJS", + "payload": { + ... + } +} +``` diff --git a/content/docs/how-to/groups/events-group.leave.md b/content/docs/how-to/groups/events-group.leave.md index 9939bb270..d8db47df9 100644 --- a/content/docs/how-to/groups/events-group.leave.md +++ b/content/docs/how-to/groups/events-group.leave.md @@ -1,12 +1,12 @@ -⚠️ **DEPRECATED**. `payload` has engine specific data. Use [group.v2.leave](#groupv2leave) instead. - -```json { title="group.leave" } -{ - "event": "group.leave", - "session": "default", - "engine": "WEBJS", - "payload": { - ... - } -} -``` +⚠️ **DEPRECATED**. `payload` has engine specific data. Use [group.v2.leave](#groupv2leave) instead. + +```json { title="group.leave" } +{ + "event": "group.leave", + "session": "default", + "engine": "WEBJS", + "payload": { + ... + } +} +``` diff --git a/content/docs/how-to/groups/events-group.v2.join.md b/content/docs/how-to/groups/events-group.v2.join.md index 2b7dfdff4..9688979c1 100644 --- a/content/docs/how-to/groups/events-group.v2.join.md +++ b/content/docs/how-to/groups/events-group.v2.join.md @@ -1,39 +1,39 @@ -`group.v2.join` happens when **you** join or are added to a group. - -```json { title="group.v2.join" } -{ - "event": "group.v2.join", - "session": "default", - "payload": { - "group": { - "id": "1231231232@g.us", - "subject": "Work Group", - "description": "Group description", - "invite": "https://chat.whatsapp.com/invitecode", - "membersCanAddNewMember": true, - "membersCanSendMessages": true, - "newMembersApprovalRequired": true, - "participants": [ - { - "id": "99999@c.us", - "role": "participant" - } - ] - }, - "timestamp": 789456123, - "_data": {} - } -} -``` - -- `group` - group information - - `id` - group ID - - `subject` - group name - - `description` - group description - - `invite` - invite link - - `membersCanAddNewMember` - if members can add new members - - `membersCanSendMessages` - if members can send messages - - `newMembersApprovalRequired` - if new members need approval from admins - - `participants` - list of participants (check [group.v2.participants](#groupv2participants) for more details) -- `timestamp` - event timestamp -- `_data` - engine specific data +`group.v2.join` happens when **you** join or are added to a group. + +```json { title="group.v2.join" } +{ + "event": "group.v2.join", + "session": "default", + "payload": { + "group": { + "id": "1231231232@g.us", + "subject": "Work Group", + "description": "Group description", + "invite": "https://chat.whatsapp.com/invitecode", + "membersCanAddNewMember": true, + "membersCanSendMessages": true, + "newMembersApprovalRequired": true, + "participants": [ + { + "id": "99999@c.us", + "role": "participant" + } + ] + }, + "timestamp": 789456123, + "_data": {} + } +} +``` + +- `group` - group information + - `id` - group ID + - `subject` - group name + - `description` - group description + - `invite` - invite link + - `membersCanAddNewMember` - if members can add new members + - `membersCanSendMessages` - if members can send messages + - `newMembersApprovalRequired` - if new members need approval from admins + - `participants` - list of participants (check [group.v2.participants](#groupv2participants) for more details) +- `timestamp` - event timestamp +- `_data` - engine specific data diff --git a/content/docs/how-to/groups/events-group.v2.leave.md b/content/docs/how-to/groups/events-group.v2.leave.md index ad8dbd655..f1e36fbae 100644 --- a/content/docs/how-to/groups/events-group.v2.leave.md +++ b/content/docs/how-to/groups/events-group.v2.leave.md @@ -1,20 +1,19 @@ -`group.v2.leave` happens when **you** leave or are removed from a group. - - -```json { title="group.v2.leave" } -{ - "event": "group.v2.leave", - "session": "default", - "payload": { - "group": { - "id": "1231231232@g.us" - }, - "timestamp": 789456123, - "_data": {} - } -} -``` - -- `group.id` - group ID -- `timestamp` - event timestamp -- `_data` - engine specific data +`group.v2.leave` happens when **you** leave or are removed from a group. + +```json { title="group.v2.leave" } +{ + "event": "group.v2.leave", + "session": "default", + "payload": { + "group": { + "id": "1231231232@g.us" + }, + "timestamp": 789456123, + "_data": {} + } +} +``` + +- `group.id` - group ID +- `timestamp` - event timestamp +- `_data` - engine specific data diff --git a/content/docs/how-to/groups/events-group.v2.participants.md b/content/docs/how-to/groups/events-group.v2.participants.md index 7ad1a1d60..49b837483 100644 --- a/content/docs/how-to/groups/events-group.v2.participants.md +++ b/content/docs/how-to/groups/events-group.v2.participants.md @@ -1,39 +1,38 @@ -`group.v2.participants` happens when someone join or leave a group. - -ℹ️ It might duplicate [group.v2.join](#groupv2join) and [group.v2.leave](#groupv2leave) events for your ID. - - -```json { title="group.v2.participants" } -{ - "event": "group.v2.participants", - "session": "default", - "payload": { - "type": "join", - "timestamp": 1666943582, - "group": { - "id": "123456789@g.us" - }, - "participants": [ - { - "id": "123456789@c.us", - "role": "participant" - } - ], - "_data": {} - } -} -``` - -- `type` - event type. Possible values: - - **join** - when someone joins the group - - **leave** - when someone leaves the group - - **promote** - when someone is promoted to admin - - **demote** - when someone is demoted to regular participant -- `participants` - list of participants (contains only changed participants) - - `id` - participant ID - - `role` - participant role. Possible values: - - **left** - left the group - - **participant** - regular participant - - **admin** - group admin - - **superadmin** - group super admin -- `_data` - engine specific data +`group.v2.participants` happens when someone join or leave a group. + +ℹ️ It might duplicate [group.v2.join](#groupv2join) and [group.v2.leave](#groupv2leave) events for your ID. + +```json { title="group.v2.participants" } +{ + "event": "group.v2.participants", + "session": "default", + "payload": { + "type": "join", + "timestamp": 1666943582, + "group": { + "id": "123456789@g.us" + }, + "participants": [ + { + "id": "123456789@c.us", + "role": "participant" + } + ], + "_data": {} + } +} +``` + +- `type` - event type. Possible values: + - **join** - when someone joins the group + - **leave** - when someone leaves the group + - **promote** - when someone is promoted to admin + - **demote** - when someone is demoted to regular participant +- `participants` - list of participants (contains only changed participants) + - `id` - participant ID + - `role` - participant role. Possible values: + - **left** - left the group + - **participant** - regular participant + - **admin** - group admin + - **superadmin** - group super admin +- `_data` - engine specific data diff --git a/content/docs/how-to/groups/events-group.v2.update.md b/content/docs/how-to/groups/events-group.v2.update.md index f8234aa07..0f31d5e4d 100644 --- a/content/docs/how-to/groups/events-group.v2.update.md +++ b/content/docs/how-to/groups/events-group.v2.update.md @@ -1,21 +1,21 @@ -`group.v2.update` happens when the group information is updated. - -```json { title="group.v2.update" } -{ - "event": "group.v2.update", - "session": "default", - "payload": { - "group": { - "id": "1231231232@g.us", - "subject": "New Work Group Name" - }, - "timestamp": 789456123, - "_data": {} - } -} -``` - -- `group` - group information with updates field (may contain all fields in some engines) - - See details in [group.v2.join](#groupv2join) -- `timestamp` - event timestamp -- `_data` - engine specific data +`group.v2.update` happens when the group information is updated. + +```json { title="group.v2.update" } +{ + "event": "group.v2.update", + "session": "default", + "payload": { + "group": { + "id": "1231231232@g.us", + "subject": "New Work Group Name" + }, + "timestamp": 789456123, + "_data": {} + } +} +``` + +- `group` - group information with updates field (may contain all fields in some engines) + - See details in [group.v2.join](#groupv2join) +- `timestamp` - event timestamp +- `_data` - engine specific data diff --git a/content/docs/how-to/groups/features-events.md b/content/docs/how-to/groups/features-events.md index deb8c2af6..459fc2155 100644 --- a/content/docs/how-to/groups/features-events.md +++ b/content/docs/how-to/groups/features-events.md @@ -1,13 +1,13 @@ -
-{{< details "**👥 Groups - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|-------------------------|:-----:|:-----:|:----:| -| `group.v2.join` | ✔️ | ✔️ | ✔️ | -| `group.v2.leave` | ✔️ | ✔️ | ✔️ | -| `group.v2.participants` | ✔️ | ✔️ | ✔️ | -| `group.v2.update` | ✔️ | ✔️ | ✔️ | -| ~~group.join~~ | ✔️ | ✔️ | | -| ~~group.leave~~ | ✔️ | | | - -{{< /details >}} +
+{{< details "**👥 Groups - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ----------------------- | :---: | :---: | :--: | +| `group.v2.join` | ✔️ | ✔️ | ✔️ | +| `group.v2.leave` | ✔️ | ✔️ | ✔️ | +| `group.v2.participants` | ✔️ | ✔️ | ✔️ | +| `group.v2.update` | ✔️ | ✔️ | ✔️ | +| ~~group.join~~ | ✔️ | ✔️ | | +| ~~group.leave~~ | ✔️ | | | + +{{< /details >}} diff --git a/content/docs/how-to/groups/features.md b/content/docs/how-to/groups/features.md index 874d3ea9f..64df3eb03 100644 --- a/content/docs/how-to/groups/features.md +++ b/content/docs/how-to/groups/features.md @@ -1,33 +1,33 @@ -
-{{< details "**👥 Groups - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|------------------------------------------------------------------------|:-----:|:-----:|:----:| -| `POST /api/{session}/groups` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups/count` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups/join-info` | ✔️ | ✔️ | ✔️ | -| `POST /api/{session}/groups/join` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups/{id}` | ✔️ | ✔️ | ✔️ | -| `DELETE /api/{session}/groups/{id}` | ✔️ | | | -| `POST /api/{session}/groups/{id}/leave` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups/{id}/picture` | ✔️ | ✔️ | ✔️ | -| `PUT /api/{session}/groups/{id}/picture` | ➕ | ➕ | ➕ | -| `DELETE /api/{session}/groups/{id}/picture` | ➕ | ➕ | ➕ | -| `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}/settings/security/info-admin-only` | ✔️ | ✔️ | ✔️ | -| `PUT /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ✔️ | ✔️ | -| `PUT /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ✔️ | ✔️ | -| `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` | ✔️ | ✔️ | ✔️ | - -- ➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) - -{{< /details >}} +
+{{< details "**👥 Groups - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ---------------------------------------------------------------------- | :---: | :---: | :--: | +| `POST /api/{session}/groups` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups/count` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups/join-info` | ✔️ | ✔️ | ✔️ | +| `POST /api/{session}/groups/join` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups/{id}` | ✔️ | ✔️ | ✔️ | +| `DELETE /api/{session}/groups/{id}` | ✔️ | | | +| `POST /api/{session}/groups/{id}/leave` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups/{id}/picture` | ✔️ | ✔️ | ✔️ | +| `PUT /api/{session}/groups/{id}/picture` | ➕ | ➕ | ➕ | +| `DELETE /api/{session}/groups/{id}/picture` | ➕ | ➕ | ➕ | +| `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}/settings/security/info-admin-only` | ✔️ | ✔️ | ✔️ | +| `PUT /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ✔️ | ✔️ | +| `PUT /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ✔️ | ✔️ | +| `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` | ✔️ | ✔️ | ✔️ | + +- ➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) + +{{< /details >}} diff --git a/content/docs/how-to/groups/index.md b/content/docs/how-to/groups/index.md index 4275d93f8..85cd784c2 100644 --- a/content/docs/how-to/groups/index.md +++ b/content/docs/how-to/groups/index.md @@ -1,448 +1,470 @@ ---- -title : "👥 Groups" -description: "Groups" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 240 -images: ["groups.jpg"] -slug: groups ---- - -Manage WhatsApp groups with the API. - -
-{{< img lqip="21x webp q20" src="groups.jpg" alt="WhatsApp Groups" >}} -
- -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/groups/features.md" >}} -{{< include file="content/docs/how-to/groups/features-events.md" >}} - -## API -- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/session` endpoint -- `{groupId}` - group id in format `123123123123@g.us`. You can get the id in a few ways: - - By [handling incoming message webhook]({{< relref "/docs/how-to/receive-messages" >}}). - - By getting all groups (see below). - - By creating a new group and saving the id. - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Check [**👤 Contacts - Lids**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) if you see `@lid` -in participants list for a group -{{< /callout >}} - -### Create a new group - -```http request -POST /api/{session}/groups -``` - -```json { title="Body" } -{ - "name": "Group name", - "participants": [ - { - "id": "123123123123@c.us" - } - ] -} -``` - -### Get all groups - -```http request -GET /api/{session}/groups -``` - - -**Response**: -depends on [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) you use. - -**Query parameters**: - -```http request -GET /api/{session}/groups?limit=10&offset=0&sortBy=subject&sortOrder=desc -``` - -If you see timeout or the request takes too long - consider using `limit` parameter to get objects in smaller chunks - -- `limit=10` - limit the number of chats to return -- `offset=0` - skip the number of chats from the start -- `sortBy={field}` - sort by field - - `sortBy=id` - sort by group id - - `sortBy=subject` - sort by group subject -- `sortOrder=desc|asc` - sort order - - `desc` - descending order (New first, A-Z) - - `asc` - ascending order (Old first, Z-A) -- `exclude=participants` - you can exclude participants data from the response - -{{< details "I see rate-overlimit in NOWEB" >}} - 👉 If you see `rate-overlimit` error with **NOWEB** engine - try enabling [**🏭 NOWEB Store before using the endpoint**]({{< relref "/docs/engines/NOWEB#store" >}})! -{{< /details >}} - -### Get groups count -Get the total number of groups - -```http request -GET /api/{session}/groups/count -``` - -```json { title="Response" } -{ - "count": 10 -} -``` - -### Join group -If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can - -```http request -POST /api/{session}/groups/join -``` - -```json { title="Body" } -{ - "code": "invitecode" -} -``` - -or using full link: -```json { title="Body" } -{ - "code": "https://chat.whatsapp.com/invitecode" -} -``` - -```json { title="Response" } -{ - "id": "123123123@g.us" -} -``` - -### Get join info for group -If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can get group info: - -```http request -GET /api/{session}/groups/join-info?code=invitecode -``` - -or using full link (remember to encode the URL) - -```http request -GET /api/{session}/groups/join-info?code=https%3A%2F%2Fchat.whatsapp.com%2Finvitecode -``` - -Response depends on engine you're using - -### Refresh groups -If you see any inconsistency in groups list or in participants list, you can refresh the groups from the WhatsApp server: -```http request -POST /api/{session}/groups/refresh -``` - -⚠️ Do not call it frequently, it can lead to `rate-overlimit` error. Usually groups API has all up-to-date information. - -### Get the group - -```http request -GET /api/{session}/groups/{groupId} -``` - -### Delete the group - -```http request -DELETE /api/{session}/groups/{groupId} -``` - -### Leave the group - -```http request -POST /api/{session}/groups/{groupId}/leave -``` - -### Group Picture -You can get, set and remove group picture - -#### Get Group Picture - -```http request -GET /api/{SESSION}/groups/{ID}/picture?refresh=false -``` - -- `{SESSION}` - session name -- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` -- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. - -```json { title="Response" } -{ - "url": "https://example.com/picture.jpg" -} -``` - -- `url` can be `null` if there's no picture for the group - -#### Set Group Picture -👉 Available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. - -```http request -PUT /api/{SESSION}/groups/{ID}/picture -``` - -- `{SESSION}` - session name -- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` - -{{< tabs "groups-set-picture" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "file": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } -} -``` - -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "file": { - "data": "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" - } -} -``` -{{< /tab >}} -{{< /tabs >}} - -```json { title="Response" } -{ - "success": true -} -``` - -#### Delete Group Picture -👉 Available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. - -```http request -DELETE /api/{SESSION}/groups/{ID}/picture -``` -- `{SESSION}` - session name -- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` - -```json { title="Response" } -{ - "success": true -} -``` - -### Set group subject - -Updates the group subject. - -Returns `true` if the subject was properly updated. This can return false if the user does not have the necessary -permissions. - -```http request -PUT /api/{session}/groups/{groupId}/subject -``` - -```json { title="Body" } -{ - "subject": "Group name" -} -``` - -### Set group description - -Updates the group description. - -Returns `true` if the subject was properly updated. This can return false if the user does not have the necessary -permissions. - -```http request -PUT /api/{session}/groups/{groupId}/description -``` - -```json { title="Body" } -{ - "description": "Group description" -} -``` - -### Security - update group info -Updates the group settings to only allow admins to edit group info (title, description, photo). - -```http request -PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only -``` - -```json { title="Body" } -{ - "adminsOnly": true -} -``` - -Get the group settings to only allow admins to edit group info (title, description, photo). - -```http request -GET /api/{session}/groups/{groupId}/settings/security/info-admin-only -``` - -```json { title="Response" } -{ - "adminsOnly": true -} -``` - -Returns `true` if the setting was properly updated. This can return false if the user does not have the necessary permissions. - -### Security - who can send messages -Updates the group settings to only allow admins to send messages. - -```http request -PUT /api/{session}/groups/{groupId}/settings/security/messages-admin-only -``` - -```json { title="Body" } -{ - "adminsOnly": true -} -``` - -Returns `true` if the setting was properly updated. This can return false if the user does not have the necessary permissions. - -Get the group settings to only allow admins to send messages. - -```http request -GET /api/{session}/groups/{groupId}/settings/security/messages-admin-only -``` - -```json { title="Response" } -{ - "adminsOnly": true -} -``` - -### Participants - -#### Get participants - -```http request -GET /api/{session}/groups/{groupId}/participants -``` - -#### Add participants - -```http request -POST /api/{session}/groups/{groupId}/participants/add -``` - -```json { title="Body" } -{ - "participants": [ - { - "id": "123123123123@c.us" - } - ] -} -``` - -#### Remove participants - -```http request -POST /api/{session}/groups/{groupId}/participants/remove -``` - -```json { title="Body" } -{ - "participants": [ - { - "id": "123123123123@c.us" - } - ] -} -``` - -### Admin - -#### Promote to admin - -Promote participants to admin users. - -```http request -POST /api/{session}/groups/{groupId}/admin/promote -``` - -```json { title="Body" } -{ - "participants": [ - { - "id": "123123123123@c.us" - } - ] -} -``` - -#### Demote to regular users - -Demote participants by to regular users. - -```http request -POST /api/{session}/groups/{groupId}/admin/demote -``` - -```json { title="Body" } -{ - "participants": [ - { - "id": "123123123123@c.us" - } - ] -} -``` - -### Invite code - -#### Get invite code - -```http request -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 - -Invalidates the current group invite code and generates a new one. - -```http request -POST /api/{session}/groups/{groupId}/invite-code/revoke -``` - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -{{< include file="content/docs/how-to/groups/features-events.md" >}} - -### group.v2.join -{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} - -### group.v2.leave -{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} - -### group.v2.participants -{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} - -### group.v2.update -{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} - -### group.join -{{< include file="content/docs/how-to/groups/events-group.join.md" >}} - -### group.leave -{{< include file="content/docs/how-to/groups/events-group.leave.md" >}} +--- +title: "👥 Groups" +description: "Groups" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 240 +images: ["groups.jpg"] +slug: groups +--- + +Manage WhatsApp groups with the API. + +
+{{< img lqip="21x webp q20" src="groups.jpg" alt="WhatsApp Groups" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/groups/features.md" >}} +{{< include file="content/docs/how-to/groups/features-events.md" >}} + +## API + +- `{session}` - use the session name for Whatsapp instance that you created with `POST /api/session` endpoint +- `{groupId}` - group id in format `123123123123@g.us`. You can get the id in a few ways: + - By [handling incoming message webhook]({{< relref "/docs/how-to/receive-messages" >}}). + - By getting all groups (see below). + - By creating a new group and saving the id. + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Check [**👤 Contacts - Lids**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) if you see `@lid` +in participants list for a group +{{< /callout >}} + +### Create a new group + +```http request +POST /api/{session}/groups +``` + +```json { title="Body" } +{ + "name": "Group name", + "participants": [ + { + "id": "123123123123@c.us" + } + ] +} +``` + +### Get all groups + +```http request +GET /api/{session}/groups +``` + +**Response**: +depends on [**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) you use. + +**Query parameters**: + +```http request +GET /api/{session}/groups?limit=10&offset=0&sortBy=subject&sortOrder=desc +``` + +If you see timeout or the request takes too long - consider using `limit` parameter to get objects in smaller chunks + +- `limit=10` - limit the number of chats to return +- `offset=0` - skip the number of chats from the start +- `sortBy={field}` - sort by field + - `sortBy=id` - sort by group id + - `sortBy=subject` - sort by group subject +- `sortOrder=desc|asc` - sort order + - `desc` - descending order (New first, A-Z) + - `asc` - ascending order (Old first, Z-A) +- `exclude=participants` - you can exclude participants data from the response + +{{< details "I see rate-overlimit in NOWEB" >}} +👉 If you see `rate-overlimit` error with **NOWEB** engine - try enabling [**🏭 NOWEB Store before using the endpoint**]({{< relref "/docs/engines/NOWEB#store" >}})! +{{< /details >}} + +### Get groups count + +Get the total number of groups + +```http request +GET /api/{session}/groups/count +``` + +```json { title="Response" } +{ + "count": 10 +} +``` + +### Join group + +If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can + +```http request +POST /api/{session}/groups/join +``` + +```json { title="Body" } +{ + "code": "invitecode" +} +``` + +or using full link: + +```json { title="Body" } +{ + "code": "https://chat.whatsapp.com/invitecode" +} +``` + +```json { title="Response" } +{ + "id": "123123123@g.us" +} +``` + +### Get join info for group + +If you have invite URL for a group (like `https://chat.whatsapp.com/invitecode`), you can get group info: + +```http request +GET /api/{session}/groups/join-info?code=invitecode +``` + +or using full link (remember to encode the URL) + +```http request +GET /api/{session}/groups/join-info?code=https%3A%2F%2Fchat.whatsapp.com%2Finvitecode +``` + +Response depends on engine you're using + +### Refresh groups + +If you see any inconsistency in groups list or in participants list, you can refresh the groups from the WhatsApp server: + +```http request +POST /api/{session}/groups/refresh +``` + +⚠️ Do not call it frequently, it can lead to `rate-overlimit` error. Usually groups API has all up-to-date information. + +### Get the group + +```http request +GET /api/{session}/groups/{groupId} +``` + +### Delete the group + +```http request +DELETE /api/{session}/groups/{groupId} +``` + +### Leave the group + +```http request +POST /api/{session}/groups/{groupId}/leave +``` + +### Group Picture + +You can get, set and remove group picture + +#### Get Group Picture + +```http request +GET /api/{SESSION}/groups/{ID}/picture?refresh=false +``` + +- `{SESSION}` - session name +- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` +- `refresh=True` - force refresh the picture. By default, we cache it 24 hours. Do not frequently refresh the picture to avoid `rate-overlimit` error. + +```json { title="Response" } +{ + "url": "https://example.com/picture.jpg" +} +``` + +- `url` can be `null` if there's no picture for the group + +#### Set Group Picture + +👉 Available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. + +```http request +PUT /api/{SESSION}/groups/{ID}/picture +``` + +- `{SESSION}` - session name +- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` + +{{< tabs "groups-set-picture" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "file": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "file": { + "data": "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" + } +} +``` + +{{< /tab >}} +{{< /tabs >}} + +```json { title="Response" } +{ + "success": true +} +``` + +#### Delete Group Picture + +👉 Available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. + +```http request +DELETE /api/{SESSION}/groups/{ID}/picture +``` + +- `{SESSION}` - session name +- `{ID}` - group id. Remember to encode `@` symbol - `123123123123%40g.us` + +```json { title="Response" } +{ + "success": true +} +``` + +### Set group subject + +Updates the group subject. + +Returns `true` if the subject was properly updated. This can return false if the user does not have the necessary +permissions. + +```http request +PUT /api/{session}/groups/{groupId}/subject +``` + +```json { title="Body" } +{ + "subject": "Group name" +} +``` + +### Set group description + +Updates the group description. + +Returns `true` if the subject was properly updated. This can return false if the user does not have the necessary +permissions. + +```http request +PUT /api/{session}/groups/{groupId}/description +``` + +```json { title="Body" } +{ + "description": "Group description" +} +``` + +### Security - update group info + +Updates the group settings to only allow admins to edit group info (title, description, photo). + +```http request +PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only +``` + +```json { title="Body" } +{ + "adminsOnly": true +} +``` + +Get the group settings to only allow admins to edit group info (title, description, photo). + +```http request +GET /api/{session}/groups/{groupId}/settings/security/info-admin-only +``` + +```json { title="Response" } +{ + "adminsOnly": true +} +``` + +Returns `true` if the setting was properly updated. This can return false if the user does not have the necessary permissions. + +### Security - who can send messages + +Updates the group settings to only allow admins to send messages. + +```http request +PUT /api/{session}/groups/{groupId}/settings/security/messages-admin-only +``` + +```json { title="Body" } +{ + "adminsOnly": true +} +``` + +Returns `true` if the setting was properly updated. This can return false if the user does not have the necessary permissions. + +Get the group settings to only allow admins to send messages. + +```http request +GET /api/{session}/groups/{groupId}/settings/security/messages-admin-only +``` + +```json { title="Response" } +{ + "adminsOnly": true +} +``` + +### Participants + +#### Get participants + +```http request +GET /api/{session}/groups/{groupId}/participants +``` + +#### Add participants + +```http request +POST /api/{session}/groups/{groupId}/participants/add +``` + +```json { title="Body" } +{ + "participants": [ + { + "id": "123123123123@c.us" + } + ] +} +``` + +#### Remove participants + +```http request +POST /api/{session}/groups/{groupId}/participants/remove +``` + +```json { title="Body" } +{ + "participants": [ + { + "id": "123123123123@c.us" + } + ] +} +``` + +### Admin + +#### Promote to admin + +Promote participants to admin users. + +```http request +POST /api/{session}/groups/{groupId}/admin/promote +``` + +```json { title="Body" } +{ + "participants": [ + { + "id": "123123123123@c.us" + } + ] +} +``` + +#### Demote to regular users + +Demote participants by to regular users. + +```http request +POST /api/{session}/groups/{groupId}/admin/demote +``` + +```json { title="Body" } +{ + "participants": [ + { + "id": "123123123123@c.us" + } + ] +} +``` + +### Invite code + +#### Get invite code + +```http request +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 + +Invalidates the current group invite code and generates a new one. + +```http request +POST /api/{session}/groups/{groupId}/invite-code/revoke +``` + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +{{< include file="content/docs/how-to/groups/features-events.md" >}} + +### group.v2.join + +{{< include file="content/docs/how-to/groups/events-group.v2.join.md" >}} + +### group.v2.leave + +{{< include file="content/docs/how-to/groups/events-group.v2.leave.md" >}} + +### group.v2.participants + +{{< include file="content/docs/how-to/groups/events-group.v2.participants.md" >}} + +### group.v2.update + +{{< include file="content/docs/how-to/groups/events-group.v2.update.md" >}} + +### group.join + +{{< include file="content/docs/how-to/groups/events-group.join.md" >}} + +### group.leave + +{{< include file="content/docs/how-to/groups/events-group.leave.md" >}} diff --git a/content/docs/how-to/install/-the-hosting.md b/content/docs/how-to/install/-the-hosting.md index 135ac10ef..4680231d2 100644 --- a/content/docs/how-to/install/-the-hosting.md +++ b/content/docs/how-to/install/-the-hosting.md @@ -1,7 +1,7 @@ -
-{{< callout context="note" title="Looking for Hosting?" icon="outline/server" >}} -We've been using [**the.hosting**](https://the.hosting/?from=686406) -for quite a while and had a great experience. - -They offer a wide range of server configurations and locations - highly recommended! 👍 -{{< /callout >}} +
+{{< callout context="note" title="Looking for Hosting?" icon="outline/server" >}} +We've been using [**the.hosting**](https://the.hosting/?from=686406) +for quite a while and had a great experience. + +They offer a wide range of server configurations and locations - highly recommended! 👍 +{{< /callout >}} diff --git a/content/docs/how-to/install/download-image.md b/content/docs/how-to/install/download-image.md index 40b9451d3..b1a63f8f9 100644 --- a/content/docs/how-to/install/download-image.md +++ b/content/docs/how-to/install/download-image.md @@ -1,56 +1,57 @@ -
-{{< tabs "download-docker-image" >}} - -{{< tab "WAHA Core" >}} -Run the command below: - -```bash -docker pull devlikeapro/waha -``` - -{{< /tab >}} - -{{< tab "➕ WAHA Plus" >}} -If you got the -[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) -, use the following commands: - -```bash -docker login -u devlikeapro -p {KEY} -docker pull devlikeapro/waha-plus -docker logout -``` - -👉 Go to -[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) -to generate the command with the right version. -{{< /tab >}} - -{{< tab "WAHA (ARM)" >}} -If you're using ARM (like Apple M1/M2, Raspberry Pi etc.) - use following commands to download the image: -```bash -# Download the image -docker pull devlikeapro/waha:arm -# Rename it, so you can use devlikeapro/waha image in other place -docker tag devlikeapro/waha:arm devlikeapro/waha -``` - -If you got the -[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) -, use the following commands: - -```bash -docker login -u devlikeapro -p {KEY} -docker pull devlikeapro/waha-plus:arm -docker logout - -# Rename it, so you can use devlikeapro/waha image in other place -docker tag devlikeapro/waha-plus:arm devlikeapro/waha-plus -``` - -👉 Go to -[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) -to generate the command with the right version. -{{< /tab >}} - -{{< /tabs >}} +
+{{< tabs "download-docker-image" >}} + +{{< tab "WAHA Core" >}} +Run the command below: + +```bash +docker pull devlikeapro/waha +``` + +{{< /tab >}} + +{{< tab "➕ WAHA Plus" >}} +If you got the +[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) +, use the following commands: + +```bash +docker login -u devlikeapro -p {KEY} +docker pull devlikeapro/waha-plus +docker logout +``` + +👉 Go to +[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) +to generate the command with the right version. +{{< /tab >}} + +{{< tab "WAHA (ARM)" >}} +If you're using ARM (like Apple M1/M2, Raspberry Pi etc.) - use following commands to download the image: + +```bash +# Download the image +docker pull devlikeapro/waha:arm +# Rename it, so you can use devlikeapro/waha image in other place +docker tag devlikeapro/waha:arm devlikeapro/waha +``` + +If you got the +[➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) +, use the following commands: + +```bash +docker login -u devlikeapro -p {KEY} +docker pull devlikeapro/waha-plus:arm +docker logout + +# Rename it, so you can use devlikeapro/waha image in other place +docker tag devlikeapro/waha-plus:arm devlikeapro/waha-plus +``` + +👉 Go to +[**Docker Image Configurator**](https://portal.devlike.pro/docker-image) +to generate the command with the right version. +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/install/index.md b/content/docs/how-to/install/index.md index 0bd9852ca..419810696 100644 --- a/content/docs/how-to/install/index.md +++ b/content/docs/how-to/install/index.md @@ -1,441 +1,467 @@ ---- -title : "🔧 Install & Update" -description: "How to install and update WAHA" -lead: "How to install and update WAHA" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 201 -slug: install -images: ["install.jpg"] -aliases: - - /docs/how-to/install-update ---- - -You probably already have run the docker run command during -[**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) guide: -```bash -docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha -``` - -{{< callout context="caution" icon="outline/alert-triangle" >}} -☝️ The above command is good **for development purposes**, but **not for production**. -{{< /callout >}} - -To make it **production-ready**, you need to configure a few more parameters to make it secure, reliable, and easy to manage. - - -{{< callout context="note" icon="outline/info-circle" >}} -If you wish to follow a **Step-By-Step guide** which shows you **how to send your first message** via HTTP API, -please go to [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). -{{< /callout >}} - -{{< callout context="tip" icon="outline/info-circle" title="WAHA Apps">}} - -If you want to use -[**🧩 Apps**]({{< relref "/docs/apps/about" >}}), such as -[**ChatWoot**]({{< relref "/docs/apps/chatwoot" >}}), -please follow the specific installation and configuration guides provided for each app: - -- [**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) - -{{< /callout >}} - - -## Requirements -### System Requirements -You can use any operating system for host system (**Linux**, **Windows** or **macOS**) -as long as you have Docker installed, and it can run **Linux** containers. - -💡 We recommend using **Linux** with **Debian** or **Ubuntu** based distributions. - -We strongly recommend using VPS or servers with minimum **2CPU and 2GB RAM** configuration for the project -even for a single session. -If you want to host more sessions - please check the numbers in -[**FAQ**]({{< relref "/docs/overview/faq#system-requirements" >}}). - -{{< details "Linux" >}} -👉 We suggest using **Debian** or **Ubuntu** based distributions. -{{< /details >}} - -{{< details "Windows" >}} -👉 For **Windows** we kindly suggest using **Hyper-V** backend for -[Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)! - -It might not work with **WSL2** backend properly. -{{< /details >}} - -{{< include file="content/docs/how-to/install/-the-hosting.md" >}} - - -### Pre-requisites -Before proceeding, make sure you have the latest version of `docker` and `docker compose` installed. - -We recommend using Docker version equal to or higher than the following: - -```bash -$ docker --version -Docker version 26.1.3, build b72abbb -$ docker compose version -Docker Compose version v2.27.0 -``` - -{{< details "Why Docker?" >}} -**Docker** makes it easy to ship **all-in-one solution** with the runtime and dependencies. -You don't have to worry about language-specific libraries or chrome installation. - -Also, Docker makes installation and update processes so simple, just one command! -{{< /details >}} - -{{< details "Why Docker Compose?" >}} -**Docker Compose** is a tool for defining and running Docker applications. -With Compose, you use a YAML file to configure your application's services. -Then, with a single command, you create and start all the services from your configuration. -{{< /details >}} - -## Install - -### Docker - -1. Install Docker on your VM -```bash -# example in ubuntu -apt-get update -apt-get upgrade -curl -fsSL https://get.docker.com -o get-docker.sh -sudo sh get-docker.sh -apt install docker-compose-plugin -``` - -### Pull Image - -Follow the instructions below: -{{< include file="content/docs/how-to/install/download-image.md" >}} - -### WAHA -2. Download the required files -```bash -# Download the env file template -wget -O .env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/.env.example -# Download the Docker compose template -wget -O docker-compose.yaml https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose.yaml -``` - -3. Tweak the `.env` and `docker-compose.yaml` according to your preferences. -Refer to the available environment variables in [**⚙️ Configuration**]({{< relref "/docs/how-to/config" >}}). - -Some important environment variables you **MUST** change: -- `WAHA_API_KEY=sha512:{SHA512_HEX_OF_YOUR_API_KEY_HERE}` - - Default Api Key is `admin` - - Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) -- `WAHA_DASHBOARD_USERNAME=admin` - [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) -- `WAHA_DASHBOARD_PASSWORD=admin` -- `WHATSAPP_SWAGGER_USERNAME=admin` - you can set the same as `WAHA_DASHBOARD_USERNAME` -- `WHATSAPP_SWAGGER_PASSWORD=admin` - you can set the same as `WAHA_DASHBOARD_PASSWORD` - -```bash -# update .env file with your values -nano .env -# update docker-compose.yaml - like image -# Remove "mongodb" and "minio" services if you don't need them -# Leave "waha" service as it is -nano docker-compose.yaml -``` - -{{< callout context="danger" title="Do Not Use Default API Keys or Passwords!" icon="outline/shield-check" >}} - -Even if you're running WAHA on a private server and think the IP is unknown - it's -straightforward for attackers to find and exploit it to send spam or abuse your WhatsApp sessions. - -Always set strong, random values (see a guide below) for: -- `WAHA_API_KEY` -- `WAHA_DASHBOARD_PASSWORD` -- `WHATSAPP_SWAGGER_PASSWORD` - you can the same as for `WAHA_DASHBOARD_PASSWORD` - -**👉 How to Generate and Hash Api-Key** -{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} - -{{< /callout >}} - - -4. Get the service up and running. -```bash -docker compose up -d -``` - -5. Your WAHA installation is complete. -Please note that the **containers are not exposed to the internet**, and they only bind to the **localhost**. -Set up something like Nginx or any other proxy server to proxy the requests to the container. - -{{< callout context="" title="How to export port from remote server?" icon="outline/info-circle" >}} -If you're using a remote server (like VPS or Virtual Machine on your laptop) you need to allow access for your browser. -Use one of the options available. - -1. Use **SSH tunneling** - -If you're connecting to ssh, you can forward port 3000 on your laptop like -```bash -ssh -L 3000:localhost:3000 user@you.address.here -``` - -2. **Bind port to all ips** - -For **temporary external access**, you can change the port binding from `127.0.0.1:3000:3000` to `3000:3000` in the `docker-compose.yaml` file. -```yaml { title="docker-compose.yaml" } -services: - waha: - image: devlikeapro/waha-plus - ports: - - "3000:3000" -``` -```bash -docker compose up -d -``` - -This makes your instance accessible at `http://:3000`. -{{< /callout >}} - -6. Now, open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) and login with the credentials you've set - -By default you can use: -- Dashboard - `admin/admin` -- Swagger - `admin/admin` -- Api Key - `admin` - -### Nginx - -👉 Replace **** with your domain name in the following steps (use lowercase). - -1. Configure Nginx to serve as a frontend proxy. -```bash -sudo apt-get install nginx -cd /etc/nginx/sites-enabled - -nano .conf -``` - -2. Use the following Nginx config and **replace** the `` in `server_name`. -```nginx -server { - server_name ; - - # Point upstream to WAHA Server - set $upstream 127.0.0.1:3000; - - location /.well-known { - alias /var/www/ssl-proof/waha/.well-known; - } - - location / { - proxy_pass_header Authorization; - proxy_pass http://$upstream; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Ssl on; # Optional - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_buffering off; - - client_max_body_size 0; - proxy_read_timeout 36000s; - proxy_redirect off; - } - listen 80; -} -``` - -3. Verify and reload your Nginx config by running the following command. -```bash -nginx -t -systemctl reload nginx -``` - -Here are two scenarios for setting up HTTPS: - -### HTTPS - Let's Encrypt - -If you have a domain name (e.g., **yourdomain.com**) that points to your server's IP address, you can use Let's Encrypt to get free, trusted SSL certificates: - -1. Run Let's Encrypt to configure SSL certificate. (replace ****!) -```bash -apt install certbot -apt-get install python3-certbot-nginx - -mkdir -p /var/www/ssl-proof/waha/.well-known -certbot --webroot -w /var/www/ssl-proof/waha/ -d -i nginx -``` - -2. Your WAHA installation should be accessible from the https://yourdomain.com now. -3. Change `WAHA_BASE_URL=https://` in the `.env` file and restart the WAHA service -```bash -# Change the WAHA_BASE_URL in .env -nano .env -# Restart the WAHA service -docker compose up -d -docker compose restart -``` - -### HTTPS - Self-Signed Certificate - -We recommend using **Let's Encrypt** free certificate if you have public IP and DNS name. - -However, if you don't have **a domain name** or -are using a **private IP address**, you can create a self-signed certificate for IP-based access, -expand the details below: - -{{< details "**HTTPS - Setup Self-Signed Certificate**" >}} - -1. Create a directory for your SSL certificates: -```bash -mkdir -p /etc/nginx/ssl -cd /etc/nginx/ssl -``` - -2. Create a configuration file for the self-signed certificate: -```bash -cat > ip-cert.cnf << 'EOL' -[req] -default_bits = 2048 -prompt = no -default_md = sha256 -distinguished_name = dn -x509_extensions = v3_ca - -[dn] -C=US -ST=State -L=City -O=Organization -OU=Department -CN= - -[v3_ca] -subjectAltName = @alt_names - -[alt_names] -IP.1 = -EOL -``` - -3. Generate a self-signed certificate valid for 10 years (3650 days): -```bash -openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout ip-cert.key -out ip-cert.crt -config ip-cert.cnf -``` - -4. Update your Nginx configuration to use the self-signed certificate: -```bash -cd /etc/nginx/sites-enabled -nano .conf -``` - -5. Modify your Nginx configuration to include SSL settings: -```nginx -server { - listen 80; - server_name ; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - server_name ; - - ssl_certificate /etc/nginx/ssl/ip-cert.crt; - ssl_certificate_key /etc/nginx/ssl/ip-cert.key; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_prefer_server_ciphers on; - - # Point upstream to WAHA Server - set $upstream 127.0.0.1:3000; - - location / { - proxy_pass_header Authorization; - proxy_pass http://$upstream; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Ssl on; # Optional - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_buffering off; - - client_max_body_size 0; - proxy_read_timeout 36000s; - proxy_redirect off; - } -} -``` - -6. Verify and reload your Nginx config: -```bash -nginx -t -systemctl reload nginx -``` - -7. Update your WAHA configuration to use HTTPS: -```bash -# Change the WAHA_BASE_URL in .env to use https -nano .env -# Add or modify: WAHA_BASE_URL=https:// -# Restart the WAHA service -docker compose up -d -docker compose restart -``` - -8. When accessing your WAHA instance, you'll need to accept the self-signed certificate warning in your browser. - -{{< /details >}} - -## Update -When there's a new version of WAHA, you can update it with these simple commands: - -[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) image: -```bash -# Login if you're using WAHA Plus -docker login -u devlikeapro -p {KEY} -docker compose pull -docker logout - -docker compose up -d -``` - -👉 If you specified exact version in `docker-compose.yml`, like -```yaml -image: devlikeapro/waha-plus:latest-2024.7.8 -``` - -remember to change it to `latest-{YEAR}.{MONTH}.{BUILD}` to get the latest version. - - -**WAHA Core** image: -```bash -docker compose pull -docker compose up -d -``` - -## Get logs, restart, stop -```bash -# Stop all containers -docker compose down -# Start all containers, apply new configuration -docker compose up -d -# Restart all containers -docker compose restart -# Show logs in real time -docker compose logs -f -# Show logs - since interval -docker compose logs --since 1h -``` - -## What's next? - -{{< include file="content/docs/overview/quick-start/links.md" >}} +--- +title: "🔧 Install & Update" +description: "How to install and update WAHA" +lead: "How to install and update WAHA" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 201 +slug: install +images: ["install.jpg"] +aliases: + - /docs/how-to/install-update +--- + +You probably already have run the docker run command during +[**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) guide: + +```bash +docker run -it --rm -p 3000:3000 --name waha devlikeapro/waha +``` + +{{< callout context="caution" icon="outline/alert-triangle" >}} +☝️ The above command is good **for development purposes**, but **not for production**. +{{< /callout >}} + +To make it **production-ready**, you need to configure a few more parameters to make it secure, reliable, and easy to manage. + +{{< callout context="note" icon="outline/info-circle" >}} +If you wish to follow a **Step-By-Step guide** which shows you **how to send your first message** via HTTP API, +please go to [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). +{{< /callout >}} + +{{< callout context="tip" icon="outline/info-circle" title="WAHA Apps">}} + +If you want to use +[**🧩 Apps**]({{< relref "/docs/apps/about" >}}), such as +[**ChatWoot**]({{< relref "/docs/apps/chatwoot" >}}), +please follow the specific installation and configuration guides provided for each app: + +- [**WhatsApp + ChatWoot - Installation Guide**]({{< relref "/blog/apps-chatwoot-1-install" >}}) + +{{< /callout >}} + +## Requirements + +### System Requirements + +You can use any operating system for host system (**Linux**, **Windows** or **macOS**) +as long as you have Docker installed, and it can run **Linux** containers. + +💡 We recommend using **Linux** with **Debian** or **Ubuntu** based distributions. + +We strongly recommend using VPS or servers with minimum **2CPU and 2GB RAM** configuration for the project +even for a single session. +If you want to host more sessions - please check the numbers in +[**FAQ**]({{< relref "/docs/overview/faq#system-requirements" >}}). + +{{< details "Linux" >}} +👉 We suggest using **Debian** or **Ubuntu** based distributions. +{{< /details >}} + +{{< details "Windows" >}} +👉 For **Windows** we kindly suggest using **Hyper-V** backend for +[Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)! + +It might not work with **WSL2** backend properly. +{{< /details >}} + +{{< include file="content/docs/how-to/install/-the-hosting.md" >}} + +### Pre-requisites + +Before proceeding, make sure you have the latest version of `docker` and `docker compose` installed. + +We recommend using Docker version equal to or higher than the following: + +```bash +$ docker --version +Docker version 26.1.3, build b72abbb +$ docker compose version +Docker Compose version v2.27.0 +``` + +{{< details "Why Docker?" >}} +**Docker** makes it easy to ship **all-in-one solution** with the runtime and dependencies. +You don't have to worry about language-specific libraries or chrome installation. + +Also, Docker makes installation and update processes so simple, just one command! +{{< /details >}} + +{{< details "Why Docker Compose?" >}} +**Docker Compose** is a tool for defining and running Docker applications. +With Compose, you use a YAML file to configure your application's services. +Then, with a single command, you create and start all the services from your configuration. +{{< /details >}} + +## Install + +### Docker + +1. Install Docker on your VM + +```bash +# example in ubuntu +apt-get update +apt-get upgrade +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +apt install docker-compose-plugin +``` + +### Pull Image + +Follow the instructions below: +{{< include file="content/docs/how-to/install/download-image.md" >}} + +### WAHA + +2. Download the required files + +```bash +# Download the env file template +wget -O .env https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/.env.example +# Download the Docker compose template +wget -O docker-compose.yaml https://raw.githubusercontent.com/devlikeapro/waha/refs/heads/core/docker-compose.yaml +``` + +3. Tweak the `.env` and `docker-compose.yaml` according to your preferences. + Refer to the available environment variables in [**⚙️ Configuration**]({{< relref "/docs/how-to/config" >}}). + +Some important environment variables you **MUST** change: + +- `WAHA_API_KEY=sha512:{SHA512_HEX_OF_YOUR_API_KEY_HERE}` + - Default Api Key is `admin` + - Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) +- `WAHA_DASHBOARD_USERNAME=admin` - [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) +- `WAHA_DASHBOARD_PASSWORD=admin` +- `WHATSAPP_SWAGGER_USERNAME=admin` - you can set the same as `WAHA_DASHBOARD_USERNAME` +- `WHATSAPP_SWAGGER_PASSWORD=admin` - you can set the same as `WAHA_DASHBOARD_PASSWORD` + +```bash +# update .env file with your values +nano .env +# update docker-compose.yaml - like image +# Remove "mongodb" and "minio" services if you don't need them +# Leave "waha" service as it is +nano docker-compose.yaml +``` + +{{< callout context="danger" title="Do Not Use Default API Keys or Passwords!" icon="outline/shield-check" >}} + +Even if you're running WAHA on a private server and think the IP is unknown - it's +straightforward for attackers to find and exploit it to send spam or abuse your WhatsApp sessions. + +Always set strong, random values (see a guide below) for: + +- `WAHA_API_KEY` +- `WAHA_DASHBOARD_PASSWORD` +- `WHATSAPP_SWAGGER_PASSWORD` - you can the same as for `WAHA_DASHBOARD_PASSWORD` + +**👉 How to Generate and Hash Api-Key** +{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} + +{{< /callout >}} + +4. Get the service up and running. + +```bash +docker compose up -d +``` + +5. Your WAHA installation is complete. + Please note that the **containers are not exposed to the internet**, and they only bind to the **localhost**. + Set up something like Nginx or any other proxy server to proxy the requests to the container. + +{{< callout context="" title="How to export port from remote server?" icon="outline/info-circle" >}} +If you're using a remote server (like VPS or Virtual Machine on your laptop) you need to allow access for your browser. +Use one of the options available. + +1. Use **SSH tunneling** + +If you're connecting to ssh, you can forward port 3000 on your laptop like + +```bash +ssh -L 3000:localhost:3000 user@you.address.here +``` + +2. **Bind port to all ips** + +For **temporary external access**, you can change the port binding from `127.0.0.1:3000:3000` to `3000:3000` in the `docker-compose.yaml` file. + +```yaml { title="docker-compose.yaml" } +services: + waha: + image: devlikeapro/waha-plus + ports: + - "3000:3000" +``` + +```bash +docker compose up -d +``` + +This makes your instance accessible at `http://:3000`. +{{< /callout >}} + +6. Now, open [http://localhost:3000/dashboard](http://localhost:3000/dashboard) and login with the credentials you've set + +By default you can use: + +- Dashboard - `admin/admin` +- Swagger - `admin/admin` +- Api Key - `admin` + +### Nginx + +👉 Replace **** with your domain name in the following steps (use lowercase). + +1. Configure Nginx to serve as a frontend proxy. + +```bash +sudo apt-get install nginx +cd /etc/nginx/sites-enabled + +nano .conf +``` + +2. Use the following Nginx config and **replace** the `` in `server_name`. + +```nginx +server { + server_name ; + + # Point upstream to WAHA Server + set $upstream 127.0.0.1:3000; + + location /.well-known { + alias /var/www/ssl-proof/waha/.well-known; + } + + location / { + proxy_pass_header Authorization; + proxy_pass http://$upstream; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Ssl on; # Optional + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_http_version 1.1; + proxy_buffering off; + + client_max_body_size 0; + proxy_read_timeout 36000s; + proxy_redirect off; + } + listen 80; +} +``` + +3. Verify and reload your Nginx config by running the following command. + +```bash +nginx -t +systemctl reload nginx +``` + +Here are two scenarios for setting up HTTPS: + +### HTTPS - Let's Encrypt + +If you have a domain name (e.g., **yourdomain.com**) that points to your server's IP address, you can use Let's Encrypt to get free, trusted SSL certificates: + +1. Run Let's Encrypt to configure SSL certificate. (replace ****!) + +```bash +apt install certbot +apt-get install python3-certbot-nginx + +mkdir -p /var/www/ssl-proof/waha/.well-known +certbot --webroot -w /var/www/ssl-proof/waha/ -d -i nginx +``` + +2. Your WAHA installation should be accessible from the https://yourdomain.com now. +3. Change `WAHA_BASE_URL=https://` in the `.env` file and restart the WAHA service + +```bash +# Change the WAHA_BASE_URL in .env +nano .env +# Restart the WAHA service +docker compose up -d +docker compose restart +``` + +### HTTPS - Self-Signed Certificate + +We recommend using **Let's Encrypt** free certificate if you have public IP and DNS name. + +However, if you don't have **a domain name** or +are using a **private IP address**, you can create a self-signed certificate for IP-based access, +expand the details below: + +{{< details "**HTTPS - Setup Self-Signed Certificate**" >}} + +1. Create a directory for your SSL certificates: + +```bash +mkdir -p /etc/nginx/ssl +cd /etc/nginx/ssl +``` + +2. Create a configuration file for the self-signed certificate: + +```bash +cat > ip-cert.cnf << 'EOL' +[req] +default_bits = 2048 +prompt = no +default_md = sha256 +distinguished_name = dn +x509_extensions = v3_ca + +[dn] +C=US +ST=State +L=City +O=Organization +OU=Department +CN= + +[v3_ca] +subjectAltName = @alt_names + +[alt_names] +IP.1 = +EOL +``` + +3. Generate a self-signed certificate valid for 10 years (3650 days): + +```bash +openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout ip-cert.key -out ip-cert.crt -config ip-cert.cnf +``` + +4. Update your Nginx configuration to use the self-signed certificate: + +```bash +cd /etc/nginx/sites-enabled +nano .conf +``` + +5. Modify your Nginx configuration to include SSL settings: + +```nginx +server { + listen 80; + server_name ; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name ; + + ssl_certificate /etc/nginx/ssl/ip-cert.crt; + ssl_certificate_key /etc/nginx/ssl/ip-cert.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + # Point upstream to WAHA Server + set $upstream 127.0.0.1:3000; + + location / { + proxy_pass_header Authorization; + proxy_pass http://$upstream; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Ssl on; # Optional + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_http_version 1.1; + proxy_buffering off; + + client_max_body_size 0; + proxy_read_timeout 36000s; + proxy_redirect off; + } +} +``` + +6. Verify and reload your Nginx config: + +```bash +nginx -t +systemctl reload nginx +``` + +7. Update your WAHA configuration to use HTTPS: + +```bash +# Change the WAHA_BASE_URL in .env to use https +nano .env +# Add or modify: WAHA_BASE_URL=https:// +# Restart the WAHA service +docker compose up -d +docker compose restart +``` + +8. When accessing your WAHA instance, you'll need to accept the self-signed certificate warning in your browser. + +{{< /details >}} + +## Update + +When there's a new version of WAHA, you can update it with these simple commands: + +[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) image: + +```bash +# Login if you're using WAHA Plus +docker login -u devlikeapro -p {KEY} +docker compose pull +docker logout + +docker compose up -d +``` + +👉 If you specified exact version in `docker-compose.yml`, like + +```yaml +image: devlikeapro/waha-plus:latest-2024.7.8 +``` + +remember to change it to `latest-{YEAR}.{MONTH}.{BUILD}` to get the latest version. + +**WAHA Core** image: + +```bash +docker compose pull +docker compose up -d +``` + +## Get logs, restart, stop + +```bash +# Stop all containers +docker compose down +# Start all containers, apply new configuration +docker compose up -d +# Restart all containers +docker compose restart +# Show logs in real time +docker compose logs -f +# Show logs - since interval +docker compose logs --since 1h +``` + +## What's next? + +{{< include file="content/docs/overview/quick-start/links.md" >}} diff --git a/content/docs/how-to/labels/features-events.md b/content/docs/how-to/labels/features-events.md index fc39c4c6b..de27661bb 100644 --- a/content/docs/how-to/labels/features-events.md +++ b/content/docs/how-to/labels/features-events.md @@ -1,11 +1,11 @@ -
-{{< details "**🏷️ Labels - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|----------------------|-------|-------|:-----| -| `label.upsert` | | ✔️ | ✔️ | -| `label.deleted` | | ✔️ | ✔️ | -| `label.chat.added` | | ✔️ | ✔️ | -| `label.chat.deleted` | | ✔️ | ✔️ | - -{{< /details >}} +
+{{< details "**🏷️ Labels - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| -------------------- | ----- | ----- | :--- | +| `label.upsert` | | ✔️ | ✔️ | +| `label.deleted` | | ✔️ | ✔️ | +| `label.chat.added` | | ✔️ | ✔️ | +| `label.chat.deleted` | | ✔️ | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/labels/features.md b/content/docs/how-to/labels/features.md index b5f7f6eb0..f2f798f34 100644 --- a/content/docs/how-to/labels/features.md +++ b/content/docs/how-to/labels/features.md @@ -1,16 +1,16 @@ -
-{{< details "**🏷️ Labels - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|--------------------------------------------------------------------------|-------|-------|:-----| -| **Get labels**
`GET /api/{session}/labels` | ✔️ | ✔️ | ✔️ | -| **Create label**
`POST /api/{session}/labels` | ✔️ | ✔️ | ✔️ | -| **Update label**
`PUT /api/{session}/labels/{labelId}` | ✔️ | ✔️ | ✔️ | -| **Delete label**
`DELETE /api/{session}/labels/{labelId}` | ✔️ | ✔️ | ✔️ | -| **Get chats by label id**
`GET /api/{session}/labels/{labelId}/chats` | ✔️ | ✔️ | ✔️ | -| **Get labels by chat id**
`GET /api/{session}/labels/chats/{chatId}/` | ✔️ | ✔️ | ✔️ | -| **PUT labels to chat**
`PUT /api/{session}/labels/chats/{chatId}/` | ✔️ | ✔️ | ✔️ | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**🏷️ Labels - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------------------------------ | ----- | ----- | :--- | +| **Get labels**
`GET /api/{session}/labels` | ✔️ | ✔️ | ✔️ | +| **Create label**
`POST /api/{session}/labels` | ✔️ | ✔️ | ✔️ | +| **Update label**
`PUT /api/{session}/labels/{labelId}` | ✔️ | ✔️ | ✔️ | +| **Delete label**
`DELETE /api/{session}/labels/{labelId}` | ✔️ | ✔️ | ✔️ | +| **Get chats by label id**
`GET /api/{session}/labels/{labelId}/chats` | ✔️ | ✔️ | ✔️ | +| **Get labels by chat id**
`GET /api/{session}/labels/chats/{chatId}/` | ✔️ | ✔️ | ✔️ | +| **PUT labels to chat**
`PUT /api/{session}/labels/chats/{chatId}/` | ✔️ | ✔️ | ✔️ | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/labels/index.md b/content/docs/how-to/labels/index.md index 1f17450bb..7d4051af2 100644 --- a/content/docs/how-to/labels/index.md +++ b/content/docs/how-to/labels/index.md @@ -1,263 +1,270 @@ ---- -title: "🏷️ Labels" -description: "Labels (available in WhatsApp Business)" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 292 -images: [ "whatsapp-labels.png" ] -slug: labels ---- - -You can work with [WhatsApp Labels](https://faq.whatsapp.com/3398508707096369/?cms_platform=android) -available in **WhatsApp Business** using the API! - -
-{{< img lqip="21x webp q20" src="whatsapp-labels.png" alt="WhatsApp Labels" >}} -
- -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/labels/features.md" >}} - -{{< include file="content/docs/how-to/labels/features-events.md" >}} - -## Label color -You'll see two color-related fields in the body and response: -- `color: 1` - internal color number, `0-19` values. -- `colorHex: #64c4ff` - is the **latest known** hex color for the label - - -⚠️ It's possible that `color` - `colorHex` map will be changed, so consider using `color` value instead -when creating or updating labels. - -Here's the **current** color map (`color` - `colorHex` - **preview**): -- `0` - `#ff9485` - -- `1` - `#64c4ff` - -- `2` - `#ffd429` - -- `3` - `#dfaef0` - -- `4` - `#99b6c1` - -- `5` - `#55ccb3` - -- `6` - `#ff9dff` - -- `7` - `#d3a91d` - -- `8` - `#6d7cce` - -- `9` - `#d7e752` - -- `10` - `#00d0e2` - -- `11` - `#ffc5c7` - -- `12` - `#93ceac` - -- `13` - `#f74848` - -- `14` - `#00a0f2` - -- `15` - `#83e422` - -- `16` - `#ffaf04` - -- `17` - `#b5ebff` - -- `18` - `#9ba6ff` - -- `19` - `#9368cf` - - - -## API - -### Get labels - -You can get a list of labels for the session using the endpoint: - -```http request -GET /api/{session}/labels -``` - -```json { title="Response" } -[ - { - "id": "1", - "name": "New Client", - "color": 1, - "colorHex": "#64c4ff" - }, - ... -] -``` - -### Create label - -```http request -POST /api/{session}/labels -``` - -Using `color` -```json { title="Body" } -{ - "name": "New Client", - "color": 1 -} -``` - -Using `colorHex` -```json { title="Body" } -{ - "name": "New Client", - "colorHex" : "#64c4ff" -} -``` - -### Update label -```http request -PUT /api/{session}/labels/{labelId} -``` - -Using `color` -```json { title="Body" } -{ - "name": "New Client", - "color": 1 -} -``` - -Using `colorHex` -```json { title="Body" } -{ - "name": "New Client", - "colorHex" : "#64c4ff" -} -``` - -### Delete label -```http request -DELETE /api/{session}/labels/{labelId} -``` - -### Get chats by label id - -You can get a list of chats by label id using the endpoint: - -```http request -GET /api/{session}/labels/{labelId}/chats -``` - -ℹ️ The response format currently depends on the -[**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) -you're using, -similar to how it works with -[**💬 Chats**]({{< relref "/docs/how-to/chats" >}}) - -### Get labels by chat id - -You can get a list of labels by chat id using the endpoint: - -```http request -GET /api/{session}/labels/chats/{chatId}/ -``` - -```json { title="Response" } -[ - { - "id": "1", - "name": "New Client", - "color": 1, - "colorHex": "#64c4ff" - }, - ... -] -``` - -### Update labels to chat - -```http request -PUT /api/{session}/labels/chats/{chatId}/ -``` - -**Upsert label**: - -👉 You need to provide **the full list of labels** you want to set to the chat. All other labels will be removed. - -```json { title="Body" } -{ - "labels": [ - { - "id": "1" - } - ] -} -``` - -**Remove labels**: - -```json { title="Body" } -{ - "labels": [] -} - -``` - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### label.upsert - -```json { title="label.upsert" } -{ - "event": "label.upsert", - "session": "default", - "payload": { - "id": "10", - "name": "Label Name", - "color": 14, - "colorHex": "#00a0f2" - }, - "engine": "NOWEB", - ... -} - -``` - -### label.deleted - -```json { title="label.deleted" } -{ - "event": "label.deleted", - "session": "default", - "payload": { - "id": "10", - "name": "", - "color": 14, - "colorHex": "#00a0f2" - }, - "engine": "NOWEB", - ... -} - -``` - -### label.chat.added - -```json { title="label.chat.added" } -{ - "event": "label.chat.added", - "session": "default", - "payload": { - "labelId": "6", - "chatId": "11111111111@c.us", - "label": null // Note: This can be null right after scanning QR code - }, - "engine": "NOWEB", - ... -} -``` - -### label.chat.deleted - -```json { title="label.chat.deleted" } -{ - "event": "label.chat.deleted", - "session": "default", - "payload": { - "labelId": "6", - "chatId": "11111111111@c.us", - "label": null - }, - "engine": "NOWEB", - ... -} -``` +--- +title: "🏷️ Labels" +description: "Labels (available in WhatsApp Business)" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 292 +images: ["whatsapp-labels.png"] +slug: labels +--- + +You can work with [WhatsApp Labels](https://faq.whatsapp.com/3398508707096369/?cms_platform=android) +available in **WhatsApp Business** using the API! + +
+{{< img lqip="21x webp q20" src="whatsapp-labels.png" alt="WhatsApp Labels" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/labels/features.md" >}} + +{{< include file="content/docs/how-to/labels/features-events.md" >}} + +## Label color + +You'll see two color-related fields in the body and response: + +- `color: 1` - internal color number, `0-19` values. +- `colorHex: #64c4ff` - is the **latest known** hex color for the label + +⚠️ It's possible that `color` - `colorHex` map will be changed, so consider using `color` value instead +when creating or updating labels. + +Here's the **current** color map (`color` - `colorHex` - **preview**): + +- `0` - `#ff9485` - +- `1` - `#64c4ff` - +- `2` - `#ffd429` - +- `3` - `#dfaef0` - +- `4` - `#99b6c1` - +- `5` - `#55ccb3` - +- `6` - `#ff9dff` - +- `7` - `#d3a91d` - +- `8` - `#6d7cce` - +- `9` - `#d7e752` - +- `10` - `#00d0e2` - +- `11` - `#ffc5c7` - +- `12` - `#93ceac` - +- `13` - `#f74848` - +- `14` - `#00a0f2` - +- `15` - `#83e422` - +- `16` - `#ffaf04` - +- `17` - `#b5ebff` - +- `18` - `#9ba6ff` - +- `19` - `#9368cf` - + +## API + +### Get labels + +You can get a list of labels for the session using the endpoint: + +```http request +GET /api/{session}/labels +``` + +```json { title="Response" } +[ + { + "id": "1", + "name": "New Client", + "color": 1, + "colorHex": "#64c4ff" + }, + ... +] +``` + +### Create label + +```http request +POST /api/{session}/labels +``` + +Using `color` + +```json { title="Body" } +{ + "name": "New Client", + "color": 1 +} +``` + +Using `colorHex` + +```json { title="Body" } +{ + "name": "New Client", + "colorHex": "#64c4ff" +} +``` + +### Update label + +```http request +PUT /api/{session}/labels/{labelId} +``` + +Using `color` + +```json { title="Body" } +{ + "name": "New Client", + "color": 1 +} +``` + +Using `colorHex` + +```json { title="Body" } +{ + "name": "New Client", + "colorHex": "#64c4ff" +} +``` + +### Delete label + +```http request +DELETE /api/{session}/labels/{labelId} +``` + +### Get chats by label id + +You can get a list of chats by label id using the endpoint: + +```http request +GET /api/{session}/labels/{labelId}/chats +``` + +ℹ️ The response format currently depends on the +[**🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) +you're using, +similar to how it works with +[**💬 Chats**]({{< relref "/docs/how-to/chats" >}}) + +### Get labels by chat id + +You can get a list of labels by chat id using the endpoint: + +```http request +GET /api/{session}/labels/chats/{chatId}/ +``` + +```json { title="Response" } +[ + { + "id": "1", + "name": "New Client", + "color": 1, + "colorHex": "#64c4ff" + }, + ... +] +``` + +### Update labels to chat + +```http request +PUT /api/{session}/labels/chats/{chatId}/ +``` + +**Upsert label**: + +👉 You need to provide **the full list of labels** you want to set to the chat. All other labels will be removed. + +```json { title="Body" } +{ + "labels": [ + { + "id": "1" + } + ] +} +``` + +**Remove labels**: + +```json { title="Body" } +{ + "labels": [] +} +``` + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### label.upsert + +```json { title="label.upsert" } +{ + "event": "label.upsert", + "session": "default", + "payload": { + "id": "10", + "name": "Label Name", + "color": 14, + "colorHex": "#00a0f2" + }, + "engine": "NOWEB", + ... +} + +``` + +### label.deleted + +```json { title="label.deleted" } +{ + "event": "label.deleted", + "session": "default", + "payload": { + "id": "10", + "name": "", + "color": 14, + "colorHex": "#00a0f2" + }, + "engine": "NOWEB", + ... +} + +``` + +### label.chat.added + +```json { title="label.chat.added" } +{ + "event": "label.chat.added", + "session": "default", + "payload": { + "labelId": "6", + "chatId": "11111111111@c.us", + "label": null // Note: This can be null right after scanning QR code + }, + "engine": "NOWEB", + ... +} +``` + +### label.chat.deleted + +```json { title="label.chat.deleted" } +{ + "event": "label.chat.deleted", + "session": "default", + "payload": { + "labelId": "6", + "chatId": "11111111111@c.us", + "label": null + }, + "engine": "NOWEB", + ... +} +``` diff --git a/content/docs/how-to/observability/index.md b/content/docs/how-to/observability/index.md index c6466ef4c..208e329d9 100644 --- a/content/docs/how-to/observability/index.md +++ b/content/docs/how-to/observability/index.md @@ -1,387 +1,393 @@ ---- -title: "🔍 Observability" -description: "Logging, monitoring, healthchecks, etc." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 299 -slug: observability ---- - -## Logging - -Options you can use to control how WAHA outputs logs: - -- `WAHA_LOG_FORMAT` - supports formats: - - `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format - - `WAHA_LOG_FORMAT=JSON` - can be useful if you're using a central logging management system -- `WAHA_LOG_LEVEL` - how much information to log `error | warn | info | debug | trace`. - - 👉 Do not set `debug` and `trace` in production, as these levels generate excessive log output. -- `WAHA_HTTP_LOG_LEVEL=info` - controls the level of `request completed` log (HTTP access). You can set it - to `error | warn | info | debug | trace`. -- `DEBUG=1` - you can set this environment variable as a shortcut for `WAHA_LOG_LEVEL=debug`, `DEBUG=1` overrides - the `WAHA_LOG_LEVEL` to `debug` if both defined. - -### Session logging - -You can enable debug mode for a session by setting the `config.debug` field to `true` when -[Starting a session]({{< relref "/docs/how-to/sessions#debug" >}}) - -This can be useful for debugging purposes when you're experiencing issues. - -```json -{ - "name": "default", - "config": { - "debug": true - } -} -``` - -## Ping - -Returns a simple response to check if the service is running. - -```http request -GET /ping -``` - -```json -{ - "message": "pong" -} -``` - -## Get server version - -Returns the version of the installed docker image. - -```http request -GET /api/server/version -``` - -```json -{ - "version": "2024.2.3", - "engine": "NOWEB", - "tier": "PLUS", - "browser": "/usr/bin/google-chrome-stable" -} -``` - -## Get server environment variables - -Returns the environment variables of the server. - -This endpoint returns only WAHA-related variables: - -```http request -GET /api/server/environment?all=false -``` - -```json -{ - "DEBUG": "1", - "WAHA_HTTP_LOG_LEVEL": "debug", - "WAHA_LOG_FORMAT": "PRETTY", - ... -} - -``` - -To return all environment variables: - -```http request -GET /api/server/environment?all=true -``` - -```json -{ - "DEBUG": "1", - "WAHA_HTTP_LOG_LEVEL": "debug", - "WAHA_LOG_FORMAT": "PRETTY", - "PATH": "/home/...", - ... -} - -``` - -## Get server status - -Returns the server status, start timestamp, and uptime. - -```http request -GET /api/server/status -``` - -```json -{ - "startTimestamp": 1723788847247, - "uptime": 3600000 -} -``` - -## Restart (stop) server - -You can stop the server by calling: - -```http request -POST /api/server/stop -``` - -```json -{ - // By default, it gracefully stops all sessions and connections, - // but you can force it to stop immediately - "force": false -} -``` -👉 If you're using Docker and followed the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide, -Docker will **automatically restart** the server, so you can use this endpoint to **reboot** the service. - - -## Health Check - -Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/waha-plus" >}}) -only. - -The health check endpoint is used to determine the health of the service. - -```http request -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 - -The health check monitors the following components: - -- 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" - } - } -} -``` - -## WAHA Debug Mode -If you enable `WAHA_DEBUG_MODE=True`, WAHA exposes a few additional features for helping with -troubleshooting (usually Memory and CPU-related issues). - -{{< callout context="caution" icon="outline/info-circle" >}} -`WAHA_DEBUG_MODE=True` is for **troubleshooting** purposes only -{{< /callout >}} - -### Get Node.js heapsnapshot -```http request -GET /api/server/debug/heapsnapshot -``` - -Creates and downloads a heap dump from Node.js. - -You can execute request in -[**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}), -then click on **Download File**: - -![Swagger - Download File](swagger-download-file.png) - -### Get Browser Trace -```http request -GET /api/server/debug/browser/trace/{SESSION}?seconds=30&categories=%2A -``` -Get **browser's trace** (uses [puppeteer](https://pptr.dev/api/puppeteer.tracing)) -which you can open in Chrome Dev Tool -([chrome://tracing](chrome://tracing)) -or -[https://trace.cafe/](https://trace.cafe/). - -**Query Parameters:** -- `seconds` - how many seconds to trace -- `categories` - categories to trace - -{{< callout context="tip" icon="outline/alert-square-rounded" >}} -- 👉 Only one trace can be active at a time per browser. -- ⌛ It takes `SECONDS` seconds to generate the trace file, please be patient 🐢 -{{< /callout >}} - -You can execute request in -[**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}), -then click on **Download File**: - -![Swagger - Download File](swagger-download-file.png) - - -### GOWS pprof - -You can expose the `6060` port and connect using pprof for the **GOWS** engine: - -```bash -go tool pprof -http=:8081 http://localhost:6060/debug/pprof/heap -``` - -Make sure to add it to docker-compose: -```yaml -services: - waha: - image: devlikeapro/waha-plus - ports: - - "127.0.0.1:6060:6060" -``` +--- +title: "🔍 Observability" +description: "Logging, monitoring, healthchecks, etc." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 299 +slug: observability +--- + +## Logging + +Options you can use to control how WAHA outputs logs: + +- `WAHA_LOG_FORMAT` - supports formats: + - `WAHA_LOG_FORMAT=PRETTY` - good for local development, **default** format + - `WAHA_LOG_FORMAT=JSON` - can be useful if you're using a central logging management system +- `WAHA_LOG_LEVEL` - how much information to log `error | warn | info | debug | trace`. + - 👉 Do not set `debug` and `trace` in production, as these levels generate excessive log output. +- `WAHA_HTTP_LOG_LEVEL=info` - controls the level of `request completed` log (HTTP access). You can set it + to `error | warn | info | debug | trace`. +- `DEBUG=1` - you can set this environment variable as a shortcut for `WAHA_LOG_LEVEL=debug`, `DEBUG=1` overrides + the `WAHA_LOG_LEVEL` to `debug` if both defined. + +### Session logging + +You can enable debug mode for a session by setting the `config.debug` field to `true` when +[Starting a session]({{< relref "/docs/how-to/sessions#debug" >}}) + +This can be useful for debugging purposes when you're experiencing issues. + +```json +{ + "name": "default", + "config": { + "debug": true + } +} +``` + +## Ping + +Returns a simple response to check if the service is running. + +```http request +GET /ping +``` + +```json +{ + "message": "pong" +} +``` + +## Get server version + +Returns the version of the installed docker image. + +```http request +GET /api/server/version +``` + +```json +{ + "version": "2024.2.3", + "engine": "NOWEB", + "tier": "PLUS", + "browser": "/usr/bin/google-chrome-stable" +} +``` + +## Get server environment variables + +Returns the environment variables of the server. + +This endpoint returns only WAHA-related variables: + +```http request +GET /api/server/environment?all=false +``` + +```json +{ + "DEBUG": "1", + "WAHA_HTTP_LOG_LEVEL": "debug", + "WAHA_LOG_FORMAT": "PRETTY", + ... +} + +``` + +To return all environment variables: + +```http request +GET /api/server/environment?all=true +``` + +```json +{ + "DEBUG": "1", + "WAHA_HTTP_LOG_LEVEL": "debug", + "WAHA_LOG_FORMAT": "PRETTY", + "PATH": "/home/...", + ... +} + +``` + +## Get server status + +Returns the server status, start timestamp, and uptime. + +```http request +GET /api/server/status +``` + +```json +{ + "startTimestamp": 1723788847247, + "uptime": 3600000 +} +``` + +## Restart (stop) server + +You can stop the server by calling: + +```http request +POST /api/server/stop +``` + +```json +{ + // By default, it gracefully stops all sessions and connections, + // but you can force it to stop immediately + "force": false +} +``` + +👉 If you're using Docker and followed the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide, +Docker will **automatically restart** the server, so you can use this endpoint to **reboot** the service. + +## Health Check + +Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/waha-plus" >}}) +only. + +The health check endpoint is used to determine the health of the service. + +```http request +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 + +The health check monitors the following components: + +- 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" + } + } +} +``` + +## WAHA Debug Mode + +If you enable `WAHA_DEBUG_MODE=True`, WAHA exposes a few additional features for helping with +troubleshooting (usually Memory and CPU-related issues). + +{{< callout context="caution" icon="outline/info-circle" >}} +`WAHA_DEBUG_MODE=True` is for **troubleshooting** purposes only +{{< /callout >}} + +### Get Node.js heapsnapshot + +```http request +GET /api/server/debug/heapsnapshot +``` + +Creates and downloads a heap dump from Node.js. + +You can execute request in +[**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}), +then click on **Download File**: + +![Swagger - Download File](swagger-download-file.png) + +### Get Browser Trace + +```http request +GET /api/server/debug/browser/trace/{SESSION}?seconds=30&categories=%2A +``` + +Get **browser's trace** (uses [puppeteer](https://pptr.dev/api/puppeteer.tracing)) +which you can open in Chrome Dev Tool +([chrome://tracing](chrome://tracing)) +or +[https://trace.cafe/](https://trace.cafe/). + +**Query Parameters:** + +- `seconds` - how many seconds to trace +- `categories` - categories to trace + +{{< callout context="tip" icon="outline/alert-square-rounded" >}} + +- 👉 Only one trace can be active at a time per browser. +- ⌛ It takes `SECONDS` seconds to generate the trace file, please be patient 🐢 + {{< /callout >}} + +You can execute request in +[**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}), +then click on **Download File**: + +![Swagger - Download File](swagger-download-file.png) + +### GOWS pprof + +You can expose the `6060` port and connect using pprof for the **GOWS** engine: + +```bash +go tool pprof -http=:8081 http://localhost:6060/debug/pprof/heap +``` + +Make sure to add it to docker-compose: + +```yaml +services: + waha: + image: devlikeapro/waha-plus + ports: + - "127.0.0.1:6060:6060" +``` diff --git a/content/docs/how-to/polls/features-events.md b/content/docs/how-to/polls/features-events.md index e5408b847..182d226bc 100644 --- a/content/docs/how-to/polls/features-events.md +++ b/content/docs/how-to/polls/features-events.md @@ -1,9 +1,9 @@ -
-{{< details "**📶 Polls - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|--------------------|-------|-------|:-----| -| `poll.vote` | | ✔️ | ✔️ | -| `poll.vote.failed` | | ✔️ | ✔️ | - -{{< /details >}} +
+{{< details "**📶 Polls - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ------------------ | ----- | ----- | :--- | +| `poll.vote` | | ✔️ | ✔️ | +| `poll.vote.failed` | | ✔️ | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/polls/features.md b/content/docs/how-to/polls/features.md index 3f170d698..3c37ee75c 100644 --- a/content/docs/how-to/polls/features.md +++ b/content/docs/how-to/polls/features.md @@ -1,10 +1,10 @@ -
-{{< details "**📶 Polls - API**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|----------------------|--------------------------------------------------------|:------|:----:| -| `POST /api/sendPoll` | [#189](https://github.com/devlikeapro/waha/issues/189) | ✔️ | ✔️ | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**📶 Polls - API**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| -------------------- | ------------------------------------------------------ | :---- | :--: | +| `POST /api/sendPoll` | [#189](https://github.com/devlikeapro/waha/issues/189) | ✔️ | ✔️ | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/polls/index.md b/content/docs/how-to/polls/index.md index 76525f737..40809b42d 100644 --- a/content/docs/how-to/polls/index.md +++ b/content/docs/how-to/polls/index.md @@ -1,232 +1,226 @@ ---- -title: "📶 Polls" -description: "How to send polls and receive votes" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 226 -slug: polls -images: [ "poll-example.jpg" ] ---- - -[**📶 Polls**]({{< relref "/docs/how-to/polls" >}}) -in WhatsApp is a good alternative for buttons and other interactive messages. - -You can ask a question and provide a few options for the user to choose from. -The user can select only one option or multiple options, depending on the poll configuration. - -
-{{< img lqip="21x webp q20" src="poll-example.jpg" alt="WhatsApp Poll" >}} -
- -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/polls/features.md" >}} - -{{< include file="content/docs/how-to/polls/features-events.md" >}} - -## API -### Send poll - -Use the endpoint to send a poll! - -```http request -POST /api/sendPoll -``` - -```json { title="Body" } -{ - "session": "default", - "chatId": "123123123@c.us", - "poll": { - "name": "How are you?", - "options": [ - "Awesome!", - "Good!", - "Not bad!" - ], - "multipleAnswers": false - } -} -``` - -```json { title="Response" } -{ - "id": "true_321321321@c.us_83ACBAAAAAAAAAAAAAAAAAAAA", - "other-fields-here": "value" -} -``` - -{{< callout context="tip" icon="outline/hand-finger-right" >}} -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). -{{< /callout >}} - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### poll.vote - -With this event, you receive new votes for the poll sent. - -#### Vote from a user in direct messages. - -```json { title="poll.vote" } -{ - "event": "poll.vote", - "session": "default", - "payload": { - "vote": { - "id": "false_1111111111@c.us_83ACBE602A05C79B234B54415E95EE8A", - "to": "me", - "from": "1111111@c.us", - "fromMe": false, - "selectedOptions": [ - "Awesome!" - ], - "timestamp": 1692861427 - }, - "poll": { - "id": "true_1111111111@c.us_BAE5F2EF5C69001E", - "to": "1111111111@c.us", - "from": "me", - "fromMe": true - } - }, - "engine": "NOWEB" -} -``` - -#### Do I receive votes only for my polls? - -No, you receive all votes. Keep in mind that you'll get all votes with this event, even from other polls. To identify -that it's your poll, look at the `poll.fromMe` field. - -#### How to handle multiple-answer votes - -For `multipleAnswers: true`, you receive the `selectedOptions` with all the selected values at a certain moment. So if a -user has chosen 3 options from the poll, you will receive **3** `poll.vote` events: - -1. `selectedOptions: ["First"]` -2. `selectedOptions: ["First", "Second"]` -3. `selectedOptions: ["First", "Second", "Third"]` - -#### Timestamp - -If a user clicks on the poll multiple times, you will receive multiple `poll.vote` events. This is true for -both `multipleAnswers: false` (when a user changes their mind about answers) and `multipleAnswers: true` (when a user -selects two or more options) events. - -There is a little chance that you may receive votes in the wrong order (due to the nature of HTTP and Webhooks), -like `1-3-2` instead of `1-2-3`. To determine the right order, look at the `timestamp` field. The event with a -higher `timestamp` value is more recent. - -👉 It's important to save the `timestamp` for each vote in your database and compare them as numbers, without converting to -internal datetime. Right now, the `timestamp` shows the timestamp in seconds, but it may be changed to milliseconds in -the future. - -#### Vote from a user in a group - -```json { title="poll.vote" } -{ - "event": "poll.vote", - "session": "default", - "payload": { - "vote": { - "id": "false_3333333333333@g.us_1C18A7EAADD2A8D0324755D241C4238A", - "to": "3333333333333@g.us", - "from": "1111111111@c.us", - "fromMe": false, - "selectedOptions": [ - "Awesome!" - ], - "timestamp": 1692861427 - }, - "poll": { - "id": "true_3333333333333@g.us_BAE5304BA1ECF704", - "to": "33333333333333@g.us", - "from": "222222222@c.us", - "fromMe": true - } - }, - "engine": "NOWEB" -} -``` - -### poll.vote.failed - -There may be cases when WAHA fails to decrypt a vote from the user. In such cases, you will receive -a `poll.vote.failed` event on your webhook. - -The payload for `poll.vote.failed` is the same as for `poll.vote`, but with an empty list in `selectedOptions`. - -```json { title="poll.vote.failed" } -{ - "event": "poll.vote.failed", - "session": "default", - "payload": { - "vote": { - "id": "false_11111111111@c.us_2E8C4CDA89EDE3BC0BC7F605364B8451", - "to": "me", - "from": "111111111@c.us", - "fromMe": false, - "selectedOptions": [], - "timestamp": 1692956972 - }, - "poll": { - "id": "true_1111111111@c.us_BAE595F4E0A2042C", - "to": "111111111@c.us", - "from": "me", - "fromMe": true - } - }, - "engine": "NOWEB" -} -``` - -#### How should I handle poll.vote.failed events? - -When you send a poll, save the poll configuration (question and options) in your database with the `id` field from the -response you received from `POST /api/sendPoll`. - -Later, when you receive a `poll.vote.failed` event, find the `id` for the poll in the database and repeat the same -question to the user, apologizing for the inconvenience. -For example, you can say: - -> Sorry, we don't understand your choice 😞 -> -> Please click one more time on the message below 👇 - -After the user clicks on the poll again, you will receive a `poll.vote` event with their choice. - -![handle-poll-vote-failed.jpg](handle-poll-vote-failed.jpg) - -#### How to test poll.vote.failed events? - -To receive `poll.vote.failed` events, follow these steps: - -1. Start a session and authorize it with a QR code. -2. Send a poll to a chat. -3. Stop the session (logout is not required). -4. Start the session again. -5. Vote on the poll. -6. You will receive a `poll.vote.failed` event. - -#### Why does the poll.vote.failed event occur and when will it be fixed? - -The issue occurs because WAHA does not have a proper storage system, but polls require proper storage in order to -decrypt votes later. - -There will be two fixes for this: - -1. In the short term, a [local file storage](https://github.com/devlikeapro/waha/issues/188) will be used - to save poll keys. -2. In the long term, work is being done - on [remote storages](https://github.com/devlikeapro/waha/issues/41). - -Even after these fixes are implemented, it's better to handle `poll.vote.failed` events anyway, so your application is -prepared for such cases! +--- +title: "📶 Polls" +description: "How to send polls and receive votes" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 226 +slug: polls +images: ["poll-example.jpg"] +--- + +[**📶 Polls**]({{< relref "/docs/how-to/polls" >}}) +in WhatsApp is a good alternative for buttons and other interactive messages. + +You can ask a question and provide a few options for the user to choose from. +The user can select only one option or multiple options, depending on the poll configuration. + +
+{{< img lqip="21x webp q20" src="poll-example.jpg" alt="WhatsApp Poll" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/polls/features.md" >}} + +{{< include file="content/docs/how-to/polls/features-events.md" >}} + +## API + +### Send poll + +Use the endpoint to send a poll! + +```http request +POST /api/sendPoll +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "123123123@c.us", + "poll": { + "name": "How are you?", + "options": ["Awesome!", "Good!", "Not bad!"], + "multipleAnswers": false + } +} +``` + +```json { title="Response" } +{ + "id": "true_321321321@c.us_83ACBAAAAAAAAAAAAAAAAAAAA", + "other-fields-here": "value" +} +``` + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +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). +{{< /callout >}} + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### poll.vote + +With this event, you receive new votes for the poll sent. + +#### Vote from a user in direct messages. + +```json { title="poll.vote" } +{ + "event": "poll.vote", + "session": "default", + "payload": { + "vote": { + "id": "false_1111111111@c.us_83ACBE602A05C79B234B54415E95EE8A", + "to": "me", + "from": "1111111@c.us", + "fromMe": false, + "selectedOptions": ["Awesome!"], + "timestamp": 1692861427 + }, + "poll": { + "id": "true_1111111111@c.us_BAE5F2EF5C69001E", + "to": "1111111111@c.us", + "from": "me", + "fromMe": true + } + }, + "engine": "NOWEB" +} +``` + +#### Do I receive votes only for my polls? + +No, you receive all votes. Keep in mind that you'll get all votes with this event, even from other polls. To identify +that it's your poll, look at the `poll.fromMe` field. + +#### How to handle multiple-answer votes + +For `multipleAnswers: true`, you receive the `selectedOptions` with all the selected values at a certain moment. So if a +user has chosen 3 options from the poll, you will receive **3** `poll.vote` events: + +1. `selectedOptions: ["First"]` +2. `selectedOptions: ["First", "Second"]` +3. `selectedOptions: ["First", "Second", "Third"]` + +#### Timestamp + +If a user clicks on the poll multiple times, you will receive multiple `poll.vote` events. This is true for +both `multipleAnswers: false` (when a user changes their mind about answers) and `multipleAnswers: true` (when a user +selects two or more options) events. + +There is a little chance that you may receive votes in the wrong order (due to the nature of HTTP and Webhooks), +like `1-3-2` instead of `1-2-3`. To determine the right order, look at the `timestamp` field. The event with a +higher `timestamp` value is more recent. + +👉 It's important to save the `timestamp` for each vote in your database and compare them as numbers, without converting to +internal datetime. Right now, the `timestamp` shows the timestamp in seconds, but it may be changed to milliseconds in +the future. + +#### Vote from a user in a group + +```json { title="poll.vote" } +{ + "event": "poll.vote", + "session": "default", + "payload": { + "vote": { + "id": "false_3333333333333@g.us_1C18A7EAADD2A8D0324755D241C4238A", + "to": "3333333333333@g.us", + "from": "1111111111@c.us", + "fromMe": false, + "selectedOptions": ["Awesome!"], + "timestamp": 1692861427 + }, + "poll": { + "id": "true_3333333333333@g.us_BAE5304BA1ECF704", + "to": "33333333333333@g.us", + "from": "222222222@c.us", + "fromMe": true + } + }, + "engine": "NOWEB" +} +``` + +### poll.vote.failed + +There may be cases when WAHA fails to decrypt a vote from the user. In such cases, you will receive +a `poll.vote.failed` event on your webhook. + +The payload for `poll.vote.failed` is the same as for `poll.vote`, but with an empty list in `selectedOptions`. + +```json { title="poll.vote.failed" } +{ + "event": "poll.vote.failed", + "session": "default", + "payload": { + "vote": { + "id": "false_11111111111@c.us_2E8C4CDA89EDE3BC0BC7F605364B8451", + "to": "me", + "from": "111111111@c.us", + "fromMe": false, + "selectedOptions": [], + "timestamp": 1692956972 + }, + "poll": { + "id": "true_1111111111@c.us_BAE595F4E0A2042C", + "to": "111111111@c.us", + "from": "me", + "fromMe": true + } + }, + "engine": "NOWEB" +} +``` + +#### How should I handle poll.vote.failed events? + +When you send a poll, save the poll configuration (question and options) in your database with the `id` field from the +response you received from `POST /api/sendPoll`. + +Later, when you receive a `poll.vote.failed` event, find the `id` for the poll in the database and repeat the same +question to the user, apologizing for the inconvenience. +For example, you can say: + +> Sorry, we don't understand your choice 😞 +> +> Please click one more time on the message below 👇 + +After the user clicks on the poll again, you will receive a `poll.vote` event with their choice. + +![handle-poll-vote-failed.jpg](handle-poll-vote-failed.jpg) + +#### How to test poll.vote.failed events? + +To receive `poll.vote.failed` events, follow these steps: + +1. Start a session and authorize it with a QR code. +2. Send a poll to a chat. +3. Stop the session (logout is not required). +4. Start the session again. +5. Vote on the poll. +6. You will receive a `poll.vote.failed` event. + +#### Why does the poll.vote.failed event occur and when will it be fixed? + +The issue occurs because WAHA does not have a proper storage system, but polls require proper storage in order to +decrypt votes later. + +There will be two fixes for this: + +1. In the short term, a [local file storage](https://github.com/devlikeapro/waha/issues/188) will be used + to save poll keys. +2. In the long term, work is being done + on [remote storages](https://github.com/devlikeapro/waha/issues/41). + +Even after these fixes are implemented, it's better to handle `poll.vote.failed` events anyway, so your application is +prepared for such cases! diff --git a/content/docs/how-to/presence/features-events.md b/content/docs/how-to/presence/features-events.md index abf649ae0..7d2ee55b0 100644 --- a/content/docs/how-to/presence/features-events.md +++ b/content/docs/how-to/presence/features-events.md @@ -1,9 +1,8 @@ -
-{{< details "**✅ Presence - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|-------------------|:-----:|:-----:|:-----| -| `presence.update` | ✔️ | ✔️ | ✔️ | - - -{{< /details >}} +
+{{< details "**✅ Presence - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ----------------- | :---: | :---: | :--- | +| `presence.update` | ✔️ | ✔️ | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/presence/features.md b/content/docs/how-to/presence/features.md index 862173c33..61d788974 100644 --- a/content/docs/how-to/presence/features.md +++ b/content/docs/how-to/presence/features.md @@ -1,13 +1,13 @@ -
-{{< details "**✅ Presence - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|---------------------------------------------------|:-----:|:-----:|:-----| -| `POST /api/{session}/presence` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/presence/{chatId}` | ✔️ | ✔️ | ✔️ | -| `POST /api/{session}/presence/{chatId}/subscribe` | ✔️ | ✔️ | ✔️ | -| `GET /api/{session}/presence` | | ✔️ | ✔️ | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**✅ Presence - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------- | :---: | :---: | :--- | +| `POST /api/{session}/presence` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/presence/{chatId}` | ✔️ | ✔️ | ✔️ | +| `POST /api/{session}/presence/{chatId}/subscribe` | ✔️ | ✔️ | ✔️ | +| `GET /api/{session}/presence` | | ✔️ | ✔️ | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/presence/index.md b/content/docs/how-to/presence/index.md index 49a899d29..24d0e5184 100644 --- a/content/docs/how-to/presence/index.md +++ b/content/docs/how-to/presence/index.md @@ -1,198 +1,203 @@ ---- -title: "✅ Presence" -description: "Presence - online, offline, typing status" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 291 -images: ["typing.jpg"] -slug: presence ---- - -You can get presence information (online, offline with last seen, typing status) for a contact if they share their -presence information. - -
-{{< img lqip="21x webp q20" src="typing.jpg" alt="WhatsApp Typing" >}} -
- - -## FAQ -👉 **I don't get notifications on my phone when WAHA session is connected** -- You need to send `offline` after all presence you send (WhatsApp doesn't send notifications to the device if a web client is active). -- For [**🏭 NOWEB Engine**]({{< relref "/docs/engines/NOWEB" >}}) also mark sure to send `markOnline: false` -when you create a new session. - -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/presence/features.md" >}} - -{{< include file="content/docs/how-to/presence/features-events.md" >}} - -## API - -### Set presence -You can set your global or chat-related presence with endpoint - -```http request -POST /api/{session}/presence -``` - -```json { title="Body" } -{ - "chatId": "111111111@c.us", - "presence": "typing" -} -``` - -Possible presence statuses that you can set or get for chats: -- `online` - send the status with no `chatId` -- `offline` - send the status with no `chatId` -- `typing` - `chatId` required -- `recording` - `chatId` required -- `paused` - resets the chat presence after you were `typing`. `chatId` required. - -**Start typing** to a chat (you can use `POST /startTyping` instead) - -```json { title="Body" } -{ - "chatId": "111111111@c.us", - "presence": "typing" -} -``` - -**Clear "typing" state** (you can use `POST /stopTyping` instead) - -```json { title="Body" } -{ - "chatId": "111111111@c.us", - "presence": "paused" -} -``` - -**Set global "online"**, all contacts will see it - -```json { title="Body" } -{ - "presence": "online" -} -``` - -💡 In the multi-device version of WhatsApp - if a desktop client is active, WhatsApp doesn't send push notifications -to the device. -If you would like to receive said notifications - you need to mark a session's presence as `offline`. - -```json { title="Body" } -{ - "presence": "offline" -} -``` - -### Get chat presence - -```http request -GET /api/{session}/presence/{chatId} -``` - -Get presence information for a single chat. For a group, you'll get participants' statuses. - -```json {title="Response"} -{ - "id": "2132132130@c.us", - "presences": [ - { - "participant": "2132132130@c.us", - "lastKnownPresence": "online", - "lastSeen": null - } - ] -} -``` - -### Subscribe to presence - -You can subscribe to presence information by calling -```http request -POST /api/{session}/presence/{chatId}/subscribe -``` - -(no body required). - -You can get later presence information for the chat with above `GET` endpoints or by listening to `presence.update` -webhook. - -### Get all chats presence - -You can get all presence information available for a session by calling - -```http request -GET /api/{session}/presence -``` - -It returns both groups' and personal chats' presence information. - -Here's few notes about fields: -- `chatId` - either contact id (`213213213@c.us`) or group chat id (`1111111111111@g.us`). -- `lastSeen` - contains Unix timestamps indicating when a participant was last online -- `lastKnownPresence` - contains the last known presence status, which can be - `offline`, `online`, `typing`, `recording`, or `paused` - -```json {title="Response"} -[ - { - "id": "2132132130@c.us", - "presences": [ - { - "participant": "2132132130@c.us", - "lastKnownPresence": "offline", - "lastSeen": 1686719326 - } - ] - }, - { - "id": "11111111111111111111111@g.us", - "presences": [ - { - "participant": "11111111111111111111111@g.us", - "lastKnownPresence": "online", - "lastSeen": null - }, - { - "participant": "2132132130@c.us", - "lastKnownPresence": "offline", - "lastSeen": 1686719326 - } - ] - } -] -``` - - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### presence.update - -You can subscribe to `presence.update` webhook event to get the most recent presence information. - -```json { title="presence.update" } -{ - "event": "presence.update", - "session": "default", - "payload": { - "id": "111111111111111111@g.us", - "presences": [ - { - "participant": "11111111111@c.us", - "lastKnownPresence": "typing", - "lastSeen": null - } - ] - }, - "engine": "NOWEB" -} -``` +--- +title: "✅ Presence" +description: "Presence - online, offline, typing status" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 291 +images: ["typing.jpg"] +slug: presence +--- + +You can get presence information (online, offline with last seen, typing status) for a contact if they share their +presence information. + +
+{{< img lqip="21x webp q20" src="typing.jpg" alt="WhatsApp Typing" >}} +
+ +## FAQ + +👉 **I don't get notifications on my phone when WAHA session is connected** + +- You need to send `offline` after all presence you send (WhatsApp doesn't send notifications to the device if a web client is active). +- For [**🏭 NOWEB Engine**]({{< relref "/docs/engines/NOWEB" >}}) also mark sure to send `markOnline: false` + when you create a new session. + +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/presence/features.md" >}} + +{{< include file="content/docs/how-to/presence/features-events.md" >}} + +## API + +### Set presence + +You can set your global or chat-related presence with endpoint + +```http request +POST /api/{session}/presence +``` + +```json { title="Body" } +{ + "chatId": "111111111@c.us", + "presence": "typing" +} +``` + +Possible presence statuses that you can set or get for chats: + +- `online` - send the status with no `chatId` +- `offline` - send the status with no `chatId` +- `typing` - `chatId` required +- `recording` - `chatId` required +- `paused` - resets the chat presence after you were `typing`. `chatId` required. + +**Start typing** to a chat (you can use `POST /startTyping` instead) + +```json { title="Body" } +{ + "chatId": "111111111@c.us", + "presence": "typing" +} +``` + +**Clear "typing" state** (you can use `POST /stopTyping` instead) + +```json { title="Body" } +{ + "chatId": "111111111@c.us", + "presence": "paused" +} +``` + +**Set global "online"**, all contacts will see it + +```json { title="Body" } +{ + "presence": "online" +} +``` + +💡 In the multi-device version of WhatsApp - if a desktop client is active, WhatsApp doesn't send push notifications +to the device. +If you would like to receive said notifications - you need to mark a session's presence as `offline`. + +```json { title="Body" } +{ + "presence": "offline" +} +``` + +### Get chat presence + +```http request +GET /api/{session}/presence/{chatId} +``` + +Get presence information for a single chat. For a group, you'll get participants' statuses. + +```json {title="Response"} +{ + "id": "2132132130@c.us", + "presences": [ + { + "participant": "2132132130@c.us", + "lastKnownPresence": "online", + "lastSeen": null + } + ] +} +``` + +### Subscribe to presence + +You can subscribe to presence information by calling + +```http request +POST /api/{session}/presence/{chatId}/subscribe +``` + +(no body required). + +You can get later presence information for the chat with above `GET` endpoints or by listening to `presence.update` +webhook. + +### Get all chats presence + +You can get all presence information available for a session by calling + +```http request +GET /api/{session}/presence +``` + +It returns both groups' and personal chats' presence information. + +Here's few notes about fields: + +- `chatId` - either contact id (`213213213@c.us`) or group chat id (`1111111111111@g.us`). +- `lastSeen` - contains Unix timestamps indicating when a participant was last online +- `lastKnownPresence` - contains the last known presence status, which can be + `offline`, `online`, `typing`, `recording`, or `paused` + +```json {title="Response"} +[ + { + "id": "2132132130@c.us", + "presences": [ + { + "participant": "2132132130@c.us", + "lastKnownPresence": "offline", + "lastSeen": 1686719326 + } + ] + }, + { + "id": "11111111111111111111111@g.us", + "presences": [ + { + "participant": "11111111111111111111111@g.us", + "lastKnownPresence": "online", + "lastSeen": null + }, + { + "participant": "2132132130@c.us", + "lastKnownPresence": "offline", + "lastSeen": 1686719326 + } + ] + } +] +``` + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### presence.update + +You can subscribe to `presence.update` webhook event to get the most recent presence information. + +```json { title="presence.update" } +{ + "event": "presence.update", + "session": "default", + "payload": { + "id": "111111111111111111@g.us", + "presences": [ + { + "participant": "11111111111@c.us", + "lastKnownPresence": "typing", + "lastSeen": null + } + ] + }, + "engine": "NOWEB" +} +``` diff --git a/content/docs/how-to/profile/features.md b/content/docs/how-to/profile/features.md index f0c222f0b..958a869a9 100644 --- a/content/docs/how-to/profile/features.md +++ b/content/docs/how-to/profile/features.md @@ -1,13 +1,13 @@ -
-{{< details "**🆔 Profile - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|------------------------------------------------------------------------------------------------------------------------------|:-----:|:-----:|:-----| -| **Get Profile**
`GET /api/{SESSION}/profile` | ✔️ | ✔️ | ✔️ | -| **Set Profile Name**
`PUT /api/{SESSION}/profile/name` | ✔️ | ✔️ | ✔️ | -| **Set Profile Status (About)**
`PUT /api/{SESSION}/profile/status` | ✔️ | ✔️ | ✔️ | -| **Set/Delete Profile Status Picture**
`PUT /api/{SESSION}/profile/picture`
`DELETE /api/{SESSION}/profile/picture` | ➕ | ➕ | ➕ | - -➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) - -{{< /details >}} +
+{{< details "**🆔 Profile - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ---------------------------------------------------------------------------------------------------------------------------- | :---: | :---: | :--- | +| **Get Profile**
`GET /api/{SESSION}/profile` | ✔️ | ✔️ | ✔️ | +| **Set Profile Name**
`PUT /api/{SESSION}/profile/name` | ✔️ | ✔️ | ✔️ | +| **Set Profile Status (About)**
`PUT /api/{SESSION}/profile/status` | ✔️ | ✔️ | ✔️ | +| **Set/Delete Profile Status Picture**
`PUT /api/{SESSION}/profile/picture`
`DELETE /api/{SESSION}/profile/picture` | ➕ | ➕ | ➕ | + +➕ - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) + +{{< /details >}} diff --git a/content/docs/how-to/profile/index.md b/content/docs/how-to/profile/index.md index e22033776..001021205 100644 --- a/content/docs/how-to/profile/index.md +++ b/content/docs/how-to/profile/index.md @@ -1,129 +1,133 @@ ---- -title: "🆔 Profile" -description: "Profile related API" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -images: [ "whatsapp-profile.jpg" ] -weight: 225 -slug: profile ---- - -You can manage your WhatsApp profile with the following API! - -{{< imgo src="/images/whatsapp/whatsapp-profile.jpg" full="false" >}} - -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/profile/features.md" >}} - -## API - -### Get Profile - -You can get your profile information with the following API call: - -```http request -GET /api/{SESSION}/profile -``` - -```json {title="Response"} -{ - "id": "111111111111@c.us", - "name": "My Name", - "picture": "https://pps.whatsapp.net/v/t/123.jpg?other-params" -} -``` - -### Set Profile Name - -You can set your name with the following API call - -```http request -PUT /api/{SESSION}/profile/name -``` - -```json {title="Body"} -{ - "name": "New Name" -} -``` - -```json {title="Response"} -{ - "success": true -} -``` - -### Set Profile Status - -You can set your status (aka **About**) message with the following API call: - -```http request -PUT /api/{SESSION}/profile/status -``` - -```json {title="Body"} -{ - "status": "New Status" -} -``` - -```json {title="Response"} -{ - "success": true -} -``` - -### Set Profile Picture - -You can set your profile picture with the following API call: - -```http request -PUT /api/{SESSSION}/profile/picture -``` - -{{< tabs "set-profile-picture" >}} -{{< tab "URL" >}} -```json {title="Body"} -{ - "file": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json {title="Body"} -{ - "file": { - "data": "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" - } -} -``` -{{< /tab >}} -{{< /tabs >}} - -```json {title="Response"} -{ - "success": true -} -``` - -### Delete Profile Picture - -You can delete your profile picture using this endpoint. - -```http request -DELETE /api/{SESSION}/profile/picture -``` - -```json {title="Response"} -{ - "success": true -} -``` +--- +title: "🆔 Profile" +description: "Profile related API" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +images: ["whatsapp-profile.jpg"] +weight: 225 +slug: profile +--- + +You can manage your WhatsApp profile with the following API! + +{{< imgo src="/images/whatsapp/whatsapp-profile.jpg" full="false" >}} + +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/profile/features.md" >}} + +## API + +### Get Profile + +You can get your profile information with the following API call: + +```http request +GET /api/{SESSION}/profile +``` + +```json {title="Response"} +{ + "id": "111111111111@c.us", + "name": "My Name", + "picture": "https://pps.whatsapp.net/v/t/123.jpg?other-params" +} +``` + +### Set Profile Name + +You can set your name with the following API call + +```http request +PUT /api/{SESSION}/profile/name +``` + +```json {title="Body"} +{ + "name": "New Name" +} +``` + +```json {title="Response"} +{ + "success": true +} +``` + +### Set Profile Status + +You can set your status (aka **About**) message with the following API call: + +```http request +PUT /api/{SESSION}/profile/status +``` + +```json {title="Body"} +{ + "status": "New Status" +} +``` + +```json {title="Response"} +{ + "success": true +} +``` + +### Set Profile Picture + +You can set your profile picture with the following API call: + +```http request +PUT /api/{SESSSION}/profile/picture +``` + +{{< tabs "set-profile-picture" >}} +{{< tab "URL" >}} + +```json {title="Body"} +{ + "file": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json {title="Body"} +{ + "file": { + "data": "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" + } +} +``` + +{{< /tab >}} +{{< /tabs >}} + +```json {title="Response"} +{ + "success": true +} +``` + +### Delete Profile Picture + +You can delete your profile picture using this endpoint. + +```http request +DELETE /api/{SESSION}/profile/picture +``` + +```json {title="Response"} +{ + "success": true +} +``` diff --git a/content/docs/how-to/proxy/index.md b/content/docs/how-to/proxy/index.md index 8ce48f501..e69f2d37b 100644 --- a/content/docs/how-to/proxy/index.md +++ b/content/docs/how-to/proxy/index.md @@ -1,123 +1,131 @@ ---- -title: "🌐 Proxy" -description: "Avoid issues with scanning QR codes in WhatsApp." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 226 -slug: proxy -images: [ "proxy.png" ] ---- - -## Overview -If you're experiencing issues scanning QR codes in WhatsApp, especially with **Indian 🇮🇳 phone numbers**, -using a proxy located close to the phone number's location may help resolve the problem. - -
-{{< img lqip="21x webp q20" src="proxy.png" alt="Proxy" >}} -
- -👉 If proxy doesn't help but the project works on YOUR local laptop - check [Tunneling](#tunneling). - -### Symptoms -1. You start a new session in WhatsApp. -2. Scan the QR code. -3. Experience a long loading time. -4. Face login failures or instant logout. -5. Encounter a new QR code or enter a FAILED state immediately. - -### Solutions -**There are two ways to solve this issue**: -1. Use a proxy (read this page and [**article about WAHA + Geonode**]({{< relref "/blog/waha-geonode" >}})). -2. Running WAHA on local network and [**expose WAHA with Ngrok**]({{< relref "/blog/waha-ngrok" >}}). - -
- - ![WhatsApp - could not login](could-not-login.png) - -
- -## Configuration -There are two ways to set up proxies: -1. Global Setting (for all sessions per container) -2. Per Session Configuration (you can define a proxy for each session when you start it) - -### Global Proxy Configuration -To use a proxy, you can set the following environment variables: - -- `WHATSAPP_PROXY_SERVER=localhost:3128`: Set the proxy server in the format `host:port`, without HTTP or HTTPS. -- `WHATSAPP_PROXY_SERVER_USERNAME=username` and `WHATSAPP_PROXY_SERVER_PASSWORD=password`: Configure credentials for the proxy. -- `WHATSAPP_PROXY_SERVER_LIST=host1.example.com:3138,host2.example.com:3138`: Specify a comma-separated list of addresses to use, utilizing a round-robin algorithm for server selection. -- `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-`: Define a session name prefix to choose the appropriate proxy from the list. - -Read more about it on [**Configuration page** ->]({{< relref "/docs/how-to/config#proxy" >}}). - -### Session Proxy Configuration -You can configure proxy for a session by setting `config.proxy` fields when you `POST /api/sessions/`: -- `server` - proxy server address, without `http://` or `https://` prefixes -- `username` and `password` - set this if the proxy requires authentication - - -**No authentication** -```json -{ - "name": "default", - "config": { - "proxy": { - "server": "localhost:3128" - } - } -} -``` - -**Proxy with authentication** -```json -{ - "name": "default", - "config": { - "proxy": { - "server": "localhost:3128", - "username": "username", - "password": "P@ssw0rd" - } - } -} -``` - -Read more about it on [**Sessions page** ->]({{< relref "/docs/how-to/sessions#configure-proxy" >}}). - - -## Recommended Proxies - -### Proxy6 -👉 Proxy6 - -Apply the promo code to get a **5% Discount** on your purchase. - -```yaml -9W9oVxx3UX -``` - -### Geonode -👉 Geonode - -It might reconnect the session due to its internal **geonode** issues - {{< issue 751 >}} - - - - -## Tunneling -If you can't use a proxy (or it doesn't help), you can try tunneling the connection to your local machine. - -You can run WAHA on local network then, you can buy something like RaspberryPi or a small server (lenovo m93 or similar) and host it there. - -So the setup would look like: -1. You have an app (with your logic and database) running on **VPS** -2. You have **WAHA** running on **your local network** on some dedicated PC (mongodb or file MUST be placed on this server as well) -3. You have [ngrok](https://ngrok.com/) (or any similar reverse proxy) running on **local network** and sharing 3000 port on dedicated name (paid ngrok required for that) -4. Your App communicated with WAHA API using the external ngrok name and WAHA send webhooks back to the server - -There's nothing we can do about network detection from Meta side :( - - +--- +title: "🌐 Proxy" +description: "Avoid issues with scanning QR codes in WhatsApp." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 226 +slug: proxy +images: ["proxy.png"] +--- + +## Overview + +If you're experiencing issues scanning QR codes in WhatsApp, especially with **Indian 🇮🇳 phone numbers**, +using a proxy located close to the phone number's location may help resolve the problem. + +
+{{< img lqip="21x webp q20" src="proxy.png" alt="Proxy" >}} +
+ +👉 If proxy doesn't help but the project works on YOUR local laptop - check [Tunneling](#tunneling). + +### Symptoms + +1. You start a new session in WhatsApp. +2. Scan the QR code. +3. Experience a long loading time. +4. Face login failures or instant logout. +5. Encounter a new QR code or enter a FAILED state immediately. + +### Solutions + +**There are two ways to solve this issue**: + +1. Use a proxy (read this page and [**article about WAHA + Geonode**]({{< relref "/blog/waha-geonode" >}})). +2. Running WAHA on local network and [**expose WAHA with Ngrok**]({{< relref "/blog/waha-ngrok" >}}). + +
+ +![WhatsApp - could not login](could-not-login.png) + +
+ +## Configuration + +There are two ways to set up proxies: + +1. Global Setting (for all sessions per container) +2. Per Session Configuration (you can define a proxy for each session when you start it) + +### Global Proxy Configuration + +To use a proxy, you can set the following environment variables: + +- `WHATSAPP_PROXY_SERVER=localhost:3128`: Set the proxy server in the format `host:port`, without HTTP or HTTPS. +- `WHATSAPP_PROXY_SERVER_USERNAME=username` and `WHATSAPP_PROXY_SERVER_PASSWORD=password`: Configure credentials for the proxy. +- `WHATSAPP_PROXY_SERVER_LIST=host1.example.com:3138,host2.example.com:3138`: Specify a comma-separated list of addresses to use, utilizing a round-robin algorithm for server selection. +- `WHATSAPP_PROXY_SERVER_INDEX_PREFIX=proxy-`: Define a session name prefix to choose the appropriate proxy from the list. + +Read more about it on [**Configuration page** ->]({{< relref "/docs/how-to/config#proxy" >}}). + +### Session Proxy Configuration + +You can configure proxy for a session by setting `config.proxy` fields when you `POST /api/sessions/`: + +- `server` - proxy server address, without `http://` or `https://` prefixes +- `username` and `password` - set this if the proxy requires authentication + +**No authentication** + +```json +{ + "name": "default", + "config": { + "proxy": { + "server": "localhost:3128" + } + } +} +``` + +**Proxy with authentication** + +```json +{ + "name": "default", + "config": { + "proxy": { + "server": "localhost:3128", + "username": "username", + "password": "P@ssw0rd" + } + } +} +``` + +Read more about it on [**Sessions page** ->]({{< relref "/docs/how-to/sessions#configure-proxy" >}}). + +## Recommended Proxies + +### Proxy6 + +👉 Proxy6 + +Apply the promo code to get a **5% Discount** on your purchase. + +```yaml +9W9oVxx3UX +``` + +### Geonode + +👉 Geonode + +It might reconnect the session due to its internal **geonode** issues - {{< issue 751 >}} + +## Tunneling + +If you can't use a proxy (or it doesn't help), you can try tunneling the connection to your local machine. + +You can run WAHA on local network then, you can buy something like RaspberryPi or a small server (lenovo m93 or similar) and host it there. + +So the setup would look like: + +1. You have an app (with your logic and database) running on **VPS** +2. You have **WAHA** running on **your local network** on some dedicated PC (mongodb or file MUST be placed on this server as well) +3. You have [ngrok](https://ngrok.com/) (or any similar reverse proxy) running on **local network** and sharing 3000 port on dedicated name (paid ngrok required for that) +4. Your App communicated with WAHA API using the external ngrok name and WAHA send webhooks back to the server + +There's nothing we can do about network detection from Meta side :( diff --git a/content/docs/how-to/receive-messages/features-events.md b/content/docs/how-to/receive-messages/features-events.md index d2b982a30..b4693a13e 100644 --- a/content/docs/how-to/receive-messages/features-events.md +++ b/content/docs/how-to/receive-messages/features-events.md @@ -1,14 +1,14 @@ -
-{{< details "**📤 Messages - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|--------------------|:-----:|:-----:|:----:| -| `message` | ✔️ | ✔️ | ✔️ | -| `message.reaction` | ✔️ | ✔️ | ✔️ | -| `message.any` | ✔️ | ✔️ | ✔️ | -| `message.ack` | ✔️ | ✔️ | ✔️ | -| `message.waiting` | ✔️ | | | -| `message.edited` | ✔️ | ✔️ | ✔️ | -| `message.revoked` | ✔️ | ✔️ | ✔️ | - -{{< /details >}} +
+{{< details "**📤 Messages - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ------------------ | :---: | :---: | :--: | +| `message` | ✔️ | ✔️ | ✔️ | +| `message.reaction` | ✔️ | ✔️ | ✔️ | +| `message.any` | ✔️ | ✔️ | ✔️ | +| `message.ack` | ✔️ | ✔️ | ✔️ | +| `message.waiting` | ✔️ | | | +| `message.edited` | ✔️ | ✔️ | ✔️ | +| `message.revoked` | ✔️ | ✔️ | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/receive-messages/index.md b/content/docs/how-to/receive-messages/index.md index a2aec6719..1891ebf53 100644 --- a/content/docs/how-to/receive-messages/index.md +++ b/content/docs/how-to/receive-messages/index.md @@ -1,341 +1,357 @@ ---- -title : "📥 Receive messages" -description: "Describe how to receive messages from WhatsApp." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 221 -images: ["messages.jpg"] -slug: receive-messages ---- -We assume that you've already run the Docker container and authenticated the session with a QR code. - -If you haven't yet - please follow the steps from [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). - -You can use [**🔄 Events via Webhooks or Websockets**]({{< relref "/docs/how-to/events" >}}) to receive messages from WhatsApp to your application. - -Start a new session with configured `message` event in webhooks - call `POST /api/sessions/` with the payload: -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} -``` - -After that, WAHA sends events (see below) about new messages to an endpoint you provided. - -{{< callout context="note" title="Observe Events" icon="outline/info-circle" >}} -To observe events and payload you can: -- Open [**📊 Dashboard / Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) and see the events in real-time -- Open [https://webhook.site](https://webhook.site), paste UUID from it to `url` field in webhook for a session -{{< /callout >}} - -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} - -## Fields -### chatId, from, to, participant -You may notice various identifiers in the `from`, `to`, and `participant` fields. Here's what they mean: -- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at the end. - For phone number `12132132131` the `chatId` is `12132132131@c.us` -- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**. Just convert it to `@c.us` to work with that properly. Kindly don't use it in `chatId` when sending messages -- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. -- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that type of ID along with communities functionality. -- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). - -### replyTo -If you get a message as a reply to another message, you'll see `replyTo` field with the message ID that was replied to. - -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "body": "Yes!", - "replyTo": "false_22222222@c.us_AAAAAAAAAAAAAAAAAAA" - } -} - -``` - - - -## Events -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -Here's examples of message-related events: - -### message - -Incoming message (text/audio/files) - -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "fromMe": true, - "to": "11111111111@c.us", - "body": "Hi there!", - "hasMedia": false, - "ack": 1, - "vCards": [], - "_data": { - ... - } - } -} -``` - -Fields: -- `hasMedia: true | false` - indicates if the message has media attached -- `media.url: http://localhost:8000/...` - the URL to download the media -- `_data` - internal **engine** data, can be different for each engine - -It's possible to have `hasMedia: true`, but `media: null` - this means that WAHA didn't download media due to configuration. - -### message.any - -Fired on all message creations, including your own. The payload is the same as for [message](#message) event. - -```json { title="message.any" } -{ - "event": "message.any", - "session": "default", - "payload": {} -} -``` - -### message.reaction -This event is triggered when a message is reacted to by a user (or when **you** react to a message). -- `payload.reaction.text` - emoji that was used to react to the message. It'll be an empty string if the reaction was removed. -- `payload.reaction.messageId` - id of the message that was reacted to. - -```json { title="message.reaction" } -{ - "event": "message.reaction", - "session": "default", - "me": { - "id": "79222222222@c.us", - "pushName": "WAHA" - }, - "payload": { - "id": "false_79111111@c.us_11111111111111111111111111111111", - "from": "79111111@c.us", - "fromMe": false, - "participant": "79111111@c.us", - "to": "79111111@c.us", - "timestamp": 1710481111.853, - "reaction": { - "text": "🙏", - "messageId": "true_79111111@c.us_11111111111111111111111111111111" - } - }, - "engine": "WEBJS", - "environment": { - "version": "2024.3.3", - "engine": "WEBJS", - "tier": "PLUS", - "browser": "/usr/bin/google-chrome-stable" - } -} -``` - -### message.ack -This event is triggered when the server or recipient gets the message, reads it, or plays it. - -```json { title="message.ack" } -{ - "event": "message.ack", - "session": "default", - "payload": {} -} -``` - -### message.waiting -Happens when you see -[Waiting for this message. This may take a while.](https://faq.whatsapp.com/3398056720476987) -on your phone. - -![waiting for this message](waiting-for-this-message.jpg) - -```json { title="message.waiting" } -{ - "event": "message.waiting", - "session": "default", - "engine": "WEBJS", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "from": "11111111111@c.us", - "fromMe": true, - "to": "11111111111@c.us", - ... - "_data": { - ... - } - } -} -``` - -### message.revoked - -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}). - -```json { title="message.revoked" } -{ - "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": "" - } - } -} -``` - - -## Media Files - -When people send you media - images, voice messages, and documents - WAHA saves them in the file storage. -In your application, you must download these files and use them as needed. You can find the URL in the `media.url` field. - -For example, you can get the webhook like this with `media` value (we've skipped other fields): - -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "timestamp": 1667561485, - "body": "Check this out (caption for the media)!", - "from": "11111111111@c.us", - "hasMedia": true, - "media": { - "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", - "mimetype": "image/jpeg", - "filename": null, - "error": null // if there was an error during file download - } - } -} -``` - -Fields: -- `hasMedia: true | false` - indicates if the message has media attached -- `media.url: http://localhost:8000/...` - the URL to download the media - -Note: If you see `hasMedia: true` but no `media.url`, this indicates that WAHA detected media but didn't download it due to your configuration settings. - -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 { title="message" } -{ - "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", - "error": null // if there was an error during file download - } - } -} -``` - -To configure the `media.url` you can use environment variables: -- `WAHA_BASE_URL=https://waha.example.com` (only affects `media.url`) - -Or define -- `WHATSAPP_API_SCHEMA=https`, -- `WHATSAPP_API_HOSTNAME=waha.example.com` -- `WHATSAPP_API_PORT=3000` - -By default, WAHA download all files that the account receive. -If you want to limit files lifetime, specify file types for download or change directory for files - -read more about [**⚙️ Configuration**]({{< relref "config" >}}). - -## API -See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). - -### Get messages -To read messages from the history, use the API: - -```http request -GET /api/messages -``` - -{{< callout context="caution" icon="outline/alert-triangle" >}} -We recommend using -[**🔄 Events via Webhooks or Websockets**]({{< relref "docs/how-to/events" >}}) -instead of constantly calling it to prevent performance issues. -{{< /callout >}} - -Accept the same parameters as -[**💬 Chats** - **Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages" >}}) endpoint: - -```bash -curl -X 'GET' \ - 'http://localhost:3000/api/messages?chatId=11111111111%40c.us&limit=1000&session=default' \ - -H 'accept: application/json' -``` - -### Get message by id -You also can get message by id using -[**💬 Chats** - **Get message by id from chat**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) endpoint. - -```http request -GET /api/{session}/chats/{chatId}/messages/{messageId}?downloadMedia=true -``` - -{{< callout context="note" icon="outline/alert-triangle" >}} -We recommend using -[**🔄 Events via Webhooks or Websockets**]({{< relref "docs/how-to/events" >}}) -instead to prevent performance issues. - -However, for single message requests, you can retrieve the message by its ID to obtain the latest `ack`, for example. -{{< /callout >}} - -## Examples -Here are a few examples of how to receive messages in different languages: -1. [Python guide ->]({{< relref "/docs/integrations/waha+python" >}}) - -**Do you use another language?** - -Please create a short guide how to handle webhook and send message after you finish your setup! -You can create a pull request with your favorite language in the -[GitHub, in examples folder ->](https://github.com/devlikeapro/waha/tree/core/examples). +--- +title: "📥 Receive messages" +description: "Describe how to receive messages from WhatsApp." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 221 +images: ["messages.jpg"] +slug: receive-messages +--- + +We assume that you've already run the Docker container and authenticated the session with a QR code. + +If you haven't yet - please follow the steps from [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). + +You can use [**🔄 Events via Webhooks or Websockets**]({{< relref "/docs/how-to/events" >}}) to receive messages from WhatsApp to your application. + +Start a new session with configured `message` event in webhooks - call `POST /api/sessions/` with the payload: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"] + } + ] + } +} +``` + +After that, WAHA sends events (see below) about new messages to an endpoint you provided. + +{{< callout context="note" title="Observe Events" icon="outline/info-circle" >}} +To observe events and payload you can: + +- Open [**📊 Dashboard / Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) and see the events in real-time +- Open [https://webhook.site](https://webhook.site), paste UUID from it to `url` field in webhook for a session + {{< /callout >}} + +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/receive-messages/features-events.md" >}} + +## Fields + +### chatId, from, to, participant + +You may notice various identifiers in the `from`, `to`, and `participant` fields. Here's what they mean: + +- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at the end. + For phone number `12132132131` the `chatId` is `12132132131@c.us` +- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**. Just convert it to `@c.us` to work with that properly. Kindly don't use it in `chatId` when sending messages +- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. +- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that type of ID along with communities functionality. +- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). + +### replyTo + +If you get a message as a reply to another message, you'll see `replyTo` field with the message ID that was replied to. + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "body": "Yes!", + "replyTo": "false_22222222@c.us_AAAAAAAAAAAAAAAAAAA" + } +} +``` + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +Here's examples of message-related events: + +### message + +Incoming message (text/audio/files) + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "fromMe": true, + "to": "11111111111@c.us", + "body": "Hi there!", + "hasMedia": false, + "ack": 1, + "vCards": [], + "_data": { + ... + } + } +} +``` + +Fields: + +- `hasMedia: true | false` - indicates if the message has media attached +- `media.url: http://localhost:8000/...` - the URL to download the media +- `_data` - internal **engine** data, can be different for each engine + +It's possible to have `hasMedia: true`, but `media: null` - this means that WAHA didn't download media due to configuration. + +### message.any + +Fired on all message creations, including your own. The payload is the same as for [message](#message) event. + +```json { title="message.any" } +{ + "event": "message.any", + "session": "default", + "payload": {} +} +``` + +### message.reaction + +This event is triggered when a message is reacted to by a user (or when **you** react to a message). + +- `payload.reaction.text` - emoji that was used to react to the message. It'll be an empty string if the reaction was removed. +- `payload.reaction.messageId` - id of the message that was reacted to. + +```json { title="message.reaction" } +{ + "event": "message.reaction", + "session": "default", + "me": { + "id": "79222222222@c.us", + "pushName": "WAHA" + }, + "payload": { + "id": "false_79111111@c.us_11111111111111111111111111111111", + "from": "79111111@c.us", + "fromMe": false, + "participant": "79111111@c.us", + "to": "79111111@c.us", + "timestamp": 1710481111.853, + "reaction": { + "text": "🙏", + "messageId": "true_79111111@c.us_11111111111111111111111111111111" + } + }, + "engine": "WEBJS", + "environment": { + "version": "2024.3.3", + "engine": "WEBJS", + "tier": "PLUS", + "browser": "/usr/bin/google-chrome-stable" + } +} +``` + +### message.ack + +This event is triggered when the server or recipient gets the message, reads it, or plays it. + +```json { title="message.ack" } +{ + "event": "message.ack", + "session": "default", + "payload": {} +} +``` + +### message.waiting + +Happens when you see +[Waiting for this message. This may take a while.](https://faq.whatsapp.com/3398056720476987) +on your phone. + +![waiting for this message](waiting-for-this-message.jpg) + +```json { title="message.waiting" } +{ + "event": "message.waiting", + "session": "default", + "engine": "WEBJS", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "from": "11111111111@c.us", + "fromMe": true, + "to": "11111111111@c.us", + ... + "_data": { + ... + } + } +} +``` + +### message.revoked + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}). + +```json { title="message.revoked" } +{ + "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": "" + } + } +} +``` + +## Media Files + +When people send you media - images, voice messages, and documents - WAHA saves them in the file storage. +In your application, you must download these files and use them as needed. You can find the URL in the `media.url` field. + +For example, you can get the webhook like this with `media` value (we've skipped other fields): + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "timestamp": 1667561485, + "body": "Check this out (caption for the media)!", + "from": "11111111111@c.us", + "hasMedia": true, + "media": { + "url": "http://localhost:3000/api/files/true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.jpg", + "mimetype": "image/jpeg", + "filename": null, + "error": null // if there was an error during file download + } + } +} +``` + +Fields: + +- `hasMedia: true | false` - indicates if the message has media attached +- `media.url: http://localhost:8000/...` - the URL to download the media + +Note: If you see `hasMedia: true` but no `media.url`, this indicates that WAHA detected media but didn't download it due to your configuration settings. + +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 { title="message" } +{ + "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", + "error": null // if there was an error during file download + } + } +} +``` + +To configure the `media.url` you can use environment variables: + +- `WAHA_BASE_URL=https://waha.example.com` (only affects `media.url`) + +Or define + +- `WHATSAPP_API_SCHEMA=https`, +- `WHATSAPP_API_HOSTNAME=waha.example.com` +- `WHATSAPP_API_PORT=3000` + +By default, WAHA download all files that the account receive. +If you want to limit files lifetime, specify file types for download or change directory for files - +read more about [**⚙️ Configuration**]({{< relref "config" >}}). + +## API + +See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). + +### Get messages + +To read messages from the history, use the API: + +```http request +GET /api/messages +``` + +{{< callout context="caution" icon="outline/alert-triangle" >}} +We recommend using +[**🔄 Events via Webhooks or Websockets**]({{< relref "docs/how-to/events" >}}) +instead of constantly calling it to prevent performance issues. +{{< /callout >}} + +Accept the same parameters as +[**💬 Chats** - **Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages" >}}) endpoint: + +```bash +curl -X 'GET' \ + 'http://localhost:3000/api/messages?chatId=11111111111%40c.us&limit=1000&session=default' \ + -H 'accept: application/json' +``` + +### Get message by id + +You also can get message by id using +[**💬 Chats** - **Get message by id from chat**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) endpoint. + +```http request +GET /api/{session}/chats/{chatId}/messages/{messageId}?downloadMedia=true +``` + +{{< callout context="note" icon="outline/alert-triangle" >}} +We recommend using +[**🔄 Events via Webhooks or Websockets**]({{< relref "docs/how-to/events" >}}) +instead to prevent performance issues. + +However, for single message requests, you can retrieve the message by its ID to obtain the latest `ack`, for example. +{{< /callout >}} + +## Examples + +Here are a few examples of how to receive messages in different languages: + +1. [Python guide ->]({{< relref "/docs/integrations/waha+python" >}}) + +**Do you use another language?** + +Please create a short guide how to handle webhook and send message after you finish your setup! +You can create a pull request with your favorite language in the +[GitHub, in examples folder ->](https://github.com/devlikeapro/waha/tree/core/examples). diff --git a/content/docs/how-to/security/how-to-generate-api-key.md b/content/docs/how-to/security/how-to-generate-api-key.md index e82400a3b..dcc938f0c 100644 --- a/content/docs/how-to/security/how-to-generate-api-key.md +++ b/content/docs/how-to/security/how-to-generate-api-key.md @@ -1,15 +1,17 @@ -1. Generate **Api Key** using uuid4 and remove `-` from it (or find a tool online) -```bash -uuidgen | tr -d '-' -> 00000000000000000000000000000000 -``` - -2. **Hash** it using **sha512** (or find a tool online) -```bash -echo -n "00000000000000000000000000000000" | shasum -a 512 -> 98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 - -``` - -- `WAHA_API_KEY=sha512:98b6...24648` - SHA512 hash in hex format. -- `X-Api-Key: 0000...0000` - **Api Key** that you need to send in `X-Api-Key` header. - - **Keep it in secret**, do not add it to `.env` +1. Generate **Api Key** using uuid4 and remove `-` from it (or find a tool online) + +```bash +uuidgen | tr -d '-' +> 00000000000000000000000000000000 +``` + +2. **Hash** it using **sha512** (or find a tool online) + +```bash +echo -n "00000000000000000000000000000000" | shasum -a 512 +> 98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 - +``` + +- `WAHA_API_KEY=sha512:98b6...24648` - SHA512 hash in hex format. +- `X-Api-Key: 0000...0000` - **Api Key** that you need to send in `X-Api-Key` header. + - **Keep it in secret**, do not add it to `.env` diff --git a/content/docs/how-to/security/index.md b/content/docs/how-to/security/index.md index 5574895d5..cd355f5a5 100644 --- a/content/docs/how-to/security/index.md +++ b/content/docs/how-to/security/index.md @@ -1,140 +1,146 @@ ---- -title : "🔒 Security" -description: "Security" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 700 -images: ["swagger-basic-auth.png"] -slug: security ---- - -{{< callout context="caution" title="Do not expose WhatsApp API on public networks!" icon="outline/shield-check" >}} -We do not recommend exposing the API on any public networks! - -Always protect the API with [**Api Key**](#api-security) and deny access by using firewalls. - -{{< /callout >}} - -## API security - -You can protect the API by requiring `X-Api-Key` header in HTTP request. - -You can use `WAHA_API_KEY` environment variable. It accepts two formats: - -- `WAHA_API_KEY=sha512:{SHA512_HEX_HASH}`: require `X-Api-Key: {PLAIN_KEY}` header in all requests to the API. This is the **recommended** format as it stores only the hash of your key in the environment variables, making it more secure if your environment variables are exposed. -- `WAHA_API_KEY={PLAIN_KEY}`: require `X-Api-Key: {PLAIN_KEY}` header in all requests to the API. This format stores your key in plain text in the environment variables, which is less secure. - -### Generate and Hash Api-Key -{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} - -### Set Api-Key Hash -Set -`WAHA_API_KEY=sha512:{SHA512_HEX_HASH}` in docker (or in `docker-compose.yaml` or `.env`): - -```bash -docker run -it -e WAHA_API_KEY=sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 devlikeapro/waha-plus -``` - -Test API works as expected -```bash -# No Key -curl http://localhost:3000/api/sessions -> {"message":"Unauthorized","statusCode":401} - -# Wrong Key -curl -H 'X-Api-Key: othersecret' http://localhost:3000/api/sessions -> {"message":"Unauthorized","statusCode":401} - -# Right Key -curl -H 'X-Api-Key: 00000000000000000000000000000000' http://localhost:3000/api/sessions -> [] -``` - -### Use Api-Key in Dashboard - -![Dashboard with API Key](waha-dashboard-key.png) - -### Use Api-Key in Swagger - -After you set Api Key - to authorize on swagger, use the **Authorize** button at the top: -![alt](swagger-auth.png) - -### Use X-Api-Key in HTTP request - -To authorize requests - set `X-Api-Key` header to `yoursecretkey` for all requests that go to WAHA. - -{{< include file="content/docs/how-to/security/set-x-api-key-http-header-code.md" >}} - - -### Exclude endpoints -If you need to exclude some endpoints (like `GET /health` or `GET /ping`) from the API Key requirement - you can -set `WAHA_API_KEY_EXCLUDE_PATH` environment variable with a comma-separated list of endpoints (no `/` at the beginning). - -```bash -docker run -it \ - -e WAHA_API_KEY_EXCLUDE_PATH="health,ping" \ - -e WAHA_API_KEY=yoursecretkey \ - devlikeapro/waha-plus -``` - - - -## Swagger Security -If you want to hide the project Swagger panel under the password - run the following command to hide under `admin/admin` -login and password. - -```bash -docker run -it -e WHATSAPP_SWAGGER_USERNAME=admin -e WHATSAPP_SWAGGER_PASSWORD=admin devlikeapro/waha-plus -``` - -Open http://localhost:3000/ and enter `admin / admin` in the inputs: - -![alt](swagger-basic-auth.png) - -{{< callout context="note" icon="outline/info-circle" >}} -Protecting Swagger under the password does not protect your API from other request! Use both techniques to protect your API and Swagger! -{{< /callout >}} - -Environment variables: -- `WHATSAPP_SWAGGER_ENABLED=true`: Toggle to enable or disable the Swagger. -- `WHATSAPP_SWAGGER_USERNAME=admin` -- `WHATSAPP_SWAGGER_PASSWORD=admin` - Swagger panel with `admin / admin` credentials. This does not affect API access. - -{{< callout context="tip" icon="outline/info-circle" >}} -You can also set [**Swagger White Label**]({{< relref "/docs/how-to/swagger#white-label" >}}) -options instead of hiding the Swagger panel. -{{< /callout >}} - - -## Dashboard Security -Read more about [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) - -When running WAHA you can set the following environment variables to configure the dashboard: -- `WAHA_DASHBOARD_ENABLED=true` - enable or disable the dashboard, by default `true`. Set to `false` to disable the dashboard. -- `WAHA_DASHBOARD_USERNAME=waha` - username used to log in, by default `admin` or `waha` -- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `admin` or `waha`. - - -## Webhook security -To make sure that you get a webhook from your WAHA instance - you can use **HMAC authentication**. - -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events#hmac-authentication" >}}). - -## HTTPS -After you set up the security options - you should set up HTTPS to protect the data in transit and prevent [Man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). - -That's fine to run it on the **local network** without HTTPS, but for **the production** environment, HTTPS is a must-have. - -{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} - -WAHA supports HTTPS out of the box if you don't want to use a reverse proxy like Nginx (**using Nginx is recommended**) - -You can set up the following environment variables to enable HTTPS: -- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. -- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` -- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` -- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` +--- +title: "🔒 Security" +description: "Security" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 700 +images: ["swagger-basic-auth.png"] +slug: security +--- + +{{< callout context="caution" title="Do not expose WhatsApp API on public networks!" icon="outline/shield-check" >}} +We do not recommend exposing the API on any public networks! + +Always protect the API with [**Api Key**](#api-security) and deny access by using firewalls. + +{{< /callout >}} + +## API security + +You can protect the API by requiring `X-Api-Key` header in HTTP request. + +You can use `WAHA_API_KEY` environment variable. It accepts two formats: + +- `WAHA_API_KEY=sha512:{SHA512_HEX_HASH}`: require `X-Api-Key: {PLAIN_KEY}` header in all requests to the API. This is the **recommended** format as it stores only the hash of your key in the environment variables, making it more secure if your environment variables are exposed. +- `WAHA_API_KEY={PLAIN_KEY}`: require `X-Api-Key: {PLAIN_KEY}` header in all requests to the API. This format stores your key in plain text in the environment variables, which is less secure. + +### Generate and Hash Api-Key + +{{< include file="content/docs/how-to/security/how-to-generate-api-key.md" >}} + +### Set Api-Key Hash + +Set +`WAHA_API_KEY=sha512:{SHA512_HEX_HASH}` in docker (or in `docker-compose.yaml` or `.env`): + +```bash +docker run -it -e WAHA_API_KEY=sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648 devlikeapro/waha-plus +``` + +Test API works as expected + +```bash +# No Key +curl http://localhost:3000/api/sessions +> {"message":"Unauthorized","statusCode":401} + +# Wrong Key +curl -H 'X-Api-Key: othersecret' http://localhost:3000/api/sessions +> {"message":"Unauthorized","statusCode":401} + +# Right Key +curl -H 'X-Api-Key: 00000000000000000000000000000000' http://localhost:3000/api/sessions +> [] +``` + +### Use Api-Key in Dashboard + +![Dashboard with API Key](waha-dashboard-key.png) + +### Use Api-Key in Swagger + +After you set Api Key - to authorize on swagger, use the **Authorize** button at the top: +![alt](swagger-auth.png) + +### Use X-Api-Key in HTTP request + +To authorize requests - set `X-Api-Key` header to `yoursecretkey` for all requests that go to WAHA. + +{{< include file="content/docs/how-to/security/set-x-api-key-http-header-code.md" >}} + +### Exclude endpoints + +If you need to exclude some endpoints (like `GET /health` or `GET /ping`) from the API Key requirement - you can +set `WAHA_API_KEY_EXCLUDE_PATH` environment variable with a comma-separated list of endpoints (no `/` at the beginning). + +```bash +docker run -it \ + -e WAHA_API_KEY_EXCLUDE_PATH="health,ping" \ + -e WAHA_API_KEY=yoursecretkey \ + devlikeapro/waha-plus +``` + +## Swagger Security + +If you want to hide the project Swagger panel under the password - run the following command to hide under `admin/admin` +login and password. + +```bash +docker run -it -e WHATSAPP_SWAGGER_USERNAME=admin -e WHATSAPP_SWAGGER_PASSWORD=admin devlikeapro/waha-plus +``` + +Open http://localhost:3000/ and enter `admin / admin` in the inputs: + +![alt](swagger-basic-auth.png) + +{{< callout context="note" icon="outline/info-circle" >}} +Protecting Swagger under the password does not protect your API from other request! Use both techniques to protect your API and Swagger! +{{< /callout >}} + +Environment variables: + +- `WHATSAPP_SWAGGER_ENABLED=true`: Toggle to enable or disable the Swagger. +- `WHATSAPP_SWAGGER_USERNAME=admin` +- `WHATSAPP_SWAGGER_PASSWORD=admin` + Swagger panel with `admin / admin` credentials. This does not affect API access. + +{{< callout context="tip" icon="outline/info-circle" >}} +You can also set [**Swagger White Label**]({{< relref "/docs/how-to/swagger#white-label" >}}) +options instead of hiding the Swagger panel. +{{< /callout >}} + +## Dashboard Security + +Read more about [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) + +When running WAHA you can set the following environment variables to configure the dashboard: + +- `WAHA_DASHBOARD_ENABLED=true` - enable or disable the dashboard, by default `true`. Set to `false` to disable the dashboard. +- `WAHA_DASHBOARD_USERNAME=waha` - username used to log in, by default `admin` or `waha` +- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `admin` or `waha`. + +## Webhook security + +To make sure that you get a webhook from your WAHA instance - you can use **HMAC authentication**. + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events#hmac-authentication" >}}). + +## HTTPS + +After you set up the security options - you should set up HTTPS to protect the data in transit and prevent [Man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). + +That's fine to run it on the **local network** without HTTPS, but for **the production** environment, HTTPS is a must-have. + +{{< include file="content/docs/how-to/security/use-nginx-for-https.md" >}} + +WAHA supports HTTPS out of the box if you don't want to use a reverse proxy like Nginx (**using Nginx is recommended**) + +You can set up the following environment variables to enable HTTPS: + +- `WAHA_HTTPS_ENABLED=true`: Set this variable to `true` to enable HTTPS. By default, it's `false`. +- `WAHA_HTTPS_PATH_KEY=/path/to/key.pem`: The path to the key file for HTTPS. By default `./.secrets/privkey.pem` +- `WAHA_HTTPS_PATH_CERT=/path/to/cert.pem`: The path to the certificate file for HTTPS. By default `./.secrets/cert.pem` +- `WAHA_HTTPS_PATH_CA=/path/to/ca.pem`: The path to the CA file for HTTPS. By default `./.secrets/chain.pem` diff --git a/content/docs/how-to/security/set-x-api-key-http-header-code.md b/content/docs/how-to/security/set-x-api-key-http-header-code.md index 1ddd6a3cd..dbdfafb88 100644 --- a/content/docs/how-to/security/set-x-api-key-http-header-code.md +++ b/content/docs/how-to/security/set-x-api-key-http-header-code.md @@ -1,62 +1,71 @@ -
- -{{< tabs "set-x-api-key-http-header" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'GET' \ - 'http://localhost:3000/api/sessions' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -headers = { - 'Content-type': 'application/json', - 'X-Api-Key': 'yoursecretkey', -} -response = requests.get("http://localhost:3000/api/sessions", headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions"; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.get(url, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} +
+ +{{< tabs "set-x-api-key-http-header" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'GET' \ + 'http://localhost:3000/api/sessions' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +headers = { + 'Content-type': 'application/json', + 'X-Api-Key': 'yoursecretkey', +} +response = requests.get("http://localhost:3000/api/sessions", headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions"; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .get(url, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/security/use-nginx-for-https.md b/content/docs/how-to/security/use-nginx-for-https.md index cd20aee1c..334cd3cbe 100644 --- a/content/docs/how-to/security/use-nginx-for-https.md +++ b/content/docs/how-to/security/use-nginx-for-https.md @@ -1,8 +1,8 @@ -
-{{< callout context="tip" title="Use Nginx to handle HTTPS" icon="outline/shield-check" >}} - -We **recommend** handling HTTPS termination with **a reverse proxy** like Nginx. - -Follow -[**🔧 Install & Update - Nginx**]({{< relref "/docs/how-to/install#nginx" >}}) to set up **Nginx with Let's Encrypt**. -{{< /callout >}} +
+{{< callout context="tip" title="Use Nginx to handle HTTPS" icon="outline/shield-check" >}} + +We **recommend** handling HTTPS termination with **a reverse proxy** like Nginx. + +Follow +[**🔧 Install & Update - Nginx**]({{< relref "/docs/how-to/install#nginx" >}}) to set up **Nginx with Let's Encrypt**. +{{< /callout >}} diff --git a/content/docs/how-to/send-messages/api-deleteMessage-code.md b/content/docs/how-to/send-messages/api-deleteMessage-code.md index 2693ec0e6..0560f983e 100644 --- a/content/docs/how-to/send-messages/api-deleteMessage-code.md +++ b/content/docs/how-to/send-messages/api-deleteMessage-code.md @@ -1,62 +1,71 @@ -
- -{{< tabs "delete-message-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'DELETE' \ - 'http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA" -headers = { - "X-Api-Key": "yoursecretkey" -} - -response = requests.delete(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA"; -const headers = { - 'X-Api-Key': 'yoursecretkey' -}; - -axios.delete(url, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "delete-message-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'DELETE' \ + 'http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA" +headers = { + "X-Api-Key": "yoursecretkey" +} + +response = requests.delete(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA"; +const headers = { + "X-Api-Key": "yoursecretkey" +}; + +axios + .delete(url, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-editMessage-code.md b/content/docs/how-to/send-messages/api-editMessage-code.md index 904582999..20092f75b 100644 --- a/content/docs/how-to/send-messages/api-editMessage-code.md +++ b/content/docs/how-to/send-messages/api-editMessage-code.md @@ -1,83 +1,92 @@ -
- -{{< tabs "edit-message-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'PUT' \ - 'http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "text": "Hello, world! (edited)", - "linkPreview": true -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "text": "Hello, world! (edited)", - "linkPreview": True -} - -response = requests.put(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA"; -const data = { - text: "Hello, world! (edited)", - linkPreview: true -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.put(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "Hello, world! (edited)", - "linkPreview" => true -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "edit-message-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'PUT' \ + 'http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "text": "Hello, world! (edited)", + "linkPreview": true +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "text": "Hello, world! (edited)", + "linkPreview": True +} + +response = requests.put(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/default/chats/12132132130%40c.us/messages/true_12132132130%40c.us_AAAAAAAAAAAAAAAAAAAA"; +const data = { + text: "Hello, world! (edited)", + linkPreview: true +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .put(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "Hello, world! (edited)", + "linkPreview" => true +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-forwardMessage-code.md b/content/docs/how-to/send-messages/api-forwardMessage-code.md index a9ef47fdc..d2351e2bb 100644 --- a/content/docs/how-to/send-messages/api-forwardMessage-code.md +++ b/content/docs/how-to/send-messages/api-forwardMessage-code.md @@ -1,87 +1,96 @@ -
- -{{< tabs "forward-message-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/forwardMessage' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/forwardMessage" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/forwardMessage"; -const data = { - session: "default", - chatId: "12132132130@c.us", - messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "forward-message-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/forwardMessage' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/forwardMessage" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/forwardMessage"; +const data = { + session: "default", + chatId: "12132132130@c.us", + messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-reaction-code.md b/content/docs/how-to/send-messages/api-reaction-code.md index dac6b00c1..a99a4ca45 100644 --- a/content/docs/how-to/send-messages/api-reaction-code.md +++ b/content/docs/how-to/send-messages/api-reaction-code.md @@ -1,87 +1,96 @@ -
- -{{< tabs "reaction-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'PUT' \ - 'http://localhost:3000/api/reaction' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "reaction": "👍" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/reaction" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "reaction": "👍" -} - -response = requests.put(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/reaction"; -const data = { - session: "default", - messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - reaction: "👍" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.put(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "reaction" => "👍" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "reaction-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'PUT' \ + 'http://localhost:3000/api/reaction' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "reaction": "👍" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/reaction" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "reaction": "👍" +} + +response = requests.put(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/reaction"; +const data = { + session: "default", + messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + reaction: "👍" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .put(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "reaction" => "👍" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendButtons-code.md b/content/docs/how-to/send-messages/api-sendButtons-code.md index f2b7c89c4..ecc33190d 100644 --- a/content/docs/how-to/send-messages/api-sendButtons-code.md +++ b/content/docs/how-to/send-messages/api-sendButtons-code.md @@ -1,199 +1,208 @@ -
- -{{< tabs "send-buttons-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendButtons' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "header": "How are you?", - "headerImage": { - "mimetype": "image/jpeg", - "filename": "filename.jpg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - }, - "body": "Tell us how are you please 🙏", - "footer": "If you have any questions, please send it in the chat", - "buttons": [ - { - "type": "reply", - "text": "I am good!" - }, - { - "type": "call", - "text": "Call us", - "phoneNumber": "+1234567890" - }, - { - "type": "copy", - "text": "Copy code", - "copyCode": "4321" - }, - { - "type": "url", - "text": "How did you do that?", - "url": "https://waha.devlike.pro" - } - ] -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendButtons" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "header": "How are you?", - "headerImage": { - "mimetype": "image/jpeg", - "filename": "filename.jpg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - }, - "body": "Tell us how are you please 🙏", - "footer": "If you have any questions, please send it in the chat", - "buttons": [ - { - "type": "reply", - "text": "I am good!" - }, - { - "type": "call", - "text": "Call us", - "phoneNumber": "+1234567890" - }, - { - "type": "copy", - "text": "Copy code", - "copyCode": "4321" - }, - { - "type": "url", - "text": "How did you do that?", - "url": "https://waha.devlike.pro" - } - ] -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendButtons"; -const data = { - session: "default", - chatId: "12132132130@c.us", - header: "How are you?", - headerImage: { - mimetype: "image/jpeg", - filename: "filename.jpg", - url: "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - }, - body: "Tell us how are you please 🙏", - footer: "If you have any questions, please send it in the chat", - buttons: [ - { - type: "reply", - text: "I am good!" - }, - { - type: "call", - text: "Call us", - phoneNumber: "+1234567890" - }, - { - type: "copy", - text: "Copy code", - copyCode: "4321" - }, - { - type: "url", - text: "How did you do that?", - url: "https://waha.devlike.pro" - } - ] -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "header" => "How are you?", - "headerImage" => [ - "mimetype" => "image/jpeg", - "filename" => "filename.jpg", - "url" => "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - ], - "body" => "Tell us how are you please 🙏", - "footer" => "If you have any questions, please send it in the chat", - "buttons" => [ - [ - "type" => "reply", - "text" => "I am good!" - ], - [ - "type" => "call", - "text" => "Call us", - "phoneNumber" => "+1234567890" - ], - [ - "type" => "copy", - "text" => "Copy code", - "copyCode" => "4321" - ], - [ - "type" => "url", - "text" => "How did you do that?", - "url" => "https://waha.devlike.pro" - ] - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-buttons-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendButtons' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "header": "How are you?", + "headerImage": { + "mimetype": "image/jpeg", + "filename": "filename.jpg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + }, + "body": "Tell us how are you please 🙏", + "footer": "If you have any questions, please send it in the chat", + "buttons": [ + { + "type": "reply", + "text": "I am good!" + }, + { + "type": "call", + "text": "Call us", + "phoneNumber": "+1234567890" + }, + { + "type": "copy", + "text": "Copy code", + "copyCode": "4321" + }, + { + "type": "url", + "text": "How did you do that?", + "url": "https://waha.devlike.pro" + } + ] +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendButtons" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "header": "How are you?", + "headerImage": { + "mimetype": "image/jpeg", + "filename": "filename.jpg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + }, + "body": "Tell us how are you please 🙏", + "footer": "If you have any questions, please send it in the chat", + "buttons": [ + { + "type": "reply", + "text": "I am good!" + }, + { + "type": "call", + "text": "Call us", + "phoneNumber": "+1234567890" + }, + { + "type": "copy", + "text": "Copy code", + "copyCode": "4321" + }, + { + "type": "url", + "text": "How did you do that?", + "url": "https://waha.devlike.pro" + } + ] +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendButtons"; +const data = { + session: "default", + chatId: "12132132130@c.us", + header: "How are you?", + headerImage: { + mimetype: "image/jpeg", + filename: "filename.jpg", + url: "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + }, + body: "Tell us how are you please 🙏", + footer: "If you have any questions, please send it in the chat", + buttons: [ + { + type: "reply", + text: "I am good!" + }, + { + type: "call", + text: "Call us", + phoneNumber: "+1234567890" + }, + { + type: "copy", + text: "Copy code", + copyCode: "4321" + }, + { + type: "url", + text: "How did you do that?", + url: "https://waha.devlike.pro" + } + ] +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "header" => "How are you?", + "headerImage" => [ + "mimetype" => "image/jpeg", + "filename" => "filename.jpg", + "url" => "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + ], + "body" => "Tell us how are you please 🙏", + "footer" => "If you have any questions, please send it in the chat", + "buttons" => [ + [ + "type" => "reply", + "text" => "I am good!" + ], + [ + "type" => "call", + "text" => "Call us", + "phoneNumber" => "+1234567890" + ], + [ + "type" => "copy", + "text" => "Copy code", + "copyCode" => "4321" + ], + [ + "type" => "url", + "text" => "How did you do that?", + "url" => "https://waha.devlike.pro" + ] + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendButtonsReply-code.md b/content/docs/how-to/send-messages/api-sendButtonsReply-code.md index 2b141e189..9bee73e53 100644 --- a/content/docs/how-to/send-messages/api-sendButtonsReply-code.md +++ b/content/docs/how-to/send-messages/api-sendButtonsReply-code.md @@ -1,95 +1,104 @@ -
- -{{< tabs "send-buttons-reply-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/send/buttons/reply' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "replyTo": "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", - "selectedDisplayText": "No", - "selectedButtonID": "button:id" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/send/buttons/reply" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "replyTo": "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", - "selectedDisplayText": "No", - "selectedButtonID": "button:id" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/send/buttons/reply"; -const data = { - session: "default", - chatId: "12132132130@c.us", - replyTo: "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", - selectedDisplayText: "No", - selectedButtonID: "button:id" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "replyTo" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", - "selectedDisplayText" => "No", - "selectedButtonID" => "button:id" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-buttons-reply-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/send/buttons/reply' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "replyTo": "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", + "selectedDisplayText": "No", + "selectedButtonID": "button:id" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/send/buttons/reply" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "replyTo": "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", + "selectedDisplayText": "No", + "selectedButtonID": "button:id" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/send/buttons/reply"; +const data = { + session: "default", + chatId: "12132132130@c.us", + replyTo: "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", + selectedDisplayText: "No", + selectedButtonID: "button:id" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "replyTo" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAA", + "selectedDisplayText" => "No", + "selectedButtonID" => "button:id" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendContactVcard-code.md b/content/docs/how-to/send-messages/api-sendContactVcard-code.md index 7f3bb1b06..5f5a6b4d9 100644 --- a/content/docs/how-to/send-messages/api-sendContactVcard-code.md +++ b/content/docs/how-to/send-messages/api-sendContactVcard-code.md @@ -1,115 +1,124 @@ -
- -{{< tabs "send-contact-vcard-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendContactVcard' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "contacts": [ - { - "fullName": "John Doe", - "organization": "Company Name", - "phoneNumber": "+91 11111 11111", - "whatsappId": "911111111111" - } - ] -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendContactVcard" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "contacts": [ - { - "fullName": "John Doe", - "organization": "Company Name", - "phoneNumber": "+91 11111 11111", - "whatsappId": "911111111111" - } - ] -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendContactVcard"; -const data = { - session: "default", - chatId: "12132132130@c.us", - contacts: [ - { - fullName: "John Doe", - organization: "Company Name", - phoneNumber: "+91 11111 11111", - whatsappId: "911111111111" - } - ] -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "contacts" => [ - [ - "fullName" => "John Doe", - "organization" => "Company Name", - "phoneNumber" => "+91 11111 11111", - "whatsappId" => "911111111111" - ] - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-contact-vcard-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendContactVcard' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "contacts": [ + { + "fullName": "John Doe", + "organization": "Company Name", + "phoneNumber": "+91 11111 11111", + "whatsappId": "911111111111" + } + ] +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendContactVcard" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "contacts": [ + { + "fullName": "John Doe", + "organization": "Company Name", + "phoneNumber": "+91 11111 11111", + "whatsappId": "911111111111" + } + ] +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendContactVcard"; +const data = { + session: "default", + chatId: "12132132130@c.us", + contacts: [ + { + fullName: "John Doe", + organization: "Company Name", + phoneNumber: "+91 11111 11111", + whatsappId: "911111111111" + } + ] +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "contacts" => [ + [ + "fullName" => "John Doe", + "organization" => "Company Name", + "phoneNumber" => "+91 11111 11111", + "whatsappId" => "911111111111" + ] + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendEvent-code.md b/content/docs/how-to/send-messages/api-sendEvent-code.md index 9ff511c63..d50f80636 100644 --- a/content/docs/how-to/send-messages/api-sendEvent-code.md +++ b/content/docs/how-to/send-messages/api-sendEvent-code.md @@ -1,107 +1,116 @@ -
- -{{< tabs "send-event-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/default/events' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "chatId": "12132132130@c.us", - "event": { - "title": "Team Meeting", - "description": "Monthly team sync-up", - "location": "Conference Room A", - "startTime": "2023-12-15T10:00:00Z", - "endTime": "2023-12-15T11:00:00Z" - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/default/events" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "chatId": "12132132130@c.us", - "event": { - "title": "Team Meeting", - "description": "Monthly team sync-up", - "location": "Conference Room A", - "startTime": "2023-12-15T10:00:00Z", - "endTime": "2023-12-15T11:00:00Z" - } -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/default/events"; -const data = { - chatId: "12132132130@c.us", - event: { - title: "Team Meeting", - description: "Monthly team sync-up", - location: "Conference Room A", - startTime: "2023-12-15T10:00:00Z", - endTime: "2023-12-15T11:00:00Z" - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "12132132130@c.us", - "event" => [ - "title" => "Team Meeting", - "description" => "Monthly team sync-up", - "location" => "Conference Room A", - "startTime" => "2023-12-15T10:00:00Z", - "endTime" => "2023-12-15T11:00:00Z" - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-event-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/default/events' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "chatId": "12132132130@c.us", + "event": { + "title": "Team Meeting", + "description": "Monthly team sync-up", + "location": "Conference Room A", + "startTime": "2023-12-15T10:00:00Z", + "endTime": "2023-12-15T11:00:00Z" + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/default/events" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "chatId": "12132132130@c.us", + "event": { + "title": "Team Meeting", + "description": "Monthly team sync-up", + "location": "Conference Room A", + "startTime": "2023-12-15T10:00:00Z", + "endTime": "2023-12-15T11:00:00Z" + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/default/events"; +const data = { + chatId: "12132132130@c.us", + event: { + title: "Team Meeting", + description: "Monthly team sync-up", + location: "Conference Room A", + startTime: "2023-12-15T10:00:00Z", + endTime: "2023-12-15T11:00:00Z" + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "12132132130@c.us", + "event" => [ + "title" => "Team Meeting", + "description" => "Monthly team sync-up", + "location" => "Conference Room A", + "startTime" => "2023-12-15T10:00:00Z", + "endTime" => "2023-12-15T11:00:00Z" + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendFile-code.md b/content/docs/how-to/send-messages/api-sendFile-code.md index 3190f5e9b..84e20c7cd 100644 --- a/content/docs/how-to/send-messages/api-sendFile-code.md +++ b/content/docs/how-to/send-messages/api-sendFile-code.md @@ -1,107 +1,116 @@ -
- -{{< tabs "send-file-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendFile' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "caption": "Check this out!", - "file": { - "mimetype": "application/pdf", - "filename": "document.pdf", - "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendFile" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "caption": "Check this out!", - "file": { - "mimetype": "application/pdf", - "filename": "document.pdf", - "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" - } -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendFile"; -const data = { - session: "default", - chatId: "12132132130@c.us", - caption: "Check this out!", - file: { - mimetype: "application/pdf", - filename: "document.pdf", - url: "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "caption" => "Check this out!", - "file" => [ - "mimetype" => "application/pdf", - "filename" => "document.pdf", - "url" => "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-file-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendFile' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "caption": "Check this out!", + "file": { + "mimetype": "application/pdf", + "filename": "document.pdf", + "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendFile" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "caption": "Check this out!", + "file": { + "mimetype": "application/pdf", + "filename": "document.pdf", + "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendFile"; +const data = { + session: "default", + chatId: "12132132130@c.us", + caption: "Check this out!", + file: { + mimetype: "application/pdf", + filename: "document.pdf", + url: "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "caption" => "Check this out!", + "file" => [ + "mimetype" => "application/pdf", + "filename" => "document.pdf", + "url" => "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/document.pdf" + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendImage-code.md b/content/docs/how-to/send-messages/api-sendImage-code.md index c70ce1b6b..3ada1f71a 100644 --- a/content/docs/how-to/send-messages/api-sendImage-code.md +++ b/content/docs/how-to/send-messages/api-sendImage-code.md @@ -1,107 +1,116 @@ -
- -{{< tabs "send-image-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendImage' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - "filename": "filename.jpeg" - }, - "caption": "Check out this image!" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendImage" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - "filename": "filename.jpeg" - }, - "caption": "Check out this image!" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendImage"; -const data = { - session: "default", - chatId: "12132132130@c.us", - file: { - mimetype: "image/jpeg", - url: "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - filename: "filename.jpeg" - }, - caption: "Check out this image!" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "file" => [ - "mimetype" => "image/jpeg", - "url" => "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - "filename" => "filename.jpeg" - ], - "caption" => "Check out this image!" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} +
+ +{{< tabs "send-image-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendImage' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + "filename": "filename.jpeg" + }, + "caption": "Check out this image!" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendImage" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + "filename": "filename.jpeg" + }, + "caption": "Check out this image!" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendImage"; +const data = { + session: "default", + chatId: "12132132130@c.us", + file: { + mimetype: "image/jpeg", + url: "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + filename: "filename.jpeg" + }, + caption: "Check out this image!" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "file" => [ + "mimetype" => "image/jpeg", + "url" => "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + "filename" => "filename.jpeg" + ], + "caption" => "Check out this image!" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md b/content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md index 8b8cc3493..1afb6a92c 100644 --- a/content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md +++ b/content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md @@ -1,123 +1,132 @@ -
- -{{< tabs "send-link-custom-preview-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/send/link-custom-preview' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Check this out! https://github.com/", - "linkPreviewHighQuality": true, - "preview": { - "url": "https://github.com/", - "title": "Your Title", - "description": "Check this out, this is a custom link preview!", - "image": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/send/link-custom-preview" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "text": "Check this out! https://github.com/", - "linkPreviewHighQuality": True, - "preview": { - "url": "https://github.com/", - "title": "Your Title", - "description": "Check this out, this is a custom link preview!", - "image": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - } -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/send/link-custom-preview"; -const data = { - session: "default", - chatId: "12132132130@c.us", - text: "Check this out! https://github.com/", - linkPreviewHighQuality: true, - preview: { - url: "https://github.com/", - title: "Your Title", - description: "Check this out, this is a custom link preview!", - image: { - url: "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "text" => "Check this out! https://github.com/", - "linkPreviewHighQuality" => true, - "preview" => [ - "url" => "https://github.com/", - "title" => "Your Title", - "description" => "Check this out, this is a custom link preview!", - "image" => [ - "url" => "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - ] - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-link-custom-preview-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/send/link-custom-preview' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Check this out! https://github.com/", + "linkPreviewHighQuality": true, + "preview": { + "url": "https://github.com/", + "title": "Your Title", + "description": "Check this out, this is a custom link preview!", + "image": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/send/link-custom-preview" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "text": "Check this out! https://github.com/", + "linkPreviewHighQuality": True, + "preview": { + "url": "https://github.com/", + "title": "Your Title", + "description": "Check this out, this is a custom link preview!", + "image": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/send/link-custom-preview"; +const data = { + session: "default", + chatId: "12132132130@c.us", + text: "Check this out! https://github.com/", + linkPreviewHighQuality: true, + preview: { + url: "https://github.com/", + title: "Your Title", + description: "Check this out, this is a custom link preview!", + image: { + url: "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "text" => "Check this out! https://github.com/", + "linkPreviewHighQuality" => true, + "preview" => [ + "url" => "https://github.com/", + "title" => "Your Title", + "description" => "Check this out, this is a custom link preview!", + "image" => [ + "url" => "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + ] + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendLocation-code.md b/content/docs/how-to/send-messages/api-sendLocation-code.md index 45dd69bc4..38b0f23cb 100644 --- a/content/docs/how-to/send-messages/api-sendLocation-code.md +++ b/content/docs/how-to/send-messages/api-sendLocation-code.md @@ -1,95 +1,104 @@ -
- -{{< tabs "send-location-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendLocation' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "latitude": 38.8937255, - "longitude": -77.0969763, - "title": "Our office" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendLocation" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "latitude": 38.8937255, - "longitude": -77.0969763, - "title": "Our office" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendLocation"; -const data = { - session: "default", - chatId: "12132132130@c.us", - latitude: 38.8937255, - longitude: -77.0969763, - title: "Our office" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "latitude" => 38.8937255, - "longitude" => -77.0969763, - "title" => "Our office" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-location-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendLocation' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "latitude": 38.8937255, + "longitude": -77.0969763, + "title": "Our office" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendLocation" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "latitude": 38.8937255, + "longitude": -77.0969763, + "title": "Our office" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendLocation"; +const data = { + session: "default", + chatId: "12132132130@c.us", + latitude: 38.8937255, + longitude: -77.0969763, + title: "Our office" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "latitude" => 38.8937255, + "longitude" => -77.0969763, + "title" => "Our office" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendPoll-code.md b/content/docs/how-to/send-messages/api-sendPoll-code.md index 362ed98ed..83e17ee21 100644 --- a/content/docs/how-to/send-messages/api-sendPoll-code.md +++ b/content/docs/how-to/send-messages/api-sendPoll-code.md @@ -1,119 +1,124 @@ -
- -{{< tabs "send-poll-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendPoll' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "poll": { - "name": "How are you?", - "options": [ - "Awesome!", - "Good!", - "Not bad!" - ], - "multipleAnswers": false - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendPoll" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "poll": { - "name": "How are you?", - "options": [ - "Awesome!", - "Good!", - "Not bad!" - ], - "multipleAnswers": False - } -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendPoll"; -const data = { - session: "default", - chatId: "12132132130@c.us", - poll: { - name: "How are you?", - options: [ - "Awesome!", - "Good!", - "Not bad!" - ], - multipleAnswers: false - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "poll" => [ - "name" => "How are you?", - "options" => [ - "Awesome!", - "Good!", - "Not bad!" - ], - "multipleAnswers" => false - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-poll-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendPoll' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "poll": { + "name": "How are you?", + "options": [ + "Awesome!", + "Good!", + "Not bad!" + ], + "multipleAnswers": false + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendPoll" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "poll": { + "name": "How are you?", + "options": [ + "Awesome!", + "Good!", + "Not bad!" + ], + "multipleAnswers": False + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendPoll"; +const data = { + session: "default", + chatId: "12132132130@c.us", + poll: { + name: "How are you?", + options: ["Awesome!", "Good!", "Not bad!"], + multipleAnswers: false + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "poll" => [ + "name" => "How are you?", + "options" => [ + "Awesome!", + "Good!", + "Not bad!" + ], + "multipleAnswers" => false + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendSeen-code.md b/content/docs/how-to/send-messages/api-sendSeen-code.md index a6446d841..80bb9ad0d 100644 --- a/content/docs/how-to/send-messages/api-sendSeen-code.md +++ b/content/docs/how-to/send-messages/api-sendSeen-code.md @@ -1,83 +1,92 @@ -
- -{{< tabs "send-seen-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendSeen' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendSeen" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendSeen"; -const data = { - session: "default", - chatId: "12132132130@c.us" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-seen-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendSeen' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendSeen" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendSeen"; +const data = { + session: "default", + chatId: "12132132130@c.us" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendText-code.md b/content/docs/how-to/send-messages/api-sendText-code.md index 2d3776d88..2dd2c4617 100644 --- a/content/docs/how-to/send-messages/api-sendText-code.md +++ b/content/docs/how-to/send-messages/api-sendText-code.md @@ -1,87 +1,96 @@ -
- -{{< tabs "send-text-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendText' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there!" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendText" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there!" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendText"; -const data = { - session: "default", - chatId: "12132132130@c.us", - text: "Hi there!" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "text" => "Hi there!" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} +
+ +{{< tabs "send-text-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendText' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there!" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendText" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there!" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendText"; +const data = { + session: "default", + chatId: "12132132130@c.us", + text: "Hi there!" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "text" => "Hi there!" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendVideo-code.md b/content/docs/how-to/send-messages/api-sendVideo-code.md index 5c5672947..8c8db3fb6 100644 --- a/content/docs/how-to/send-messages/api-sendVideo-code.md +++ b/content/docs/how-to/send-messages/api-sendVideo-code.md @@ -1,115 +1,124 @@ -
- -{{< tabs "send-video-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendVideo' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "caption": "Watch this video!", - "asNote": false, - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "convert": false -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendVideo" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "caption": "Watch this video!", - "asNote": False, - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "convert": False -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendVideo"; -const data = { - session: "default", - chatId: "12132132130@c.us", - caption: "Watch this video!", - asNote: false, - file: { - mimetype: "video/mp4", - filename: "video.mp4", - url: "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - convert: false -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "caption" => "Watch this video!", - "asNote" => false, - "file" => [ - "mimetype" => "video/mp4", - "filename" => "video.mp4", - "url" => "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - ], - "convert" => false -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-video-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendVideo' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "caption": "Watch this video!", + "asNote": false, + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "convert": false +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendVideo" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "caption": "Watch this video!", + "asNote": False, + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "convert": False +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendVideo"; +const data = { + session: "default", + chatId: "12132132130@c.us", + caption: "Watch this video!", + asNote: false, + file: { + mimetype: "video/mp4", + filename: "video.mp4", + url: "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + convert: false +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "caption" => "Watch this video!", + "asNote" => false, + "file" => [ + "mimetype" => "video/mp4", + "filename" => "video.mp4", + "url" => "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + ], + "convert" => false +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-sendVoice-code.md b/content/docs/how-to/send-messages/api-sendVoice-code.md index 3a7208dd8..e5db832df 100644 --- a/content/docs/how-to/send-messages/api-sendVoice-code.md +++ b/content/docs/how-to/send-messages/api-sendVoice-code.md @@ -1,103 +1,112 @@ -
- -{{< tabs "send-voice-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendVoice' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "chatId": "12132132130@c.us", - "file": { - "mimetype": "audio/ogg; codecs=opus", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - }, - "convert": false -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendVoice" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "chatId": "12132132130@c.us", - "file": { - "mimetype": "audio/ogg; codecs=opus", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - }, - "convert": False -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendVoice"; -const data = { - session: "default", - chatId: "12132132130@c.us", - file: { - mimetype: "audio/ogg; codecs=opus", - url: "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - }, - convert: false -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "chatId" => "12132132130@c.us", - "file" => [ - "mimetype" => "audio/ogg; codecs=opus", - "url" => "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - ], - "convert" => false -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "send-voice-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendVoice' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "chatId": "12132132130@c.us", + "file": { + "mimetype": "audio/ogg; codecs=opus", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + }, + "convert": false +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendVoice" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "chatId": "12132132130@c.us", + "file": { + "mimetype": "audio/ogg; codecs=opus", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + }, + "convert": False +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendVoice"; +const data = { + session: "default", + chatId: "12132132130@c.us", + file: { + mimetype: "audio/ogg; codecs=opus", + url: "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + }, + convert: false +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "chatId" => "12132132130@c.us", + "file" => [ + "mimetype" => "audio/ogg; codecs=opus", + "url" => "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + ], + "convert" => false +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/api-star-code.md b/content/docs/how-to/send-messages/api-star-code.md index 3857994c7..155b982ea 100644 --- a/content/docs/how-to/send-messages/api-star-code.md +++ b/content/docs/how-to/send-messages/api-star-code.md @@ -1,91 +1,100 @@ -
- -{{< tabs "star-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'PUT' \ - 'http://localhost:3000/api/star' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "session": "default", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "chatId": "12132132130@c.us", - "star": true -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/star" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "session": "default", - "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "chatId": "12132132130@c.us", - "star": True -} - -response = requests.put(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/star"; -const data = { - session: "default", - messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - chatId: "12132132130@c.us", - star: true -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.put(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", - "chatId" => "12132132130@c.us", - "star" => true -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "star-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'PUT' \ + 'http://localhost:3000/api/star' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "session": "default", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "chatId": "12132132130@c.us", + "star": true +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/star" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "session": "default", + "messageId": "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "chatId": "12132132130@c.us", + "star": True +} + +response = requests.put(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/star"; +const data = { + session: "default", + messageId: "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + chatId: "12132132130@c.us", + star: true +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .put(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "messageId" => "false_12132132130@c.us_AAAAAAAAAAAAAAAAAAAA", + "chatId" => "12132132130@c.us", + "star" => true +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/features.md b/content/docs/how-to/send-messages/features.md index 59e34038c..927ecc57c 100644 --- a/content/docs/how-to/send-messages/features.md +++ b/content/docs/how-to/send-messages/features.md @@ -1,34 +1,34 @@ -
-{{< details "**📤 Messages - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|-------------------------------------------------------------|:------------------------------------------------------------:|:-----:|:----:| -| `POST /api/sendText` | ✔️ | ✔️ | ✔️ | -| `POST /api/sendSeen` | ✔️ | ✔️ | ✔️ | -| `PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ✔️ | -| `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ✔️ | -| `POST /api/sendImage` | ➕ | ➕ | ➕ ️ | -| `POST /api/sendFile` | ➕ | ➕ | ➕ ️ | -| `POST /api/sendVoice` | ➕ | ➕ | ➕ ️ | -| `POST /api/sendVideo` | ➕ | ➕ | ➕ ️ | -| `POST /api/send/link-custom-preview` | | ➕ | ➕ ️ | -| `POST /api/forwardMessage` | ✔️
[#588](https://github.com/devlikeapro/waha/issues/588) | ✔️ | | -| `POST /api/sendLocation` | ✔️ | ✔️ | | -| `POST /api/startTyping` | ✔️ | ✔️ | ✔️ | -| `POST /api/stopTyping` | ✔️ | ✔️ | ✔️ | -| `POST /api/{session}/presence` | ✔️ | ✔️ | ✔️ | -| `POST /api/reaction` | ✔️ | ✔️ | ✔️ | -| `POST /api/star` | ✔️ | ✔️ | | -| `POST /api/sendContactVcard` | | ✔️ | ✔️ | -| `GET /api/messages` | ✔️ | ✔️¹ | | -| `GET /api/checkNumberStatus` | ✔️ | ✔️ | ✔️ | -| `POST /api/send/buttons/reply` | ➕ | | | -| `POST /api/sendButtons` | | | | -| `POST /api/{session}/media/convert/voice` | ➕ | ➕ | ➕ | -| `POST /api/{session}/media/convert/video` | ➕ | ➕ | ➕ | - -1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**📤 Messages - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ----------------------------------------------------------- | :----------------------------------------------------------: | :---: | :--: | +| `POST /api/sendText` | ✔️ | ✔️ | ✔️ | +| `POST /api/sendSeen` | ✔️ | ✔️ | ✔️ | +| `PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ✔️ | +| `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ✔️ | +| `POST /api/sendImage` | ➕ | ➕ | ➕ ️ | +| `POST /api/sendFile` | ➕ | ➕ | ➕ ️ | +| `POST /api/sendVoice` | ➕ | ➕ | ➕ ️ | +| `POST /api/sendVideo` | ➕ | ➕ | ➕ ️ | +| `POST /api/send/link-custom-preview` | | ➕ | ➕ ️ | +| `POST /api/forwardMessage` | ✔️
[#588](https://github.com/devlikeapro/waha/issues/588) | ✔️ | | +| `POST /api/sendLocation` | ✔️ | ✔️ | | +| `POST /api/startTyping` | ✔️ | ✔️ | ✔️ | +| `POST /api/stopTyping` | ✔️ | ✔️ | ✔️ | +| `POST /api/{session}/presence` | ✔️ | ✔️ | ✔️ | +| `POST /api/reaction` | ✔️ | ✔️ | ✔️ | +| `POST /api/star` | ✔️ | ✔️ | | +| `POST /api/sendContactVcard` | | ✔️ | ✔️ | +| `GET /api/messages` | ✔️ | ✔️¹ | | +| `GET /api/checkNumberStatus` | ✔️ | ✔️ | ✔️ | +| `POST /api/send/buttons/reply` | ➕ | | | +| `POST /api/sendButtons` | | | | +| `POST /api/{session}/media/convert/voice` | ➕ | ➕ | ➕ | +| `POST /api/{session}/media/convert/video` | ➕ | ➕ | ➕ | + +1. **NOWEB** - you need to [**Enable Store**]({{< relref "/docs/engines/noweb#store" >}}) to get **chats, contacts and messages** + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/send-messages/index.md b/content/docs/how-to/send-messages/index.md index b4f15f616..242b8e667 100644 --- a/content/docs/how-to/send-messages/index.md +++ b/content/docs/how-to/send-messages/index.md @@ -1,958 +1,991 @@ ---- -title: "📤 Send messages" -description: "Describe how to send messages." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 220 -images: ["messages.jpg"] -slug: send-messages ---- - -We assume that you've already run the Docker container and authenticated the session with a QR code. - -If you haven't yet - please follow the steps from [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). - -
-{{< img lqip="21x webp q20" src="messages.jpg" alt="WhatsApp Messages" >}} -
- -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/send-messages/features.md" >}} - -## Fields - -There are common fields that you can find in almost all requests: - -```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 version supports only `default` session. -- Plus 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 - -`chatId` - this is a phone number or Group identifier where you're sending the message. - -- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at - the end. - For phone number `12132132131` the `chatId` is `12132132131@c.us` -- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**, just convert it to `@c.us` to work - with that properly. Kindly don't use it in `chatId` when sending messages -- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. -- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that - type of ID along with communities functionality. -- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). - -👉 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. - -Read more -about [error sending text to half of Brazilian numbers (every number registered before 2012) ->](https://github.com/devlikeapro/waha/issues/238) - -### 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.url` field with public available URL for that file - -See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). - -### reply_to - -You can add the `reply_to` field in order to reply to a specific message. - -```json -{ - "chatId": "11111111111@c.us", - ... - "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" -} -``` - -`reply_to` is available in all messages - -## Send Seen - -If you get a new message via [**🔄 Events**]({{< relref "docs/how-to/events#message" >}}) -and want to reply to that message, you need to first send that you've seen the message -(double green tick) - read [**⚠️ How to Avoid Blocking**]({{< relref "docs/overview/how-to-avoid-blocking" >}}) - -{{< callout context="note" title="Read all unread messages in the chat" >}} -Check -[**💬 Chats - Read messages**]({{< relref "/docs/how-to/chats#read-messages" >}}) API -to read messages without providing message id. -{{< /callout >}} - -```http request -POST /api/sendSeen -``` - -Send seen (read a message) for **all unread** messages **older than 7 days** (30 max for DM, 100 max for groups) -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us" -} -``` - -In **NOWEB** and **GOWS** -[**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) -you can control what messages to read by using `messagesIds` (or deprecated `messageId`) field: - -Send seen for **direct message**: - -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "messageIds": [ - "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - ] -} -``` - -Send seen for **Group Message** you need to provide `participant` field: - -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@g.us", - "messageIds": [ - "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA_33333333333@c.us" - ], - "participant": "33333333333@c.us" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendSeen-code.md" >}} - -## Send Text -Use the API to send text messages to the chat. - -```http request -POST /api/sendText -``` - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there!" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendText-code.md" >}} - -Here's some additional options: -- `reply_to: false_1111@c.us_AAA` - to reply on a message -- `mentions` - to mention a contact in a group -- `linkPreview: false` - to disable preview generation for links in the message - -### Link preview - -```http request -POST /api/sendText -``` - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there!", - "linkPreview": true, - "linkPreviewHighQuality": true -} -``` - -If the text has a link - it generates a preview for that link. You adjust the behaviour by setting -- `linkPreview: true` - to enable link preview -- `linkPreviewHighQuality: true` - to enable high-quality link preview (requires additional upload to WA servers) - -{{< details-html "🖼️ **Link Preview** Screenshot" >}} -{{< imgo src="whatsapp-link-preview.jpg" alt="WhatsApp Link Preview" >}} -{{< /details-html >}} - -{{< callout context="tip" title="Custom Link Preview" icon="outline/info-circle" >}} -If link preview generation process fails or site protects it with captcha - you can generate your own preview and -[**Send Custom Link Preview**](#send-link-custom-preview) -{{< /callout >}} - - -### Reply on message - -To reply on a message - add `reply_to` field: - -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "text": "Reply text" -} -``` - -### Mention contact - -If you send a message in a group and want to mention a participant in the message - -use `mentions` field for that in `POST /api/sendText` request. - -Please note that you MUST mention a number in the text as well in the format `@2132132130` and -also mention it in `mentions` in format `2132132130@c.us` - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there! @2132132130", - "mentions": [ - "2132132130@c.us" - ] -} -``` - -## Send Image -Use API to send images to the chat. - -```http request -POST /api/sendImage -``` - -You can send images in two ways: - -1. Provide a **URL** for the image. -2. Encode the whole file content into **BASE64** and send it in the request body. - -{{< tabs "send-image-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", - "filename": "filename.jpeg" - }, - "caption": "string" -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "file": { - "mimetype": "image/jpeg", - "filename": "filename.jpeg", - "data": "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" - }, - "caption": "string" -} -``` -{{< /tab >}} -{{< /tabs >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendImage-code.md" >}} - -## Send Voice -Use API to send voice messages to the chat. - -```http request -POST /api/sendVoice -``` - -You can send voice messages in two ways: - -1. Provide a **URL** for the voice. -2. Encode the whole file content into **BASE64** and send it in the request body. - - -{{< tabs "send-voice-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "file": { - "mimetype": "audio/ogg; codecs=opus", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - }, - "convert": false -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "chatId": "11111111111@c.us", - "file": { - "mimetype": "audio/ogg; codecs=opus", - "filename": "voice-message.mp3", - "data": "T2dnUwACAAAAAAAAAAAAX3UXAAAAAJiLB2IBE09wdXNIZWFkAQE4AcBdAAAAAABPZ2dTAAAAAAAAAAAAAABfdRcBAAAAVVl7zwE+T3B1c1RhZ3MNAAAATGF2ZjYwLjE2LjEwMAEAAAAdAAAAZW5jb2Rlcj1MYXZjNjAuMzEuMTAyIGxpYm9wdXNPZ2dTAACAuwAAAAAAAABfdRcCAAAAL42/Ojb/Jof/PYaH/yKA4fPMenp+e8z/CrOztL64wbO2t7jB19j5yIF5e917fPyCd3FubGxtbW1tbW3Yf/rBBvEI8G4VvV7oPr9JMoJLyZyZgMawSmQ2Pmj/cOTSbOV1l+ysyV7ik2gSuPpnU/ZhEc6XLz3N0I89PJg6bOlAf72AQHALmc8mmhekvqT/ga1f9vnjhN3IhOGelIRrJZ0oQCRqyeCsDAZPE1WPEdY+ON/2LeqlcaLnM3UokC91fHEqgVe7VyeHT7R3W3VYnKKpfLJcyBEXJcTCDWqEP+WeD8lyvy1i+h181AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5djjV/mYbkuyKag0igDQJswpb4gB7pi47FR55KMIIQ3de4el9eWqSFx62UFlTOcf/jPYFT3m+hfQFZ2yDZDhOtHex3KQLLJ/J4niMkX0BTzP/gfrD0k1EgvjKdhv1fJTvt2m9ey3UjW86un58ddELy9aStoFDcFnqEv5rBA/4H4PDGI7I5MTpXN8GLOEnWvEKtYwnhqNPS/wb5Sdm2Ga/y2Ge30Trcb9rIoQmhFMNoWep7qrG+n9R+Fl7uxxPY4nFN8Bk5dk0zyfUVBpFv+Ftym+zdQ9KT2HBd8gREKMeeuladiKBq6vjsYqeqjtWxShywnCYrJHzcki4aujfCC4nFQ25zN32yb8ESZmuawrKGOHnJtU1tFVLy//MVS4BOIbZfqZ/rbdtOOZ9xYGPOSo0yAE1wTcv8V83EgPdQqRbQywC32iw/V0cVGKYDjmZEkcgFKIyTbSfNBy0gg8QFN6cLSNOavKGcLbsRIFRF6HmCCPFPYhlqNnP7SHTwvSEvEx5vOgYrKF2HRU3fNWkkgAS4lL6DfNL7ZEEL7JpardJ6KkmK6/qNNY1qcTGMDnMa1SCcsnf8Tz5RynKgzyvwhHpvo/i01jAVotOnmSW9/a1dTfRGiSlvXLPwgc5bCU45CPwj+eYe7/9wxCT+wTLdAQeMPkNKEfcE4KcQX7MfwhYr1InVmvoopmpkHPTj56hw9iMjJ67y01KMz/RrGateDYgvHQmCpMwew+mXE2JKRb1jSuED/m6DjxFHqP5sOjCVLjkoKCKmLG/FqdnsTSKzEKgKvNj9aBEXh5Az0R1DYKKxid6ByiRtJCzltLMsSWm0Ei9il7uLAY8NFDzedOgU1TokCKTX7ifaL2mxId3kWHPvysigBVPtCT+XLVKzyV5gE1Hc6xYNiCY+KHPhxAmKUugQIEOpdZqt6qiW4paNTkZ/7loFb3xUwaksTu+15xOhXCXUh/3PWIFW36Q5uCCQmjGQFWe292iU3OulVH2woTcmllotMwjTV/AykeDcsFKr5mNuIp0hgNg0EOYhClPAeoSNWxnNqFt2Q3VnXq5QmdmDAfwr+hFXlctfycYtiJn1k5ZbtsbjCLlyC2KCcuZKt0PuH0pYgYYkUoug/7Opws014C0mchZ3F1hn/MEgwiK2Nm5XQGSttdYONpbWVH06FBXbwGyfJTcU2fON1s0hxkjiUI+vxrywSKdCBVMw/tY9QEknp7IvlSqXhrOpz28eamGSaBIhFwixiv3EpOJbXaq79m4RF3JvcpEYgGbAmof/OVWUOrf/M4M/m2tjAFYV8TXWTtiFWbjFyNOU5rSFekTRU2zKu9ErQ54iMfuykMPzUgXZH2zqHROmlF7MG3X3xdv/SgwrykIDk9WWPHp464oPzQMGyFyBgUCowVQtI4/XXVDjxfmvQp7zrL13drWaJCfEKg+xjl6Jfac2UcxV9VU9QbiY1fNYK5KwlVCWLYhvgL8SRsMwbB6B9CNGZfHuJmSym/ytSKcszOHTSCF+0ammQX5wdOpFSgYGXMPCOa32Ydklc/xB71b9ZmZOt+AL22Nja3e0cX19xJstZda58leu/deltuOslpv1TxoRFgX8n3hh9TICfoa0BKVT4j5HFBm8Q5phkg4aUef2huRNiJ5zFMm9BWwfLy4d3SqVyo+m/oVcrG02ZJ/MLWT35q/H0MD/uUgMz+FPQgTWE5oOXlP8RMkrc7mSnWwuBVZPEpwDEiHMupIYuflzn0YQZsT8BLsY92kvMk9pZGBzSrE8c0V8Tg6uoqn6jOXAoQGKfBDYAzI09+767RR2WyI+sexBGif0T6Z3PceetkHlxtUszM3s7wg4h2sY+Tc6yDg78/NiD0pkhj0GVqrLTgDHzPZ7AahEPFVGUGIqtuwGqVuWHC7qGEzKvD9lhnegfp8IoXGAQN3+oPE2zrL0QBmO8aQNjftUK6FRLXAhkzhO5kVVTK3M63k+UE0d6UEtOPXirRoLRBiYEUAsruQF4ZlzQvk/qK2Yz/36Wilk6cHnMG64cE8JzMp5wUlcPHof+4I14UzlazMQM4oMF1o+cv0LNzTIjGrGd3dfZGOdjXE4HmnI8SokU/0OKFm3gRSAjqBCksXw9eyqEYijAAz7AWcoQQg1KdQnQiYbC5Incmu179FZIxeVEg3Tx4dUFc//P4RHhVdlw8rRrKa0IskW5kiwdssru9fsDg/qG37Ay/3fc9vRa5R43H/XJspnLUp7lIFsZtdQZ6DWU9mRC+vaOysBl7SY2kldjfK8Hjw7KufRNVAHhMbkMaFwHloFv0+h3rGPDWK+hK+FolJM2XzGasKxCacTQVeT3fogUL2Qn+VdVENz7+eV5OgK83g1WDoWpTABGl7frsoegTuufgwQztUZi/j5eiVbZnr6u6t1dwzBR0Bxv+han+vxrWkrcqqBUpleCQDUylJkQxxcxg068P6uPwXt4XWCd2WDsAJUhgusbtCR3gWizCeygQzRD9XlAcqwQzt/PuwNbZzhw91NyWnQjo1oaQ+hv0G3DAUTCWg0zd+tjV/8UacT468IyOJdXHTUoq2c9SFwarmNJ6oaFHHBUwSDeYNlIurF59S/j3c4YoWuBj0RGGH4Rae0P1D6NlfAGnKvnPDZiOKkZ6/G937H9JrSImHMJTA5byFxmt9kQi/nBZIgH1BTKaQFLioO56r7jXTTsW1cD65JXu2Os5j/xp6W42EU/5JUexB88hxJ6nhHiPXAwyd+HHYFfNgRdty5hnRe8f5JTY8S9X2VwA2+MLm6oUd2QROzPAYhZJV/KOlXBq7Gnu+AKn2bf98NxAYxXFdizxppn2CtTVZub0QJM41zz8DuvXzyIpmGnkLLsFjSCsrALY68eTzoS1C2c984xaWTrXn7V7Lz1bQSafOVOMBnwx59PLj/J3LNfJCqmlvjaoSQHsi13djeWAHnbNbt2Y9YMWKPksS0x+i3zCxktnY62LH4cqU+5S46oIPOjQRJ0eEREktBy13/CNVf0uB4DJjnVU9EH/tGjraYl/gCIAXAzY7FN7rQqj37gAReY/bD2+QQVwoxzYoH5YrdAbSGTrUdks9q3dv7ZJkmjD7kATIJXY/4pi0OmdAIR43l5cEhOVEHbcjG20eY+iHUyGwmEcazxeulyNdn31Cpmu+Vhu2M2JGKZTSM0SCa5FebrjD4wX4il2ZA0DUnoa7A7Y9KBuwNqJkew7B3+7s1rcSAAkSw6rnq5uFbHCN5leMaEa/5MK2SCTpB+FEYmRVCo5DOAvBa3tR5E7Sgu43RJ5o4uo2I0MrnNI1B3I9ttDNv7c+hu6XBPnBd1ro59ksGMjnwkMfkJjqcFyzMF74YzZ7I65znXVrJM7Ht6hoAPZeIjIFuC9c2WIoqCB/JBN4Sj4Maz4EcxXGPblbSi8k2ZcqXpOa7VJZcmIkQ2anc53c4Sy0GP7cP38I6gyiSLbXUWNffVtgvyJb1iq6A7YfEogqM3Kgem+B3AgVV1c67goCtUXuRZroI7REHGJ/u5xXDdgo9Nntc13vY77Tlk5WQr2m/lIpFjGVEn9j7Qg0jmQg3eKw3Uc4y1CQbzIkkx80CbT56kxbCJy+y8DDKR0F0+PMIbZyTzPUsogmk57S3k1y8wuzd86o/2/TGpg80wYfUgEPMbtGpnyQpvZs1sTbNsactYKvrfzfc1xhldDs6L4IpirO4irtOAoaJ4bW2ssuXi/pbOv55vZa2v0Csg0MvsSk8fizrpwS2kQoNlMwSZEGNsHAoTgDpp4Ue8kqrN2UyCIMVXRIh71JPqoJ1czJwMQdGMVKFAckOeriEHNRiESW3vXI9K22NXSKBxvLe6VfEp7XavCQnJFaLxtAFgQ8G7yNwd05M/TxJrJ3abL9nwU5eDiIOmoJEXZe7JUKb75EzaTIeavXnaAmH7eH3vatPIulzZAN3V3EQP0B6WgnykR6HuUAhUJeMqEDe5NYVW13qIVPkicsMsVvrCD2BNmDWvUnHFca53Chd9gJlLrowXFpB5qYS+y9KLV7P2J9KI5BF0Oazf3OdIv+aAFva9luhEmvGsPfNqgHNfY2Ic49IQBjjeuVnnVU1nZjAnbkeCNNvW1jXQB9KZY0ALZWUkzdSbqmwdvKf7TYqacMcnGMQt99GeVrFzoN8M+a42Xree0PyfG/uW8QUDRwVp+pIhv/0nZJjk5IGzU5cFKCk/b18hFHsnugpSY1UyTfr+IBPu4w8wvhicI+T7ncesfrMsg4ZjZF3zCPkUnA28BTD5Qb0OsHfHnPhC4wZBf6cO2VyMICoUhvPH8Is+GjRwM29jY8y1tiWobsBQFqIQeqKVJfWmAHJEWCkTdEB1zzBKYcs3LgMoGWHP0nG5UzITfMsK2QP7tIgSQll0U7VpZq8mA3c2I8e8PV55PRRljsA1v3eVohD0lUQuuwUhW5+kMn8AIdbbuBziRYTj/qY1Zb2VkavoYYK1Zk4MvW96nIzRGXUQmV3V9AAed4h3x5vL9jcTchP8gGcS1Nf1uxGr3ExjF6afi7H4vogoklntcK1lpqZFE2djYgKXx3gNgfzIItuLWw4A3uG5r8zrmiKrahkxKyL2ObJuDxEGIS9U8fA4N96upF/8BkxJsnXweDu7y8NXFszU8vgjDNlEwV0AF1Sth5G/mr6Owxpy7WddTHakN3A1LWHPWiOo81E8YC5N6t6MCXMooP+ao27VqzeVOwQ3ZOlLUoK1O1GrkQ5A2VKblT7RKTlWkaI1fxG9Kvi6tCkuHnJEu2EdkeaP93Q74iiUuspp4t+lw1Z7RiZDDZzLiDNXY2ICOUtlKE3H1rzxGDGISBdtT6qEIvEMCl+dBoQyFVo9fkYIGdTlF8qm0qeUalUceuINfkW5saiwKRn0WLnt5HxLG/PJsc6rcG5xP8ao3ubuk616t84ACDLdzq9lOuknV0gnTRn5Lp2Ijtl5VCxRipEsrVXD/os1pIM9o5uPyNUt90iusAvKUkfUtqYi8VCi9xdFlzj+vgMnlqXmqhrHsQQaDK2VaUTW3HbT0F73KEIUylz/4iKTb2Nj9LRM1KjFpHNzk66dViBQo/f7LtFHMb3eTIpd/Zo9ewF6MwiK7t9fOkYKm//t7qFxFCVvNrPQ0PVZ9EpJDkMDU+Jt2WUfpO7iYry5oolIOv3cbBRgRgdYOI/+vitPxuPVyhBwpUDjtGQtvWmNbyYQ7xMDG4OW3HJ7HJ2V26mh4mXdk5tuPeFfPijvLqDT0jbmWZVgMHGA99/yf7l0ni9xGjoOJF2bcWjqLBo4ExtHDUt9adU0IiphZCT70tAyj4tjZcB6tQYN+z3kX8DA7S/EI2C2X1QatU90fy2GEN2EM/mjypomOg1rtyRxMJBx8UHz19dI/FeLqap2Dgqtxmi3r2CdnTuceTz+/okOIPW9+noNst4H2OGyzsd1yh6Tn92rKnGx4L1dJfCJmb+iC+Qzomjfb6qHz1KoCQAcP9S09cnGJCM4hdsEaFNm3uB1RkQ2HK1/kRBxWcDfmYZRJWzx9dHxv0bEP3Kg57qY0gZWWt2n82O3O3NK/6RcsPuKBAOwXoCcHzv0MdUeQmXoFEb3GclmcjKEPZomo3c/98vrPG2rz12zw+WxkqTZmSmv0nDYqc46OvRX1d1F0b+po0mY0alDbKAG6z8i6hgEutOVhMgOCIPfd3fJHUYfZ/w+mN78SIUqJdLl7qN/XVcrHjv0bkYOFhYqAedkYnt/9YBNYROIkdA43i4CqBqcaKV8RfiZEjYtOIrvgLGwU+sWojW1UsaeSEmj5IgDY7lW1XuyZTBkhTV0odleEm+klqtbZfGqur0hCjkuICgPYH36Q0X6bm9veUxdsc3ct16yiwd/YxAzIN+pTgHdkBXwYWNC73a0uCVwwZvRyrsmDo4B5QLN8KFvt7E5LNRvSSFkKc09t05b7VgiHaHcUOu+djmzsL8Bdhg/IuIVX7Cfl/fYX54Cx6fTM+Bx20a+r8GVJ5kHfBqJL2vwaIz8CbCa6T9JWCkGiVjK4Hbu5vIHNW95ANB3Y6qsShswOpdn6F+KWi2vf/TeYr2CCQZD5X4Z+MR4aSOZ93QzKim+nCz859hiDFwfbEm3bXjJ+EfWIs0LzFeLF3IqkZus1pJ1RHQJeAZUEInM0p9Uo6jUCmOcMSpvNZrFThHNX3eCJpy8cEZGJasQAdFxgv5YJgHcjMbSBOaK2+PgicDbu7xXUDVcP8sXYOesj3+Crgjjuapqo3iP9bCRIkeyk4OZtIsngY56CjydI2yX3guY0bpRJ2PTT03AawSfNyDGc6MZ6XQMynP2xmN7+khtEAfEUOyXV44I6HLOzaGzh8qP5D97+Sk5BlibesB8DqCXtIw2vR46nLTfAN0RD8Nmq3w7BQ8WDrDJyAMP73Mr3UappHUzGMFpaKe7YiYRgZ2OvK/HU9ASsYq9ZzFvFyM2m+UD3uyc3sd6rqhJlUwHLheztgX5mRvCNU3B3Bb5a06cC3GxxldTuKA+YnDqG4oSuijNOCS6IWPd5Ljuw7N+pLUV+XohEb9j0qt71dUjdhkuvovfiGOzmxwUTErRA6S+2+kBAaDZqnGG1Bt1j4f3QeW3SJCkztXRD9urPKCsrO4xPgnxonpkVgEjQ3is7GbFMoF08h+cJO81obLoniJs5QIlUpnGVwU/WqqmBZP9vzew728h+LVUZk0D1dLhGcRxHeBOMfQAhe9C2rPlXTR57ACkNPUIrcdBHXn3hhPz7BRBedtBtmdgwfwVniDirYOPF/sFlJqA57UwNUT5BXerTEHgMgbWXJF/Iy8RP03HGKWjFtH2msgPL9zxc/4SD2PQjkhV/CN5q4qM+igRMLV2CaW9rZHf4iAhm1H9nY8vK4RbMhUi458tWqB/++/gfmYyLRFuppA719eLnN+AZcCvFTjrUe0Zhm2JN8mFVstivSKwD/lOKWJNOgKd8a6WgPKSb+a0Zxc+HhcT3DF7ec9cQu4bfmyoEHpekOkhsGIVzsg/CLr8VQ+26qNdtIlRaTcavAeOvY5su59aHVylKXK+Rrr38S0xiMVu7Ie7D6vFqMdwlZSDNe+RHOZktsL0UoO0KfZ+XfCuepKg7Rc6gEMYWNoElwWSn2Hbx9rCjtkm0HI7b/Y4JibgXuQRIRkc+Yuc8gC9N3vsBDTGV0ggomTyqoqC2SYIrtNiKzsUlL6aH067pqAnwyJp8z7Zzn3lVUWUCpyKj6KDqGZobC1O1Pmxpac/4JyRMpzCSeG0nvhY4qJVd1UuPdW0Qk6NuH4Hvl6gY+qds9M9gmumZiH7i3lbIlmghqBaplK3NV/KWSUXrb1XS0u5ki5pLuGG6Xn+IqkiQYoqlYZQEcLhbZtPDpa6knDOuTeZXmtZ1LONDnwSPALUw8cK/Jiqd/sN/HPN2FXOVWttijyzJtCQ6sJSV1J2IGIIzKVgycvNN4taEaxKi2HBeId03Gvu37re8Bk2iTMNAtH3xADRs+jTqHrYu2Qq17KlS116JqoF4RkhgVXoKqVYmZ8S3A4IMSI3FkPRgvLB6rDGhMYuUuX+xgRPT+XynHbWoj4l7517TLYHZhxV5ywwIiTAMwJI+AGq6FWoLsaTo2hD0QI/XUXx0+2D2qrJDwQ7DDGezYIaaAVN/cUqB7XblFAHO/2R6W04FUMuVPKDtatyp3dYGJZCXjRP6+M+k8uI6w8wFgArmdYDz555/SJ3G+sKL7N7YVFGmH0XFbRjV/UGcaR0bkVqB+g6FmZD8N37RAvHif29f2TrRm9z/pWlLKmrE+8YiA9zvdsKbURHdKHGKYiAjE36xyys5BZ1pm7Pvs1WKgENAckwkQwjuvkmec88IcAclLMX6bYBAMKZojKPDzGDgtrGerC9eDlqmII9ZY+3/0N3YPXsU3BYPUyRcmuXD0xgd3AGXkdBDHT4vIXjD6/VQxWx0YPm7OXni/9avXQ/yhCiW6PL2efjfuCq8dbTJcpgY3MGW1/g4MzMy87luaHDAtwrtHjHUpAgqRTgJdKeVrIW4b/CFrIxaTVNWnbumyAItlEc7Js1Im8fd2CKGPEUrkZUHwdCQpiB5dayMhsmktBh82udwOYsEqIwk70yD0ieGTQqVJLUdy/YfDd857l2kXSIaXtSjOSNji6tqi12RGXN4bsRzQngp4nIiJhM2Etf0Gka6Y76M6uH/OGpG8Cka7O/5sDEXqMcpfNEs8FH6iaBhjue12HD5jl+WuaNll1KiaZg2i0bsyYpeneEgANuUQZh/O43l2oZwi0DxIuqm8nz2KN36INDYv1bpCuUKsizFFC8YofeCCYg/oTJ464ddUJw2hrih6D72fKCTD3r4mgXaeKMnKnd6FDy252ThCx9YNq9B1GLAsbDx6LmNpUTQ9R2JLcoZkhMKYfKOqxS/cKw+2uurPJPEGBYE769SbUFOzfOg2UoukK6disPtyfTcXmMitMkxBU99CBpdHPsxq18pvxZgjwytAoekeZS17n3KmUAvSP7+x7qUvqvBGdNlrarYhardo+M1QP99Qx9zc3X5Nn7NlgHAvIzK0n85TGYSFyG93yFg0ymRN8NnKI7UNxAi6eSCrWbHxl45LXk8H6RZb0BsA47EK1jTNZakkcoX0paOEHvsCGXqwyRGRMQA9Idymb3WAr24XQDtgsfsbtB0xRNzyYjhmhYv00LYgvFjLiOotQ+5S2n4bAUoMRX0GL3yg+Rb9eRzIpZ86Iua8Ewnp3poABSpBI3maJRm9GIv6kMX+IyT5ZW88c7sx7TIyKFr8XUA+zVHqmnNiQYzB3vFBiKZXfJLcOmI+JGF3Ok9CNab+ZE2i0C2TjYuVUKadm+Qrdtg/s/g2ImfICovydbmWV6jIjYFQlzBsrSRLdjaGJONSpqhORIYBlo9SUkO7KTw0vTbKWuZpwCqXx1oNwEo/I6lu6ssPW/c2wEG4dhYmSHu/uW6h0KSZpKWonouPffaHWcMjFgPi7v2RTRigutUzk7mgbEG27vgyrYETxNJcIjcpvcM/jBFFISTNVgEa9DhHXCHPiP86fwno729QksRRSgALIWV+GgrzDtgn9xrtunJXySIdyinQ1zFTx1BDfSnyK9Y3TFtjlug++mqe3hVGf/rqP49HmZVWllMhNJ4QW8wTEsulA/1cvG/+Gmx9IYIRYu6148dPvJuIQEiEkQvCZBg2IW/z8jaFsZ+XA4HS7C0D+F0wjiAjNPX42QbaEJ8qZ2Mvbtfpv/XlMw6smEQvO021acjJlb4QJK2ObPZFrlIj5rBbQYEbJBnMhKTih0jr97rhovU/75tKu8fAsnFNd4+unB0KY91DyU5w5Lkgx+4lm/p3E3H241plcqcanX0uk86YNiC6hP0zje9yhwxIhF4E3SejK+JXFshwdnZRV++GW5GSAX6rF76PI+rGaNuDpWuM4t1A8NkxcA2dY0rpeSmqAGx6N5161bMj7MXaL+8f1zMRyyM9xtLe3R/s/xwpOxBCQiOVr0+mW+HoZfePHi/labmmbNr9djg2IVg9cgnoBcHl1r2T285oqBDV98+68i+INNkFcR93GHtNBV1ER63wPSO1PPqDB2DO4MNDMxHDJCGLtEjIqZ8ZEG7c3gwm2RYYoFsXBcwdSjmNIEz2CQqaglPfkDu4tZjSx7J3RlNUXfq0gFGng4Un+7YrbxbME5CMs5h3XOq1v6Hhg+Gf7p4QIfwd1mLmQuut6S/Fz4wuo+hd961gVeMHr1kHFGW6A7aapXJY6K8USSoTHK1wD8gDiHAkloX1Kq1nhSY3ixPmdtVroZDEEuASzl4b0zHpOmoLRn2eZU9BtiwGYfsXjdBW5C6j5ZnqiVGc/2xZRqE7GE8ASAIoqV5OUxdldS92gqr0cz+WWNVqYldIGIYkqHSFhyDtcKwzo0236NNN4nEe7TtcCHK/AH98a+6YgXJM6rSHIbVQxGHZOzxOzEshaHbFiwvBtiwV+4xL4srGUiuBiP/LtAFzF9Yb/+TNhKvFTuHO0n5yCfCF2PKazMxi+fDo/k0eMSukDEMSVDpCw5E6OFbeUabb9Gmm8TiPdp2uBDlfgD++NfdMSdJM6rSHIbVQxGHZOzxOzF1rDR/v2TbBtiwV+5B03B9ht/GKvRxoW8011g6/JzmcwHRWYo/uKYcDvvfxdVdkzAxmhpbAKMarUxK6Qrw1EqHSFhyDtcKwzo0230ZTTeJxHu07XAhyvwB/fGvumIFyTOq0hyG1UMRh2Ts8TsxvuDHNGyQSwbYsaZa2gJ9ohNMkrk4XPNia7PWrATeBuQQ9LU7Z/NQeoq/Qg2Nb3prntPPbYI2rM1WpiV0gYhiSodIWHInTAuMcbb6MppvE4j3adrgQ5X4A/vjX3TEC5JnatIchtVDEYdk7PE7MQiFYdkVuXkG2LGma/mg5e8Z6IjcM7fuq+RIuvDx9uizinuKOJKH3fq9tJOX3pH8GTk/KEQvBNHjErpSxj38b2VDpCw5E6fQWjjbfRlNN4nEe7TtcCHK/AH98a+6YgXJM6rSHIbVQxGHZOzxOzFRqfR9vvLnBtixqCSeDqcu2eK4lp2cic8Ik0AVhnQXHIQ22FXBDnv1R4wGNMMKC4+MKwi7ziaJo8YldIV4aiVDpCw5B2uFbeUabb9Gmm8TiPdp2uBDlfgD++NfdMQLkmdq0hyG1UMRh2Ts8Tsxms7HNGiaVQbYsbAj1NYrNxTHmE8zxCiniv63/c1q0FwgmiZ9dqcUMBxj/ZXDcRvwdEfGSXA0eEzZ6WMe/jeyodIWHIO1wrbyjTbfo003icR7tO1wIcr8Af3xr7piBckzqtIchtVDEYdk7PE7MQiDWdiRv4UG2LJFSxx/kHEURcLINCgPFHhpksGhaeh2LcqdjymyW9ni1TDL/f7xtwrinkdnvETVU2JXSFeGolQ6QsOQdrhWGY4236NNN4nEe7TtcCHK/AH98a+6YgXJM6rSHIbVQxGHZOzxOzFRp+x9OvRzBk9nZ1MAAAB3AQAAAAAAAF91FwMAAAAfkx2xNW1ucG5ubWxm/xp1ff8Bd+D/B5WOsMSz4ra3r+GunJzupLSx77xz+caP9J+rqKOjoaWeoq/Q2LJJEYQ4WOyyuBxSHL3mbwmZ6dDnOiiFKXbZfN4Ln6jRHzyKP7S7F49TSX6guq1MSuk16AQo+VDpCw5E6OFYZ0abb9Gmm8TiPdp2uBDlfgD++NfdMSdJM6rSHIbVQxGHZOzxOzGazn8xyJlhBtiz6/3Ni8UCybIzFgnHhepG9M1f6zwAgaeHiVfjlL3zNPrM3hBCgtatzepYXfho8YldKWMQCFHgQdIWHIO1wrbwcbb6MppvE4j3adrgQ5X4A/vjX3TEC5JnatIchtVDEYdk7PE7MePzDzHDYmMG2LPsFTQ65SjyeOS1lqx9kz0D2a0JxupDf967pHUB7zU52dWlK5V5Druv4zbs+rYxFIEDqtTErpAxDElQ6QsN9bbhW3hehGU4Ar1IFQo0J2BDlfgD+z6/u6e1mhkMQ2ekrfgdhW+7NIyjVGjWKV20htiz8YtoNGZ/RKoGUYwXxyGGZ/wAGrcs0Af/tV6mham3Mp9FaQchtbWkkZxrqHPpzVaglUvBiGJKh0hYb623CsM6NJ/ajTTeJxHu07WYwk3COu/GvumIFyTO1aQ5DaqGIw7J2eJ2YzXmw0ZoBvqG2G9i7FiMvMFPxn+2kPy3HINrHDyneeJNF6USWmU7ciZ29Vku5arcMbu2RNnd/vvGq1MSuk17/4lapDpCw/LPTcZ7IwjKvUjiPNCcFQqeI4PwB/Z5/Wdt09rNDIYhm4pW/A7CtOIKRgisfo+9VXPYXuV3Gkwl8RdRjrQeShAUUqcYVNh/0YWP3DEcNVrDgeY5m39Qv09wSj9aISd5+K9cqCWvSGuf1IdIiZjokmFYZ0avUl6kbv8SPdp2sxhJ+Edd+NfdMQLkmdVpDkNqoYjDsnZ4nZj5gxo/33u12G+QliDlO3BOkuGrdTL6a7NHIuq3UVt1RFoU/FIQx2qx/mBG5SzGLzDf/Rk/jReSk86OeHReppvIJwRQj+nRwuYm6uInq6hcGRKcDjpzc2zCvIdkYbyw40GwgedqoYjDsnZ4nZjC0Z70IWgY2G+RDmqKrRjdbtiyUKtUF/6evDvsEpOvVa51iQUuGbfS5uItucIs9fYzxAMQeYujFi6M4cg5S+hibLwRnD2TQX0dGxjpCIymtA6uoq7+TM1qBk5PY5PmyL/fxWKjYksfCmmqEkq62IqZZpli8Mhb0MexuXzBZTnld+KgBegOI20yalbwhNJHPK/DsaTgECMDcEGc/LLKmJ5rcVnjOL03Kdujgqn/Bql1tb9oKOi3YKU4OHtdtipVvDrLohJclniXx4hGfl2v3Z//jqHVA0IPY/0nSlMslGU2rH0B5n3lCvtzshQPOPh+ix1rKRE/ElPMRbs1dOacVolxaM+MlIOIuL46ivcsIFtwt7AzWKiSbWHty7wj4EhaQ4zlbmadNaEyOX7uG0WypvosyeNsJ/cjZteIMQNcLxYlSlhkqjbf9B7mSSjh1D1ksORZ5BuVU+T1It5cJwRdyLyktv4Yq++BEslOHscG/uNuB03G8C9kZziZwMxu56ye9bjd98PqseDYgvFcnv3ysFnsR8pyquUfFNRx2NmwDoaZqbJqp09iySIP5jqk95FZOvETY5r21MapN/SLcElGJ2gAuCbuTRsk8m5+JTeL/4iwBU9SZGoqpTY0mletATGIJzG+GbOaF/yFu/sMV2LIwUaIWmKO3iU3pF2qDuDYguTCzM2wratRJfIFt/z25ZYtQpF/EH9/wgmEGdS4rz3UagmFuWjmyKsRAZOveCsG4MysTHnW8VCeD1F25dqDR7f704TmtBlkihqbcIH6/BKmhBJ91UYqQGHddjURKVmjg8R4ivrVmqC8Q6oHX9oIVuT+LdpQgnZwy0924tiKGeK4CMDaZ/wW/ZTVYpcY8bCfnvIWsFiaADhn0RMNqkV+QEwvAX8XHvdNMlBlfps7P4K89gUmD34Ozz9Z7d80oVKnXdo4NdiCDaL8SkYDmG1jNvIpF0XAW1Nn9dTQ5trUGQc3wGoh/0yD1fWlguURTRHDsaSMSGxtOBz11vkv0cG+NZASx0zL1m4KFhfeXlIdQ3f5ZnrwmhIo5yFY2WLBlCrlo8k7g68yffujB7eBBni6zuynQ/xtxJFrdoU7UDY44CR5YTrOHw22is5eGXut7T6tomJzsTg34Mp4rWOU2l/DI8ZYkCdwYUT2yG6DfYKrBMUxONX5Wrv1HPI9NjDYRFUdbpgbq+oweuabDcAro2jzgVp6NSW1UeRz80P4JbtZte0VAk/v4HfgfxU5oMmVMleRhALk/7Bq1RWcQ7dW1QFIVHPKDebE9WQjTsM6uBxcSP21BeKGodOwXFx8nVc4MKt5yO+GrpBCn7iO919m5NvNtuF9b9iJ4tDWhbOfHAV5FOv0d6eN88+UKym6hcWZys+8jnDgnYyjbaLPawep4Fc8SoOCl5THZzfXwULpwq0jp9mRcszS55dcFA5nh1aDZnWYpdYeeJK+9nF9yhu9apnQd39Cw6kcy7ZtWp5zzVr/CDOYuQXWlO/bEoewIJUZC21cISabQfeNnKcC8b9ZqJaWqVND4Z0elGwKepwzzxQDEXVAQ5QLIqHc2HXALqUT7mMLVJr6fKirQRG8VcBRF9FGfPKPW26kFktaPSOZ0zx+GUw2LfmcFG5elHvcbyYxGvG0LPJA2Io+u5YbsNiZKFX+ttBqQk5yh5sD9rCv0sjU7meteGyahpAZLasiOdogw+AjtPEqP+sLK3GNc4pPGqlSF73WjCiYnwkKkE45tqYIWAs3UD+S08CqDF5ATG5rgvumYIpV881PRcMP0exK4+ECbDk8mXVHKbZNzCwH8FzqMAh2QmRVT48F+gMAB9CmL8oivlRGcv8+bziFh5THMSsxReRlqAhFABXTAfh6Gme8hmWH+ss3prCjRvkkpr29KiMwxJpaT0rEeVojoRGfSXI/U7Gi4F9aQhSMZYAy5t3P13JDUNFrZ5liIuZoFZpvL1lEhEuOPb0xt1AJ+luYpQOC2bogsY7kbZP2wdjq7YZG+D9pApv7HPIpeYlYC9IYV+1vQRRzGh+fuAuVIgOpAtCV5VZy5COkxWvhoxFmLpUher5kYrZ+Mf0S+QRxJ6gqM1VqUaLxvzlrPNMtj3Z5AlNXhJVbLwwndiXeGbFBIFqnTU1BF9HxYc1cIMGstG+D5J/nKeLlob63SzRy+gK1S9V1Mg/I5wrLyS6s+ady0hgG2O6WTAOBEIcb5qVgEvrgwvtjh/vu91ShyBaeZ7YFBVIBSnwDZI+BvOfqJe2voEb7S+FXXW9NfL+4Jql894Ez9/7HLDJsfb8KgjNDoodmL0+DoKv+Fbn7dctgNEZ5O7B7fRcciQt3LgBurZLSMCuZvgP8X7mqExaNEgBJxiplcLQFjxlIXDwSL0rnbK8oF9jZ8CGJuvR84vMuz1R9qLWuhUpXFKbUEL5j9OkF/YRHmHdfjL8AxuLmWhs2Rb0gzZx06qCXwBr7KuYMxjvl8+aXoqzidjACGr/t6pk+vEo6TDyyVytDf3ffT6d0zvswrOZB/GNBIC7vzMT3cYeerVANj+4ajmhi0w28l8ORt9/pJ5Fz+PnD42td5+3sCZfBjXWqa9FXu1WD9/uasu6XtY1pIRDzBnRMP2xM32CoKBPy2Njr6S35IsnI4TNTeau5NgOWX5OFVYE6ZgN6DElVmyFne7MN9gChxFOHXpVS2cONr0nWqz7U+z6wZyI0eBgMx+PFGcqAIMiUaO/zgg5IP8kCC22DfoyDJ2FDCp45GQ4sVOSzsjKZlq5mH9HvCDFiWanE1+jnxapIwUUU2ifSW7HNOJdhtahJc7m4adZurkg0XwTF/CUl0jTWS0kcuZI9BOQOtsVNm7KxbcdUaZHD9XIWhkpbe7XPTnC06TkVaPGSsvXL79jYqWQ+Alk6uSjmrbU8n8KIX9KEcZzpQcNT0ezGkg4Cp7Z8tKp/cYxaphLMhdFj6VNdVvGU0ew4YWOeforLj6tQJBmqFF36B2E+3nfeUCyJU9ndWhcabX0pzhuQRhsdm2xPc4jj1vfCWQhpYCLlPiwVOhYeP3/HOOkfB3kmaere3SGx7Z0S/Va/t/qbG9NJosFXmmo28FZkd8Qmnls07Wf3KlY6/YXysR2KFlTk7/W5tLPx2N+R+RuhHUUBPFwU5SIBMZaKAtCmWsdx/Xv4FQWRQP3/A0n9c6mGsYPBJuU6w1HqyWtvu4gy48ZCIaGbzT5Mn0FUU43zVYnUVCjsVHkcV3R5jDVLcqiSOWATectAViZc8ZJAlS1lHqiHgNnNhjZ7u2QwaljaxgaD/LIvv2Rdr84XyOPqBp3dgzbYtKv6zUGfocd6ejCrAHyzs9yL06aie/Zp0DKZ6CkTJElTZeztKNQznx7zl/oWt2Xx+NQg0zVXx70lPtNYc2bxWsqrleQa4nWS/wRJ3+tkpRRVOyrGwqDj+NjVfsVMj2Atqdu05MNzcf/UGvS6+AdfTdM/1AcXk2pr3hq/O1xoR0tNk+iTzCZJcAqeU6X4qpoewSpuyPKs5sMs3lJJqMUfxCT6fjdo9vTzQC0tEvDkiLiSUtL1z4VXuWUjUCXm7xvlr/khELbuBv1S4Wd/XZIie41ihwrEYCeJszctpjqkqD6plUDAxiiJ0h1XP7HHenpLUxXB8TFTbvmny6rrpMM09cpanmARrKKANu3PLrvu2Njysel9Bwn/gLP1LtcvUZcbxZBVAEdCuvKHq964J38kKip31XMDXv0bTQJxTfV1XhgS6ca35hlWFpgyy6FKxyr1KFhAD+W4IXz6UVD2e46CTIZhv4o8s7AJDOzEjI23WD+ZEGRiDAJVIPKDwsOL9t1aY3msQd+W5jszpQgGFfoX02HsqYB4al4jRci1Wk2leNM/b3AxzKirdFsapZMDpiv5uwIjnYaB32a9S9o/2tFu6mGYt+Ho2NibI13FqMn8ZYc8Y6+wOdKqIQeavClhCLKgV2PM/NFHLKeZ55R/TjMIPiQ/9Ix3ndHrGusjyQhv8pmo827ClSbuqZhiPSfYstUQKLW41BX5VfQFE/TsOPMemI0bNK1TyhY61I6NRwatGPO8zZHRds6cSq2KPssX8WJJYo5CglZj9GyvC8RS77jPPp4rSKrtjyHxatEKgLgsCBJYtlEewaEIein4ydxJOpxflNriz9jff2hI3y5NSVHtR32PBbDmq4aA3thEQWv7G4a4eFE/RS6sDMCl+DilXzBDHz2zIsOSPm3z1CGmR6B2kdC5WFiai1ay7Ss7PgUkvwwLbasdBgTM5GErv+AdthDg30ErSrIr6QQweyrkmwooZ/5u47L6r74LlUhNgMQy+Dp8sk7n06ADM6Innd8V79sXLkvNhqKRftnldve71mBFHg1ba03HHmM62OUjoRVcNaXuMOyS3gjVyWSqrkK6x9mOA3UZOiAaZGf2JGhmc3V6hhctv6oQw3Xtx0wtqWtoJeYwY+vyy9gJtF47phAiPW+XMamcDOhd+nnSCJ7V0enipMvwyqv68KKWK58ycE+vE++6rRGMEIqV2aYw1f9hgw60RLO69hQPyqu9fYK/Ew1EbiejSvSXXIK+ay/7U5plwFuhksvGGGr1DCJO2D2RZFAyUstM+00aRI7Z7D2vwHu2gzp0tGIZ9enA6eTUHbRN17Qte4y4qfF4ZzVhND3IxwjUmIHlRUNNP2M2jixY9zkQmk2NCNginefPQrH8bRV6y2HbG45cMdxjki9laH2aEzyW9Ka9y+drASAbA3qrItIl1gmoU+MUu5W9CuspBtB1xRbG4fw4ajUy4JGjkCDhHDdKUry2tVVQNzjILSRD/8KKDhu8uESNx4MG0ugFgGLXTEVFEWHBaAnohuelRWBTTJp/cmk3UqHbYuhdLfe5QrC0kkElV9vJpaEClcgrGDPbvNgE5kYgeHQP/fupVJYjPDEte8muq2C9omFNFIY8bUerNCmPefB/aD7KSKpfmiZ/hhu5fQj//oIL+RD95G/UABnNFbPKisBDR0CohZ5JhswLqG82XFYDQY1LhkpIkBAx/IrFjXNgvFvDfWzaRK8S5J9BGCQ7T5bbfjbdEDlOkVqlw8yDP3wJy3pzDL2K8REJQ1bh/BfqUaR2i4basth9UJk9QH2VmXByVoJqQLoeUtthNKocoWm+G7bzkKXr1nACg6RANNmPH+zKcgYMKiHzLXNQw2b43Du8mFVDh9y+sB82y8oUJtlSkmVcQc/mw3S0BuwvXP1LcoGMwyH1dQBzb9ytY60rYpT5gktEtSyVgpi7zWLPR+NiCJmrwQ42U7RKVM6vIDUlr7ETD5fJ43aLvtJUOx27JdnzkzHgiryoQPd0uGHPc3FbLgaD4llHpePvEFispiQCrQqYB0BjAMnXs6zOTWgelTL+dXhMNwBm5tAEQ4hy0p77oTLxqdIGqgD1NdOT5QSXE79cd4rYBKfXOR6w/EBAbjPderK3LOaks7t25OAV0MJDxXFQN5nPIdFFrXbILOKUruJ1WNvKp/dgV1Orz5HvuFh8V5iFWwfiRMW8hgFpwSqpT55DeDegSHBrHgb2DW2dyGq98Ah+Cd9dyPV+fUWLfX7LWfm+QlZN2ZNHRiffYcrIRAdvU+oTXUmbHr2R8MuEj33fbmg3g2VkkAZaGt+AbEglzZLHdBgr/9jZOc72ButMwJKCkjx7gBRTAzsExPdjU0hqN6tGWP6gQeCxr57b6HvxWL1eKVXtTvZ/E5mSqHVPGwrWizzbWv1iQNt4HtVYVUWd4yeQRloLdnCIRU+TLd9Q4aho4wR9hwh6QFmhRvrbta0x3Upn7vZoH2/0RJqiO3QX+hLw8T2gNIUcrBNNsYIAAZZlfOYqRp/NNYqCoFlQXDjH92dX7440CydyGIsliOGOOubd43pkTPMS39gDPFcP+yKag28CNXidLWIFap5PZsTfJJZ/h4Tvpp9P/hCd9pVkOGx1HBSFUw+ntcQ7vpnWoB9yIpL4PK1AZkDc24y3ghqA7o8yu5Q4+zLQjJn2rtVB+z4cu7VDNzUA3N/2bEK7F3jM7TisYKnBE1JY6nwMusM3bfZSzU2BqWvhDqPzhM0TT5Q1M4WsuJYy83dQzUb3sabQeY55bsbK4w7jutI8OGJ+AvHJDjjtyQ8Gjdh00V4KjkOkFz4G4M/r4MFdTNFay1tftnQwqbTZGdOrf1igC/mlnYfsLwGRawav8SmQ06IDwGbpy0fB9TP0dPYxKXcqqWTD26yvOV2XMBc0abUpOQ3e6A4O2yxkTitcYDfangz6mJvpM7oUO1nxKunmjyC4Ap3MckqrvMtOkbZERJMBqhaNiRR5k5WUm5kziZJeAA5LUBOLrdfcWBigOdErPB03AAJ8k0BI8YclJ0yt1EQZuOaey6MhLeG7bv/fHoAE3IU3FAqHqyC58uw8qxiaAYq2uFnO+/Yyjjk3Ej1390X+bkR0bgZ/6TsAKOvF2IoX/hHqoykp7zju+9QfFKxx2tB6yrZG3B2pnYbNF6/MTdjhJD8gJkLOzx795AV7IQYpQDec77qDur2p0njz3zC9DxGguYqM5Wh501BeZZmfhPPIRvuhn5QKABqYr/7vZIxFZbBK4xwAoly+upGikv2GA/1Wi6J+xd5/YG5LqbeSmNB9kf/5iHUBdnMHOm6qaVaeLH1/iVgqIs1+Txz+rNREB5lCQ2zu+HGLDfBxebyN4jeB9hehqHHUrkHYQB5ltYAVDbcUeqa2wnWIAJTTWRg5jQd3qZO/uOOUx5/+yUclTdFERR9jwgTC78iNRyuUBD09av5HPNHq0H7sokNgg5cQTFmqkWXd0JQUmpOqpWpRqcnLdNTBqNjDMytp7RtHmq4BNmoGw3sPiL01L3EA2HrJ6cPfL6hi3EMD9dZSA3N0GsOn4D8fBOCyq2FigKme/QMz0UBPViO4t8ewdSrPhhMWoc2T8IvaoMWYA2lYeE1xEzflkbhCiimEqEPWniW31qFeN1T9/DzgOoDXXIGb5zgB0LMeDB/Yk5xdy0O2j4CJFycFoldUUBMYnYoNXH+ljIPC40jja8WsA9jyr5gxuWijljR+ucNuK5pSktcyBKalgNCGaJ/lSxc+gjF5Vw6dvpxf/Kqvv8uzNbqabOofoS61Q3HVs67XCQub7aTutki3H0haAglk6RprQEdeEuc+qifYwuRUYylppMsRGK8mf8StrTW10BSy2HZ35wmcDrgQfdP4b998PwR4WUN2YtLSvUNu1HvjVOwUqH9rnaLGm5JUiK8k697WZEn0LycAGK6jH+DS1zQbQge3NYr+7J0WXo+frJznN2/fG3GuISEBhJePFsKxMqTW//DKbDGWOq7uhnCZbsmrv0YoN3TUM68Q0qGWtXKr5FWq2R+aoc5xnLeA0jxjqpHToEa+rFeLtxl4NXVfolfhpjbinSqmP/MEGtmo4JPQHIDnsN75amW2hQhfJzrr7Sx+3X+GrM982GeZQpVznIH4Kp8ogxEtCoT48Pg1XFfW9dNm+RudchV6bj9eDeir2AdbK59AR8seQOGQTwr1PyLFTz+rGG5djWikI1JZD3McNe6GiEaNc908IwBdNqrOaIXTIDfn1j/tym2mhxTt4n/MTGR9bQzwG7mr9BrQhNmsgZiHKxk7WyiUbp++Fie8xFRU+Yz2zd3YfVdMQ9pQGqnxnUtT2noNTxg5I3njUit7DjmCrhBtFGYjcQTFyANwPazQv3Ujxt8zTWDSWOZ5sO71HICh8kt6QG/MitnDQbNfkSoC1vbRk+mE1RDdc2MEEPPWx6mKXPNJ6C0X1sPCYISjDwvQBkZo1I0tIfP3+y7BRODQpH+sbmXmQNiLTEaBdyZeHoZVYe0Yj3NU/xbsJkRzyKOk0A6wZr09bDB2wTC28usngye417c2/WQutsHmHjVsRmtsM+CtU6sRdgi4oO0GDiLyLuxkrKPOenqZ5v5AnJFn+qBVAjpGLCyltE7NJk7HOAutwGjDYDHn2NXSKfDC959C6J4pPKuZt6dvvdEGMG47pTcT6ePwZJiuf025ykjcd4QloS4Er0m8ig2O8g+JMooKUh0ej8iQNBLiYCrvu+v/ABYnoyOaaMKOzV965UHIWver1mXCt2NcLmgaIsFpC0ucm0pd3oVpAo1ci1TTXvaF7CDm4zzSLywr/i2lK7KBRbh4LKAZdIx1AgqMQT3V9ZLAm3Jvzpyx2NlxgGpCNaBXSoDAnLfUzQYgY3vMaLZU2qS1Ze00wzwx654H/KMF8lwOUOS83D+wwTcSP+YrDDWrmOde1yhhqEmwPFpnDBkwYp0QZjLGCuzqRaBSeSTS4llafcz+0aJQVs/yqLpnf7kTdw97DEu30PPxSv1/LplSuDhM4gPi/kIiHEHintZL4g9un/cdvAfBdjNM+ebTT1qwmrMcM1m6A7V78BdjuqN6PwW12NiCVGTh80QubINYf1A//mtJr9+APXQnBPx8mtr8P6+hj26L9f5VHpac3/VB9QcL+hNdi4bDk9acSZn8BoTrMnmTvj7uN2bwfGyWtLnk3OWKZ0RB7d7HQ25L8S4ruDBXc9Uz+D+IhdBv/ihUrk6hYNOIczXC+0+ix5bDBfjz1/3Zp7nsPyiMSNQ3K2MOo/6v93Ey/IKp2vuQTXbbHKLImGN6qPY9dKTB2NlsiBoIu4nB/b93ClPryYdRHyfQsmTZPORJyduPL9KbIt+Erky8SNcL+5rskkRIoLnqV4JVyliaMqqs3EocIKFDdCaiysl1YlsUCZHiCIB3gubiWrir5kJu/UMFifzZxipAu6SovczVRW0F+NMnZx9NZ4t08W8Io2xlxGHh3lIGjxXCBrjg63xwAWfXVA0tEe47929zDGJImlb1tvWs5L40z9jYgoSkTRxrvA7Qz/l12As8UmtMIla/tcetalzNn7QA7ya7M9Bw12o8dEzD/x1KIEtLpsyVAdZr//oR9jvIhibcAqWhvg2LZ9mCPRpBTbS0hp1oXkGD73Pqi10FDDapQli55J2/6sERLCOqWqPazPBMdnGVroCAYjffznXW5jzz622VtXSdxmHZRoXcT7yOwjl6cvElPhhpeyHe8u+TLAJ6lNrY2YqxHm7riX+0iPCXtBojkA3ER49JNvUhBH0cAtIKqqQPcTy7JoTMbH/FiXLfUDOMnB+4Bjrxx4snZMrKIMt6TwznPjeZmsiD/RKQRxRqourDgzILDHocGeOX3DcXjcxmK6LFbG/V20pwWUqbEtxK64y3ZQ6/+OgvQfwQU9n+hf13n2z+239rGLgOEJt9MipMW32DfjNswLvLXMavIAas5tjYg4R4F8gesECQjMkj7s6lFC7vtHKrsF/Hf4Y70miGa0ZHOs1nQELgAaLYCixnVfwava+dCwZm6sA1QpkvdSDWxogSulDduFxE2Lfxa+QinrStxt7i90mtgoiWBhJv3AmR6L40mxYJEzc47wW4ZUzc0g9jtw5X0Z1iDUrq0elDe6m8ycGGsIxCWHuQWMPaYIMuBBqTpOmGgvG2GOAWo1Ruh2kE+tjtz84qz7pykudGa4gw9JTujCRU4cM/CygPcBZu4QU/z1X/d8SBKsfV/2HNzBvSqZdkGw/R3yz4aCL2rOoNpOwLmh4ClRrfjJd3RZqMlFG2j/vyZDzQE60bRSAvXALvUK2rUDeRz177fOcKv7PgutO9Gifte61tW1DsOO3pNoGoDs9IIxETnO4Zdm8N+nxrcJnVaLtunhMcDZtmPAgO2O3QkCiNPtbhNuvlz/dPh/+Vi/fnl5XrDvUBtZDuB3EL9h869qEuQKNYQjglXJhfAB0YGvTiteHFoSftSyp9VZmQR1ySLSQAOERpUrJB2eQQHCQXwLJ1xmG4qY7eexGNkz+oRW/LdpGGzkDxjpouSctkrTXrVnkMvO08s0ciU0SI9PB8OCPxsMWjKEkYP3Cjpruk/KXYiyyCPxyOSMHYSBRH2OrKKhSwN2zjkpsOWBA7ARyGskEzVeFThNWQh40BC24XAn4DL3L2PZTHDYBiyUqPlcwECpZGo17w9oKuGCnM7/AUFOiUdXVCH+1zwX78yvaqQJW3vypZ/j4OfLiBheITEB408KG87DIlI1Io7PmsAiNvbIOzXVrdi0aiet2O0fz2tRIHcI1CNT5XQbSKxJueD1X4OsaT+eLzRYStxfenl+iKgrJHDCRhHUlnDtSYYdj05XM++d73zbNGlv2J44Urd8vpvLUHAeSO0iihMCbBgRyJ/a1J5WOrg4jloD+QjViPwzirVTam6wCWGeorUUm7FrEKHbNDBBsO62T1VSj2vbOAuSu6sPrGpmNmbzbC7IXiL2UWuk/vgdxcqeSIJgf7iV20pLDA4H0JkazzdfabOU6AJRK0MWwJKs4cgyTR7tqzsV0fxAn4zZNiWOWf2dwVX/jD4EHQO3BO4Ur84qfdEdxgmnRsnso+Gr1oWpIXbClvLa6sqEtum7IkaH0hFn1PZ2dTAAS4mgEAAAAAAABfdRcEAAAAgR4degrQtux6hXl56XNy2PQGwHO14/lLnslyODAsNeYj1BHEjawHKlXE+mVJZwHuOFV9Oe0MbMMmNuTKtMUQW2Q3aXaExaytismucf5yt8c0ac3bv9SJpIeMPKVayhImtAmmy+J/Kfrqm4t6Kn/Ji2E8GJvCeQh/Yn2HME84qlWD0CxR5O1f6Dew4a8/6MkakC2TPqb05rYfU/bQmQipSzeGI2b8NGDkJE4TNyhKI4ry+NbNPoRNn0WNq16iFvbAVGu56bauPmOpbkFSiRcIRomKrTzXpq3f6U5IdFh2sdj0AgL/DFux/K0Ifwh22J0l9HWF+TMADaCRadg40cLyQiSMVGdqpRLOEGs/VBX6rR108Sc6LAq6UJw8dvhauWsIy1lDSNunaI0PS2JEbGEgTqQFO8xrbklxhiKqgIHpSLAbDUn+H93jda5VtooQBmWNUWU7sSg5BxJC/iNSG8RTr8poRQDniK2/Vt+FOjhxCT0AWm19Of0aoiPUwwhjw7PG9d3xyH1tLCGFX42Bz+DIAn9bSZbU2HCGQKLroj6PaPRlouo253IRqgR/vnZZtmKwwMt1E/jiWaDqh6F3WCGpOLgRUJpSBY5pTMsnRhg0K2ZWlh4OgyMgpNUkmfUXQGhd27yHyiRJAr+nsbSyGlG/4vTFRuPF/RPncWL9bj34xVageMLSBm+AZlfE6LiJeq5bmBv162nMS7D/EDHKpfMZykoCiG7UVuyxfxXgokPPPgJA3l5Rlms5RT3jtdpDjYpje40ggdI0HXRvKJb8VjdeNvwfbHiR5edVpv4Ov5wCb5OSEtpplmxbFvnwyAsb5X76+3HjIZMkoNL1W9pmjfd6DSjYhanCwyeaOlIJblYMyyod2H4dpBDFNy4ZKJuAF9gdUTypva0NYvdFpwN27Yd8IklpsNv+j9wTTnC4CuCkL1/TWGN+WCN5griPuxztgYqnh+wr4wZXUs39iYtn6xcZBJXddn53NR+F6X2rEWi+bBaRH9OaJtacCSZKINgiVODowsgcg+sKGq9ax46M+QpGUw+XFmFnElbkHvG5fPvLqLX2sQ8b5q07D7I35vUw7pweYAhqvQG8+u8S1T8ZmeJKV01xAH1dmLLuVwekYiktX/Tzl00Cje221xfKB/WTRgZ2zTNnwdh0DOuK59Kv3YPqDkMxT+jX0jAskKStMsZJV8PYgmTl7DO146krTmx85JbVfMbn3qwJHX4c8rdWz3n0Fp6jEqmx68xdK1Z93D5NjTpl0cDb1kOlY2uguw9wsw2A+dgdTgfO8fQ62ZwOlu5kOUW7zKdf0ccmc3Bpc9hV3KwogzviTA7bwkIVV9K9e07W4ukHOFxoEEdQ2ILnipmlFqu9SdFfKRcm2Th69CdO84123m1J1Ivj+2FNclOsSiZRshSeBCssoGmcMJyhme9KQcOncRH6jgge84tlBpMdIhz5h4qSGpqaaS7LATOUFlo/bBXUzWedzVy9tiDU5RUSN9toHX5QZu1QMrr7Kc1vUuJvUtiJv/w4qBM0pC1nwe14DRw8pIFVS1ZkPd2/OhObWBxCJXq9NvAn2lCRaN078/evPyuZZ2KiivQV2WuP4wtFcRLKvwqdA88OgpRwssTEgJFRkjoyrIQlIHg7FW1L/z7a7aJ38H2jFBvb15ti+WGLYNDnkFB1cDeTFIMENYqDZXa6dMxXh947SbUAb84ba8eC6ZtQ/A/Vkz22mFBmTUuPc9fDf8TE93v5uNKfN9ewsua0L4SmuTeIbWGHE7oJtZf7DERRmvX2ATf23TrBiMzXEkzK1B+h1GFqn55H/F5McMP76wlvFeaRHZnQ2IMTLKGUibc5Wxq+IUDKD8xXmY4AWPBut9+lS/wGzYhbyewo070iQeYcPNGli/6apbQ2z+x9l6jxxNpOKmzV4Isqv/JcOZrK/KMDimHcos5rKLc00mLC5IZubEY7hRUfdMdzGGOO0OD3RJICSy7IuxvH4NiC6fxHXJVbA6qj5goRP21a19L1XwoPLhRbpOvDZzLCFatayo0lBmLZbw+HKGkN7OWpueGV5wvrMSPF9XjFgJIL+8rqjMpI4kCmZEucrJizYL6lW89ci0iS6YWsEfhPAFccHi7g7Kj966mZaiTDszpnYg==" - }, - "session": "default", - "convert": false -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Fields**: -- `file` - provide **one of** the fields: - - `url` - URL to the file - - `data` - Base 64 encoded binary content of the file -- `convert: false` - convert the file to the right format. **Default:** `false` - - Set `convert: true` if you don't have the right format, check the format note below. - -{{< include file="content/docs/how-to/send-messages/media-voice-format.md" >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendVoice-code.md" >}} - -### Media - Convert Voice -{{< include file="content/docs/how-to/send-messages/media-voice-convert.md" >}} - - -## Send Video -```http request -POST /api/sendVideo -``` -Use API to send a video to a chat. - -You can send video messages in two ways: - -1. Provide a **URL** for the file and the API will download and send it in the request body. -2. Provide the file as a **BASE64** string in the request body. - -{{< tabs "send-video-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "caption": "Watch this video!", - "asNote": false, - // aka video note, rounded video - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "convert": false -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "chatId": "11111111111@c.us", - "caption": "Watch this video!", - "asNote": false, - // aka video note, rounded video - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "data": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" - }, - "session": "default", - "convert": false -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Fields**: -- `file` - provide **one of** the fields: - - `url` - URL to the file - - `data` - Base 64 encoded binary content of the file -- `convert: false` - convert the file to the right format. **Default:** `false` - - Set `convert: true` if you don't have the right format, check the format note below. - -{{< include file="content/docs/how-to/send-messages/media-video-format.md" >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendVideo-code.md" >}} - -### Media - Convert Video - -{{< include file="content/docs/how-to/send-messages/media-video-convert.md" >}} - - -## Send File - -Use API to send a file (as a document/attachment) to a chat. - -```http request -POST /api/sendFile -``` - -You can send files in two ways: - -1. Provide a **URL** for the file. -2. Encode the whole file content into **BASE64** and send it in the request body. - -{{< tabs "send-file-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "session": "default", - "caption": "Check this out!", - "chatId": "11111111111@c.us", - "file": { - "mimetype": "image/jpeg", - "filename": "filename.jpeg", - "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/video.mp4" - } -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "file": { - "mimetype": "image/jpeg", - "filename": "filename.jpeg", - "data": "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" - }, - "caption": "string" -} -``` -{{< /tab >}} -{{< /tabs >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendFile-code.md" >}} - -## Send Poll - -We have a dedicated page about [**📶 Polls**]({{< relref "/docs/how-to/polls" >}})! - -![alt](poll-example.jpg) - -```http request -POST /api/sendPoll -``` - -The request body is pretty simple: - -```json { title="Body" } -{ - "session": "default", - "chatId": "123123123@c.us", - "poll": { - "name": "How are you?", - "options": [ - "Awesome!", - "Good!", - "Not bad!" - ], - "multipleAnswers": false - } -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendPoll-code.md" >}} - - -## Send Event -You can send Event Message using API - -```http request -POST /api/{SESSION}/events -``` - -{{< callout context="note" icon="outline/info-circle" >}} -👉 Read more about how to send [**📅 Event Message**]({{< relref "/docs/how-to/event-message" >}}) and receive responses. -{{< /callout >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendEvent-code.md" >}} - - -
-{{< img lqip="21x webp q20" src="whatsapp-event-message.jpg" alt="WhatsApp Event Message" >}} -
- - - -## Send Link Custom Preview -{{< callout context="tip" icon="outline/hand-finger-right" >}} -Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. -{{< /callout >}} - -Using [/api/sendText](#send-text) -you can send **auto-generated link previews**. - -If you want to send a **custom link preview** in case of any errors or captcha during the link preview generation -(like for Amazon: {{< issue 596 >}},{{< issue 880 >}} ), you can use the following API. - -```http request -POST /api/send/link-custom-preview -``` -{{< tabs "send-link-custom-preview-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "text": "Check this out! https://github.com/", - "linkPreviewHighQuality": true, - "preview": { - "url": "https://github.com/", - "title": "Your Title", - "description": "Check this out, this is a custom link preview!", - "image": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - } -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "11111111111@c.us", - "text": "Check this out! https://github.com/", - "linkPreviewHighQuality": true, - "preview": { - "url": "https://github.com/", - "title": "Your Title", - "description": "Check this out, this is a custom link preview!", - "image": { - "data": "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" - } - } -} -``` -{{< /tab >}} -{{< /tabs >}} - -{{< details-html "🖼️ **Link Preview** Screenshot" >}} -{{< imgo src="whatsapp-link-preview.png" alt="WhatsApp Link Preview" >}} -{{< /details-html >}} - -**Fields**: -- `text` - must contain `preview.url` somewhere in the text -- `preview.url` - must be a valid URL -- `preview.title` - title of the link preview -- `preview.description` - description of the link preview -- `preview.image` - one of: - - `preview.image.url` - URL of the image to be used in the link preview - - `preview.image.data` - base64 encoded image data to be used in the link preview - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md" >}} - -## Forward Message - -You can forward a message to another chat (that you chatted before, otherwise it may fail): - -```http request -POST /api/forwardMessage -``` - -```json { title="Body" } -{ - "chatId": "11111111111@c.us", - "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "session": "default" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-forwardMessage-code.md" >}} - - -## Edit message - -You can edit **text** messages or **"caption"** in media messages. - -```http request -PUT /api/{session}/chats/{chatId}/messages/{messageId} -``` - -👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. - -So if you want to edit `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: - -```http request -PUT /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA -``` - -```json { title="Body" } -{ - "text": "Hello, world!", - "linkPreview": true -} -``` - -- `linkPreview: false` - to disable preview generation for links in the message - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-editMessage-code.md" >}} - -## Delete message - -You can delete messages from the chat. - -```http request -DELETE /api/{session}/chats/{chatId}/messages/{messageId} -``` - -👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. - -So if you want to delete `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: - -```http request -DELETE /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-deleteMessage-code.md" >}} - - -## Add a reaction -Use API to add a reaction to a message. - -```http request -PUT /api/reaction -``` - -{{< callout context="note" title="Use PUT method" icon="outline/alert-octagon" >}} -Reaction API uses **PUT**, not **POST** request! Please make sure you send right request. -{{< /callout >}} - - -```json { title="Body" } -{ - "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "reaction": "👍", - "session": "default" -} -``` - -To **remove reaction from a message** - send empty string in the reaction request: - -```json { title="Body" } -{ - "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "reaction": "", - "session": "default" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-reaction-code.md" >}} - -## Star and unstar message -Use API to star or unstar a message. - -```http request -PUT /api/star -``` - -{{< callout context="note" title="Use PUT method" icon="outline/alert-octagon" >}} -Star API uses **PUT**, not **POST** request! Please make sure you send right request. -{{< /callout >}} - -**Star:** - -```json { title="Body" } -{ - "messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "chatId": "71111111111@c.us", - "star": true, - "session": "default" -} -``` - -**Unstar:** - -```json { title="Body" } -{ - "messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "chatId": "71111111111@c.us", - "star": false, - "session": "default" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-star-code.md" >}} - -## Send contact (vcard) -Use the API to send contact (vcard) - -```http request -POST /api/sendContactVcard -``` - -You can send contacts in multiple ways: - -{{< tabs "send-vcard-body" >}} -{{< tab "Fields" >}} -```json { title="Body" } -{ - "session": "default", - "chatId": "79111111@c.us", - "contacts": [ - { - "fullName": "John Doe", - "organization": "Company Name", - "phoneNumber": "+91 11111 11111", - "whatsappId": "911111111111" - } - ] -} -``` -{{}} - -{{< tab "vCard" >}} - -```json { title="Body" } -{ - "session": "default", - "chatId": "79111111@c.us", - "contacts": [ - { - "vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD" - } - ] -} -``` -{{}} - -{{< tab "Combined" >}} -```json { title="Body" } - { - "chatId": "79111111@c.us", - "contacts": [ - { - "vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD" - }, - { - "fullName": "John Doe", - "organization": "Company Name", - "phoneNumber": "+91 11111 11111", - "whatsappId": "911111111111" - } - ], - "session": "default" -} -``` -{{}} - -{{< /tabs >}} - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendContactVcard-code.md" >}} - -## Send location - -```http request -POST /api/sendLocation -``` - -```json -{ - "chatId": "11111111111@c.us", - "latitude": 38.8937255, - "longitude": -77.0969763, - "title": "Our office", - "session": "default" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendLocation-code.md" >}} - -## Send Status (aka stories) - -You can send statuses (aka stories)! - -Check out [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) page. - -## Send messages to Channels - -You can send messages to channels! - -Check out [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) page. - -## Send Buttons Reply -If you're using **Official Business API** to send buttons and wanna "click" on the buttons -(for testing or other purposes) you can do it using the API - -```http request -POST /api/send/buttons/reply -``` - -```json { title="Body" } -{ - "chatId": "11111111111@c.us", - "replyTo": "false_11111111111@c.us_AAAAAAAAAAAAAAAAA", - "selectedDisplayText": "No", - "selectedButtonID": "button:id", - "session": "default" -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendButtonsReply-code.md" >}} - -{{< details "**How to get fields for the Body**" >}} -When you get `message` event to the session, you need to get some fields from it. - -For testing purpose you can use [**📊 Dashboard - Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) to get the fields. - -{{< tabs "send-buttons-reply-message" >}} -{{< tab "WEBJS" >}} -- **Message ID** - `payload.id` in format `false_11111111111@c.us_AAAAAAAAAA666` -- **Button ID** - `payload._data.dynamicReplyButtons.[1].buttonId` - like `button:id` -- **Button Display Text** - `payload._data.dynamicReplyButtons.[1].buttonText.displayText` - like `No` -{{< /tab >}} - -{{< tab "NOWEB" >}} -- **Not implemented yet** -{{< /tab >}} -{{< tab "GOWS" >}} -- **Not implemented yet** -{{< /tab >}} -{{< /tabs >}} - -{{< /details >}} - -## Send Buttons -{{< callout context="danger" title="Buttons do not work at the moment!" icon="outline/alert-octagon" >}} -Buttons are fragile creatures and may not work as expected. -Please consider adding fallback logic using text/poll messages. -{{< /callout >}} - - -![alt](send-buttons.jpg) - -You can send **interactive message** (aka **buttons**) using - -```http request -POST /api/sendButtons -``` - -```json -{ - "chatId": "11111111111@c.us", - "header": "How are you?", - "headerImage": { - "mimetype": "image/jpeg", - "filename": "filename.jpg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - }, - "body": "Tell us how are you please 🙏", - "footer": "If you have any questions, please send it in the chat", - "buttons": [ - { - "type": "reply", - "text": "I am good!" - }, - { - "type": "call", - "text": "Call us", - "phoneNumber": "+1234567890" - }, - { - "type": "copy", - "text": "Copy code", - "copyCode": "4321" - }, - { - "type": "url", - "text": "How did you do that?", - "url": "https://waha.devlike.pro" - } - ], - "session": "default" -} -``` - -👉 `headerImage` is available only in -[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/send-messages/api-sendButtons-code.md" >}} - -### Buttons -Here's available buttons you can use in `buttons`: - -{{< tabs "send-buttons-types" >}} -{{< tab "Quick Reply" >}} -```json -{ - // Optional id - // "id": "123", - "type": "reply", - "text": "I am good!" -} -``` -{{< /tab >}} - - -{{< tab "URL" >}} -```json -{ - "type": "url", - "text": "How did you do that?", - "url": "https://waha.devlike.pro" -} -``` -{{< /tab >}} - -{{< tab "Call" >}} -```json -{ - "type": "call", - "text": "Call us", - "phoneNumber": "+1234567890" -} -``` -{{< /tab >}} - -{{< tab "Copy" >}} -```json -{ - "type": "copy", - "text": "Copy code", - "copyCode": "4321" -} -``` -{{< /tab >}} -{{< /tabs >}} +--- +title: "📤 Send messages" +description: "Describe how to send messages." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 220 +images: ["messages.jpg"] +slug: send-messages +--- + +We assume that you've already run the Docker container and authenticated the session with a QR code. + +If you haven't yet - please follow the steps from [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}). + +
+{{< img lqip="21x webp q20" src="messages.jpg" alt="WhatsApp Messages" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/send-messages/features.md" >}} + +## Fields + +There are common fields that you can find in almost all requests: + +```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 version supports only `default` session. +- Plus 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 + +`chatId` - this is a phone number or Group identifier where you're sending the message. + +- `123123123@c.us` **Phone numbers** accounts - international phone number without + at the start and add `@c.us` at + the end. + For phone number `12132132131` the `chatId` is `12132132131@c.us` +- `123123123@s.whatsapp.net` can also appear in **internal data for NOWEB**, just convert it to `@c.us` to work + with that properly. Kindly don't use it in `chatId` when sending messages +- `12312312123133@g.us` - **Groups** uses random number with `@g.us` at the end. +- `123123123@lid` - **is a hidden user ID**, each user has a regular ID along with a hidden one. WhatsApp added that + type of ID along with communities functionality. +- `123123123@newsletter` - for [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}). + +👉 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. + +Read more +about [error sending text to half of Brazilian numbers (every number registered before 2012) ->](https://github.com/devlikeapro/waha/issues/238) + +### 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.url` field with public available URL for that file + +See the list of engines [**that support the feature ->**]({{< relref "/docs/how-to/engines#features" >}}). + +### reply_to + +You can add the `reply_to` field in order to reply to a specific message. + +```json +{ + "chatId": "11111111111@c.us", + ... + "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" +} +``` + +`reply_to` is available in all messages + +## Send Seen + +If you get a new message via [**🔄 Events**]({{< relref "docs/how-to/events#message" >}}) +and want to reply to that message, you need to first send that you've seen the message +(double green tick) - read [**⚠️ How to Avoid Blocking**]({{< relref "docs/overview/how-to-avoid-blocking" >}}) + +{{< callout context="note" title="Read all unread messages in the chat" >}} +Check +[**💬 Chats - Read messages**]({{< relref "/docs/how-to/chats#read-messages" >}}) API +to read messages without providing message id. +{{< /callout >}} + +```http request +POST /api/sendSeen +``` + +Send seen (read a message) for **all unread** messages **older than 7 days** (30 max for DM, 100 max for groups) + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us" +} +``` + +In **NOWEB** and **GOWS** +[**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) +you can control what messages to read by using `messagesIds` (or deprecated `messageId`) field: + +Send seen for **direct message**: + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "messageIds": ["false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA"] +} +``` + +Send seen for **Group Message** you need to provide `participant` field: + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@g.us", + "messageIds": ["false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA_33333333333@c.us"], + "participant": "33333333333@c.us" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendSeen-code.md" >}} + +## Send Text + +Use the API to send text messages to the chat. + +```http request +POST /api/sendText +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there!" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendText-code.md" >}} + +Here's some additional options: + +- `reply_to: false_1111@c.us_AAA` - to reply on a message +- `mentions` - to mention a contact in a group +- `linkPreview: false` - to disable preview generation for links in the message + +### Link preview + +```http request +POST /api/sendText +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there!", + "linkPreview": true, + "linkPreviewHighQuality": true +} +``` + +If the text has a link - it generates a preview for that link. You adjust the behaviour by setting + +- `linkPreview: true` - to enable link preview +- `linkPreviewHighQuality: true` - to enable high-quality link preview (requires additional upload to WA servers) + +{{< details-html "🖼️ **Link Preview** Screenshot" >}} +{{< imgo src="whatsapp-link-preview.jpg" alt="WhatsApp Link Preview" >}} +{{< /details-html >}} + +{{< callout context="tip" title="Custom Link Preview" icon="outline/info-circle" >}} +If link preview generation process fails or site protects it with captcha - you can generate your own preview and +[**Send Custom Link Preview**](#send-link-custom-preview) +{{< /callout >}} + +### Reply on message + +To reply on a message - add `reply_to` field: + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "reply_to": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "text": "Reply text" +} +``` + +### Mention contact + +If you send a message in a group and want to mention a participant in the message - +use `mentions` field for that in `POST /api/sendText` request. + +Please note that you MUST mention a number in the text as well in the format `@2132132130` and +also mention it in `mentions` in format `2132132130@c.us` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there! @2132132130", + "mentions": ["2132132130@c.us"] +} +``` + +## Send Image + +Use API to send images to the chat. + +```http request +POST /api/sendImage +``` + +You can send images in two ways: + +1. Provide a **URL** for the image. +2. Encode the whole file content into **BASE64** and send it in the request body. + +{{< tabs "send-image-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg", + "filename": "filename.jpeg" + }, + "caption": "string" +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "file": { + "mimetype": "image/jpeg", + "filename": "filename.jpeg", + "data": "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" + }, + "caption": "string" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendImage-code.md" >}} + +## Send Voice + +Use API to send voice messages to the chat. + +```http request +POST /api/sendVoice +``` + +You can send voice messages in two ways: + +1. Provide a **URL** for the voice. +2. Encode the whole file content into **BASE64** and send it in the request body. + +{{< tabs "send-voice-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "file": { + "mimetype": "audio/ogg; codecs=opus", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + }, + "convert": false +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "chatId": "11111111111@c.us", + "file": { + "mimetype": "audio/ogg; codecs=opus", + "filename": "voice-message.mp3", + "data": "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" + }, + "session": "default", + "convert": false +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Fields**: + +- `file` - provide **one of** the fields: + - `url` - URL to the file + - `data` - Base 64 encoded binary content of the file +- `convert: false` - convert the file to the right format. **Default:** `false` + - Set `convert: true` if you don't have the right format, check the format note below. + +{{< include file="content/docs/how-to/send-messages/media-voice-format.md" >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendVoice-code.md" >}} + +### Media - Convert Voice + +{{< include file="content/docs/how-to/send-messages/media-voice-convert.md" >}} + +## Send Video + +```http request +POST /api/sendVideo +``` + +Use API to send a video to a chat. + +You can send video messages in two ways: + +1. Provide a **URL** for the file and the API will download and send it in the request body. +2. Provide the file as a **BASE64** string in the request body. + +{{< tabs "send-video-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "caption": "Watch this video!", + "asNote": false, + // aka video note, rounded video + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "convert": false +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "chatId": "11111111111@c.us", + "caption": "Watch this video!", + "asNote": false, + // aka video note, rounded video + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "data": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" + }, + "session": "default", + "convert": false +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Fields**: + +- `file` - provide **one of** the fields: + - `url` - URL to the file + - `data` - Base 64 encoded binary content of the file +- `convert: false` - convert the file to the right format. **Default:** `false` + - Set `convert: true` if you don't have the right format, check the format note below. + +{{< include file="content/docs/how-to/send-messages/media-video-format.md" >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendVideo-code.md" >}} + +### Media - Convert Video + +{{< include file="content/docs/how-to/send-messages/media-video-convert.md" >}} + +## Send File + +Use API to send a file (as a document/attachment) to a chat. + +```http request +POST /api/sendFile +``` + +You can send files in two ways: + +1. Provide a **URL** for the file. +2. Encode the whole file content into **BASE64** and send it in the request body. + +{{< tabs "send-file-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "session": "default", + "caption": "Check this out!", + "chatId": "11111111111@c.us", + "file": { + "mimetype": "image/jpeg", + "filename": "filename.jpeg", + "url": "https://raw.githubusercontent.com/devlikeapro/waha/core/examples/video.mp4" + } +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "file": { + "mimetype": "image/jpeg", + "filename": "filename.jpeg", + "data": "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" + }, + "caption": "string" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendFile-code.md" >}} + +## Send Poll + +We have a dedicated page about [**📶 Polls**]({{< relref "/docs/how-to/polls" >}})! + +![alt](poll-example.jpg) + +```http request +POST /api/sendPoll +``` + +The request body is pretty simple: + +```json { title="Body" } +{ + "session": "default", + "chatId": "123123123@c.us", + "poll": { + "name": "How are you?", + "options": ["Awesome!", "Good!", "Not bad!"], + "multipleAnswers": false + } +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendPoll-code.md" >}} + +## Send Event + +You can send Event Message using API + +```http request +POST /api/{SESSION}/events +``` + +{{< callout context="note" icon="outline/info-circle" >}} +👉 Read more about how to send [**📅 Event Message**]({{< relref "/docs/how-to/event-message" >}}) and receive responses. +{{< /callout >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendEvent-code.md" >}} + +
+{{< img lqip="21x webp q20" src="whatsapp-event-message.jpg" alt="WhatsApp Event Message" >}} +
+ +## Send Link Custom Preview + +{{< callout context="tip" icon="outline/hand-finger-right" >}} +Available in [**➕ WAHA Plus**]({{< relref "waha-plus#plus" >}}) version. +{{< /callout >}} + +Using [/api/sendText](#send-text) +you can send **auto-generated link previews**. + +If you want to send a **custom link preview** in case of any errors or captcha during the link preview generation +(like for Amazon: {{< issue 596 >}},{{< issue 880 >}} ), you can use the following API. + +```http request +POST /api/send/link-custom-preview +``` + +{{< tabs "send-link-custom-preview-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "text": "Check this out! https://github.com/", + "linkPreviewHighQuality": true, + "preview": { + "url": "https://github.com/", + "title": "Your Title", + "description": "Check this out, this is a custom link preview!", + "image": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + } +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "11111111111@c.us", + "text": "Check this out! https://github.com/", + "linkPreviewHighQuality": true, + "preview": { + "url": "https://github.com/", + "title": "Your Title", + "description": "Check this out, this is a custom link preview!", + "image": { + "data": "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" + } + } +} +``` + +{{< /tab >}} +{{< /tabs >}} + +{{< details-html "🖼️ **Link Preview** Screenshot" >}} +{{< imgo src="whatsapp-link-preview.png" alt="WhatsApp Link Preview" >}} +{{< /details-html >}} + +**Fields**: + +- `text` - must contain `preview.url` somewhere in the text +- `preview.url` - must be a valid URL +- `preview.title` - title of the link preview +- `preview.description` - description of the link preview +- `preview.image` - one of: + - `preview.image.url` - URL of the image to be used in the link preview + - `preview.image.data` - base64 encoded image data to be used in the link preview + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendLinkCustomPreview-code.md" >}} + +## Forward Message + +You can forward a message to another chat (that you chatted before, otherwise it may fail): + +```http request +POST /api/forwardMessage +``` + +```json { title="Body" } +{ + "chatId": "11111111111@c.us", + "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "session": "default" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-forwardMessage-code.md" >}} + +## Edit message + +You can edit **text** messages or **"caption"** in media messages. + +```http request +PUT /api/{session}/chats/{chatId}/messages/{messageId} +``` + +👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. + +So if you want to edit `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: + +```http request +PUT /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA +``` + +```json { title="Body" } +{ + "text": "Hello, world!", + "linkPreview": true +} +``` + +- `linkPreview: false` - to disable preview generation for links in the message + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-editMessage-code.md" >}} + +## Delete message + +You can delete messages from the chat. + +```http request +DELETE /api/{session}/chats/{chatId}/messages/{messageId} +``` + +👉 Remember to escape `@` in `chatId` and `messageId` with `%40`. + +So if you want to delete `true_123@c.us_AAA` message in `123@c.us` chat you need to send request to: + +```http request +DELETE /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-deleteMessage-code.md" >}} + +## Add a reaction + +Use API to add a reaction to a message. + +```http request +PUT /api/reaction +``` + +{{< callout context="note" title="Use PUT method" icon="outline/alert-octagon" >}} +Reaction API uses **PUT**, not **POST** request! Please make sure you send right request. +{{< /callout >}} + +```json { title="Body" } +{ + "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "reaction": "👍", + "session": "default" +} +``` + +To **remove reaction from a message** - send empty string in the reaction request: + +```json { title="Body" } +{ + "messageId": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "reaction": "", + "session": "default" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-reaction-code.md" >}} + +## Star and unstar message + +Use API to star or unstar a message. + +```http request +PUT /api/star +``` + +{{< callout context="note" title="Use PUT method" icon="outline/alert-octagon" >}} +Star API uses **PUT**, not **POST** request! Please make sure you send right request. +{{< /callout >}} + +**Star:** + +```json { title="Body" } +{ + "messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "chatId": "71111111111@c.us", + "star": true, + "session": "default" +} +``` + +**Unstar:** + +```json { title="Body" } +{ + "messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "chatId": "71111111111@c.us", + "star": false, + "session": "default" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-star-code.md" >}} + +## Send contact (vcard) + +Use the API to send contact (vcard) + +```http request +POST /api/sendContactVcard +``` + +You can send contacts in multiple ways: + +{{< tabs "send-vcard-body" >}} +{{< tab "Fields" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "79111111@c.us", + "contacts": [ + { + "fullName": "John Doe", + "organization": "Company Name", + "phoneNumber": "+91 11111 11111", + "whatsappId": "911111111111" + } + ] +} +``` + +{{}} + +{{< tab "vCard" >}} + +```json { title="Body" } +{ + "session": "default", + "chatId": "79111111@c.us", + "contacts": [ + { + "vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD" + } + ] +} +``` + +{{}} + +{{< tab "Combined" >}} + +```json { title="Body" } +{ + "chatId": "79111111@c.us", + "contacts": [ + { + "vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD" + }, + { + "fullName": "John Doe", + "organization": "Company Name", + "phoneNumber": "+91 11111 11111", + "whatsappId": "911111111111" + } + ], + "session": "default" +} +``` + +{{}} + +{{< /tabs >}} + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendContactVcard-code.md" >}} + +## Send location + +```http request +POST /api/sendLocation +``` + +```json +{ + "chatId": "11111111111@c.us", + "latitude": 38.8937255, + "longitude": -77.0969763, + "title": "Our office", + "session": "default" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendLocation-code.md" >}} + +## Send Status (aka stories) + +You can send statuses (aka stories)! + +Check out [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) page. + +## Send messages to Channels + +You can send messages to channels! + +Check out [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) page. + +## Send Buttons Reply + +If you're using **Official Business API** to send buttons and wanna "click" on the buttons +(for testing or other purposes) you can do it using the API + +```http request +POST /api/send/buttons/reply +``` + +```json { title="Body" } +{ + "chatId": "11111111111@c.us", + "replyTo": "false_11111111111@c.us_AAAAAAAAAAAAAAAAA", + "selectedDisplayText": "No", + "selectedButtonID": "button:id", + "session": "default" +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendButtonsReply-code.md" >}} + +{{< details "**How to get fields for the Body**" >}} +When you get `message` event to the session, you need to get some fields from it. + +For testing purpose you can use [**📊 Dashboard - Event Monitor**]({{< relref "/docs/how-to/dashboard#event-monitor" >}}) to get the fields. + +{{< tabs "send-buttons-reply-message" >}} +{{< tab "WEBJS" >}} + +- **Message ID** - `payload.id` in format `false_11111111111@c.us_AAAAAAAAAA666` +- **Button ID** - `payload._data.dynamicReplyButtons.[1].buttonId` - like `button:id` +- **Button Display Text** - `payload._data.dynamicReplyButtons.[1].buttonText.displayText` - like `No` + {{< /tab >}} + +{{< tab "NOWEB" >}} + +- **Not implemented yet** + {{< /tab >}} + {{< tab "GOWS" >}} +- **Not implemented yet** + {{< /tab >}} + {{< /tabs >}} + +{{< /details >}} + +## Send Buttons + +{{< callout context="danger" title="Buttons do not work at the moment!" icon="outline/alert-octagon" >}} +Buttons are fragile creatures and may not work as expected. +Please consider adding fallback logic using text/poll messages. +{{< /callout >}} + +![alt](send-buttons.jpg) + +You can send **interactive message** (aka **buttons**) using + +```http request +POST /api/sendButtons +``` + +```json +{ + "chatId": "11111111111@c.us", + "header": "How are you?", + "headerImage": { + "mimetype": "image/jpeg", + "filename": "filename.jpg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + }, + "body": "Tell us how are you please 🙏", + "footer": "If you have any questions, please send it in the chat", + "buttons": [ + { + "type": "reply", + "text": "I am good!" + }, + { + "type": "call", + "text": "Call us", + "phoneNumber": "+1234567890" + }, + { + "type": "copy", + "text": "Copy code", + "copyCode": "4321" + }, + { + "type": "url", + "text": "How did you do that?", + "url": "https://waha.devlike.pro" + } + ], + "session": "default" +} +``` + +👉 `headerImage` is available only in +[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/send-messages/api-sendButtons-code.md" >}} + +### Buttons + +Here's available buttons you can use in `buttons`: + +{{< tabs "send-buttons-types" >}} +{{< tab "Quick Reply" >}} + +```json +{ + // Optional id + // "id": "123", + "type": "reply", + "text": "I am good!" +} +``` + +{{< /tab >}} + +{{< tab "URL" >}} + +```json +{ + "type": "url", + "text": "How did you do that?", + "url": "https://waha.devlike.pro" +} +``` + +{{< /tab >}} + +{{< tab "Call" >}} + +```json +{ + "type": "call", + "text": "Call us", + "phoneNumber": "+1234567890" +} +``` + +{{< /tab >}} + +{{< tab "Copy" >}} + +```json +{ + "type": "copy", + "text": "Copy code", + "copyCode": "4321" +} +``` + +{{< /tab >}} +{{< /tabs >}} diff --git a/content/docs/how-to/send-messages/media-video-convert.md b/content/docs/how-to/send-messages/media-video-convert.md index cf2a2ee55..f0133c9df 100644 --- a/content/docs/how-to/send-messages/media-video-convert.md +++ b/content/docs/how-to/send-messages/media-video-convert.md @@ -1,63 +1,66 @@ -```http request -POST /api/{SESSION}/media/convert/video -``` - -WhatsApp supports only the special format for video messages. - -You can convert any file to the right format using this API if you need to send video to many chats (so it doesn't get converted every time with `convert: true` flag in `/api/sendVideo`) - -{{< tabs "send-voice-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi" -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "data": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Response** depends on your `Accept` HTTP header you're using in request: - -```bash { title="Accept: application/json (Request)" } -curl -X 'POST' \ - 'http://localhost:3000/api/default/media/convert/video' \ - -H 'Accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi", - "data": null -}' -``` - -```json { title="Accept: application/json (Response)" } -{ - "mimetype": "video/mp4", - "data": "base64-encoded-content-here" -} -``` - -```bash {title="Accept: video/mp4 (Request)"} -curl -X POST \ - 'http://localhost:3000/api/default/media/convert/video' \ - -H 'Accept: video/mp4' \ - -H 'Content-Type: application/json' \ - -d '{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi", - "data": null -}' \ - --output output.mp4 -``` - - -```bash { title="Accept: video/mp4 (Response)" } -# Check file after curl above. -open output.mp4 -``` +```http request +POST /api/{SESSION}/media/convert/video +``` + +WhatsApp supports only the special format for video messages. + +You can convert any file to the right format using this API if you need to send video to many chats (so it doesn't get converted every time with `convert: true` flag in `/api/sendVideo`) + +{{< tabs "send-voice-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi" +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "data": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Response** depends on your `Accept` HTTP header you're using in request: + +```bash { title="Accept: application/json (Request)" } +curl -X 'POST' \ + 'http://localhost:3000/api/default/media/convert/video' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi", + "data": null +}' +``` + +```json { title="Accept: application/json (Response)" } +{ + "mimetype": "video/mp4", + "data": "base64-encoded-content-here" +} +``` + +```bash {title="Accept: video/mp4 (Request)"} +curl -X POST \ + 'http://localhost:3000/api/default/media/convert/video' \ + -H 'Accept: video/mp4' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.avi", + "data": null +}' \ + --output output.mp4 +``` + +```bash { title="Accept: video/mp4 (Response)" } +# Check file after curl above. +open output.mp4 +``` diff --git a/content/docs/how-to/send-messages/media-video-format.md b/content/docs/how-to/send-messages/media-video-format.md index 1b00fbad5..f352f950d 100644 --- a/content/docs/how-to/send-messages/media-video-format.md +++ b/content/docs/how-to/send-messages/media-video-format.md @@ -1,29 +1,31 @@ -
-{{< callout context="note" title="Video File Format" icon="outline/file" >}} -WhatsApp accepts only a file in **mp4 using libx264** format. - -If you have a file in a different format (like **avi**) you can use one of the options: - -1. **Set convert: true** in the body when calling API: -```json { title="Body" } -{ - ..., - "convert": true -} -``` - -2. **Convert file before sending** by calling [**🖼️ Media - Convert Video**](#media---convert-video) - -3. **Run ffmpeg**: -```bash -ffmpeg -i input_video.mp4 -c:v libx264 -map 0 -movflags +faststart output_video.mp4 -``` -`-map 0 -movflags +faststart` options required for thumbnail generation. -{{< /callout >}} - -{{< callout context="tip" title="WEBJS - use :chrome image" icon="outline/browser" >}} -If you're using **WEBJS** (default engine) - make sure to use `devlikeapro/waha-plus:chrome` docker image. - -Read more about [**Docker images and engines →**]({{< relref "/docs/how-to/engines" >}}). -{{< /callout >}} - +
+{{< callout context="note" title="Video File Format" icon="outline/file" >}} +WhatsApp accepts only a file in **mp4 using libx264** format. + +If you have a file in a different format (like **avi**) you can use one of the options: + +1. **Set convert: true** in the body when calling API: + +```json { title="Body" } +{ + ..., + "convert": true +} +``` + +2. **Convert file before sending** by calling [**🖼️ Media - Convert Video**](#media---convert-video) + +3. **Run ffmpeg**: + +```bash +ffmpeg -i input_video.mp4 -c:v libx264 -map 0 -movflags +faststart output_video.mp4 +``` + +`-map 0 -movflags +faststart` options required for thumbnail generation. +{{< /callout >}} + +{{< callout context="tip" title="WEBJS - use :chrome image" icon="outline/browser" >}} +If you're using **WEBJS** (default engine) - make sure to use `devlikeapro/waha-plus:chrome` docker image. + +Read more about [**Docker images and engines →**]({{< relref "/docs/how-to/engines" >}}). +{{< /callout >}} diff --git a/content/docs/how-to/send-messages/media-voice-convert.md b/content/docs/how-to/send-messages/media-voice-convert.md index 1edab7160..11415d8f0 100644 --- a/content/docs/how-to/send-messages/media-voice-convert.md +++ b/content/docs/how-to/send-messages/media-voice-convert.md @@ -1,64 +1,66 @@ -```http request -POST /api/{SESSION}/media/convert/voice -``` - -WhatsApp supports only the special format for voice (audio) messages. - -You can convert any file to the right format using this API if you need to send voice to many chats (so it doesn't get converted every time with `convert: true` flag in `/api/sendVoice`) - -{{< tabs "convert-voice-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3" -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "data": "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" -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Response** depends on your `Accept` HTTP header you're using in request: - -```bash { title="Accept: application/json (Request)" } -curl -X 'POST' \ - 'http://localhost:3000/api/default/media/convert/voice' \ - -H 'Accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3", - "data": null -}' -``` - -```json { title="Accept: application/json (Response)" } -{ - "mimetype": "audio/ogg; codecs=opus", - "data": "base64-encoded-content-here" -} -``` - -```bash {title="Accept: audio/ogg; codecs=opus (Request)"} -curl -X POST \ - 'http://localhost:3000/api/default/media/convert/voice' \ - -H 'Accept: audio/ogg; codecs=opus' \ - -H 'Content-Type: application/json' \ - -d '{ - "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3", - "data": null -}' \ - --output output.ogg -``` - - -```bash { title="Accept: audio/ogg; codecs=opus (Response)" } -# Check file after curl above. -open output.ogg -``` - +```http request +POST /api/{SESSION}/media/convert/voice +``` + +WhatsApp supports only the special format for voice (audio) messages. + +You can convert any file to the right format using this API if you need to send voice to many chats (so it doesn't get converted every time with `convert: true` flag in `/api/sendVoice`) + +{{< tabs "convert-voice-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3" +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "data": "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" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Response** depends on your `Accept` HTTP header you're using in request: + +```bash { title="Accept: application/json (Request)" } +curl -X 'POST' \ + 'http://localhost:3000/api/default/media/convert/voice' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3", + "data": null +}' +``` + +```json { title="Accept: application/json (Response)" } +{ + "mimetype": "audio/ogg; codecs=opus", + "data": "base64-encoded-content-here" +} +``` + +```bash {title="Accept: audio/ogg; codecs=opus (Request)"} +curl -X POST \ + 'http://localhost:3000/api/default/media/convert/voice' \ + -H 'Accept: audio/ogg; codecs=opus' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://github.com/devlikeapro/waha/raw/core/examples/voice.mp3", + "data": null +}' \ + --output output.ogg +``` + +```bash { title="Accept: audio/ogg; codecs=opus (Response)" } +# Check file after curl above. +open output.ogg +``` diff --git a/content/docs/how-to/send-messages/media-voice-format.md b/content/docs/how-to/send-messages/media-voice-format.md index 54fb6b375..dcd7d658d 100644 --- a/content/docs/how-to/send-messages/media-voice-format.md +++ b/content/docs/how-to/send-messages/media-voice-format.md @@ -1,21 +1,24 @@ -
-{{< callout context="note" title="Voice File Format" icon="outline/file" >}} -WhatsApp accept only file with **OPUS** encoding and packed in **OGG** container. - -If you have a file in a different format (like **mp3**) you can use one of the options: - -1. **Set convert: true** in the body when calling API: -```json { title="Body" } -{ - ..., - "convert": true -} -``` - -2. **Convert file before sending** by calling [**🖼️ Media - Convert Voice**](#media---convert-voice) - -3. **Run ffmpeg**: -```bash -ffmpeg -i input.mp3 -c:a libopus -b:a 32k -ar 48000 -ac 1 output.opus -``` -{{< /callout >}} +
+{{< callout context="note" title="Voice File Format" icon="outline/file" >}} +WhatsApp accept only file with **OPUS** encoding and packed in **OGG** container. + +If you have a file in a different format (like **mp3**) you can use one of the options: + +1. **Set convert: true** in the body when calling API: + +```json { title="Body" } +{ + ..., + "convert": true +} +``` + +2. **Convert file before sending** by calling [**🖼️ Media - Convert Voice**](#media---convert-voice) + +3. **Run ffmpeg**: + +```bash +ffmpeg -i input.mp3 -c:a libopus -b:a 32k -ar 48000 -ac 1 output.opus +``` + +{{< /callout >}} diff --git a/content/docs/how-to/sessions/api-session-create.md b/content/docs/how-to/sessions/api-session-create.md index d9a32a2ea..8a20241f8 100644 --- a/content/docs/how-to/sessions/api-session-create.md +++ b/content/docs/how-to/sessions/api-session-create.md @@ -1,119 +1,126 @@ -
- -{{< tabs "create-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sessions' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions"; -const data = { - name: "default", - config: { - webhooks: [ - { - url: "https://webhook.site/11111111-1111-1111-1111-11111111", - events: [ - "message" - ] - } - ] - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "config" => [ - "webhooks" => [ - [ - "url" => "https://webhook.site/11111111-1111-1111-1111-11111111", - "events" => [ - "message" - ] - ] - ] - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "create-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sessions' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": [ + "message" + ] + } + ] + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": [ + "message" + ] + } + ] + } +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions"; +const data = { + name: "default", + config: { + webhooks: [ + { + url: "https://webhook.site/11111111-1111-1111-1111-11111111", + events: ["message"] + } + ] + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "config" => [ + "webhooks" => [ + [ + "url" => "https://webhook.site/11111111-1111-1111-1111-11111111", + "events" => [ + "message" + ] + ] + ] + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-delete.md b/content/docs/how-to/sessions/api-session-delete.md index 2b2822848..951780d36 100644 --- a/content/docs/how-to/sessions/api-session-delete.md +++ b/content/docs/how-to/sessions/api-session-delete.md @@ -1,65 +1,74 @@ -
- -{{< tabs "delete-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'DELETE' \ - 'http://localhost:3000/api/sessions/default' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.delete(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default"; -const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.delete(url, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "delete-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'DELETE' \ + 'http://localhost:3000/api/sessions/default' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.delete(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default"; +const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .delete(url, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-get.md b/content/docs/how-to/sessions/api-session-get.md index 3f249d21d..ed7ddfdb6 100644 --- a/content/docs/how-to/sessions/api-session-get.md +++ b/content/docs/how-to/sessions/api-session-get.md @@ -1,64 +1,73 @@ -
- -{{< tabs "get-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'GET' \ - 'http://localhost:3000/api/sessions/default' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default"; -const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.get(url, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "get-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'GET' \ + 'http://localhost:3000/api/sessions/default' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default"; +const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .get(url, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-list.md b/content/docs/how-to/sessions/api-session-list.md index 8f4ab766d..83d7508c0 100644 --- a/content/docs/how-to/sessions/api-session-list.md +++ b/content/docs/how-to/sessions/api-session-list.md @@ -1,117 +1,125 @@ -
- -{{< tabs "list-sessions-api" "language" >}} - -{{< tab "cURL" >}} -```sh -# List active sessions -curl -X 'GET' \ - 'http://localhost:3000/api/sessions' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' - -# List all sessions (including stopped) -curl -X 'GET' \ - 'http://localhost:3000/api/sessions?all=true' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -# List active sessions -url = "http://localhost:3000/api/sessions" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) - -# List all sessions (including stopped) -url = "http://localhost:3000/api/sessions?all=true" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -// List active sessions -const getActiveSessions = async () => { - const url = "http://localhost:3000/api/sessions"; - const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { headers }); - console.log(response.data); -}; - -// List all sessions (including stopped) -const getAllSessions = async () => { - const url = "http://localhost:3000/api/sessions?all=true"; - const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { headers }); - console.log(response.data); -}; - -// Call the functions -getActiveSessions().catch(console.error); -getAllSessions().catch(console.error); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "list-sessions-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +# List active sessions +curl -X 'GET' \ + 'http://localhost:3000/api/sessions' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' + +# List all sessions (including stopped) +curl -X 'GET' \ + 'http://localhost:3000/api/sessions?all=true' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +# List active sessions +url = "http://localhost:3000/api/sessions" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) + +# List all sessions (including stopped) +url = "http://localhost:3000/api/sessions?all=true" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +// List active sessions +const getActiveSessions = async () => { + const url = "http://localhost:3000/api/sessions"; + const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { headers }); + console.log(response.data); +}; + +// List all sessions (including stopped) +const getAllSessions = async () => { + const url = "http://localhost:3000/api/sessions?all=true"; + const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { headers }); + console.log(response.data); +}; + +// Call the functions +getActiveSessions().catch(console.error); +getAllSessions().catch(console.error); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-logout.md b/content/docs/how-to/sessions/api-session-logout.md index c304ea6bf..65ba1b6f4 100644 --- a/content/docs/how-to/sessions/api-session-logout.md +++ b/content/docs/how-to/sessions/api-session-logout.md @@ -1,66 +1,75 @@ -
- -{{< tabs "logout-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sessions/default/logout' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default/logout" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.post(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default/logout"; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, {}, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "logout-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sessions/default/logout' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default/logout" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.post(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default/logout"; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, {}, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-me.md b/content/docs/how-to/sessions/api-session-me.md index ee188ac9c..cbd33340c 100644 --- a/content/docs/how-to/sessions/api-session-me.md +++ b/content/docs/how-to/sessions/api-session-me.md @@ -1,64 +1,73 @@ -
- -{{< tabs "get-session-me-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'GET' \ - 'http://localhost:3000/api/sessions/default/me' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default/me" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default/me"; -const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.get(url, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "get-session-me-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'GET' \ + 'http://localhost:3000/api/sessions/default/me' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default/me" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default/me"; +const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .get(url, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-pairing-code.md b/content/docs/how-to/sessions/api-session-pairing-code.md index e257b6ecb..5cfa3f7e1 100644 --- a/content/docs/how-to/sessions/api-session-pairing-code.md +++ b/content/docs/how-to/sessions/api-session-pairing-code.md @@ -1,79 +1,88 @@ -
- -{{< tabs "pairing-code-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/default/auth/request-code' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "phoneNumber": "12132132130" -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/default/auth/request-code" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "phoneNumber": "12132132130" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/default/auth/request-code"; -const data = { - phoneNumber: "12132132130" -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "12132132130" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "pairing-code-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/default/auth/request-code' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "phoneNumber": "12132132130" +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/default/auth/request-code" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "phoneNumber": "12132132130" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/default/auth/request-code"; +const data = { + phoneNumber: "12132132130" +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "12132132130" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-qr.md b/content/docs/how-to/sessions/api-session-qr.md index 526bc546c..d57520de3 100644 --- a/content/docs/how-to/sessions/api-session-qr.md +++ b/content/docs/how-to/sessions/api-session-qr.md @@ -1,165 +1,173 @@ -
- -{{< tabs "qr-code-api" "language" >}} - -{{< tab "cURL" >}} -```sh -# Get binary image -curl -X 'GET' \ - 'http://localhost:3000/api/default/auth/qr' \ - -H 'accept: image/png' \ - -H 'X-Api-Key: yoursecretkey' \ - --output qr-code.png - -# Get base64 image -curl -X 'GET' \ - 'http://localhost:3000/api/default/auth/qr' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' - -# Get raw QR code value -curl -X 'GET' \ - 'http://localhost:3000/api/default/auth/qr?format=raw' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -# Get binary image -url = "http://localhost:3000/api/default/auth/qr" -headers = { - "accept": "image/png", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -with open("qr-code.png", "wb") as f: - f.write(response.content) - -# Get base64 image -url = "http://localhost:3000/api/default/auth/qr" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) - -# Get raw QR code value -url = "http://localhost:3000/api/default/auth/qr?format=raw" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); -const fs = require('fs'); - -// Get binary image -const getBinaryImage = async () => { - const url = "http://localhost:3000/api/default/auth/qr"; - const headers = { - 'accept': 'image/png', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { - headers, - responseType: 'arraybuffer' - }); - - fs.writeFileSync('qr-code.png', response.data); -}; - -// Get base64 image -const getBase64Image = async () => { - const url = "http://localhost:3000/api/default/auth/qr"; - const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { headers }); - console.log(response.data); -}; - -// Get raw QR code value -const getRawQRCode = async () => { - const url = "http://localhost:3000/api/default/auth/qr?format=raw"; - const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { headers }); - console.log(response.data); -}; - -// Call the functions -getBinaryImage().catch(console.error); -getBase64Image().catch(console.error); -getRawQRCode().catch(console.error); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "qr-code-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +# Get binary image +curl -X 'GET' \ + 'http://localhost:3000/api/default/auth/qr' \ + -H 'accept: image/png' \ + -H 'X-Api-Key: yoursecretkey' \ + --output qr-code.png + +# Get base64 image +curl -X 'GET' \ + 'http://localhost:3000/api/default/auth/qr' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' + +# Get raw QR code value +curl -X 'GET' \ + 'http://localhost:3000/api/default/auth/qr?format=raw' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +# Get binary image +url = "http://localhost:3000/api/default/auth/qr" +headers = { + "accept": "image/png", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +with open("qr-code.png", "wb") as f: + f.write(response.content) + +# Get base64 image +url = "http://localhost:3000/api/default/auth/qr" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) + +# Get raw QR code value +url = "http://localhost:3000/api/default/auth/qr?format=raw" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); +const fs = require("fs"); + +// Get binary image +const getBinaryImage = async () => { + const url = "http://localhost:3000/api/default/auth/qr"; + const headers = { + "accept": "image/png", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { + headers, + responseType: "arraybuffer" + }); + + fs.writeFileSync("qr-code.png", response.data); +}; + +// Get base64 image +const getBase64Image = async () => { + const url = "http://localhost:3000/api/default/auth/qr"; + const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { headers }); + console.log(response.data); +}; + +// Get raw QR code value +const getRawQRCode = async () => { + const url = "http://localhost:3000/api/default/auth/qr?format=raw"; + const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { headers }); + console.log(response.data); +}; + +// Call the functions +getBinaryImage().catch(console.error); +getBase64Image().catch(console.error); +getRawQRCode().catch(console.error); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-restart.md b/content/docs/how-to/sessions/api-session-restart.md index 12632a279..924956ce3 100644 --- a/content/docs/how-to/sessions/api-session-restart.md +++ b/content/docs/how-to/sessions/api-session-restart.md @@ -1,66 +1,75 @@ -
- -{{< tabs "restart-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sessions/default/restart' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default/restart" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.post(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default/restart"; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, {}, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "restart-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sessions/default/restart' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default/restart" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.post(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default/restart"; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, {}, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-screenshot.md b/content/docs/how-to/sessions/api-session-screenshot.md index 1cbed9df8..6b18e12d5 100644 --- a/content/docs/how-to/sessions/api-session-screenshot.md +++ b/content/docs/how-to/sessions/api-session-screenshot.md @@ -1,122 +1,130 @@ -
- -{{< tabs "screenshot-api" "language" >}} - -{{< tab "cURL" >}} -```sh -# Get binary image -curl -X 'GET' \ - 'http://localhost:3000/api/screenshot?session=default' \ - -H 'accept: image/png' \ - -H 'X-Api-Key: yoursecretkey' \ - --output screenshot.png - -# Get base64 image -curl -X 'GET' \ - 'http://localhost:3000/api/screenshot?session=default' \ - -H 'accept: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -# Get binary image -url = "http://localhost:3000/api/screenshot?session=default" -headers = { - "accept": "image/png", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -with open("screenshot.png", "wb") as f: - f.write(response.content) - -# Get base64 image -url = "http://localhost:3000/api/screenshot?session=default" -headers = { - "accept": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.get(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); -const fs = require('fs'); - -// Get binary image -const getBinaryImage = async () => { - const url = "http://localhost:3000/api/screenshot?session=default"; - const headers = { - 'accept': 'image/png', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { - headers, - responseType: 'arraybuffer' - }); - - fs.writeFileSync('screenshot.png', response.data); -}; - -// Get base64 image -const getBase64Image = async () => { - const url = "http://localhost:3000/api/screenshot?session=default"; - const headers = { - 'accept': 'application/json', - 'X-Api-Key': 'yoursecretkey' - }; - - const response = await axios.get(url, { headers }); - console.log(response.data); -}; - -// Call the functions -getBinaryImage().catch(console.error); -getBase64Image().catch(console.error); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "screenshot-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +# Get binary image +curl -X 'GET' \ + 'http://localhost:3000/api/screenshot?session=default' \ + -H 'accept: image/png' \ + -H 'X-Api-Key: yoursecretkey' \ + --output screenshot.png + +# Get base64 image +curl -X 'GET' \ + 'http://localhost:3000/api/screenshot?session=default' \ + -H 'accept: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +# Get binary image +url = "http://localhost:3000/api/screenshot?session=default" +headers = { + "accept": "image/png", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +with open("screenshot.png", "wb") as f: + f.write(response.content) + +# Get base64 image +url = "http://localhost:3000/api/screenshot?session=default" +headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.get(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); +const fs = require("fs"); + +// Get binary image +const getBinaryImage = async () => { + const url = "http://localhost:3000/api/screenshot?session=default"; + const headers = { + "accept": "image/png", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { + headers, + responseType: "arraybuffer" + }); + + fs.writeFileSync("screenshot.png", response.data); +}; + +// Get base64 image +const getBase64Image = async () => { + const url = "http://localhost:3000/api/screenshot?session=default"; + const headers = { + "accept": "application/json", + "X-Api-Key": "yoursecretkey" + }; + + const response = await axios.get(url, { headers }); + console.log(response.data); +}; + +// Call the functions +getBinaryImage().catch(console.error); +getBase64Image().catch(console.error); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-start.md b/content/docs/how-to/sessions/api-session-start.md index 7277cfdf9..4cac46571 100644 --- a/content/docs/how-to/sessions/api-session-start.md +++ b/content/docs/how-to/sessions/api-session-start.md @@ -1,66 +1,75 @@ -
- -{{< tabs "start-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sessions/default/start' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default/start" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.post(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default/start"; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, {}, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "start-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sessions/default/start' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default/start" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.post(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default/start"; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, {}, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-stop.md b/content/docs/how-to/sessions/api-session-stop.md index 5e4386007..4509fad64 100644 --- a/content/docs/how-to/sessions/api-session-stop.md +++ b/content/docs/how-to/sessions/api-session-stop.md @@ -1,66 +1,75 @@ -
- -{{< tabs "stop-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sessions/default/stop' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default/stop" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} - -response = requests.post(url, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default/stop"; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.post(url, {}, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "stop-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sessions/default/stop' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default/stop" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} + +response = requests.post(url, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default/stop"; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .post(url, {}, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/api-session-update.md b/content/docs/how-to/sessions/api-session-update.md index 870d7e2d7..77aea6b89 100644 --- a/content/docs/how-to/sessions/api-session-update.md +++ b/content/docs/how-to/sessions/api-session-update.md @@ -1,119 +1,126 @@ -
- -{{< tabs "update-session-api" "language" >}} - -{{< tab "cURL" >}} -```sh -curl -X 'PUT' \ - 'http://localhost:3000/api/sessions/default' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -H 'X-Api-Key: yoursecretkey' \ - -d '{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -}' -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sessions/default" -headers = { - "Content-Type": "application/json", - "X-Api-Key": "yoursecretkey" -} -data = { - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} - -response = requests.put(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sessions/default"; -const data = { - name: "default", - config: { - webhooks: [ - { - url: "https://webhook.site/11111111-1111-1111-1111-11111111", - events: [ - "message" - ] - } - ] - } -}; -const headers = { - 'Content-Type': 'application/json', - 'X-Api-Key': 'yoursecretkey' -}; - -axios.put(url, data, { headers }) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` -{{< /tab >}} - -{{< tab "PHP" >}} -```php - "default", - "config" => [ - "webhooks" => [ - [ - "url" => "https://webhook.site/11111111-1111-1111-1111-11111111", - "events" => [ - "message" - ] - ] - ] - ] -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'X-Api-Key: yoursecretkey' -]); -$response = curl_exec($ch); -curl_close($ch); - -echo $response; -?> -``` -{{< /tab >}} - -{{< /tabs >}} \ No newline at end of file +
+ +{{< tabs "update-session-api" "language" >}} + +{{< tab "cURL" >}} + +```sh +curl -X 'PUT' \ + 'http://localhost:3000/api/sessions/default' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'X-Api-Key: yoursecretkey' \ + -d '{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": [ + "message" + ] + } + ] + } +}' +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sessions/default" +headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +} +data = { + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": [ + "message" + ] + } + ] + } +} + +response = requests.put(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sessions/default"; +const data = { + name: "default", + config: { + webhooks: [ + { + url: "https://webhook.site/11111111-1111-1111-1111-11111111", + events: ["message"] + } + ] + } +}; +const headers = { + "Content-Type": "application/json", + "X-Api-Key": "yoursecretkey" +}; + +axios + .put(url, data, { headers }) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` + +{{< /tab >}} + +{{< tab "PHP" >}} + +```php + "default", + "config" => [ + "webhooks" => [ + [ + "url" => "https://webhook.site/11111111-1111-1111-1111-11111111", + "events" => [ + "message" + ] + ] + ] + ] +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Api-Key: yoursecretkey' +]); +$response = curl_exec($ch); +curl_close($ch); + +echo $response; +?> +``` + +{{< /tab >}} + +{{< /tabs >}} diff --git a/content/docs/how-to/sessions/features-events.md b/content/docs/how-to/sessions/features-events.md index ac32f7b9c..e051f08f8 100644 --- a/content/docs/how-to/sessions/features-events.md +++ b/content/docs/how-to/sessions/features-events.md @@ -1,11 +1,10 @@ -
-{{< details "**🖥️ Sessions - Events**" >}} - -| **Events** | WEBJS | NOWEB | GOWS | -|------------------|:-----:|:-----:|:-----:| -| `session.status` | ✔️ | ✔️ | ✔️ | -| `engine.event` | ✔️ | ✔️ | ✔️ | -| ~~state.change~~ | ✔️ | ✔️ | ✔️ | - - -{{< /details >}} +
+{{< details "**🖥️ Sessions - Events**" >}} + +| **Events** | WEBJS | NOWEB | GOWS | +| ---------------- | :---: | :---: | :--: | +| `session.status` | ✔️ | ✔️ | ✔️ | +| `engine.event` | ✔️ | ✔️ | ✔️ | +| ~~state.change~~ | ✔️ | ✔️ | ✔️ | + +{{< /details >}} diff --git a/content/docs/how-to/sessions/features.md b/content/docs/how-to/sessions/features.md index 8206bca9f..1660fd691 100644 --- a/content/docs/how-to/sessions/features.md +++ b/content/docs/how-to/sessions/features.md @@ -1,22 +1,22 @@ -
-{{< details "**🖥️ Sessions - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|---------------------------------------------------------------|:-----:|:-----:|:-----| -| **List sessions**
`GET /api/sessions/` | ✔️ | ✔️ | ✔️ | -| **Get session**
`GET /api/sessions/{name}` | ✔️ | ✔️ | ✔️ | -| **Create session**
`POST /api/sessions/` | ✔️ | ✔️ | ✔️ | -| **Update session**
`POST /api/sessions/{name}/` | ✔️ | ✔️ | ✔️ | -| **Delete session**
`DELETE /api/sessions/{name}/` | ✔️ | ✔️ | ✔️ | -| **Start session**
`POST /api/sessions/{name}/start` | ✔️ | ✔️ | ✔️ | -| **Stop session**
`POST /api/sessions/{name}/stop` | ✔️ | ✔️ | ✔️ | -| **Restart session**
`POST /api/sessions/{name}/restart` | ✔️ | ✔️ | ✔️ | -| **Logout from a session**
`POST /api/sessions/logout` | ✔️ | ✔️ | ✔️ | -| **Get screenshot**
`GET /api/screenshot` | ✔️ | ➖ | ➖ | -| **Get me**
`GET /api/sessions/{session}/me` | ✔️ | ✔️ | ✔️ | -| **Get QR**
`POST /api/{session}/auth/qr` | ✔️ | ✔️ | ✔️ | -| **Request code**
`POST /api/{session}/auth/request-code` | ✔️ | ✔️ | ✔️ | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**🖥️ Sessions - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------------------- | :---: | :---: | :--- | +| **List sessions**
`GET /api/sessions/` | ✔️ | ✔️ | ✔️ | +| **Get session**
`GET /api/sessions/{name}` | ✔️ | ✔️ | ✔️ | +| **Create session**
`POST /api/sessions/` | ✔️ | ✔️ | ✔️ | +| **Update session**
`POST /api/sessions/{name}/` | ✔️ | ✔️ | ✔️ | +| **Delete session**
`DELETE /api/sessions/{name}/` | ✔️ | ✔️ | ✔️ | +| **Start session**
`POST /api/sessions/{name}/start` | ✔️ | ✔️ | ✔️ | +| **Stop session**
`POST /api/sessions/{name}/stop` | ✔️ | ✔️ | ✔️ | +| **Restart session**
`POST /api/sessions/{name}/restart` | ✔️ | ✔️ | ✔️ | +| **Logout from a session**
`POST /api/sessions/logout` | ✔️ | ✔️ | ✔️ | +| **Get screenshot**
`GET /api/screenshot` | ✔️ | ➖ | ➖ | +| **Get me**
`GET /api/sessions/{session}/me` | ✔️ | ✔️ | ✔️ | +| **Get QR**
`POST /api/{session}/auth/qr` | ✔️ | ✔️ | ✔️ | +| **Request code**
`POST /api/{session}/auth/request-code` | ✔️ | ✔️ | ✔️ | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/sessions/index.md b/content/docs/how-to/sessions/index.md index 4ac8e29e6..3a766b409 100644 --- a/content/docs/how-to/sessions/index.md +++ b/content/docs/how-to/sessions/index.md @@ -1,827 +1,810 @@ ---- -title: "🖥️ Sessions" -description: "All about sessions (WhatsApp accounts) actions." -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 210 -slug: sessions -images: ["waha-session-lifecycle.png"] ---- - -**Session** represents a **WhatsApp Account (Phone Number)** connected to **WAHA** -that you can use to send and receive messages. - -## Features - -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/sessions/features.md" >}} - -{{< include file="content/docs/how-to/sessions/features-events.md" >}} - -## Session Lifecycle - -Before you can -[**📤 Send**]({{< relref "/docs/how-to/send-messages" >}}) -or -[**📥 Receive**]({{< relref "/docs/how-to/receive-messages" >}}) -messages -, you need to [**Create**](#create-session) a session (optionally, [**Start**](#start-session)) and authenticate it using -[**QR code**](#get-qr) or [**pairing code**](#get-pairing-code). - -Here's Session Lifecycle State Diagram: - -{{< imgo src="waha-session-lifecycle.png" >}} - - -### Session Status - -Here's the list of possible `session.status` values: - -- `STOPPED` - session is stopped -- `STARTING` - session is starting -- `SCAN_QR_CODE` - session is required to scan QR code or login via phone number. - - The `SCAN_QR_CODE` is issued every time when QR updated (WhatsApp requirements) - - Every time you receive the `session.status` event with `SCAN_QR_CODE` status, - you need to [**fetch updated QR ->**]({{< relref "/docs/how-to/sessions#get-qr" >}}), because it's changed. -- `WORKING` - session is working and ready to use -- `FAILED` - session is failed due to some error. It's likely either authorization is required again or device has been - disconnected from that account. - Try to [**Restart**](#restart-session) the session and if it doesn't help - [**Logout**](#logout-session) and -[**Start **](#start-session) the session again. - - -## Create Session - -In order to create (and start) a new session - with [**Session Config**](#session-config). - -```http request -POST /api/sessions -``` - -```json { title="Body" } -{ - // "name" is Optional - it'll be generated automatically - "name": "default", - "config": { - // Read about Session Config below - ... - } -} -``` - -```json { title="Response" } -{ - "name": "session_123123123", - // if name is not provided - it'll be generated automatically - "status": "STARTING", - "engine": { - "engine": "WEBJS" - }, - "config": { - ... - }, - "me": null -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-create.md" >}} - -{{< callout >}} -**WAHA** uses session `name` more like "id", but we call it `name` for historical and compatibility reasons. -{{< /callout >}} - -### Postpone start - -By default, the session starts right after creation. -You can create a session and postpone its start by setting `start` field to `false`. -It'll create a session in `STOPPED` status, and you can start it later by calling `POST /api/sessions/{session}/start`. - -```json { title="Body" } -{ - "name": "default", - "start": false -} - -``` - -## Session Config -**Full possible config** for a session: - -```json -{ - "name": "default", - "config": { - "debug": true, - // Only for NOWEB engine - "noweb": { - "store": { - "enabled": true, - "fullSync": false - } - }, - // Use "metadata" to save additional information. - "metadata": { - "user.id": "123", - "user.email": "email@example.com" - }, - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - // Optional - "hmac": { - "key": "your-secret-key" - }, - // Optional - "customHeaders": [ - { - "name": "X-My-Custom-Header", - "value": "Value" - } - ], - // Optional - "retries": { - "policy": "constant", - "delaySeconds": 2, - "attempts": 15 - } - } - ], - // Optional - "proxy": { - "server": "localhost:3128", - // Optional - username, password - "username": "username", - "password": "P@ssw0rd" - } - } -} -``` - -### NOWEB - -[NOWEB **🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) has a specific store that allows you to save session data. - -You need to add `config.noweb` field to activate the store: - -```json -{ - "name": "default", - "config": { - "noweb": { - "store": { - "enabled": true, - "fullSync": false - } - } - } -} -``` - -### Metadata -`metadata` is an attribute on Session objects that lets you store more information, -structured as key-value pairs, -to sessions for your own use and reference. -For example, you can store your user’s unique identifier from your system. - -Associated `metadata` field is available in: -1. [List Sessions](#list-sessions) and [Get Session](#get-session) responses -2. [**🔄 Events**]({{< relref "events#metadata" >}}) events -3. [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata - - -```json -{ - "name": "default", - "config": { - "metadata": { - "user.id": "123", - "user.email": "email@example.com" - } - } -} -``` - -Sample `metadata` use cases: -- **Link IDs**: Attach your system’s unique IDs to a Session object to simplify lookups. For example, add your user or tenant id. -- **Customer details**: Annotate a customer by storing an internal information (email, customer name) for your future -use, so you don't have to look into two systems. - -WAHA does not use metadata for any internal purposes, it's up to you how to use it. - - -### Webhooks -Read more about -[**🔄 Events - Webhooks**]({{< relref "/docs/how-to/events#webhooks" >}}). - -You can configure webhooks for a session: - -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} -``` - -**Full possible webhook config**: -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ], - // Optional - "hmac": { - "key": "your-secret-key" - }, - // Optional - "customHeaders": [ - { - "name": "X-My-Custom-Header", - "value": "Value" - } - ], - // Optional - "retries": { - "policy": "constant", - "delaySeconds": 2, - "attempts": 15 - } - } - ] - } -} - -``` - -👉 Read more about available options on -[**🔄 Webhooks**]({{< relref "/docs/how-to/events#webhooks-advanced-imagesversionspluspng" >}}) page. - - - -### Proxy - -You can configure proxy for a session by setting `config.proxy` fields when you create or update a session. - -- `server` - proxy server address, without `http://` or `https://` prefixes -- `username` and `password` - set this if the proxy requires authentication - -**No authentication** - -```json -{ - "name": "default", - "config": { - "proxy": { - "server": "localhost:3128" - } - } -} -``` - -**Proxy with authentication** - -```json -{ - "name": "default", - "config": { - "proxy": { - "server": "localhost:3128", - "username": "username", - "password": "P@ssw0rd" - } - } -} -``` - -You can configure proxy when for all sessions by set up environment variables. -Read more about it on [**Proxy page** ->]({{< relref "/docs/how-to/proxy" >}}) or [**Configuration page** ->]({{< -relref "/docs/how-to/config#proxy" >}}). - -👉 Read more about [**NOWEB Store Configuration**]({{< relref "/docs/engines/noweb#store" >}}). - -### Debug - -You can enable debug mode for a session by setting `config.debug` field to `true`. -It'll show you more logs in the console. -Can be useful for debugging purposes when you're experiencing some issues. - -```json -{ - "name": "default", - "config": { - "debug": true - } -} -``` - - -## Update Session - -In order to update a session - call `PUT /api/sessions/{session}` with a **full** new configuration -(see the possible `config` in [**Session Config**](#session-config) section) - -```json -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-update.md" >}} - -⚠️ If the session not in `STOPPED` status, it'll be **stopped** and **started** with a new configuration. - -## Start Session - -In order to start a session - call - -```http request -POST /api/sessions/{session}/start -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-start.md" >}} - -🎯 **Idempotent operation** - you can call it multiple times, and it'll start the session only if it's not running. - -## Stop Session - -In order to stop a session - call - -```http request -POST /api/sessions/{session}/stop -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-stop.md" >}} - -ℹ️ **Stop** doesn't **Log out** or **Delete** anything - -🎯 **Idempotent operation** - you can call it multiple times, and it'll stop the session only if it's running. - -## Restart Session - -In order to start a session - call - -```http request -POST /api/sessions/{session}/restart -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-restart.md" >}} - -⚠️ If the session is already running (status is not `STOPPED`), it'll be **stopped** and **started**. - -## Logout Session - -In order to log out the session - call - -```http request -POST /api/sessions/{session}/logout -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-logout.md" >}} - -⚠️ If the session is running (not in `STOPPED` status), it'll be **logged out** and **started** from scratch. - -👉 If the session in `WORKING` status it'll also remove associated device from **Connected Devices** list in the app. - -ℹ️ **Log out** removes **session information** (authentication info and data), -but keeps the **session's configuration**, so you can start a new session with the same configuration. - -## Delete Session - -In order to delete a session - call - -```http request -DELETE /api/sessions/{session} -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-delete.md" >}} - -⚠️ **Delete** also **logs out** the session (removes both session configuration and data). - -⚠️ **Delete** also **stops** the session if it's running (session status is not `STOPPED`) - -🎯 **Idempotent operation** - you can call it multiple times, and it'll stop the session only if it exists. - -## List Sessions - -To get session list - call - -```http request -GET /api/sessions -``` - -```json { title="Response" } -[ - { - "name": "default", - "status": "WORKING", - "config": { - "proxy": null, - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message", - "session.status" - ], - "hmac": null, - "retries": null, - "customHeaders": null - } - ], - "debug": false - }, - "me": { - "id": "79111111@c.us", - "pushName": "WAHA" - }, - "engine": { - "engine": "NOWEB" - } - } -] -``` - -You can add `?all=true` parameter to the request it'll show you ALL session, including **STOPPED**. - -```http request -GET /api/sessions?all=true -``` - -## Get Session - -To get information about a specific session - call - -```http request -GET /api/sessions/{session} -``` - -```json { title="Response" } -{ - "name": "default", - "status": "WORKING", - "config": { - "proxy": null, - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message", - "session.status" - ], - "hmac": null, - "retries": null, - "customHeaders": null - } - ], - "debug": false - }, - "me": { - "id": "79111111@c.us", - "pushName": "WAHA" - }, - "engine": { - "engine": "NOWEB" - } -} -``` - -## Get screenshot - -Get screenshot of the session's screen. - -### Binary - -```http request -GET /api/screenshot?session=default -``` - -### Base64 - -You can get screenshot in base64 format by adding `Accept: application/json` header to the request. - -```http request -GET /api/screenshot?session=default -``` - -```http request {title="Headers"} -Accept: application/json -``` - -```json { title="Response" } -{ - "mimetype": "image/png", - "data": "base64-encoded-data" -} -``` - -You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**: - -{{< imgo src="/images/swagger-media-type.png" alt="swagger" >}} - -{{< include file="content/docs/how-to/sessions/api-session-screenshot.md" >}} - -## Get me - -ℹ️ You'll get the same info if you request `GET /api/sessions/{session}` in `me` field. - -Get information about the associated account for that session (if any). - -```http request -GET /api/sessions/{session}/me -``` - -**Authenticated and working** session's response: - -```json { title="Response" } -{ - "id": "11111111111@c.us", - "pushName": "string" -} -``` - -**Stopped** or **not authenticated** session returns `null`: - -```json { title="Response" } -null -``` - -{{< include file="content/docs/how-to/sessions/api-session-me.md" >}} - -## Get QR - -The simplest way to authenticate a new session - get QR code and scan it on your device. - -```http request -GET /api/{session}/auth/qr -``` - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-qr.md" >}} - -You'll get QR image that you can scan and get authenticated - -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` - -### Binary - -**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 -``` - -### Base64 - -**Base64 image** - you'll get image in base64 format in response if you set `Accept: application/json` header. - -```http request -GET /api/{session}/auth/qr?format=image -``` - -```http request {title="Headers"} -Accept: application/json -``` - -```json { title="Response" } -{ - "mimetype": "image/png", - "data": "base64-encoded-data" -} -``` - -You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**: - -{{< imgo src="/images/swagger-media-type.png" alt="swagger" >}} - -### Raw - -**Raw** - you'll get raw data in response, you can use it **to generate QR code on your side** with the `value`. - -```http request -GET /api/{session}/auth/qr?format=raw -``` - -```json { title="Response" } -{ - "value": "value-that-you-need-to-use-to-generate-qr-code" -} -``` - -## Get pairing code - -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. - -```http request -POST /api/{session}/auth/request-code -``` - -Body example: - -```json -{ - "phoneNumber": "12132132130" -} -``` - -You'll get code in the need to enter in **WhatsApp app** to authenticate the session: - -```json { title="Response" } -{ - "code": "ABCD-ABCD" -} -``` - -👉 **Always** add to [**QR code auth flow**](#get-qr) in your application as a fallback, -because the pairing code is not always available and works as expected. - -Here's how you can call it from various languages: -{{< include file="content/docs/how-to/sessions/api-session-pairing-code.md" >}} - -## Events - -Read more about -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). - -### session.status - -The `session.status` event is triggered when the session status changes. - -```json { title="session.status" } -{ - "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" - } -} -``` - -## engine.event -Internal event that is triggered when the engine emits an event. - -```json { title="engine.event" } -{ - "id": "evt_11111111111111111111111111", - "session": "default", - "event": "engine.event", - "payload": { - "session": "default", - "event": "{{engine.EventName}}", - "data": { - "field": "value" - } - }, - "timestamp": 1742102571277, - "metadata": {}, - "me": { - "": null - }, - "environment": { - "": null - } -} -``` - -## Advanced sessions - -With [WAHA Plus version]({{< relref "waha-plus" >}}) you can save session state to avoid scanning QR code everytime, -configure autostart options so when the docker container restarts - it restores all previously run sessions! - -### Session persistent - -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 - -By default, WAHA track which session have been run on which worker and restart it when -worker got restarted. If you want to disable it - set `WAHA_WORKER_RESTART_SESSIONS=False` in -environment variable. - -### Multiple sessions - -If you want to save server's CPU and Memory - run multiple sessions inside one docker container! -[Plus version]({{< relref "waha-plus" >}}) supports multiple sessions in one container. - -## DEPRECATED - -Before new granular API we have a simple API to control the session. - -**Kindly switch to new API** that allows you to control the session **in a more flexible way**. - -### Start -The endpoint **Create** (if not exists), -**Update** (if existed before) and **Start** a new session. - -```http request -POST /api/sessions/start -``` - -Accepts the same configuration as -[Create](#create-session) and [Update](#update-session) API. - -```json { title="Body" } -{ - "name": "default", - "config": { - "webhooks": [ - { - "url": "https://webhook.site/11111111-1111-1111-1111-11111111", - "events": [ - "message" - ] - } - ] - } -} -``` - -### Stop - -```http request -POST /api/sessions/stop -``` - -- **Stop** if `logout: false` -- **Stop**, **Logout** and **Delete** session if `logout: true` - -```json { title="Body" } -{ - "name": "default", - "logout": true -} -``` - -### Logout - -**Logout** and **Delete** session. - -```http request -POST /api/sessions/logout -``` - -```json { title="Body" } -{ - "name": "default" -} -``` +--- +title: "🖥️ Sessions" +description: "All about sessions (WhatsApp accounts) actions." +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 210 +slug: sessions +images: ["waha-session-lifecycle.png"] +--- + +**Session** represents a **WhatsApp Account (Phone Number)** connected to **WAHA** +that you can use to send and receive messages. + +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/sessions/features.md" >}} + +{{< include file="content/docs/how-to/sessions/features-events.md" >}} + +## Session Lifecycle + +Before you can +[**📤 Send**]({{< relref "/docs/how-to/send-messages" >}}) +or +[**📥 Receive**]({{< relref "/docs/how-to/receive-messages" >}}) +messages +, you need to [**Create**](#create-session) a session (optionally, [**Start**](#start-session)) and authenticate it using +[**QR code**](#get-qr) or [**pairing code**](#get-pairing-code). + +Here's Session Lifecycle State Diagram: + +{{< imgo src="waha-session-lifecycle.png" >}} + +### Session Status + +Here's the list of possible `session.status` values: + +- `STOPPED` - session is stopped +- `STARTING` - session is starting +- `SCAN_QR_CODE` - session is required to scan QR code or login via phone number. + - The `SCAN_QR_CODE` is issued every time when QR updated (WhatsApp requirements) + - Every time you receive the `session.status` event with `SCAN_QR_CODE` status, + you need to [**fetch updated QR ->**]({{< relref "/docs/how-to/sessions#get-qr" >}}), because it's changed. +- `WORKING` - session is working and ready to use +- `FAILED` - session is failed due to some error. It's likely either authorization is required again or device has been + disconnected from that account. + Try to [**Restart**](#restart-session) the session and if it doesn't help - [**Logout**](#logout-session) and + [**Start **](#start-session) the session again. + +## Create Session + +In order to create (and start) a new session - with [**Session Config**](#session-config). + +```http request +POST /api/sessions +``` + +```json { title="Body" } +{ + // "name" is Optional - it'll be generated automatically + "name": "default", + "config": { + // Read about Session Config below + ... + } +} +``` + +```json { title="Response" } +{ + "name": "session_123123123", + // if name is not provided - it'll be generated automatically + "status": "STARTING", + "engine": { + "engine": "WEBJS" + }, + "config": { + ... + }, + "me": null +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-create.md" >}} + +{{< callout >}} +**WAHA** uses session `name` more like "id", but we call it `name` for historical and compatibility reasons. +{{< /callout >}} + +### Postpone start + +By default, the session starts right after creation. +You can create a session and postpone its start by setting `start` field to `false`. +It'll create a session in `STOPPED` status, and you can start it later by calling `POST /api/sessions/{session}/start`. + +```json { title="Body" } +{ + "name": "default", + "start": false +} +``` + +## Session Config + +**Full possible config** for a session: + +```json +{ + "name": "default", + "config": { + "debug": true, + // Only for NOWEB engine + "noweb": { + "store": { + "enabled": true, + "fullSync": false + } + }, + // Use "metadata" to save additional information. + "metadata": { + "user.id": "123", + "user.email": "email@example.com" + }, + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + // Optional + "hmac": { + "key": "your-secret-key" + }, + // Optional + "customHeaders": [ + { + "name": "X-My-Custom-Header", + "value": "Value" + } + ], + // Optional + "retries": { + "policy": "constant", + "delaySeconds": 2, + "attempts": 15 + } + } + ], + // Optional + "proxy": { + "server": "localhost:3128", + // Optional - username, password + "username": "username", + "password": "P@ssw0rd" + } + } +} +``` + +### NOWEB + +[NOWEB **🏭 Engine**]({{< relref "/docs/how-to/engines" >}}) has a specific store that allows you to save session data. + +You need to add `config.noweb` field to activate the store: + +```json +{ + "name": "default", + "config": { + "noweb": { + "store": { + "enabled": true, + "fullSync": false + } + } + } +} +``` + +### Metadata + +`metadata` is an attribute on Session objects that lets you store more information, +structured as key-value pairs, +to sessions for your own use and reference. +For example, you can store your user’s unique identifier from your system. + +Associated `metadata` field is available in: + +1. [List Sessions](#list-sessions) and [Get Session](#get-session) responses +2. [**🔄 Events**]({{< relref "events#metadata" >}}) events +3. [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata + +```json +{ + "name": "default", + "config": { + "metadata": { + "user.id": "123", + "user.email": "email@example.com" + } + } +} +``` + +Sample `metadata` use cases: + +- **Link IDs**: Attach your system’s unique IDs to a Session object to simplify lookups. For example, add your user or tenant id. +- **Customer details**: Annotate a customer by storing an internal information (email, customer name) for your future + use, so you don't have to look into two systems. + +WAHA does not use metadata for any internal purposes, it's up to you how to use it. + +### Webhooks + +Read more about +[**🔄 Events - Webhooks**]({{< relref "/docs/how-to/events#webhooks" >}}). + +You can configure webhooks for a session: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"] + } + ] + } +} +``` + +**Full possible webhook config**: + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"], + // Optional + "hmac": { + "key": "your-secret-key" + }, + // Optional + "customHeaders": [ + { + "name": "X-My-Custom-Header", + "value": "Value" + } + ], + // Optional + "retries": { + "policy": "constant", + "delaySeconds": 2, + "attempts": 15 + } + } + ] + } +} +``` + +👉 Read more about available options on +[**🔄 Webhooks**]({{< relref "/docs/how-to/events#webhooks-advanced-imagesversionspluspng" >}}) page. + +### Proxy + +You can configure proxy for a session by setting `config.proxy` fields when you create or update a session. + +- `server` - proxy server address, without `http://` or `https://` prefixes +- `username` and `password` - set this if the proxy requires authentication + +**No authentication** + +```json +{ + "name": "default", + "config": { + "proxy": { + "server": "localhost:3128" + } + } +} +``` + +**Proxy with authentication** + +```json +{ + "name": "default", + "config": { + "proxy": { + "server": "localhost:3128", + "username": "username", + "password": "P@ssw0rd" + } + } +} +``` + +You can configure proxy when for all sessions by set up environment variables. +Read more about it on [**Proxy page** ->]({{< relref "/docs/how-to/proxy" >}}) or [**Configuration page** ->]({{< +relref "/docs/how-to/config#proxy" >}}). + +👉 Read more about [**NOWEB Store Configuration**]({{< relref "/docs/engines/noweb#store" >}}). + +### Debug + +You can enable debug mode for a session by setting `config.debug` field to `true`. +It'll show you more logs in the console. +Can be useful for debugging purposes when you're experiencing some issues. + +```json +{ + "name": "default", + "config": { + "debug": true + } +} +``` + +## Update Session + +In order to update a session - call `PUT /api/sessions/{session}` with a **full** new configuration +(see the possible `config` in [**Session Config**](#session-config) section) + +```json +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"] + } + ] + } +} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-update.md" >}} + +⚠️ If the session not in `STOPPED` status, it'll be **stopped** and **started** with a new configuration. + +## Start Session + +In order to start a session - call + +```http request +POST /api/sessions/{session}/start +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-start.md" >}} + +🎯 **Idempotent operation** - you can call it multiple times, and it'll start the session only if it's not running. + +## Stop Session + +In order to stop a session - call + +```http request +POST /api/sessions/{session}/stop +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-stop.md" >}} + +ℹ️ **Stop** doesn't **Log out** or **Delete** anything + +🎯 **Idempotent operation** - you can call it multiple times, and it'll stop the session only if it's running. + +## Restart Session + +In order to start a session - call + +```http request +POST /api/sessions/{session}/restart +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-restart.md" >}} + +⚠️ If the session is already running (status is not `STOPPED`), it'll be **stopped** and **started**. + +## Logout Session + +In order to log out the session - call + +```http request +POST /api/sessions/{session}/logout +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-logout.md" >}} + +⚠️ If the session is running (not in `STOPPED` status), it'll be **logged out** and **started** from scratch. + +👉 If the session in `WORKING` status it'll also remove associated device from **Connected Devices** list in the app. + +ℹ️ **Log out** removes **session information** (authentication info and data), +but keeps the **session's configuration**, so you can start a new session with the same configuration. + +## Delete Session + +In order to delete a session - call + +```http request +DELETE /api/sessions/{session} +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-delete.md" >}} + +⚠️ **Delete** also **logs out** the session (removes both session configuration and data). + +⚠️ **Delete** also **stops** the session if it's running (session status is not `STOPPED`) + +🎯 **Idempotent operation** - you can call it multiple times, and it'll stop the session only if it exists. + +## List Sessions + +To get session list - call + +```http request +GET /api/sessions +``` + +```json { title="Response" } +[ + { + "name": "default", + "status": "WORKING", + "config": { + "proxy": null, + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message", "session.status"], + "hmac": null, + "retries": null, + "customHeaders": null + } + ], + "debug": false + }, + "me": { + "id": "79111111@c.us", + "pushName": "WAHA" + }, + "engine": { + "engine": "NOWEB" + } + } +] +``` + +You can add `?all=true` parameter to the request it'll show you ALL session, including **STOPPED**. + +```http request +GET /api/sessions?all=true +``` + +## Get Session + +To get information about a specific session - call + +```http request +GET /api/sessions/{session} +``` + +```json { title="Response" } +{ + "name": "default", + "status": "WORKING", + "config": { + "proxy": null, + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message", "session.status"], + "hmac": null, + "retries": null, + "customHeaders": null + } + ], + "debug": false + }, + "me": { + "id": "79111111@c.us", + "pushName": "WAHA" + }, + "engine": { + "engine": "NOWEB" + } +} +``` + +## Get screenshot + +Get screenshot of the session's screen. + +### Binary + +```http request +GET /api/screenshot?session=default +``` + +### Base64 + +You can get screenshot in base64 format by adding `Accept: application/json` header to the request. + +```http request +GET /api/screenshot?session=default +``` + +```http request {title="Headers"} +Accept: application/json +``` + +```json { title="Response" } +{ + "mimetype": "image/png", + "data": "base64-encoded-data" +} +``` + +You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**: + +{{< imgo src="/images/swagger-media-type.png" alt="swagger" >}} + +{{< include file="content/docs/how-to/sessions/api-session-screenshot.md" >}} + +## Get me + +ℹ️ You'll get the same info if you request `GET /api/sessions/{session}` in `me` field. + +Get information about the associated account for that session (if any). + +```http request +GET /api/sessions/{session}/me +``` + +**Authenticated and working** session's response: + +```json { title="Response" } +{ + "id": "11111111111@c.us", + "pushName": "string" +} +``` + +**Stopped** or **not authenticated** session returns `null`: + +```json { title="Response" } +null +``` + +{{< include file="content/docs/how-to/sessions/api-session-me.md" >}} + +## Get QR + +The simplest way to authenticate a new session - get QR code and scan it on your device. + +```http request +GET /api/{session}/auth/qr +``` + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-qr.md" >}} + +You'll get QR image that you can scan and get authenticated + +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` + +### Binary + +**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 +``` + +### Base64 + +**Base64 image** - you'll get image in base64 format in response if you set `Accept: application/json` header. + +```http request +GET /api/{session}/auth/qr?format=image +``` + +```http request {title="Headers"} +Accept: application/json +``` + +```json { title="Response" } +{ + "mimetype": "image/png", + "data": "base64-encoded-data" +} +``` + +You can change it in Swagger by clicking on **Media Type** dropdown and selecting **application/json**: + +{{< imgo src="/images/swagger-media-type.png" alt="swagger" >}} + +### Raw + +**Raw** - you'll get raw data in response, you can use it **to generate QR code on your side** with the `value`. + +```http request +GET /api/{session}/auth/qr?format=raw +``` + +```json { title="Response" } +{ + "value": "value-that-you-need-to-use-to-generate-qr-code" +} +``` + +## Get pairing code + +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. + +```http request +POST /api/{session}/auth/request-code +``` + +Body example: + +```json +{ + "phoneNumber": "12132132130" +} +``` + +You'll get code in the need to enter in **WhatsApp app** to authenticate the session: + +```json { title="Response" } +{ + "code": "ABCD-ABCD" +} +``` + +👉 **Always** add to [**QR code auth flow**](#get-qr) in your application as a fallback, +because the pairing code is not always available and works as expected. + +Here's how you can call it from various languages: +{{< include file="content/docs/how-to/sessions/api-session-pairing-code.md" >}} + +## Events + +Read more about +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}). + +### session.status + +The `session.status` event is triggered when the session status changes. + +```json { title="session.status" } +{ + "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" + } +} +``` + +## engine.event + +Internal event that is triggered when the engine emits an event. + +```json { title="engine.event" } +{ + "id": "evt_11111111111111111111111111", + "session": "default", + "event": "engine.event", + "payload": { + "session": "default", + "event": "{{engine.EventName}}", + "data": { + "field": "value" + } + }, + "timestamp": 1742102571277, + "metadata": {}, + "me": { + "": null + }, + "environment": { + "": null + } +} +``` + +## Advanced sessions + +With [WAHA Plus version]({{< relref "waha-plus" >}}) you can save session state to avoid scanning QR code everytime, +configure autostart options so when the docker container restarts - it restores all previously run sessions! + +### Session persistent + +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 + +By default, WAHA track which session have been run on which worker and restart it when +worker got restarted. If you want to disable it - set `WAHA_WORKER_RESTART_SESSIONS=False` in +environment variable. + +### Multiple sessions + +If you want to save server's CPU and Memory - run multiple sessions inside one docker container! +[Plus version]({{< relref "waha-plus" >}}) supports multiple sessions in one container. + +## DEPRECATED + +Before new granular API we have a simple API to control the session. + +**Kindly switch to new API** that allows you to control the session **in a more flexible way**. + +### Start + +The endpoint **Create** (if not exists), +**Update** (if existed before) and **Start** a new session. + +```http request +POST /api/sessions/start +``` + +Accepts the same configuration as +[Create](#create-session) and [Update](#update-session) API. + +```json { title="Body" } +{ + "name": "default", + "config": { + "webhooks": [ + { + "url": "https://webhook.site/11111111-1111-1111-1111-11111111", + "events": ["message"] + } + ] + } +} +``` + +### Stop + +```http request +POST /api/sessions/stop +``` + +- **Stop** if `logout: false` +- **Stop**, **Logout** and **Delete** session if `logout: true` + +```json { title="Body" } +{ + "name": "default", + "logout": true +} +``` + +### Logout + +**Logout** and **Delete** session. + +```http request +POST /api/sessions/logout +``` + +```json { title="Body" } +{ + "name": "default" +} +``` diff --git a/content/docs/how-to/status/features.md b/content/docs/how-to/status/features.md index f385be257..b2111dee7 100644 --- a/content/docs/how-to/status/features.md +++ b/content/docs/how-to/status/features.md @@ -1,15 +1,15 @@ -
-{{< details "**🟢 Status - API**" >}} - -| **API** | WEBJS | NOWEB | GOWS | -|--------------------------------------------------------------------------------|:-----:|:-----:|:-----:| -| **Send Text Status**
`POST /api/{session}/status/text` | ✔️ | ✔️ | ✔️ | -| **Send Image Status**
`POST /api/{session}/status/image` | ✔️ | ✔️ | ✔️ | -| **Send Voice Status**
`POST /api/{session}/status/voice` | ✔️ | ✔️ | ✔️ | -| **Send Video Status**
`POST /api/{session}/status/video` | ✔️ | ✔️ | ✔️ | -| **Delete Status**
`POST /api/{session}/status/delete` | | ✔️ | ✔️ | -| **Get New Status Message ID**
`GET /api/{session}/status/new-message-id` | | ✔️ | ✔️ | - -_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ - -{{< /details >}} +
+{{< details "**🟢 Status - API**" >}} + +| **API** | WEBJS | NOWEB | GOWS | +| ------------------------------------------------------------------------------ | :---: | :---: | :--: | +| **Send Text Status**
`POST /api/{session}/status/text` | ✔️ | ✔️ | ✔️ | +| **Send Image Status**
`POST /api/{session}/status/image` | ✔️ | ✔️ | ✔️ | +| **Send Voice Status**
`POST /api/{session}/status/voice` | ✔️ | ✔️ | ✔️ | +| **Send Video Status**
`POST /api/{session}/status/video` | ✔️ | ✔️ | ✔️ | +| **Delete Status**
`POST /api/{session}/status/delete` | | ✔️ | ✔️ | +| **Get New Status Message ID**
`GET /api/{session}/status/new-message-id` | | ✔️ | ✔️ | + +_If you see the feature is not available in the above list, please [create a feature request](https://github.com/devlikeapro/waha/issues/new/choose) or **leave "+1" comment** on the existing one._ + +{{< /details >}} diff --git a/content/docs/how-to/status/index.md b/content/docs/how-to/status/index.md index d090d0d7e..448cbb979 100644 --- a/content/docs/how-to/status/index.md +++ b/content/docs/how-to/status/index.md @@ -1,398 +1,414 @@ ---- -title : "🟢 Status" -description: "Status (aka Stories)" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 232 -slug: status -images: [ "status.png" ] ---- - -You can send statuses (aka stories) using HTTP API! - -
-{{< img lqip="21x webp q20" src="status.png" alt="WhatsApp Status" >}} -
- - -## Features -Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): - -{{< include file="content/docs/how-to/status/features.md" >}} - -## API - -{{< callout context="note" icon="outline/info-circle" title="About contacts field" >}} -When you send status you can provide optional `contacts` field - list of contacts to send status to. - -- [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) engine **doesn't suppport** `contacts` field. You can send status to all contacts (or configure white/black list in the app before). -- [**NOWEB**]({{< relref "/docs/how-to/engines#noweb" >}}) engine **supports** `contacts` field, you must [**🏭 Enable NOWEB Store before using these endpoints**]({{< relref "/docs/engines/NOWEB#store" >}}) -- [**GOWS**]({{< relref "/docs/how-to/engines#gows" >}}) engine **supports** `contacts` field. - -You can fetch your contacts using [**👤 Contacts API**]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}). - -```json { title="Body" } -{ - "text": "Have a look! https://waha.devlike.pro/", - "contacts": ["123123@c.us", "3333@c.us"], - "backgroundColor": "#38b42f", - "font": 1 -} -``` - -{{< /callout >}} - - -### Send Text Status -Send status to **all** your contacts: -```http request -POST /api/{session}/status/text -``` - -```json { title="Body" } -{ - "text": "Have a look! https://waha.devlike.pro/", - "backgroundColor": "#38b42f", - "font": 1 -} -``` -- `text` - text to send as status. -- `font` - font type, experiment with values here to get different fonts. -- `backgroundColor` - background color of the status. -- `contacts` - array of contacts to send status to. - -Send status to specific contacts: -```json { title="Body" } -{ - "text": "Have a look! https://waha.devlike.pro/", - "backgroundColor": "#38b42f", - "font": 1, - "contacts": [ - "55xxxxxxxxxxx@c.us", - "55xxxxxxxxxxx@c.us" - ] -} -``` - -### Send Image Status -```http request -POST /api/{session}/status/image -``` - -{{< tabs "send-image-status-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" - }, - "caption": "string" -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} - -```json { title="Body" } -{ - "file": { - "mimetype": "image/jpeg", - "data": "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" - }, - "caption": "string" -} -``` -{{< /tab >}} -{{< /tabs >}} - -### Send Video Status -```http request -POST /api/{session}/status/video -``` - -{{< tabs "send-video-status-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "file": { - "mimetype": "video/mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "backgroundColor": "#38b42f" -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "file": { - "mimetype": "video/mp4", - "filename": "video.mp4", - "data": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" - }, - "backgroundColor": "#38b42f" -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Fields**: -- `file` - provide **one of** the fields: - - `url` - URL to the file - - `data` - Base 64 encoded binary content of the file -- `convert: false` - convert the file to the right format. **Default:** `false` - - Set `convert: true` if you don't have the right format, check the format note below. - -{{< include file="content/docs/how-to/send-messages/media-video-format.md" >}} - -#### Media - Convert Video - -{{< include file="content/docs/how-to/send-messages/media-video-convert.md" >}} - -### Send Voice Status - -```http request -POST /api/{session}/status/voice -``` - -{{< tabs "send-voice-status-body" >}} -{{< tab "URL" >}} -```json { title="Body" } -{ - "file": { - "mimetype": "audio/ogg; codecs=opus", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - }, - "backgroundColor": "#38b42f", - "convert": false -} -``` -{{< /tab >}} - -{{< tab "BASE64" >}} -```json { title="Body" } -{ - "file": { - "mimetype": "audio/ogg; codecs=opus", - "data": "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" - }, - "backgroundColor": "#38b42f" -} -``` -{{< /tab >}} -{{< /tabs >}} - -**Fields**: -- `file` - provide **one of** the fields: - - `url` - URL to the file - - `data` - Base 64 encoded binary content of the file -- `convert: false` - convert the file to the right format. **Default:** `false` - - Set `convert: true` if you don't have the right format, check the format note below. - -{{< include file="content/docs/how-to/send-messages/media-voice-format.md" >}} - -#### Media - Convert Voice -{{< include file="content/docs/how-to/send-messages/media-voice-convert.md" >}} - -### Delete Status -Here's how you can delete status message you previously sent. - -```http request -POST /api/{session}/status/delete -``` - -When you send status - you'll get the response like below, save `key.id` (it's message id). -```json { title="Response" } -{ - "key": { - "remoteJid": "status@broadcast", - "fromMe": true, - "id": "AAAAAAAAAAAAAAAAAAAAAA" // <===== key.id - }, - "message": { - ... - } -} -``` - -```json { title="Body" } -{ - "id": "AAAAAAAAAAAAAAAAAAAAAA" -} -``` - -It removes status from all contacts in the list. - -### Get New Status Message ID -Generates new message ID for status message. -You can use it in -[Send Status to 10K contacts](#send-status-to-10k-contacts-manually) -flow for manually sending status messages to big amount of contacts. - -```http request -GET /api/{session}/status/new-message-id -``` - -```json { title="Response" } -{ - "id": "AAAAAAAAAAAAAAAAAAAAAA" -} -``` - -After that you can set it when you send status messages: -```json { title="Body" } - -{ - "id": "AAAAAAAAAAAAAAAAAAAAAA", - "text": "Have a look! https://waha.devlike.pro/", - "contacts": ["first-chunk-of-contacts-here"], - ... -} -``` - -## How-to -### Get status messages - -You can use regular -[`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) -to fetch status messages. Set `chatId` to `status@broadcast` for that - -```http request -GET /api/default/chats/status%40broadcast/messages?downloadMedia=true&limit=100 -``` - -### Receive status messages - -If you wish to receive status messages in real-time - you can subscribe to the following -[**🔄 Events**]({{< relref "/docs/how-to/events" >}}) -: - -- [`message`]({{< relref "/docs/how-to/receive-messages#message" >}}) event for a message (send by someone else) -- [`message.any`]({{< relref "/docs/how-to/receive-messages#messageany" >}}) event for a message (including your messages) - -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "false_status@broadcast_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_123123@c.us", - "timestamp": 1667561485, - "body": "Check this out!", - "hasMedia": true, - "media": { - "url": "http://localhost:3000/api/files/false_status@broadcast_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_123123@c.us.jpg", - "mimetype": "image/jpeg", - "filename": null - } - } -} -``` - - -### Send Status to 10K Contacts Manually - -If you have a large contact list (e.g., **10,000 contacts or more**), different engines handle status messages differently. - -{{< callout context="note" icon="outline/info-circle" title="How Engines Send Status to Many Contacts" >}} - -- **WEBJS**: Handles the process internally, following the official WhatsApp Web behavior. It automatically chunks the contact list. -- **NOWEB**: Splits the contact list into chunks of **5,000 contacts** and sends status messages sequentially. - - When sending **image, voice, or video** status messages, **NOWEB re-uploads** the media for each chunk. -- **GOWS**: Also splits the contact list into chunks of **5,000 contacts**, sending them sequentially. - - For **image, voice, or video** status messages, **GOWS reuses** the uploaded media for each chunk (no re-uploads). - -Both **NOWEB** and **GOWS** use the same `message.id` for each chunk, allowing you to track "views" for status messages just like regular messages. - -{{< /callout >}} - -You might encounter errors when sending status messages to 10K contacts. - -If that happens, or if you'd like more control over the process, you can use the following manual flow to send the status message to your contacts in smaller chunks. - - -#### 1. Generate a New Message ID - -First, generate a new message ID. You’ll use this ID for all status messages in this batch. - -```http request -GET /api/{SESSION}/status/new-message-id -``` - -```json { title="Response" } -{ - "id": "AAAAAAAAAAAAAAAAAAAAAA" -} -``` - - -#### 2. Get Your Own ID - -To view your own status message on your device, retrieve your user ID: - -```http request -GET /api/{SESSION}/me -``` - -```json { title="Response" } -{ - "id": "11111111111@c.us", - ... -} -``` - - -#### 3. Get Your Contacts List - -You can either use your existing contact list from a CRM or database, or fetch all contacts from WhatsApp: - -```http request -GET /api/contacts/all?session={NAME} -``` - -```json {title="Response"} -[ - { - "id": "88888888888@c.us", - ... - }, - { - "id": "99999999999@c.us", - ... - } -] -``` - - -#### 4. Send the Status Message to Contacts - -Once you have your **Message ID**, **your own ID**, and the **contacts list**, you can start sending status messages in chunks. - -We recommend using smaller chunks (**256–512 contacts**) to make retries and error handling easier. - -If you set `contacts: null`, the system uses the default chunk size of **5,000 contacts**, which works well for most cases. - -{{< callout context="caution" icon="outline/alert-triangle" >}} -- Always use the same **Message ID** for all chunks. This allows you to track views consistently across all recipients. -- Include **your own ID** in the **first chunk**, so you can immediately view the status and receive the `message.ack` event. - {{< /callout >}} - -```http request -POST /api/{session}/status/text -``` - -```json { title="Body" } -{ - "id": "AAAAAAAAA", - "contacts": ["11111111111@c.us", "88888888888@c.us", "..."], - "text": "Check this out!" -} -``` - -Continue sending the status message to the next chunk until you’ve sent it to all contacts. - -If you encounter any errors, you can retry sending the message to the same chunk. - +--- +title: "🟢 Status" +description: "Status (aka Stories)" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 232 +slug: status +images: ["status.png"] +--- + +You can send statuses (aka stories) using HTTP API! + +
+{{< img lqip="21x webp q20" src="status.png" alt="WhatsApp Status" >}} +
+ +## Features + +Here's the list of features that are available by [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}): + +{{< include file="content/docs/how-to/status/features.md" >}} + +## API + +{{< callout context="note" icon="outline/info-circle" title="About contacts field" >}} +When you send status you can provide optional `contacts` field - list of contacts to send status to. + +- [**WEBJS**]({{< relref "/docs/how-to/engines#webjs" >}}) engine **doesn't suppport** `contacts` field. You can send status to all contacts (or configure white/black list in the app before). +- [**NOWEB**]({{< relref "/docs/how-to/engines#noweb" >}}) engine **supports** `contacts` field, you must [**🏭 Enable NOWEB Store before using these endpoints**]({{< relref "/docs/engines/NOWEB#store" >}}) +- [**GOWS**]({{< relref "/docs/how-to/engines#gows" >}}) engine **supports** `contacts` field. + +You can fetch your contacts using [**👤 Contacts API**]({{< relref "/docs/how-to/contacts#get-all-contacts" >}}). + +```json { title="Body" } +{ + "text": "Have a look! https://waha.devlike.pro/", + "contacts": ["123123@c.us", "3333@c.us"], + "backgroundColor": "#38b42f", + "font": 1 +} +``` + +{{< /callout >}} + +### Send Text Status + +Send status to **all** your contacts: + +```http request +POST /api/{session}/status/text +``` + +```json { title="Body" } +{ + "text": "Have a look! https://waha.devlike.pro/", + "backgroundColor": "#38b42f", + "font": 1 +} +``` + +- `text` - text to send as status. +- `font` - font type, experiment with values here to get different fonts. +- `backgroundColor` - background color of the status. +- `contacts` - array of contacts to send status to. + +Send status to specific contacts: + +```json { title="Body" } +{ + "text": "Have a look! https://waha.devlike.pro/", + "backgroundColor": "#38b42f", + "font": 1, + "contacts": ["55xxxxxxxxxxx@c.us", "55xxxxxxxxxxx@c.us"] +} +``` + +### Send Image Status + +```http request +POST /api/{session}/status/image +``` + +{{< tabs "send-image-status-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" + }, + "caption": "string" +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "image/jpeg", + "data": "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" + }, + "caption": "string" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +### Send Video Status + +```http request +POST /api/{session}/status/video +``` + +{{< tabs "send-video-status-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "video/mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "backgroundColor": "#38b42f" +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "video/mp4", + "filename": "video.mp4", + "data": "AAAAGGZ0eXBtcDQyAAAAAGlzb21tcDQyAAAHEW1vb3YAAABsbXZoZAAAAADgAUTa4AFE2gAAdTAAAHe6AAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAANzdHJhawAAAFx0a2hkAAAAA+ABRNrgAUTaAAAAAQAAAAAAAHVOAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAUAAAAC0AAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAB1TgAAA+kAAQAAAAAC621kaWEAAAAgbWRoZAAAAADgAUTa4AFE2gAAdTAAAHVOVcQAAAAAAF9oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAASVNPIE1lZGlhIGZpbGUgcHJvZHVjZWQgYnkgR29vZ2xlIEluYy4gQ3JlYXRlZCBvbjogMDIvMDIvMjAyMy4AAAACZG1pbmYAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAIkc3RibAAAAJhzdHNkAAAAAAAAAAEAAACIYXZjMQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAUAAtAASAAAAEgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj//wAAADJhdmNDAWQAH//hABtnZAAfrNEAUAW7AWoCAgKAAAH0gAB1MAeMGIkBAARo648sAAAAGHN0dHMAAAAAAAAAAQAAAB4AAAPpAAAAKHN0c2MAAAAAAAAAAgAAAAEAAAAOAAAAAQAAAAMAAAACAAAAAQAAABxzdGNvAAAAAAAAAAMAAAcxAAAq7wAAS24AAACMc3RzegAAAAAAAAAAAAAAHgAAA0kAAAAyAAAAJQAAACYAAAAmAAAAKQAAACUAAAAlAAAAJQAAACkAAAAlAAAAJQAAACUAAAApAAAAJAAAACQAAAAkAAAAJwAAACQAAAAkAAAAJQAAACYAAAAlAAAAJQAAACUAAAAmAAAAJQAAACUAAAAlAAAAKgAAABRzdHNzAAAAAAAAAAEAAAABAAAAiGN0dHMAAAAAAAAADwAAAAEAAAPpAAAAAQAAD6QAAAADAAAAAAAAAAEAAA+kAAAAAwAAAAAAAAABAAAPpAAAAAMAAAAAAAAAAQAAD6QAAAADAAAAAAAAAAEAAA+kAAAAAwAAAAAAAAABAAAPpAAAAAMAAAAAAAAAAQAAE40AAAAEAAAAAAAAABR2bWhkAAAAAQAAAAAAAAAAAAACuHRyYWsAAABcdGtoZAAAAAPgAUTa4AFE2gAAAAIAAAAAAAB3ugAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAlRtZGlhAAAAIG1kaGQAAAAA4AFE2uABRNoAAKxEAACwABXHAAAAAABfaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAElTTyBNZWRpYSBmaWxlIHByb2R1Y2VkIGJ5IEdvb2dsZSBJbmMuIENyZWF0ZWQgb246IDAyLzAyLzIwMjMuAAAAAc1taW5mAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABkXN0YmwAAABpc3RzZAAAAAAAAAABAAAAWW1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAACsRAAAAAAANWVzZHMAAAAAAycAAgAEH0AVAAAAAAAAAAAAAAAFEBIQAAAAAAAAAAAAAAAAAAAGAQIAAAAYc3R0cwAAAAAAAAABAAAALAAABAAAAAAoc3RzYwAAAAAAAAACAAAAAQAAABUAAAABAAAAAwAAAAIAAAABAAAAHHN0Y28AAAAAAAAAAwAADHYAACz0AABLvQAAAMRzdHN6AAAAAAAAAAAAAAAsAAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAF0AAABcwAAAXQAAAFzAAABdAAAAXMAAAAQc21oZAAAAAAAAAAAAAAAcnVkdGEAAABqbWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAA9aWxzdAAAABlnc3N0AAAAEWRhdGEAAAABAAAAADAAAAAcZ3N0ZAAAABRkYXRhAAAAAQAAAAAxMDY4AABHe21kYXQAAANFJbhABd/+9Y2vmWVRi0/fwl7Vp8FFIlFodBXWJ7AAAAMAAAMAAAMAAAMCb3w7b+xvu484N6S/wPJaC8sMAAADApIAAAxYAAEIAAAaIAAD7AAAqQAAIeAABmgAAcgAAHOAACMgAAnwAAPEAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAAzkv4VetcGPbngLXvkqeR7JxISR12BgR++cnsBM31J1hURZirB4HGwWvpFdPC289mAkjXLCSyIdvFR3dv6aHr0B82L8J9Xog23WabSqb8cO+rmTPXAgY7aaIpgPquTfAAAJQGERBcipJr4m65wx3o3poM4QuaQq1SlHkzKL3Tov43kRfCoIa5GVUZ6CE6rriYcm72C827hp2mDdqNx6fHB1jsnRsQxit03/N5XMsHAWWiLnLJlru6Fjs4nF8PgsKqHV100N02/K4Lui85ShIhYz0cYsI7cmrr9AQCKLf3rbXvAOQEK9iZ3ELwGrUemoiVtzbbFzFplif1tWr4bGWSBRmylGBomUYqlh1w2hY5WSz2e+e7EcHvZ3AoMWZIUkvohRPbA016vF3x1mlXVR5P1rFnPwA9O12c73pWqAnTtHi4IAABARcfYC/FQsIkx5nfpXAi1MP7Uyt1kxrRbxQyilN42vcIBU33ywVC0b3cmIpGpnrZ4Z8LXriYPNJkqXUN5+h61ktEcZ1ymfgp77JtlJItHJN+fuhrxPY8HucNaFPQrChl1Ud+EN4SuQWg4TvEUl5O7cM275b8BOxJtWfRMVkuL/A93UIq3SWPbsd9Dd06g+obkwgq9up6u9YZkWczBlwDmK5gitbPbKN4o1ZI7AAAOLsX06bPLKB01V+iAw3xjzslG/7US1WFR/CRaZZ5EIoPL0xOxVV/wmQeGC5YwF7JNsJLtWzbrAJl/y1td4SJ5Tw1iu0O1RsxzaEkmLjU/lPicm/sSMjMcK1Tw4SwcuwXwlCRbCcqWoNDNOJZK3+YBqxBc8XHcOrAAAJCIWAAAvoK4AAQw+gAAefAAAB/vwAAQwIAADMiAAA+XoAAZvgAAOJsAAK8cAAKXMAAKNgAANGgAAVBAAACTAAAFAAADAC5AAAIMAAAaMVdIAAAALiHiTIXf/eEAAAMAAAMAAAMAAAMCGogH7ip1N+0CWY7DPZHZwAAAAwAAAwAEHaAAAAAhAakHyLf/AAADAAADAAADAAADABkThmAAAAMAAAMAAxaIAAAAIgGpC8jX/wAAAwAAAwAAAwAAAwAVSr7ewAAAAwAAAwAHXcAAAAAiAakPyNf/AAADAAADAAADAAADABVKvt7AAAADAAADAAddwAAAACUh5IohV//8hAAAAwAAAwAAAwAAAwAEcKP8u5AAAAMAAAMAAQdwAAAAIQGpl8i3/wAAAwAAAwAAAwAAAwAZE4ZgAAADAAADAAMWiAAAACEBqZvIt/8AAAMAAAMAAAMAAAMAGROGYAAAAwAAAwADFogAAAAhAamfyLf/AAADAAADAAADAAADABkThmAAAAMAAAMAAxaIAAAAJSHmyiE3//pYAAADAAADAAADAAADAAi4gzWuQAAAAwAAAwADMiAAAAAhAaonyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIQGqK8iX/wAAAwAAAwAAAwAAAwAcp+fgAAADAAADAATdkAAAACEBqi/Il/8AAAMAAAMAAAMAAAMAHKfn4AAAAwAAAwAE3ZAAAAAlIekKIRf/+lgAAAMAAAMAAAMAAAMACLPP13NAAAADAAADAAO6YCEABQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" + }, + "backgroundColor": "#38b42f" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Fields**: + +- `file` - provide **one of** the fields: + - `url` - URL to the file + - `data` - Base 64 encoded binary content of the file +- `convert: false` - convert the file to the right format. **Default:** `false` + - Set `convert: true` if you don't have the right format, check the format note below. + +{{< include file="content/docs/how-to/send-messages/media-video-format.md" >}} + +#### Media - Convert Video + +{{< include file="content/docs/how-to/send-messages/media-video-convert.md" >}} + +### Send Voice Status + +```http request +POST /api/{session}/status/voice +``` + +{{< tabs "send-voice-status-body" >}} +{{< tab "URL" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "audio/ogg; codecs=opus", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + }, + "backgroundColor": "#38b42f", + "convert": false +} +``` + +{{< /tab >}} + +{{< tab "BASE64" >}} + +```json { title="Body" } +{ + "file": { + "mimetype": "audio/ogg; codecs=opus", + "data": "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" + }, + "backgroundColor": "#38b42f" +} +``` + +{{< /tab >}} +{{< /tabs >}} + +**Fields**: + +- `file` - provide **one of** the fields: + - `url` - URL to the file + - `data` - Base 64 encoded binary content of the file +- `convert: false` - convert the file to the right format. **Default:** `false` + - Set `convert: true` if you don't have the right format, check the format note below. + +{{< include file="content/docs/how-to/send-messages/media-voice-format.md" >}} + +#### Media - Convert Voice + +{{< include file="content/docs/how-to/send-messages/media-voice-convert.md" >}} + +### Delete Status + +Here's how you can delete status message you previously sent. + +```http request +POST /api/{session}/status/delete +``` + +When you send status - you'll get the response like below, save `key.id` (it's message id). + +```json { title="Response" } +{ + "key": { + "remoteJid": "status@broadcast", + "fromMe": true, + "id": "AAAAAAAAAAAAAAAAAAAAAA" // <===== key.id + }, + "message": { + ... + } +} +``` + +```json { title="Body" } +{ + "id": "AAAAAAAAAAAAAAAAAAAAAA" +} +``` + +It removes status from all contacts in the list. + +### Get New Status Message ID + +Generates new message ID for status message. +You can use it in +[Send Status to 10K contacts](#send-status-to-10k-contacts-manually) +flow for manually sending status messages to big amount of contacts. + +```http request +GET /api/{session}/status/new-message-id +``` + +```json { title="Response" } +{ + "id": "AAAAAAAAAAAAAAAAAAAAAA" +} +``` + +After that you can set it when you send status messages: + +```json { title="Body" } + +{ + "id": "AAAAAAAAAAAAAAAAAAAAAA", + "text": "Have a look! https://waha.devlike.pro/", + "contacts": ["first-chunk-of-contacts-here"], + ... +} +``` + +## How-to + +### Get status messages + +You can use regular +[`GET /api/{session}/chats/{chatId}/messages`]({{< relref "/docs/how-to/chats#get-messages-from-chat" >}}) +to fetch status messages. Set `chatId` to `status@broadcast` for that + +```http request +GET /api/default/chats/status%40broadcast/messages?downloadMedia=true&limit=100 +``` + +### Receive status messages + +If you wish to receive status messages in real-time - you can subscribe to the following +[**🔄 Events**]({{< relref "/docs/how-to/events" >}}) +: + +- [`message`]({{< relref "/docs/how-to/receive-messages#message" >}}) event for a message (send by someone else) +- [`message.any`]({{< relref "/docs/how-to/receive-messages#messageany" >}}) event for a message (including your messages) + +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "false_status@broadcast_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_123123@c.us", + "timestamp": 1667561485, + "body": "Check this out!", + "hasMedia": true, + "media": { + "url": "http://localhost:3000/api/files/false_status@broadcast_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_123123@c.us.jpg", + "mimetype": "image/jpeg", + "filename": null + } + } +} +``` + +### Send Status to 10K Contacts Manually + +If you have a large contact list (e.g., **10,000 contacts or more**), different engines handle status messages differently. + +{{< callout context="note" icon="outline/info-circle" title="How Engines Send Status to Many Contacts" >}} + +- **WEBJS**: Handles the process internally, following the official WhatsApp Web behavior. It automatically chunks the contact list. +- **NOWEB**: Splits the contact list into chunks of **5,000 contacts** and sends status messages sequentially. + - When sending **image, voice, or video** status messages, **NOWEB re-uploads** the media for each chunk. +- **GOWS**: Also splits the contact list into chunks of **5,000 contacts**, sending them sequentially. + - For **image, voice, or video** status messages, **GOWS reuses** the uploaded media for each chunk (no re-uploads). + +Both **NOWEB** and **GOWS** use the same `message.id` for each chunk, allowing you to track "views" for status messages just like regular messages. + +{{< /callout >}} + +You might encounter errors when sending status messages to 10K contacts. + +If that happens, or if you'd like more control over the process, you can use the following manual flow to send the status message to your contacts in smaller chunks. + +#### 1. Generate a New Message ID + +First, generate a new message ID. You’ll use this ID for all status messages in this batch. + +```http request +GET /api/{SESSION}/status/new-message-id +``` + +```json { title="Response" } +{ + "id": "AAAAAAAAAAAAAAAAAAAAAA" +} +``` + +#### 2. Get Your Own ID + +To view your own status message on your device, retrieve your user ID: + +```http request +GET /api/{SESSION}/me +``` + +```json { title="Response" } +{ + "id": "11111111111@c.us", + ... +} +``` + +#### 3. Get Your Contacts List + +You can either use your existing contact list from a CRM or database, or fetch all contacts from WhatsApp: + +```http request +GET /api/contacts/all?session={NAME} +``` + +```json {title="Response"} +[ + { + "id": "88888888888@c.us", + ... + }, + { + "id": "99999999999@c.us", + ... + } +] +``` + +#### 4. Send the Status Message to Contacts + +Once you have your **Message ID**, **your own ID**, and the **contacts list**, you can start sending status messages in chunks. + +We recommend using smaller chunks (**256–512 contacts**) to make retries and error handling easier. + +If you set `contacts: null`, the system uses the default chunk size of **5,000 contacts**, which works well for most cases. + +{{< callout context="caution" icon="outline/alert-triangle" >}} + +- Always use the same **Message ID** for all chunks. This allows you to track views consistently across all recipients. +- Include **your own ID** in the **first chunk**, so you can immediately view the status and receive the `message.ack` event. + {{< /callout >}} + +```http request +POST /api/{session}/status/text +``` + +```json { title="Body" } +{ + "id": "AAAAAAAAA", + "contacts": ["11111111111@c.us", "88888888888@c.us", "..."], + "text": "Check this out!" +} +``` + +Continue sending the status message to the next chunk until you’ve sent it to all contacts. + +If you encounter any errors, you can retry sending the message to the same chunk. diff --git a/content/docs/how-to/storages/docker-compose.md b/content/docs/how-to/storages/docker-compose.md index 249482855..2c3aeb0e0 100644 --- a/content/docs/how-to/storages/docker-compose.md +++ b/content/docs/how-to/storages/docker-compose.md @@ -1,10 +1,9 @@ -[//]: # () -{{< callout context="tip" icon="outline/info-circle" >}} -You can find complete - -docker-compose.yaml - -with all storages and other configurations and use it as the starting point for your project. -{{< /callout >}} - - +[//]: # + +{{< callout context="tip" icon="outline/info-circle" >}} +You can find complete + +docker-compose.yaml + +with all storages and other configurations and use it as the starting point for your project. +{{< /callout >}} diff --git a/content/docs/how-to/storages/features.md b/content/docs/how-to/storages/features.md index 3cddf1043..b0b83297d 100644 --- a/content/docs/how-to/storages/features.md +++ b/content/docs/how-to/storages/features.md @@ -1,14 +1,14 @@ -| Storage | WEBJS | NOWEB | GOWS | -|-----------------------------------|:-----:|:-----:|:----:| -| **Local** - **🖥️ Session** | ✔️ | ✔️ | ✔️ | -| **Local** - **🖼️ Media** | ✔️ | ✔️ | ✔️ | -| **PostgresSQL** - **🖥️ Session** | ➕ | ➕ | ➕ | -| **PostgresSQL** - **🖼️ Media** | ➕ | ➕ | ➕ | -| **S3** - **🖼️ Media** | ➕ | ➕ | ➕ | -| ~~MongoDB - 🖥️ Session~~ | ➕ | ➕ | ❌ | - -- **PostgreSQL**, **S3** and **MongoDB** storages are available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) -- **MongoDB is deprecated** and no new features will be added to it. -- Any **S3 Compatible** storage can be used, such as AWS S3, MinIO, DigitalOcean Spaces, etc. For in-house solutions, you can use [**MinIO**](https://min.io/). - ---- +| Storage | WEBJS | NOWEB | GOWS | +| -------------------------------- | :---: | :---: | :--: | +| **Local** - **🖥️ Session** | ✔️ | ✔️ | ✔️ | +| **Local** - **🖼️ Media** | ✔️ | ✔️ | ✔️ | +| **PostgresSQL** - **🖥️ Session** | ➕ | ➕ | ➕ | +| **PostgresSQL** - **🖼️ Media** | ➕ | ➕ | ➕ | +| **S3** - **🖼️ Media** | ➕ | ➕ | ➕ | +| ~~MongoDB - 🖥️ Session~~ | ➕ | ➕ | ❌ | + +- **PostgreSQL**, **S3** and **MongoDB** storages are available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) +- **MongoDB is deprecated** and no new features will be added to it. +- Any **S3 Compatible** storage can be used, such as AWS S3, MinIO, DigitalOcean Spaces, etc. For in-house solutions, you can use [**MinIO**](https://min.io/). + +--- diff --git a/content/docs/how-to/storages/index.md b/content/docs/how-to/storages/index.md index 18c57286b..7c7d5f948 100644 --- a/content/docs/how-to/storages/index.md +++ b/content/docs/how-to/storages/index.md @@ -1,387 +1,415 @@ ---- -title: "🗄️ Storages" -description: "Storages - where to save authentication and media files" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 700 -images: ["waha-storages.drawio.png"] -slug: storages ---- - -WAHA uses several **Storage** types. Below you can find a list of these storage options and how to configure them. - -1. [**🖥️ Session Storage**](#sessions) - 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 Storage**](#media) - store **the media files** (such as images, videos, and other files that are received from the WhatsApp instance) - -{{< imgo src="/images/waha/storages/waha-storages.drawio.png" >}} - -{{< include file="content/docs/how-to/storages/features.md" >}} - -{{< include file="content/docs/how-to/storages/docker-compose.md" >}} - -## Sessions Storage -**🖥️ Session Storage** is used to store **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 avoid scanning the QR code every time you launch WAHA, -you **MUST** connect the session storage to the container. - -For the session storage, you can use the following options: -1. [**Local**](#sessions---local) - the default option, stores the session data in the local storage using files. -2. [**PostgreSQL**](#sessions---postgresql) - stores the session data in the PostgreSQL database. -3. [**MongoDB**](#sessions---mongodb) - stores the session data in the MongoDB database. - -{{< include file="content/docs/how-to/storages/docker-compose.md" >}} - -### Sessions - Local -By default, the WAHA uses the **local storage (files)** to store the session data. - -{{< callout context="note" icon="outline/info-circle" >}} -It's a **well-tested solution** even for **production** with multiple sessions -{{< /callout >}} - -#### Quick Start -To use local storage with session persistence, you need to mount a volume to the `/app/.sessions` directory. Here are the common ways to do this: - -1. **Using Docker Run** (recommended for development): -```bash -docker run -v `pwd`/.sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus -``` - -2. **Using Docker Compose** (recommended for production): -```yaml -services: - waha: - image: devlikeapro/waha-plus - volumes: - - ./.sessions:/app/.sessions - ports: - - "127.0.0.1:3000:3000" -``` - -3. **Using Custom Directory** (if you need a specific location): -```bash -docker run -v /custom/path/to/sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus -``` - -#### Configuration Options -- `WAHA_LOCAL_STORE_BASE_DIR=/app/.sessions` - Override the base directory for local storage - - Useful for handling Azure "dot" restrictions {{< issue 597 >}} - - Default: `/app/.sessions` - -#### Directory Structure -The session data is organized in the following structure: -```sh -sessions/ -├── webjs/ # Engine-specific directory -│ ├── default/ # Session directory -│ │ └── ... # Session files -│ └── another-session/ # Another session -│ └── ... # Session files -│ -└── noweb/ # Another engine - └── default/ - └── ... -``` - -#### Health Check -[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) provides [health check endpoints]({{< relref "/docs/how-to/observability" >}}). - -### Sessions - PostgreSQL -If you want to use the PostgreSQL to store the session data, you need to set `WHATSAPP_SESSIONS_POSTGRESQL_URL` environment variable - -**Using Docker Run** -```sh -docker run \ - -e WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable \ - -p 3000:3000 \ - devlikeapro/waha-plus -``` - -**Using Docker Compose** -```yaml { title="docker-compose.yaml" } -services: - waha: - image: devlikeapro/waha-plus - ports: - - "127.0.0.1:3000:3000" - environment: - - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable - depends_on: - - postgres - - postgres: - image: postgres:17 - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=postgres - volumes: - - postgres_data:/var/lib/postgresql/data - command: - - postgres - - "-c" - - "max_connections=3000" - -volumes: - postgres_data: -``` - -{{< details "❓ I want to run >100 sessions on PostgreSQL | pg sorry, too many clients already" >}} -If you see the error: -> pg sorry, too many clients already - -Make sure to increase the `max_connections` in the `postgresql.conf` file or start it with the flag: -```bash -postgres -c max_connections=3000 -``` -{{< /details >}} - -{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} -👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. -{{< /callout >}} - -### Sessions - MongoDB -{{< callout context="danger" title="Deprecated" icon="outline/alert-square-rounded" >}} -**MongoDB** storage is **deprecated** and no new features will be added to it. - -👉 Use [**PostgresSQL**](#sessions---postgresql) -instead for new installations. -{{< /callout >}} - -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 the WAHA server** for the best performance and security reasons. - -{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} -👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. -{{< /callout >}} - -First, you need to start MongoDB server: -```bash -docker run -d -p 27017:27017 --name mongodb -v mongo-data:/data/db 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/waha-plus -``` - -That's all you need to do to use MongoDB storage. -All session authentication data will be automatically stored in the MongoDB database. - -For managing and troubleshooting MongoDB, we recommend using [MongoDB Compass](https://www.mongodb.com/products/tools/compass). - -![alt](waha-mongodb.png) - -#### Health Check -[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) provides [health check endpoints]({{< relref "/docs/how-to/observability" >}}). - -## Media Storage -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**](#media---local) - stores the media files in the local storage using files. -2. [**PostgreSQL**](#media---postgresql) - stores the media files in the PostgreSQL database. -3. [**S3**](#media---s3) - stores the media files in the S3 storage. - -### Media - Local -By default, WAHA stores media files in local storage with a **180-second lifetime**. - -To persist media files: - -```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 \ - devlikeapro/waha-plus -``` - -```yaml -services: - waha: - image: devlikeapro/waha-plus - volumes: - - ./.media:/app/.media - environment: - - WHATSAPP_FILES_FOLDER=/app/.media - - WHATSAPP_FILES_LIFETIME=0 - ports: - - "127.0.0.1:3000:3000" -``` - -### Media - PostgreSQL -You can store media files in PostgreSQL. - -It'll create additional `media` table in **each database for session**. - -{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} -👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. -{{< /callout >}} - -```bash -docker run \ - -e WAHA_MEDIA_STORAGE=POSTGRESQL \ - -e WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable \ - -p 3000:3000 \ - devlikeapro/waha-plus -``` - -```yaml -services: - waha: - image: devlikeapro/waha-plus - environment: - - WAHA_MEDIA_STORAGE=POSTGRESQL - - WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable - ports: - - "127.0.0.1:3000:3000" - depends_on: - - postgres - - postgres: - image: postgres:17 - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=postgres - volumes: - - postgres_data:/var/lib/postgresql/data - -volumes: - postgres_data: -``` - -### Media - S3 -To store media files in S3-compatible storage: - -```bash -docker run \ - -e WAHA_MEDIA_STORAGE=S3 \ - -e WAHA_S3_REGION=eu-west-1 \ - -e WAHA_S3_BUCKET=waha \ - -e WAHA_S3_ACCESS_KEY_ID=minioadmin \ - -e WAHA_S3_SECRET_ACCESS_KEY=minioadmin \ - -e WAHA_S3_ENDPOINT=http://127.0.0.1:9000 \ - -e WAHA_S3_FORCE_PATH_STYLE=True \ - -e WAHA_S3_PROXY_FILES=False \ - -p 3000:3000 \ - devlikeapro/waha-plus -``` - -```yaml -services: - waha: - image: devlikeapro/waha-plus - environment: - - WAHA_MEDIA_STORAGE=S3 - - WAHA_S3_REGION=eu-west-1 - - WAHA_S3_BUCKET=waha - - WAHA_S3_ACCESS_KEY_ID=minioadmin - - WAHA_S3_SECRET_ACCESS_KEY=minioadmin - - WAHA_S3_ENDPOINT=http://minio:9000 - - WAHA_S3_FORCE_PATH_STYLE=True - - WAHA_S3_PROXY_FILES=False - ports: - - "127.0.0.1:3000:3000" - depends_on: - - minio - - minio: - image: minio/minio - environment: - - MINIO_ROOT_USER=minioadmin - - MINIO_ROOT_PASSWORD=minioadmin - command: server /data --console-address ":9001" - volumes: - - minio_data:/data - ports: - - "9000:9000" - - "9001:9001" - -volumes: - minio_data: -``` - -**S3 metadata** for each file: -- `X-Amz-Meta-Waha-Session=default` - session name -- `X-Amz-Meta-Waha-Message-Id=true_111...` - message ID -- `X-Amz-Meta-Waha-Media-File-Name=media.jpg` - media file name - -## FAQ -### Database Schema -{{< callout context="caution" icon="outline/database" >}} -When using **PostgreSQL** or **MongoDB** storage, -WAHA creates **multiple databases** using the credentials provided in the connection URL: - -1. `waha_{engine}` - A **single database** with - - session configuration - - common parameters that persist until you remove a session -2. `waha_{engine}_{sessionname}` - A **separate database** for **each session** that contains: - - Credentials - - Messages - - Contacts - - Other session-specific data -{{< /callout >}} - -{{< callout context="note" title="Database Schemas" icon="outline/database" >}} -![PostgreSQL Databases](psql-databases.png) ![MongoDB Databases](mongodb-databases.png) -{{< /callout >}} - -This approach provides **several benefits**: -1. Easy monitoring of storage usage per session -2. Better stability when running multiple sessions -3. Isolation between sessions - if one session's database has issues, it won't affect other sessions -4. Clear separation of concerns between session configuration and session data - -{{< callout context="danger" title="User Permissions" icon="outline/user" >}} -Make sure that the user that connects to the database has **create/drop** permissions on the databases. -{{< /callout >}} - -### Multiple Workers - Single Database Server -{{< callout context="warning" icon="outline/alert-triangle" >}} -When running **multiple WAHA workers** with **the same database**, you **MUST** set a unique `WAHA_WORKER_ID` for each worker to prevent conflicts and ensure proper operation. -{{< /callout >}} - -Example configuration for multiple workers: - -```yaml -services: - waha-worker-1: - image: devlikeapro/waha-plus - environment: - - WAHA_WORKER_ID=worker-1 - - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable - ports: - - "127.0.0.1:3000:3000" - depends_on: - - postgres - - waha-worker-2: - image: devlikeapro/waha-plus - environment: - - WAHA_WORKER_ID=worker-2 - - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable - ports: - - "127.0.0.1:3001:3000" - depends_on: - - postgres - - postgres: - image: postgres:17 - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=postgres - volumes: - - postgres_data:/var/lib/postgresql/data - -volumes: - postgres_data: -``` +--- +title: "🗄️ Storages" +description: "Storages - where to save authentication and media files" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 700 +images: ["waha-storages.drawio.png"] +slug: storages +--- + +WAHA uses several **Storage** types. Below you can find a list of these storage options and how to configure them. + +1. [**🖥️ Session Storage**](#sessions) - 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 Storage**](#media) - store **the media files** (such as images, videos, and other files that are received from the WhatsApp instance) + +{{< imgo src="/images/waha/storages/waha-storages.drawio.png" >}} + +{{< include file="content/docs/how-to/storages/features.md" >}} + +{{< include file="content/docs/how-to/storages/docker-compose.md" >}} + +## Sessions Storage + +**🖥️ Session Storage** is used to store **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 avoid scanning the QR code every time you launch WAHA, +you **MUST** connect the session storage to the container. + +For the session storage, you can use the following options: + +1. [**Local**](#sessions---local) - the default option, stores the session data in the local storage using files. +2. [**PostgreSQL**](#sessions---postgresql) - stores the session data in the PostgreSQL database. +3. [**MongoDB**](#sessions---mongodb) - stores the session data in the MongoDB database. + +{{< include file="content/docs/how-to/storages/docker-compose.md" >}} + +### Sessions - Local + +By default, the WAHA uses the **local storage (files)** to store the session data. + +{{< callout context="note" icon="outline/info-circle" >}} +It's a **well-tested solution** even for **production** with multiple sessions +{{< /callout >}} + +#### Quick Start + +To use local storage with session persistence, you need to mount a volume to the `/app/.sessions` directory. Here are the common ways to do this: + +1. **Using Docker Run** (recommended for development): + +```bash +docker run -v `pwd`/.sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus +``` + +2. **Using Docker Compose** (recommended for production): + +```yaml +services: + waha: + image: devlikeapro/waha-plus + volumes: + - ./.sessions:/app/.sessions + ports: + - "127.0.0.1:3000:3000" +``` + +3. **Using Custom Directory** (if you need a specific location): + +```bash +docker run -v /custom/path/to/sessions:/app/.sessions -p 3000:3000 devlikeapro/waha-plus +``` + +#### Configuration Options + +- `WAHA_LOCAL_STORE_BASE_DIR=/app/.sessions` - Override the base directory for local storage + - Useful for handling Azure "dot" restrictions {{< issue 597 >}} + - Default: `/app/.sessions` + +#### Directory Structure + +The session data is organized in the following structure: + +```sh +sessions/ +├── webjs/ # Engine-specific directory +│ ├── default/ # Session directory +│ │ └── ... # Session files +│ └── another-session/ # Another session +│ └── ... # Session files +│ +└── noweb/ # Another engine + └── default/ + └── ... +``` + +#### Health Check + +[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) provides [health check endpoints]({{< relref "/docs/how-to/observability" >}}). + +### Sessions - PostgreSQL + +If you want to use the PostgreSQL to store the session data, you need to set `WHATSAPP_SESSIONS_POSTGRESQL_URL` environment variable + +**Using Docker Run** + +```sh +docker run \ + -e WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable \ + -p 3000:3000 \ + devlikeapro/waha-plus +``` + +**Using Docker Compose** + +```yaml { title="docker-compose.yaml" } +services: + waha: + image: devlikeapro/waha-plus + ports: + - "127.0.0.1:3000:3000" + environment: + - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable + depends_on: + - postgres + + postgres: + image: postgres:17 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - postgres_data:/var/lib/postgresql/data + command: + - postgres + - "-c" + - "max_connections=3000" + +volumes: + postgres_data: +``` + +{{< details "❓ I want to run >100 sessions on PostgreSQL | pg sorry, too many clients already" >}} +If you see the error: + +> pg sorry, too many clients already + +Make sure to increase the `max_connections` in the `postgresql.conf` file or start it with the flag: + +```bash +postgres -c max_connections=3000 +``` + +{{< /details >}} + +{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} +👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. +{{< /callout >}} + +### Sessions - MongoDB + +{{< callout context="danger" title="Deprecated" icon="outline/alert-square-rounded" >}} +**MongoDB** storage is **deprecated** and no new features will be added to it. + +👉 Use [**PostgresSQL**](#sessions---postgresql) +instead for new installations. +{{< /callout >}} + +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 the WAHA server** for the best performance and security reasons. + +{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} +👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. +{{< /callout >}} + +First, you need to start MongoDB server: + +```bash +docker run -d -p 27017:27017 --name mongodb -v mongo-data:/data/db 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/waha-plus +``` + +That's all you need to do to use MongoDB storage. +All session authentication data will be automatically stored in the MongoDB database. + +For managing and troubleshooting MongoDB, we recommend using [MongoDB Compass](https://www.mongodb.com/products/tools/compass). + +![alt](waha-mongodb.png) + +#### Health Check + +[**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) provides [health check endpoints]({{< relref "/docs/how-to/observability" >}}). + +## Media Storage + +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**](#media---local) - stores the media files in the local storage using files. +2. [**PostgreSQL**](#media---postgresql) - stores the media files in the PostgreSQL database. +3. [**S3**](#media---s3) - stores the media files in the S3 storage. + +### Media - Local + +By default, WAHA stores media files in local storage with a **180-second lifetime**. + +To persist media files: + +```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 \ + devlikeapro/waha-plus +``` + +```yaml +services: + waha: + image: devlikeapro/waha-plus + volumes: + - ./.media:/app/.media + environment: + - WHATSAPP_FILES_FOLDER=/app/.media + - WHATSAPP_FILES_LIFETIME=0 + ports: + - "127.0.0.1:3000:3000" +``` + +### Media - PostgreSQL + +You can store media files in PostgreSQL. + +It'll create additional `media` table in **each database for session**. + +{{< callout title="WAHA uses Multiple Databases schema" context="note" icon="outline/database" >}} +👉 Read how WAHA uses databases in the [**Database Schema**](#database-schema) section. +{{< /callout >}} + +```bash +docker run \ + -e WAHA_MEDIA_STORAGE=POSTGRESQL \ + -e WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable \ + -p 3000:3000 \ + devlikeapro/waha-plus +``` + +```yaml +services: + waha: + image: devlikeapro/waha-plus + environment: + - WAHA_MEDIA_STORAGE=POSTGRESQL + - WAHA_MEDIA_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable + ports: + - "127.0.0.1:3000:3000" + depends_on: + - postgres + + postgres: + image: postgres:17 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: +``` + +### Media - S3 + +To store media files in S3-compatible storage: + +```bash +docker run \ + -e WAHA_MEDIA_STORAGE=S3 \ + -e WAHA_S3_REGION=eu-west-1 \ + -e WAHA_S3_BUCKET=waha \ + -e WAHA_S3_ACCESS_KEY_ID=minioadmin \ + -e WAHA_S3_SECRET_ACCESS_KEY=minioadmin \ + -e WAHA_S3_ENDPOINT=http://127.0.0.1:9000 \ + -e WAHA_S3_FORCE_PATH_STYLE=True \ + -e WAHA_S3_PROXY_FILES=False \ + -p 3000:3000 \ + devlikeapro/waha-plus +``` + +```yaml +services: + waha: + image: devlikeapro/waha-plus + environment: + - WAHA_MEDIA_STORAGE=S3 + - WAHA_S3_REGION=eu-west-1 + - WAHA_S3_BUCKET=waha + - WAHA_S3_ACCESS_KEY_ID=minioadmin + - WAHA_S3_SECRET_ACCESS_KEY=minioadmin + - WAHA_S3_ENDPOINT=http://minio:9000 + - WAHA_S3_FORCE_PATH_STYLE=True + - WAHA_S3_PROXY_FILES=False + ports: + - "127.0.0.1:3000:3000" + depends_on: + - minio + + minio: + image: minio/minio + environment: + - MINIO_ROOT_USER=minioadmin + - MINIO_ROOT_PASSWORD=minioadmin + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + ports: + - "9000:9000" + - "9001:9001" + +volumes: + minio_data: +``` + +**S3 metadata** for each file: + +- `X-Amz-Meta-Waha-Session=default` - session name +- `X-Amz-Meta-Waha-Message-Id=true_111...` - message ID +- `X-Amz-Meta-Waha-Media-File-Name=media.jpg` - media file name + +## FAQ + +### Database Schema + +{{< callout context="caution" icon="outline/database" >}} +When using **PostgreSQL** or **MongoDB** storage, +WAHA creates **multiple databases** using the credentials provided in the connection URL: + +1. `waha_{engine}` - A **single database** with + - session configuration + - common parameters that persist until you remove a session +2. `waha_{engine}_{sessionname}` - A **separate database** for **each session** that contains: - Credentials - Messages - Contacts - Other session-specific data + {{< /callout >}} + +{{< callout context="note" title="Database Schemas" icon="outline/database" >}} +![PostgreSQL Databases](psql-databases.png) ![MongoDB Databases](mongodb-databases.png) +{{< /callout >}} + +This approach provides **several benefits**: + +1. Easy monitoring of storage usage per session +2. Better stability when running multiple sessions +3. Isolation between sessions - if one session's database has issues, it won't affect other sessions +4. Clear separation of concerns between session configuration and session data + +{{< callout context="danger" title="User Permissions" icon="outline/user" >}} +Make sure that the user that connects to the database has **create/drop** permissions on the databases. +{{< /callout >}} + +### Multiple Workers - Single Database Server + +{{< callout context="warning" icon="outline/alert-triangle" >}} +When running **multiple WAHA workers** with **the same database**, you **MUST** set a unique `WAHA_WORKER_ID` for each worker to prevent conflicts and ensure proper operation. +{{< /callout >}} + +Example configuration for multiple workers: + +```yaml +services: + waha-worker-1: + image: devlikeapro/waha-plus + environment: + - WAHA_WORKER_ID=worker-1 + - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable + ports: + - "127.0.0.1:3000:3000" + depends_on: + - postgres + + waha-worker-2: + image: devlikeapro/waha-plus + environment: + - WAHA_WORKER_ID=worker-2 + - WHATSAPP_SESSIONS_POSTGRESQL_URL=postgres://postgres:postgres@postgres:5432/postgres?sslmode=disable + ports: + - "127.0.0.1:3001:3000" + depends_on: + - postgres + + postgres: + image: postgres:17 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: +``` diff --git a/content/docs/how-to/swagger/index.md b/content/docs/how-to/swagger/index.md index 2d58299f8..2f3831870 100644 --- a/content/docs/how-to/swagger/index.md +++ b/content/docs/how-to/swagger/index.md @@ -1,65 +1,69 @@ ---- -title: "📚 Swagger (OpenAPI)" -description: "Swagger (OpenAPI) documentation" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 203 -images: ['swagger.png'] -slug: swagger ---- - -## Overview -The project provides HTTP API (REST), which is documented with OpenAPI specification and Swagger UI. - - - -You can see all available endpoints, request/response examples, and even execute them directly from the Swagger UI. - -Find the latest versions: -- [Swagger documentation ->](/swagger) -- [Postman ->](https://www.postman.com/devlikeapro/workspace/waha/collection/35390377-42210829-5a92-45c5-a001-6a453c5d764a?action=share&creator=35390377) -- [OpenAPI specification ->](/swagger/openapi.json) - -You can find Swagger documentation on the following url after you -[install and started]( {{< relref "/docs/how-to/install" >}}) it: -- Swagger: [http://localhost:3000](http://localhost:3000). -- OpenAPI: [http://localhost:3000/-json](http://localhost:3000/-json). - -## Configuration -- `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" >}}). - -### White label -You can show your own brand in the Swagger documentation. - - -
-
- -👉 Swagger White Label is available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version only. - -Use the following environment variables to customize the Swagger documentation: -- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. -- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. -- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. -- `WHATSAPP_SWAGGER_VIDEO_EXAMPLE_URL` - link to the video example `https://github.com/devlikeapro/waha/raw/core/examples/video.mp4` -- `WHATSAPP_SWAGGER_OPUS_EXAMPLE_URL` - link to the opus example `https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus` -- `WHATSAPP_SWAGGER_JPG_EXAMPLE_URL` - link to the jpg example `https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg` - -**Example** (consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml#L15-L38) or other methods to store these settings): -```bash -docker run -it -p 3000:3000 -e WHATSAPP_SWAGGER_TITLE="AwesomeCRM" -e 'WHATSAPP_SWAGGER_DESCRIPTION=

FantasticFindz - Discover unique treasures from around the world at unbelievable prices!
Read more about us!

' -e "WHATSAPP_SWAGGER_EXTERNAL_DOC_URL=https://google.com" devlikeapro/waha-plus -``` - - - +--- +title: "📚 Swagger (OpenAPI)" +description: "Swagger (OpenAPI) documentation" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 203 +images: ["swagger.png"] +slug: swagger +--- + +## Overview + +The project provides HTTP API (REST), which is documented with OpenAPI specification and Swagger UI. + + + +You can see all available endpoints, request/response examples, and even execute them directly from the Swagger UI. + +Find the latest versions: + +- [Swagger documentation ->](/swagger) +- [Postman ->](https://www.postman.com/devlikeapro/workspace/waha/collection/35390377-42210829-5a92-45c5-a001-6a453c5d764a?action=share&creator=35390377) +- [OpenAPI specification ->](/swagger/openapi.json) + +You can find Swagger documentation on the following url after you +[install and started]( {{< relref "/docs/how-to/install" >}}) it: + +- Swagger: [http://localhost:3000](http://localhost:3000). +- OpenAPI: [http://localhost:3000/-json](http://localhost:3000/-json). + +## Configuration + +- `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" >}}). + +### White label + +You can show your own brand in the Swagger documentation. + + +
+
+ +👉 Swagger White Label is available in [**WAHA Plus**]({{< relref "waha-plus#plus" >}}) version only. + +Use the following environment variables to customize the Swagger documentation: + +- `WHATSAPP_SWAGGER_TITLE` - the title of the Swagger documentation and some other places. +- `WHATSAPP_SWAGGER_DESCRIPTION` - Markdown formatted description of your API. +- `WHATSAPP_SWAGGER_EXTERNAL_DOC_URL` - URL to the external documentation. +- `WHATSAPP_SWAGGER_VIDEO_EXAMPLE_URL` - link to the video example `https://github.com/devlikeapro/waha/raw/core/examples/video.mp4` +- `WHATSAPP_SWAGGER_OPUS_EXAMPLE_URL` - link to the opus example `https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus` +- `WHATSAPP_SWAGGER_JPG_EXAMPLE_URL` - link to the jpg example `https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg` + +**Example** (consider using [docker-compose](https://github.com/devlikeapro/waha/blob/core/docker-compose.yaml#L15-L38) or other methods to store these settings): + +```bash +docker run -it -p 3000:3000 -e WHATSAPP_SWAGGER_TITLE="AwesomeCRM" -e 'WHATSAPP_SWAGGER_DESCRIPTION=

FantasticFindz - Discover unique treasures from around the world at unbelievable prices!
Read more about us!

' -e "WHATSAPP_SWAGGER_EXTERNAL_DOC_URL=https://google.com" devlikeapro/waha-plus +``` diff --git a/content/docs/how-to/waha-plus/index.md b/content/docs/how-to/waha-plus/index.md index df4c93719..31943ac36 100644 --- a/content/docs/how-to/waha-plus/index.md +++ b/content/docs/how-to/waha-plus/index.md @@ -1,81 +1,86 @@ ---- -title : "➕ WAHA Plus" -description: "WAHA Plus - advanced version with more features!" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 900 -images: [ "patron-portal.png"] -slug: waha-plus -aliases: - - /docs/how-to/plus-version ---- - -## Overview - -**WAHA** is distributed in two versions: - -1. Core the basic version that meet almost 80% people’s needs. 100% free and open source. -2. Plus the version with advanced messages, security, and reliability features. - -👉👉 Compare versions on -[**🎁 Support Us**](/support-us) -page - -## Tiers -You support the project and get WAHA Plus by donating to the project on one of the platforms. - -👉👉 See tiers and available platforms on -[**🎁 Support Us**](/support-us) - - -## Patron Portal -

- Patron Portal -
-
-

- -After subscribing on Patreon or Boosty, you will get access to the [WAHA Patron Portal ->](https://portal.devlike.pro/) -where you will get the password to download the Plus image and manage your perks! - -Read more about Patron Portal in -**Patreon -> ** -or -**Boosty ->** -posts. - -### 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/waha-plus -docker logout -``` - -Then in all commands use **Plus** image `devlikeapro/waha-plus` instead of Core `devlikeapro/waha`. - -### Invite Team -If you support the project with [**WAHA PRO**](/support-us#tier-pro) tier - invite **up to 5 members** to your team -to help you with developing the project! - -The members inherit **PRO** tier and will have their own docker key and GitHub access to the project. - - -![Portal - Your Team](portal-your-team.png) - -#### Invite Member -1. **Login** to [**Patron Portal**](https://portal.devlike.pro) -2. **Create Team** at the bottom the page -3. **Invite a new member** by sending invitation to their email - -#### Join Team -1. Get **email with invitation** -2. **Login** to [**Patron Portal**](https://portal.devlike.pro) -3. **Join** the team - -![alt](portal-join-team.png) - -_If **The Member** doesn't see **PRO** tier - kindly refresh the page after waiting 10-30 seconds (sync tiers takes a bit of time)_ +--- +title: "➕ WAHA Plus" +description: "WAHA Plus - advanced version with more features!" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 900 +images: ["patron-portal.png"] +slug: waha-plus +aliases: + - /docs/how-to/plus-version +--- + +## Overview + +**WAHA** is distributed in two versions: + +1. Core the basic version that meet almost 80% people’s needs. 100% free and open source. +2. Plus the version with advanced messages, security, and reliability features. + +👉👉 Compare versions on +[**🎁 Support Us**](/support-us) +page + +## Tiers + +You support the project and get WAHA Plus by donating to the project on one of the platforms. + +👉👉 See tiers and available platforms on +[**🎁 Support Us**](/support-us) + +## Patron Portal + +

+ Patron Portal +
+
+

+ +After subscribing on Patreon or Boosty, you will get access to the [WAHA Patron Portal ->](https://portal.devlike.pro/) +where you will get the password to download the Plus image and manage your perks! + +Read more about Patron Portal in +**Patreon -> ** +or +**Boosty ->** +posts. + +### 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/waha-plus +docker logout +``` + +Then in all commands use **Plus** image `devlikeapro/waha-plus` instead of Core `devlikeapro/waha`. + +### Invite Team + +If you support the project with [**WAHA PRO**](/support-us#tier-pro) tier - invite **up to 5 members** to your team +to help you with developing the project! + +The members inherit **PRO** tier and will have their own docker key and GitHub access to the project. + +![Portal - Your Team](portal-your-team.png) + +#### Invite Member + +1. **Login** to [**Patron Portal**](https://portal.devlike.pro) +2. **Create Team** at the bottom the page +3. **Invite a new member** by sending invitation to their email + +#### Join Team + +1. Get **email with invitation** +2. **Login** to [**Patron Portal**](https://portal.devlike.pro) +3. **Join** the team + +![alt](portal-join-team.png) + +_If **The Member** doesn't see **PRO** tier - kindly refresh the page after waiting 10-30 seconds (sync tiers takes a bit of time)_ diff --git a/content/docs/integrations/_index.md b/content/docs/integrations/_index.md index 7cf3d0ca0..88a23169f 100644 --- a/content/docs/integrations/_index.md +++ b/content/docs/integrations/_index.md @@ -1,15 +1,14 @@ ---- -title: "🔌 Integrations" -description: "Integrations with WAHA" -lead: "Integrations with WAHA" -date: 2020-10-06T08:49:15+00:00 -lastmod: 2020-10-06T08:49:15+00:00 -draft: false -weight: 900 -slug: integrations -sidebar: - collapsed: true ---- - -Different ways to integrate WAHA with other services. - +--- +title: "🔌 Integrations" +description: "Integrations with WAHA" +lead: "Integrations with WAHA" +date: 2020-10-06T08:49:15+00:00 +lastmod: 2020-10-06T08:49:15+00:00 +draft: false +weight: 900 +slug: integrations +sidebar: + collapsed: true +--- + +Different ways to integrate WAHA with other services. diff --git a/content/docs/integrations/about/index.md b/content/docs/integrations/about/index.md index 535bc8766..0cdc9a19b 100644 --- a/content/docs/integrations/about/index.md +++ b/content/docs/integrations/about/index.md @@ -1,19 +1,19 @@ ---- -title: "Integrations" -description: "Understanding WAHA Integrations" -lead: "Understanding WAHA Integrations" -date: 2024-07-13T12:00:00+00:00 -lastmod: 2024-07-13T12:00:00+00:00 -draft: false -weight: 901 -images: [] -toc: true -slug: about ---- - -[**🔌 Integrations**]({{< relref "/docs/integrations/about" >}}) -are **external ecosystem tools** that connect WAHA with other services. - -They include both WAHA Team-supported and community-created solutions. - -{{< include file="content/docs/apps/about/apps-vs-integrations.md" >}} +--- +title: "Integrations" +description: "Understanding WAHA Integrations" +lead: "Understanding WAHA Integrations" +date: 2024-07-13T12:00:00+00:00 +lastmod: 2024-07-13T12:00:00+00:00 +draft: false +weight: 901 +images: [] +toc: true +slug: about +--- + +[**🔌 Integrations**]({{< relref "/docs/integrations/about" >}}) +are **external ecosystem tools** that connect WAHA with other services. + +They include both WAHA Team-supported and community-created solutions. + +{{< include file="content/docs/apps/about/apps-vs-integrations.md" >}} diff --git a/content/docs/integrations/chatwoot/index.md b/content/docs/integrations/chatwoot/index.md index 1241ee76c..55b385699 100644 --- a/content/docs/integrations/chatwoot/index.md +++ b/content/docs/integrations/chatwoot/index.md @@ -1,36 +1,36 @@ ---- -title: "ChatWoot" -description: "WAHA ChatWoot Integration" -lead: "WAHA ChatWoot Integration" -date: 2024-09-05T08:49:31+00:00 -lastmod: 2024-09-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 903 -images: ["waha-chatwoot.png"] -toc: true ---- - -

- -

- -{{< callout context="tip" icon="outline/hand-finger-right" title="Use built-in ChatWoot App instead!" >}} -Consider using new -[**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! - -It's a new, a built-in connection from **WAHA/WhatsApp** to **ChatWoot**! -{{< /callout >}} - -To set up **WhatsApp ChatWoot** integration you'll need few things: -1. **WAHA** - installed self-hosted WhatsApp API - [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) -2. [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) - to create workflows -3. **ChatWoot** - either [self-hosted](https://www.chatwoot.com/docs/self-hosted) or [cloud](https://app.chatwoot.com/) version - 1. To use **ChatWoot Cloud** you need to make sure your **n8n** webhook is accessible from the internet -4. **PostgreSQL** - to store ChatWoot data (and WAHA-ChatWoot relations) - -👉 Check out [**WhatsApp + ChatWoot Templates**](https://waha-n8n-templates.devlike.pro/chatwoot/) -to start from the scratch and create your first **ChatWoot** integration! - +--- +title: "ChatWoot" +description: "WAHA ChatWoot Integration" +lead: "WAHA ChatWoot Integration" +date: 2024-09-05T08:49:31+00:00 +lastmod: 2024-09-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 903 +images: ["waha-chatwoot.png"] +toc: true +--- + +

+ +

+ +{{< callout context="tip" icon="outline/hand-finger-right" title="Use built-in ChatWoot App instead!" >}} +Consider using new +[**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}})! + +It's a new, a built-in connection from **WAHA/WhatsApp** to **ChatWoot**! +{{< /callout >}} + +To set up **WhatsApp ChatWoot** integration you'll need few things: + +1. **WAHA** - installed self-hosted WhatsApp API - [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) +2. [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) - to create workflows +3. **ChatWoot** - either [self-hosted](https://www.chatwoot.com/docs/self-hosted) or [cloud](https://app.chatwoot.com/) version + 1. To use **ChatWoot Cloud** you need to make sure your **n8n** webhook is accessible from the internet +4. **PostgreSQL** - to store ChatWoot data (and WAHA-ChatWoot relations) + +👉 Check out [**WhatsApp + ChatWoot Templates**](https://waha-n8n-templates.devlike.pro/chatwoot/) +to start from the scratch and create your first **ChatWoot** integration! diff --git a/content/docs/integrations/live-helper-chat/index.md b/content/docs/integrations/live-helper-chat/index.md index af73fd6c5..43f8f40b2 100644 --- a/content/docs/integrations/live-helper-chat/index.md +++ b/content/docs/integrations/live-helper-chat/index.md @@ -1,38 +1,36 @@ ---- -title: "Live Helper Chat" -description: "WhatsApp API + Live Helper Chat integration." -lead: "WhatsApp API + Live Helper Chat integration." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 909 -toc: true -images: ['logo.png'] ---- - - -
- - ![Logo](logo.png) - -
- -Open source -Live Helper Chat -> -system with mobile app, Bot, AI, Voice & Video & ScreenShare. - -
- -![Screenshot](screenshot.png) - -
- - -👉 Please checkout - -WhatsApp WAHA integration on Live Helper Chat -> - -documentation for more details how to integrate WhatsApp with Live Helper Chat. +--- +title: "Live Helper Chat" +description: "WhatsApp API + Live Helper Chat integration." +lead: "WhatsApp API + Live Helper Chat integration." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 909 +toc: true +images: ["logo.png"] +--- + +
+ +![Logo](logo.png) + +
+ +Open source +Live Helper Chat -> +system with mobile app, Bot, AI, Voice & Video & ScreenShare. + +
+ +![Screenshot](screenshot.png) + +
+ +👉 Please checkout + +WhatsApp WAHA integration on Live Helper Chat -> + +documentation for more details how to integrate WhatsApp with Live Helper Chat. diff --git a/content/docs/integrations/n8n/index.md b/content/docs/integrations/n8n/index.md index 1dc2ee4b7..40cf44624 100644 --- a/content/docs/integrations/n8n/index.md +++ b/content/docs/integrations/n8n/index.md @@ -1,96 +1,105 @@ ---- -title: "n8n" -description: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" -lead: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" -date: 2024-09-05T08:49:31+00:00 -lastmod: 2024-09-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 902 -toc: true -images: ['WAHA+n8n.png'] ---- - -

- -

- -## Overview - -{{< imgo src="/images/n8n/waha-n8n.png" >}} - -👉 You can follow -[**WAHA + n8n: No Code Low Code WhatsApp Automation Step-By-Step Guide**]({{< relref "/blog/waha-n8n" >}}) -to start **WAHA** and **n8n** from the scratch and start your first "echo" workflow! - -Alternatively, check the installation guides for **n8n** and **WAHA**: - -**WAHA**: - - [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) - - [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) - -**n8n**: - - [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) - -## Install WAHA n8n node -Go to your **n8n** => **Settings** => **Community nodes** and install: - -```sh -@devlikeapro/n8n-nodes-waha -``` - -If you need help with that, check the -[**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) - -## WAHA API Credentials - -Before using the node you need to add **WAHA API** credentials. - -Go to your n8n installation and create a new **WAHA API** credential: -{{< imgo src="/images/n8n/waha-n8n-credentials.png" >}} - -If it doesn't allow you to **Save** it (no save button) - just put **any string** in `Api Key` field, know issue :( - -## WAHA Actions -**@devlikeapro/n8n-nodes-waha** provides **WAHA Actions** with all available API calls that you can find -in the [WAHA API documentation](https://waha.devlike.pro/docs/how-to/) or [Swagger](https://waha.devlike.pro/swagger/). - -{{< imgo src="/images/n8n/waha-n8n-actions.png" >}} - -## WAHA Trigger -**@devlikeapro/n8n-nodes-waha** provides **WAHA Trigger** node, -which make it possible to trigger the workflow when the specific event happens in WAHA. - -{{< imgo src="/images/n8n/waha-n8n-WAHATrigger.png" >}} - -💡 **Remember to configure your WAHA Session** with proper **Webhook** with **WAHA trigger** -> **Webhook URL** and -the events you want to listen! - -{{< imgo src="/images/n8n/waha-n8n-WAHATrigger-url.png" >}} - -{{< imgo src="/images/n8n/waha-n8n-dashboard-session.png" >}} - -## Workflow Examples -👉 Check out -[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) -for workflow templates! - -{{< imgo src="/images/n8n/waha-n8n.png" >}} - -## Troubleshooting -If you're experiencing any issues or have a feature request, please check the below resources: -**WAHA**: -- [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) -- [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) -- [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) - -**n8n**: -- [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) -- [**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) -- [**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) - -If that doesn't help - kindly open an issue in the -[**devlikeapro/n8n-nodes-waha**](https://github.com/devlikeapro/n8n-nodes-waha/) -GitHub repository, we're happy to help you out! +--- +title: "n8n" +description: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" +lead: "Start developing your WhatsApp automation with using n8n and WAHA in pair!" +date: 2024-09-05T08:49:31+00:00 +lastmod: 2024-09-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 902 +toc: true +images: ["WAHA+n8n.png"] +--- + +

+ +

+ +## Overview + +{{< imgo src="/images/n8n/waha-n8n.png" >}} + +👉 You can follow +[**WAHA + n8n: No Code Low Code WhatsApp Automation Step-By-Step Guide**]({{< relref "/blog/waha-n8n" >}}) +to start **WAHA** and **n8n** from the scratch and start your first "echo" workflow! + +Alternatively, check the installation guides for **n8n** and **WAHA**: + +**WAHA**: + +- [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) +- [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) + +**n8n**: + +- [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) + +## Install WAHA n8n node + +Go to your **n8n** => **Settings** => **Community nodes** and install: + +```sh +@devlikeapro/n8n-nodes-waha +``` + +If you need help with that, check the +[**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) + +## WAHA API Credentials + +Before using the node you need to add **WAHA API** credentials. + +Go to your n8n installation and create a new **WAHA API** credential: +{{< imgo src="/images/n8n/waha-n8n-credentials.png" >}} + +If it doesn't allow you to **Save** it (no save button) - just put **any string** in `Api Key` field, know issue :( + +## WAHA Actions + +**@devlikeapro/n8n-nodes-waha** provides **WAHA Actions** with all available API calls that you can find +in the [WAHA API documentation](https://waha.devlike.pro/docs/how-to/) or [Swagger](https://waha.devlike.pro/swagger/). + +{{< imgo src="/images/n8n/waha-n8n-actions.png" >}} + +## WAHA Trigger + +**@devlikeapro/n8n-nodes-waha** provides **WAHA Trigger** node, +which make it possible to trigger the workflow when the specific event happens in WAHA. + +{{< imgo src="/images/n8n/waha-n8n-WAHATrigger.png" >}} + +💡 **Remember to configure your WAHA Session** with proper **Webhook** with **WAHA trigger** -> **Webhook URL** and +the events you want to listen! + +{{< imgo src="/images/n8n/waha-n8n-WAHATrigger-url.png" >}} + +{{< imgo src="/images/n8n/waha-n8n-dashboard-session.png" >}} + +## Workflow Examples + +👉 Check out +[**https://waha-n8n-workflows.devlike.pro**](http://waha-n8n-templates.devlike.pro/) +for workflow templates! + +{{< imgo src="/images/n8n/waha-n8n.png" >}} + +## Troubleshooting + +If you're experiencing any issues or have a feature request, please check the below resources: +**WAHA**: + +- [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) +- [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) +- [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) + +**n8n**: + +- [**Installation guide**](https://docs.n8n.io/hosting/installation/docker/#starting-n8n) +- [**Install community nodes**](https://docs.n8n.io/integrations/community-nodes/installation/gui-install/) +- [**Create credentials**](https://docs.n8n.io/credentials/add-edit-credentials/) + +If that doesn't help - kindly open an issue in the +[**devlikeapro/n8n-nodes-waha**](https://github.com/devlikeapro/n8n-nodes-waha/) +GitHub repository, we're happy to help you out! diff --git a/content/docs/integrations/typebot/index.md b/content/docs/integrations/typebot/index.md index 6ec4bfbc9..31cca702e 100644 --- a/content/docs/integrations/typebot/index.md +++ b/content/docs/integrations/typebot/index.md @@ -1,29 +1,29 @@ ---- -title: "Typebot" -description: "WAHA Typebot Integration" -lead: "WAHA Typebot Integration" -date: 2024-09-05T08:49:31+00:00 -lastmod: 2024-09-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 902 -images: ["waha+typebot.png"] -toc: true ---- - -

- -

- -To set up **WhatsApp Typebot** integration you'll need few things: -1. **WAHA** - installed self-hosted WhatsApp API - [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) -2. [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) - to create workflows -3. **Typebot** - either [self-hosted](https://docs.typebot.io/self-hosting/get-started) or [cloud](https://app.typebot.io/) version - 1. To use **Typebot Cloud** you need to make sure your **n8n** webhook is accessible from the internet -4. **PostgreSQL** - to store Typebot data (and WAHA-Typebot relations) - -👉 Check out [**WAHA + Typebot Template**](https://waha-n8n-templates.devlike.pro/whatsapp-typebot/) -to start from the scratch and create your first **Typebot** integration! - +--- +title: "Typebot" +description: "WAHA Typebot Integration" +lead: "WAHA Typebot Integration" +date: 2024-09-05T08:49:31+00:00 +lastmod: 2024-09-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 902 +images: ["waha+typebot.png"] +toc: true +--- + +

+ +

+ +To set up **WhatsApp Typebot** integration you'll need few things: + +1. **WAHA** - installed self-hosted WhatsApp API - [**⚡ Quick Start**]({{< relref "/docs/overview/quick-start" >}}) +2. [**🔌 n8n Integration**]({{< relref "/docs/integrations/n8n" >}}) - to create workflows +3. **Typebot** - either [self-hosted](https://docs.typebot.io/self-hosting/get-started) or [cloud](https://app.typebot.io/) version + 1. To use **Typebot Cloud** you need to make sure your **n8n** webhook is accessible from the internet +4. **PostgreSQL** - to store Typebot data (and WAHA-Typebot relations) + +👉 Check out [**WAHA + Typebot Template**](https://waha-n8n-templates.devlike.pro/whatsapp-typebot/) +to start from the scratch and create your first **Typebot** integration! diff --git a/content/docs/integrations/uptime-kuma/index.md b/content/docs/integrations/uptime-kuma/index.md index 4972192c6..cd5bd833f 100644 --- a/content/docs/integrations/uptime-kuma/index.md +++ b/content/docs/integrations/uptime-kuma/index.md @@ -1,50 +1,52 @@ ---- -title: "Uptime Kuma" -description: "Send notifications from Uptime Kuma to your WhatsApp!" -lead: "Send notifications from Uptime Kuma to your WhatsApp!" -date: 2024-09-05T08:49:31+00:00 -lastmod: 2024-09-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 980 -images: ["uptime-kuma.jpg"] -toc: true ---- - -
-{{< img lqip="21x webp q20" src="uptime-kuma.jpg" alt="Uptime Kuma + WhatsApp" >}} -
- -If you're using **self-hosted** -[**Uptime Kuma**](https://github.com/louislam/uptime-kuma) -you can use **self-hosted** -[**WAHA**](/) -to send notifications from Kuma to your WhatsApp! - -## Overview -Here's what you'll get: -
-{{< img lqip="21x webp q20" src="kuma-whatsapp-notifications.png" alt="Uptime Kuma + WhatsApp" >}} -
- - -## Setup -Go to **Kuma** -> **Settings** -> **Notifications** and find **WhatsApp (WAHA)** notification type. - -{{< callout context="note" icon="outline/info-circle" >}} -If you don't find it there - kindly update **Uptime Kuma** to the latest version or -try setting up it from -[Uptime Kuma](https://github.com/louislam/uptime-kuma) - -**WhatsApp (WAHA)** provider has been added in [this commit](https://github.com/louislam/uptime-kuma/commit/6f8f8f955f1d47016b43db62bf8757bb5b108abf). -{{< /callout >}} - -
-{{< img lqip="21x webp q20" src="kuma-setup.png" alt="Uptime Kuma + WhatsApp setup" >}} -
- -
- -Configure parameters and click **Test** to receive a test message. +--- +title: "Uptime Kuma" +description: "Send notifications from Uptime Kuma to your WhatsApp!" +lead: "Send notifications from Uptime Kuma to your WhatsApp!" +date: 2024-09-05T08:49:31+00:00 +lastmod: 2024-09-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 980 +images: ["uptime-kuma.jpg"] +toc: true +--- + +
+{{< img lqip="21x webp q20" src="uptime-kuma.jpg" alt="Uptime Kuma + WhatsApp" >}} +
+ +If you're using **self-hosted** +[**Uptime Kuma**](https://github.com/louislam/uptime-kuma) +you can use **self-hosted** +[**WAHA**](/) +to send notifications from Kuma to your WhatsApp! + +## Overview + +Here's what you'll get: + +
+{{< img lqip="21x webp q20" src="kuma-whatsapp-notifications.png" alt="Uptime Kuma + WhatsApp" >}} +
+ +## Setup + +Go to **Kuma** -> **Settings** -> **Notifications** and find **WhatsApp (WAHA)** notification type. + +{{< callout context="note" icon="outline/info-circle" >}} +If you don't find it there - kindly update **Uptime Kuma** to the latest version or +try setting up it from +[Uptime Kuma](https://github.com/louislam/uptime-kuma) + +**WhatsApp (WAHA)** provider has been added in [this commit](https://github.com/louislam/uptime-kuma/commit/6f8f8f955f1d47016b43db62bf8757bb5b108abf). +{{< /callout >}} + +
+{{< img lqip="21x webp q20" src="kuma-setup.png" alt="Uptime Kuma + WhatsApp setup" >}} +
+ +
+ +Configure parameters and click **Test** to receive a test message. diff --git a/content/docs/integrations/waha+csharp/index.md b/content/docs/integrations/waha+csharp/index.md index 1b28006e7..b951c80bd 100644 --- a/content/docs/integrations/waha+csharp/index.md +++ b/content/docs/integrations/waha+csharp/index.md @@ -1,48 +1,47 @@ ---- -title: "WAHA + C#" -description: "WAHA + C#" -lead: "WAHA + C# integration" -date: 2024-09-05T08:49:31+00:00 -lastmod: 2024-09-06T08:49:31+00:00 -draft: false -menu: -docs: -parent: "help" -weight: 990 -images: [ 'csharp.svg' ] -toc: true -slug: csharp ---- - -

- -

- -## waha-net library - -{{< callout context="caution" icon="outline/alert-triangle" >}} -It's **community-driven library**, so please check the code before using it. - -As alternative, you can use [built-in HTTP API](#using-built-in-http-api). -{{< /callout >}} - -Check out: - -{{< link-card -title="GitHub: waha-net/waha-net" -href="https://github.com/Waha-net/waha-net" -target="_blank">}} - -{{< link-card -title="GitHub: waha-net/waha-aspire-hosting" -href="https://github.com/Waha-net/waha-aspire-hosting" -target="_blank" >}} - -## Using Built-in HTTP API - -{{< include file="layouts/code/language/csharp/install-dependencies.md" >}} - -{{< include file="layouts/code/language/csharp/send-message.md" >}} - -{{< include file="layouts/code/language/csharp/receive-message.md" >}} - +--- +title: "WAHA + C#" +description: "WAHA + C#" +lead: "WAHA + C# integration" +date: 2024-09-05T08:49:31+00:00 +lastmod: 2024-09-06T08:49:31+00:00 +draft: false +menu: +docs: +parent: "help" +weight: 990 +images: ["csharp.svg"] +toc: true +slug: csharp +--- + +

+ +

+ +## waha-net library + +{{< callout context="caution" icon="outline/alert-triangle" >}} +It's **community-driven library**, so please check the code before using it. + +As alternative, you can use [built-in HTTP API](#using-built-in-http-api). +{{< /callout >}} + +Check out: + +{{< link-card +title="GitHub: waha-net/waha-net" +href="https://github.com/Waha-net/waha-net" +target="_blank">}} + +{{< link-card +title="GitHub: waha-net/waha-aspire-hosting" +href="https://github.com/Waha-net/waha-aspire-hosting" +target="_blank" >}} + +## Using Built-in HTTP API + +{{< include file="layouts/code/language/csharp/install-dependencies.md" >}} + +{{< include file="layouts/code/language/csharp/send-message.md" >}} + +{{< include file="layouts/code/language/csharp/receive-message.md" >}} diff --git a/content/docs/integrations/waha+go/index.md b/content/docs/integrations/waha+go/index.md index a2ebfa400..2ded50309 100644 --- a/content/docs/integrations/waha+go/index.md +++ b/content/docs/integrations/waha+go/index.md @@ -1,24 +1,23 @@ ---- -title: "WAHA + Go" -description: "WhatsApp API + Go examples." -lead: "WhatsApp API + Go examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: [] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: go ---- - -

- -

- -{{< include file="/layouts/code/language/go/install-dependencies.md" >}} -{{< include file="/layouts/code/language/go/send-message.md" >}} -{{< include file="/layouts/code/language/go/receive-message.md" >}} - +--- +title: "WAHA + Go" +description: "WhatsApp API + Go examples." +lead: "WhatsApp API + Go examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: [] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: go +--- + +

+ +

+ +{{< include file="/layouts/code/language/go/install-dependencies.md" >}} +{{< include file="/layouts/code/language/go/send-message.md" >}} +{{< include file="/layouts/code/language/go/receive-message.md" >}} diff --git a/content/docs/integrations/waha+java/index.md b/content/docs/integrations/waha+java/index.md index d2f97bbf3..5ca011f14 100644 --- a/content/docs/integrations/waha+java/index.md +++ b/content/docs/integrations/waha+java/index.md @@ -1,24 +1,23 @@ ---- -title: "WAHA + Java" -description: "WhatsApp API + Java examples." -lead: "WhatsApp API + Java examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: [] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: java ---- - -

- -

- -{{< include file="/layouts/code/language/java/install-dependencies.md" >}} -{{< include file="/layouts/code/language/java/send-message.md" >}} -{{< include file="/layouts/code/language/java/receive-message.md" >}} - +--- +title: "WAHA + Java" +description: "WhatsApp API + Java examples." +lead: "WhatsApp API + Java examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: [] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: java +--- + +

+ +

+ +{{< include file="/layouts/code/language/java/install-dependencies.md" >}} +{{< include file="/layouts/code/language/java/send-message.md" >}} +{{< include file="/layouts/code/language/java/receive-message.md" >}} diff --git a/content/docs/integrations/waha+js/index.md b/content/docs/integrations/waha+js/index.md index 2be9870fc..85bf170f7 100644 --- a/content/docs/integrations/waha+js/index.md +++ b/content/docs/integrations/waha+js/index.md @@ -1,25 +1,25 @@ ---- -title: "WAHA + JS/TS" -description: "WhatsApp API + Javascript/TypeScript examples." -lead: "WhatsApp API + Javascript/TypeScript examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: [] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: javascript ---- -WhatsApp API + JavaScript/TypeScript - -

- -

- -{{< include file="/layouts/code/language/javascript/install-dependencies.md" >}} -{{< include file="/layouts/code/language/javascript/send-message.md" >}} -{{< include file="/layouts/code/language/javascript/receive-message.md" >}} - +--- +title: "WAHA + JS/TS" +description: "WhatsApp API + Javascript/TypeScript examples." +lead: "WhatsApp API + Javascript/TypeScript examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: [] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: javascript +--- + +WhatsApp API + JavaScript/TypeScript + +

+ +

+ +{{< include file="/layouts/code/language/javascript/install-dependencies.md" >}} +{{< include file="/layouts/code/language/javascript/send-message.md" >}} +{{< include file="/layouts/code/language/javascript/receive-message.md" >}} diff --git a/content/docs/integrations/waha+kotlin/index.md b/content/docs/integrations/waha+kotlin/index.md index c018afc7b..c940d43b9 100644 --- a/content/docs/integrations/waha+kotlin/index.md +++ b/content/docs/integrations/waha+kotlin/index.md @@ -1,122 +1,122 @@ ---- -title: "WAHA + Kotlin" -description: "WhatsApp API + Kotlin examples." -lead: "WhatsApp API + Kotlin examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: ["kotlin-whatsapp.png"] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: kotlin ---- - -

- -

- -We've created a few examples on how to interact with WAHA WhatsApp API with Kotlin (ktor). - -You can find the examples in -[examples folder on GitHub with detailed instructions in README.md ->](https://github.com/devlikeapro/waha-kotlin) - -## Installation - -We assume that you have installed software: - -1. Kotlin + JVM -2. Docker - -### Download and start image - -First of all, you must run WhatsApp 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/): - -Download and start WhatsApp API docker container - -```bash -# Download the image -docker pull devlikeapro/waha -# Run the docker container -docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -#### Download image - ARM - -If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following -commands to download the image - - For Core version the command is - -```bash -# Download the image -docker pull devlikeapro/waha:arm -# Rename it, so you can use devlikeapro/waha image in other place -docker tag devlikeapro/waha:arm devlikeapro/waha -# Run the docker container -docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -### Start session and scan QR - -2. Open Swagger API in the browser http://localhost:3000/ -3. Start session and scan QR code in swagger - 1. Find `POST /api/session` 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 -{ - "chatId": "12132132130@c.us", - "text": "Hi there!", - "session": "default" -} -``` - -If you see **Hi there!** message then you're ready to run bots! - -## WhatsApp Echo Bot - -The WhatsApp Echo Bot is a sample ktor 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 -git clone https://github.com/devlikeapro/waha-kotlin.git - -# Build and run the app -./gradlew build -./gradlew 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! - -Send message to the WhatsApp (that you used to scan QR code) and it'll echo text -back to you! - - -## Using Built-in HTTP API -{{< include file="/layouts/code/language/kotlin/install-dependencies.md" >}} -{{< include file="/layouts/code/language/kotlin/send-message.md" >}} -{{< include file="/layouts/code/language/kotlin/receive-message.md" >}} +--- +title: "WAHA + Kotlin" +description: "WhatsApp API + Kotlin examples." +lead: "WhatsApp API + Kotlin examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: ["kotlin-whatsapp.png"] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: kotlin +--- + +

+ +

+ +We've created a few examples on how to interact with WAHA WhatsApp API with Kotlin (ktor). + +You can find the examples in +[examples folder on GitHub with detailed instructions in README.md ->](https://github.com/devlikeapro/waha-kotlin) + +## Installation + +We assume that you have installed software: + +1. Kotlin + JVM +2. Docker + +### Download and start image + +First of all, you must run WhatsApp 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/): + +Download and start WhatsApp API docker container + +```bash +# Download the image +docker pull devlikeapro/waha +# Run the docker container +docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +#### Download image - ARM + +If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following +commands to download the image + +For Core version the command is + +```bash +# Download the image +docker pull devlikeapro/waha:arm +# Rename it, so you can use devlikeapro/waha image in other place +docker tag devlikeapro/waha:arm devlikeapro/waha +# Run the docker container +docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +### Start session and scan QR + +2. Open Swagger API in the browser http://localhost:3000/ +3. Start session and scan QR code in swagger + 1. Find `POST /api/session` 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 +{ + "chatId": "12132132130@c.us", + "text": "Hi there!", + "session": "default" +} +``` + +If you see **Hi there!** message then you're ready to run bots! + +## WhatsApp Echo Bot + +The WhatsApp Echo Bot is a sample ktor 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 +git clone https://github.com/devlikeapro/waha-kotlin.git + +# Build and run the app +./gradlew build +./gradlew 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! + +Send message to the WhatsApp (that you used to scan QR code) and it'll echo text +back to you! + +## Using Built-in HTTP API + +{{< include file="/layouts/code/language/kotlin/install-dependencies.md" >}} +{{< include file="/layouts/code/language/kotlin/send-message.md" >}} +{{< include file="/layouts/code/language/kotlin/receive-message.md" >}} diff --git a/content/docs/integrations/waha+php/index.md b/content/docs/integrations/waha+php/index.md index eac46fe87..f48ff3056 100644 --- a/content/docs/integrations/waha+php/index.md +++ b/content/docs/integrations/waha+php/index.md @@ -1,24 +1,23 @@ ---- -title: "WAHA + PHP" -description: "WhatsApp API + PHP examples." -lead: "WhatsApp API + PHP examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: [] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: PHP ---- - -

- -

- -{{< include file="/layouts/code/language/php/install-dependencies.md" >}} -{{< include file="/layouts/code/language/php/send-message.md" >}} -{{< include file="/layouts/code/language/php/receive-message.md" >}} - +--- +title: "WAHA + PHP" +description: "WhatsApp API + PHP examples." +lead: "WhatsApp API + PHP examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: [] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: PHP +--- + +

+ +

+ +{{< include file="/layouts/code/language/php/install-dependencies.md" >}} +{{< include file="/layouts/code/language/php/send-message.md" >}} +{{< include file="/layouts/code/language/php/receive-message.md" >}} diff --git a/content/docs/integrations/waha+python/index.md b/content/docs/integrations/waha+python/index.md index d49360227..7c6c6147c 100644 --- a/content/docs/integrations/waha+python/index.md +++ b/content/docs/integrations/waha+python/index.md @@ -1,155 +1,156 @@ ---- -title: "WAHA + Python" -description: "WhatsApp API + Python examples." -lead: "WhatsApp API + Python examples." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false -images: ["python-whatsapp.png"] -menu: -docs: -parent: "help" -weight: 990 -toc: true -slug: python ---- - -

- -

- -We've created a few examples on how to interact with WAHA WhatsApp API with Python. - -You can find the examples in [examples folder on GitHub with detailed instructions in README.md ->](https://github.com/devlikeapro/waha/tree/core/examples/python) - -## Installation - -We assume that you have installed software: - -1. Python 3 -2. Docker - -### Download and start image - -First of all, you must run WhatsApp 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/): - -Download and start WhatsApp API docker container - -```bash -# Download the image -docker pull devlikeapro/waha -# Run the docker container -docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -#### Download image - ARM - -If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following -commands to download the image - - For Core version the command is - -```bash -# Download the image -docker pull devlikeapro/waha:arm -# Rename it, so you can use devlikeapro/waha image in other place -docker tag devlikeapro/waha:arm devlikeapro/waha -# Run the docker container -docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -### Start session and scan QR - -2. Open Swagger API in the browser http://localhost:3000/ -3. Start session and scan QR code in swagger - 1. Find `POST /api/sessions` 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 -{ - "chatId": "12132132130@c.us", - "text": "Hi there!", - "session": "default" -} -``` - -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. - -```bash -# Clone the git repository with example -git clone https://github.com/devlikeapro/waha.git -# Open python example folder -cd waha/examples/python -# Install requirements -python -mpip install -r requirements.txt -# Run the bot -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! - -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 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/waha-plus/). - -Download **WAHA Plus** version: - -```bash -# Download the image -docker pull devlikeapro/waha-plus -# Run the docker container -docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha-plus -``` - -Run the WhatsApp Download Files bot: - -```bash -# Clone the git repository with example -git clone https://github.com/devlikeapro/waha.git -# Open python example folder -cd waha/examples/python -# Install requirements -python -mpip install -r requirements.txt -# Run the bot -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! - -## Using Built-in HTTP API -{{< include file="/layouts/code/language/python/install-dependencies.md" >}} -{{< include file="/layouts/code/language/python/send-message.md" >}} -{{< include file="/layouts/code/language/python/receive-message.md" >}} +--- +title: "WAHA + Python" +description: "WhatsApp API + Python examples." +lead: "WhatsApp API + Python examples." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false +images: ["python-whatsapp.png"] +menu: +docs: +parent: "help" +weight: 990 +toc: true +slug: python +--- + +

+ +

+ +We've created a few examples on how to interact with WAHA WhatsApp API with Python. + +You can find the examples in [examples folder on GitHub with detailed instructions in README.md ->](https://github.com/devlikeapro/waha/tree/core/examples/python) + +## Installation + +We assume that you have installed software: + +1. Python 3 +2. Docker + +### Download and start image + +First of all, you must run WhatsApp 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/): + +Download and start WhatsApp API docker container + +```bash +# Download the image +docker pull devlikeapro/waha +# Run the docker container +docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +#### Download image - ARM + +If you're using ARM (like Apple Silicon, Apple M1, etc.) - use following +commands to download the image + +For Core version the command is + +```bash +# Download the image +docker pull devlikeapro/waha:arm +# Rename it, so you can use devlikeapro/waha image in other place +docker tag devlikeapro/waha:arm devlikeapro/waha +# Run the docker container +docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +### Start session and scan QR + +2. Open Swagger API in the browser http://localhost:3000/ +3. Start session and scan QR code in swagger + 1. Find `POST /api/sessions` 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 +{ + "chatId": "12132132130@c.us", + "text": "Hi there!", + "session": "default" +} +``` + +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. + +```bash +# Clone the git repository with example +git clone https://github.com/devlikeapro/waha.git +# Open python example folder +cd waha/examples/python +# Install requirements +python -mpip install -r requirements.txt +# Run the bot +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! + +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 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/waha-plus/). + +Download **WAHA Plus** version: + +```bash +# Download the image +docker pull devlikeapro/waha-plus +# Run the docker container +docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha-plus +``` + +Run the WhatsApp Download Files bot: + +```bash +# Clone the git repository with example +git clone https://github.com/devlikeapro/waha.git +# Open python example folder +cd waha/examples/python +# Install requirements +python -mpip install -r requirements.txt +# Run the bot +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! + +## Using Built-in HTTP API + +{{< include file="/layouts/code/language/python/install-dependencies.md" >}} +{{< include file="/layouts/code/language/python/send-message.md" >}} +{{< include file="/layouts/code/language/python/receive-message.md" >}} diff --git a/content/docs/overview/_index.md b/content/docs/overview/_index.md index c9dbe086a..fef0f1f2e 100644 --- a/content/docs/overview/_index.md +++ b/content/docs/overview/_index.md @@ -1,16 +1,16 @@ ---- -title : "📄 Overview" -description: "WAHA - WhatsApp API" -lead: "" -date: 2020-10-06T08:48:45+00:00 -lastmod: 2020-10-06T08:48:45+00:00 -draft: false -weight: 100 -slug: overview -sidebar: - collapsed: true ---- - -Overview of the **WAHA** - WhatsApp API. - -What is it, how to use it, and what you can do with it. +--- +title: "📄 Overview" +description: "WAHA - WhatsApp API" +lead: "" +date: 2020-10-06T08:48:45+00:00 +lastmod: 2020-10-06T08:48:45+00:00 +draft: false +weight: 100 +slug: overview +sidebar: + collapsed: true +--- + +Overview of the **WAHA** - WhatsApp API. + +What is it, how to use it, and what you can do with it. diff --git a/content/docs/overview/changelog.md b/content/docs/overview/changelog.md index 6355187d0..571e3b1b1 100644 --- a/content/docs/overview/changelog.md +++ b/content/docs/overview/changelog.md @@ -1,1157 +1,1283 @@ ---- -title: "🆕 Changelog" -description: "WAHA's changelog" -lead: "You can find here the list of changes made to WAHA." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false - -menu: - docs: - parent: "help" -weight: 199 -toc: true ---- - - -## Get Notified -If you wish to get **Monthly Summary** about WAHA changes, subscribe to our channels. - -{{< callout context="tip" title="You can subscribe on free tier!" icon="outline/rss" >}} -- [**Patreon ->**](https://patreon.com/wa_http_api) -- [**Boosty ->**](https://boosty.to/wa-http-api) -{{< /callout >}} - -If you wish to get **Real-Time Email** about new changes, -you can **Watch Releases** in [**🐙 WAHA GitHub**](https://github.com/devlikeapro/waha) - -{{< details "💡 GitHub - How To Subscribe" >}} - -Go to [https://github.com/devlikeapro/waha](https://github.com/devlikeapro/waha), click **Watch - Custom**: -{{< imgo src="/images/github/github-watch.png" full="false" >}} - -Select **Releases**, click **Apply**: -{{< imgo src="/images/github/github-watch-releases.png" full="false" >}} - -You will get notifications about new releases in associated email! - -{{< /details >}} -## Releases -Latest Version: - -GitHub Release - - -{{< callout context="note" icon="outline/info-circle" >}} -Check the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) page to learn how to update WAHA. -{{< /callout >}} - -### 2025.8 - -🛠️ **Fixes** - -- `2025.8.1` - **WEBJS** - fix create group - {{< issue 1145 >}} -- `2025.8.1` - **NOWEB** - fix channel list - {{< issue 1177 >}} -- `2025.8.1` - limited characters in the session name - {{< issue 1163 >}} - -### 2025.7 -**🆕 NEW** - -- `2025.7.11` - Add languages (i18n) on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) -- `2025.7.8` - Add [**👤 Update Contact API**]({{< relref "/docs/how-to/contacts#update-contact" >}}) - {{< issue 1124 >}} - - **WEBJS**, **GOWS**, **NOWEB** -- `2025.7.5` - Add [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) - {{< issue 441 >}} -- `2025.7.2` - **WEBJS** - Add `GET /api/server/debug/browser/trace` API to [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - {{< issue 1092 >}} -- `2025.7.2` - **WEBJS** - `--a-waha-session` and `--a-waha-timestamp` to chrome/chromium args - {{< issue 1092 >}} - -**🧩 Apps**: -- `2025.7.11` - **ChatWoot** - fix @lid issue - find first by chat id -- `2025.7.11` - **ChatWoot** - add **Udru** language -- `2025.7.8` - **ChatWoot** - send `png` as image, not as attachment -- `2025.7.5` - Add [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) - {{< issue 441 >}} - -🛠️ **Fixes** -- `2025.7.11` - **WEBJS** - Fix "You provided 'null' where a stream was expected" - {{< issue 1178 >}} -- `2025.7.10` - **GOWS** - speed up sending a message to groups - {{< issue 1100 >}} -- `2025.7.10` - **NOWEB** - do not freeze server in a lot of sessions case (use regular `sqlite3`) -- `2025.7.9` - **WEBJS** - add `WAHA_RUN_XVFB=False` parameter - {{< issue 1151 >}} -- `2025.7.9` - adjust `UV_THREADPOOL_SIZE` values (`cpu*2` or min is `4`) -- `2025.7.7` - **WEBJS** - add browser cache - {{< issue 1131 >}}, {{< issue 1140 >}} -- `2025.7.6` - **WEBJS** - fix **send seen** and **send read messages** - {{< issue 1117 >}} -- `2025.7.5` - **WEBJS** - ignore old reactions on connection - {{< issue 494 >}} -- `2025.7.5` - **WEBJS** - increase rendering processes to 2 -- `2025.7.4` - **NOWEB** - handle [**👤 Lids**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) on first message - - {{< issue 1073 >}}, {{< issue 1097 >}} -- `2025.7.4` - **NOWEB** - fix some connection issues - - {{< issue 531 >}}, {{< issue 1098 >}} -- `2025.7.4` - **WEBJS** - increase `protocolTimeout` to 300s - {{< issue 1103 >}} -- `2025.7.4` - **WEBJS** - fix some `STARTING => FAILED` sessions - {{< issue 1071 >}} -- `2025.7.4` - **GOWS** - Fix [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) to 10K contacts - {{< issue 1058 >}} -- `2025.7.3` - **GOWS** - fix generating preview links youtu.be -- `2025.7.3` - **GOWS** - fix fetching media for some messages -- `2025.7.3` - **GOWS** - reconnect on session start if any network error happens -- `2025.7.3` - **GOWS** - fix stuck in `STARTING` - - {{< issue 1043 >}}, {{< issue 1068 >}}, {{< issue 1094 >}} -- `2025.7.3` - **WEBJS** - disable GPU -- `2025.7.2` - **WEBJS** - limit renderer process to **1** - {{< issue 1092 >}} -- `2025.7.2` - remove healthcheck and `ping-check.sh` script - {{< issue 1085 >}} -- `2025.7.1` - move `HEALTHCHECK` from Dockerfile to docker-compose - {{< issue 1090 >}} - -**⚙️ Updates** -- `2025.7.9` - **NOWEB** - up proto to `v1025126393` -- `2025.7.4` - **NOWEB** - up engine to `2025-07-04` -- `2025.7.3` - **GOWS** - up engine and proto to `v1024307498` - -### 2025.6 -**🆕 NEW** -- `2025.6.5` - [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) now available in **WAHA Core** - {{< issue 1069 >}} -- `2025.6.5` - Support hash in Api Key variable `WAHA_API_KEY=sha512:{HASH}` in [**🔒 API Key Security**]({{< relref "/docs/how-to/security" >}}) - {{< issue 1069 >}} -- `2025.6.3` - Add `message.edited` to [**🔄 Events**]({{< relref "/docs/how-to/events#messageedited" >}}) - {{< issue 916 >}}, {{< issue 1041 >}} - - **WEBJS**, **GOWS**, **NOWEB** - - ⚠️ **NOWEB** - removed an edited **protocol message** from `message` and `message.any`, now listen `message.edited` instead -- `2025.6.3` - **GOWS** Add `message.revoked` to [**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}) - {{< issue 917 >}} -- `2025.6.3` - Add `revokedMessageId` field to `message.revoked` to [**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}) -- `2025.6.2` - Add `convert: true` flag (`false` by default) to `/api/sendVoice` and `/api/sendVideo` - {{< issue 724 >}} -- `2025.6.2` - Add API to convert voice and video files before sending it - {{< issue 724 >}} - - [**POST /api/{session}/media/convert/voice**]({{< relref "/docs/how-to/send-messages#media---convert-voice" >}}) - - [**POST /api/{session}/media/convert/video**]({{< relref "/docs/how-to/send-messages#media---convert-video" >}}) - - No more `ffmpeg` required, just use `convert: true` or convert API! - -🛠️ **Fixes** -- `2025.6.7` - fix `curl: command not found` in healthcheck - {{< issue 1085 >}} - - `:noweb` and `:gows` docker images -- `2025.6.6` - **NOWEB** - show poll on the sender device - {{< issue 988 >}} -- `2025.6.6` - **WEBJS** - return message response - {{< issue 1083 >}} -- `2025.6.6` - **WEBJS** - fix pin message - {{< issue 1081 >}}, {{< issue 1082 >}} -- `2025.6.6` - **WEBJS** - fix zombie processes - {{< issue 1078 >}} -- `2025.6.6` - Return `501 Not Implemented` if engine does not support API - {{< issue 1047 >}} -- `2025.6.4` - **NOWEB** - fix *continuous loop of state synchronization* - {{< issue 1054 >}} -- `2025.6.3` - Add `timeout` for `AsyncLock` to prevent long queues - - **NOWEB** - has a lot of it - - **WEBJS**, **GOWS** - some API for session management -- `2025.6.3` - **WEBJS** - add `Xvfb` to container {{< issue 1032 >}} -- `2025.6.2` - **WEBJS** - fix disconnection issues {{< issue 1032 >}} -- `2025.6.1` - **GOWS** - fix memory leak {{< issue 919 >}} -- `2025.6.1` - **WEBJS** - fix [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) management issues - - {{< issue 1023 >}}, {{< issue 1024 >}}, {{< issue 1025 >}}, {{< issue 1026 >}}, {{< issue 1027 >}} - -**⚙️ Updates** -- `2025.6.2` - **WEBJS** - update chrome, puppeter -- `2025.6.1` - **GOWS** - up engine to **2025.06.09** version -- `2025.6.1` - **WEBJS** - up engine to **2025.06.09** version - -### 2025.5 -**🆕 NEW** -- `2025.5.5` - **WEBJS** - [**✅ Presence**]({{}}) API and Events - {{< issue 636 >}} -- `2025.5.5` - **GOWS** - [**📶 Polls**]({{< relref "docs/how-to/polls" >}}) support - {{< issue 899 >}} -- `2025.5.5` - Filter chats by `ids` in [**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API - {{< issue 791 >}} -- `2025.5.4` - Add [**👤 Contacts - Lids API**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) to map `@lid` to `@c.us` - {{< issue 957 >}} - - **WEBJS**, **NOWEB**, **GOWS** -- `2025.5.4` - **GOWS** - [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support - {{< issue 922 >}} -- `2025.5.4` - **GOWS** - add `POST /api/sendContactVcard` support - {{< issue 902 >}} - -🛠️ **Fixes** -- `2025.5.6` - Fix fetch media from S3/PostgreSQL - {{< issue 1007 >}} -- `2025.5.5` - Subscribe [**✅ Presence**]({{}}) on each request - - **WEBJS**, **NOWEB**, **GOWS** -- `2025.5.5` - **WEBJS** - hide "Fresh Look" modal form {{< issue 987 >}} -- `2025.5.5` - **WEBJS** - add `tini` to docker to handle zombie processes {{< issue 990 >}} -- `2025.5.5` - **Local Storage** - fix empty session name issues when calling logout or delete -- `2025.5.5` - fix pairing Business Accounts connected to official Meta API - {{< issue 864 >}} - - **NOWEB**, **GOWS** -- `2025.5.4` - **PostgreSQL** - use `5432` port by default if not provided {{< issue 975 >}} -- `2025.5.4` - **NOWEB** - fix "async-lock timed out in queue" error on session actions {{< issue 831 >}} -- `2025.5.3` - **NOWEB** - fix `poll.vote` event - {{< issue 960 >}} -- `2025.5.2` - **GOWS** - fix pairing Business Accounts connected to official Meta API - {{< issue 864 >}} -- `2025.5.2` - **NOWEB** - fix pairing via code {{< issue 961 >}} -- `2025.5.2` - **GOWS** and **NOWEB** - fix "undefined senderKeyDistributionMessage" error -- `2025.5.2` - protect **PostgreSQL** media with an API key -- `2025.5.2` - minor security update -- `2025.5.1` - **NOWEB** - fix syncing for accounts with many messages/contacts - {{< issue 952 >}} - - [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}): **Local**, **PostgreSQL**, **MongoDB** -- `2025.5.1` - **NOWEB** - no duplicate `message.ack` for a single message - {{< issue 948 >}} -- `2025.5.1` - **WEBJS** - fix potential connection leak to storages - {{< issue 952 >}} -- `2025.5.1` - **WEBJS** - fix adding/removing participant to group - {{< issue 944 >}} -- `2025.5.1` - **WEBJS** - fix sorting groups in `/chats` and `/chats/overview` - {{< issue 915 >}} - -**⚙️ Updates** -- `2025.5.5` - update nestjs - fixes `DeprecationWarning: The 'util.isObject' API is deprecated` - -### 2025.4 -`2025.4.2` - -**🆕 NEW** -- Add [**💬 Chats - Read messages**]({{< relref "/docs/how-to/chats#read-messages" >}}) API to mark unread messages as read {{< issue 783>}} - - **WEBJS**, **NOWEB**, **GOWS** -- Add `filter.ack` to [**💬 Chats - Get messages**]({{< relref "/docs/how-to/chats#get-messages" >}}) API - - **WEBJS**, **NOWEB**, **GOWS** -- **WEBJS** - add `message.ack` events for [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) and [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) messages - - {{< issue 495 >}}, {{< issue 900 >}} -- **WEBJS** - add `message._data.receipts` in [**💬 Chats** - **Get message by id**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) and [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) - - It shows all receipts (ack status) for the message - - {{< issue 495 >}}, {{< issue 900 >}} -- Read multiple messages by using `messageIds` in [**POST /api/sendSeen**]({{< relref "/docs/how-to/send-messages#send-seen" >}}) API - - **NOWEB**, **GOWS** - -🛠️ **Fixes** -- **NOWEB** - update message status on `/api/sendSeen` - {{< issue 635 >}} -- **NOWEB** - fix "Cannot read properties of undefined (reading 'protocolMessage')" - {{< issue 932 >}} -- **WEBJS** - restart browser on **ProtocolError** and **Promise was collected** - - {{< issue 244 >}}, {{< issue 714 >}}, {{< issue 685 >}}, {{< issue 936 >}} -- **NOWEB** - Fix `ack` for new messages (it was `UNKNOWN`, now it's `DEVICE`) -- **GOWS** - send `DEVICE` `message.ack` for all groups participants -- Fix **sending** messages to **anonymous groups** (one with `@lid` participants) - - **NOWEB** - - **GOWS** -- Fix **receiving** messages to **groups** and **status** (some messages were missed) - - **NOWEB** - - **GOWS** - -**⚙️ Updates** - -- **NOWEB** - update engine to the latest version -- **GOWS** - update engine to the latest version -- **WEBJS** - update - - **puppeter** (all images) - - **chrome** (`devlikeapro/waha-plus:chrome`and `devlikeapro/waha:chrome` images) - ---- - -`2025.4.1` -- Fix Send Reaction to [**📢 Channels**]({{< relref "/docs/how-to/channels#send-reaction-to-the-channel" >}}) - {{< issue 889 >}} - - **GOWS**, **NOWEB** -- [**📤 Send Link Custom Preview**]({{< relref "/docs/how-to/send-messages#send-link-custom-preview" >}}) - {{< issue 880 >}}, {{< issue 596 >}} - - **GOWS**, **NOWEB** -- **GOWS** - fix Send Reaction to other participants messages {{< issue 894 >}} - ---- - -### 2025.3 -`2025.3.3` -- **GOWS** - fix timeout on chat overview - {{< issue 881 >}}, {{< issue 878 >}} -- **NOWEB** - cache presence data for 1 minute - -`2025.3.2` -- Add [**📤 Button Reply**]({{< relref "/docs/how-to/send-messages#send-buttons-reply" >}}) API - {{< issue 848 >}} - - **WEBJS** -- Add features for [**🔄 Global Webhooks**]({{< relref "/docs/how-to/events#global-webhooks" >}}) - {{< issue 855 >}} - - **GOWS**, **NOWEB**, **WEBJS** - - Set HMAC using `WHATSAPP_HOOK_HMAC_KEY` environment variable - - Set retries using `WHATSAPP_HOOK_RETRIES_*` environment variables - - Set custom headers using `WHATSAPP_HOOK_CUSTOM_HEADERS` environment variables -- **GOWS** - Fix Get Contact `The "original" argument must be of type function` - {{< issue 866 >}} -- **NOWEB** - fix out of memory when session stuck in `STARTING` statuses - - {{< issue 821 >}}, {{< issue 860 >}}, {{< issue 869 >}} -- **NOWEB** - mark session as `FAILED` if QR code is not scanned in the interval. -- **NOWEB** - presences optimizations - store presence for 1 hour and fetch new if not accessed -- Handle sending [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) to 50K contacts - {{< issue 858 >}} - - **GOWS**, **NOWEB** -- Add [**🟢 Status - Get New Status Message ID**]({{< relref "/docs/how-to/status" >}}) - {{< issue 858 >}} - - **GOWS**, **NOWEB** - - You can use it in [**Send Status to 10K contacts**]({{< relref "/docs/how-to/status#send-status-to-10k-contacts-manually" >}}) flow -- Add searches by Name and Phone Number to [**📊Dashboard**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) -- **GOWS** - extract `replyTo` - {{< issue 876 >}} - - -`2025.3.1` -- **GOWS** multiple improvements - - Enable Link Previews - {{< issue 763 >}} - - Delete Status Message - {{< issue 754 >}} - - Delete Message - {{< issue 796 >}} - - Edit Message - {{< issue 797 >}} - - Reply To Message - {{< issue 799 >}} - - Add `filename` on `/api/sendFile` - {{< issue 853 >}} -- `linkPreviewHighQuality: true` for [**📤 Send messages - Link Preview**]({{< relref "/docs/how-to/send-messages#link-preview" >}}) - - **GOWS**, **NOWEB** -- Add `event.timestamp` to [**🔄 Events**]({{< relref "/docs/how-to/events" >}}) - {{< issue 755 >}} -- **NOWEB** - Filter [**📞 Calls**]({{< relref "/docs/how-to/calls" >}}) from `message` event - {{< issue 840 >}} -- Support **disappearing messages** in [**📤 Send messages**]({{< relref "/docs/how-to/send-messages" >}}) - {{< issue 736 >}} - - **GOWS**, **NOWEB**, **WEBJS** - - Might require repairing (logout/scan qr) for old chats -- Add `source: api|app` in [**🔄 Events** - message.any]({{< relref "/docs/how-to/events#messageany" >}}) - {{< issue 787 >}} -- Add [**👥 Groups Count API**]({{< relref "/docs/how-to/groups#get-groups-count" >}}) - {{< issue 752 >}} - - **GOWS**, **NOWEB**, **WEBJS** - -### 2025.2 -`2025.2.8` -- **WEBJS** - fix empty channels {{< issue 832 >}} -- Edit message `linkPreview` {{< issue 833 >}} - -`2025.2.7` -- Add [**👥 Group Picture API**]({{< relref "/docs/how-to/groups#group-picture" >}}) - {{< issue 802 >}} - - **WEBJS**, **NOWEB**, **GOWS** - - Picture Update available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) -- **GOWS** - Add [**👥 Group API**]({{< relref "/docs/how-to/groups" >}}) - {{< issue 825 >}} -- **NOWEB** - Add [**👥 Group Settings API**]({{< relref "/docs/how-to/groups" >}}) - {{< issue 695 >}}, {{< issue 808 >}} -- Add `exclude=participants` to [**👥 Get All Groups API**]({{< relref "/docs/how-to/groups#get-all-groups" >}}) - {{< issue 242 >}} - - **WEBJS**, **NOWEB**, **GOWS** -- **NOWEB** - fix `TypeError: group.participants is not iterable` - {{< issue 810 >}} -- **NOWEB** - disable auto-restart every 30 mins, restart will happen only on socket error - {{< issue 756 >}} - -`2025.2.6` -- **NOWEB** + **PostgreSQL** - fix `\u0000 - unsupported Unicode escape sequence` - {{< issue 820 >}} - -`2025.2.5` -- **NOWEB** - fix `body: null` or empty `body` in some cases - {{< issue 813 >}} -- **NOWEB** - add `message.revoked` event - -`2025.2.4` -- Add [**👥 group.v2 events**]({{< relref "/docs/how-to/groups#events" >}}) - - `group.v2.join` - when you join a group - - `group.v2.leave` - when you leave a group - - `group.v2.participants` - when someone joins, leaves, get promoted or demoted in a group - - `group.v2.update` - when group information are updated - - **WEBJS**, **NOWEB**, **GOWS** engines - - {{< issue 583 >}}, {{< issue 527 >}}, {{< issue 404 >}} -- **NOWEB** - catch and log unhandled errors {{< issue 809 >}} - -`2025.2.3` -- Add [**🆔 Profile API**]({{< relref "/docs/how-to/profile" >}} ) to get and update profile information {{< issue 529 >}} - - **WEBJS**, **NOWEB**, **GOWS** engines -- Fix `hasMedia` behaviour - now when you request messages with `downloadMedia=False`, `hasMedia: true` if message has media - - **WEBJS**, **NOWEB**, **GOWS** engines - -`2025.2.2` -- [**📢 Search Public Channels**]({{< relref "/docs/how-to/channels#search-channels-by-view" >}}) API - {{< issue 440 >}} - - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) -- [**📢 Get Messages (Preview) From Public Channels**]({{< relref "/docs/how-to/channels##get-messages-from-channel-preview" >}}) API - - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) -- **PostgreSQL** - fix `sorry, too many clients already` in some cases - - **WEBJS**, **NOWEB**, **GOWS** engines -- **S3** - fix `headers[headerName].trim is not a function` error {{< issue 790 >}} - -`2025.2.1` -- **GOWS** - [**👤 Contacts**]({{< relref "/docs/how-to/contacts" >}}) API -- **GOWS** - [**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API -- **GOWS** - [**💬 Chats - Get Messages**]({{< relref "/docs/how-to/chats#get-messages" >}}) API -- **NOWEB** - fix group message error {{< issue 765 >}}, {{< issue 766 >}} -- **GOWS** - fix group message error {{< issue 765 >}}, {{< issue 766 >}} - -### 2025.1 -[**Release Notes**]({{< relref "/blog/waha-2025-1" >}}) - -`2025.1.6` -- **WEBJS** - fix send image/video to [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) - {{< issue 733 >}} - -`2025.1.5` -- **GOWS** - add [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) API -- **GOWS** - add [**🟢 Status (aka Stories) API**]({{< relref "/docs/how-to/status" >}}) API -- **GOWS** - add [**Check Contact exists**]({{< relref "/docs/how-to/contacts" >}}) API - -`2025.1.4` -- [**🖥️ Session Storage - PostgresSQL**]({{< relref "/docs/how-to/storages#sessions---postgresql" >}}) - add support for storing sessions in PostgreSQL - - Available in all [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}})! -- [**🖼️ Media Storage - PostgresSQL**]({{< relref "/docs/how-to/storages#media---postgresql" >}}) - add support for storing media files in PostgreSQL - - Available in all [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}})! -- [**🗄️ Local Storage**]({{< relref "/docs/how-to/storages" >}}) available in **WAHA Core** now - {{< issue 741 >}} - - Both **🖥️ Session** and **🖼️ Media** storages -- **S3**, **PostgreSQL** - add `chat-id` metadata {{< issue 717 >}} -- **WEBJS** - remove unnecessary flags for chrome/chromium process to increase stability - - {{< issue 685 >}}, {{< issue 714 >}} - -`2025.1.3` -- **GOWS** - add [**🏭 GOWS Engine**]({{< relref "/docs/how-to/engines#gows" >}}) beta version (does not support many features yet) -- Lazy QR code png generation (300+ sessions performance issue) -- Shutdown HTTP server gracefully - -`2025.1.2` -- **NOWEB** - fix corrupted sessions {{< issue 731 >}} -- Use atomic write for files (**NOWEB** + media files) - -`2025.1.1` -- **NOWEB** - do not save empty creds into file when session stops {{< issue 727 >}} -- **NOWEB** + **MongoDB** - add descending order for messages -- Some timeout fixes - -### 2024.12 - -[**Release Notes**]({{< relref "/blog/waha-2024-12" >}}) - -`2024.12.6` -- Add [**💬 Get chats overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) - - **WEBJS**, **NOWEB** - - {{< issue 566 >}} - - {{< issue 573 >}} - - {{< issue 701 >}} -- Add [**📊 Chat UI to Dashboard**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) - -as an example for [**💬 Get chats overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) -- Add [**💬 Get chat picture API**]({{< relref "/docs/how-to/chats#get-chat-picture" >}}) -- Add `refresh` flag to **Get chat picture** and **Get contact picture** API -- Cache profile picture for 24 hours -- **WEBJS** - fix "Could not get the quoted message" error when replying to a message - {{< issue 576 >}} -- **NOWEB** - Fix `not-authorized` on get profile picture {{< issue 381 >}} - -`2024.12.5` -- **NOWEB** - attempt #3 to fix missing messages {{< issue 671 >}} - -`2024.12.4` -- Add [**👥 Join Group API**]({{< relref "/docs/how-to/groups#join-group" >}}) - {{< issue 688 >}} - -`2024.12.3` -- **NOWEB** - use **NOWEB** engine by default in [devlikeapro/waha-plus:noweb]({{< relref "/docs/how-to/engines#docker-images" >}}) - {{< issue 414 >}} -- **NOWEB** - fix `rate-overlimit` error on groups API {{< issue 462 >}} -- Add pagination to [**👥 Get Groups API**]({{< relref "/docs/how-to/groups#get-all-groups" >}}) -- Add [**👥 Refresh Groups API**]({{< relref "/docs/how-to/groups#refresh-groups" >}}) - -`2024.12.2` -- **NOWEB** - attempt #2 to fix missing messages {{< issue 671 >}} - -`2024.12.1` -- **WEBJS** - fix get channel info by id {{< issue 682 >}} -- **WEBJS** - fix channel messages {{< issue 683 >}} - -### 2024.11 -`2024.11.11` -- **NOWEB** - fix 403 on media message {{< issue 667 >}} -- **WEBJS** - fix channels list and message {{< issue 664 >}} - -`2024.11.10` -- **WEBJS** - fix empty groups and participants {{< issue 670 >}} {{< issue 674 >}} - -`2024.11.9` -- **NOWEB** - attempt to fix missing messages {{< issue 671 >}} - -`2024.11.8` -- **WEBJS** - Fix QR code (set `WAHA_WEBJS_CACHE_TYPE=none` by default) - {{< issue 659 >}} - -`2024.11.7` -- **WEBJS** - Add `WAHA_WEBJS_CACHE_TYPE=none` - ability to disable cache for `WEBJS` engine {{< issue 653 >}}, {{< issue 654 >}} - - [**⚙️ Configuration - WEBJS**]({{< relref "/docs/how-to/config#webjs" >}}) - -`2024.11.6` -- Fix **WAHA Core** version {{< issue 645 >}} - -`2024.11.5` -- Add [**📊 Dashboard - Event Monitor**]({{< relref "dashboard#event-monitor" >}}) - observe your events in real-time! -- All [**🔄 Webhooks**]({{< relref "events#webhooks" >}}) features in **WAHA Core** version now: Retries, HMAC, Custom Headers! -- [**🔄 Websockets**]({{< relref "events#websockets" >}}) supports all events now {{< issue 535 >}} -- [**💬 Chats** - **Pin, Unpin message**]({{< relref "/docs/how-to/chats#pin-message" >}}) {{< issue 613>}} - - **WEBJS**, **NOWEB** -- **NOWEB** - fix `me.pushName` after authentication {{< issue 409 >}} -- Add `engine.event` for debug and troubleshooting - -`2024.11.4` -- **NOWEB** - fix many contacts send status issues {{< issue 390 >}}, {{< issue 413 >}} -- **NOWEB** - `contacts` list for [**🟢 Status (aka Stories) API**]({{< relref "docs/how-to/status" >}}) is not required anymore -- **WEBJS** - fix **HTTP ERROR 429** {{}} - -`2024.11.3` -- add `linkPreview` flag in `POST /api/sendText` to disable generating preview for links {{< issue 596 >}}, {{< issue 598 >}} -- Fix "Sqlite: attempt to write to read only database" error {{< issue 628 >}} -- Fix `POST /api/sendVideo` - "TargetCloseError: Protocol error" {{< issue 629 >}} - -`2024.11.2` -- **WEBJS** - fix cases when it stops receiving events (message, message.ack, etc) - -`2024.11.1` -- Create, Update and Delete [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) - {{< issue 607 >}} - - **WEBJS**, **NOWEB** -- **WEBJS** - Add [**🟢 Status (aka Stories) API**]({{< relref "docs/how-to/status" >}}) - - **NOWEB** related issues: {{< issue 390 >}}, {{< issue 413 >}}. You can **WEBJS** for now to handle such cases for now. -- **NOWEB** + **MongoDB** - fix double message issue - {{< issue 623 >}} - - -### 2024.10 -`2024.10.13` -- **NOWEB** - fix waves issue on voice message {{< issue 621 >}} -- Fix `GET /api/messages` limit {{< issue 620 >}} - -`2024.10.12` -- **WEBJS** - fix `FAILED` session (remove `--single-process`) - -`2024.10.11` -- **WEBJS** + **MongoDB** - Fix `SingletonLock: File exists` error on launch - -`2024.10.10` -- **WEBJS** - Update puppeter and Chrome version -- **WEBJS** - Set window size to 1280x720 -- **WEBJS** - Fix `SingletonLock: File exists` error on launch - -`2024.10.9` -- Add pagination and filters to [**💬 Chats** - **Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages" >}}) - - **WEBJS** can return messages by a single chat - - **NOWEB** can return messages by a chat or `chatId=all` - - {{< issue 140 >}}, {{< issue 449 >}}, {{< issue 458 >}} -- Add [**💬 Chats** - **Get message by id**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) - - `GET /api/{session}/chats/{chatId}/messages/{messageId}` - - {{< issue 159 >}}, {{< issue 484 >}} -- Add [**💬 Chats** - Pagination]({{< relref "/docs/how-to/chats#pagination" >}}) - - {{< issue 371 >}} -- Add [**👤 Contacts** - Pagination]({{< relref "/docs/how-to/contacts#pagination" >}}) - - {{< issue 371 >}} -- Add [**💬 Chats** - Unread Chat]({{< relref "/docs/how-to/chats#unread-chat" >}}) - - `POST /api/{session}/chats/{chatId}/unread` - - **WEBJS**, **NOWEB** - - {{< issue 498 >}} -- **NOWEB** - Fix `/archive` and `/unarchive` chats - [**💬 Chats** - Archive Chat]({{< relref "/docs/how-to/chats#archive-chat" >}}) - - {{< issue 445 >}} -- Remove the device from **Connected Devices** on [**🖥️ Session Logout**]({{< relref "/docs/how-to/sessions#logout-session" >}}) - - **WEBJS**, **NOWEB** - - {{< issue 148 >}}, {{< issue 327 >}}, {{< issue 194 >}}, {{< issue 211 >}} - -`2024.10.8` -- Add `WAHA_LOCAL_STORE_BASE_DIR` to allow overriding the base directory for local storage [#597](https://github.com/devlikeapro/waha/issues/597) - -`2024.10.7` -- **WAHA Core** - fix webhooks issue [#595](https://github.com/devlikeapro/waha/issues/595) - -`2024.10.6` -- **WEBJS** + **MongoDB** - reduce CPU usage - -`2024.10.5` -- Add **Send Buttons** API `POST /api/sendButtons` - [$544](https://github.com/devlikeapro/waha/issues/544) - - [**📤 Send messages** - Send Buttons]({{}}) - - **NOWEB** -- Add **forward message** API `POST /api/forwardMessage` - [#158](https://github.com/devlikeapro/waha/issues/158) - - [**📤 Send messages** - Forward Message]({{}}) - - **WEBJS**, **NOWEB** -- Fix sessions stuck in `STARTING` on container restart - [#586](https://github.com/devlikeapro/waha/issues/586) -- Add `WAHA_AUTO_START_DELAY_SECONDS=0` environment variable so you can control the delay between sessions - - [**⚙️ Configuration** - Sessions]({{}}) -- Track session status and do not restart it - [#491](https://github.com/devlikeapro/waha/issues/491) -- Add workers environment variables: `WAHA_WORKER_ID`, `WAHA_WORKER_RESTART_SESSIONS` -- Add request id in webhooks headers and logs [#580](https://github.com/devlikeapro/waha/issues/580) - - [**🔄 Webhooks** - Headers]({{< relref "events#headers" >}}) -- Add `policy` for webhook retries [#587](https://github.com/devlikeapro/waha/issues/587) - - [**🔄 Webhooks** - Headers]({{< relref "events#retries" >}}) - -`2024.10.4` -- **NOWEB** - send video note via `POST /api/sendVideo` via `asNote: true` -- **NOWEB** - handle "sent by advertisement" message properly [#567](https://github.com/devlikeapro/waha/issues/567) -- **NOWEB** + **MongoDB** - save auth data when stopping session (and container) - -`2024.10.3` -- **WEBJS** + **MongoDB** - handle removing temp folder with retries -- **WEBJS** - add more logs for state changes to help debugging - -`2024.10.2` -- 📢 **WEBJS** + **MongoDB** setup - handle disconnection properly (it stop saving auth data if connection to mongodb lost) - -`2024.10.1` - [**Release Notes**]({{< relref "/blog/waha-2024-10" >}}) -- Receive **media** now available in **WAHA Core** version! - - [**📥 Receive messages** - Files]({{}}) -- Add `PORT` environment variable for Heroku deployment - [#555](https://github.com/devlikeapro/waha/issues/555) -- Add `WAHA_BASE_URL` environment variable to set the base URL for the server for `media.url` links -- **WEBJS** - Add `message.waiting` event for encrypted but not yet decrypted messages [#554](https://github.com/devlikeapro/waha/issues/554) - - [**🔄 Webhooks** - message.waiting]({{< relref "events#messagewaiting" >}}) - - [https://faq.whatsapp.com/3398056720476987](https://faq.whatsapp.com/3398056720476987) -- **WEBJS** - handle connectivity issues better, restart client if required [#552](https://github.com/devlikeapro/waha/issues/552) -- Use `axios` as default library for sending webhooks - solve bad webhooks performance issues for many sessions installation. -- Handle webhooks retries properly in **WAHA Plus** version (using `axios`) - -### 2024.9 - -`2024.9.6` -- **NOWEB** - set session presence (`online|offline`) at the start - [#412](https://github.com/devlikeapro/waha/issues/412) - - Affects notifications on your phone (if it's `online` - you won't get in-app notifications on your device) -- **WEBJS**, **NOWEB** - fix auto restart logic bug -- **WEBJS** - support pairing via code `POST /api/{session}/auth/request-code` - - Read more [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions#get-pairing-code" >}}) -- Retrieve engine info only on detailed `GET /api/sessions/{name}` -- Check session's status before performing the request in most endpoints -- **Dashboard** - add login via **QR** and **Code** auth flows -- **Dashboard, API** - Add `me` for `STOPPED` sessions (account phone number, push name) -- **Dashboard** - Hide duplicated sessions flag for multiple servers setup (match by `session.name+me.id`) - -`2024.9.5` -- **NOWEB** - fix memory leak and performance problems [#533](https://github.com/devlikeapro/waha/issues/533) -- **WEBJS** - reduce memory usage for chrome/chromium for ~40MB per session -- Adjust error message for WAHA Core when session `STOPPED` [#538](https://github.com/devlikeapro/waha/issues/538) -- Removed `VENOM` engine completely -- Add special `/api/server/debug/heapsnapshot` to get heap dump for Node.js by `WAHA_DEBUG_MODE=True` - -`2024.9.4` -- Fix empty config sessions operations (`Session not found`) - -`2024.9.3` -- **NOWEB** - fix restarting issue when websocket is not connected yet (WebSocket was closed before the connection was established) - -`2024.9.2` -- **NOWEB** - fix error on incoming messages - [#521](https://github.com/devlikeapro/waha/issues/521) - -`2024.9.1` - [**Release Notes**]({{< relref "/blog/waha-2024-9" >}}) -- Add support for **S3** to store media file - [#353](https://github.com/devlikeapro/waha/issues/353) - - Read more [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) -- Add more granular API for [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) - - Dedicated `create, update, delete, start, stop, logout, restart` actions! - - The old API is working the same way as before for backward compatibility, but marked as **Deprecated** - - Related issues: [#435](https://github.com/devlikeapro/waha/issues/435), [#480](https://github.com/devlikeapro/waha/issues/480) -- Add ability to add your [**Metadata**]({{< relref "/docs/how-to/sessions#metadata" >}}) to a session [#443](https://github.com/devlikeapro/waha/issues/443). - - `metadata` field available in: - - [List Sessions]({{< relref "/docs/how-to/sessions#list-sessions" >}}) and [Get Session]({{< relref "/docs/how-to/sessions#get-session" >}}) responses - - [**🔄 Webhooks**]({{< relref "events#metadata" >}}) events - - [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata -- Add **Bulk Operations** (start, restart, etc.) for [**📊 Dashboard**]({{< relref "dashboard" >}}) - [#438](https://github.com/devlikeapro/waha/issues/438) -- Add environment variables on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) - [#319](https://github.com/devlikeapro/waha/issues/319) -- Add [**🔄 Webhooks - Custom Headers**]({{< relref "/docs/how-to/events#custom-headers" >}}) on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) -- Add `GET /api/server/version` and `/api/server/environment` endpoints - - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) -- Validate API request on `/api/sessions/*` endpoints - [#470](https://github.com/devlikeapro/waha/issues/470) - - 📢 **Requires attention** - make sure you're sending the right requests -- Add `POST /api/sendSeen` documentation and correct swagger spec [#485](https://github.com/devlikeapro/waha/issues/485) -- Add `GET /api/server/status` endpoint to **get server uptime** - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) -- Add `POST /api/server/stop` endpoint to **restart** server - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) -- Add `WHATSAPP_API_SCHEMA=http` environment variable so you can get the right `media.url` link -- Add `media.error` to messages with media and error - [#510](https://github.com/devlikeapro/waha/issues/510) -- Add `reply_to` field for text and media (image, files, etc) messages - [#503](https://github.com/devlikeapro/waha/issues/503) - - [**📤 Send messages** - reply_to]({{}}) -- Add `replyTo` field for receiving message - [#506](https://github.com/devlikeapro/waha/issues/506) - - [**📥 Receive messages** - replyTo]({{}}) -- Update **NOWEB** engine to the latest upstream changes - -### 2024.8 -`2024.8.5` -- **NOWEB** - ⚠️ urgent fix [#511](https://github.com/devlikeapro/waha/issues/511) - -`2024.8.4` -- **WEBJS** - fix get `GET /api/{session}/chats?limit=1` "Cannot read properties of undefined (reading 'getChats')" - -[#486](https://github.com/devlikeapro/waha/issues/486) -- **NOWEB** - fix sticker download - [#504](https://github.com/devlikeapro/waha/issues/504) - -`2024.8.3` -- fix restart container with **NOWEB** engine [#483](https://github.com/devlikeapro/waha/issues/483) -- fix " this.logger.info is not a function" in swagger plus [#496](https://github.com/devlikeapro/waha/issues/496) - -`2024.8.2` -- fix flaky **WEBJS** engine issues (`Failed to add page binding with name ...`) -- **WEBJS** + **MongoDB** - switch to native `zip` and `unzip` binaries [#465](https://github.com/devlikeapro/waha/issues/465) - - If you're not using official docker image install `zip` and `unzip` AND set `WAHA_ZIPPER=ZIPUNZIP` env variable. -- Add `WAHA_HTTP_LOG_LEVEL=info` variable to control `request completed` log level - [#466](https://github.com/devlikeapro/waha/issues/466) - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - -`2024.8.1` - [**Release Notes**]({{< relref "/blog/waha-2024-8" >}}) -- Add [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support [#318](https://github.com/devlikeapro/waha/issues/318) -- Add [**📞 Calls**]({{< relref "docs/how-to/calls" >}}) events [#307](https://github.com/devlikeapro/waha/issues/307) -- Add [**chat.archive**]({{< relref "docs/how-to/events#chatarchive" >}}) event [#434](https://github.com/devlikeapro/waha/issues/434) -- Add [**Archive and Unarchive chat endpoints**]({{< relref "docs/how-to/chats" >}}) [#434](https://github.com/devlikeapro/waha/issues/434) -- Add "sessions.name" index for MongoDB storage [#447](https://github.com/devlikeapro/waha/issues/447) -- Add `WHATSAPP_API_KEY_EXCLUDE_PATH` to exclude URI from key auth [#451](https://github.com/devlikeapro/waha/issues/451) - [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) -- Add `GET /ping` endpoint to just touch the service (no checks like in `GET /health` is done during that) - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - ----- - -### 2024.7 - -- `2024.7.7` - **WEBJS** + **MongoDB** fix - `unexpected end of file` [#457](https://github.com/devlikeapro/waha/issues/457) -- `2024.7.6` - **WEBJS** restart fix [#444](https://github.com/devlikeapro/waha/issues/444) -- `2024.7.5` - [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}) -- `2024.7.4` - **NOWEB** fix profile picture [#422](https://github.com/devlikeapro/waha/issues/422) -- `2024.7.3` - added JSON logging format - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}). -- `2024.7.2` - **WEBJS** create group fix [#416](https://github.com/devlikeapro/waha/issues/416) -- `2024.7.1` - **WEBJS** urgent update [#399](https://github.com/devlikeapro/waha/issues/399) - ----- - -### 2024.6 -#### 📢 Breaking changes - ----- - -Docker image has been renamed to `devlikeapro/waha` and `devlikeapro/waha-plus`! -- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#docker-images" >}}) -- Build: `2024.6.2` - ----- - -***🎉 New*** - ----- - -Starting `2026.6.1` we publish images with `{version}` tag, so you can pin the version you want to use. - -`devlikeapro/waha-plus:chrome-{version}` => `devlikeapro/waha-plus:chrome-2024.6.1` - -- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#versions" >}}) -- Build: `2024.6.1` - ----- - -Added `limit` and `offset` parameters to `GET /api/{session}/chats` endpoint. - -- Read more about [Get all chats]({{< relref "/docs/how-to/chats#get-all-chats" >}}) -- Build: `2024.6.4` -- Engine: **WEBJS** -- Engine: **NOWEB** - ----- - -Added Out of the box **HTTPS Support**! - -👉 [**Step-by-step guide on how to set up HTTPS for WAHA**]({{< relref "/blog/waha-https" >}}) - -- Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) -- Build: `2024.6.5` -- Issue: [#42](https://github.com/devlikeapro/waha/issues/42) -- Issue: [#369](https://github.com/devlikeapro/waha/issues/369) - ----- - -Add [Websockets](({{< relref "/docs/how-to/events#websockets" >}})) support! - -- Read more about [Websockets]({{< relref "/docs/how-to/events#websockets" >}}) -- Build: `2024.6.7` - ----- - -**🎉 New - NOWEB** - ----- - -You asked it, we did it - **contacts, chats, and messages** endpoints are now available in **NOWEB** engine! -Please make sure to [Enable NOWEB Store]({{< relref "/docs/engines/noweb#store" >}}) before using these endpoints. - -- Build: `2024.6.3` -- Engine: **NOWEB** -- [Read more about NOWEB Store]({{< relref "/docs/engines/noweb#store" >}}) -- Issue [#169](https://github.com/devlikeapro/waha/issues/169) -- Issue [#206](https://github.com/devlikeapro/waha/issues/206) -- Issue [#217](https://github.com/devlikeapro/waha/issues/217) -- Issue [#322](https://github.com/devlikeapro/waha/issues/322) -- Issue [#339](https://github.com/devlikeapro/waha/issues/339) - ----- - -Generate thumbnail preview for video and image messages in **NOWEB** engine. -- Build: `2024.6.3` -- Engine: **NOWEB** - ----- - -Fix sending poll response in **NOWEB** engine. -- Build: `2024.6.1` -- Engine: **NOWEB** -- Issue: [#356](https://github.com/devlikeapro/waha/issues/356) - ----- - -Delete status endpoint - [`POST /api/{session}/status/delete`]({{}}) - -- Build: `2024.6.7` -- Engine: **NOWEB** -- Issue: [#386](https://github.com/devlikeapro/waha/issues/386) - ----- - -**🎉 New - DASHBOARD** - ----- - -Starting `2024.6.3` [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) is available in **WAHA Core** version! - -- Read more about [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) -- Build: `2024.6.3` - ----- - -Starting `2024.6.3` [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) allows connecting to **multiple WAHA instances**! - -- Read more about [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) -- Build: `2024.6.3` - ----- - -**🐛 Fixes - NOWEB** - - -Sender presence keeps on typing after sending message. -- Issue: [#379](https://github.com/devlikeapro/waha/issues/379) -- Build: `2024.6.6` - ----- - -### 2024.5 -**🎉 New** - ----- - -Added `WAHA_PRINT_QR` environment variable to control QR code printing (by default `True`). Set `WAHA_PRINT_QR=False` to disable QR code printing. -- Read more about it on [Configuration]({{< relref "/docs/how-to/config" >}}) -- Issue: [#351](https://github.com/devlikeapro/waha/issues/351) -- Build: `2024.5.13` - ----- - -[Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) - show your own brand in the Swagger documentation! -- Read more about [Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) -- Issue: [#305](https://github.com/devlikeapro/waha/issues/305) -- Build: `2024.5.4` - ----- - -**🐛 Fixes** - ----- - -Don't allow to start two sessions with the same name. - -Before API allowed to start two sessions with the same name, which could lead to potential problems (no way to stop the first, abandoned session). -- Issue: [#315](https://github.com/devlikeapro/waha/issues/315) -- Read more about [start a session](https://waha.devlike.pro/docs/how-to/sessions/#start) -- Build: `2024.5.3` -- Engine: **ALL** - ----- - -**🐛 Fixes - WEBJS** - -Handling rare errors in MongoDB process for saving and restoring session data. -- Build: `2024.5.12` -- Engine: **WEBJS** -- Commit: [9c398f2](https://github.com/devlikeapro/waha-plus/commit/9c398f26f937bf0de2c43ebb1e032c7a766ca8f7) - ----- - -Fix send video issue `POST /api/sendVideo` in **WEBJS**. -- Issue: [#321](https://github.com/devlikeapro/waha/issues/321) -- Issue: [#328](https://github.com/devlikeapro/waha/issues/328) -- Build: `2024.5.9` -- Engine: **WEBJS** - ----- - -Use local cache for **WEBJS** engine (versions file). -- Issue: [#316](https://github.com/devlikeapro/waha/issues/316) -- Build: `2024.5.4` -- Engine: **WEBJS** - ----- - -**🐛 Fixes - NOWEB** - -Fix `message.ack` event for viewing status (`status@broadcast`) messages. - -- Issue: [#329](https://github.com/devlikeapro/waha/issues/329) -- Build: `2024.5.14` - ----- - -Auto restart **NOWEB** connection every 30 minutes. - -- Issue: [#336](https://github.com/devlikeapro/waha/issues/336) -- Build: `2024.5.14` - ----- - -Set heap memory limit to 16GB for **NOWEB** engine. - -- Issue: [#347](https://github.com/devlikeapro/waha/issues/347) -- Build: `2024.5.12` - ----- - -Add `body` to messages with caption in **NOWEB** engine. - -- Build: `2024.5.10` - ----- - -Fix "document with caption" message media issue - -- Issue: [#345](https://github.com/devlikeapro/waha/issues/345) -- Build: `2024.5.10` - ----- - -Important **NOWEB** Engine Update! -WhatsApp has deprecated the version currently being used in the NOWEB engine - -- [Read on Patreon](https://www.patreon.com/posts/important-noweb-104631614) -- [Read on Boosty](https://boosty.to/wa-http-api/posts/6ccedda7-ddae-413b-b15f-f2f22192c0d8) -- Build: `2024.5.8` -- Engine: **NOWEB** - ----- - -### 2024.4 -**🎉 New** - -Add **WAHA Dashboard** - UI to manage your WhatsApp sessions! -- Read more about [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) - ----- - -Add `GET /api/sessions/{session}` endpoint to get information about a specific session. -- Read more about [Get session information]({{< relref "/docs/how-to/sessions#get-session" >}}) -- Issue: [#300](https://github.com/devlikeapro/waha/issues/300) - ----- - -Implement `GET /api/contacts/profile-picture` for **NOWEB** engine. -- Read more about [Get contact profile picture](https://waha.devlike.pro/docs/how-to/contacts/#get-contact-profile-picture) -- Issue: [#298](https://github.com/devlikeapro/waha/issues/298) - ----- - -### 2024.3 -**🎉 New** - ----- - -Add `message.reaction` webhook in **WEBJS** and **NOWEB** engines -- Read more about [message.reaction]({{< relref "/docs/how-to/events#messagereaction" >}}) event -- Issue: [#275](https://github.com/devlikeapro/waha/issues/275) - -👉 **NOWEB** engine note - reactions were sent in `'message'` and `'message.any'` events, not it's available **only** in `'message.reaction'`! - ----- - -Add star and unstar message endpoint `PUT /api/star` -- Read [Star and unstar message]({{< relref "/docs/how-to/send-messages#star-and-unstar-message" >}}) documentation -- Issue: [#273](https://github.com/devlikeapro/waha/issues/240) - ----- - -Add `PUT /api/{session}/chats/{chatId}/messages/{messageId}` endpoint to **edit** the message. -- Read more about [Edit message]({{< relref "/docs/how-to/send-messages#edit-message" >}}) -- Issue: [#241](https://github.com/devlikeapro/waha/issues/241) - ----- - -Add `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` endpoint to **delete** the message. -- Read more about [Delete message]({{< relref "/docs/how-to/send-messages#delete-message" >}}) -- Issue: [#209](https://github.com/devlikeapro/waha/issues/209) - ----- - -Add `POST /api/sendContactVcard` support for **NOWEB** engine. -- Read more about [Send Contact vCard]({{< relref "/docs/how-to/send-messages#send-contact-vcard" >}}) -- Issue: [#276](https://github.com/devlikeapro/waha/issues/256) - ----- - -Handles `caption` and `filename` right in `POST /api/sendFile` -- Issue: [#94](https://github.com/devlikeapro/waha/issues/94) -- Issue: [#133](https://github.com/devlikeapro/waha/issues/133) - ----- - -Add security settings for who can send messages `PUT /api/{session}/groups/{groupId}/settings/security/messages-admin-only` -- Read [Security - who can send messages]({{< relref "/docs/how-to/groups##security---who-can-send-messages" >}}) -- Issue: [#274](https://github.com/devlikeapro/waha/issues/274) - ----- - -Add `config.debug` field to `POST /api/sessions/start` to enable debug and verbose logs for the session. - ----- - -#### 📢 Breaking changes -- **NOWEB** - reactions were sent in `'message'` and `'message.any'` events, not it's available **only** in `'message.reaction'`! -- Add **required body** in `PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only` endpoint. -```json -{ - "adminsOnly": false -} -``` - -- `POST /api/sendContactVcard` doesn't work in **VENOM** anymore (use **NOWEB** engine). - -### 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/observability/) - -### 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/waha/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/waha/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/waha/issues/185) -- Add dedicated `media` field in webhook payload - now you can know which media is attached to the message. -```json { title="message" } -{ - "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) -- Add [polls support in NOWEB engine](https://waha.devlike.pro/docs/how-to/polls) -- Add dedicated [Get QR](https://waha.devlike.pro/docs/how-to/sessions/#get-qr) endpoint! -- Support [pairing method (NOWEB)](https://waha.devlike.pro/docs/how-to/sessions/#get-pairing-code) - you can connect with a code instead of QR. -- Add string field `ackName: DEVICE|READ|...` in [message.ack payload](https://waha.devlike.pro/docs/how-to/events/#messageack) -- Support `message.ack` event webhook in **NOWEB** engine - -### 2023.8 -August 2023 -- Added [stories (aka status) endpoints](https://waha.devlike.pro/docs/how-to/send-messages/#send-status-aka-stories) to **NOWEB** engine! - - `POST /api/{session}/status/text|image|voice|video` - choose one that suites your! -- Added [chats endpoints](https://waha.devlike.pro/docs/how-to/chats) - - Get all chats - `GET /api/{session/chats` - - Delete chat - `DELETE /api/{session/chats/{chatId}` - - Get messages from chat - `GET /api/{session/chats/{chatId}/messages?limit=1000?downloadMedia=true` - - Clear messages in the chat `DELETE /api/{session/chats/{chatId}/messages` -- Added `downloadMedia` flag to speed up `GET /api/messages` and `GET /api/{session/chats/{chatId}/messages` performance. -- Added [set presence endpoint](https://waha.devlike.pro/docs/how-to/presence)! - - With `online` presence you can show your status as online [#121](https://github.com/devlikeapro/waha/issues/121) - - With `offline` presence you can get notifications for your device [#28](https://github.com/devlikeapro/waha/issues/28) -- Added security settings for edit group info `PUT /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.7 -July 2023 -- Now session can have their own [🔄 Webhooks]({{< relref "/docs/how-to/events" >}}) - - you can define webhook configuration when you start a session with `POST /api/sessions/start`! - - Add HMAC authentication for webhooks - - Configure retries - - Add you custom headers -- Added [proxy configuration](https://waha.devlike.pro/docs/how-to/config/#proxy) with supporting proxy authentication. - Thanks **puntolino** for the contribution! - You can control proxy's settings per session with `POST /api/sessions/start` or globally with environment variables. -- Added [presence information](https://waha.devlike.pro/docs/how-to/presence) - now you can get online status for - a contact by calling endpoints or receiving a webhook event! -- Now you can mention contact in groups by settings `mentions` field in `POST /api/sendText` - [read more about it in Send Messages ->]({{< relref "/docs/how-to/send-messages" >}}) - -### 2023.6 -June 2023 - -Improvements on session management, restarting sessions and more: - -- Added `WHATSAPP_RESTART_ALL_SESSIONS=True`: Set this variable to `True` to start all **STOPPED** sessions after - container restarts. By default, this variable is set to `False`. - - Please note that this will start all **STOPPED** sessions, not just the sessions that were working before the - restart. You can maintain the session list by - using `POST /api/sessions/stop` with the `logout: True` parameter or by calling `POST /api/sessions/logout` to remove - **STOPPED** sessions. You can see all sessions, including **STOPPED** sessions, in the `GET /api/sessions/all=True` - response. -- `WHATSAPP_START_SESSION` now support more than one session! Separate session names by command, and it'll start them - ALWAYS after container restart `WHATSAPP_START_SESSION=session1,session2` -- `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. -- Added `?all=true` parameter to `GET /api/session?all=True` endpoint - it'll show you ALL session, included - **STOPPED**, so you can know which one will be restarted if you set `WHATSAPP_RESTART_ALL_SESSIONS=True` environment variable. -- Added `POST /api/sessions/logout` that allow you to logout from session - remove saved credentials. -- Added `logout` boolean parameter to `POST /api/sessions/stop` request that allow you to stop the session AND logout at - the same time. -- Added `engine` field in webhook payload - -```json { title="message" } -{ - "event": "message", - "session": "default", - "engine": "WEBJS", - "payload": {} -} -``` - -### 2023.5 -May 2023 - -- Added new [NOWEB engine]({{< relref "/docs/how-to/engines" >}}). **NOWEB** engine does not require a browser to work - with - WhatsApp Web, it does so directly using a WebSocket. - - Less CPU and RAM usage! - - Send Locations API works! - - Send Link Preview API works! - - ⚠ Read the article before using it [How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). - -### 2023.4 -March 2023 - -- Add [Groups API]({{< relref "/docs/how-to/groups" >}}) -- Use Chromium by default instead of Chrome - -### 2023.1 -January 2023 - -- Added [Contacts API]({{< relref "/docs/how-to/contacts" >}}) - - Get all contacts - - Get a contact - - Get contact "about" (status) - - Get contact profile picture - - Check number exists (is registered in WhatsApp) - works even if the number is not in the contact list - - Block and unblock contact - -### 2022.12 -December 2023 - -- Added `GET /messages/` endpoint to get chat messages [#31](https://github.com/devlikeapro/waha/issues/31) -- Added `WHATSAPP_SWAGGER_USERNAME` and `WHATSAPP_SWAGGER_PASSWORD` to hide and protect swagger panel. - -### 2022.11 - -**Please test changes in test environment before update production!!** - -**Engine** - -1. WAHA has changed its underlying engine from Venom to Whatsapp Web.JS. It might change the response and webhook's - payloads. -2. Optimize CPU and memory consumption. - -**Requests** - -- For all `/api/sessions/` requests use `name` field instead of `sessionName`. -- For all "chatting" requests use `session` field instead of `sessionName`. - -**Sessions** - -Now you don't have to scan QR code each time you run WAHA, WAHA saves it for you! Available only in Plus version. - -**Authentication** - -Now you can authenticate all requests for WAHA - use `WHATSAPP_API_KEY=secret` environment variable to set "secret key". - -If `WHATSAPP_API_KEY` is set - requests must have `X-Api-Key` header with `secret` value, where `secret` - any random -secret key. - -**Webhooks** - -Instead of setting each webhook via environment variables - we use two environments variables: - -- `WHATSAPP_HOOK_URL` - to set a URL -- `WHATSAPP_HOOK_EVENTS` - to set events that are sent to the URL - -**Webhook payload** - -The data for webhooks are wrapped inside a new `WAWebhook` object with `event` and `payload` fields to help you identify -which handler you should call based on `event`. - -```json { title="message.any" } -{ - "event": "message.any", - "payload": { - } -} -``` +--- +title: "🆕 Changelog" +description: "WAHA's changelog" +lead: "You can find here the list of changes made to WAHA." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false + +menu: + docs: + parent: "help" +weight: 199 +toc: true +--- + +## Get Notified + +If you wish to get **Monthly Summary** about WAHA changes, subscribe to our channels. + +{{< callout context="tip" title="You can subscribe on free tier!" icon="outline/rss" >}} + +- [**Patreon ->**](https://patreon.com/wa_http_api) +- [**Boosty ->**](https://boosty.to/wa-http-api) + {{< /callout >}} + +If you wish to get **Real-Time Email** about new changes, +you can **Watch Releases** in [**🐙 WAHA GitHub**](https://github.com/devlikeapro/waha) + +{{< details "💡 GitHub - How To Subscribe" >}} + +Go to [https://github.com/devlikeapro/waha](https://github.com/devlikeapro/waha), click **Watch - Custom**: +{{< imgo src="/images/github/github-watch.png" full="false" >}} + +Select **Releases**, click **Apply**: +{{< imgo src="/images/github/github-watch-releases.png" full="false" >}} + +You will get notifications about new releases in associated email! + +{{< /details >}} + +## Releases + +Latest Version: + +GitHub Release + + +{{< callout context="note" icon="outline/info-circle" >}} +Check the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) page to learn how to update WAHA. +{{< /callout >}} + +### 2025.8 + +🛠️ **Fixes** + +- `2025.8.1` - **WEBJS** - fix create group - {{< issue 1145 >}} +- `2025.8.1` - **NOWEB** - fix channel list - {{< issue 1177 >}} +- `2025.8.1` - limited characters in the session name - {{< issue 1163 >}} + +### 2025.7 + +**🆕 NEW** + +- `2025.7.11` - Add languages (i18n) on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) +- `2025.7.8` - Add [**👤 Update Contact API**]({{< relref "/docs/how-to/contacts#update-contact" >}}) - {{< issue 1124 >}} + - **WEBJS**, **GOWS**, **NOWEB** +- `2025.7.5` - Add [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) - {{< issue 441 >}} +- `2025.7.2` - **WEBJS** - Add `GET /api/server/debug/browser/trace` API to [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) - {{< issue 1092 >}} +- `2025.7.2` - **WEBJS** - `--a-waha-session` and `--a-waha-timestamp` to chrome/chromium args - {{< issue 1092 >}} + +**🧩 Apps**: + +- `2025.7.11` - **ChatWoot** - fix @lid issue - find first by chat id +- `2025.7.11` - **ChatWoot** - add **Udru** language +- `2025.7.8` - **ChatWoot** - send `png` as image, not as attachment +- `2025.7.5` - Add [**🧩 ChatWoot App**]({{< relref "/docs/apps/chatwoot" >}}) - {{< issue 441 >}} + +🛠️ **Fixes** + +- `2025.7.11` - **WEBJS** - Fix "You provided 'null' where a stream was expected" - {{< issue 1178 >}} +- `2025.7.10` - **GOWS** - speed up sending a message to groups - {{< issue 1100 >}} +- `2025.7.10` - **NOWEB** - do not freeze server in a lot of sessions case (use regular `sqlite3`) +- `2025.7.9` - **WEBJS** - add `WAHA_RUN_XVFB=False` parameter - {{< issue 1151 >}} +- `2025.7.9` - adjust `UV_THREADPOOL_SIZE` values (`cpu*2` or min is `4`) +- `2025.7.7` - **WEBJS** - add browser cache - {{< issue 1131 >}}, {{< issue 1140 >}} +- `2025.7.6` - **WEBJS** - fix **send seen** and **send read messages** - {{< issue 1117 >}} +- `2025.7.5` - **WEBJS** - ignore old reactions on connection - {{< issue 494 >}} +- `2025.7.5` - **WEBJS** - increase rendering processes to 2 +- `2025.7.4` - **NOWEB** - handle [**👤 Lids**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) on first message + - {{< issue 1073 >}}, {{< issue 1097 >}} +- `2025.7.4` - **NOWEB** - fix some connection issues + - {{< issue 531 >}}, {{< issue 1098 >}} +- `2025.7.4` - **WEBJS** - increase `protocolTimeout` to 300s - {{< issue 1103 >}} +- `2025.7.4` - **WEBJS** - fix some `STARTING => FAILED` sessions - {{< issue 1071 >}} +- `2025.7.4` - **GOWS** - Fix [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) to 10K contacts - {{< issue 1058 >}} +- `2025.7.3` - **GOWS** - fix generating preview links youtu.be +- `2025.7.3` - **GOWS** - fix fetching media for some messages +- `2025.7.3` - **GOWS** - reconnect on session start if any network error happens +- `2025.7.3` - **GOWS** - fix stuck in `STARTING` + - {{< issue 1043 >}}, {{< issue 1068 >}}, {{< issue 1094 >}} +- `2025.7.3` - **WEBJS** - disable GPU +- `2025.7.2` - **WEBJS** - limit renderer process to **1** - {{< issue 1092 >}} +- `2025.7.2` - remove healthcheck and `ping-check.sh` script - {{< issue 1085 >}} +- `2025.7.1` - move `HEALTHCHECK` from Dockerfile to docker-compose - {{< issue 1090 >}} + +**⚙️ Updates** + +- `2025.7.9` - **NOWEB** - up proto to `v1025126393` +- `2025.7.4` - **NOWEB** - up engine to `2025-07-04` +- `2025.7.3` - **GOWS** - up engine and proto to `v1024307498` + +### 2025.6 + +**🆕 NEW** + +- `2025.6.5` - [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) now available in **WAHA Core** - {{< issue 1069 >}} +- `2025.6.5` - Support hash in Api Key variable `WAHA_API_KEY=sha512:{HASH}` in [**🔒 API Key Security**]({{< relref "/docs/how-to/security" >}}) - {{< issue 1069 >}} +- `2025.6.3` - Add `message.edited` to [**🔄 Events**]({{< relref "/docs/how-to/events#messageedited" >}}) - {{< issue 916 >}}, {{< issue 1041 >}} + - **WEBJS**, **GOWS**, **NOWEB** + - ⚠️ **NOWEB** - removed an edited **protocol message** from `message` and `message.any`, now listen `message.edited` instead +- `2025.6.3` - **GOWS** Add `message.revoked` to [**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}) - {{< issue 917 >}} +- `2025.6.3` - Add `revokedMessageId` field to `message.revoked` to [**🔄 Events**]({{< relref "/docs/how-to/events#messagerevoked" >}}) +- `2025.6.2` - Add `convert: true` flag (`false` by default) to `/api/sendVoice` and `/api/sendVideo` - {{< issue 724 >}} +- `2025.6.2` - Add API to convert voice and video files before sending it - {{< issue 724 >}} + - [**POST /api/{session}/media/convert/voice**]({{< relref "/docs/how-to/send-messages#media---convert-voice" >}}) + - [**POST /api/{session}/media/convert/video**]({{< relref "/docs/how-to/send-messages#media---convert-video" >}}) + - No more `ffmpeg` required, just use `convert: true` or convert API! + +🛠️ **Fixes** + +- `2025.6.7` - fix `curl: command not found` in healthcheck - {{< issue 1085 >}} + - `:noweb` and `:gows` docker images +- `2025.6.6` - **NOWEB** - show poll on the sender device - {{< issue 988 >}} +- `2025.6.6` - **WEBJS** - return message response - {{< issue 1083 >}} +- `2025.6.6` - **WEBJS** - fix pin message - {{< issue 1081 >}}, {{< issue 1082 >}} +- `2025.6.6` - **WEBJS** - fix zombie processes - {{< issue 1078 >}} +- `2025.6.6` - Return `501 Not Implemented` if engine does not support API - {{< issue 1047 >}} +- `2025.6.4` - **NOWEB** - fix _continuous loop of state synchronization_ - {{< issue 1054 >}} +- `2025.6.3` - Add `timeout` for `AsyncLock` to prevent long queues + - **NOWEB** - has a lot of it + - **WEBJS**, **GOWS** - some API for session management +- `2025.6.3` - **WEBJS** - add `Xvfb` to container {{< issue 1032 >}} +- `2025.6.2` - **WEBJS** - fix disconnection issues {{< issue 1032 >}} +- `2025.6.1` - **GOWS** - fix memory leak {{< issue 919 >}} +- `2025.6.1` - **WEBJS** - fix [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) management issues + - {{< issue 1023 >}}, {{< issue 1024 >}}, {{< issue 1025 >}}, {{< issue 1026 >}}, {{< issue 1027 >}} + +**⚙️ Updates** + +- `2025.6.2` - **WEBJS** - update chrome, puppeter +- `2025.6.1` - **GOWS** - up engine to **2025.06.09** version +- `2025.6.1` - **WEBJS** - up engine to **2025.06.09** version + +### 2025.5 + +**🆕 NEW** + +- `2025.5.5` - **WEBJS** - [**✅ Presence**]({{}}) API and Events - {{< issue 636 >}} +- `2025.5.5` - **GOWS** - [**📶 Polls**]({{< relref "docs/how-to/polls" >}}) support - {{< issue 899 >}} +- `2025.5.5` - Filter chats by `ids` in [**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API - {{< issue 791 >}} +- `2025.5.4` - Add [**👤 Contacts - Lids API**]({{< relref "/docs/how-to/contacts/#api---lids" >}}) to map `@lid` to `@c.us` - {{< issue 957 >}} + - **WEBJS**, **NOWEB**, **GOWS** +- `2025.5.4` - **GOWS** - [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support - {{< issue 922 >}} +- `2025.5.4` - **GOWS** - add `POST /api/sendContactVcard` support - {{< issue 902 >}} + +🛠️ **Fixes** + +- `2025.5.6` - Fix fetch media from S3/PostgreSQL - {{< issue 1007 >}} +- `2025.5.5` - Subscribe [**✅ Presence**]({{}}) on each request + - **WEBJS**, **NOWEB**, **GOWS** +- `2025.5.5` - **WEBJS** - hide "Fresh Look" modal form {{< issue 987 >}} +- `2025.5.5` - **WEBJS** - add `tini` to docker to handle zombie processes {{< issue 990 >}} +- `2025.5.5` - **Local Storage** - fix empty session name issues when calling logout or delete +- `2025.5.5` - fix pairing Business Accounts connected to official Meta API - {{< issue 864 >}} + - **NOWEB**, **GOWS** +- `2025.5.4` - **PostgreSQL** - use `5432` port by default if not provided {{< issue 975 >}} +- `2025.5.4` - **NOWEB** - fix "async-lock timed out in queue" error on session actions {{< issue 831 >}} +- `2025.5.3` - **NOWEB** - fix `poll.vote` event - {{< issue 960 >}} +- `2025.5.2` - **GOWS** - fix pairing Business Accounts connected to official Meta API - {{< issue 864 >}} +- `2025.5.2` - **NOWEB** - fix pairing via code {{< issue 961 >}} +- `2025.5.2` - **GOWS** and **NOWEB** - fix "undefined senderKeyDistributionMessage" error +- `2025.5.2` - protect **PostgreSQL** media with an API key +- `2025.5.2` - minor security update +- `2025.5.1` - **NOWEB** - fix syncing for accounts with many messages/contacts - {{< issue 952 >}} + - [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}): **Local**, **PostgreSQL**, **MongoDB** +- `2025.5.1` - **NOWEB** - no duplicate `message.ack` for a single message - {{< issue 948 >}} +- `2025.5.1` - **WEBJS** - fix potential connection leak to storages - {{< issue 952 >}} +- `2025.5.1` - **WEBJS** - fix adding/removing participant to group - {{< issue 944 >}} +- `2025.5.1` - **WEBJS** - fix sorting groups in `/chats` and `/chats/overview` - {{< issue 915 >}} + +**⚙️ Updates** + +- `2025.5.5` - update nestjs - fixes `DeprecationWarning: The 'util.isObject' API is deprecated` + +### 2025.4 + +`2025.4.2` + +**🆕 NEW** + +- Add [**💬 Chats - Read messages**]({{< relref "/docs/how-to/chats#read-messages" >}}) API to mark unread messages as read {{< issue 783>}} + - **WEBJS**, **NOWEB**, **GOWS** +- Add `filter.ack` to [**💬 Chats - Get messages**]({{< relref "/docs/how-to/chats#get-messages" >}}) API + - **WEBJS**, **NOWEB**, **GOWS** +- **WEBJS** - add `message.ack` events for [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) and [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) messages + - {{< issue 495 >}}, {{< issue 900 >}} +- **WEBJS** - add `message._data.receipts` in [**💬 Chats** - **Get message by id**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) [**👥 Groups**]({{< relref "/docs/how-to/groups" >}}) and [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) + - It shows all receipts (ack status) for the message + - {{< issue 495 >}}, {{< issue 900 >}} +- Read multiple messages by using `messageIds` in [**POST /api/sendSeen**]({{< relref "/docs/how-to/send-messages#send-seen" >}}) API + - **NOWEB**, **GOWS** + +🛠️ **Fixes** + +- **NOWEB** - update message status on `/api/sendSeen` - {{< issue 635 >}} +- **NOWEB** - fix "Cannot read properties of undefined (reading 'protocolMessage')" - {{< issue 932 >}} +- **WEBJS** - restart browser on **ProtocolError** and **Promise was collected** + - {{< issue 244 >}}, {{< issue 714 >}}, {{< issue 685 >}}, {{< issue 936 >}} +- **NOWEB** - Fix `ack` for new messages (it was `UNKNOWN`, now it's `DEVICE`) +- **GOWS** - send `DEVICE` `message.ack` for all groups participants +- Fix **sending** messages to **anonymous groups** (one with `@lid` participants) + - **NOWEB** + - **GOWS** +- Fix **receiving** messages to **groups** and **status** (some messages were missed) + - **NOWEB** + - **GOWS** + +**⚙️ Updates** + +- **NOWEB** - update engine to the latest version +- **GOWS** - update engine to the latest version +- **WEBJS** - update + - **puppeter** (all images) + - **chrome** (`devlikeapro/waha-plus:chrome`and `devlikeapro/waha:chrome` images) + +--- + +`2025.4.1` + +- Fix Send Reaction to [**📢 Channels**]({{< relref "/docs/how-to/channels#send-reaction-to-the-channel" >}}) - {{< issue 889 >}} + - **GOWS**, **NOWEB** +- [**📤 Send Link Custom Preview**]({{< relref "/docs/how-to/send-messages#send-link-custom-preview" >}}) - {{< issue 880 >}}, {{< issue 596 >}} + - **GOWS**, **NOWEB** +- **GOWS** - fix Send Reaction to other participants messages {{< issue 894 >}} + +--- + +### 2025.3 + +`2025.3.3` + +- **GOWS** - fix timeout on chat overview - {{< issue 881 >}}, {{< issue 878 >}} +- **NOWEB** - cache presence data for 1 minute + +`2025.3.2` + +- Add [**📤 Button Reply**]({{< relref "/docs/how-to/send-messages#send-buttons-reply" >}}) API - {{< issue 848 >}} + - **WEBJS** +- Add features for [**🔄 Global Webhooks**]({{< relref "/docs/how-to/events#global-webhooks" >}}) - {{< issue 855 >}} + - **GOWS**, **NOWEB**, **WEBJS** + - Set HMAC using `WHATSAPP_HOOK_HMAC_KEY` environment variable + - Set retries using `WHATSAPP_HOOK_RETRIES_*` environment variables + - Set custom headers using `WHATSAPP_HOOK_CUSTOM_HEADERS` environment variables +- **GOWS** - Fix Get Contact `The "original" argument must be of type function` - {{< issue 866 >}} +- **NOWEB** - fix out of memory when session stuck in `STARTING` statuses + - {{< issue 821 >}}, {{< issue 860 >}}, {{< issue 869 >}} +- **NOWEB** - mark session as `FAILED` if QR code is not scanned in the interval. +- **NOWEB** - presences optimizations - store presence for 1 hour and fetch new if not accessed +- Handle sending [**🟢 Status**]({{< relref "/docs/how-to/status" >}}) to 50K contacts - {{< issue 858 >}} + - **GOWS**, **NOWEB** +- Add [**🟢 Status - Get New Status Message ID**]({{< relref "/docs/how-to/status" >}}) - {{< issue 858 >}} + - **GOWS**, **NOWEB** + - You can use it in [**Send Status to 10K contacts**]({{< relref "/docs/how-to/status#send-status-to-10k-contacts-manually" >}}) flow +- Add searches by Name and Phone Number to [**📊Dashboard**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) +- **GOWS** - extract `replyTo` - {{< issue 876 >}} + +`2025.3.1` + +- **GOWS** multiple improvements + - Enable Link Previews - {{< issue 763 >}} + - Delete Status Message - {{< issue 754 >}} + - Delete Message - {{< issue 796 >}} + - Edit Message - {{< issue 797 >}} + - Reply To Message - {{< issue 799 >}} + - Add `filename` on `/api/sendFile` - {{< issue 853 >}} +- `linkPreviewHighQuality: true` for [**📤 Send messages - Link Preview**]({{< relref "/docs/how-to/send-messages#link-preview" >}}) + - **GOWS**, **NOWEB** +- Add `event.timestamp` to [**🔄 Events**]({{< relref "/docs/how-to/events" >}}) - {{< issue 755 >}} +- **NOWEB** - Filter [**📞 Calls**]({{< relref "/docs/how-to/calls" >}}) from `message` event - {{< issue 840 >}} +- Support **disappearing messages** in [**📤 Send messages**]({{< relref "/docs/how-to/send-messages" >}}) - {{< issue 736 >}} + - **GOWS**, **NOWEB**, **WEBJS** + - Might require repairing (logout/scan qr) for old chats +- Add `source: api|app` in [**🔄 Events** - message.any]({{< relref "/docs/how-to/events#messageany" >}}) - {{< issue 787 >}} +- Add [**👥 Groups Count API**]({{< relref "/docs/how-to/groups#get-groups-count" >}}) - {{< issue 752 >}} + - **GOWS**, **NOWEB**, **WEBJS** + +### 2025.2 + +`2025.2.8` + +- **WEBJS** - fix empty channels {{< issue 832 >}} +- Edit message `linkPreview` {{< issue 833 >}} + +`2025.2.7` + +- Add [**👥 Group Picture API**]({{< relref "/docs/how-to/groups#group-picture" >}}) - {{< issue 802 >}} + - **WEBJS**, **NOWEB**, **GOWS** + - Picture Update available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) +- **GOWS** - Add [**👥 Group API**]({{< relref "/docs/how-to/groups" >}}) - {{< issue 825 >}} +- **NOWEB** - Add [**👥 Group Settings API**]({{< relref "/docs/how-to/groups" >}}) - {{< issue 695 >}}, {{< issue 808 >}} +- Add `exclude=participants` to [**👥 Get All Groups API**]({{< relref "/docs/how-to/groups#get-all-groups" >}}) - {{< issue 242 >}} + - **WEBJS**, **NOWEB**, **GOWS** +- **NOWEB** - fix `TypeError: group.participants is not iterable` - {{< issue 810 >}} +- **NOWEB** - disable auto-restart every 30 mins, restart will happen only on socket error - {{< issue 756 >}} + +`2025.2.6` + +- **NOWEB** + **PostgreSQL** - fix `\u0000 - unsupported Unicode escape sequence` - {{< issue 820 >}} + +`2025.2.5` + +- **NOWEB** - fix `body: null` or empty `body` in some cases - {{< issue 813 >}} +- **NOWEB** - add `message.revoked` event + +`2025.2.4` + +- Add [**👥 group.v2 events**]({{< relref "/docs/how-to/groups#events" >}}) + - `group.v2.join` - when you join a group + - `group.v2.leave` - when you leave a group + - `group.v2.participants` - when someone joins, leaves, get promoted or demoted in a group + - `group.v2.update` - when group information are updated + - **WEBJS**, **NOWEB**, **GOWS** engines + - {{< issue 583 >}}, {{< issue 527 >}}, {{< issue 404 >}} +- **NOWEB** - catch and log unhandled errors {{< issue 809 >}} + +`2025.2.3` + +- Add [**🆔 Profile API**]({{< relref "/docs/how-to/profile" >}} ) to get and update profile information {{< issue 529 >}} + - **WEBJS**, **NOWEB**, **GOWS** engines +- Fix `hasMedia` behaviour - now when you request messages with `downloadMedia=False`, `hasMedia: true` if message has media + - **WEBJS**, **NOWEB**, **GOWS** engines + +`2025.2.2` + +- [**📢 Search Public Channels**]({{< relref "/docs/how-to/channels#search-channels-by-view" >}}) API - {{< issue 440 >}} + - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) +- [**📢 Get Messages (Preview) From Public Channels**]({{< relref "/docs/how-to/channels##get-messages-from-channel-preview" >}}) API + - Available in [**➕ WAHA Plus**]({{< relref "/docs/how-to/waha-plus" >}}) +- **PostgreSQL** - fix `sorry, too many clients already` in some cases + - **WEBJS**, **NOWEB**, **GOWS** engines +- **S3** - fix `headers[headerName].trim is not a function` error {{< issue 790 >}} + +`2025.2.1` + +- **GOWS** - [**👤 Contacts**]({{< relref "/docs/how-to/contacts" >}}) API +- **GOWS** - [**💬 Chats - Get Chats Overview**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) API +- **GOWS** - [**💬 Chats - Get Messages**]({{< relref "/docs/how-to/chats#get-messages" >}}) API +- **NOWEB** - fix group message error {{< issue 765 >}}, {{< issue 766 >}} +- **GOWS** - fix group message error {{< issue 765 >}}, {{< issue 766 >}} + +### 2025.1 + +[**Release Notes**]({{< relref "/blog/waha-2025-1" >}}) + +`2025.1.6` + +- **WEBJS** - fix send image/video to [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) - {{< issue 733 >}} + +`2025.1.5` + +- **GOWS** - add [**📢 Channels**]({{< relref "/docs/how-to/channels" >}}) API +- **GOWS** - add [**🟢 Status (aka Stories) API**]({{< relref "/docs/how-to/status" >}}) API +- **GOWS** - add [**Check Contact exists**]({{< relref "/docs/how-to/contacts" >}}) API + +`2025.1.4` + +- [**🖥️ Session Storage - PostgresSQL**]({{< relref "/docs/how-to/storages#sessions---postgresql" >}}) - add support for storing sessions in PostgreSQL + - Available in all [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}})! +- [**🖼️ Media Storage - PostgresSQL**]({{< relref "/docs/how-to/storages#media---postgresql" >}}) - add support for storing media files in PostgreSQL + - Available in all [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}})! +- [**🗄️ Local Storage**]({{< relref "/docs/how-to/storages" >}}) available in **WAHA Core** now - {{< issue 741 >}} + - Both **🖥️ Session** and **🖼️ Media** storages +- **S3**, **PostgreSQL** - add `chat-id` metadata {{< issue 717 >}} +- **WEBJS** - remove unnecessary flags for chrome/chromium process to increase stability + - {{< issue 685 >}}, {{< issue 714 >}} + +`2025.1.3` + +- **GOWS** - add [**🏭 GOWS Engine**]({{< relref "/docs/how-to/engines#gows" >}}) beta version (does not support many features yet) +- Lazy QR code png generation (300+ sessions performance issue) +- Shutdown HTTP server gracefully + +`2025.1.2` + +- **NOWEB** - fix corrupted sessions {{< issue 731 >}} +- Use atomic write for files (**NOWEB** + media files) + +`2025.1.1` + +- **NOWEB** - do not save empty creds into file when session stops {{< issue 727 >}} +- **NOWEB** + **MongoDB** - add descending order for messages +- Some timeout fixes + +### 2024.12 + +[**Release Notes**]({{< relref "/blog/waha-2024-12" >}}) + +`2024.12.6` + +- Add [**💬 Get chats overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) + - **WEBJS**, **NOWEB** + - {{< issue 566 >}} + - {{< issue 573 >}} + - {{< issue 701 >}} +- Add [**📊 Chat UI to Dashboard**]({{< relref "/docs/how-to/dashboard#chat-ui" >}}) - + as an example for [**💬 Get chats overview API**]({{< relref "/docs/how-to/chats#get-chats-overview" >}}) +- Add [**💬 Get chat picture API**]({{< relref "/docs/how-to/chats#get-chat-picture" >}}) +- Add `refresh` flag to **Get chat picture** and **Get contact picture** API +- Cache profile picture for 24 hours +- **WEBJS** - fix "Could not get the quoted message" error when replying to a message - {{< issue 576 >}} +- **NOWEB** - Fix `not-authorized` on get profile picture {{< issue 381 >}} + +`2024.12.5` + +- **NOWEB** - attempt #3 to fix missing messages {{< issue 671 >}} + +`2024.12.4` + +- Add [**👥 Join Group API**]({{< relref "/docs/how-to/groups#join-group" >}}) - {{< issue 688 >}} + +`2024.12.3` + +- **NOWEB** - use **NOWEB** engine by default in [devlikeapro/waha-plus:noweb]({{< relref "/docs/how-to/engines#docker-images" >}}) - {{< issue 414 >}} +- **NOWEB** - fix `rate-overlimit` error on groups API {{< issue 462 >}} +- Add pagination to [**👥 Get Groups API**]({{< relref "/docs/how-to/groups#get-all-groups" >}}) +- Add [**👥 Refresh Groups API**]({{< relref "/docs/how-to/groups#refresh-groups" >}}) + +`2024.12.2` + +- **NOWEB** - attempt #2 to fix missing messages {{< issue 671 >}} + +`2024.12.1` + +- **WEBJS** - fix get channel info by id {{< issue 682 >}} +- **WEBJS** - fix channel messages {{< issue 683 >}} + +### 2024.11 + +`2024.11.11` + +- **NOWEB** - fix 403 on media message {{< issue 667 >}} +- **WEBJS** - fix channels list and message {{< issue 664 >}} + +`2024.11.10` + +- **WEBJS** - fix empty groups and participants {{< issue 670 >}} {{< issue 674 >}} + +`2024.11.9` + +- **NOWEB** - attempt to fix missing messages {{< issue 671 >}} + +`2024.11.8` + +- **WEBJS** - Fix QR code (set `WAHA_WEBJS_CACHE_TYPE=none` by default) - {{< issue 659 >}} + +`2024.11.7` + +- **WEBJS** - Add `WAHA_WEBJS_CACHE_TYPE=none` - ability to disable cache for `WEBJS` engine {{< issue 653 >}}, {{< issue 654 >}} + - [**⚙️ Configuration - WEBJS**]({{< relref "/docs/how-to/config#webjs" >}}) + +`2024.11.6` + +- Fix **WAHA Core** version {{< issue 645 >}} + +`2024.11.5` + +- Add [**📊 Dashboard - Event Monitor**]({{< relref "dashboard#event-monitor" >}}) - observe your events in real-time! +- All [**🔄 Webhooks**]({{< relref "events#webhooks" >}}) features in **WAHA Core** version now: Retries, HMAC, Custom Headers! +- [**🔄 Websockets**]({{< relref "events#websockets" >}}) supports all events now {{< issue 535 >}} +- [**💬 Chats** - **Pin, Unpin message**]({{< relref "/docs/how-to/chats#pin-message" >}}) {{< issue 613>}} + - **WEBJS**, **NOWEB** +- **NOWEB** - fix `me.pushName` after authentication {{< issue 409 >}} +- Add `engine.event` for debug and troubleshooting + +`2024.11.4` + +- **NOWEB** - fix many contacts send status issues {{< issue 390 >}}, {{< issue 413 >}} +- **NOWEB** - `contacts` list for [**🟢 Status (aka Stories) API**]({{< relref "docs/how-to/status" >}}) is not required anymore +- **WEBJS** - fix **HTTP ERROR 429** {{}} + +`2024.11.3` + +- add `linkPreview` flag in `POST /api/sendText` to disable generating preview for links {{< issue 596 >}}, {{< issue 598 >}} +- Fix "Sqlite: attempt to write to read only database" error {{< issue 628 >}} +- Fix `POST /api/sendVideo` - "TargetCloseError: Protocol error" {{< issue 629 >}} + +`2024.11.2` + +- **WEBJS** - fix cases when it stops receiving events (message, message.ack, etc) + +`2024.11.1` + +- Create, Update and Delete [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) - {{< issue 607 >}} + - **WEBJS**, **NOWEB** +- **WEBJS** - Add [**🟢 Status (aka Stories) API**]({{< relref "docs/how-to/status" >}}) + - **NOWEB** related issues: {{< issue 390 >}}, {{< issue 413 >}}. You can **WEBJS** for now to handle such cases for now. +- **NOWEB** + **MongoDB** - fix double message issue - {{< issue 623 >}} + +### 2024.10 + +`2024.10.13` + +- **NOWEB** - fix waves issue on voice message {{< issue 621 >}} +- Fix `GET /api/messages` limit {{< issue 620 >}} + +`2024.10.12` + +- **WEBJS** - fix `FAILED` session (remove `--single-process`) + +`2024.10.11` + +- **WEBJS** + **MongoDB** - Fix `SingletonLock: File exists` error on launch + +`2024.10.10` + +- **WEBJS** - Update puppeter and Chrome version +- **WEBJS** - Set window size to 1280x720 +- **WEBJS** - Fix `SingletonLock: File exists` error on launch + +`2024.10.9` + +- Add pagination and filters to [**💬 Chats** - **Get messages from chat**]({{< relref "/docs/how-to/chats#get-messages" >}}) + - **WEBJS** can return messages by a single chat + - **NOWEB** can return messages by a chat or `chatId=all` + - {{< issue 140 >}}, {{< issue 449 >}}, {{< issue 458 >}} +- Add [**💬 Chats** - **Get message by id**]({{< relref "/docs/how-to/chats#get-message-by-id" >}}) + - `GET /api/{session}/chats/{chatId}/messages/{messageId}` + - {{< issue 159 >}}, {{< issue 484 >}} +- Add [**💬 Chats** - Pagination]({{< relref "/docs/how-to/chats#pagination" >}}) + - {{< issue 371 >}} +- Add [**👤 Contacts** - Pagination]({{< relref "/docs/how-to/contacts#pagination" >}}) + - {{< issue 371 >}} +- Add [**💬 Chats** - Unread Chat]({{< relref "/docs/how-to/chats#unread-chat" >}}) + - `POST /api/{session}/chats/{chatId}/unread` + - **WEBJS**, **NOWEB** + - {{< issue 498 >}} +- **NOWEB** - Fix `/archive` and `/unarchive` chats - [**💬 Chats** - Archive Chat]({{< relref "/docs/how-to/chats#archive-chat" >}}) + - {{< issue 445 >}} +- Remove the device from **Connected Devices** on [**🖥️ Session Logout**]({{< relref "/docs/how-to/sessions#logout-session" >}}) + - **WEBJS**, **NOWEB** + - {{< issue 148 >}}, {{< issue 327 >}}, {{< issue 194 >}}, {{< issue 211 >}} + +`2024.10.8` + +- Add `WAHA_LOCAL_STORE_BASE_DIR` to allow overriding the base directory for local storage [#597](https://github.com/devlikeapro/waha/issues/597) + +`2024.10.7` + +- **WAHA Core** - fix webhooks issue [#595](https://github.com/devlikeapro/waha/issues/595) + +`2024.10.6` + +- **WEBJS** + **MongoDB** - reduce CPU usage + +`2024.10.5` + +- Add **Send Buttons** API `POST /api/sendButtons` - [$544](https://github.com/devlikeapro/waha/issues/544) + - [**📤 Send messages** - Send Buttons]({{}}) + - **NOWEB** +- Add **forward message** API `POST /api/forwardMessage` - [#158](https://github.com/devlikeapro/waha/issues/158) + - [**📤 Send messages** - Forward Message]({{}}) + - **WEBJS**, **NOWEB** +- Fix sessions stuck in `STARTING` on container restart - [#586](https://github.com/devlikeapro/waha/issues/586) +- Add `WAHA_AUTO_START_DELAY_SECONDS=0` environment variable so you can control the delay between sessions + - [**⚙️ Configuration** - Sessions]({{}}) +- Track session status and do not restart it - [#491](https://github.com/devlikeapro/waha/issues/491) +- Add workers environment variables: `WAHA_WORKER_ID`, `WAHA_WORKER_RESTART_SESSIONS` +- Add request id in webhooks headers and logs [#580](https://github.com/devlikeapro/waha/issues/580) + - [**🔄 Webhooks** - Headers]({{< relref "events#headers" >}}) +- Add `policy` for webhook retries [#587](https://github.com/devlikeapro/waha/issues/587) + - [**🔄 Webhooks** - Headers]({{< relref "events#retries" >}}) + +`2024.10.4` + +- **NOWEB** - send video note via `POST /api/sendVideo` via `asNote: true` +- **NOWEB** - handle "sent by advertisement" message properly [#567](https://github.com/devlikeapro/waha/issues/567) +- **NOWEB** + **MongoDB** - save auth data when stopping session (and container) + +`2024.10.3` + +- **WEBJS** + **MongoDB** - handle removing temp folder with retries +- **WEBJS** - add more logs for state changes to help debugging + +`2024.10.2` + +- 📢 **WEBJS** + **MongoDB** setup - handle disconnection properly (it stop saving auth data if connection to mongodb lost) + +`2024.10.1` - [**Release Notes**]({{< relref "/blog/waha-2024-10" >}}) + +- Receive **media** now available in **WAHA Core** version! + - [**📥 Receive messages** - Files]({{}}) +- Add `PORT` environment variable for Heroku deployment - [#555](https://github.com/devlikeapro/waha/issues/555) +- Add `WAHA_BASE_URL` environment variable to set the base URL for the server for `media.url` links +- **WEBJS** - Add `message.waiting` event for encrypted but not yet decrypted messages [#554](https://github.com/devlikeapro/waha/issues/554) + - [**🔄 Webhooks** - message.waiting]({{< relref "events#messagewaiting" >}}) + - [https://faq.whatsapp.com/3398056720476987](https://faq.whatsapp.com/3398056720476987) +- **WEBJS** - handle connectivity issues better, restart client if required [#552](https://github.com/devlikeapro/waha/issues/552) +- Use `axios` as default library for sending webhooks - solve bad webhooks performance issues for many sessions installation. +- Handle webhooks retries properly in **WAHA Plus** version (using `axios`) + +### 2024.9 + +`2024.9.6` + +- **NOWEB** - set session presence (`online|offline`) at the start - [#412](https://github.com/devlikeapro/waha/issues/412) + - Affects notifications on your phone (if it's `online` - you won't get in-app notifications on your device) +- **WEBJS**, **NOWEB** - fix auto restart logic bug +- **WEBJS** - support pairing via code `POST /api/{session}/auth/request-code` + - Read more [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions#get-pairing-code" >}}) +- Retrieve engine info only on detailed `GET /api/sessions/{name}` +- Check session's status before performing the request in most endpoints +- **Dashboard** - add login via **QR** and **Code** auth flows +- **Dashboard, API** - Add `me` for `STOPPED` sessions (account phone number, push name) +- **Dashboard** - Hide duplicated sessions flag for multiple servers setup (match by `session.name+me.id`) + +`2024.9.5` + +- **NOWEB** - fix memory leak and performance problems [#533](https://github.com/devlikeapro/waha/issues/533) +- **WEBJS** - reduce memory usage for chrome/chromium for ~40MB per session +- Adjust error message for WAHA Core when session `STOPPED` [#538](https://github.com/devlikeapro/waha/issues/538) +- Removed `VENOM` engine completely +- Add special `/api/server/debug/heapsnapshot` to get heap dump for Node.js by `WAHA_DEBUG_MODE=True` + +`2024.9.4` + +- Fix empty config sessions operations (`Session not found`) + +`2024.9.3` + +- **NOWEB** - fix restarting issue when websocket is not connected yet (WebSocket was closed before the connection was established) + +`2024.9.2` + +- **NOWEB** - fix error on incoming messages - [#521](https://github.com/devlikeapro/waha/issues/521) + +`2024.9.1` - [**Release Notes**]({{< relref "/blog/waha-2024-9" >}}) + +- Add support for **S3** to store media file - [#353](https://github.com/devlikeapro/waha/issues/353) + - Read more [**🗄️ Storages**]({{< relref "/docs/how-to/storages" >}}) +- Add more granular API for [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) + - Dedicated `create, update, delete, start, stop, logout, restart` actions! + - The old API is working the same way as before for backward compatibility, but marked as **Deprecated** + - Related issues: [#435](https://github.com/devlikeapro/waha/issues/435), [#480](https://github.com/devlikeapro/waha/issues/480) +- Add ability to add your [**Metadata**]({{< relref "/docs/how-to/sessions#metadata" >}}) to a session [#443](https://github.com/devlikeapro/waha/issues/443). + - `metadata` field available in: + - [List Sessions]({{< relref "/docs/how-to/sessions#list-sessions" >}}) and [Get Session]({{< relref "/docs/how-to/sessions#get-session" >}}) responses + - [**🔄 Webhooks**]({{< relref "events#metadata" >}}) events + - [**📊 Dashboard**]({{< relref "dashboard" >}}) for view, and search sessions by metadata +- Add **Bulk Operations** (start, restart, etc.) for [**📊 Dashboard**]({{< relref "dashboard" >}}) - [#438](https://github.com/devlikeapro/waha/issues/438) +- Add environment variables on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) - [#319](https://github.com/devlikeapro/waha/issues/319) +- Add [**🔄 Webhooks - Custom Headers**]({{< relref "/docs/how-to/events#custom-headers" >}}) on [**📊 Dashboard**]({{< relref "/docs/how-to/dashboard" >}}) +- Add `GET /api/server/version` and `/api/server/environment` endpoints + - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) +- Validate API request on `/api/sessions/*` endpoints - [#470](https://github.com/devlikeapro/waha/issues/470) + - 📢 **Requires attention** - make sure you're sending the right requests +- Add `POST /api/sendSeen` documentation and correct swagger spec [#485](https://github.com/devlikeapro/waha/issues/485) +- Add `GET /api/server/status` endpoint to **get server uptime** - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) +- Add `POST /api/server/stop` endpoint to **restart** server - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) +- Add `WHATSAPP_API_SCHEMA=http` environment variable so you can get the right `media.url` link +- Add `media.error` to messages with media and error - [#510](https://github.com/devlikeapro/waha/issues/510) +- Add `reply_to` field for text and media (image, files, etc) messages - [#503](https://github.com/devlikeapro/waha/issues/503) + - [**📤 Send messages** - reply_to]({{}}) +- Add `replyTo` field for receiving message - [#506](https://github.com/devlikeapro/waha/issues/506) + - [**📥 Receive messages** - replyTo]({{}}) +- Update **NOWEB** engine to the latest upstream changes + +### 2024.8 + +`2024.8.5` + +- **NOWEB** - ⚠️ urgent fix [#511](https://github.com/devlikeapro/waha/issues/511) + +`2024.8.4` + +- **WEBJS** - fix get `GET /api/{session}/chats?limit=1` "Cannot read properties of undefined (reading 'getChats')" - + [#486](https://github.com/devlikeapro/waha/issues/486) +- **NOWEB** - fix sticker download - [#504](https://github.com/devlikeapro/waha/issues/504) + +`2024.8.3` + +- fix restart container with **NOWEB** engine [#483](https://github.com/devlikeapro/waha/issues/483) +- fix " this.logger.info is not a function" in swagger plus [#496](https://github.com/devlikeapro/waha/issues/496) + +`2024.8.2` + +- fix flaky **WEBJS** engine issues (`Failed to add page binding with name ...`) +- **WEBJS** + **MongoDB** - switch to native `zip` and `unzip` binaries [#465](https://github.com/devlikeapro/waha/issues/465) + - If you're not using official docker image install `zip` and `unzip` AND set `WAHA_ZIPPER=ZIPUNZIP` env variable. +- Add `WAHA_HTTP_LOG_LEVEL=info` variable to control `request completed` log level - [#466](https://github.com/devlikeapro/waha/issues/466) - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) + +`2024.8.1` - [**Release Notes**]({{< relref "/blog/waha-2024-8" >}}) + +- Add [**🏷️ Labels**]({{< relref "docs/how-to/labels" >}}) support [#318](https://github.com/devlikeapro/waha/issues/318) +- Add [**📞 Calls**]({{< relref "docs/how-to/calls" >}}) events [#307](https://github.com/devlikeapro/waha/issues/307) +- Add [**chat.archive**]({{< relref "docs/how-to/events#chatarchive" >}}) event [#434](https://github.com/devlikeapro/waha/issues/434) +- Add [**Archive and Unarchive chat endpoints**]({{< relref "docs/how-to/chats" >}}) [#434](https://github.com/devlikeapro/waha/issues/434) +- Add "sessions.name" index for MongoDB storage [#447](https://github.com/devlikeapro/waha/issues/447) +- Add `WHATSAPP_API_KEY_EXCLUDE_PATH` to exclude URI from key auth [#451](https://github.com/devlikeapro/waha/issues/451) - [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) +- Add `GET /ping` endpoint to just touch the service (no checks like in `GET /health` is done during that) - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}) + +--- + +### 2024.7 + +- `2024.7.7` - **WEBJS** + **MongoDB** fix - `unexpected end of file` [#457](https://github.com/devlikeapro/waha/issues/457) +- `2024.7.6` - **WEBJS** restart fix [#444](https://github.com/devlikeapro/waha/issues/444) +- `2024.7.5` - [**📰 WhatsApp Channels**]({{< relref "/docs/how-to/channels" >}}) +- `2024.7.4` - **NOWEB** fix profile picture [#422](https://github.com/devlikeapro/waha/issues/422) +- `2024.7.3` - added JSON logging format - [**🔍 Observability**]({{< relref "/docs/how-to/observability" >}}). +- `2024.7.2` - **WEBJS** create group fix [#416](https://github.com/devlikeapro/waha/issues/416) +- `2024.7.1` - **WEBJS** urgent update [#399](https://github.com/devlikeapro/waha/issues/399) + +--- + +### 2024.6 + +#### 📢 Breaking changes + +--- + +Docker image has been renamed to `devlikeapro/waha` and `devlikeapro/waha-plus`! + +- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#docker-images" >}}) +- Build: `2024.6.2` + +--- + +**_🎉 New_** + +--- + +Starting `2026.6.1` we publish images with `{version}` tag, so you can pin the version you want to use. + +`devlikeapro/waha-plus:chrome-{version}` => `devlikeapro/waha-plus:chrome-2024.6.1` + +- Read more about [WAHA Docker images]({{< relref "/docs/how-to/engines#versions" >}}) +- Build: `2024.6.1` + +--- + +Added `limit` and `offset` parameters to `GET /api/{session}/chats` endpoint. + +- Read more about [Get all chats]({{< relref "/docs/how-to/chats#get-all-chats" >}}) +- Build: `2024.6.4` +- Engine: **WEBJS** +- Engine: **NOWEB** + +--- + +Added Out of the box **HTTPS Support**! + +👉 [**Step-by-step guide on how to set up HTTPS for WAHA**]({{< relref "/blog/waha-https" >}}) + +- Read more about [**🔒 Security**]({{< relref "/docs/how-to/security" >}}) +- Build: `2024.6.5` +- Issue: [#42](https://github.com/devlikeapro/waha/issues/42) +- Issue: [#369](https://github.com/devlikeapro/waha/issues/369) + +--- + +Add [Websockets](({{< relref "/docs/how-to/events#websockets" >}})) support! + +- Read more about [Websockets]({{< relref "/docs/how-to/events#websockets" >}}) +- Build: `2024.6.7` + +--- + +**🎉 New - NOWEB** + +--- + +You asked it, we did it - **contacts, chats, and messages** endpoints are now available in **NOWEB** engine! +Please make sure to [Enable NOWEB Store]({{< relref "/docs/engines/noweb#store" >}}) before using these endpoints. + +- Build: `2024.6.3` +- Engine: **NOWEB** +- [Read more about NOWEB Store]({{< relref "/docs/engines/noweb#store" >}}) +- Issue [#169](https://github.com/devlikeapro/waha/issues/169) +- Issue [#206](https://github.com/devlikeapro/waha/issues/206) +- Issue [#217](https://github.com/devlikeapro/waha/issues/217) +- Issue [#322](https://github.com/devlikeapro/waha/issues/322) +- Issue [#339](https://github.com/devlikeapro/waha/issues/339) + +--- + +Generate thumbnail preview for video and image messages in **NOWEB** engine. + +- Build: `2024.6.3` +- Engine: **NOWEB** + +--- + +Fix sending poll response in **NOWEB** engine. + +- Build: `2024.6.1` +- Engine: **NOWEB** +- Issue: [#356](https://github.com/devlikeapro/waha/issues/356) + +--- + +Delete status endpoint - [`POST /api/{session}/status/delete`]({{}}) + +- Build: `2024.6.7` +- Engine: **NOWEB** +- Issue: [#386](https://github.com/devlikeapro/waha/issues/386) + +--- + +**🎉 New - DASHBOARD** + +--- + +Starting `2024.6.3` [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) is available in **WAHA Core** version! + +- Read more about [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) +- Build: `2024.6.3` + +--- + +Starting `2024.6.3` [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) allows connecting to **multiple WAHA instances**! + +- Read more about [WAHA Dashboard]({{< relref "/docs/how-to/dashboard" >}}) +- Build: `2024.6.3` + +--- + +**🐛 Fixes - NOWEB** + +Sender presence keeps on typing after sending message. + +- Issue: [#379](https://github.com/devlikeapro/waha/issues/379) +- Build: `2024.6.6` + +--- + +### 2024.5 + +**🎉 New** + +--- + +Added `WAHA_PRINT_QR` environment variable to control QR code printing (by default `True`). Set `WAHA_PRINT_QR=False` to disable QR code printing. + +- Read more about it on [Configuration]({{< relref "/docs/how-to/config" >}}) +- Issue: [#351](https://github.com/devlikeapro/waha/issues/351) +- Build: `2024.5.13` + +--- + +[Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) - show your own brand in the Swagger documentation! + +- Read more about [Swagger White Label]({{< relref "/docs/how-to/swagger#white-label" >}}) +- Issue: [#305](https://github.com/devlikeapro/waha/issues/305) +- Build: `2024.5.4` + +--- + +**🐛 Fixes** + +--- + +Don't allow to start two sessions with the same name. + +Before API allowed to start two sessions with the same name, which could lead to potential problems (no way to stop the first, abandoned session). + +- Issue: [#315](https://github.com/devlikeapro/waha/issues/315) +- Read more about [start a session](https://waha.devlike.pro/docs/how-to/sessions/#start) +- Build: `2024.5.3` +- Engine: **ALL** + +--- + +**🐛 Fixes - WEBJS** + +Handling rare errors in MongoDB process for saving and restoring session data. + +- Build: `2024.5.12` +- Engine: **WEBJS** +- Commit: [9c398f2](https://github.com/devlikeapro/waha-plus/commit/9c398f26f937bf0de2c43ebb1e032c7a766ca8f7) + +--- + +Fix send video issue `POST /api/sendVideo` in **WEBJS**. + +- Issue: [#321](https://github.com/devlikeapro/waha/issues/321) +- Issue: [#328](https://github.com/devlikeapro/waha/issues/328) +- Build: `2024.5.9` +- Engine: **WEBJS** + +--- + +Use local cache for **WEBJS** engine (versions file). + +- Issue: [#316](https://github.com/devlikeapro/waha/issues/316) +- Build: `2024.5.4` +- Engine: **WEBJS** + +--- + +**🐛 Fixes - NOWEB** + +Fix `message.ack` event for viewing status (`status@broadcast`) messages. + +- Issue: [#329](https://github.com/devlikeapro/waha/issues/329) +- Build: `2024.5.14` + +--- + +Auto restart **NOWEB** connection every 30 minutes. + +- Issue: [#336](https://github.com/devlikeapro/waha/issues/336) +- Build: `2024.5.14` + +--- + +Set heap memory limit to 16GB for **NOWEB** engine. + +- Issue: [#347](https://github.com/devlikeapro/waha/issues/347) +- Build: `2024.5.12` + +--- + +Add `body` to messages with caption in **NOWEB** engine. + +- Build: `2024.5.10` + +--- + +Fix "document with caption" message media issue + +- Issue: [#345](https://github.com/devlikeapro/waha/issues/345) +- Build: `2024.5.10` + +--- + +Important **NOWEB** Engine Update! +WhatsApp has deprecated the version currently being used in the NOWEB engine + +- [Read on Patreon](https://www.patreon.com/posts/important-noweb-104631614) +- [Read on Boosty](https://boosty.to/wa-http-api/posts/6ccedda7-ddae-413b-b15f-f2f22192c0d8) +- Build: `2024.5.8` +- Engine: **NOWEB** + +--- + +### 2024.4 + +**🎉 New** + +Add **WAHA Dashboard** - UI to manage your WhatsApp sessions! + +- Read more about [Dashboard]({{< relref "/docs/how-to/dashboard" >}}) + +--- + +Add `GET /api/sessions/{session}` endpoint to get information about a specific session. + +- Read more about [Get session information]({{< relref "/docs/how-to/sessions#get-session" >}}) +- Issue: [#300](https://github.com/devlikeapro/waha/issues/300) + +--- + +Implement `GET /api/contacts/profile-picture` for **NOWEB** engine. + +- Read more about [Get contact profile picture](https://waha.devlike.pro/docs/how-to/contacts/#get-contact-profile-picture) +- Issue: [#298](https://github.com/devlikeapro/waha/issues/298) + +--- + +### 2024.3 + +**🎉 New** + +--- + +Add `message.reaction` webhook in **WEBJS** and **NOWEB** engines + +- Read more about [message.reaction]({{< relref "/docs/how-to/events#messagereaction" >}}) event +- Issue: [#275](https://github.com/devlikeapro/waha/issues/275) + +👉 **NOWEB** engine note - reactions were sent in `'message'` and `'message.any'` events, not it's available **only** in `'message.reaction'`! + +--- + +Add star and unstar message endpoint `PUT /api/star` + +- Read [Star and unstar message]({{< relref "/docs/how-to/send-messages#star-and-unstar-message" >}}) documentation +- Issue: [#273](https://github.com/devlikeapro/waha/issues/240) + +--- + +Add `PUT /api/{session}/chats/{chatId}/messages/{messageId}` endpoint to **edit** the message. + +- Read more about [Edit message]({{< relref "/docs/how-to/send-messages#edit-message" >}}) +- Issue: [#241](https://github.com/devlikeapro/waha/issues/241) + +--- + +Add `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` endpoint to **delete** the message. + +- Read more about [Delete message]({{< relref "/docs/how-to/send-messages#delete-message" >}}) +- Issue: [#209](https://github.com/devlikeapro/waha/issues/209) + +--- + +Add `POST /api/sendContactVcard` support for **NOWEB** engine. + +- Read more about [Send Contact vCard]({{< relref "/docs/how-to/send-messages#send-contact-vcard" >}}) +- Issue: [#276](https://github.com/devlikeapro/waha/issues/256) + +--- + +Handles `caption` and `filename` right in `POST /api/sendFile` + +- Issue: [#94](https://github.com/devlikeapro/waha/issues/94) +- Issue: [#133](https://github.com/devlikeapro/waha/issues/133) + +--- + +Add security settings for who can send messages `PUT /api/{session}/groups/{groupId}/settings/security/messages-admin-only` + +- Read [Security - who can send messages]({{< relref "/docs/how-to/groups##security---who-can-send-messages" >}}) +- Issue: [#274](https://github.com/devlikeapro/waha/issues/274) + +--- + +Add `config.debug` field to `POST /api/sessions/start` to enable debug and verbose logs for the session. + +--- + +#### 📢 Breaking changes + +- **NOWEB** - reactions were sent in `'message'` and `'message.any'` events, not it's available **only** in `'message.reaction'`! +- Add **required body** in `PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only` endpoint. + +```json +{ + "adminsOnly": false +} +``` + +- `POST /api/sendContactVcard` doesn't work in **VENOM** anymore (use **NOWEB** engine). + +### 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/observability/) + +### 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/waha/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/waha/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/waha/issues/185) +- Add dedicated `media` field in webhook payload - now you can know which media is attached to the message. + +```json { title="message" } +{ + "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) +- Add [polls support in NOWEB engine](https://waha.devlike.pro/docs/how-to/polls) +- Add dedicated [Get QR](https://waha.devlike.pro/docs/how-to/sessions/#get-qr) endpoint! +- Support [pairing method (NOWEB)](https://waha.devlike.pro/docs/how-to/sessions/#get-pairing-code) - you can connect with a code instead of QR. +- Add string field `ackName: DEVICE|READ|...` in [message.ack payload](https://waha.devlike.pro/docs/how-to/events/#messageack) +- Support `message.ack` event webhook in **NOWEB** engine + +### 2023.8 + +August 2023 + +- Added [stories (aka status) endpoints](https://waha.devlike.pro/docs/how-to/send-messages/#send-status-aka-stories) to **NOWEB** engine! + - `POST /api/{session}/status/text|image|voice|video` - choose one that suites your! +- Added [chats endpoints](https://waha.devlike.pro/docs/how-to/chats) + - Get all chats - `GET /api/{session/chats` + - Delete chat - `DELETE /api/{session/chats/{chatId}` + - Get messages from chat - `GET /api/{session/chats/{chatId}/messages?limit=1000?downloadMedia=true` + - Clear messages in the chat `DELETE /api/{session/chats/{chatId}/messages` +- Added `downloadMedia` flag to speed up `GET /api/messages` and `GET /api/{session/chats/{chatId}/messages` performance. +- Added [set presence endpoint](https://waha.devlike.pro/docs/how-to/presence)! + - With `online` presence you can show your status as online [#121](https://github.com/devlikeapro/waha/issues/121) + - With `offline` presence you can get notifications for your device [#28](https://github.com/devlikeapro/waha/issues/28) +- Added security settings for edit group info `PUT /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.7 + +July 2023 + +- Now session can have their own [🔄 Webhooks]({{< relref "/docs/how-to/events" >}}) - + you can define webhook configuration when you start a session with `POST /api/sessions/start`! + - Add HMAC authentication for webhooks + - Configure retries + - Add you custom headers +- Added [proxy configuration](https://waha.devlike.pro/docs/how-to/config/#proxy) with supporting proxy authentication. + Thanks **puntolino** for the contribution! + You can control proxy's settings per session with `POST /api/sessions/start` or globally with environment variables. +- Added [presence information](https://waha.devlike.pro/docs/how-to/presence) - now you can get online status for + a contact by calling endpoints or receiving a webhook event! +- Now you can mention contact in groups by settings `mentions` field in `POST /api/sendText` + [read more about it in Send Messages ->]({{< relref "/docs/how-to/send-messages" >}}) + +### 2023.6 + +June 2023 + +Improvements on session management, restarting sessions and more: + +- Added `WHATSAPP_RESTART_ALL_SESSIONS=True`: Set this variable to `True` to start all **STOPPED** sessions after + container restarts. By default, this variable is set to `False`. + - Please note that this will start all **STOPPED** sessions, not just the sessions that were working before the + restart. You can maintain the session list by + using `POST /api/sessions/stop` with the `logout: True` parameter or by calling `POST /api/sessions/logout` to remove + **STOPPED** sessions. You can see all sessions, including **STOPPED** sessions, in the `GET /api/sessions/all=True` + response. +- `WHATSAPP_START_SESSION` now support more than one session! Separate session names by command, and it'll start them + ALWAYS after container restart `WHATSAPP_START_SESSION=session1,session2` +- `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. +- Added `?all=true` parameter to `GET /api/session?all=True` endpoint - it'll show you ALL session, included + **STOPPED**, so you can know which one will be restarted if you set `WHATSAPP_RESTART_ALL_SESSIONS=True` environment variable. +- Added `POST /api/sessions/logout` that allow you to logout from session - remove saved credentials. +- Added `logout` boolean parameter to `POST /api/sessions/stop` request that allow you to stop the session AND logout at + the same time. +- Added `engine` field in webhook payload + +```json { title="message" } +{ + "event": "message", + "session": "default", + "engine": "WEBJS", + "payload": {} +} +``` + +### 2023.5 + +May 2023 + +- Added new [NOWEB engine]({{< relref "/docs/how-to/engines" >}}). **NOWEB** engine does not require a browser to work + with + WhatsApp Web, it does so directly using a WebSocket. + - Less CPU and RAM usage! + - Send Locations API works! + - Send Link Preview API works! + - ⚠ Read the article before using it [How to avoid blocking ->]({{< relref "/docs/overview/how-to-avoid-blocking" >}}). + +### 2023.4 + +March 2023 + +- Add [Groups API]({{< relref "/docs/how-to/groups" >}}) +- Use Chromium by default instead of Chrome + +### 2023.1 + +January 2023 + +- Added [Contacts API]({{< relref "/docs/how-to/contacts" >}}) + - Get all contacts + - Get a contact + - Get contact "about" (status) + - Get contact profile picture + - Check number exists (is registered in WhatsApp) - works even if the number is not in the contact list + - Block and unblock contact + +### 2022.12 + +December 2023 + +- Added `GET /messages/` endpoint to get chat messages [#31](https://github.com/devlikeapro/waha/issues/31) +- Added `WHATSAPP_SWAGGER_USERNAME` and `WHATSAPP_SWAGGER_PASSWORD` to hide and protect swagger panel. + +### 2022.11 + +**Please test changes in test environment before update production!!** + +**Engine** + +1. WAHA has changed its underlying engine from Venom to Whatsapp Web.JS. It might change the response and webhook's + payloads. +2. Optimize CPU and memory consumption. + +**Requests** + +- For all `/api/sessions/` requests use `name` field instead of `sessionName`. +- For all "chatting" requests use `session` field instead of `sessionName`. + +**Sessions** + +Now you don't have to scan QR code each time you run WAHA, WAHA saves it for you! Available only in Plus version. + +**Authentication** + +Now you can authenticate all requests for WAHA - use `WHATSAPP_API_KEY=secret` environment variable to set "secret key". + +If `WHATSAPP_API_KEY` is set - requests must have `X-Api-Key` header with `secret` value, where `secret` - any random +secret key. + +**Webhooks** + +Instead of setting each webhook via environment variables - we use two environments variables: + +- `WHATSAPP_HOOK_URL` - to set a URL +- `WHATSAPP_HOOK_EVENTS` - to set events that are sent to the URL + +**Webhook payload** + +The data for webhooks are wrapped inside a new `WAWebhook` object with `event` and `payload` fields to help you identify +which handler you should call based on `event`. + +```json { title="message.any" } +{ + "event": "message.any", + "payload": {} +} +``` diff --git a/content/docs/overview/faq.md b/content/docs/overview/faq.md index 9771d3e81..dc97ab817 100644 --- a/content/docs/overview/faq.md +++ b/content/docs/overview/faq.md @@ -1,105 +1,107 @@ ---- -title: "❓ FAQ" -description: "Answers to frequently asked questions." -lead: "Answers to frequently asked questions." -date: 2020-10-06T08:49:31+00:00 -lastmod: 2020-10-06T08:49:31+00:00 -draft: false - -menu: -docs: -parent: "help" -weight: 190 -toc: true ---- - -## System Requirements -### How much CPU and Memory does WAHA need? - -WAHA has multiple [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) under the hood, and the CPU and Memory requirements change depending on the engine used. - -{{< callout context="tip" icon="outline/server" >}} -We **strongly recommend** using a VPS or server with a minimum **2CPU** and **4GB RAM** configuration for the project **even for a single session**. - -If you want to host **more sessions** - please check the numbers below -{{< /callout >}} - - -| Sessions (accounts) in the container | **WEBJS** | **NOWEB** | **GOWS** | -|--------------------------------------|:---------------:|:---------------:|:---------------:| -| 1 | 0.3CPU / 400MB | 0.1 CPU / 200MB | 0.1 CPU / 200MB | -| 10 | 3CPU / 2.5GB | 1CPU / 2GB | 0.5 CPU / 1GB | -| 50 | 15CPU / 20GB | 2CPU / 4GB | 1.5 CPU / 3GB | -| 100 | - | 4CPU / 8GB | 3-5 CPU / 5GB | -| 500 | - | - | 5-8 CPU / 25GB | - -{{< include file="content/docs/how-to/install/-the-hosting.md" >}} - -### How to horizontally scale WAHA? -You can scale WAHA horizontally by **running multiple instances of WAHA** on **different servers** -and distribute the load between them. - -{{< callout context="tip" icon="outline/rocket" >}} -Read about [**WAHA Scaling - how to handle 50+ sessions ->**]({{< relref "/blog/waha-scaling" >}}) -{{< /callout >}} - -## WAHA Plus -### What is the difference between WAHA Core and WAHA Plus? - -These are two versions of the product we build: - -**WAHA Core** -- The free and open source project available for everyone. -- Supports automating a single **WhatsApp Account** (aka [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}})) -- Sends and receives **unlimited text messages**. -- Doesn't have any built-in [🔒 Security]({{< relref "/docs/how-to/security" >}}) features, -which means you need to make sure your infrastructure is secure. - -**WAHA Plus** -- The full version available through donations -- Supports **unlimited** [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) -- Sends and receives **multimedia messages** (images, videos) -- Has built-in [🔒 Security]({{< relref "/docs/how-to/security" >}}) features - -{{< callout >}} -You can find the full comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. -{{< /callout >}} - -### What is the difference between Core, Plus and PRO Tiers? - -- **Core Tier** - it's free tier (aka community edition) that you're already in, and you can use **WAHA Core** for free! -- **Plus Tier** - allows you to have access to **WAHA Plus** docker image and enjoy all features available in the product! -- **PRO Tier** - also gives you access to **WAHA Plus** image AND **WAHA Plus Source Code** on [GitHub](https://github.com/devlikeapro/waha-plus). Also our team will pay additional attentions to your requests 🫶 - - [waha-plus](https://github.com/devlikeapro/waha-plus) - - [gow-plus](https://github.com/devlikeapro/gows-plus) - - [dashboard](https://github.com/devlikeapro/waha-hub) - -{{< callout >}} -You can find the full tier comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. -{{< /callout >}} - - -### Is it one time donation? - -According to [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page: -> It doesn't require monthly subscriptions, once installed on your server - it always works! -> **(until WhatsApp made backward-incompatible changes, and you have to update the image, or you need to reinstall it on new server )** - -Meaning that the installed WAHA will continue to work even after you subscription got expired. -Unfortunately, WhatsApp makes backward incompatible changes and when it happens we need to keep up and update the docker image, -which means that you need to update your WAHA as well, otherwise it won't work 😔 -It happens like every **3-6 months** or so and depends on your country as well. - -In order to update WAHA you need to have **active docker key** -(which you get on WAHA [Patron Portal](https://portal.devlike.pro)), meaning at this time you need to be active subscriber. - -In summary, it's not one time purchase, it's rather **"every 3-6 months" purchase** to get the latest update. - - -{{< callout >}} -💡 We recommend staying subscribing, so we can keep developing awesome product for you! -Your support the only reason why we're able to publish and maintain the project 🫶 - -You can find the full comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. -{{< /callout >}} - +--- +title: "❓ FAQ" +description: "Answers to frequently asked questions." +lead: "Answers to frequently asked questions." +date: 2020-10-06T08:49:31+00:00 +lastmod: 2020-10-06T08:49:31+00:00 +draft: false + +menu: +docs: +parent: "help" +weight: 190 +toc: true +--- + +## System Requirements + +### How much CPU and Memory does WAHA need? + +WAHA has multiple [**🏭 Engines**]({{< relref "/docs/how-to/engines" >}}) under the hood, and the CPU and Memory requirements change depending on the engine used. + +{{< callout context="tip" icon="outline/server" >}} +We **strongly recommend** using a VPS or server with a minimum **2CPU** and **4GB RAM** configuration for the project **even for a single session**. + +If you want to host **more sessions** - please check the numbers below +{{< /callout >}} + +| Sessions (accounts) in the container | **WEBJS** | **NOWEB** | **GOWS** | +| ------------------------------------ | :------------: | :-------------: | :-------------: | +| 1 | 0.3CPU / 400MB | 0.1 CPU / 200MB | 0.1 CPU / 200MB | +| 10 | 3CPU / 2.5GB | 1CPU / 2GB | 0.5 CPU / 1GB | +| 50 | 15CPU / 20GB | 2CPU / 4GB | 1.5 CPU / 3GB | +| 100 | - | 4CPU / 8GB | 3-5 CPU / 5GB | +| 500 | - | - | 5-8 CPU / 25GB | + +{{< include file="content/docs/how-to/install/-the-hosting.md" >}} + +### How to horizontally scale WAHA? + +You can scale WAHA horizontally by **running multiple instances of WAHA** on **different servers** +and distribute the load between them. + +{{< callout context="tip" icon="outline/rocket" >}} +Read about [**WAHA Scaling - how to handle 50+ sessions ->**]({{< relref "/blog/waha-scaling" >}}) +{{< /callout >}} + +## WAHA Plus + +### What is the difference between WAHA Core and WAHA Plus? + +These are two versions of the product we build: + +**WAHA Core** + +- The free and open source project available for everyone. +- Supports automating a single **WhatsApp Account** (aka [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}})) +- Sends and receives **unlimited text messages**. +- Doesn't have any built-in [🔒 Security]({{< relref "/docs/how-to/security" >}}) features, + which means you need to make sure your infrastructure is secure. + +**WAHA Plus** + +- The full version available through donations +- Supports **unlimited** [**🖥️ Sessions**]({{< relref "/docs/how-to/sessions" >}}) +- Sends and receives **multimedia messages** (images, videos) +- Has built-in [🔒 Security]({{< relref "/docs/how-to/security" >}}) features + +{{< callout >}} +You can find the full comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. +{{< /callout >}} + +### What is the difference between Core, Plus and PRO Tiers? + +- **Core Tier** - it's free tier (aka community edition) that you're already in, and you can use **WAHA Core** for free! +- **Plus Tier** - allows you to have access to **WAHA Plus** docker image and enjoy all features available in the product! +- **PRO Tier** - also gives you access to **WAHA Plus** image AND **WAHA Plus Source Code** on [GitHub](https://github.com/devlikeapro/waha-plus). Also our team will pay additional attentions to your requests 🫶 + - [waha-plus](https://github.com/devlikeapro/waha-plus) + - [gow-plus](https://github.com/devlikeapro/gows-plus) + - [dashboard](https://github.com/devlikeapro/waha-hub) + +{{< callout >}} +You can find the full tier comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. +{{< /callout >}} + +### Is it one time donation? + +According to [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page: + +> It doesn't require monthly subscriptions, once installed on your server - it always works! +> **(until WhatsApp made backward-incompatible changes, and you have to update the image, or you need to reinstall it on new server )** + +Meaning that the installed WAHA will continue to work even after you subscription got expired. +Unfortunately, WhatsApp makes backward incompatible changes and when it happens we need to keep up and update the docker image, +which means that you need to update your WAHA as well, otherwise it won't work 😔 +It happens like every **3-6 months** or so and depends on your country as well. + +In order to update WAHA you need to have **active docker key** +(which you get on WAHA [Patron Portal](https://portal.devlike.pro)), meaning at this time you need to be active subscriber. + +In summary, it's not one time purchase, it's rather **"every 3-6 months" purchase** to get the latest update. + +{{< callout >}} +💡 We recommend staying subscribing, so we can keep developing awesome product for you! +Your support the only reason why we're able to publish and maintain the project 🫶 + +You can find the full comparison table on [**🎁 Support Us**]({{< relref "/support-us#donations" >}}) page. +{{< /callout >}} diff --git a/content/docs/overview/how-to-avoid-blocking.md b/content/docs/overview/how-to-avoid-blocking.md index d0307a3b4..60b0ae41c 100644 --- a/content/docs/overview/how-to-avoid-blocking.md +++ b/content/docs/overview/how-to-avoid-blocking.md @@ -1,92 +1,90 @@ ---- -title: "⚠️ How to Avoid Blocking" -description: "How to Avoid Blocking From Whatsapp" -date: 2020-11-12T13:26:54+01:00 -lastmod: 2020-11-12T13:26:54+01:00 -draft: false - -menu: - docs: - parent: "help" -weight: 103 -toc: true ---- - -How to Avoid Blocking in WhatsApp when developing bots. - -It's important to keep in mind that WhatsApp has strict policies in place to prevent spamming and abuse of their -platform. - -If you're developing a bot for WhatsApp, it's crucial to follow these guidelines to avoid getting blocked. - -## Guidelines to Follow - -### 1. Only Reply to Messages - -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 lead to your bot being blocked. Make -sure to only send relevant and useful information to the user. -Additionally, do not send too many messages at once, as this can also trigger spam filters. - -### 3. Other Considerations - -There are other guidelines to follow when developing a bot for WhatsApp, such as avoiding the use of banned words and -not sharing sensitive or inappropriate content. -Make sure to read WhatsApp's policies thoroughly to ensure that your bot complies with all of their rules. - -## How to Process Messages - -When processing messages in your bot, it's important to follow certain steps to avoid being flagged as spam. -Here's a recommended process to follow: - -1. **Send seen** before processing the message. This can be done by sending a `POST /api/sendSeen/` request to - the WAHA API. - -2. **Start typing** before sending a message and wait for a random interval depending on the size of the message. This can - be done by sending a `POST /api/startTyping/` request. - -3. **Stop typing** before sending the message. This can be done by sending a `POST /api/stopTyping/` request. - -4. **Send the text message** using the `POST /api/sendText` request. - -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 Avoid Getting Banned - -WhatsApp knows that it's uncommon for someone to send so many messages or bulk messages to people they've never talked to before, so it is considered spam/marketing junk pretty quickly. Here are some tips before sending a message to WhatsApp: - -**Dos and Don'ts:** - -1. Important: Do NOT send messages which get you reported. As long as you don't get reports from users who you sent a message to, 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 in 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 to someone without 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's consent. - -**Keep in mind:** - -1. For every message you send to someone who doesn't have your number in their contact list, they are asked if it's spam. Being tagged as spam a few times (5-10) will get you banned. -2. WhatsApp records every movement you make; you can even check the logs when sending a simple support email. It contains all kinds of information, so 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 it 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 an 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 do this 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). - - +--- +title: "⚠️ How to Avoid Blocking" +description: "How to Avoid Blocking From Whatsapp" +date: 2020-11-12T13:26:54+01:00 +lastmod: 2020-11-12T13:26:54+01:00 +draft: false + +menu: + docs: + parent: "help" +weight: 103 +toc: true +--- + +How to Avoid Blocking in WhatsApp when developing bots. + +It's important to keep in mind that WhatsApp has strict policies in place to prevent spamming and abuse of their +platform. + +If you're developing a bot for WhatsApp, it's crucial to follow these guidelines to avoid getting blocked. + +## Guidelines to Follow + +### 1. Only Reply to Messages + +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 lead to your bot being blocked. Make +sure to only send relevant and useful information to the user. +Additionally, do not send too many messages at once, as this can also trigger spam filters. + +### 3. Other Considerations + +There are other guidelines to follow when developing a bot for WhatsApp, such as avoiding the use of banned words and +not sharing sensitive or inappropriate content. +Make sure to read WhatsApp's policies thoroughly to ensure that your bot complies with all of their rules. + +## How to Process Messages + +When processing messages in your bot, it's important to follow certain steps to avoid being flagged as spam. +Here's a recommended process to follow: + +1. **Send seen** before processing the message. This can be done by sending a `POST /api/sendSeen/` request to + the WAHA API. + +2. **Start typing** before sending a message and wait for a random interval depending on the size of the message. This can + be done by sending a `POST /api/startTyping/` request. + +3. **Stop typing** before sending the message. This can be done by sending a `POST /api/stopTyping/` request. + +4. **Send the text message** using the `POST /api/sendText` request. + +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 Avoid Getting Banned + +WhatsApp knows that it's uncommon for someone to send so many messages or bulk messages to people they've never talked to before, so it is considered spam/marketing junk pretty quickly. Here are some tips before sending a message to WhatsApp: + +**Dos and Don'ts:** + +1. Important: Do NOT send messages which get you reported. As long as you don't get reports from users who you sent a message to, 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 in 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 to someone without 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's consent. + +**Keep in mind:** + +1. For every message you send to someone who doesn't have your number in their contact list, they are asked if it's spam. Being tagged as spam a few times (5-10) will get you banned. +2. WhatsApp records every movement you make; you can even check the logs when sending a simple support email. It contains all kinds of information, so 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 it 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 an 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 do this 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). diff --git a/content/docs/overview/introduction.md b/content/docs/overview/introduction.md index e3f0bc862..caf2b35c6 100644 --- a/content/docs/overview/introduction.md +++ b/content/docs/overview/introduction.md @@ -1,41 +1,41 @@ ---- -title: "📖 Introduction" -description: "WAHA - WhatsApp API that you can install on your own server and run in less than 5 minutes!" -lead: "" -date: 2020-10-06T08:48:57+00:00 -lastmod: 2020-10-06T08:48:57+00:00 -draft: false - -menu: -docs: -parent: "overview" -weight: 101 -toc: true ---- -**WAHA** - WhatsApp HTTP API that you can install on your own server and run in less than 5 minutes! - -
- -
- -## Get started - -{{< callout context="tip" icon="outline/rocket" >}} -Run **WhatsApp API** in less than 5 minutes! - -[**⚡ Quick Start**]({{< relref "quick-start" >}}) -will guide you through the necessary steps to successfully send your first text message using WhatsApp API. -{{< /callout >}} - - -{{< callout context="info" title="Disclaimer" icon="outline/gavel" >}} -This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at [whatsapp.com](https://whatsapp.com). - -"WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners. Also, it is not guaranteed that you will not be blocked by using this method. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe. - -For any businesses looking to integrate with WhatsApp for critical applications, we highly recommend using officially supported methods, such as Twilio's solution or other alternatives. You might also consider [the official API ->](https://developers.facebook.com/docs/whatsapp/). -{{< /callout >}} - -## Quick Links - -{{< include file="content/docs/overview/quick-start/links.md" >}} +--- +title: "📖 Introduction" +description: "WAHA - WhatsApp API that you can install on your own server and run in less than 5 minutes!" +lead: "" +date: 2020-10-06T08:48:57+00:00 +lastmod: 2020-10-06T08:48:57+00:00 +draft: false + +menu: +docs: +parent: "overview" +weight: 101 +toc: true +--- + +**WAHA** - WhatsApp HTTP API that you can install on your own server and run in less than 5 minutes! + +
+ +
+ +## Get started + +{{< callout context="tip" icon="outline/rocket" >}} +Run **WhatsApp API** in less than 5 minutes! + +[**⚡ Quick Start**]({{< relref "quick-start" >}}) +will guide you through the necessary steps to successfully send your first text message using WhatsApp API. +{{< /callout >}} + +{{< callout context="info" title="Disclaimer" icon="outline/gavel" >}} +This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at [whatsapp.com](https://whatsapp.com). + +"WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners. Also, it is not guaranteed that you will not be blocked by using this method. WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered totally safe. + +For any businesses looking to integrate with WhatsApp for critical applications, we highly recommend using officially supported methods, such as Twilio's solution or other alternatives. You might also consider [the official API ->](https://developers.facebook.com/docs/whatsapp/). +{{< /callout >}} + +## Quick Links + +{{< include file="content/docs/overview/quick-start/links.md" >}} diff --git a/content/docs/overview/quick-start/index.md b/content/docs/overview/quick-start/index.md index 553d3dc8d..777bc6e14 100644 --- a/content/docs/overview/quick-start/index.md +++ b/content/docs/overview/quick-start/index.md @@ -1,212 +1,219 @@ ---- -title: "⚡ Quick Start" -description: "One page summary of how to start WhatsApp API." -lead: "Step-by-Step guide to send your first message via WhatsApp API." -date: 2020-11-16T13:59:39+01:00 -lastmod: 2020-11-16T13:59:39+01:00 -draft: false - -parent: "overview" -weight: 102 -toc: true ---- - -{{< imgo src="waha-first-message.jpg" full="false" >}} - -## Step-by-Step guide -On this page, you're going to install and run WAHA, -authenticate the client using a QR code, -and send **your first message** to WhatsApp using the API! - -We will guide you through the necessary steps to successfully send your first text message using the WhatsApp API. - -
- Are you a visual learner? - -We've got you covered!
-Watch the video tutorial below to see how to send your first message using WAHA - -
- -
-
- - -## Step 0. Requirements - -WAHA works on top of **Docker**, that's the only thing you'll need! -
- logo -
- -👉 Please follow the - - Docker official guides to install it on Linux, Windows, and macOS - - -{{< details "Why Docker?" >}} -Docker makes it easy to ship an **all-in-one solution** with the runtime and dependencies. -You don't have to worry about language-specific libraries or Chrome installation. - -Also, Docker makes installation and update processes so simple, just one command! -{{< /details >}} - -## Step 1. Download image - -Assuming you have installed [Docker](https://docs.docker.com/get-docker/), let's download the image! -Follow the instructions below: - -{{< include file="content/docs/how-to/install/download-image.md" >}} - -## Step 2. Run WAHA - -Run WhatsApp HTTP API: - -```bash -docker run -it -v $(pwd)/sessions:/app/.sessions --rm -p 3000:3000 --name waha devlikeapro/waha - -# It prints logs and the last line must be -# WhatsApp API is running on: http://[::1]:3000 -``` - -{{< callout context="danger" title="Not a Production-Ready Installation!" icon="outline/shield-check" >}} -☝️ The above command is meant only for **initial testing**, not for production use. - -Please follow the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide to set up a secure WAHA instance -after you finish the quick start guide. - -{{< /callout >}} - -👉 Now, open the [📊 Dashboard]({{< relref "/docs/how-to/dashboard" >}}) at - -http://localhost:3000/dashboard - - -You'll see the WAHA Dashboard: - -![Dashboard](dashboard.png) - -## Step 3. Start a new session - -To start a new session, you should have your mobile phone with the **WhatsApp application** installed close to you. - -Here is the - -official instruction on WhatsApp site - -on how to log in. - -Now you can start the **default** session (current status should be `STOPPED`). - -You can leave all configuration parameters as default: -![alt](dashboard-start-session.png) - -## Step 4. Get and scan QR - -Wait until the session status is `SCAN_QR` and click on the "camera" icon: -
-![alt](dashboard-qr.png) -👉 If instead of the QR you see **Click to reload QR** - **stop** the session and **start** it again. - -
- -You'll see the QR code from the WhatsApp Web app. Now get **your phone** with the WhatsApp application installed and **scan the QR**: -![alt](whatsapp-link-devices.jpeg) - -The session status will move to `WORKING` status: -![alt](dashboard-working.png) - -## Step 5. Send a text message - -Now we're ready to send the first messages to WhatsApp via the API! - -Replace `123123` with **your phone number without +**, but keep the `@c.us` part: -{{< tabs "send-text-message" >}} - -{{< tab "curl" >}} -```sh -curl -X 'POST' \ - 'http://localhost:3000/api/sendText' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "chatId": "123123@c.us", - "text": "Hi there!", - "session": "default" -}' -``` -{{< /tab >}} - -{{< tab "JavaScript" >}} -```js -fetch('http://localhost:3000/api/sendText', { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - chatId: "123123@c.us", - text: "Hi there!", - session: "default" - }) -}) -.then(response => response.json()) -.then(data => console.log(data)) -.catch(error => console.error('Error:', error)); -``` -{{< /tab >}} - -{{< tab "Python" >}} -```python -import requests - -url = "http://localhost:3000/api/sendText" -headers = { - "Accept": "application/json", - "Content-Type": "application/json" -} -data = { - "chatId": "123123@c.us", - "text": "Hi there!", - "session": "default" -} - -response = requests.post(url, json=data, headers=headers) -print(response.json()) -``` -{{< /tab >}} - -{{< /tabs >}} - -As alternative to `curl`, you can use [**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}) for that. - -Open Swagger at - -http://localhost:3000/#/chatting -, scroll down to **chatting** section. - -- Find `POST /api/sendText` endpoint and expand it -- Click **Try it out** -- Replace `123123@c.us` with **your phone number without +**, but keep `@c.us` part -- Click **Execute** - -![alt](swagger-send-text.png) - -## What's next? - -{{< include file="content/docs/how-to/install/-the-hosting.md" >}} - -{{< callout context="tip" icon="outline/robot" title="Build Fast" >}} -Ask [**🤖 WAHA GPT**]({{< relref "/gpt" >}}) to help you build **{python|js|php}** code! -{{< /callout >}} - -{{< include file="content/docs/overview/quick-start/links.md" >}} +--- +title: "⚡ Quick Start" +description: "One page summary of how to start WhatsApp API." +lead: "Step-by-Step guide to send your first message via WhatsApp API." +date: 2020-11-16T13:59:39+01:00 +lastmod: 2020-11-16T13:59:39+01:00 +draft: false + +parent: "overview" +weight: 102 +toc: true +--- + +{{< imgo src="waha-first-message.jpg" full="false" >}} + +## Step-by-Step guide + +On this page, you're going to install and run WAHA, +authenticate the client using a QR code, +and send **your first message** to WhatsApp using the API! + +We will guide you through the necessary steps to successfully send your first text message using the WhatsApp API. + +
+ Are you a visual learner? + +We've got you covered!
+Watch the video tutorial below to see how to send your first message using WAHA + +
+ +
+
+ +## Step 0. Requirements + +WAHA works on top of **Docker**, that's the only thing you'll need! + +
+ logo +
+ +👉 Please follow the + +Docker official guides to install it on Linux, Windows, and macOS + + +{{< details "Why Docker?" >}} +Docker makes it easy to ship an **all-in-one solution** with the runtime and dependencies. +You don't have to worry about language-specific libraries or Chrome installation. + +Also, Docker makes installation and update processes so simple, just one command! +{{< /details >}} + +## Step 1. Download image + +Assuming you have installed [Docker](https://docs.docker.com/get-docker/), let's download the image! +Follow the instructions below: + +{{< include file="content/docs/how-to/install/download-image.md" >}} + +## Step 2. Run WAHA + +Run WhatsApp HTTP API: + +```bash +docker run -it -v $(pwd)/sessions:/app/.sessions --rm -p 3000:3000 --name waha devlikeapro/waha + +# It prints logs and the last line must be +# WhatsApp API is running on: http://[::1]:3000 +``` + +{{< callout context="danger" title="Not a Production-Ready Installation!" icon="outline/shield-check" >}} +☝️ The above command is meant only for **initial testing**, not for production use. + +Please follow the [**🔧 Install & Update**]({{< relref "/docs/how-to/install" >}}) guide to set up a secure WAHA instance +after you finish the quick start guide. + +{{< /callout >}} + +👉 Now, open the [📊 Dashboard]({{< relref "/docs/how-to/dashboard" >}}) at + +http://localhost:3000/dashboard + + +You'll see the WAHA Dashboard: + +![Dashboard](dashboard.png) + +## Step 3. Start a new session + +To start a new session, you should have your mobile phone with the **WhatsApp application** installed close to you. + +Here is the + +official instruction on WhatsApp site + +on how to log in. + +Now you can start the **default** session (current status should be `STOPPED`). + +You can leave all configuration parameters as default: +![alt](dashboard-start-session.png) + +## Step 4. Get and scan QR + +Wait until the session status is `SCAN_QR` and click on the "camera" icon: +
+![alt](dashboard-qr.png) +👉 If instead of the QR you see **Click to reload QR** - **stop** the session and **start** it again. + +
+ +You'll see the QR code from the WhatsApp Web app. Now get **your phone** with the WhatsApp application installed and **scan the QR**: +![alt](whatsapp-link-devices.jpeg) + +The session status will move to `WORKING` status: +![alt](dashboard-working.png) + +## Step 5. Send a text message + +Now we're ready to send the first messages to WhatsApp via the API! + +Replace `123123` with **your phone number without +**, but keep the `@c.us` part: +{{< tabs "send-text-message" >}} + +{{< tab "curl" >}} + +```sh +curl -X 'POST' \ + 'http://localhost:3000/api/sendText' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "chatId": "123123@c.us", + "text": "Hi there!", + "session": "default" +}' +``` + +{{< /tab >}} + +{{< tab "JavaScript" >}} + +```js +fetch("http://localhost:3000/api/sendText", { + method: "POST", + headers: { + "Accept": "application/json", + "Content-Type": "application/json" + }, + body: JSON.stringify({ + chatId: "123123@c.us", + text: "Hi there!", + session: "default" + }) +}) + .then((response) => response.json()) + .then((data) => console.log(data)) + .catch((error) => console.error("Error:", error)); +``` + +{{< /tab >}} + +{{< tab "Python" >}} + +```python +import requests + +url = "http://localhost:3000/api/sendText" +headers = { + "Accept": "application/json", + "Content-Type": "application/json" +} +data = { + "chatId": "123123@c.us", + "text": "Hi there!", + "session": "default" +} + +response = requests.post(url, json=data, headers=headers) +print(response.json()) +``` + +{{< /tab >}} + +{{< /tabs >}} + +As alternative to `curl`, you can use [**📚 Swagger**]({{< relref "/docs/how-to/swagger" >}}) for that. + +Open Swagger at + +http://localhost:3000/#/chatting +, scroll down to **chatting** section. + +- Find `POST /api/sendText` endpoint and expand it +- Click **Try it out** +- Replace `123123@c.us` with **your phone number without +**, but keep `@c.us` part +- Click **Execute** + +![alt](swagger-send-text.png) + +## What's next? + +{{< include file="content/docs/how-to/install/-the-hosting.md" >}} + +{{< callout context="tip" icon="outline/robot" title="Build Fast" >}} +Ask [**🤖 WAHA GPT**]({{< relref "/gpt" >}}) to help you build **{python|js|php}** code! +{{< /callout >}} + +{{< include file="content/docs/overview/quick-start/links.md" >}} diff --git a/content/docs/overview/quick-start/links.md b/content/docs/overview/quick-start/links.md index fcf088d34..74c716e76 100644 --- a/content/docs/overview/quick-start/links.md +++ b/content/docs/overview/quick-start/links.md @@ -1,38 +1,36 @@ -
-{{< card-grid >}} -{{< card title="Learn WAHA" icon="outline/book" color="yellow" >}} - -- [📤 Send messages]({{}}) -- [📥 Receive messages]({{}}) -- [📊 Dashboard]({{< relref "/docs/how-to/dashboard" >}}) -- [🔍 Other How-to guides]({{}}) - -{{< /card >}} -{{< card title="Get Ready for Production" icon="outline/server" color="purple" >}} - -- [🔧 Installation Guide]({{< relref "/docs/how-to/install" >}}) -- [🔒 Security]({{< relref "/docs/how-to/security" >}}) -- [🗄️ Storages]({{< relref "/docs/how-to/sessions" >}}) -- [➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) - - -{{< /card >}} -{{< /card-grid >}} - -{{< card-grid >}} -{{< card title="What's going on?" icon="outline/info-circle" color="green" >}} - -- [🆕 Changelog]({{< relref "/docs/overview/changelog" >}}) -- [🐙 GitHub](https://github.com/devlikeapro/waha) - -{{< /card >}} -{{< card title="Other docs" icon="outline/books" color="red" >}} - -- [🧩 Apps]({{< relref "/docs/apps/about" >}}) -- [🔌 Integrations]({{< relref "/docs/integrations" >}}) -- [📚 Swagger]({{< relref "/docs/how-to/swagger" >}}) -- [🏭 Engines]({{< relref "/docs/how-to/engines" >}}) - -{{< /card >}} -{{< /card-grid >}} - +
+{{< card-grid >}} +{{< card title="Learn WAHA" icon="outline/book" color="yellow" >}} + +- [📤 Send messages]({{}}) +- [📥 Receive messages]({{}}) +- [📊 Dashboard]({{< relref "/docs/how-to/dashboard" >}}) +- [🔍 Other How-to guides]({{}}) + +{{< /card >}} +{{< card title="Get Ready for Production" icon="outline/server" color="purple" >}} + +- [🔧 Installation Guide]({{< relref "/docs/how-to/install" >}}) +- [🔒 Security]({{< relref "/docs/how-to/security" >}}) +- [🗄️ Storages]({{< relref "/docs/how-to/sessions" >}}) +- [➕ WAHA Plus]({{< relref "/docs/how-to/waha-plus" >}}) + +{{< /card >}} +{{< /card-grid >}} + +{{< card-grid >}} +{{< card title="What's going on?" icon="outline/info-circle" color="green" >}} + +- [🆕 Changelog]({{< relref "/docs/overview/changelog" >}}) +- [🐙 GitHub](https://github.com/devlikeapro/waha) + +{{< /card >}} +{{< card title="Other docs" icon="outline/books" color="red" >}} + +- [🧩 Apps]({{< relref "/docs/apps/about" >}}) +- [🔌 Integrations]({{< relref "/docs/integrations" >}}) +- [📚 Swagger]({{< relref "/docs/how-to/swagger" >}}) +- [🏭 Engines]({{< relref "/docs/how-to/engines" >}}) + +{{< /card >}} +{{< /card-grid >}} diff --git a/content/gpt/_index.md b/content/gpt/_index.md index e0ce0cafa..eb04eaaaa 100644 --- a/content/gpt/_index.md +++ b/content/gpt/_index.md @@ -1,47 +1,45 @@ ---- -title: "WAHA GPT" -description: "WAHA GPT to help you with development" -summary: "WAHA GPT to help you with development" -date: 2024-10-26T15:50:07+02:00 -lastmod: 2024-10-26T15:50:07+02:00 -draft: false -images: ['wahagpt.png'] ---- - -Ask anything, -**WAHA GPT** -will help you with development! - - - -

- - 🤖 WAHA GPT - -

- - - - ---- -
-
-
- -[https://chatgpt.com/g/g-pgnsaOg6W-waha-gpt](https://chatgpt.com/g/g-pgnsaOg6W-waha-gpt) - -> Write Python code to send a text message to +212321. - -🤔 ... - -> Write Python client for session management to use it as: `client.sessions.create('name', config)` - -🤔 ... - -> How to get a contact by phone number? - -🤔 ... - -
-
-
+--- +title: "WAHA GPT" +description: "WAHA GPT to help you with development" +summary: "WAHA GPT to help you with development" +date: 2024-10-26T15:50:07+02:00 +lastmod: 2024-10-26T15:50:07+02:00 +draft: false +images: ["wahagpt.png"] +--- + +Ask anything, +**WAHA GPT** +will help you with development! + + + +

+ + 🤖 WAHA GPT + +

+ +--- + +
+
+
+ +[https://chatgpt.com/g/g-pgnsaOg6W-waha-gpt](https://chatgpt.com/g/g-pgnsaOg6W-waha-gpt) + +> Write Python code to send a text message to +212321. + +🤔 ... + +> Write Python client for session management to use it as: `client.sessions.create('name', config)` + +🤔 ... + +> How to get a contact by phone number? + +🤔 ... + +
+
+
diff --git a/content/privacy-policy/index.md b/content/privacy-policy/index.md index 42c376138..c3a0992f8 100644 --- a/content/privacy-policy/index.md +++ b/content/privacy-policy/index.md @@ -1,36 +1,35 @@ ---- -title: "Privacy Policy" -description: "We do not use cookies and we do not collect any personal data." -date: 2020-08-27T19:23:18+02:00 -lastmod: 2020-08-27T19:23:18+02:00 -draft: true - ---- - -__TLDR__: We do not use cookies and we do not collect any personal data. - -## Website visitors - -- No personal information is collected. -- No information is stored in the browser. -- No information is shared with, sent to or sold to third-parties. -- No information is shared with advertising companies. -- No information is mined and harvested for personal and behavioral trends. -- No information is monetized. - -### Information we collect and what we use it for - -We run [Plausible](https://plausible.io/) analytics on getdoks.org. The following information is collected: - -- __Page URL__. We track the page URL of each page view on this website. We use this to understand which pages have been viewed and how many times a particular page has been viewed. For example: _https://getdoks.org/_. -- __HTTP Referrer__. We use the referrer string to understand the number of visitors referred to this website from links on other sites. For example: _https://github.com/_. -- __Browser__. We use this to understand what browsers people use when visiting this website. This is derived from the User-Agent HTTP header. The full User-Agent is discarded. For example: _Chrome_. -- __Operating system__. We use this to understand what operating systems people use when visiting this website. We only use the brand of the operating system and don’t include the version number or any other details. This is derived from the User-Agent HTTP header. The full User-Agent is discarded. For example: _GNU/Linux_. -- __Device type__. We use this to understand what devices people use when visiting this website. This is derived from window.innerWidth. The actual width of the browser in pixels is discarded. For example: _Desktop_. -- __Visitor Country__. We look up the visitor’s country using the IP address. We do not track anything more granular than the country of origin and the IP address of the visitor is discarded. We never store IP addresses in our database or logs. For example: _Canada_. - -## Contact us - -[Contact us]({{< relref "contact/index.md" >}}) if you have any questions. - -Effective Date: _27th August 2020_ +--- +title: "Privacy Policy" +description: "We do not use cookies and we do not collect any personal data." +date: 2020-08-27T19:23:18+02:00 +lastmod: 2020-08-27T19:23:18+02:00 +draft: true +--- + +**TLDR**: We do not use cookies and we do not collect any personal data. + +## Website visitors + +- No personal information is collected. +- No information is stored in the browser. +- No information is shared with, sent to or sold to third-parties. +- No information is shared with advertising companies. +- No information is mined and harvested for personal and behavioral trends. +- No information is monetized. + +### Information we collect and what we use it for + +We run [Plausible](https://plausible.io/) analytics on getdoks.org. The following information is collected: + +- **Page URL**. We track the page URL of each page view on this website. We use this to understand which pages have been viewed and how many times a particular page has been viewed. For example: _https://getdoks.org/_. +- **HTTP Referrer**. We use the referrer string to understand the number of visitors referred to this website from links on other sites. For example: _https://github.com/_. +- **Browser**. We use this to understand what browsers people use when visiting this website. This is derived from the User-Agent HTTP header. The full User-Agent is discarded. For example: _Chrome_. +- **Operating system**. We use this to understand what operating systems people use when visiting this website. We only use the brand of the operating system and don’t include the version number or any other details. This is derived from the User-Agent HTTP header. The full User-Agent is discarded. For example: _GNU/Linux_. +- **Device type**. We use this to understand what devices people use when visiting this website. This is derived from window.innerWidth. The actual width of the browser in pixels is discarded. For example: _Desktop_. +- **Visitor Country**. We look up the visitor’s country using the IP address. We do not track anything more granular than the country of origin and the IP address of the visitor is discarded. We never store IP addresses in our database or logs. For example: _Canada_. + +## Contact us + +[Contact us]({{< relref "contact/index.md" >}}) if you have any questions. + +Effective Date: _27th August 2020_ diff --git a/content/support-us/_index.md b/content/support-us/_index.md index bbdfcff46..cce99e762 100644 --- a/content/support-us/_index.md +++ b/content/support-us/_index.md @@ -1,12 +1,11 @@ ---- -title: "🎁 Support Us" -description: "WAHA - WhatsApp API that you can run in a click!" -summary: "🎁 Support Us" -date: 2024-01-29T15:50:07+02:00 -lastmod: 2024-01-29T15:50:07+02:00 -draft: false -aliases: - - /pricing - - /support-us ---- - +--- +title: "🎁 Support Us" +description: "WAHA - WhatsApp API that you can run in a click!" +summary: "🎁 Support Us" +date: 2024-01-29T15:50:07+02:00 +lastmod: 2024-01-29T15:50:07+02:00 +draft: false +aliases: + - /pricing + - /support-us +--- diff --git a/content/versions.md b/content/versions.md index 659813f85..fab572f55 100644 --- a/content/versions.md +++ b/content/versions.md @@ -1,11 +1,11 @@ ---- -title: "Versions" -description: "" -lead: "An appendix of hosted documentation for nearly every release of Doks, from v0 through v3." -date: 2021-09-24T08:50:23+02:00 -lastmod: 2021-09-24T08:50:23+02:00 -draft: true - -layout: versions -url: "/docs/versions/" ---- +--- +title: "Versions" +description: "" +lead: "An appendix of hosted documentation for nearly every release of Doks, from v0 through v3." +date: 2021-09-24T08:50:23+02:00 +lastmod: 2021-09-24T08:50:23+02:00 +draft: true + +layout: versions +url: "/docs/versions/" +--- diff --git a/content/waha-uptime-kuma/_index.md b/content/waha-uptime-kuma/_index.md index 218f1f62a..415253616 100644 --- a/content/waha-uptime-kuma/_index.md +++ b/content/waha-uptime-kuma/_index.md @@ -1,9 +1,10 @@ ---- -title : "WhatsApp Uptime Kuma" -description: "Send notifications from Uptime Kuma to your WhatsApp!" -lead: "Send notifications from Uptime Kuma to your WhatsApp!" -date: 2024-09-05T15:50:07+02:00 -lastmod: 2024-09-15T15:50:07+02:00 -draft: false ---- -Uptime Kuma => WhatsApp using WAHA +--- +title: "WhatsApp Uptime Kuma" +description: "Send notifications from Uptime Kuma to your WhatsApp!" +lead: "Send notifications from Uptime Kuma to your WhatsApp!" +date: 2024-09-05T15:50:07+02:00 +lastmod: 2024-09-15T15:50:07+02:00 +draft: false +--- + +Uptime Kuma => WhatsApp using WAHA diff --git a/content/whatsapp-channels/_index.md b/content/whatsapp-channels/_index.md index 3c9cd117b..dcb71ed91 100644 --- a/content/whatsapp-channels/_index.md +++ b/content/whatsapp-channels/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp Channels Automation" -description: "WhatsApp Channels Automation (Private-Hosted, HTTP)!" -lead: "Self-Hosted WhatsApp Channels Automation (Private-Hosted, HTTP)!" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp Channels Automation - +--- +title: "WhatsApp Channels Automation" +description: "WhatsApp Channels Automation (Private-Hosted, HTTP)!" +lead: "Self-Hosted WhatsApp Channels Automation (Private-Hosted, HTTP)!" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp Channels Automation diff --git a/content/whatsapp-chatwoot/_index.md b/content/whatsapp-chatwoot/_index.md index eed8fc244..a040c41e4 100644 --- a/content/whatsapp-chatwoot/_index.md +++ b/content/whatsapp-chatwoot/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp ChatWoot Integration" -description: "WhatsApp ChatWoot Integration" -lead: "WhatsApp ChatWoot Integration" -date: 2024-09-05T15:50:07+02:00 -lastmod: 2024-09-15T15:50:07+02:00 -draft: false ---- -WhatsApp ChatWoot Integration - +--- +title: "WhatsApp ChatWoot Integration" +description: "WhatsApp ChatWoot Integration" +lead: "WhatsApp ChatWoot Integration" +date: 2024-09-05T15:50:07+02:00 +lastmod: 2024-09-15T15:50:07+02:00 +draft: false +--- + +WhatsApp ChatWoot Integration diff --git a/content/whatsapp-groups/_index.md b/content/whatsapp-groups/_index.md index f30ed4e74..7fe1cec52 100644 --- a/content/whatsapp-groups/_index.md +++ b/content/whatsapp-groups/_index.md @@ -1,11 +1,11 @@ ---- -title : "WhatsApp Groups Automation" -description: "WhatsApp Groups Automation (Private-Hosted, HTTP)!" -lead: "Self-Hosted WhatsApp Groups Automation (Private-Hosted, HTTP)!" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false -images: ['whatsapp-groups.jpg'] ---- -WhatsApp Groups Automation - +--- +title: "WhatsApp Groups Automation" +description: "WhatsApp Groups Automation (Private-Hosted, HTTP)!" +lead: "Self-Hosted WhatsApp Groups Automation (Private-Hosted, HTTP)!" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +images: ["whatsapp-groups.jpg"] +--- + +WhatsApp Groups Automation diff --git a/content/whatsapp-low-code/_index.md b/content/whatsapp-low-code/_index.md index 480be8ad6..7cfd6b2cf 100644 --- a/content/whatsapp-low-code/_index.md +++ b/content/whatsapp-low-code/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp Automation with n8n" -description: "WhatsApp Automation with n8n" -lead: "WhatsApp Automation with n8n" -date: 2024-09-05T15:50:07+02:00 -lastmod: 2024-09-15T15:50:07+02:00 -draft: false ---- -WhatsApp No-Code Low-Code Automation - +--- +title: "WhatsApp Automation with n8n" +description: "WhatsApp Automation with n8n" +lead: "WhatsApp Automation with n8n" +date: 2024-09-05T15:50:07+02:00 +lastmod: 2024-09-15T15:50:07+02:00 +draft: false +--- + +WhatsApp No-Code Low-Code Automation diff --git a/content/whatsapp-plus-csharp/_index.md b/content/whatsapp-plus-csharp/_index.md index 9ed5c46fe..3f8f4df4b 100644 --- a/content/whatsapp-plus-csharp/_index.md +++ b/content/whatsapp-plus-csharp/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + C#" -description: "WhatsApp + C#" -lead: "Send and receive messages from WhatsApp using GoLang" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + C# - +--- +title: "WhatsApp + C#" +description: "WhatsApp + C#" +lead: "Send and receive messages from WhatsApp using GoLang" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + C# diff --git a/content/whatsapp-plus-go/_index.md b/content/whatsapp-plus-go/_index.md index 0703c1ce7..ad0fd4f22 100644 --- a/content/whatsapp-plus-go/_index.md +++ b/content/whatsapp-plus-go/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + Go" -description: "WhatsApp + Go" -lead: "Send and receive messages from WhatsApp using GoLang" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + GoLang - +--- +title: "WhatsApp + Go" +description: "WhatsApp + Go" +lead: "Send and receive messages from WhatsApp using GoLang" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + GoLang diff --git a/content/whatsapp-plus-java/_index.md b/content/whatsapp-plus-java/_index.md index d4449f736..7a2411d3c 100644 --- a/content/whatsapp-plus-java/_index.md +++ b/content/whatsapp-plus-java/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + Java" -description: "WhatsApp + Java" -lead: "Send and receive messages from WhatsApp using Java" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + Java - +--- +title: "WhatsApp + Java" +description: "WhatsApp + Java" +lead: "Send and receive messages from WhatsApp using Java" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + Java diff --git a/content/whatsapp-plus-javascript/_index.md b/content/whatsapp-plus-javascript/_index.md index beadb29d5..ef0111e4d 100644 --- a/content/whatsapp-plus-javascript/_index.md +++ b/content/whatsapp-plus-javascript/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + JS/TS" -description: "WhatsApp + JS/TS" -lead: "Send and receive messages from WhatsApp using JS/TS" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + JavaScript/TypeScript - +--- +title: "WhatsApp + JS/TS" +description: "WhatsApp + JS/TS" +lead: "Send and receive messages from WhatsApp using JS/TS" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + JavaScript/TypeScript diff --git a/content/whatsapp-plus-kotlin/_index.md b/content/whatsapp-plus-kotlin/_index.md index 54df24dd2..340b9e7f2 100644 --- a/content/whatsapp-plus-kotlin/_index.md +++ b/content/whatsapp-plus-kotlin/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + Kotlin" -description: "WhatsApp + Kotlin" -lead: "Send and receive messages from WhatsApp using Kotlin" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + Kotlin - +--- +title: "WhatsApp + Kotlin" +description: "WhatsApp + Kotlin" +lead: "Send and receive messages from WhatsApp using Kotlin" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + Kotlin diff --git a/content/whatsapp-plus-php/_index.md b/content/whatsapp-plus-php/_index.md index 89d631c92..02c2e35db 100644 --- a/content/whatsapp-plus-php/_index.md +++ b/content/whatsapp-plus-php/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + PHP" -description: "WhatsApp + PHP" -lead: "Send and receive messages from WhatsApp using PHP" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + PHP - +--- +title: "WhatsApp + PHP" +description: "WhatsApp + PHP" +lead: "Send and receive messages from WhatsApp using PHP" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + PHP diff --git a/content/whatsapp-plus-python/_index.md b/content/whatsapp-plus-python/_index.md index 428d6c7f9..18e1464c7 100644 --- a/content/whatsapp-plus-python/_index.md +++ b/content/whatsapp-plus-python/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp + Python" -description: "WhatsApp + Python" -lead: "Send and receive messages from WhatsApp using Python" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp + Python - +--- +title: "WhatsApp + Python" +description: "WhatsApp + Python" +lead: "Send and receive messages from WhatsApp using Python" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp + Python diff --git a/content/whatsapp-status/_index.md b/content/whatsapp-status/_index.md index e2380285b..8b5fbae8b 100644 --- a/content/whatsapp-status/_index.md +++ b/content/whatsapp-status/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp Status Automation" -description: "WhatsApp Status Automation (Private-Hosted, HTTP)!" -lead: "Self-Hosted WhatsApp Status Automation (Private-Hosted, HTTP)!" -date: 2024-07-15T15:50:07+02:00 -lastmod: 2024-07-15T15:50:07+02:00 -draft: false ---- -WhatsApp Status Automation - +--- +title: "WhatsApp Status Automation" +description: "WhatsApp Status Automation (Private-Hosted, HTTP)!" +lead: "Self-Hosted WhatsApp Status Automation (Private-Hosted, HTTP)!" +date: 2024-07-15T15:50:07+02:00 +lastmod: 2024-07-15T15:50:07+02:00 +draft: false +--- + +WhatsApp Status Automation diff --git a/content/whatsapp-typebot/_index.md b/content/whatsapp-typebot/_index.md index 29d8b743a..980db2308 100644 --- a/content/whatsapp-typebot/_index.md +++ b/content/whatsapp-typebot/_index.md @@ -1,10 +1,10 @@ ---- -title : "WhatsApp Typebot Integration" -description: "WhatsApp Typebot Integration" -lead: "WhatsApp Typebot Integration" -date: 2024-09-05T15:50:07+02:00 -lastmod: 2024-09-15T15:50:07+02:00 -draft: false ---- -WhatsApp Typebot Automation - +--- +title: "WhatsApp Typebot Integration" +description: "WhatsApp Typebot Integration" +lead: "WhatsApp Typebot Integration" +date: 2024-09-05T15:50:07+02:00 +lastmod: 2024-09-15T15:50:07+02:00 +draft: false +--- + +WhatsApp Typebot Automation diff --git a/data/docs-versions.yml b/data/docs-versions.yml index 8e7e5dd99..290e9bd72 100644 --- a/data/docs-versions.yml +++ b/data/docs-versions.yml @@ -1,60 +1,60 @@ -# - group: v1.x -# baseurl: "https://getbootstrap.com" -# description: "Every minor and patch release from v1 is listed below." -# versions: -# - v: "1.0.0" -# - v: "1.1.0" -# - v: "1.1.1" -# - v: "1.2.0" -# - v: "1.3.0" -# - v: "1.4.0" -# -# - group: v2.x -# baseurl: "https://getbootstrap.com" -# description: "Every minor and patch release from v2 is listed below." -# versions: -# - v: "2.0.0" -# - v: "2.0.1" -# - v: "2.0.2" -# - v: "2.0.3" -# - v: "2.0.4" -# - v: "2.1.0" -# - v: "2.1.1" -# - v: "2.2.0" -# - v: "2.2.1" -# - v: "2.2.2" -# - v: "2.3.0" -# - v: "2.3.1" -# - v: "2.3.2" -# -# - group: v3.x -# baseurl: "https://getbootstrap.com/docs" -# description: "Every minor and patch release from v3 is listed below. Last update was v3.4.1." -# versions: -# - v: "3.3" -# - v: "3.4" -# -# - group: v4.x -# baseurl: "https://getbootstrap.com/docs" -# description: "Our previous major release with its minor releases. Last update was v4.6.0." -# versions: -# - v: "4.0" -# - v: "4.1" -# - v: "4.2" -# - v: "4.3" -# - v: "4.4" -# - v: "4.5" -# - v: "4.6" - -- group: v0.x - baseurl: "/docs" - description: "Current major release. Last update was v0.2.0." - versions: - - v: "0.1" - - v: "0.2" - -- group: v1.x - baseurl: "/docs" - description: "Every minor and patch release from v1 is listed below. Last update was v1.0.0." - versions: - - v: "1.0" +# - group: v1.x +# baseurl: "https://getbootstrap.com" +# description: "Every minor and patch release from v1 is listed below." +# versions: +# - v: "1.0.0" +# - v: "1.1.0" +# - v: "1.1.1" +# - v: "1.2.0" +# - v: "1.3.0" +# - v: "1.4.0" +# +# - group: v2.x +# baseurl: "https://getbootstrap.com" +# description: "Every minor and patch release from v2 is listed below." +# versions: +# - v: "2.0.0" +# - v: "2.0.1" +# - v: "2.0.2" +# - v: "2.0.3" +# - v: "2.0.4" +# - v: "2.1.0" +# - v: "2.1.1" +# - v: "2.2.0" +# - v: "2.2.1" +# - v: "2.2.2" +# - v: "2.3.0" +# - v: "2.3.1" +# - v: "2.3.2" +# +# - group: v3.x +# baseurl: "https://getbootstrap.com/docs" +# description: "Every minor and patch release from v3 is listed below. Last update was v3.4.1." +# versions: +# - v: "3.3" +# - v: "3.4" +# +# - group: v4.x +# baseurl: "https://getbootstrap.com/docs" +# description: "Our previous major release with its minor releases. Last update was v4.6.0." +# versions: +# - v: "4.0" +# - v: "4.1" +# - v: "4.2" +# - v: "4.3" +# - v: "4.4" +# - v: "4.5" +# - v: "4.6" + +- group: v0.x + baseurl: '/docs' + description: 'Current major release. Last update was v0.2.0.' + versions: + - v: '0.1' + - v: '0.2' + +- group: v1.x + baseurl: '/docs' + description: 'Every minor and patch release from v1 is listed below. Last update was v1.0.0.' + versions: + - v: '1.0' diff --git a/functions/hi-from-lambda.js b/functions/hi-from-lambda.js index 88e4fa008..6175354b5 100644 --- a/functions/hi-from-lambda.js +++ b/functions/hi-from-lambda.js @@ -1,11 +1,11 @@ -exports.handler = (event, context, callback) => { - callback (null, { - statusCode: 200, - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - message: 'Hi from Lambda.', - }), - }); -} +exports.handler = (event, context, callback) => { + callback(null, { + statusCode: 200, + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + message: 'Hi from Lambda.' + }) + }); +}; diff --git a/hugo_stats.json b/hugo_stats.json index de2df0e0a..53c13626d 100644 --- a/hugo_stats.json +++ b/hugo_stats.json @@ -145,6 +145,7 @@ "d-none", "d-xl-block", "d-xl-none", + "dark-text", "diagram", "diagram-kroki", "diagram-kroki-mermaid", @@ -384,7 +385,6 @@ "wrap" ], "ids": [ - "--filter-chats-by-ids", "-and-more", "-breaking-changes", "-breaking-changes-1", @@ -402,6 +402,7 @@ "-events", "-faq", "-filter-by-ack", + "-filter-chats-by-ids", "-final-word", "-fixes--stability", "-group-receipts-tracking", @@ -563,7 +564,7 @@ "download-and-start-image", "download-image---arm", "edit-message", - "enable--store", + "enable-store", "engineevent", "engines", "entities-schema", @@ -697,7 +698,6 @@ "https---lets-encrypt", "https---self-signed-certificate", "install", - "install-dependencies", "install-plus", "install-waha-n8n-node", "installation", @@ -785,7 +785,6 @@ "quick-start", "raw", "read-messages", - "receive-message", "receive-messages-from-the-channel", "receive-status-messages", "recommended-proxies", @@ -824,7 +823,6 @@ "send-image-to-the-channel", "send-link-custom-preview", "send-location", - "send-message", "send-messages-to-channels", "send-poll", "send-reaction-to-the-channel", diff --git a/i18n/de.yaml b/i18n/de.yaml index d1f125ee3..06a0b93a1 100644 --- a/i18n/de.yaml +++ b/i18n/de.yaml @@ -1,5 +1,5 @@ -- id: get-started - translation: "Loslegen" - -- id: on-this-page - translation: "Auf dieser Seite" +- id: get-started + translation: "Loslegen" + +- id: on-this-page + translation: "Auf dieser Seite" diff --git a/i18n/en.yaml b/i18n/en.yaml index 05ff248fe..dc4e42b71 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -1,17 +1,17 @@ -- id: get-started - translation: "Get Started" - -- id: on-this-page - translation: "On this page" - -- id: search-text - translation: "Search docs..." - -- id: 404-title - translation: "Page not found :(" - -- id: 404-text - translation: "The page you are looking for doesn't exist or has been moved." - -- id: browse - translation: "Browse" +- id: get-started + translation: "Get Started" + +- id: on-this-page + translation: "On this page" + +- id: search-text + translation: "Search docs..." + +- id: 404-title + translation: "Page not found :(" + +- id: 404-text + translation: "The page you are looking for doesn't exist or has been moved." + +- id: browse + translation: "Browse" diff --git a/i18n/nl.yaml b/i18n/nl.yaml index 2899edae9..d175f7842 100644 --- a/i18n/nl.yaml +++ b/i18n/nl.yaml @@ -1,17 +1,17 @@ -- id: get-started - translation: "Aan de slag" - -- id: on-this-page - translation: "Op deze pagina" - -- id: search-text - translation: "Zoeken..." - -- id: 404-title - translation: "Pagina niet gevonden :(" - -- id: 404-text - translation: "De gezochte pagina bestaat niet of deze is verplaatst." - -- id: browse - translation: "Browse" +- id: get-started + translation: "Aan de slag" + +- id: on-this-page + translation: "Op deze pagina" + +- id: search-text + translation: "Zoeken..." + +- id: 404-title + translation: "Pagina niet gevonden :(" + +- id: 404-text + translation: "De gezochte pagina bestaat niet of deze is verplaatst." + +- id: browse + translation: "Browse" diff --git a/layouts/code/events/message.channel.md b/layouts/code/events/message.channel.md index 56ab90d7e..f7686ca3e 100644 --- a/layouts/code/events/message.channel.md +++ b/layouts/code/events/message.channel.md @@ -1,12 +1,12 @@ -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "false_123123@newsletter_AAA", - "timestamp": 1720776511, - "from": "123@newsletter", - "body": "How are you all?! ❤️" - } -} -``` \ No newline at end of file +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "false_123123@newsletter_AAA", + "timestamp": 1720776511, + "from": "123@newsletter", + "body": "How are you all?! ❤️" + } +} +``` diff --git a/layouts/code/events/message.group.md b/layouts/code/events/message.group.md index 7cc937f0c..4bf1904d3 100644 --- a/layouts/code/events/message.group.md +++ b/layouts/code/events/message.group.md @@ -1,12 +1,12 @@ -```json { title="message" } -{ - "event": "message", - "session": "default", - "payload": { - "id": "123@g.us", - "timestamp": 1720776511, - "from": "999@c.us", - "body": "How are you all?! ❤️" - } -} -``` \ No newline at end of file +```json { title="message" } +{ + "event": "message", + "session": "default", + "payload": { + "id": "123@g.us", + "timestamp": 1720776511, + "from": "999@c.us", + "body": "How are you all?! ❤️" + } +} +``` diff --git a/layouts/code/index/docker-run.md b/layouts/code/index/docker-run.md index c82d796dc..8df71cd3d 100644 --- a/layouts/code/index/docker-run.md +++ b/layouts/code/index/docker-run.md @@ -1,3 +1,3 @@ -```bash {lineNos=true} -docker run -it -p 3000:3000 devlikeapro/waha -``` +```bash {lineNos=true} +docker run -it -p 3000:3000 devlikeapro/waha +``` diff --git a/layouts/code/language/csharp/install-dependencies.md b/layouts/code/language/csharp/install-dependencies.md index 385822dfc..ece9b1d89 100644 --- a/layouts/code/language/csharp/install-dependencies.md +++ b/layouts/code/language/csharp/install-dependencies.md @@ -1,5 +1,3 @@ -### Install Dependencies - -```bash -dotnet add package System.Net.Http.Json -``` +```bash +dotnet add package System.Net.Http.Json +``` diff --git a/layouts/code/language/csharp/receive-message.md b/layouts/code/language/csharp/receive-message.md index 4d9d2760a..b8759d5e4 100644 --- a/layouts/code/language/csharp/receive-message.md +++ b/layouts/code/language/csharp/receive-message.md @@ -1,22 +1,21 @@ -### Receive Message -```cs -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using System.Text.Json; - -var builder = WebApplication.CreateBuilder(args); -var app = builder.Build(); - -app.MapPost("/bot", async (HttpContext context) => -{ - var data = await JsonSerializer.DeserializeAsync(context.Request.Body); - if (data.GetProperty("event").GetString() != "message") - { - // Process message, save it, respond, etc. - ProcessMessage(data.GetProperty("payload")); - } - await context.Response.WriteAsync("OK"); -}); - -app.Run(); -``` \ No newline at end of file +```cs +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using System.Text.Json; + +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.MapPost("/bot", async (HttpContext context) => +{ + var data = await JsonSerializer.DeserializeAsync(context.Request.Body); + if (data.GetProperty("event").GetString() != "message") + { + // Process message, save it, respond, etc. + ProcessMessage(data.GetProperty("payload")); + } + await context.Response.WriteAsync("OK"); +}); + +app.Run(); +``` diff --git a/layouts/code/language/csharp/send-message.md b/layouts/code/language/csharp/send-message.md index ea35b817d..f488a9dc5 100644 --- a/layouts/code/language/csharp/send-message.md +++ b/layouts/code/language/csharp/send-message.md @@ -1,18 +1,17 @@ -### Send Message -```cs -using System; -using System.Net.Http; -using System.Net.Http.Json; -using System.Threading.Tasks; - -var client = new HttpClient(); -var url = "http://localhost:3000/api/sendText"; -var data = new -{ - session = "default", - chatId = "12132132130@c.us", - text = "Hi there!" -}; -var response = await client.PostAsJsonAsync(url, data); -response.EnsureSuccessStatusCode(); -``` \ No newline at end of file +```cs +using System; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading.Tasks; + +var client = new HttpClient(); +var url = "http://localhost:3000/api/sendText"; +var data = new +{ + session = "default", + chatId = "12132132130@c.us", + text = "Hi there!" +}; +var response = await client.PostAsJsonAsync(url, data); +response.EnsureSuccessStatusCode(); +``` diff --git a/layouts/code/language/go/install-dependencies.md b/layouts/code/language/go/install-dependencies.md index 842bac147..cfbf599d4 100644 --- a/layouts/code/language/go/install-dependencies.md +++ b/layouts/code/language/go/install-dependencies.md @@ -1,5 +1,3 @@ -### Install Dependencies - -```bash -go get -u github.com/gofiber/fiber/v2 -``` +```bash +go get -u github.com/gofiber/fiber/v2 +``` diff --git a/layouts/code/language/go/receive-message.md b/layouts/code/language/go/receive-message.md index cacf9b3b9..b3fc9f5de 100644 --- a/layouts/code/language/go/receive-message.md +++ b/layouts/code/language/go/receive-message.md @@ -1,28 +1,27 @@ -### Receive Message -```go -package main - -import ( - "fmt" - "github.com/gofiber/fiber/v2" -) - -func main() { - app := fiber.New() - - app.Post("/bot", func(c *fiber.Ctx) error { - var data map[string]interface{} - if err := c.BodyParser(&data); err != nil { - return err - } - - if event, ok := data["event"].(string); ok && event == "message" { - fmt.Println("Received message:", data["payload"]) - // Process message... - } - return c.SendString("OK") - }) - - app.Listen(":3000") -} -``` \ No newline at end of file +```go +package main + +import ( + "fmt" + "github.com/gofiber/fiber/v2" +) + +func main() { + app := fiber.New() + + app.Post("/bot", func(c *fiber.Ctx) error { + var data map[string]interface{} + if err := c.BodyParser(&data); err != nil { + return err + } + + if event, ok := data["event"].(string); ok && event == "message" { + fmt.Println("Received message:", data["payload"]) + // Process message... + } + return c.SendString("OK") + }) + + app.Listen(":3000") +} +``` diff --git a/layouts/code/language/go/send-message.md b/layouts/code/language/go/send-message.md index f8c3a94c0..e0f92e088 100644 --- a/layouts/code/language/go/send-message.md +++ b/layouts/code/language/go/send-message.md @@ -1,28 +1,27 @@ -### Send Message -```cs -package main - -import ( - "bytes" - "encoding/json" - "net/http" -) - -type Message struct { - Session string `json:"session"` - ChatID string `json:"chatId"` - Text string `json:"text"` -} - -func main() { - url := "http://localhost:3000/api/sendText" - msg := Message{Session: "default", ChatID: "12132132130@c.us", Text: "Hi there!"} - jsonData, _ := json.Marshal(msg) - - resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) - if err != nil { - panic(err) - } - defer resp.Body.Close() -} -``` \ No newline at end of file +```cs +package main + +import ( + "bytes" + "encoding/json" + "net/http" +) + +type Message struct { + Session string `json:"session"` + ChatID string `json:"chatId"` + Text string `json:"text"` +} + +func main() { + url := "http://localhost:3000/api/sendText" + msg := Message{Session: "default", ChatID: "12132132130@c.us", Text: "Hi there!"} + jsonData, _ := json.Marshal(msg) + + resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + panic(err) + } + defer resp.Body.Close() +} +``` diff --git a/layouts/code/language/java/install-dependencies.md b/layouts/code/language/java/install-dependencies.md index 6708dc380..78e353708 100644 --- a/layouts/code/language/java/install-dependencies.md +++ b/layouts/code/language/java/install-dependencies.md @@ -1,6 +1,4 @@ -### Install Dependencies - -```bash -java --version -# No additional dependencies required -``` +```bash +java --version +# No additional dependencies required +``` diff --git a/layouts/code/language/java/receive-message.md b/layouts/code/language/java/receive-message.md index 2bc13ce5e..079c315f7 100644 --- a/layouts/code/language/java/receive-message.md +++ b/layouts/code/language/java/receive-message.md @@ -1,27 +1,26 @@ -### Receive Message -```java -import io.javalin.Javalin; -import io.javalin.http.Context; -import org.json.JSONObject; - -public class WhatsAppWebhook { - public static void main(String[] args) { - Javalin app = Javalin.create().start(7000); - - app.post("/bot", WhatsAppWebhook::handleWebhook); - } - - private static void handleWebhook(Context ctx) { - JSONObject json = new JSONObject(ctx.body()); - if (!"message".equals(json.getString("event"))) { - processMessage(json.getJSONObject("payload")); - } - ctx.result("OK"); - } - - private static void processMessage(JSONObject payload) { - System.out.println("Received message: " + payload.toString()); - } -} - -``` \ No newline at end of file +```java +import io.javalin.Javalin; +import io.javalin.http.Context; +import org.json.JSONObject; + +public class WhatsAppWebhook { + public static void main(String[] args) { + Javalin app = Javalin.create().start(7000); + + app.post("/bot", WhatsAppWebhook::handleWebhook); + } + + private static void handleWebhook(Context ctx) { + JSONObject json = new JSONObject(ctx.body()); + if (!"message".equals(json.getString("event"))) { + processMessage(json.getJSONObject("payload")); + } + ctx.result("OK"); + } + + private static void processMessage(JSONObject payload) { + System.out.println("Received message: " + payload.toString()); + } +} + +``` diff --git a/layouts/code/language/java/send-message.md b/layouts/code/language/java/send-message.md index f148e4b11..1a259e19b 100644 --- a/layouts/code/language/java/send-message.md +++ b/layouts/code/language/java/send-message.md @@ -1,20 +1,19 @@ -### Send Message -```java -import kong.unirest.HttpResponse; -import kong.unirest.JsonNode; -import kong.unirest.Unirest; - -public class WhatsAppClient { - public static void main(String[] args) { - String url = "http://localhost:3000/api/sendText"; - - HttpResponse response = Unirest.post(url) - .header("Content-Type", "application/json") - .body("{\"session\": \"default\", \"chatId\": \"12132132130@c.us\", \"text\": \"Hi there!\"}") - .asJson(); - - System.out.println(response.getBody()); - } -} - -``` \ No newline at end of file +```java +import kong.unirest.HttpResponse; +import kong.unirest.JsonNode; +import kong.unirest.Unirest; + +public class WhatsAppClient { + public static void main(String[] args) { + String url = "http://localhost:3000/api/sendText"; + + HttpResponse response = Unirest.post(url) + .header("Content-Type", "application/json") + .body("{\"session\": \"default\", \"chatId\": \"12132132130@c.us\", \"text\": \"Hi there!\"}") + .asJson(); + + System.out.println(response.getBody()); + } +} + +``` diff --git a/layouts/code/language/javascript/install-dependencies.md b/layouts/code/language/javascript/install-dependencies.md index 2473dbee0..33ac4756d 100644 --- a/layouts/code/language/javascript/install-dependencies.md +++ b/layouts/code/language/javascript/install-dependencies.md @@ -1,5 +1,3 @@ -### Install Dependencies - -```bash -npm install axios express -``` +```bash +npm install axios express +``` diff --git a/layouts/code/language/javascript/receive-message.md b/layouts/code/language/javascript/receive-message.md index e26c18750..27e900876 100644 --- a/layouts/code/language/javascript/receive-message.md +++ b/layouts/code/language/javascript/receive-message.md @@ -1,17 +1,16 @@ -### Receive Message -```javascript -const express = require('express'); -const app = express(); -app.use(express.json()); - -app.post("/bot", (req, res) => { - const data = req.body; - if (data.event !== "message") { - // Process the message, save it, etc. - processMessage(data.payload); - } - res.send("OK"); -}); - -app.listen(3000, () => console.log("Bot is running on port 3000")); -``` \ No newline at end of file +```javascript +const express = require("express"); +const app = express(); +app.use(express.json()); + +app.post("/bot", (req, res) => { + const data = req.body; + if (data.event !== "message") { + // Process the message, save it, etc. + processMessage(data.payload); + } + res.send("OK"); +}); + +app.listen(3000, () => console.log("Bot is running on port 3000")); +``` diff --git a/layouts/code/language/javascript/send-message.md b/layouts/code/language/javascript/send-message.md index 7421b9d5c..97aa8326a 100644 --- a/layouts/code/language/javascript/send-message.md +++ b/layouts/code/language/javascript/send-message.md @@ -1,15 +1,15 @@ -### Send Message -```javascript -const axios = require('axios'); - -const url = "http://localhost:3000/api/sendText"; -const data = { - session: "default", - chatId: "12132132130@c.us", - text: "Hi there!" -}; - -axios.post(url, data) - .then(response => console.log(response.data)) - .catch(error => console.error(error)); -``` \ No newline at end of file +```javascript +const axios = require("axios"); + +const url = "http://localhost:3000/api/sendText"; +const data = { + session: "default", + chatId: "12132132130@c.us", + text: "Hi there!" +}; + +axios + .post(url, data) + .then((response) => console.log(response.data)) + .catch((error) => console.error(error)); +``` diff --git a/layouts/code/language/kotlin/install-dependencies.md b/layouts/code/language/kotlin/install-dependencies.md index 5a0029a1b..29150bb5e 100644 --- a/layouts/code/language/kotlin/install-dependencies.md +++ b/layouts/code/language/kotlin/install-dependencies.md @@ -1,10 +1,8 @@ -### Install Dependencies - -```kotlin {title="build.gradle.kts"} -dependencies { - implementation("io.ktor:ktor-server-core:2.3.5") - implementation("io.ktor:ktor-server-netty:2.3.5") - implementation("io.ktor:ktor-client-core:2.3.5") - implementation("io.ktor:ktor-client-cio:2.3.5") // Optional HTTP client -} -``` +```kotlin {title="build.gradle.kts"} +dependencies { + implementation("io.ktor:ktor-server-core:2.3.5") + implementation("io.ktor:ktor-server-netty:2.3.5") + implementation("io.ktor:ktor-client-core:2.3.5") + implementation("io.ktor:ktor-client-cio:2.3.5") // Optional HTTP client +} +``` diff --git a/layouts/code/language/kotlin/receive-message.md b/layouts/code/language/kotlin/receive-message.md index 8c2c506f3..6d6f56838 100644 --- a/layouts/code/language/kotlin/receive-message.md +++ b/layouts/code/language/kotlin/receive-message.md @@ -1,33 +1,32 @@ -### Receive Message -```kotlin -import io.ktor.application.* -import io.ktor.features.ContentNegotiation -import io.ktor.jackson.jackson -import io.ktor.request.* -import io.ktor.response.* -import io.ktor.routing.* -import io.ktor.server.engine.* -import io.ktor.server.netty.* - -fun main() { - embeddedServer(Netty, port = 8080) { - install(ContentNegotiation) { - jackson() - } - routing { - post("/bot") { - val data = call.receive>() - if (data["event"] == "message") { // Fixed condition logic - processMessage(data["payload"]) - } - call.respondText("OK") - } - } - }.start(wait = true) -} - -fun processMessage(payload: Any?) { - println("Processing message: $payload") -} - -``` \ No newline at end of file +```kotlin +import io.ktor.application.* +import io.ktor.features.ContentNegotiation +import io.ktor.jackson.jackson +import io.ktor.request.* +import io.ktor.response.* +import io.ktor.routing.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* + +fun main() { + embeddedServer(Netty, port = 8080) { + install(ContentNegotiation) { + jackson() + } + routing { + post("/bot") { + val data = call.receive>() + if (data["event"] == "message") { // Fixed condition logic + processMessage(data["payload"]) + } + call.respondText("OK") + } + } + }.start(wait = true) +} + +fun processMessage(payload: Any?) { + println("Processing message: $payload") +} + +``` diff --git a/layouts/code/language/kotlin/send-message.md b/layouts/code/language/kotlin/send-message.md index 6067cdd61..1feee0381 100644 --- a/layouts/code/language/kotlin/send-message.md +++ b/layouts/code/language/kotlin/send-message.md @@ -1,23 +1,21 @@ -### Send Message - -```kotlin -import io.ktor.client.* -import io.ktor.client.request.* -import io.ktor.http.* - -suspend fun sendMessage() { - val client = HttpClient() - val response = - client.post("http://localhost:3000/api/sendText") { - contentType(ContentType.Application.Json) - setBody( - mapOf( - "session" to "default", - "chatId" to "12132132130@newsletter", - "text" to "Hi there!" - ) - ) - } - println(response.status) -} -``` \ No newline at end of file +```kotlin +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.http.* + +suspend fun sendMessage() { + val client = HttpClient() + val response = + client.post("http://localhost:3000/api/sendText") { + contentType(ContentType.Application.Json) + setBody( + mapOf( + "session" to "default", + "chatId" to "12132132130@newsletter", + "text" to "Hi there!" + ) + ) + } + println(response.status) +} +``` diff --git a/layouts/code/language/php/install-dependencies.md b/layouts/code/language/php/install-dependencies.md index 234408743..dddfed5e7 100644 --- a/layouts/code/language/php/install-dependencies.md +++ b/layouts/code/language/php/install-dependencies.md @@ -1,6 +1,4 @@ -### Install Dependencies - -```bash -php -m | grep curl -php -m | grep json -``` +```bash +php -m | grep curl +php -m | grep json +``` diff --git a/layouts/code/language/php/receive-message.md b/layouts/code/language/php/receive-message.md index 6981ddd68..5451c311e 100644 --- a/layouts/code/language/php/receive-message.md +++ b/layouts/code/language/php/receive-message.md @@ -1,13 +1,12 @@ -### Receive Message -```php - - -``` \ No newline at end of file +```php + + +``` diff --git a/layouts/code/language/php/send-message.md b/layouts/code/language/php/send-message.md index c04a90ff2..12c485afa 100644 --- a/layouts/code/language/php/send-message.md +++ b/layouts/code/language/php/send-message.md @@ -1,22 +1,20 @@ -### Send Message - -```php - "default", - "chatId" => "12132132130@newsletter", - "text" => "Hi there!" -]; - -$ch = curl_init($url); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_POST, true); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json' -]); -$response = curl_exec($ch); -curl_close($ch); -?> -``` \ No newline at end of file +```php + "default", + "chatId" => "12132132130@newsletter", + "text" => "Hi there!" +]; + +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_POST, true); +curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json' +]); +$response = curl_exec($ch); +curl_close($ch); +?> +``` diff --git a/layouts/code/language/python/install-dependencies.md b/layouts/code/language/python/install-dependencies.md index 442fbbb14..c5d73aa04 100644 --- a/layouts/code/language/python/install-dependencies.md +++ b/layouts/code/language/python/install-dependencies.md @@ -1,6 +1,4 @@ -### Install Dependencies - -```bash -pip install requests -pip install flask -``` +```bash +pip install requests +pip install flask +``` diff --git a/layouts/code/language/python/receive-message.md b/layouts/code/language/python/receive-message.md index 9cc9169f6..68226773c 100644 --- a/layouts/code/language/python/receive-message.md +++ b/layouts/code/language/python/receive-message.md @@ -1,17 +1,15 @@ -### Receive Message - -```python -from flask import Flask -from flask import request - -app = Flask(__name__) - - -@app.route("/bot", methods=["POST"]) -def whatsapp_webhook(): - data = request.get_json() - if data["event"] != "message": - # answer to message, save it, etc - process_message(data["payload"]) - return "OK" -``` \ No newline at end of file +```python +from flask import Flask +from flask import request + +app = Flask(__name__) + + +@app.route("/bot", methods=["POST"]) +def whatsapp_webhook(): + data = request.get_json() + if data["event"] != "message": + # answer to message, save it, etc + process_message(data["payload"]) + return "OK" +``` diff --git a/layouts/code/language/python/send-message.md b/layouts/code/language/python/send-message.md index 3bebdf223..234c4e08d 100644 --- a/layouts/code/language/python/send-message.md +++ b/layouts/code/language/python/send-message.md @@ -1,14 +1,12 @@ -### Send Message - -```python -import requests - -url = "http://localhost:3000/api/sendText" -data = { - "session": "default", - "chatId": "12132132130@newsletter", - "text": "Hi there!" -} -response = requests.post(url, json=data) -response.raise_for_status() -``` \ No newline at end of file +```python +import requests + +url = "http://localhost:3000/api/sendText" +data = { + "session": "default", + "chatId": "12132132130@newsletter", + "text": "Hi there!" +} +response = requests.post(url, json=data) +response.raise_for_status() +``` diff --git a/layouts/code/requests/Channel.SendText.md b/layouts/code/requests/Channel.SendText.md index 301eedcd1..39c4d9925 100644 --- a/layouts/code/requests/Channel.SendText.md +++ b/layouts/code/requests/Channel.SendText.md @@ -1,11 +1,11 @@ -```http request -POST /api/sendText -``` - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@newsletter", - "text": "Hi there!" -} -``` +```http request +POST /api/sendText +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@newsletter", + "text": "Hi there!" +} +``` diff --git a/layouts/code/requests/Channels.List.md b/layouts/code/requests/Channels.List.md index edfd7dbf9..a7ff309bf 100644 --- a/layouts/code/requests/Channels.List.md +++ b/layouts/code/requests/Channels.List.md @@ -1,14 +1,16 @@ -```http request -GET /api/{session}/channels -``` - -```json { title="Body" } -[{ - "id": "123@newsletter", - "name": "Local News", - "description": "...", - "invite": "...", - "picture": "...", - "role": "ADMIN" -}] -``` \ No newline at end of file +```http request +GET /api/{session}/channels +``` + +```json { title="Body" } +[ + { + "id": "123@newsletter", + "name": "Local News", + "description": "...", + "invite": "...", + "picture": "...", + "role": "ADMIN" + } +] +``` diff --git a/layouts/code/requests/Chat.SendText.md b/layouts/code/requests/Chat.SendText.md index 787514d11..9a059b067 100644 --- a/layouts/code/requests/Chat.SendText.md +++ b/layouts/code/requests/Chat.SendText.md @@ -1,11 +1,11 @@ -```http request -POST /api/sendText -``` - -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@c.us", - "text": "Hi there!" -} -``` +```http request +POST /api/sendText +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@c.us", + "text": "Hi there!" +} +``` diff --git a/layouts/code/requests/Groups.Create.md b/layouts/code/requests/Groups.Create.md index 72d5e1b8d..15a699b6a 100644 --- a/layouts/code/requests/Groups.Create.md +++ b/layouts/code/requests/Groups.Create.md @@ -1,11 +1,10 @@ -```http request -POST /api/{session}/groups -``` -```json { title="Body" } -{ - "name": "Group name", - "participants": [ - {"id": "123123123123@c.us"} - ] -} -``` \ No newline at end of file +```http request +POST /api/{session}/groups +``` + +```json { title="Body" } +{ + "name": "Group name", + "participants": [{ "id": "123123123123@c.us" }] +} +``` diff --git a/layouts/code/requests/Groups.List.md b/layouts/code/requests/Groups.List.md index 771baf723..80e5c1000 100644 --- a/layouts/code/requests/Groups.List.md +++ b/layouts/code/requests/Groups.List.md @@ -1,12 +1,15 @@ -```http request -GET /api/{session}/groups -``` -```json { title="Body" } -[{ - "id": "123@g.us", - "name": "Work Group", - "description": "...", - "invite": "...", - "participants": [{"id": "123"}] -}] -``` \ No newline at end of file +```http request +GET /api/{session}/groups +``` + +```json { title="Body" } +[ + { + "id": "123@g.us", + "name": "Work Group", + "description": "...", + "invite": "...", + "participants": [{ "id": "123" }] + } +] +``` diff --git a/layouts/code/requests/Groups.SendText.md b/layouts/code/requests/Groups.SendText.md index 83ce32453..ce7a94b96 100644 --- a/layouts/code/requests/Groups.SendText.md +++ b/layouts/code/requests/Groups.SendText.md @@ -1,10 +1,11 @@ -```http request -POST /api/sendText -``` -```json { title="Body" } -{ - "session": "default", - "chatId": "12132132130@g.us", - "text": "Hi there!" -} -``` \ No newline at end of file +```http request +POST /api/sendText +``` + +```json { title="Body" } +{ + "session": "default", + "chatId": "12132132130@g.us", + "text": "Hi there!" +} +``` diff --git a/layouts/code/requests/Status.SendImage.md b/layouts/code/requests/Status.SendImage.md index 742a6a491..6f7ce16f5 100644 --- a/layouts/code/requests/Status.SendImage.md +++ b/layouts/code/requests/Status.SendImage.md @@ -1,12 +1,13 @@ -```http request -POST /api/{session}/status/image -``` -```json { title="Body" } -{ - "file": { - "mimetype": "image/jpeg", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" - }, - "caption": "string" -} -``` \ No newline at end of file +```http request +POST /api/{session}/status/image +``` + +```json { title="Body" } +{ + "file": { + "mimetype": "image/jpeg", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg" + }, + "caption": "string" +} +``` diff --git a/layouts/code/requests/Status.SendText.md b/layouts/code/requests/Status.SendText.md index 7d391c2ea..2e82f990c 100644 --- a/layouts/code/requests/Status.SendText.md +++ b/layouts/code/requests/Status.SendText.md @@ -1,10 +1,11 @@ -```http request -POST /api/{session}/status/text -``` -```json { title="Body" } -{ - "text": "Have a look! https://waha.devlike.pro/", - "backgroundColor": "#38b42f", - "font": 1 -} -``` \ No newline at end of file +```http request +POST /api/{session}/status/text +``` + +```json { title="Body" } +{ + "text": "Have a look! https://waha.devlike.pro/", + "backgroundColor": "#38b42f", + "font": 1 +} +``` diff --git a/layouts/code/requests/Status.SendVideo.md b/layouts/code/requests/Status.SendVideo.md index 5f62f650a..b04913574 100644 --- a/layouts/code/requests/Status.SendVideo.md +++ b/layouts/code/requests/Status.SendVideo.md @@ -1,12 +1,13 @@ -```http request -POST /api/{session}/status/video -``` -```json { title="Body" } -{ - "file": { - "mimetype": "video/mp4", - "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - }, - "backgroundColor": "#38b42f" -} -``` \ No newline at end of file +```http request +POST /api/{session}/status/video +``` + +```json { title="Body" } +{ + "file": { + "mimetype": "video/mp4", + "url": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + }, + "backgroundColor": "#38b42f" +} +``` diff --git a/layouts/include/why-waha-section.html b/layouts/include/why-waha-section.html index d5d4c92a7..73ea1ef22 100644 --- a/layouts/include/why-waha-section.html +++ b/layouts/include/why-waha-section.html @@ -23,7 +23,7 @@

It's free!

API -

HTTP / REST API

+

HTTP / REST API

Use your favorite language - Python, JavaScript, PHP, C#, Clojure, or PowerShell. -
+
PowerShell, really? Are you insane?! Choose another language, dude. @@ -46,19 +46,19 @@

HTTP / REST API

Easy -

Easy & Simple

+

Easy & Simple

You can @@ -68,7 +68,7 @@

Easy & Simple

Documentation has many examples and how-to guides. -
+
*It's actually "a command", not a click. @@ -76,13 +76,13 @@

Easy & Simple

Checked -

No blocking

+

No blocking

Under the hood it runs a real instance of WhatsApp Web to avoid getting blocked. -
+
WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered @@ -93,4 +93,4 @@

No blocking

- + \ No newline at end of file diff --git a/layouts/index.html b/layouts/index.html index 9edfbbc6a..6ec082b86 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -74,7 +74,7 @@

Send and Receive
Messages

alt='WhatsApp Channel Logo' style='width: 5rem' > -

+

WhatsApp Channels and Status Automation

@@ -97,7 +97,7 @@

API -

+

WAHA can do
much more

@@ -148,7 +148,7 @@

-

Built-in Dashboard

+

Built-in Dashboard

WAHA provides Dashboard - a web interface to easily manage your WhatsApp sessions! diff --git a/layouts/whatsapp-channels/list.html b/layouts/whatsapp-channels/list.html index 443503ede..1d54a2332 100644 --- a/layouts/whatsapp-channels/list.html +++ b/layouts/whatsapp-channels/list.html @@ -77,7 +77,7 @@

alt='WhatsApp Channel Logo' style='width: 5rem' > -

+

Get WhatsApp Channels

@@ -94,7 +94,7 @@

Send Messages

API -

+

Receive Messages

diff --git a/layouts/whatsapp-groups/list.html b/layouts/whatsapp-groups/list.html index 2380630c2..3d4b1ecef 100644 --- a/layouts/whatsapp-groups/list.html +++ b/layouts/whatsapp-groups/list.html @@ -71,7 +71,7 @@

alt='WhatsApp Groups Logo' style='width: 5rem' > -

+

Get WhatsApp Groups

@@ -87,7 +87,7 @@

Send Messages

API -

+

Receive Messages

diff --git a/layouts/whatsapp-plus-csharp/list.html b/layouts/whatsapp-plus-csharp/list.html index 55fe17d17..a245e3358 100644 --- a/layouts/whatsapp-plus-csharp/list.html +++ b/layouts/whatsapp-plus-csharp/list.html @@ -27,22 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + C# + WhatsApp + C#
@@ -65,17 +59,23 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/csharp/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/csharp/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/csharp/receive-message.md") | safeHTML }}
@@ -111,4 +111,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-go/list.html b/layouts/whatsapp-plus-go/list.html index c7d63c4be..31ef697c3 100644 --- a/layouts/whatsapp-plus-go/list.html +++ b/layouts/whatsapp-plus-go/list.html @@ -27,22 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + Go + WhatsApp + Go

@@ -65,17 +59,23 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/go/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/go/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/go/receive-message.md") | safeHTML }}
@@ -106,4 +106,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-java/list.html b/layouts/whatsapp-plus-java/list.html index 7432d09a9..2f8d25c89 100644 --- a/layouts/whatsapp-plus-java/list.html +++ b/layouts/whatsapp-plus-java/list.html @@ -27,22 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + Java + WhatsApp + Java
@@ -65,17 +59,23 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/java/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/java/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/java/receive-message.md") | safeHTML }}
@@ -106,4 +106,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-javascript/list.html b/layouts/whatsapp-plus-javascript/list.html index e9b2bc5b9..ecea5547d 100644 --- a/layouts/whatsapp-plus-javascript/list.html +++ b/layouts/whatsapp-plus-javascript/list.html @@ -18,7 +18,8 @@

WhatsApp + JavaScript/TypeScript

WAHA provides a private, self-hosted, - and free HTTP API to seamlessly integrate and automate WhatsApp using JavaScript or TypeScript. + and free HTTP API to seamlessly integrate and automate WhatsApp using JavaScript + or TypeScript.

Send messages, manage chats, and streamline workflows effortlessly with a simple API!

@@ -26,19 +27,17 @@

WhatsApp + JavaScript/TypeScript

logo + style='border-radius: 50%; width: 7rem' />
WhatsApp + JavaScript + alt='WhatsApp + JavaScript' />
@@ -61,17 +60,22 @@

- WhatsApp Channel Logo - {{ .Page.RenderString (readFile "/layouts/code/language/javascript/install-dependencies.md") | safeHTML }} + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/javascript/install-dependencies.md") | safeHTML + }}
-
+
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/javascript/send-message.md") | safeHTML }}
API +

Receive Message

{{ .Page.RenderString (readFile "/layouts/code/language/javascript/receive-message.md") | safeHTML }}
@@ -101,4 +105,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-kotlin/list.html b/layouts/whatsapp-plus-kotlin/list.html index e9ea99f1c..831a55a7e 100644 --- a/layouts/whatsapp-plus-kotlin/list.html +++ b/layouts/whatsapp-plus-kotlin/list.html @@ -27,21 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + Kotlin + WhatsApp + Kotlin
@@ -64,17 +59,23 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/kotlin/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/kotlin/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/kotlin/receive-message.md") | safeHTML }}
@@ -109,4 +110,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-php/list.html b/layouts/whatsapp-plus-php/list.html index 04784734c..56bf45fb3 100644 --- a/layouts/whatsapp-plus-php/list.html +++ b/layouts/whatsapp-plus-php/list.html @@ -27,21 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + PHP + WhatsApp + PHP
@@ -64,17 +59,23 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

+ {{ .Page.RenderString (readFile "/layouts/code/language/php/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/php/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/php/receive-message.md") | safeHTML }}
@@ -105,4 +106,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/layouts/whatsapp-plus-python/list.html b/layouts/whatsapp-plus-python/list.html index 36e36e458..046e8a866 100644 --- a/layouts/whatsapp-plus-python/list.html +++ b/layouts/whatsapp-plus-python/list.html @@ -27,21 +27,16 @@

{{ .Summary }}

logo + style='border-radius: 50%; width: 7rem' />
- WhatsApp + Python + WhatsApp + Python
@@ -64,17 +59,22 @@

- WhatsApp Channel Logo + WhatsApp Channel Logo +

Install Dependencies

{{ .Page.RenderString (readFile "/layouts/code/language/python/install-dependencies.md") | safeHTML }}
Free +

Send Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/python/send-message.md") | safeHTML }}
API +

Receive Message

+ {{ .Page.RenderString (readFile "/layouts/code/language/python/receive-message.md") | safeHTML }}
@@ -109,4 +109,4 @@

{{ $content := readFile "/layouts/include/why-waha-section.html" | safeHTML }} {{ $content }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/static/site.webmanifest b/static/site.webmanifest index 10578cfe1..58a7c248e 100644 --- a/static/site.webmanifest +++ b/static/site.webmanifest @@ -1 +1,11 @@ -{"name":"WAHA - WhatsApp API","short_name":"WAHA","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} +{ + "name": "WAHA - WhatsApp API", + "short_name": "WAHA", + "icons": [ + { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/static/swagger/index.css b/static/swagger/index.css index f2376fdaa..11a5b3221 100644 --- a/static/swagger/index.css +++ b/static/swagger/index.css @@ -1,16 +1,16 @@ -html { - box-sizing: border-box; - overflow: -moz-scrollbars-vertical; - overflow-y: scroll; -} - -*, -*:before, -*:after { - box-sizing: inherit; -} - -body { - margin: 0; - background: #fafafa; -} +html { + box-sizing: border-box; + overflow: -moz-scrollbars-vertical; + overflow-y: scroll; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + margin: 0; + background: #fafafa; +} diff --git a/static/swagger/openapi.json b/static/swagger/openapi.json index 6266aa3a5..e44f6367c 100644 --- a/static/swagger/openapi.json +++ b/static/swagger/openapi.json @@ -1,12621 +1,10662 @@ -{ - "openapi": "3.1.0", - "paths": { - "/api/{session}/auth/qr": { - "get": { - "operationId": "AuthController_getQR", - "summary": "Get QR code for pairing WhatsApp API.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "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": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RequestCodeRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🔑 Auth" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions": { - "get": { - "operationId": "SessionsController_list", - "summary": "List all sessions", - "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": [] - } - ] - }, - "post": { - "operationId": "SessionsController_create", - "summary": "Create a session", - "description": "Create session a new session (and start it at the same time if required).", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionCreateRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}": { - "get": { - "operationId": "SessionsController_get", - "summary": "Get session information", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionInfo" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "put": { - "operationId": "SessionsController_update", - "summary": "Update a session", - "description": "", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionUpdateRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "SessionsController_delete", - "summary": "Delete the session", - "description": "Delete the session with the given name. Stop and logout as well. Idempotent operation.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}/me": { - "get": { - "operationId": "SessionsController_getMe", - "summary": "Get information about the authenticated account", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MeInfo" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}/start": { - "post": { - "operationId": "SessionsController_start", - "summary": "Start the session", - "description": "Start the session with the given name. The session must exist. Idempotent operation.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}/stop": { - "post": { - "operationId": "SessionsController_stop", - "summary": "Stop the session", - "description": "Stop the session with the given name. Idempotent operation.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}/logout": { - "post": { - "operationId": "SessionsController_logout", - "summary": "Logout from the session", - "description": "Logout the session, restart a session if it was not STOPPED", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/{session}/restart": { - "post": { - "operationId": "SessionsController_restart", - "summary": "Restart the session", - "description": "Restart the session with the given name.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/start": { - "post": { - "operationId": "SessionsController_DEPRACATED_start", - "summary": "Upsert and Start session", - "description": "Create session (if not exists) or update a config (if exists) and start it.", - "deprecated": true, - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionStartDeprecatedRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDTO" - } - } - } - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/stop": { - "post": { - "operationId": "SessionsController_DEPRECATED_stop", - "summary": "Stop (and Logout if asked) session", - "description": "Stop session and Logout by default.", - "deprecated": true, - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionStopDeprecatedRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sessions/logout": { - "post": { - "operationId": "SessionsController_DEPRECATED_logout", - "summary": "Logout and Delete session.", - "description": "Stop, Logout and Delete session.", - "deprecated": true, - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionLogoutDeprecatedRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🖥️ Sessions" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/profile": { - "get": { - "operationId": "ProfileController_getMyProfile", - "summary": "Get my profile", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MyProfile" - } - } - } - } - }, - "tags": [ - "🆔 Profile" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/profile/name": { - "put": { - "operationId": "ProfileController_setProfileName", - "summary": "Set my profile name", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProfileNameRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "🆔 Profile" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/profile/status": { - "put": { - "operationId": "ProfileController_setProfileStatus", - "summary": "Set profile status (About)", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProfileStatusRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "🆔 Profile" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/profile/picture": { - "put": { - "operationId": "ProfileController_setProfilePicture", - "summary": "Set profile picture", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProfilePictureRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "🆔 Profile" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "ProfileController_deleteProfilePicture", - "summary": "Delete profile picture", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "🆔 Profile" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendText": { - "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": [] - } - ] - }, - "get": { - "operationId": "ChattingController_sendTextGet", - "summary": "Send a text message", - "deprecated": true, - "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": [] - } - ] - } - }, - "/api/sendImage": { - "post": { - "operationId": "ChattingController_sendImage", - "summary": "Send an image", - "description": "Either from an URL or base64 data - look at the request schemas for details.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageImageRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendFile": { - "post": { - "operationId": "ChattingController_sendFile", - "summary": "Send a file", - "description": "Either from an URL or base64 data - look at the request schemas for details.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageFileRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendVoice": { - "post": { - "operationId": "ChattingController_sendVoice", - "summary": "Send an voice message", - "description": "Either from an URL or base64 data - look at the request schemas for details.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageVoiceRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendVideo": { - "post": { - "operationId": "ChattingController_sendVideo", - "summary": "Send a video", - "description": "Either from an URL or base64 data - look at the request schemas for details.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageVideoRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/send/link-custom-preview": { - "post": { - "operationId": "ChattingController_sendLinkCustomPreview", - "summary": "Send a text message with a CUSTOM link preview.", - "description": "You can use regular /api/sendText if you wanna send auto-generated link preview.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageLinkCustomPreviewRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendButtons": { - "post": { - "operationId": "ChattingController_sendButtons", - "summary": "Send buttons (interactive message)", - "description": "Send Buttons", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendButtonsRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/forwardMessage": { - "post": { - "operationId": "ChattingController_forwardMessage", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageForwardRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAMessage" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendSeen": { - "post": { - "operationId": "ChattingController_sendSeen", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendSeenRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/startTyping": { - "post": { - "operationId": "ChattingController_startTyping", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/stopTyping": { - "post": { - "operationId": "ChattingController_stopTyping", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/reaction": { - "put": { - "operationId": "ChattingController_setReaction", - "summary": "React to a message with an emoji", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageReactionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/star": { - "put": { - "operationId": "ChattingController_setStar", - "summary": "Star or unstar a message", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageStarRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendPoll": { - "post": { - "operationId": "ChattingController_sendPoll", - "summary": "Send a poll with options", - "description": "You can use it as buttons or list replacement", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessagePollRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendLocation": { - "post": { - "operationId": "ChattingController_sendLocation", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageLocationRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "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/send/buttons/reply": { - "post": { - "operationId": "ChattingController_sendButtonsReply", - "summary": "Reply on a button message", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageButtonReply" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/messages": { - "get": { - "operationId": "ChattingController_getMessages", - "summary": "Get messages in a chat", - "description": "DEPRECATED. Use \"GET /api/chats/{id}/messages\" instead", - "deprecated": true, - "parameters": [ - { - "name": "downloadMedia", - "required": false, - "in": "query", - "example": false, - "description": "Download media for messages", - "schema": { - "default": true, - "type": "boolean" - } - }, - { - "name": "chatId", - "required": true, - "in": "query", - "example": "11111111111@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - }, - { - "name": "limit", - "required": true, - "in": "query", - "schema": { - "default": 10, - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "filter.timestamp.lte", - "required": false, - "in": "query", - "description": "Filter messages before this timestamp (inclusive)", - "schema": { - "type": "number" - } - }, - { - "name": "filter.timestamp.gte", - "required": false, - "in": "query", - "description": "Filter messages after this timestamp (inclusive)", - "schema": { - "type": "number" - } - }, - { - "name": "filter.fromMe", - "required": false, - "in": "query", - "description": "From me filter (by default shows all messages)", - "schema": { - "type": "boolean" - } - }, - { - "name": "filter.ack", - "required": false, - "in": "query", - "description": "Filter messages by acknowledgment status", - "schema": { - "enum": [ - "ERROR", - "PENDING", - "SERVER", - "DEVICE", - "READ", - "PLAYED" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WAMessage" - } - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/checkNumberStatus": { - "get": { - "operationId": "ChattingController_DEPRECATED_checkNumberStatus", - "summary": "Check number status", - "description": "DEPRECATED. Use \"POST /contacts/check-exists\" instead", - "deprecated": true, - "parameters": [ - { - "name": "phone", - "required": true, - "in": "query", - "description": "The phone number to check", - "example": "1213213213", - "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/reply": { - "post": { - "operationId": "ChattingController_reply", - "summary": "DEPRECATED - you can set \"reply_to\" field when sending text, image, etc", - "deprecated": true, - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageReplyRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/sendLinkPreview": { - "post": { - "operationId": "ChattingController_sendLinkPreview_DEPRECATED", - "summary": "", - "deprecated": true, - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageLinkPreviewRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📤 Chatting" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats": { - "get": { - "operationId": "ChatsController_getChats", - "summary": "Get chats", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "sortBy", - "required": false, - "in": "query", - "description": "Sort by field", - "schema": { - "enum": [ - "conversationTimestamp", - "id", - "name" - ], - "type": "string" - } - }, - { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", - "schema": { - "enum": [ - "desc", - "asc" - ], - "type": "string" - } - }, - { - "name": "limit", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/overview": { - "get": { - "operationId": "ChatsController_getChatsOverview", - "summary": "Get chats overview. Includes all necessary things to build UI \"your chats overview\" page - chat id, name, picture, last message. Sorting by last message timestamp", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "limit", - "required": false, - "in": "query", - "schema": { - "default": 20, - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "ids", - "required": false, - "in": "query", - "description": "Filter by chat ids", - "example": [ - "111111111@c.us" - ], - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatSummary" - } - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "post": { - "operationId": "ChatsController_postChatsOverview", - "summary": "Get chats overview. Use POST if you have too many \"ids\" params - GET can limit it", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OverviewBodyRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatSummary" - } - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}": { - "delete": { - "operationId": "ChatsController_deleteChat", - "summary": "Deletes the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/picture": { - "get": { - "operationId": "ChatsController_getChatPicture", - "summary": "Gets chat picture", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "refresh", - "required": false, - "in": "query", - "example": false, - "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", - "schema": { - "default": false, - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatPictureResponse" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/messages": { - "get": { - "operationId": "ChatsController_getChatMessages", - "summary": "Gets messages in the chat", - "parameters": [ - { - "name": "downloadMedia", - "required": false, - "in": "query", - "example": false, - "description": "Download media for messages", - "schema": { - "default": true, - "type": "boolean" - } - }, - { - "name": "limit", - "required": true, - "in": "query", - "schema": { - "default": 10, - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "filter.timestamp.lte", - "required": false, - "in": "query", - "description": "Filter messages before this timestamp (inclusive)", - "schema": { - "type": "number" - } - }, - { - "name": "filter.timestamp.gte", - "required": false, - "in": "query", - "description": "Filter messages after this timestamp (inclusive)", - "schema": { - "type": "number" - } - }, - { - "name": "filter.fromMe", - "required": false, - "in": "query", - "description": "From me filter (by default shows all messages)", - "schema": { - "type": "boolean" - } - }, - { - "name": "filter.ack", - "required": false, - "in": "query", - "description": "Filter messages by acknowledgment status", - "schema": { - "enum": [ - "ERROR", - "PENDING", - "SERVER", - "DEVICE", - "READ", - "PLAYED" - ], - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WAMessage" - } - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "ChatsController_clearMessages", - "summary": "Clears all messages from the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/messages/read": { - "post": { - "operationId": "ChatsController_readChatMessages", - "summary": "Read unread messages in the chat", - "parameters": [ - { - "name": "messages", - "required": false, - "in": "query", - "example": 30, - "description": "How much messages to read (latest first)", - "schema": { - "type": "number" - } - }, - { - "name": "days", - "required": false, - "in": "query", - "description": "How much days to read (latest first)", - "schema": { - "default": 7, - "type": "number" - } - }, - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReadChatMessagesResponse" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/messages/{messageId}": { - "get": { - "operationId": "ChatsController_getChatMessage", - "summary": "Gets message by id", - "parameters": [ - { - "name": "downloadMedia", - "required": false, - "in": "query", - "example": true, - "description": "Download media for messages", - "schema": { - "default": true, - "type": "boolean" - } - }, - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "messageId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAMessage" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "ChatsController_deleteMessage", - "summary": "Deletes a message from the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "messageId", - "required": true, - "in": "path", - "description": "Message ID in format {fromMe}_{chat}_{message_id}[_{participant}]", - "example": "true_123456789@c.us_BAE6A33293978B16", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "put": { - "operationId": "ChatsController_editMessage", - "summary": "Edits a message in the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "messageId", - "required": true, - "in": "path", - "description": "Message ID in format {fromMe}_{chat}_{message_id}[_{participant}]", - "example": "true_123456789@c.us_BAE6A33293978B16", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EditMessageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/messages/{messageId}/pin": { - "post": { - "operationId": "ChatsController_pinMessage", - "summary": "Pins a message in the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "messageId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PinMessageRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/messages/{messageId}/unpin": { - "post": { - "operationId": "ChatsController_unpinMessage", - "summary": "Unpins a message in the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "messageId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/archive": { - "post": { - "operationId": "ChatsController_archiveChat", - "summary": "Archive the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/unarchive": { - "post": { - "operationId": "ChatsController_unarchiveChat", - "summary": "Unarchive the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/chats/{chatId}/unread": { - "post": { - "operationId": "ChatsController_unreadChat", - "summary": "Unread the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "💬 Chats" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels": { - "get": { - "operationId": "ChannelsController_list", - "summary": "Get list of know channels", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "role", - "required": false, - "in": "query", - "schema": { - "enum": [ - "OWNER", - "ADMIN", - "SUBSCRIBER" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Channel" - } - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "post": { - "operationId": "ChannelsController_create", - "summary": "Create a new channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChannelRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Channel" - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}": { - "delete": { - "operationId": "ChannelsController_delete", - "summary": "Delete the channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID" - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "get": { - "operationId": "ChannelsController_get", - "summary": "Get the channel info", - "description": "You can use either id (123@newsletter) OR invite code (https://www.whatsapp.com/channel/123)", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID or invite code from invite link https://www.whatsapp.com/channel/11111" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Channel" - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}/messages/preview": { - "get": { - "operationId": "ChannelsController_previewChannelMessages", - "summary": "Preview channel messages", - "description": "You can use either invite code (https://www.whatsapp.com/channel/123) or (123)ORChannel ID (123@newsletter).", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Channel id or invite code", - "schema": { - "default": "0029Va4K0PZ5a245NkngBA2M" - } - }, - { - "name": "downloadMedia", - "required": true, - "in": "query", - "schema": { - "default": false, - "type": "boolean" - } - }, - { - "name": "limit", - "required": true, - "in": "query", - "schema": { - "default": 10, - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelMessage" - } - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}/follow": { - "post": { - "operationId": "ChannelsController_follow", - "summary": "Follow the channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID" - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}/unfollow": { - "post": { - "operationId": "ChannelsController_unfollow", - "summary": "Unfollow the channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID" - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}/mute": { - "post": { - "operationId": "ChannelsController_mute", - "summary": "Mute the channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID" - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/{id}/unmute": { - "post": { - "operationId": "ChannelsController_unmute", - "summary": "Unmute the channel.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "default": "123123123@newsletter" - }, - "description": "WhatsApp Channel ID" - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/search/by-view": { - "post": { - "operationId": "ChannelsController_searchByView", - "summary": "Search for channels (by view)", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelSearchByView" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelListResult" - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/search/by-text": { - "post": { - "operationId": "ChannelsController_searchByText", - "summary": "Search for channels (by text)", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelSearchByText" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelListResult" - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/search/views": { - "get": { - "operationId": "ChannelsController_getSearchViews", - "summary": "Get list of views for channel search", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelView" - } - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/search/countries": { - "get": { - "operationId": "ChannelsController_getSearchCountries", - "summary": "Get list of countries for channel search", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelCountry" - } - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/channels/search/categories": { - "get": { - "operationId": "ChannelsController_getSearchCategories", - "summary": "Get list of categories for channel search", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelCategory" - } - } - } - } - } - }, - "tags": [ - "📢 Channels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/text": { - "post": { - "operationId": "StatusController_sendTextStatus", - "summary": "Send text status", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TextStatus" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/image": { - "post": { - "operationId": "StatusController_sendImageStatus", - "summary": "Send image status", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImageStatus" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/voice": { - "post": { - "operationId": "StatusController_sendVoiceStatus", - "summary": "Send voice status", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VoiceStatus" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/video": { - "post": { - "operationId": "StatusController_sendVideoStatus", - "summary": "Send video status", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VideoStatus" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/delete": { - "post": { - "operationId": "StatusController_deleteStatus", - "summary": "DELETE sent status", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteStatusRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/status/new-message-id": { - "get": { - "operationId": "StatusController_getNewMessageId", - "summary": "Generate message ID you can use to batch contacts", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NewMessageIDResponse" - } - } - } - } - }, - "tags": [ - "🟢 Status" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/labels": { - "get": { - "operationId": "LabelsController_getAll", - "summary": "Get all labels", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Label" - } - } - } - } - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "post": { - "operationId": "LabelsController_create", - "summary": "Create a new label", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LabelBody" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Label" - } - } - } - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/labels/{labelId}": { - "put": { - "operationId": "LabelsController_update", - "summary": "Update a label", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "labelId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LabelBody" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Label" - } - } - } - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "LabelsController_delete", - "summary": "Delete a label", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "labelId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/labels/chats/{chatId}": { - "get": { - "operationId": "LabelsController_getChatLabels", - "summary": "Get labels for the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Label" - } - } - } - } - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "put": { - "operationId": "LabelsController_putChatLabels", - "summary": "Save labels for the chat", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetLabelsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/labels/{labelId}/chats": { - "get": { - "operationId": "LabelsController_getChatsByLabel", - "summary": "Get chats by label", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "labelId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "🏷️ Labels" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/all": { - "get": { - "operationId": "ContactsController_getAll", - "summary": "Get all contacts", - "parameters": [ - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - }, - { - "name": "sortBy", - "required": false, - "in": "query", - "description": "Sort by field", - "schema": { - "enum": [ - "id", - "name" - ], - "type": "string" - } - }, - { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", - "schema": { - "enum": [ - "desc", - "asc" - ], - "type": "string" - } - }, - { - "name": "limit", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts": { - "get": { - "operationId": "ContactsController_get", - "summary": "Get contact basic info", - "description": "The method always return result, even if the phone number is not registered in WhatsApp. For that - use /contacts/check-exists endpoint below.", - "parameters": [ - { - "name": "contactId", - "required": true, - "in": "query", - "example": "11111111111@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/check-exists": { - "get": { - "operationId": "ContactsController_checkExists", - "summary": "Check phone number is registered in WhatsApp.", - "parameters": [ - { - "name": "phone", - "required": true, - "in": "query", - "description": "The phone number to check", - "example": "1213213213", - "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": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/about": { - "get": { - "operationId": "ContactsController_getAbout", - "summary": "Gets the Contact's \"about\" info", - "description": "Returns null if you do not have permission to read their status.", - "parameters": [ - { - "name": "contactId", - "required": true, - "in": "query", - "example": "11111111111@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/profile-picture": { - "get": { - "operationId": "ContactsController_getProfilePicture", - "summary": "Get contact's profile picture URL", - "description": "If privacy settings do not allow to get the picture, the method will return null.", - "parameters": [ - { - "name": "contactId", - "required": true, - "in": "query", - "example": "11111111111@c.us", - "schema": { - "type": "string" - } - }, - { - "name": "refresh", - "required": false, - "in": "query", - "example": false, - "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", - "schema": { - "default": false, - "type": "boolean" - } - }, - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/block": { - "post": { - "operationId": "ContactsController_block", - "summary": "Block contact", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContactRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/contacts/unblock": { - "post": { - "operationId": "ContactsController_unblock", - "summary": "Unblock contact", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContactRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/lids": { - "get": { - "operationId": "LidsController_getAll", - "summary": "Get all known lids to phone number mapping", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "limit", - "required": false, - "in": "query", - "schema": { - "default": 100, - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "default": 0, - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LidToPhoneNumber" - } - } - } - } - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/lids/count": { - "get": { - "operationId": "LidsController_getLidsCount", - "summary": "Get the number of known lids", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CountResponse" - } - } - } - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/lids/{lid}": { - "get": { - "operationId": "LidsController_findPNByLid", - "summary": "Get phone number by lid", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "lid", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LidToPhoneNumber" - } - } - } - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/lids/pn/{phoneNumber}": { - "get": { - "operationId": "LidsController_findLIDByPhoneNumber", - "summary": "Get lid by phone number (chat id)", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "phoneNumber", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LidToPhoneNumber" - } - } - } - } - }, - "tags": [ - "👤 Contacts" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups": { - "post": { - "operationId": "GroupsController_createGroup", - "summary": "Create a new group.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGroupRequest" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "get": { - "operationId": "GroupsController_getGroups", - "summary": "Get all groups.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "sortBy", - "required": false, - "in": "query", - "description": "Sort by field", - "schema": { - "enum": [ - "id", - "subject" - ], - "type": "string" - } - }, - { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", - "schema": { - "enum": [ - "desc", - "asc" - ], - "type": "string" - } - }, - { - "name": "limit", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "offset", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "exclude", - "required": false, - "in": "query", - "description": "Exclude fields", - "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "", - "participants" - ] - } - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/join-info": { - "get": { - "operationId": "GroupsController_joinInfoGroup", - "summary": "Get info about the group before joining.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "code", - "required": true, - "in": "query", - "description": "Group code (123) or url (https://chat.whatsapp.com/123)", - "example": "https://chat.whatsapp.com/1234567890abcdef", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/join": { - "post": { - "operationId": "GroupsController_joinGroup", - "summary": "Join group via code", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JoinGroupRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JoinGroupResponse" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/count": { - "get": { - "operationId": "GroupsController_getGroupsCount", - "summary": "Get the number of groups.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CountResponse" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/refresh": { - "post": { - "operationId": "GroupsController_refreshGroups", - "summary": "Refresh groups from the server.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}": { - "get": { - "operationId": "GroupsController_getGroup", - "summary": "Get the group.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "GroupsController_deleteGroup", - "summary": "Delete the group.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/leave": { - "post": { - "operationId": "GroupsController_leaveGroup", - "summary": "Leave the group.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/picture": { - "get": { - "operationId": "GroupsController_getChatPicture", - "summary": "Get group picture", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - }, - { - "name": "refresh", - "required": false, - "in": "query", - "example": false, - "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", - "schema": { - "default": false, - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatPictureResponse" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "put": { - "operationId": "GroupsController_setPicture", - "summary": "Set group picture", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProfilePictureRequest" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "delete": { - "operationId": "GroupsController_deletePicture", - "summary": "Delete group picture", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - }, - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Result" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/description": { - "put": { - "operationId": "GroupsController_setDescription", - "summary": "Updates the group description.", - "description": "Returns \"true\" if the subject was properly updated. This can return \"false\" if the user does not have the necessary permissions.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DescriptionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/subject": { - "put": { - "operationId": "GroupsController_setSubject", - "summary": "Updates the group subject", - "description": "Returns \"true\" if the subject was properly updated. This can return \"false\" if the user does not have the necessary permissions.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubjectRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/settings/security/info-admin-only": { - "put": { - "operationId": "GroupsController_setInfoAdminOnly", - "summary": "Updates the group \"info admin only\" settings.", - "description": "You can allow only admins to edit group info (title, description, photo).", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsSecurityChangeInfo" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "get": { - "operationId": "GroupsController_getInfoAdminOnly", - "summary": "Get the group's 'info admin only' settings.", - "description": "You can allow only admins to edit group info (title, description, photo).", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsSecurityChangeInfo" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/settings/security/messages-admin-only": { - "put": { - "operationId": "GroupsController_setMessagesAdminOnly", - "summary": "Update settings - who can send messages", - "description": "Updates the group settings to only allow admins to send messages.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsSecurityChangeInfo" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "get": { - "operationId": "GroupsController_getMessagesAdminOnly", - "summary": "Get settings - who can send messages", - "description": "The group settings to only allow admins to send messages.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsSecurityChangeInfo" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/invite-code": { - "get": { - "operationId": "GroupsController_getInviteCode", - "summary": "Gets the invite code for the group.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "string" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/invite-code/revoke": { - "post": { - "operationId": "GroupsController_revokeInviteCode", - "summary": "Invalidates the current group invite code and generates a new one.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "string" - } - } - } - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/participants": { - "get": { - "operationId": "GroupsController_getParticipants", - "summary": "Get participants", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/participants/add": { - "post": { - "operationId": "GroupsController_addParticipants", - "summary": "Add participants", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ParticipantsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/participants/remove": { - "post": { - "operationId": "GroupsController_removeParticipants", - "summary": "Remove participants", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ParticipantsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/admin/promote": { - "post": { - "operationId": "GroupsController_promoteToAdmin", - "summary": "Promote participants to admin users.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ParticipantsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/groups/{id}/admin/demote": { - "post": { - "operationId": "GroupsController_demoteToAdmin", - "summary": "Demotes participants to regular users.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "id", - "required": true, - "in": "path", - "description": "Group ID", - "example": "123123123@g.us", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ParticipantsRequest" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "👥 Groups" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/presence": { - "post": { - "operationId": "PresenceController_setPresence", - "summary": "Set session presence", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHASessionPresence" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "✅ Presence" - ], - "security": [ - { - "api_key": [] - } - ] - }, - "get": { - "operationId": "PresenceController_getPresenceAll", - "summary": "Get all subscribed presence information.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WAHAChatPresences" - } - } - } - } - } - }, - "tags": [ - "✅ Presence" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/presence/{chatId}": { - "get": { - "operationId": "PresenceController_getPresence", - "summary": "Get the presence for the chat id. If it hasn't been subscribed - it also subscribes to it.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAChatPresences" - } - } - } - } - }, - "tags": [ - "✅ Presence" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/presence/{chatId}/subscribe": { - "post": { - "operationId": "PresenceController_subscribe", - "summary": "Subscribe to presence events for the chat.", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - }, - { - "name": "chatId", - "required": true, - "in": "path", - "description": "Chat ID", - "example": "123456789@c.us", - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "" - } - }, - "tags": [ - "✅ Presence" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/screenshot": { - "get": { - "operationId": "ScreenshotController_screenshot", - "parameters": [ - { - "name": "session", - "required": true, - "in": "query", - "schema": { - "default": "default", - "type": "string" - } - } - ], - "responses": { - "200": { - "content": { - "image/png": { - "schema": { - "type": "string", - "format": "binary" - } - }, - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/Base64File" - } - ] - } - } - }, - "description": "" - } - }, - "tags": [ - "🖼️ Screenshot" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/{session}/events": { - "post": { - "operationId": "EventsController_sendEvent", - "summary": "Send an event message", - "parameters": [ - { - "name": "session", - "required": true, - "in": "path", - "schema": { - "default": "default" - }, - "description": "Session name" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventMessageRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAMessage" - } - } - } - } - }, - "tags": [ - "📅 Events" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/ping": { - "get": { - "operationId": "PingController_ping", - "summary": "Ping the server", - "description": "Check if the server is alive and responding to requests.", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PingResponse" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/health": { - "get": { - "operationId": "HealthController_check", - "summary": "Check the health of the server", - "description": "Perform all health checks and return the server's health status.", - "parameters": [], - "responses": { - "200": { - "description": "The Health Check is successful", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "ok" - }, - "info": { - "type": "object", - "example": { - "database": { - "status": "up" - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - }, - "nullable": true - }, - "error": { - "type": "object", - "example": {}, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - }, - "nullable": true - }, - "details": { - "type": "object", - "example": { - "database": { - "status": "up" - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - } - } - } - } - } - } - }, - "503": { - "description": "The Health Check is not successful", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "error" - }, - "info": { - "type": "object", - "example": { - "database": { - "status": "up" - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - }, - "nullable": true - }, - "error": { - "type": "object", - "example": { - "redis": { - "status": "down", - "message": "Could not connect" - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - }, - "nullable": true - }, - "details": { - "type": "object", - "example": { - "database": { - "status": "up" - }, - "redis": { - "status": "down", - "message": "Could not connect" - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string" - } - }, - "additionalProperties": true - } - } - } - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/server/version": { - "get": { - "operationId": "ServerController_get", - "summary": "Get the version of the server", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/server/environment": { - "get": { - "operationId": "ServerController_environment", - "summary": "Get the server environment", - "parameters": [ - { - "name": "all", - "required": false, - "in": "query", - "example": false, - "description": "Include all environment variables", - "schema": { - "default": false, - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/server/status": { - "get": { - "operationId": "ServerController_status", - "summary": "Get the server status", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServerStatusResponse" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/server/stop": { - "post": { - "operationId": "ServerController_stop", - "summary": "Stop (and restart) the server", - "description": "If you're using docker, after calling this endpoint Docker will start a new container, so you can use this endpoint to restart the server", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StopRequest" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StopResponse" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/server/debug/heapsnapshot": { - "get": { - "operationId": "ServerDebugController_heapsnapshot", - "summary": "Return a heapsnapshot", - "description": "Return a heapsnapshot of the server's memory", - "parameters": [], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - }, - "/api/version": { - "get": { - "operationId": "VersionController_get", - "summary": "Get the server version ", - "deprecated": true, - "description": "Use 'GET /api/server/version' instead ", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - } - } - } - }, - "tags": [ - "🔍 Observability" - ], - "security": [ - { - "api_key": [] - } - ] - } - } - }, - "info": { - "title": "WAHA - WhatsApp HTTP API", - "description": "WhatsApp HTTP API that you can run in a click!
📊 Dashboard

Learn more:

Support the project and get WAHA Plus version!

", - "version": "2025.5.5", - "contact": {} - }, - "tags": [ - { - "name": "🖥️ Sessions", - "description": "Control WhatsApp sessions (accounts)" - }, - { - "name": "🔑 Auth", - "description": "Authentication" - }, - { - "name": "🆔 Profile", - "description": "Your profile information" - }, - { - "name": "🖼️ Screenshot", - "description": "Get screenshot of WhatsApp and show QR code" - }, - { - "name": "📤 Chatting", - "description": "Chatting methods" - }, - { - "name": "📢 Channels", - "description": "Channels (newsletters) methods" - }, - { - "name": "🟢 Status", - "description": "Status (aka stories) methods" - }, - { - "name": "💬 Chats", - "description": "Chats methods" - }, - { - "name": "👤 Contacts", - "description": "Contacts methods.
\n Use phone number (without +) or phone number and `@c.us` at the end as `contactId`.
\n 'E.g: `12312312310` OR `12312312310@c.us`
" - }, - { - "name": "👥 Groups", - "description": "Groups methods.
" - }, - { - "name": "✅ Presence", - "description": "Presence information" - }, - { - "name": "📅 Events", - "description": "Event Message" - }, - { - "name": "🏷️ Labels", - "description": "Labels - available only for WhatsApp Business accounts" - }, - { - "name": "🔍 Observability", - "description": "Other methods" - }, - { - "name": "🗄️ Storage", - "description": "Storage methods" - } - ], - "servers": [ - { - "url": "{protocol}://{host}:{port}/{baseUrl}", - "description": "", - "variables": { - "protocol": { - "default": "http", - "enum": [ - "http", - "https" - ], - "description": "The protocol used to access the server." - }, - "host": { - "default": "localhost", - "description": "The hostname or IP address of the server." - }, - "port": { - "default": "3000", - "description": "The port number on which the server is listening for requests" - }, - "baseUrl": { - "default": "", - "description": "The base URL path for all API endpoints. This can be used to group related endpoints together under a common path." - } - } - } - ], - "components": { - "securitySchemes": { - "api_key": { - "type": "apiKey", - "in": "header", - "name": "X-Api-Key", - "description": "Your secret api key" - } - }, - "schemas": { - "Base64File": { - "type": "object", - "properties": { - "mimetype": { - "type": "string" - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimetype", - "data" - ] - }, - "QRCodeValue": { - "type": "object", - "properties": { - "value": { - "type": "string" - } - }, - "required": [ - "value" - ] - }, - "RequestCodeRequest": { - "type": "object", - "properties": { - "phoneNumber": { - "type": "string", - "description": "Mobile phone number in international format", - "example": "12132132130" - }, - "method": { - "type": "string", - "description": "How would you like to receive the one time code for registration? |sms|voice. Leave empty for Web pairing.", - "example": null - } - }, - "required": [ - "phoneNumber" - ] - }, - "MeInfo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "11111111111@c.us" - }, - "pushName": { - "type": "string" - } - }, - "required": [ - "id", - "pushName" - ] - }, - "Map": { - "type": "object", - "properties": {} - }, - "ProxyConfig": { - "type": "object", - "properties": { - "server": { - "type": "string", - "example": "localhost:3128" - }, - "username": { - "type": "string", - "example": null - }, - "password": { - "type": "string", - "example": null - } - }, - "required": [ - "server" - ] - }, - "NowebStoreConfig": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false, - "description": "Enable or disable the store for contacts, chats, and messages.", - "example": true - }, - "fullSync": { - "type": "boolean", - "default": false, - "description": "Enable full sync on session initialization (when scanning QR code).\nFull sync will download all contacts, chats, and messages from the phone.\nIf disabled, only messages early than 90 days will be downloaded and some contacts may be missing." - } - }, - "required": [ - "enabled", - "fullSync" - ] - }, - "NowebConfig": { - "type": "object", - "properties": { - "markOnline": { - "type": "boolean", - "default": true, - "description": "Mark the session as online when it connects to the server." - }, - "store": { - "$ref": "#/components/schemas/NowebStoreConfig" - } - }, - "required": [ - "markOnline" - ] - }, - "HmacConfiguration": { - "type": "object", - "properties": { - "key": { - "type": "string", - "example": "your-secret-key" - } - } - }, - "RetriesConfiguration": { - "type": "object", - "properties": { - "delaySeconds": { - "type": "number", - "example": 2 - }, - "attempts": { - "type": "number", - "example": 15 - }, - "policy": { - "enum": [ - "linear", - "exponential", - "constant" - ], - "type": "string", - "example": "linear" - } - } - }, - "CustomHeader": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "X-My-Custom-Header" - }, - "value": { - "type": "string", - "example": "Value" - } - }, - "required": [ - "name", - "value" - ] - }, - "WebhookConfig": { - "type": "object", - "properties": { - "url": { - "type": "string", - "example": "https://webhook.site/11111111-1111-1111-1111-11111111", - "description": "You can use https://docs.webhook.site/ to test webhooks and see the payload" - }, - "events": { - "example": [ - "message", - "session.status" - ], - "type": "array", - "items": { - "type": "object" - } - }, - "hmac": { - "example": null, - "allOf": [ - { - "$ref": "#/components/schemas/HmacConfiguration" - } - ] - }, - "retries": { - "example": null, - "allOf": [ - { - "$ref": "#/components/schemas/RetriesConfiguration" - } - ] - }, - "customHeaders": { - "example": null, - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomHeader" - } - } - }, - "required": [ - "url", - "events" - ] - }, - "SessionConfig": { - "type": "object", - "properties": { - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session. You'll get 'metadata' in all webhooks.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "proxy": { - "example": null, - "allOf": [ - { - "$ref": "#/components/schemas/ProxyConfig" - } - ] - }, - "debug": { - "type": "boolean", - "default": false - }, - "noweb": { - "example": { - "store": { - "enabled": true, - "fullSync": false - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/NowebConfig" - } - ] - }, - "webhooks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WebhookConfig" - } - } - } - }, - "SessionInfo": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default", - "description": "Session name (id)" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "assignedWorker": { - "type": "string" - }, - "status": { - "enum": [ - "STOPPED", - "STARTING", - "SCAN_QR_CODE", - "WORKING", - "FAILED" - ], - "type": "string" - }, - "config": { - "$ref": "#/components/schemas/SessionConfig" - } - }, - "required": [ - "name", - "status" - ] - }, - "SessionCreateRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "maxLength": 54, - "example": "default", - "description": "Session name (id)" - }, - "start": { - "type": "boolean", - "description": "Start session after creation", - "example": true, - "default": true - }, - "config": { - "$ref": "#/components/schemas/SessionConfig" - } - } - }, - "SessionDTO": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default", - "description": "Session name (id)" - }, - "status": { - "enum": [ - "STOPPED", - "STARTING", - "SCAN_QR_CODE", - "WORKING", - "FAILED" - ], - "type": "string" - }, - "config": { - "$ref": "#/components/schemas/SessionConfig" - } - }, - "required": [ - "name", - "status" - ] - }, - "SessionUpdateRequest": { - "type": "object", - "properties": { - "config": { - "$ref": "#/components/schemas/SessionConfig" - } - } - }, - "SessionStartDeprecatedRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default", - "description": "Session name (id)" - }, - "config": { - "$ref": "#/components/schemas/SessionConfig" - } - }, - "required": [ - "name" - ] - }, - "SessionStopDeprecatedRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default", - "description": "Session name (id)" - }, - "logout": { - "type": "boolean", - "default": false, - "example": false, - "description": "Stop and logout from the session." - } - }, - "required": [ - "name" - ] - }, - "SessionLogoutDeprecatedRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default", - "description": "Session name (id)" - } - }, - "required": [ - "name" - ] - }, - "MyProfile": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "11111111111@c.us" - }, - "picture": { - "type": "string", - "nullable": true, - "example": "https://example.com/picture.jpg" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "picture", - "name" - ] - }, - "ProfileNameRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "My New Name" - } - }, - "required": [ - "name" - ] - }, - "Result": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "default": true - } - }, - "required": [ - "success" - ] - }, - "ProfileStatusRequest": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "🎉 Hey there! I am using WhatsApp 🎉" - } - }, - "required": [ - "status" - ] - }, - "RemoteFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "string", - "description": "MIME type of the attachment.", - "example": "image/jpeg" - }, - "filename": { - "type": "string", - "description": "Document file name. Value can be null", - "example": "filename.jpg" - }, - "url": { - "type": "string", - "example": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - }, - "required": [ - "mimetype", - "url" - ] - }, - "BinaryFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "string", - "description": "MIME type of the attachment.", - "example": "image/jpeg" - }, - "filename": { - "type": "string", - "description": "Document file name. Optional", - "example": "filename.jpeg" - }, - "data": { - "type": "string", - "description": "Base64-encoded data of the file", - "example": "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" - } - }, - "required": [ - "mimetype", - "data" - ] - }, - "ProfilePictureRequest": { - "type": "object", - "properties": { - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - } - }, - "required": [ - "file" - ] - }, - "MessageTextRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "text": { - "type": "string", - "default": "Hi there!" - }, - "linkPreview": { - "type": "boolean", - "default": true - }, - "linkPreviewHighQuality": { - "type": "boolean", - "default": false - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "text", - "session" - ] - }, - "S3MediaData": { - "type": "object", - "properties": { - "Bucket": { - "type": "string", - "description": "The name of the S3 bucket", - "example": "my-bucket" - }, - "Key": { - "type": "string", - "description": "The key of the object in the S3 bucket", - "example": "default/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" - } - }, - "required": [ - "Bucket", - "Key" - ] - }, - "WAMedia": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "The URL for the media in the message if any", - "example": "http://localhost:3000/api/files/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" - }, - "mimetype": { - "type": "string", - "description": "mimetype for the media in the message if any", - "example": "audio/jpeg" - }, - "filename": { - "type": "string", - "description": "The original filename in mediaUrl in the message if any", - "example": "example.pdf" - }, - "s3": { - "description": "S3 attributes for the media in the message if you are using S3 media storage", - "allOf": [ - { - "$ref": "#/components/schemas/S3MediaData" - } - ] - }, - "error": { - "type": "object", - "description": "Error message if there's an error downloading the media", - "example": null - } - } - }, - "WALocation": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "latitude": { - "type": "string" - }, - "longitude": { - "type": "string" - } - }, - "required": [ - "latitude", - "longitude" - ] - }, - "ReplyToMessage": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "AAAAAAAAAAAAAAAAAAAA" - }, - "participant": { - "type": "string", - "example": "11111111111@c.us" - }, - "body": { - "type": "string", - "example": "Hello!" - }, - "_data": { - "type": "object", - "description": "Raw data from reply's message" - } - }, - "required": [ - "id" - ] - }, - "WAMessage": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "timestamp": { - "type": "number", - "description": "Unix timestamp for when the message was created", - "example": 1666943582 - }, - "from": { - "type": "string", - "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", - "example": "11111111111@c.us" - }, - "fromMe": { - "type": "boolean", - "description": "Indicates if the message was sent by the current user" - }, - "source": { - "enum": [ - "api", - "app" - ], - "type": "string", - "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", - "example": "api" - }, - "to": { - "type": "string", - "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", - "example": "11111111111@c.us" - }, - "participant": { - "type": "string", - "description": "For groups - participant who sent the message" - }, - "body": { - "type": "string", - "description": "Message content" - }, - "hasMedia": { - "type": "boolean", - "description": "Indicates if the message has media available for download" - }, - "media": { - "description": "Media object for the message if any and downloaded", - "allOf": [ - { - "$ref": "#/components/schemas/WAMedia" - } - ] - }, - "mediaUrl": { - "type": "string", - "description": "Use `media.url` instead! The URL for the media in the message if any", - "deprecated": true, - "example": "http://localhost:3000/api/files/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" - }, - "ack": { - "enum": [ - -1, - 0, - 1, - 2, - 3, - 4 - ], - "type": "number", - "description": "ACK status for the message" - }, - "ackName": { - "type": "string", - "description": "ACK status name for the message" - }, - "author": { - "type": "string", - "description": "If the message was sent to a group, this field will contain the user that sent the message." - }, - "location": { - "description": "Location information contained in the message, if the message is type \"location\"", - "allOf": [ - { - "$ref": "#/components/schemas/WALocation" - } - ] - }, - "vCards": { - "description": "List of vCards contained in the message.", - "type": "array", - "items": { - "type": "string" - } - }, - "_data": { - "type": "object", - "description": "Message in a raw format that we get from WhatsApp. May be changed anytime, use it with caution! It depends a lot on the underlying backend." - }, - "replyTo": { - "$ref": "#/components/schemas/ReplyToMessage" - } - }, - "required": [ - "id", - "timestamp", - "from", - "fromMe", - "source", - "to", - "participant", - "body", - "hasMedia", - "mediaUrl", - "ack", - "ackName" - ] - }, - "MessageImageRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "caption": { - "type": "string" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "file", - "session" - ] - }, - "MessageFileRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "caption": { - "type": "string" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "file", - "session" - ] - }, - "VoiceBinaryFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "object", - "default": "audio/ogg; codecs=opus", - "description": "MIME type of the attachment." - }, - "filename": { - "type": "object", - "default": "voice-message.mp3", - "description": "Document file name. Optional" - }, - "data": { - "type": "string", - "description": "Base64-encoded data of the file", - "example": "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VSO3pMrPlDI7//NkxP8g454UCuJGUWisGIZWQwUgpHZyhg4kNUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxP4ibDnMAOGEzFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV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" - } - }, - "required": [ - "mimetype", - "filename", - "data" - ] - }, - "VoiceRemoteFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "object", - "default": "audio/ogg; codecs=opus", - "description": "MIME type of the attachment." - }, - "url": { - "type": "string", - "example": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" - } - }, - "required": [ - "mimetype", - "url" - ] - }, - "MessageVoiceRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/VoiceRemoteFile" - }, - { - "$ref": "#/components/schemas/VoiceBinaryFile" - } - ] - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "file", - "session" - ] - }, - "VideoRemoteFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "object", - "default": "video/mp4", - "description": "MIME type of the attachment." - }, - "filename": { - "type": "object", - "default": "video.mp4", - "description": "Document file name. Optional" - }, - "url": { - "type": "string", - "example": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" - } - }, - "required": [ - "mimetype", - "filename", - "url" - ] - }, - "VideoBinaryFile": { - "type": "object", - "properties": { - "mimetype": { - "type": "object", - "default": "video/mp4", - "description": "MIME type of the attachment." - }, - "filename": { - "type": "object", - "default": "video.mp4", - "description": "Document file name. Optional" - }, - "data": { - "type": "string", - "description": "Base64-encoded data of the file", - "example": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" - } - }, - "required": [ - "mimetype", - "filename", - "data" - ] - }, - "MessageVideoRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/VideoRemoteFile" - }, - { - "$ref": "#/components/schemas/VideoBinaryFile" - } - ] - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "asNote": { - "type": "boolean", - "description": "Send as video note (aka instant or round video).", - "example": false - }, - "caption": { - "type": "string", - "default": "Just watch at this!" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "file", - "session" - ] - }, - "FileURL": { - "type": "object", - "properties": { - "url": { - "type": "string", - "example": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - } - }, - "FileContent": { - "type": "object", - "properties": { - "data": { - "type": "string", - "description": "Base64-encoded data of the file", - "example": "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" - } - } - }, - "LinkPreviewData": { - "type": "object", - "properties": { - "image": { - "oneOf": [ - { - "$ref": "#/components/schemas/FileURL" - }, - { - "$ref": "#/components/schemas/FileContent" - } - ], - "example": { - "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" - } - }, - "url": { - "type": "string", - "default": "https://github.com/" - }, - "title": { - "type": "string", - "default": "Your Title" - }, - "description": { - "type": "string", - "default": "Check this out, amazing!" - } - }, - "required": [ - "url", - "title", - "description" - ] - }, - "MessageLinkCustomPreviewRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "text": { - "type": "string", - "default": "Check this out! https://github.com/", - "description": "The text to send. MUST include the URL provided in preview.url" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "linkPreviewHighQuality": { - "type": "boolean", - "default": true - }, - "preview": { - "$ref": "#/components/schemas/LinkPreviewData" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "text", - "preview", - "session" - ] - }, - "Button": { - "type": "object", - "properties": { - "text": { - "type": "string", - "example": "Button Text" - }, - "id": { - "type": "string", - "example": "321321" - }, - "url": { - "type": "string", - "example": "https://example.com" - }, - "phoneNumber": { - "type": "string", - "example": "+1234567890" - }, - "copyCode": { - "type": "string", - "example": "4321" - }, - "type": { - "type": "string", - "default": "reply", - "enum": [ - "reply", - "url", - "call", - "copy" - ] - } - }, - "required": [ - "text", - "type" - ] - }, - "SendButtonsRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "header": { - "type": "string", - "example": "How are you?" - }, - "headerImage": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - }, - "body": { - "type": "string", - "example": "Tell us how are you please 🙏" - }, - "footer": { - "type": "string", - "example": "If you have any questions, please send it in the chat" - }, - "buttons": { - "example": [ - { - "type": "reply", - "text": "I am good!" - }, - { - "type": "call", - "text": "Call us", - "phoneNumber": "+1234567890" - }, - { - "type": "copy", - "text": "Copy code", - "copyCode": "4321" - }, - { - "type": "url", - "text": "How did you do that?", - "url": "https://waha.devlike.pro" - } - ], - "type": "array", - "items": { - "$ref": "#/components/schemas/Button" - } - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "header", - "body", - "footer", - "buttons", - "session" - ] - }, - "MessageForwardRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "messageId": { - "type": "string", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "messageId", - "session" - ] - }, - "SendSeenRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "messageId": { - "type": "string", - "example": null, - "deprecated": true - }, - "messageIds": { - "example": [ - "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - ], - "type": "array", - "items": { - "type": "string" - } - }, - "participant": { - "type": "string", - "example": "11111111111@c.us", - "default": null, - "description": "NOWEB engine only - the ID of the user that sent the message (undefined for individual chats)" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "session" - ] - }, - "ChatRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "session" - ] - }, - "MessageReactionRequest": { - "type": "object", - "properties": { - "messageId": { - "type": "string", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "reaction": { - "type": "string", - "description": "Emoji to react with. Send an empty string to remove the reaction", - "example": "👍" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "messageId", - "reaction", - "session" - ] - }, - "MessageStarRequest": { - "type": "object", - "properties": { - "messageId": { - "type": "string", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "star": { - "type": "boolean" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "messageId", - "chatId", - "star", - "session" - ] - }, - "MessagePoll": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "How are you?" - }, - "options": { - "example": [ - "Awesome!", - "Good!", - "Not bad!" - ], - "type": "array", - "items": { - "type": "string" - } - }, - "multipleAnswers": { - "type": "object", - "default": false - } - }, - "required": [ - "name", - "options", - "multipleAnswers" - ] - }, - "MessagePollRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "poll": { - "$ref": "#/components/schemas/MessagePoll" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "poll", - "session" - ] - }, - "MessageLocationRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "latitude": { - "type": "number", - "example": 38.8937255 - }, - "longitude": { - "type": "number", - "example": -77.0969763 - }, - "title": { - "type": "string", - "example": "Our office" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "latitude", - "longitude", - "title", - "session" - ] - }, - "Contact": { - "type": "object", - "properties": { - "fullName": { - "type": "string", - "example": "John Doe", - "description": "The full name of the contact" - }, - "organization": { - "type": "string", - "example": "Company Name", - "description": "The organization of the contact" - }, - "phoneNumber": { - "type": "string", - "example": "+91 11111 11111", - "description": "The phone number of the contact" - }, - "whatsappId": { - "type": "string", - "example": "911111111111", - "description": "The whatsapp id of the contact. DO NOT add + or @c.us" - }, - "vcard": { - "type": "string", - "default": null - } - }, - "required": [ - "fullName", - "phoneNumber", - "vcard" - ] - }, - "VCardContact": { - "type": "object", - "properties": { - "vcard": { - "type": "string", - "example": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD", - "description": "The vcard string" - } - }, - "required": [ - "vcard" - ] - }, - "MessageContactVcardRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "contacts": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/VCardContact" - }, - { - "$ref": "#/components/schemas/Contact" - } - ] - } - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "contacts", - "session" - ] - }, - "MessageButtonReply": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "replyTo": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "selectedDisplayText": { - "type": "string" - }, - "selectedButtonID": { - "type": "string" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "selectedDisplayText", - "selectedButtonID", - "session" - ] - }, - "WANumberExistResult": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "Chat id for the phone number. Undefined if the number does not exist" - }, - "numberExists": { - "type": "boolean" - } - }, - "required": [ - "numberExists" - ] - }, - "MessageReplyRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "text": { - "type": "string", - "default": "Hi there!" - }, - "linkPreview": { - "type": "boolean", - "default": true - }, - "linkPreviewHighQuality": { - "type": "boolean", - "default": false - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "chatId", - "text", - "session" - ] - }, - "MessageLinkPreviewRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "session": { - "type": "string", - "default": "default" - }, - "url": { - "type": "string" - }, - "title": { - "type": "string" - } - }, - "required": [ - "chatId", - "session", - "url", - "title" - ] - }, - "ChatSummary": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string", - "nullable": true - }, - "picture": { - "type": "string", - "nullable": true - }, - "lastMessage": { - "type": "object" - }, - "_chat": { - "type": "object" - } - }, - "required": [ - "id", - "name", - "picture", - "lastMessage", - "_chat" - ] - }, - "OverviewPaginationParams": { - "type": "object", - "properties": { - "limit": { - "type": "number", - "default": 20 - }, - "offset": { - "type": "number" - } - } - }, - "OverviewFilter": { - "type": "object", - "properties": { - "ids": { - "description": "Filter by chat ids", - "example": [ - "111111111@c.us" - ], - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "OverviewBodyRequest": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/components/schemas/OverviewPaginationParams" - }, - "filter": { - "$ref": "#/components/schemas/OverviewFilter" - } - }, - "required": [ - "pagination", - "filter" - ] - }, - "ChatPictureResponse": { - "type": "object", - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ] - }, - "ReadChatMessagesResponse": { - "type": "object", - "properties": { - "ids": { - "description": "Messages IDs that have been read", - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "PinMessageRequest": { - "type": "object", - "properties": { - "duration": { - "type": "number", - "description": "Duration in seconds. 24 hours (86400), 7 days (604800), 30 days (2592000)", - "example": 86400 - } - }, - "required": [ - "duration" - ] - }, - "EditMessageRequest": { - "type": "object", - "properties": { - "text": { - "type": "string", - "default": "Hello, world!" - }, - "linkPreview": { - "type": "boolean", - "default": true - }, - "linkPreviewHighQuality": { - "type": "boolean", - "default": false - } - }, - "required": [ - "text" - ] - }, - "Channel": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Newsletter id", - "example": "123123123123@newsletter" - }, - "name": { - "type": "string", - "description": "Channel name", - "example": "Channel Name" - }, - "invite": { - "type": "string", - "description": "Invite link", - "example": "https://www.whatsapp.com/channel/111111111111111111111111" - }, - "preview": { - "type": "string", - "description": "Preview for channel's picture", - "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" - }, - "picture": { - "type": "string", - "description": "Channel's picture", - "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" - }, - "role": { - "enum": [ - "OWNER", - "ADMIN", - "SUBSCRIBER", - "GUEST" - ], - "type": "string" - }, - "description": { - "type": "string" - }, - "verified": { - "type": "boolean" - }, - "subscribersCount": { - "type": "number" - } - }, - "required": [ - "id", - "name", - "invite", - "role", - "verified", - "subscribersCount" - ] - }, - "CreateChannelRequest": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "Channel Name" - }, - "description": { - "type": "string", - "example": "Channel Description" - }, - "picture": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - } - }, - "required": [ - "name" - ] - }, - "ChannelMessage": { - "type": "object", - "properties": { - "reactions": { - "type": "object", - "example": { - "👍": 10, - "❤️": 5 - }, - "additionalProperties": { - "type": "number" - } - }, - "message": { - "$ref": "#/components/schemas/WAMessage" - }, - "viewCount": { - "type": "number" - } - }, - "required": [ - "reactions", - "message", - "viewCount" - ] - }, - "ChannelSearchByView": { - "type": "object", - "properties": { - "view": { - "type": "string", - "default": "RECOMMENDED" - }, - "countries": { - "default": [ - "US" - ], - "type": "array", - "items": { - "type": "string" - } - }, - "categories": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "limit": { - "type": "number", - "default": 50 - }, - "startCursor": { - "type": "string", - "default": "" - } - }, - "required": [ - "view", - "countries", - "categories", - "limit", - "startCursor" - ] - }, - "ChannelPagination": { - "type": "object", - "properties": { - "startCursor": { - "type": "string", - "nullable": true - }, - "endCursor": { - "type": "string", - "nullable": true - }, - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - } - }, - "required": [ - "startCursor", - "endCursor", - "hasNextPage", - "hasPreviousPage" - ] - }, - "ChannelPublicInfo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Newsletter id", - "example": "123123123123@newsletter" - }, - "name": { - "type": "string", - "description": "Channel name", - "example": "Channel Name" - }, - "invite": { - "type": "string", - "description": "Invite link", - "example": "https://www.whatsapp.com/channel/111111111111111111111111" - }, - "preview": { - "type": "string", - "description": "Preview for channel's picture", - "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" - }, - "picture": { - "type": "string", - "description": "Channel's picture", - "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" - }, - "description": { - "type": "string" - }, - "verified": { - "type": "boolean" - }, - "subscribersCount": { - "type": "number" - } - }, - "required": [ - "id", - "name", - "invite", - "verified", - "subscribersCount" - ] - }, - "ChannelListResult": { - "type": "object", - "properties": { - "page": { - "$ref": "#/components/schemas/ChannelPagination" - }, - "channels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelPublicInfo" - } - } - }, - "required": [ - "page", - "channels" - ] - }, - "ChannelSearchByText": { - "type": "object", - "properties": { - "text": { - "type": "string", - "default": "Donald Trump" - }, - "categories": { - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "limit": { - "type": "number", - "default": 50 - }, - "startCursor": { - "type": "string", - "default": "" - } - }, - "required": [ - "text", - "categories", - "limit", - "startCursor" - ] - }, - "ChannelView": { - "type": "object", - "properties": { - "value": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "value", - "name" - ] - }, - "ChannelCountry": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "code", - "name" - ] - }, - "ChannelCategory": { - "type": "object", - "properties": { - "value": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "value", - "name" - ] - }, - "TextStatus": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Pre-generated status message id", - "example": "BBBBBBBBBBBBBBBBB", - "default": null - }, - "contacts": { - "description": "Contact list to send the status to.", - "example": null, - "type": "array", - "items": { - "type": "string" - } - }, - "text": { - "type": "string", - "default": "Have a look! https://github.com/" - }, - "backgroundColor": { - "type": "string", - "default": "#38b42f" - }, - "font": { - "type": "number", - "default": 0 - }, - "linkPreview": { - "type": "boolean", - "default": true - }, - "linkPreviewHighQuality": { - "type": "boolean", - "default": false - } - }, - "required": [ - "text", - "backgroundColor", - "font" - ] - }, - "ImageStatus": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Pre-generated status message id", - "example": "BBBBBBBBBBBBBBBBB", - "default": null - }, - "contacts": { - "description": "Contact list to send the status to.", - "example": null, - "type": "array", - "items": { - "type": "string" - } - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/RemoteFile" - }, - { - "$ref": "#/components/schemas/BinaryFile" - } - ] - }, - "caption": { - "type": "string" - } - }, - "required": [ - "file" - ] - }, - "VoiceStatus": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Pre-generated status message id", - "example": "BBBBBBBBBBBBBBBBB", - "default": null - }, - "contacts": { - "description": "Contact list to send the status to.", - "example": null, - "type": "array", - "items": { - "type": "string" - } - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/VoiceRemoteFile" - }, - { - "$ref": "#/components/schemas/VoiceBinaryFile" - } - ] - }, - "backgroundColor": { - "type": "string", - "default": "#38b42f" - } - }, - "required": [ - "file", - "backgroundColor" - ] - }, - "VideoStatus": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Pre-generated status message id", - "example": "BBBBBBBBBBBBBBBBB", - "default": null - }, - "contacts": { - "description": "Contact list to send the status to.", - "example": null, - "type": "array", - "items": { - "type": "string" - } - }, - "file": { - "oneOf": [ - { - "$ref": "#/components/schemas/VideoRemoteFile" - }, - { - "$ref": "#/components/schemas/VideoBinaryFile" - } - ] - }, - "caption": { - "type": "string" - } - }, - "required": [ - "file" - ] - }, - "DeleteStatusRequest": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Status message id to delete", - "example": "AAAAAAAAAAAAAAAAA", - "default": null - }, - "contacts": { - "description": "Contact list to send the status to.", - "example": null, - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "NewMessageIDResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Pre-generated message id", - "example": "BBBBBBBBBBBBBBBBB" - } - }, - "required": [ - "id" - ] - }, - "Label": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "1", - "description": "Label ID" - }, - "name": { - "type": "string", - "example": "Lead", - "description": "Label name" - }, - "color": { - "type": "number", - "example": 0, - "description": "Color number, not hex" - }, - "colorHex": { - "type": "string", - "example": "#ff9485", - "description": "Color in hex" - } - }, - "required": [ - "id", - "name", - "color", - "colorHex" - ] - }, - "LabelBody": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "Lead", - "description": "Label name" - }, - "colorHex": { - "type": "string", - "example": "#ff9485", - "description": "Color in hex" - }, - "color": { - "type": "number", - "example": null, - "description": "Color number, not hex" - } - }, - "required": [ - "name" - ] - }, - "LabelID": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "1", - "description": "Label ID" - } - }, - "required": [ - "id" - ] - }, - "SetLabelsRequest": { - "type": "object", - "properties": { - "labels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LabelID" - } - } - }, - "required": [ - "labels" - ] - }, - "ContactRequest": { - "type": "object", - "properties": { - "contactId": { - "type": "string", - "example": "11111111111@c.us" - }, - "session": { - "type": "string", - "default": "default" - } - }, - "required": [ - "contactId", - "session" - ] - }, - "LidToPhoneNumber": { - "type": "object", - "properties": { - "lid": { - "type": "string", - "description": "Linked ID for the user", - "example": "1111111@lid" - }, - "pn": { - "type": "string", - "description": "Phone number (chat id) for the user", - "example": "3333333@c.us" - } - } - }, - "CountResponse": { - "type": "object", - "properties": { - "count": { - "type": "number", - "default": 0 - } - }, - "required": [ - "count" - ] - }, - "Participant": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "123456789@c.us" - } - }, - "required": [ - "id" - ] - }, - "CreateGroupRequest": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "participants": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Participant" - } - } - }, - "required": [ - "name", - "participants" - ] - }, - "JoinGroupRequest": { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Group code (123) or url (https://chat.whatsapp.com/123)", - "example": "https://chat.whatsapp.com/1234567890abcdef" - } - }, - "required": [ - "code" - ] - }, - "JoinGroupResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Group ID", - "example": "123@g.us" - } - }, - "required": [ - "id" - ] - }, - "DescriptionRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - }, - "required": [ - "description" - ] - }, - "SubjectRequest": { - "type": "object", - "properties": { - "subject": { - "type": "string" - } - }, - "required": [ - "subject" - ] - }, - "SettingsSecurityChangeInfo": { - "type": "object", - "properties": { - "adminsOnly": { - "type": "boolean", - "default": true - } - }, - "required": [ - "adminsOnly" - ] - }, - "ParticipantsRequest": { - "type": "object", - "properties": { - "participants": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Participant" - } - } - }, - "required": [ - "participants" - ] - }, - "WAHASessionPresence": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "description": "Chat ID - either group id or contact id", - "example": "11111111111@c.us" - }, - "presence": { - "type": "string", - "enum": [ - "offline", - "online", - "typing", - "recording", - "paused" - ] - } - }, - "required": [ - "chatId", - "presence" - ] - }, - "WAHAPresenceData": { - "type": "object", - "properties": { - "participant": { - "type": "string", - "description": "Chat ID - participant or contact id", - "example": "11111111111@c.us" - }, - "lastSeen": { - "type": "number", - "example": 1686568773 - }, - "lastKnownPresence": { - "type": "string", - "enum": [ - "offline", - "online", - "typing", - "recording", - "paused" - ] - } - }, - "required": [ - "participant", - "lastKnownPresence" - ] - }, - "WAHAChatPresences": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Chat ID - either group id or contact id", - "example": "11111111111@c.us" - }, - "presences": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WAHAPresenceData" - } - } - }, - "required": [ - "id", - "presences" - ] - }, - "EventLocation": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the location", - "example": "Luxe Nail Studio 💅" - } - }, - "required": [ - "name" - ] - }, - "EventMessage": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the event", - "example": "John's Nail Appointment 💅" - }, - "description": { - "type": "string", - "description": "Description of the event", - "example": "It's time for your nail care session! 🌟\\n\\nYou'll be getting a *classic gel manicure* – clean, polished, and long-lasting. 💖\\n\\n📍 *Location:* Luxe Nail Studio\\nWe're on the *2nd floor of the Plaza Mall*, next to the flower shop. Look for the *pink neon sign*!\\n\\nFeel free to arrive *5–10 mins early* so we can get started on time 😊" - }, - "startTime": { - "type": "number", - "description": "Start time of the event (Unix timestamp in seconds)", - "example": 2063137000 - }, - "endTime": { - "type": "number", - "description": "End time of the event (Unix timestamp in seconds)", - "example": null - }, - "location": { - "description": "Location of the event", - "allOf": [ - { - "$ref": "#/components/schemas/EventLocation" - } - ] - }, - "extraGuestsAllowed": { - "type": "boolean", - "description": "Whether extra guests are allowed", - "example": false - } - }, - "required": [ - "name", - "startTime" - ] - }, - "EventMessageRequest": { - "type": "object", - "properties": { - "chatId": { - "type": "string", - "example": "11111111111@c.us" - }, - "reply_to": { - "type": "string", - "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", - "example": null - }, - "event": { - "$ref": "#/components/schemas/EventMessage" - } - }, - "required": [ - "chatId", - "event" - ] - }, - "PingResponse": { - "type": "object", - "properties": { - "message": { - "type": "string", - "default": "pong" - } - }, - "required": [ - "message" - ] - }, - "WAHAEnvironment": { - "type": "object", - "properties": { - "version": { - "type": "string", - "example": "YYYY.MM.BUILD" - }, - "engine": { - "type": "string", - "example": "WEBJS" - }, - "tier": { - "type": "string", - "example": "PLUS" - }, - "browser": { - "type": "string", - "example": "/usr/path/to/bin/google-chrome" - } - }, - "required": [ - "version", - "engine", - "tier", - "browser" - ] - }, - "WorkerInfo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "waha", - "description": "The worker ID." - } - }, - "required": [ - "id" - ] - }, - "ServerStatusResponse": { - "type": "object", - "properties": { - "startTimestamp": { - "type": "number", - "example": 1723788847247, - "description": "The timestamp when the server started (milliseconds)." - }, - "uptime": { - "type": "number", - "example": 3600000, - "description": "The uptime of the server in milliseconds." - }, - "worker": { - "$ref": "#/components/schemas/WorkerInfo" - } - }, - "required": [ - "startTimestamp", - "uptime", - "worker" - ] - }, - "StopRequest": { - "type": "object", - "properties": { - "force": { - "type": "boolean", - "default": false, - "example": false, - "description": "By default, it gracefully stops the server, but you can force it to terminate immediately." - } - } - }, - "StopResponse": { - "type": "object", - "properties": { - "stopping": { - "type": "boolean", - "default": true, - "example": true, - "description": "Always 'true' if the server is stopping." - } - }, - "required": [ - "stopping" - ] - }, - "WASessionStatusBody": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "default" - }, - "status": { - "type": "string", - "enum": [ - "STOPPED", - "STARTING", - "SCAN_QR_CODE", - "WORKING", - "FAILED" - ] - } - }, - "required": [ - "name", - "status" - ] - }, - "WAHAWebhookSessionStatus": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "session.status", - "description": "The event is triggered when the session status changes." - }, - "payload": { - "$ref": "#/components/schemas/WASessionStatusBody" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookMessage": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "message", - "description": "Incoming message." - }, - "payload": { - "$ref": "#/components/schemas/WAMessage" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAReaction": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Reaction to the message. Either the reaction (emoji) or empty string to remove the reaction" - }, - "messageId": { - "type": "string", - "description": "Message ID for the message to react to", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - } - }, - "required": [ - "text", - "messageId" - ] - }, - "WAMessageReaction": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "timestamp": { - "type": "number", - "description": "Unix timestamp for when the message was created", - "example": 1666943582 - }, - "from": { - "type": "string", - "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", - "example": "11111111111@c.us" - }, - "fromMe": { - "type": "boolean", - "description": "Indicates if the message was sent by the current user" - }, - "source": { - "enum": [ - "api", - "app" - ], - "type": "string", - "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", - "example": "api" - }, - "to": { - "type": "string", - "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", - "example": "11111111111@c.us" - }, - "participant": { - "type": "string", - "description": "For groups - participant who sent the message" - }, - "reaction": { - "description": "Reaction to the message. Either the reaction (emoji) or empty string to remove the reaction", - "allOf": [ - { - "$ref": "#/components/schemas/WAReaction" - } - ] - } - }, - "required": [ - "id", - "timestamp", - "from", - "fromMe", - "source", - "to", - "participant", - "reaction" - ] - }, - "WAHAWebhookMessageReaction": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "message.reaction", - "description": "The event is triggered when a user reacts or removes a reaction." - }, - "payload": { - "$ref": "#/components/schemas/WAMessageReaction" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookMessageAny": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "message.any", - "description": "Fired on all message creations, including your own." - }, - "payload": { - "$ref": "#/components/schemas/WAMessage" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAMessageAckBody": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "from": { - "type": "string", - "example": "11111111111@c.us" - }, - "to": { - "type": "string", - "example": "11111111111@c.us" - }, - "participant": { - "type": "string", - "example": "11111111111@c.us" - }, - "fromMe": { - "type": "boolean" - }, - "ack": { - "type": "number", - "enum": [ - -1, - 0, - 1, - 2, - 3, - 4 - ] - }, - "ackName": { - "type": "string" - }, - "_data": { - "type": "object" - } - }, - "required": [ - "id", - "from", - "to", - "participant", - "fromMe", - "ack", - "ackName" - ] - }, - "WAHAWebhookMessageAck": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "message.ack", - "description": "Receive events when server or recipient gets the message, read or played it." - }, - "payload": { - "$ref": "#/components/schemas/WAMessageAckBody" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAMessageRevokedBody": { - "type": "object", - "properties": { - "after": { - "$ref": "#/components/schemas/WAMessage" - }, - "before": { - "$ref": "#/components/schemas/WAMessage" - }, - "_data": { - "type": "object" - } - } - }, - "WAHAWebhookMessageRevoked": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "message.revoked", - "description": "The event is triggered when a user, whether it be you or any other participant, revokes a previously sent message." - }, - "payload": { - "$ref": "#/components/schemas/WAMessageRevokedBody" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "GroupParticipant": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "123456789@c.us" - }, - "role": { - "enum": [ - "left", - "participant", - "admin", - "superadmin" - ], - "type": "string", - "example": "participant" - } - }, - "required": [ - "id", - "role" - ] - }, - "GroupInfo": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "123456789@g.us" - }, - "subject": { - "type": "string", - "example": "Group Name" - }, - "description": { - "type": "string", - "example": "Group Description" - }, - "invite": { - "type": "string", - "description": "Invite URL", - "example": "https://chat.whatsapp.com/1234567890abcdef" - }, - "membersCanAddNewMember": { - "type": "boolean", - "description": "Members can add new members" - }, - "membersCanSendMessages": { - "type": "boolean", - "description": "Members can send messages to the group" - }, - "newMembersApprovalRequired": { - "type": "boolean", - "description": "Admin approval required for new members" - }, - "participants": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GroupParticipant" - } - } - }, - "required": [ - "id", - "subject", - "description", - "membersCanAddNewMember", - "membersCanSendMessages", - "newMembersApprovalRequired", - "participants" - ] - }, - "GroupV2JoinEvent": { - "type": "object", - "properties": { - "timestamp": { - "type": "number", - "description": "Unix timestamp", - "example": 1666943582 - }, - "group": { - "$ref": "#/components/schemas/GroupInfo" - }, - "_data": { - "type": "object" - } - }, - "required": [ - "timestamp", - "group", - "_data" - ] - }, - "WebhookGroupV2Join": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.v2.join", - "description": "When you joined or were added to a group" - }, - "payload": { - "$ref": "#/components/schemas/GroupV2JoinEvent" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "GroupId": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "123456789@g.us" - } - }, - "required": [ - "id" - ] - }, - "GroupV2LeaveEvent": { - "type": "object", - "properties": { - "timestamp": { - "type": "number", - "description": "Unix timestamp", - "example": 1666943582 - }, - "group": { - "$ref": "#/components/schemas/GroupId" - }, - "_data": { - "type": "object" - } - }, - "required": [ - "timestamp", - "group", - "_data" - ] - }, - "WebhookGroupV2Leave": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.v2.leave", - "description": "When you left or were removed from a group" - }, - "payload": { - "$ref": "#/components/schemas/GroupV2LeaveEvent" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "GroupV2UpdateEvent": { - "type": "object", - "properties": { - "timestamp": { - "type": "number", - "description": "Unix timestamp", - "example": 1666943582 - }, - "group": { - "type": "object" - }, - "_data": { - "type": "object" - } - }, - "required": [ - "timestamp", - "group", - "_data" - ] - }, - "WebhookGroupV2Update": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.v2.update", - "description": "When group info is updated" - }, - "payload": { - "$ref": "#/components/schemas/GroupV2UpdateEvent" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "GroupV2ParticipantsEvent": { - "type": "object", - "properties": { - "type": { - "enum": [ - "join", - "leave", - "promote", - "demote" - ], - "type": "string", - "description": "Type of the event" - }, - "timestamp": { - "type": "number", - "description": "Unix timestamp", - "example": 1666943582 - }, - "group": { - "$ref": "#/components/schemas/GroupId" - }, - "participants": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GroupParticipant" - } - }, - "_data": { - "type": "object" - } - }, - "required": [ - "type", - "timestamp", - "group", - "participants", - "_data" - ] - }, - "WebhookGroupV2Participants": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.v2.participants", - "description": "When participants changed - join, leave, promote to admin" - }, - "payload": { - "$ref": "#/components/schemas/GroupV2ParticipantsEvent" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookPresenceUpdate": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "presence.update", - "description": "The most recent presence information for a chat." - }, - "payload": { - "$ref": "#/components/schemas/WAHAChatPresences" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "PollVote": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "selectedOptions": { - "description": "Option that user has selected", - "example": [ - "Awesome!" - ], - "type": "array", - "items": { - "type": "string" - } - }, - "timestamp": { - "type": "number", - "description": "Timestamp, ms", - "example": 1692861369 - }, - "to": { - "type": "string" - }, - "from": { - "type": "string" - }, - "fromMe": { - "type": "boolean" - }, - "participant": { - "type": "string" - } - }, - "required": [ - "id", - "selectedOptions", - "timestamp", - "to", - "from", - "fromMe" - ] - }, - "MessageDestination": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "to": { - "type": "string" - }, - "from": { - "type": "string" - }, - "fromMe": { - "type": "boolean" - }, - "participant": { - "type": "string" - } - }, - "required": [ - "id", - "to", - "from", - "fromMe" - ] - }, - "PollVotePayload": { - "type": "object", - "properties": { - "vote": { - "$ref": "#/components/schemas/PollVote" - }, - "poll": { - "$ref": "#/components/schemas/MessageDestination" - }, - "_data": { - "type": "object" - } - }, - "required": [ - "vote", - "poll" - ] - }, - "WAHAWebhookPollVote": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "poll.vote", - "description": "With this event, you receive new votes for the poll sent." - }, - "payload": { - "$ref": "#/components/schemas/PollVotePayload" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookPollVoteFailed": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "poll.vote.failed", - "description": "There may be cases when it fails to decrypt a vote from the user. Read more about how to handle such events in the documentations." - }, - "payload": { - "$ref": "#/components/schemas/PollVotePayload" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "ChatArchiveEvent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "11111111111@c.us" - }, - "archived": { - "type": "boolean" - }, - "timestamp": { - "type": "number" - } - }, - "required": [ - "id", - "archived", - "timestamp" - ] - }, - "WAHAWebhookChatArchive": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "chat.archive", - "description": "The event is triggered when the chat is archived or unarchived" - }, - "payload": { - "$ref": "#/components/schemas/ChatArchiveEvent" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "CallData": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Call ID", - "example": "ABCDEFGABCDEFGABCDEFGABCDEFG" - }, - "from": { - "type": "string", - "example": "11111111111@c.us" - }, - "timestamp": { - "type": "number" - }, - "isVideo": { - "type": "boolean" - }, - "isGroup": { - "type": "boolean" - } - }, - "required": [ - "id", - "timestamp", - "isVideo", - "isGroup" - ] - }, - "WAHAWebhookCallReceived": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "call.received", - "description": "The event is triggered when the call is received by the user." - }, - "payload": { - "$ref": "#/components/schemas/CallData" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookCallAccepted": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "call.accepted", - "description": "The event is triggered when the call is accepted by the user." - }, - "payload": { - "$ref": "#/components/schemas/CallData" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookCallRejected": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "call.rejected", - "description": "The event is triggered when the call is rejected by the user." - }, - "payload": { - "$ref": "#/components/schemas/CallData" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookLabelUpsert": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "label.upsert", - "description": "The event is triggered when a label is created or updated" - }, - "payload": { - "$ref": "#/components/schemas/Label" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookLabelDeleted": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "label.deleted", - "description": "The event is triggered when a label is deleted" - }, - "payload": { - "$ref": "#/components/schemas/Label" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "LabelChatAssociation": { - "type": "object", - "properties": { - "labelId": { - "type": "string", - "example": "1", - "description": "Label ID" - }, - "chatId": { - "type": "string", - "description": "Chat ID", - "example": "11111111111@c.us" - }, - "label": { - "nullable": true, - "allOf": [ - { - "$ref": "#/components/schemas/Label" - } - ] - } - }, - "required": [ - "labelId", - "chatId", - "label" - ] - }, - "WAHAWebhookLabelChatAdded": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "label.chat.added", - "description": "The event is triggered when a label is added to a chat" - }, - "payload": { - "$ref": "#/components/schemas/LabelChatAssociation" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookLabelChatDeleted": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "label.chat.deleted", - "description": "The event is triggered when a label is deleted from a chat" - }, - "payload": { - "$ref": "#/components/schemas/LabelChatAssociation" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "EventResponse": { - "type": "object", - "properties": { - "response": { - "type": "string", - "enum": [ - "UNKNOWN", - "GOING", - "NOT_GOING", - "MAYBE" - ] - }, - "timestampMs": { - "type": "number" - }, - "extraGuestCount": { - "type": "number" - } - }, - "required": [ - "response", - "timestampMs", - "extraGuestCount" - ] - }, - "EventResponsePayload": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Message ID", - "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" - }, - "timestamp": { - "type": "number", - "description": "Unix timestamp for when the message was created", - "example": 1666943582 - }, - "from": { - "type": "string", - "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", - "example": "11111111111@c.us" - }, - "fromMe": { - "type": "boolean", - "description": "Indicates if the message was sent by the current user" - }, - "source": { - "enum": [ - "api", - "app" - ], - "type": "string", - "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", - "example": "api" - }, - "to": { - "type": "string", - "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", - "example": "11111111111@c.us" - }, - "participant": { - "type": "string", - "description": "For groups - participant who sent the message" - }, - "_data": { - "type": "object", - "description": "Message in a raw format that we get from WhatsApp. May be changed anytime, use it with caution! It depends a lot on the underlying backend." - }, - "eventCreationKey": { - "$ref": "#/components/schemas/MessageDestination" - }, - "eventResponse": { - "$ref": "#/components/schemas/EventResponse" - } - }, - "required": [ - "id", - "timestamp", - "from", - "fromMe", - "source", - "to", - "participant", - "eventCreationKey" - ] - }, - "WAHAWebhookEventResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "event.response", - "description": "The event is triggered when the event response is received." - }, - "payload": { - "$ref": "#/components/schemas/EventResponsePayload" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookEventResponseFailed": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "event.response.failed", - "description": "The event is triggered when the event response is failed to decrypt." - }, - "payload": { - "$ref": "#/components/schemas/EventResponsePayload" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "EnginePayload": { - "type": "object", - "properties": { - "event": { - "type": "string" - }, - "data": { - "type": "object" - } - }, - "required": [ - "event", - "data" - ] - }, - "WAHAWebhookEngineEvent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "engine.event", - "description": "Internal engine event." - }, - "payload": { - "$ref": "#/components/schemas/EnginePayload" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookGroupJoin": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.join", - "description": "Some one join a group.", - "deprecated": true - }, - "payload": { - "type": "object" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookGroupLeave": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "group.leave", - "description": "Some one left a group.", - "deprecated": true - }, - "payload": { - "type": "object" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - }, - "WAHAWebhookStateChange": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", - "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" - }, - "timestamp": { - "type": "number", - "example": 1634567890123, - "description": "Unix timestamp (ms) for when the event was created." - }, - "session": { - "type": "string", - "example": "default" - }, - "metadata": { - "example": { - "user.id": "123", - "user.email": "email@example.com" - }, - "description": "Metadata for the session.", - "allOf": [ - { - "$ref": "#/components/schemas/Map" - } - ] - }, - "engine": { - "enum": [ - "WEBJS", - "NOWEB", - "GOWS" - ], - "type": "string", - "example": "WEBJS" - }, - "event": { - "enum": [ - "session.status", - "message", - "message.reaction", - "message.any", - "message.ack", - "message.waiting", - "message.revoked", - "state.change", - "group.join", - "group.leave", - "group.v2.join", - "group.v2.leave", - "group.v2.update", - "group.v2.participants", - "presence.update", - "poll.vote", - "poll.vote.failed", - "chat.archive", - "call.received", - "call.accepted", - "call.rejected", - "label.upsert", - "label.deleted", - "label.chat.added", - "label.chat.deleted", - "event.response", - "event.response.failed", - "engine.event" - ], - "type": "object", - "default": "state.change", - "description": "It’s an internal engine’s state, not session status.", - "deprecated": true - }, - "payload": { - "type": "object" - }, - "me": { - "$ref": "#/components/schemas/MeInfo" - }, - "environment": { - "$ref": "#/components/schemas/WAHAEnvironment" - } - }, - "required": [ - "id", - "timestamp", - "session", - "engine", - "event", - "payload", - "environment" - ] - } - } - }, - "externalDocs": { - "description": "WAHA - WhatsApp HTTP API", - "url": "https://waha.devlike.pro/" - }, - "webhooks": { - "session.status": { - "post": { - "summary": "The event is triggered when the session status changes.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookSessionStatus" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "message": { - "post": { - "summary": "Incoming message.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookMessage" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "message.reaction": { - "post": { - "summary": "The event is triggered when a user reacts or removes a reaction.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookMessageReaction" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "message.any": { - "post": { - "summary": "Fired on all message creations, including your own.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookMessageAny" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "message.ack": { - "post": { - "summary": "Receive events when server or recipient gets the message, read or played it.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookMessageAck" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "message.revoked": { - "post": { - "summary": "The event is triggered when a user, whether it be you or any other participant, revokes a previously sent message.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookMessageRevoked" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.v2.join": { - "post": { - "summary": "When you joined or were added to a group", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookGroupV2Join" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.v2.leave": { - "post": { - "summary": "When you left or were removed from a group", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookGroupV2Leave" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.v2.update": { - "post": { - "summary": "When group info is updated", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookGroupV2Update" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.v2.participants": { - "post": { - "summary": "When participants changed - join, leave, promote to admin", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookGroupV2Participants" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "presence.update": { - "post": { - "summary": "The most recent presence information for a chat.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookPresenceUpdate" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "poll.vote": { - "post": { - "summary": "With this event, you receive new votes for the poll sent.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookPollVote" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "poll.vote.failed": { - "post": { - "summary": "There may be cases when it fails to decrypt a vote from the user. Read more about how to handle such events in the documentations.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookPollVoteFailed" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "chat.archive": { - "post": { - "summary": "The event is triggered when the chat is archived or unarchived", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookChatArchive" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "call.received": { - "post": { - "summary": "The event is triggered when the call is received by the user.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookCallReceived" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "call.accepted": { - "post": { - "summary": "The event is triggered when the call is accepted by the user.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookCallAccepted" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "call.rejected": { - "post": { - "summary": "The event is triggered when the call is rejected by the user.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookCallRejected" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "label.upsert": { - "post": { - "summary": "The event is triggered when a label is created or updated", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookLabelUpsert" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "label.deleted": { - "post": { - "summary": "The event is triggered when a label is deleted", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookLabelDeleted" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "label.chat.added": { - "post": { - "summary": "The event is triggered when a label is added to a chat", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookLabelChatAdded" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "label.chat.deleted": { - "post": { - "summary": "The event is triggered when a label is deleted from a chat", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookLabelChatDeleted" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "event.response": { - "post": { - "summary": "The event is triggered when the event response is received.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookEventResponse" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "event.response.failed": { - "post": { - "summary": "The event is triggered when the event response is failed to decrypt.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookEventResponseFailed" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "engine.event": { - "post": { - "summary": "Internal engine event.", - "deprecated": false, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookEngineEvent" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.join": { - "post": { - "summary": "Some one join a group.", - "deprecated": true, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookGroupJoin" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "group.leave": { - "post": { - "summary": "Some one left a group.", - "deprecated": true, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookGroupLeave" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - }, - "state.change": { - "post": { - "summary": "It’s an internal engine’s state, not session status.", - "deprecated": true, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WAHAWebhookStateChange" - } - } - } - }, - "responses": { - "200": { - "description": "Return a 200 status to indicate that the data was received successfully" - } - } - } - } - } -} +{ + "openapi": "3.1.0", + "paths": { + "/api/{session}/auth/qr": { + "get": { + "operationId": "AuthController_getQR", + "summary": "Get QR code for pairing WhatsApp API.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "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": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestCodeRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🔑 Auth"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions": { + "get": { + "operationId": "SessionsController_list", + "summary": "List all sessions", + "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": [] + } + ] + }, + "post": { + "operationId": "SessionsController_create", + "summary": "Create a session", + "description": "Create session a new session (and start it at the same time if required).", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}": { + "get": { + "operationId": "SessionsController_get", + "summary": "Get session information", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionInfo" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "SessionsController_update", + "summary": "Update a session", + "description": "", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "SessionsController_delete", + "summary": "Delete the session", + "description": "Delete the session with the given name. Stop and logout as well. Idempotent operation.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}/me": { + "get": { + "operationId": "SessionsController_getMe", + "summary": "Get information about the authenticated account", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MeInfo" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}/start": { + "post": { + "operationId": "SessionsController_start", + "summary": "Start the session", + "description": "Start the session with the given name. The session must exist. Idempotent operation.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}/stop": { + "post": { + "operationId": "SessionsController_stop", + "summary": "Stop the session", + "description": "Stop the session with the given name. Idempotent operation.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}/logout": { + "post": { + "operationId": "SessionsController_logout", + "summary": "Logout from the session", + "description": "Logout the session, restart a session if it was not STOPPED", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/{session}/restart": { + "post": { + "operationId": "SessionsController_restart", + "summary": "Restart the session", + "description": "Restart the session with the given name.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/start": { + "post": { + "operationId": "SessionsController_DEPRACATED_start", + "summary": "Upsert and Start session", + "description": "Create session (if not exists) or update a config (if exists) and start it.", + "deprecated": true, + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionStartDeprecatedRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionDTO" + } + } + } + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/stop": { + "post": { + "operationId": "SessionsController_DEPRECATED_stop", + "summary": "Stop (and Logout if asked) session", + "description": "Stop session and Logout by default.", + "deprecated": true, + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionStopDeprecatedRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sessions/logout": { + "post": { + "operationId": "SessionsController_DEPRECATED_logout", + "summary": "Logout and Delete session.", + "description": "Stop, Logout and Delete session.", + "deprecated": true, + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionLogoutDeprecatedRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🖥️ Sessions"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/profile": { + "get": { + "operationId": "ProfileController_getMyProfile", + "summary": "Get my profile", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MyProfile" + } + } + } + } + }, + "tags": ["🆔 Profile"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/profile/name": { + "put": { + "operationId": "ProfileController_setProfileName", + "summary": "Set my profile name", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileNameRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["🆔 Profile"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/profile/status": { + "put": { + "operationId": "ProfileController_setProfileStatus", + "summary": "Set profile status (About)", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileStatusRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["🆔 Profile"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/profile/picture": { + "put": { + "operationId": "ProfileController_setProfilePicture", + "summary": "Set profile picture", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfilePictureRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["🆔 Profile"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "ProfileController_deleteProfilePicture", + "summary": "Delete profile picture", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["🆔 Profile"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendText": { + "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": [] + } + ] + }, + "get": { + "operationId": "ChattingController_sendTextGet", + "summary": "Send a text message", + "deprecated": true, + "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": [] + } + ] + } + }, + "/api/sendImage": { + "post": { + "operationId": "ChattingController_sendImage", + "summary": "Send an image", + "description": "Either from an URL or base64 data - look at the request schemas for details.", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageImageRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendFile": { + "post": { + "operationId": "ChattingController_sendFile", + "summary": "Send a file", + "description": "Either from an URL or base64 data - look at the request schemas for details.", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageFileRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendVoice": { + "post": { + "operationId": "ChattingController_sendVoice", + "summary": "Send an voice message", + "description": "Either from an URL or base64 data - look at the request schemas for details.", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageVoiceRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendVideo": { + "post": { + "operationId": "ChattingController_sendVideo", + "summary": "Send a video", + "description": "Either from an URL or base64 data - look at the request schemas for details.", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageVideoRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/send/link-custom-preview": { + "post": { + "operationId": "ChattingController_sendLinkCustomPreview", + "summary": "Send a text message with a CUSTOM link preview.", + "description": "You can use regular /api/sendText if you wanna send auto-generated link preview.", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageLinkCustomPreviewRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendButtons": { + "post": { + "operationId": "ChattingController_sendButtons", + "summary": "Send buttons (interactive message)", + "description": "Send Buttons", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendButtonsRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/forwardMessage": { + "post": { + "operationId": "ChattingController_forwardMessage", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageForwardRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAMessage" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendSeen": { + "post": { + "operationId": "ChattingController_sendSeen", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendSeenRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/startTyping": { + "post": { + "operationId": "ChattingController_startTyping", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/stopTyping": { + "post": { + "operationId": "ChattingController_stopTyping", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/reaction": { + "put": { + "operationId": "ChattingController_setReaction", + "summary": "React to a message with an emoji", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageReactionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/star": { + "put": { + "operationId": "ChattingController_setStar", + "summary": "Star or unstar a message", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageStarRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendPoll": { + "post": { + "operationId": "ChattingController_sendPoll", + "summary": "Send a poll with options", + "description": "You can use it as buttons or list replacement", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessagePollRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendLocation": { + "post": { + "operationId": "ChattingController_sendLocation", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageLocationRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "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/send/buttons/reply": { + "post": { + "operationId": "ChattingController_sendButtonsReply", + "summary": "Reply on a button message", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageButtonReply" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/messages": { + "get": { + "operationId": "ChattingController_getMessages", + "summary": "Get messages in a chat", + "description": "DEPRECATED. Use \"GET /api/chats/{id}/messages\" instead", + "deprecated": true, + "parameters": [ + { + "name": "downloadMedia", + "required": false, + "in": "query", + "example": false, + "description": "Download media for messages", + "schema": { + "default": true, + "type": "boolean" + } + }, + { + "name": "chatId", + "required": true, + "in": "query", + "example": "11111111111@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "default": 10, + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "filter.timestamp.lte", + "required": false, + "in": "query", + "description": "Filter messages before this timestamp (inclusive)", + "schema": { + "type": "number" + } + }, + { + "name": "filter.timestamp.gte", + "required": false, + "in": "query", + "description": "Filter messages after this timestamp (inclusive)", + "schema": { + "type": "number" + } + }, + { + "name": "filter.fromMe", + "required": false, + "in": "query", + "description": "From me filter (by default shows all messages)", + "schema": { + "type": "boolean" + } + }, + { + "name": "filter.ack", + "required": false, + "in": "query", + "description": "Filter messages by acknowledgment status", + "schema": { + "enum": ["ERROR", "PENDING", "SERVER", "DEVICE", "READ", "PLAYED"], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WAMessage" + } + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/checkNumberStatus": { + "get": { + "operationId": "ChattingController_DEPRECATED_checkNumberStatus", + "summary": "Check number status", + "description": "DEPRECATED. Use \"POST /contacts/check-exists\" instead", + "deprecated": true, + "parameters": [ + { + "name": "phone", + "required": true, + "in": "query", + "description": "The phone number to check", + "example": "1213213213", + "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/reply": { + "post": { + "operationId": "ChattingController_reply", + "summary": "DEPRECATED - you can set \"reply_to\" field when sending text, image, etc", + "deprecated": true, + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageReplyRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/sendLinkPreview": { + "post": { + "operationId": "ChattingController_sendLinkPreview_DEPRECATED", + "summary": "", + "deprecated": true, + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageLinkPreviewRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📤 Chatting"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats": { + "get": { + "operationId": "ChatsController_getChats", + "summary": "Get chats", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "Sort by field", + "schema": { + "enum": ["conversationTimestamp", "id", "name"], + "type": "string" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", + "schema": { + "enum": ["desc", "asc"], + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/overview": { + "get": { + "operationId": "ChatsController_getChatsOverview", + "summary": "Get chats overview. Includes all necessary things to build UI \"your chats overview\" page - chat id, name, picture, last message. Sorting by last message timestamp", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "limit", + "required": false, + "in": "query", + "schema": { + "default": 20, + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "ids", + "required": false, + "in": "query", + "description": "Filter by chat ids", + "example": ["111111111@c.us"], + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatSummary" + } + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "ChatsController_postChatsOverview", + "summary": "Get chats overview. Use POST if you have too many \"ids\" params - GET can limit it", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OverviewBodyRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatSummary" + } + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}": { + "delete": { + "operationId": "ChatsController_deleteChat", + "summary": "Deletes the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/picture": { + "get": { + "operationId": "ChatsController_getChatPicture", + "summary": "Gets chat picture", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "refresh", + "required": false, + "in": "query", + "example": false, + "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", + "schema": { + "default": false, + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatPictureResponse" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/messages": { + "get": { + "operationId": "ChatsController_getChatMessages", + "summary": "Gets messages in the chat", + "parameters": [ + { + "name": "downloadMedia", + "required": false, + "in": "query", + "example": false, + "description": "Download media for messages", + "schema": { + "default": true, + "type": "boolean" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "default": 10, + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "filter.timestamp.lte", + "required": false, + "in": "query", + "description": "Filter messages before this timestamp (inclusive)", + "schema": { + "type": "number" + } + }, + { + "name": "filter.timestamp.gte", + "required": false, + "in": "query", + "description": "Filter messages after this timestamp (inclusive)", + "schema": { + "type": "number" + } + }, + { + "name": "filter.fromMe", + "required": false, + "in": "query", + "description": "From me filter (by default shows all messages)", + "schema": { + "type": "boolean" + } + }, + { + "name": "filter.ack", + "required": false, + "in": "query", + "description": "Filter messages by acknowledgment status", + "schema": { + "enum": ["ERROR", "PENDING", "SERVER", "DEVICE", "READ", "PLAYED"], + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WAMessage" + } + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "ChatsController_clearMessages", + "summary": "Clears all messages from the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/messages/read": { + "post": { + "operationId": "ChatsController_readChatMessages", + "summary": "Read unread messages in the chat", + "parameters": [ + { + "name": "messages", + "required": false, + "in": "query", + "example": 30, + "description": "How much messages to read (latest first)", + "schema": { + "type": "number" + } + }, + { + "name": "days", + "required": false, + "in": "query", + "description": "How much days to read (latest first)", + "schema": { + "default": 7, + "type": "number" + } + }, + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadChatMessagesResponse" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/messages/{messageId}": { + "get": { + "operationId": "ChatsController_getChatMessage", + "summary": "Gets message by id", + "parameters": [ + { + "name": "downloadMedia", + "required": false, + "in": "query", + "example": true, + "description": "Download media for messages", + "schema": { + "default": true, + "type": "boolean" + } + }, + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "messageId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAMessage" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "ChatsController_deleteMessage", + "summary": "Deletes a message from the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "messageId", + "required": true, + "in": "path", + "description": "Message ID in format {fromMe}_{chat}_{message_id}[_{participant}]", + "example": "true_123456789@c.us_BAE6A33293978B16", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "ChatsController_editMessage", + "summary": "Edits a message in the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "messageId", + "required": true, + "in": "path", + "description": "Message ID in format {fromMe}_{chat}_{message_id}[_{participant}]", + "example": "true_123456789@c.us_BAE6A33293978B16", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EditMessageRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/messages/{messageId}/pin": { + "post": { + "operationId": "ChatsController_pinMessage", + "summary": "Pins a message in the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "messageId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PinMessageRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/messages/{messageId}/unpin": { + "post": { + "operationId": "ChatsController_unpinMessage", + "summary": "Unpins a message in the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "messageId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/archive": { + "post": { + "operationId": "ChatsController_archiveChat", + "summary": "Archive the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/unarchive": { + "post": { + "operationId": "ChatsController_unarchiveChat", + "summary": "Unarchive the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/chats/{chatId}/unread": { + "post": { + "operationId": "ChatsController_unreadChat", + "summary": "Unread the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["💬 Chats"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels": { + "get": { + "operationId": "ChannelsController_list", + "summary": "Get list of know channels", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "role", + "required": false, + "in": "query", + "schema": { + "enum": ["OWNER", "ADMIN", "SUBSCRIBER"], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "ChannelsController_create", + "summary": "Create a new channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChannelRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Channel" + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}": { + "delete": { + "operationId": "ChannelsController_delete", + "summary": "Delete the channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID" + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "ChannelsController_get", + "summary": "Get the channel info", + "description": "You can use either id (123@newsletter) OR invite code (https://www.whatsapp.com/channel/123)", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID or invite code from invite link https://www.whatsapp.com/channel/11111" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Channel" + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}/messages/preview": { + "get": { + "operationId": "ChannelsController_previewChannelMessages", + "summary": "Preview channel messages", + "description": "You can use either invite code (https://www.whatsapp.com/channel/123) or (123)ORChannel ID (123@newsletter).", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Channel id or invite code", + "schema": { + "default": "0029Va4K0PZ5a245NkngBA2M" + } + }, + { + "name": "downloadMedia", + "required": true, + "in": "query", + "schema": { + "default": false, + "type": "boolean" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "default": 10, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelMessage" + } + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}/follow": { + "post": { + "operationId": "ChannelsController_follow", + "summary": "Follow the channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID" + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}/unfollow": { + "post": { + "operationId": "ChannelsController_unfollow", + "summary": "Unfollow the channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID" + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}/mute": { + "post": { + "operationId": "ChannelsController_mute", + "summary": "Mute the channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID" + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/{id}/unmute": { + "post": { + "operationId": "ChannelsController_unmute", + "summary": "Unmute the channel.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "default": "123123123@newsletter" + }, + "description": "WhatsApp Channel ID" + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/search/by-view": { + "post": { + "operationId": "ChannelsController_searchByView", + "summary": "Search for channels (by view)", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelSearchByView" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelListResult" + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/search/by-text": { + "post": { + "operationId": "ChannelsController_searchByText", + "summary": "Search for channels (by text)", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelSearchByText" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelListResult" + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/search/views": { + "get": { + "operationId": "ChannelsController_getSearchViews", + "summary": "Get list of views for channel search", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelView" + } + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/search/countries": { + "get": { + "operationId": "ChannelsController_getSearchCountries", + "summary": "Get list of countries for channel search", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelCountry" + } + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/channels/search/categories": { + "get": { + "operationId": "ChannelsController_getSearchCategories", + "summary": "Get list of categories for channel search", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelCategory" + } + } + } + } + } + }, + "tags": ["📢 Channels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/text": { + "post": { + "operationId": "StatusController_sendTextStatus", + "summary": "Send text status", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TextStatus" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/image": { + "post": { + "operationId": "StatusController_sendImageStatus", + "summary": "Send image status", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageStatus" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/voice": { + "post": { + "operationId": "StatusController_sendVoiceStatus", + "summary": "Send voice status", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceStatus" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/video": { + "post": { + "operationId": "StatusController_sendVideoStatus", + "summary": "Send video status", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VideoStatus" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/delete": { + "post": { + "operationId": "StatusController_deleteStatus", + "summary": "DELETE sent status", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteStatusRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/status/new-message-id": { + "get": { + "operationId": "StatusController_getNewMessageId", + "summary": "Generate message ID you can use to batch contacts", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewMessageIDResponse" + } + } + } + } + }, + "tags": ["🟢 Status"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/labels": { + "get": { + "operationId": "LabelsController_getAll", + "summary": "Get all labels", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "LabelsController_create", + "summary": "Create a new label", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LabelBody" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/labels/{labelId}": { + "put": { + "operationId": "LabelsController_update", + "summary": "Update a label", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "labelId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LabelBody" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "LabelsController_delete", + "summary": "Delete a label", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "labelId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/labels/chats/{chatId}": { + "get": { + "operationId": "LabelsController_getChatLabels", + "summary": "Get labels for the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "LabelsController_putChatLabels", + "summary": "Save labels for the chat", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetLabelsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/labels/{labelId}/chats": { + "get": { + "operationId": "LabelsController_getChatsByLabel", + "summary": "Get chats by label", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "labelId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["🏷️ Labels"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/all": { + "get": { + "operationId": "ContactsController_getAll", + "summary": "Get all contacts", + "parameters": [ + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "Sort by field", + "schema": { + "enum": ["id", "name"], + "type": "string" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", + "schema": { + "enum": ["desc", "asc"], + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts": { + "get": { + "operationId": "ContactsController_get", + "summary": "Get contact basic info", + "description": "The method always return result, even if the phone number is not registered in WhatsApp. For that - use /contacts/check-exists endpoint below.", + "parameters": [ + { + "name": "contactId", + "required": true, + "in": "query", + "example": "11111111111@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/check-exists": { + "get": { + "operationId": "ContactsController_checkExists", + "summary": "Check phone number is registered in WhatsApp.", + "parameters": [ + { + "name": "phone", + "required": true, + "in": "query", + "description": "The phone number to check", + "example": "1213213213", + "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": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/about": { + "get": { + "operationId": "ContactsController_getAbout", + "summary": "Gets the Contact's \"about\" info", + "description": "Returns null if you do not have permission to read their status.", + "parameters": [ + { + "name": "contactId", + "required": true, + "in": "query", + "example": "11111111111@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/profile-picture": { + "get": { + "operationId": "ContactsController_getProfilePicture", + "summary": "Get contact's profile picture URL", + "description": "If privacy settings do not allow to get the picture, the method will return null.", + "parameters": [ + { + "name": "contactId", + "required": true, + "in": "query", + "example": "11111111111@c.us", + "schema": { + "type": "string" + } + }, + { + "name": "refresh", + "required": false, + "in": "query", + "example": false, + "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", + "schema": { + "default": false, + "type": "boolean" + } + }, + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/block": { + "post": { + "operationId": "ContactsController_block", + "summary": "Block contact", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContactRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/contacts/unblock": { + "post": { + "operationId": "ContactsController_unblock", + "summary": "Unblock contact", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContactRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/lids": { + "get": { + "operationId": "LidsController_getAll", + "summary": "Get all known lids to phone number mapping", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "limit", + "required": false, + "in": "query", + "schema": { + "default": 100, + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "default": 0, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LidToPhoneNumber" + } + } + } + } + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/lids/count": { + "get": { + "operationId": "LidsController_getLidsCount", + "summary": "Get the number of known lids", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CountResponse" + } + } + } + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/lids/{lid}": { + "get": { + "operationId": "LidsController_findPNByLid", + "summary": "Get phone number by lid", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "lid", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LidToPhoneNumber" + } + } + } + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/lids/pn/{phoneNumber}": { + "get": { + "operationId": "LidsController_findLIDByPhoneNumber", + "summary": "Get lid by phone number (chat id)", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "phoneNumber", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LidToPhoneNumber" + } + } + } + } + }, + "tags": ["👤 Contacts"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups": { + "post": { + "operationId": "GroupsController_createGroup", + "summary": "Create a new group.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroupRequest" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "GroupsController_getGroups", + "summary": "Get all groups.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "Sort by field", + "schema": { + "enum": ["id", "subject"], + "type": "string" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "Sort order - descending (Z => A, New first) or ascending (A => Z, Old first)", + "schema": { + "enum": ["desc", "asc"], + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "offset", + "required": false, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "exclude", + "required": false, + "in": "query", + "description": "Exclude fields", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": ["", "participants"] + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/join-info": { + "get": { + "operationId": "GroupsController_joinInfoGroup", + "summary": "Get info about the group before joining.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "code", + "required": true, + "in": "query", + "description": "Group code (123) or url (https://chat.whatsapp.com/123)", + "example": "https://chat.whatsapp.com/1234567890abcdef", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/join": { + "post": { + "operationId": "GroupsController_joinGroup", + "summary": "Join group via code", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JoinGroupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JoinGroupResponse" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/count": { + "get": { + "operationId": "GroupsController_getGroupsCount", + "summary": "Get the number of groups.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CountResponse" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/refresh": { + "post": { + "operationId": "GroupsController_refreshGroups", + "summary": "Refresh groups from the server.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}": { + "get": { + "operationId": "GroupsController_getGroup", + "summary": "Get the group.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "GroupsController_deleteGroup", + "summary": "Delete the group.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/leave": { + "post": { + "operationId": "GroupsController_leaveGroup", + "summary": "Leave the group.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/picture": { + "get": { + "operationId": "GroupsController_getChatPicture", + "summary": "Get group picture", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + }, + { + "name": "refresh", + "required": false, + "in": "query", + "example": false, + "description": "Refresh the picture from the server (24h cache by default). Do not refresh if not needed, you can get rate limit error", + "schema": { + "default": false, + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatPictureResponse" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "GroupsController_setPicture", + "summary": "Set group picture", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfilePictureRequest" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "GroupsController_deletePicture", + "summary": "Delete group picture", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + }, + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Result" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/description": { + "put": { + "operationId": "GroupsController_setDescription", + "summary": "Updates the group description.", + "description": "Returns \"true\" if the subject was properly updated. This can return \"false\" if the user does not have the necessary permissions.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DescriptionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/subject": { + "put": { + "operationId": "GroupsController_setSubject", + "summary": "Updates the group subject", + "description": "Returns \"true\" if the subject was properly updated. This can return \"false\" if the user does not have the necessary permissions.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubjectRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/settings/security/info-admin-only": { + "put": { + "operationId": "GroupsController_setInfoAdminOnly", + "summary": "Updates the group \"info admin only\" settings.", + "description": "You can allow only admins to edit group info (title, description, photo).", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSecurityChangeInfo" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "GroupsController_getInfoAdminOnly", + "summary": "Get the group's 'info admin only' settings.", + "description": "You can allow only admins to edit group info (title, description, photo).", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSecurityChangeInfo" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/settings/security/messages-admin-only": { + "put": { + "operationId": "GroupsController_setMessagesAdminOnly", + "summary": "Update settings - who can send messages", + "description": "Updates the group settings to only allow admins to send messages.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSecurityChangeInfo" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "GroupsController_getMessagesAdminOnly", + "summary": "Get settings - who can send messages", + "description": "The group settings to only allow admins to send messages.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSecurityChangeInfo" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/invite-code": { + "get": { + "operationId": "GroupsController_getInviteCode", + "summary": "Gets the invite code for the group.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/invite-code/revoke": { + "post": { + "operationId": "GroupsController_revokeInviteCode", + "summary": "Invalidates the current group invite code and generates a new one.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/participants": { + "get": { + "operationId": "GroupsController_getParticipants", + "summary": "Get participants", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/participants/add": { + "post": { + "operationId": "GroupsController_addParticipants", + "summary": "Add participants", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/participants/remove": { + "post": { + "operationId": "GroupsController_removeParticipants", + "summary": "Remove participants", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/admin/promote": { + "post": { + "operationId": "GroupsController_promoteToAdmin", + "summary": "Promote participants to admin users.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/groups/{id}/admin/demote": { + "post": { + "operationId": "GroupsController_demoteToAdmin", + "summary": "Demotes participants to regular users.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Group ID", + "example": "123123123@g.us", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "" + } + }, + "tags": ["👥 Groups"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/presence": { + "post": { + "operationId": "PresenceController_setPresence", + "summary": "Set session presence", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHASessionPresence" + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": ["✅ Presence"], + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "PresenceController_getPresenceAll", + "summary": "Get all subscribed presence information.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WAHAChatPresences" + } + } + } + } + } + }, + "tags": ["✅ Presence"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/presence/{chatId}": { + "get": { + "operationId": "PresenceController_getPresence", + "summary": "Get the presence for the chat id. If it hasn't been subscribed - it also subscribes to it.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAChatPresences" + } + } + } + } + }, + "tags": ["✅ Presence"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/presence/{chatId}/subscribe": { + "post": { + "operationId": "PresenceController_subscribe", + "summary": "Subscribe to presence events for the chat.", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + }, + { + "name": "chatId", + "required": true, + "in": "path", + "description": "Chat ID", + "example": "123456789@c.us", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": ["✅ Presence"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/screenshot": { + "get": { + "operationId": "ScreenshotController_screenshot", + "parameters": [ + { + "name": "session", + "required": true, + "in": "query", + "schema": { + "default": "default", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Base64File" + } + ] + } + } + }, + "description": "" + } + }, + "tags": ["🖼️ Screenshot"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/{session}/events": { + "post": { + "operationId": "EventsController_sendEvent", + "summary": "Send an event message", + "parameters": [ + { + "name": "session", + "required": true, + "in": "path", + "schema": { + "default": "default" + }, + "description": "Session name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventMessageRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAMessage" + } + } + } + } + }, + "tags": ["📅 Events"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/ping": { + "get": { + "operationId": "PingController_ping", + "summary": "Ping the server", + "description": "Check if the server is alive and responding to requests.", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PingResponse" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/health": { + "get": { + "operationId": "HealthController_check", + "summary": "Check the health of the server", + "description": "Perform all health checks and return the server's health status.", + "parameters": [], + "responses": { + "200": { + "description": "The Health Check is successful", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "ok" + }, + "info": { + "type": "object", + "example": { + "database": { + "status": "up" + } + }, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + }, + "nullable": true + }, + "error": { + "type": "object", + "example": {}, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + }, + "nullable": true + }, + "details": { + "type": "object", + "example": { + "database": { + "status": "up" + } + }, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + } + } + } + } + } + } + }, + "503": { + "description": "The Health Check is not successful", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "error" + }, + "info": { + "type": "object", + "example": { + "database": { + "status": "up" + } + }, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + }, + "nullable": true + }, + "error": { + "type": "object", + "example": { + "redis": { + "status": "down", + "message": "Could not connect" + } + }, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + }, + "nullable": true + }, + "details": { + "type": "object", + "example": { + "database": { + "status": "up" + }, + "redis": { + "status": "down", + "message": "Could not connect" + } + }, + "additionalProperties": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string" + } + }, + "additionalProperties": true + } + } + } + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/server/version": { + "get": { + "operationId": "ServerController_get", + "summary": "Get the version of the server", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/server/environment": { + "get": { + "operationId": "ServerController_environment", + "summary": "Get the server environment", + "parameters": [ + { + "name": "all", + "required": false, + "in": "query", + "example": false, + "description": "Include all environment variables", + "schema": { + "default": false, + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/server/status": { + "get": { + "operationId": "ServerController_status", + "summary": "Get the server status", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServerStatusResponse" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/server/stop": { + "post": { + "operationId": "ServerController_stop", + "summary": "Stop (and restart) the server", + "description": "If you're using docker, after calling this endpoint Docker will start a new container, so you can use this endpoint to restart the server", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StopRequest" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StopResponse" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/server/debug/heapsnapshot": { + "get": { + "operationId": "ServerDebugController_heapsnapshot", + "summary": "Return a heapsnapshot", + "description": "Return a heapsnapshot of the server's memory", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + }, + "/api/version": { + "get": { + "operationId": "VersionController_get", + "summary": "Get the server version ", + "deprecated": true, + "description": "Use 'GET /api/server/version' instead ", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + } + } + } + }, + "tags": ["🔍 Observability"], + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "info": { + "title": "WAHA - WhatsApp HTTP API", + "description": "WhatsApp HTTP API that you can run in a click!
📊 Dashboard

Learn more:

Support the project and get WAHA Plus version!

", + "version": "2025.5.5", + "contact": {} + }, + "tags": [ + { + "name": "🖥️ Sessions", + "description": "Control WhatsApp sessions (accounts)" + }, + { + "name": "🔑 Auth", + "description": "Authentication" + }, + { + "name": "🆔 Profile", + "description": "Your profile information" + }, + { + "name": "🖼️ Screenshot", + "description": "Get screenshot of WhatsApp and show QR code" + }, + { + "name": "📤 Chatting", + "description": "Chatting methods" + }, + { + "name": "📢 Channels", + "description": "Channels (newsletters) methods" + }, + { + "name": "🟢 Status", + "description": "Status (aka stories) methods" + }, + { + "name": "💬 Chats", + "description": "Chats methods" + }, + { + "name": "👤 Contacts", + "description": "Contacts methods.
\n Use phone number (without +) or phone number and `@c.us` at the end as `contactId`.
\n 'E.g: `12312312310` OR `12312312310@c.us`
" + }, + { + "name": "👥 Groups", + "description": "Groups methods.
" + }, + { + "name": "✅ Presence", + "description": "Presence information" + }, + { + "name": "📅 Events", + "description": "Event Message" + }, + { + "name": "🏷️ Labels", + "description": "Labels - available only for WhatsApp Business accounts" + }, + { + "name": "🔍 Observability", + "description": "Other methods" + }, + { + "name": "🗄️ Storage", + "description": "Storage methods" + } + ], + "servers": [ + { + "url": "{protocol}://{host}:{port}/{baseUrl}", + "description": "", + "variables": { + "protocol": { + "default": "http", + "enum": ["http", "https"], + "description": "The protocol used to access the server." + }, + "host": { + "default": "localhost", + "description": "The hostname or IP address of the server." + }, + "port": { + "default": "3000", + "description": "The port number on which the server is listening for requests" + }, + "baseUrl": { + "default": "", + "description": "The base URL path for all API endpoints. This can be used to group related endpoints together under a common path." + } + } + } + ], + "components": { + "securitySchemes": { + "api_key": { + "type": "apiKey", + "in": "header", + "name": "X-Api-Key", + "description": "Your secret api key" + } + }, + "schemas": { + "Base64File": { + "type": "object", + "properties": { + "mimetype": { + "type": "string" + }, + "data": { + "type": "string" + } + }, + "required": ["mimetype", "data"] + }, + "QRCodeValue": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": ["value"] + }, + "RequestCodeRequest": { + "type": "object", + "properties": { + "phoneNumber": { + "type": "string", + "description": "Mobile phone number in international format", + "example": "12132132130" + }, + "method": { + "type": "string", + "description": "How would you like to receive the one time code for registration? |sms|voice. Leave empty for Web pairing.", + "example": null + } + }, + "required": ["phoneNumber"] + }, + "MeInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "11111111111@c.us" + }, + "pushName": { + "type": "string" + } + }, + "required": ["id", "pushName"] + }, + "Map": { + "type": "object", + "properties": {} + }, + "ProxyConfig": { + "type": "object", + "properties": { + "server": { + "type": "string", + "example": "localhost:3128" + }, + "username": { + "type": "string", + "example": null + }, + "password": { + "type": "string", + "example": null + } + }, + "required": ["server"] + }, + "NowebStoreConfig": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "description": "Enable or disable the store for contacts, chats, and messages.", + "example": true + }, + "fullSync": { + "type": "boolean", + "default": false, + "description": "Enable full sync on session initialization (when scanning QR code).\nFull sync will download all contacts, chats, and messages from the phone.\nIf disabled, only messages early than 90 days will be downloaded and some contacts may be missing." + } + }, + "required": ["enabled", "fullSync"] + }, + "NowebConfig": { + "type": "object", + "properties": { + "markOnline": { + "type": "boolean", + "default": true, + "description": "Mark the session as online when it connects to the server." + }, + "store": { + "$ref": "#/components/schemas/NowebStoreConfig" + } + }, + "required": ["markOnline"] + }, + "HmacConfiguration": { + "type": "object", + "properties": { + "key": { + "type": "string", + "example": "your-secret-key" + } + } + }, + "RetriesConfiguration": { + "type": "object", + "properties": { + "delaySeconds": { + "type": "number", + "example": 2 + }, + "attempts": { + "type": "number", + "example": 15 + }, + "policy": { + "enum": ["linear", "exponential", "constant"], + "type": "string", + "example": "linear" + } + } + }, + "CustomHeader": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "X-My-Custom-Header" + }, + "value": { + "type": "string", + "example": "Value" + } + }, + "required": ["name", "value"] + }, + "WebhookConfig": { + "type": "object", + "properties": { + "url": { + "type": "string", + "example": "https://webhook.site/11111111-1111-1111-1111-11111111", + "description": "You can use https://docs.webhook.site/ to test webhooks and see the payload" + }, + "events": { + "example": ["message", "session.status"], + "type": "array", + "items": { + "type": "object" + } + }, + "hmac": { + "example": null, + "allOf": [ + { + "$ref": "#/components/schemas/HmacConfiguration" + } + ] + }, + "retries": { + "example": null, + "allOf": [ + { + "$ref": "#/components/schemas/RetriesConfiguration" + } + ] + }, + "customHeaders": { + "example": null, + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomHeader" + } + } + }, + "required": ["url", "events"] + }, + "SessionConfig": { + "type": "object", + "properties": { + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session. You'll get 'metadata' in all webhooks.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "proxy": { + "example": null, + "allOf": [ + { + "$ref": "#/components/schemas/ProxyConfig" + } + ] + }, + "debug": { + "type": "boolean", + "default": false + }, + "noweb": { + "example": { + "store": { + "enabled": true, + "fullSync": false + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/NowebConfig" + } + ] + }, + "webhooks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebhookConfig" + } + } + } + }, + "SessionInfo": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default", + "description": "Session name (id)" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "assignedWorker": { + "type": "string" + }, + "status": { + "enum": ["STOPPED", "STARTING", "SCAN_QR_CODE", "WORKING", "FAILED"], + "type": "string" + }, + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + }, + "required": ["name", "status"] + }, + "SessionCreateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 54, + "example": "default", + "description": "Session name (id)" + }, + "start": { + "type": "boolean", + "description": "Start session after creation", + "example": true, + "default": true + }, + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + } + }, + "SessionDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default", + "description": "Session name (id)" + }, + "status": { + "enum": ["STOPPED", "STARTING", "SCAN_QR_CODE", "WORKING", "FAILED"], + "type": "string" + }, + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + }, + "required": ["name", "status"] + }, + "SessionUpdateRequest": { + "type": "object", + "properties": { + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + } + }, + "SessionStartDeprecatedRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default", + "description": "Session name (id)" + }, + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + }, + "required": ["name"] + }, + "SessionStopDeprecatedRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default", + "description": "Session name (id)" + }, + "logout": { + "type": "boolean", + "default": false, + "example": false, + "description": "Stop and logout from the session." + } + }, + "required": ["name"] + }, + "SessionLogoutDeprecatedRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default", + "description": "Session name (id)" + } + }, + "required": ["name"] + }, + "MyProfile": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "11111111111@c.us" + }, + "picture": { + "type": "string", + "nullable": true, + "example": "https://example.com/picture.jpg" + }, + "name": { + "type": "string" + } + }, + "required": ["id", "picture", "name"] + }, + "ProfileNameRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "My New Name" + } + }, + "required": ["name"] + }, + "Result": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "default": true + } + }, + "required": ["success"] + }, + "ProfileStatusRequest": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "🎉 Hey there! I am using WhatsApp 🎉" + } + }, + "required": ["status"] + }, + "RemoteFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "string", + "description": "MIME type of the attachment.", + "example": "image/jpeg" + }, + "filename": { + "type": "string", + "description": "Document file name. Value can be null", + "example": "filename.jpg" + }, + "url": { + "type": "string", + "example": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + }, + "required": ["mimetype", "url"] + }, + "BinaryFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "string", + "description": "MIME type of the attachment.", + "example": "image/jpeg" + }, + "filename": { + "type": "string", + "description": "Document file name. Optional", + "example": "filename.jpeg" + }, + "data": { + "type": "string", + "description": "Base64-encoded data of the file", + "example": "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" + } + }, + "required": ["mimetype", "data"] + }, + "ProfilePictureRequest": { + "type": "object", + "properties": { + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + } + }, + "required": ["file"] + }, + "MessageTextRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "text": { + "type": "string", + "default": "Hi there!" + }, + "linkPreview": { + "type": "boolean", + "default": true + }, + "linkPreviewHighQuality": { + "type": "boolean", + "default": false + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "text", "session"] + }, + "S3MediaData": { + "type": "object", + "properties": { + "Bucket": { + "type": "string", + "description": "The name of the S3 bucket", + "example": "my-bucket" + }, + "Key": { + "type": "string", + "description": "The key of the object in the S3 bucket", + "example": "default/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" + } + }, + "required": ["Bucket", "Key"] + }, + "WAMedia": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "The URL for the media in the message if any", + "example": "http://localhost:3000/api/files/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" + }, + "mimetype": { + "type": "string", + "description": "mimetype for the media in the message if any", + "example": "audio/jpeg" + }, + "filename": { + "type": "string", + "description": "The original filename in mediaUrl in the message if any", + "example": "example.pdf" + }, + "s3": { + "description": "S3 attributes for the media in the message if you are using S3 media storage", + "allOf": [ + { + "$ref": "#/components/schemas/S3MediaData" + } + ] + }, + "error": { + "type": "object", + "description": "Error message if there's an error downloading the media", + "example": null + } + } + }, + "WALocation": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "latitude": { + "type": "string" + }, + "longitude": { + "type": "string" + } + }, + "required": ["latitude", "longitude"] + }, + "ReplyToMessage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "AAAAAAAAAAAAAAAAAAAA" + }, + "participant": { + "type": "string", + "example": "11111111111@c.us" + }, + "body": { + "type": "string", + "example": "Hello!" + }, + "_data": { + "type": "object", + "description": "Raw data from reply's message" + } + }, + "required": ["id"] + }, + "WAMessage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "timestamp": { + "type": "number", + "description": "Unix timestamp for when the message was created", + "example": 1666943582 + }, + "from": { + "type": "string", + "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", + "example": "11111111111@c.us" + }, + "fromMe": { + "type": "boolean", + "description": "Indicates if the message was sent by the current user" + }, + "source": { + "enum": ["api", "app"], + "type": "string", + "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", + "example": "api" + }, + "to": { + "type": "string", + "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", + "example": "11111111111@c.us" + }, + "participant": { + "type": "string", + "description": "For groups - participant who sent the message" + }, + "body": { + "type": "string", + "description": "Message content" + }, + "hasMedia": { + "type": "boolean", + "description": "Indicates if the message has media available for download" + }, + "media": { + "description": "Media object for the message if any and downloaded", + "allOf": [ + { + "$ref": "#/components/schemas/WAMedia" + } + ] + }, + "mediaUrl": { + "type": "string", + "description": "Use `media.url` instead! The URL for the media in the message if any", + "deprecated": true, + "example": "http://localhost:3000/api/files/false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA.oga" + }, + "ack": { + "enum": [-1, 0, 1, 2, 3, 4], + "type": "number", + "description": "ACK status for the message" + }, + "ackName": { + "type": "string", + "description": "ACK status name for the message" + }, + "author": { + "type": "string", + "description": "If the message was sent to a group, this field will contain the user that sent the message." + }, + "location": { + "description": "Location information contained in the message, if the message is type \"location\"", + "allOf": [ + { + "$ref": "#/components/schemas/WALocation" + } + ] + }, + "vCards": { + "description": "List of vCards contained in the message.", + "type": "array", + "items": { + "type": "string" + } + }, + "_data": { + "type": "object", + "description": "Message in a raw format that we get from WhatsApp. May be changed anytime, use it with caution! It depends a lot on the underlying backend." + }, + "replyTo": { + "$ref": "#/components/schemas/ReplyToMessage" + } + }, + "required": ["id", "timestamp", "from", "fromMe", "source", "to", "participant", "body", "hasMedia", "mediaUrl", "ack", "ackName"] + }, + "MessageImageRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "caption": { + "type": "string" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "file", "session"] + }, + "MessageFileRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "caption": { + "type": "string" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "file", "session"] + }, + "VoiceBinaryFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "object", + "default": "audio/ogg; codecs=opus", + "description": "MIME type of the attachment." + }, + "filename": { + "type": "object", + "default": "voice-message.mp3", + "description": "Document file name. Optional" + }, + "data": { + "type": "string", + "description": "Base64-encoded data of the file", + "example": "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VSO3pMrPlDI7//NkxP8g454UCuJGUWisGIZWQwUgpHZyhg4kNUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxP4ibDnMAOGEzFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//NkxHwAAANIAAAAAFVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV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" + } + }, + "required": ["mimetype", "filename", "data"] + }, + "VoiceRemoteFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "object", + "default": "audio/ogg; codecs=opus", + "description": "MIME type of the attachment." + }, + "url": { + "type": "string", + "example": "https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus" + } + }, + "required": ["mimetype", "url"] + }, + "MessageVoiceRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/VoiceRemoteFile" + }, + { + "$ref": "#/components/schemas/VoiceBinaryFile" + } + ] + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "file", "session"] + }, + "VideoRemoteFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "object", + "default": "video/mp4", + "description": "MIME type of the attachment." + }, + "filename": { + "type": "object", + "default": "video.mp4", + "description": "Document file name. Optional" + }, + "url": { + "type": "string", + "example": "https://github.com/devlikeapro/waha/raw/core/examples/video.mp4" + } + }, + "required": ["mimetype", "filename", "url"] + }, + "VideoBinaryFile": { + "type": "object", + "properties": { + "mimetype": { + "type": "object", + "default": "video/mp4", + "description": "MIME type of the attachment." + }, + "filename": { + "type": "object", + "default": "video.mp4", + "description": "Document file name. Optional" + }, + "data": { + "type": "string", + "description": "Base64-encoded data of the file", + "example": "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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHYhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAciEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAgAaq3yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq7yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAgAaq/yd8AAAMAAAMAAAMAAAMAHrvIgAAAAwAAAwAFtJAAAAAjIetKI9/zIAAAAwAAAwAAAwAAAwAVW8H+swAAAwAAAwAAEvcAAAAgAatHyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAgAatLyV8AAAMAAAMAAAMAAAMAKY8KAAADAAADAAAIOyAAAAAhAatPyJf/AAADAAADAAADAAADAByn5+AAAAMAAAMABN2QAAAAIiHtiiNf5EAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMCgiAAAAAhAavXyLf/AAADAAADAAADAAADAAADAAADAAADAAADAO6YAAAAIQGr28i3/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwDumAAAACEBq9/It/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMA7pgAAAAiIe/aIt+HAAADAAADAAADAAADAAADAAADAAADAAADAAmagAAAACEBrGfIl/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMBF3AAAAAhAaxryJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHUhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4hEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcyEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwhEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3p4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHohEAUAoBv/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADengAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiEQBQCgG//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAhAaxvyJf/AAADAAADAAADAAADAAADAAADAAADAAADARdwAAAAIQGsc8iX/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwEXcAAAAAEKIRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6IRAFAKAb/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHI=" + } + }, + "required": ["mimetype", "filename", "data"] + }, + "MessageVideoRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/VideoRemoteFile" + }, + { + "$ref": "#/components/schemas/VideoBinaryFile" + } + ] + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "asNote": { + "type": "boolean", + "description": "Send as video note (aka instant or round video).", + "example": false + }, + "caption": { + "type": "string", + "default": "Just watch at this!" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "file", "session"] + }, + "FileURL": { + "type": "object", + "properties": { + "url": { + "type": "string", + "example": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + } + }, + "FileContent": { + "type": "object", + "properties": { + "data": { + "type": "string", + "description": "Base64-encoded data of the file", + "example": "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" + } + } + }, + "LinkPreviewData": { + "type": "object", + "properties": { + "image": { + "oneOf": [ + { + "$ref": "#/components/schemas/FileURL" + }, + { + "$ref": "#/components/schemas/FileContent" + } + ], + "example": { + "url": "https://github.com/devlikeapro/waha/raw/core/examples/waha.jpg" + } + }, + "url": { + "type": "string", + "default": "https://github.com/" + }, + "title": { + "type": "string", + "default": "Your Title" + }, + "description": { + "type": "string", + "default": "Check this out, amazing!" + } + }, + "required": ["url", "title", "description"] + }, + "MessageLinkCustomPreviewRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "text": { + "type": "string", + "default": "Check this out! https://github.com/", + "description": "The text to send. MUST include the URL provided in preview.url" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "linkPreviewHighQuality": { + "type": "boolean", + "default": true + }, + "preview": { + "$ref": "#/components/schemas/LinkPreviewData" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "text", "preview", "session"] + }, + "Button": { + "type": "object", + "properties": { + "text": { + "type": "string", + "example": "Button Text" + }, + "id": { + "type": "string", + "example": "321321" + }, + "url": { + "type": "string", + "example": "https://example.com" + }, + "phoneNumber": { + "type": "string", + "example": "+1234567890" + }, + "copyCode": { + "type": "string", + "example": "4321" + }, + "type": { + "type": "string", + "default": "reply", + "enum": ["reply", "url", "call", "copy"] + } + }, + "required": ["text", "type"] + }, + "SendButtonsRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "header": { + "type": "string", + "example": "How are you?" + }, + "headerImage": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + }, + "body": { + "type": "string", + "example": "Tell us how are you please 🙏" + }, + "footer": { + "type": "string", + "example": "If you have any questions, please send it in the chat" + }, + "buttons": { + "example": [ + { + "type": "reply", + "text": "I am good!" + }, + { + "type": "call", + "text": "Call us", + "phoneNumber": "+1234567890" + }, + { + "type": "copy", + "text": "Copy code", + "copyCode": "4321" + }, + { + "type": "url", + "text": "How did you do that?", + "url": "https://waha.devlike.pro" + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/Button" + } + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "header", "body", "footer", "buttons", "session"] + }, + "MessageForwardRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "messageId": { + "type": "string", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "messageId", "session"] + }, + "SendSeenRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "messageId": { + "type": "string", + "example": null, + "deprecated": true + }, + "messageIds": { + "example": ["false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA"], + "type": "array", + "items": { + "type": "string" + } + }, + "participant": { + "type": "string", + "example": "11111111111@c.us", + "default": null, + "description": "NOWEB engine only - the ID of the user that sent the message (undefined for individual chats)" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "session"] + }, + "ChatRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "session"] + }, + "MessageReactionRequest": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "reaction": { + "type": "string", + "description": "Emoji to react with. Send an empty string to remove the reaction", + "example": "👍" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["messageId", "reaction", "session"] + }, + "MessageStarRequest": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "star": { + "type": "boolean" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["messageId", "chatId", "star", "session"] + }, + "MessagePoll": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "How are you?" + }, + "options": { + "example": ["Awesome!", "Good!", "Not bad!"], + "type": "array", + "items": { + "type": "string" + } + }, + "multipleAnswers": { + "type": "object", + "default": false + } + }, + "required": ["name", "options", "multipleAnswers"] + }, + "MessagePollRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "poll": { + "$ref": "#/components/schemas/MessagePoll" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "poll", "session"] + }, + "MessageLocationRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "latitude": { + "type": "number", + "example": 38.8937255 + }, + "longitude": { + "type": "number", + "example": -77.0969763 + }, + "title": { + "type": "string", + "example": "Our office" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "latitude", "longitude", "title", "session"] + }, + "Contact": { + "type": "object", + "properties": { + "fullName": { + "type": "string", + "example": "John Doe", + "description": "The full name of the contact" + }, + "organization": { + "type": "string", + "example": "Company Name", + "description": "The organization of the contact" + }, + "phoneNumber": { + "type": "string", + "example": "+91 11111 11111", + "description": "The phone number of the contact" + }, + "whatsappId": { + "type": "string", + "example": "911111111111", + "description": "The whatsapp id of the contact. DO NOT add + or @c.us" + }, + "vcard": { + "type": "string", + "default": null + } + }, + "required": ["fullName", "phoneNumber", "vcard"] + }, + "VCardContact": { + "type": "object", + "properties": { + "vcard": { + "type": "string", + "example": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Doe\nORG:Company Name;\nTEL;type=CELL;type=VOICE;waid=911111111111:+91 11111 11111\nEND:VCARD", + "description": "The vcard string" + } + }, + "required": ["vcard"] + }, + "MessageContactVcardRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "contacts": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/VCardContact" + }, + { + "$ref": "#/components/schemas/Contact" + } + ] + } + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "contacts", "session"] + }, + "MessageButtonReply": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "replyTo": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "selectedDisplayText": { + "type": "string" + }, + "selectedButtonID": { + "type": "string" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "selectedDisplayText", "selectedButtonID", "session"] + }, + "WANumberExistResult": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "Chat id for the phone number. Undefined if the number does not exist" + }, + "numberExists": { + "type": "boolean" + } + }, + "required": ["numberExists"] + }, + "MessageReplyRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "text": { + "type": "string", + "default": "Hi there!" + }, + "linkPreview": { + "type": "boolean", + "default": true + }, + "linkPreviewHighQuality": { + "type": "boolean", + "default": false + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["chatId", "text", "session"] + }, + "MessageLinkPreviewRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "session": { + "type": "string", + "default": "default" + }, + "url": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": ["chatId", "session", "url", "title"] + }, + "ChatSummary": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string", + "nullable": true + }, + "picture": { + "type": "string", + "nullable": true + }, + "lastMessage": { + "type": "object" + }, + "_chat": { + "type": "object" + } + }, + "required": ["id", "name", "picture", "lastMessage", "_chat"] + }, + "OverviewPaginationParams": { + "type": "object", + "properties": { + "limit": { + "type": "number", + "default": 20 + }, + "offset": { + "type": "number" + } + } + }, + "OverviewFilter": { + "type": "object", + "properties": { + "ids": { + "description": "Filter by chat ids", + "example": ["111111111@c.us"], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "OverviewBodyRequest": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/OverviewPaginationParams" + }, + "filter": { + "$ref": "#/components/schemas/OverviewFilter" + } + }, + "required": ["pagination", "filter"] + }, + "ChatPictureResponse": { + "type": "object", + "properties": { + "url": { + "type": "string" + } + }, + "required": ["url"] + }, + "ReadChatMessagesResponse": { + "type": "object", + "properties": { + "ids": { + "description": "Messages IDs that have been read", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PinMessageRequest": { + "type": "object", + "properties": { + "duration": { + "type": "number", + "description": "Duration in seconds. 24 hours (86400), 7 days (604800), 30 days (2592000)", + "example": 86400 + } + }, + "required": ["duration"] + }, + "EditMessageRequest": { + "type": "object", + "properties": { + "text": { + "type": "string", + "default": "Hello, world!" + }, + "linkPreview": { + "type": "boolean", + "default": true + }, + "linkPreviewHighQuality": { + "type": "boolean", + "default": false + } + }, + "required": ["text"] + }, + "Channel": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Newsletter id", + "example": "123123123123@newsletter" + }, + "name": { + "type": "string", + "description": "Channel name", + "example": "Channel Name" + }, + "invite": { + "type": "string", + "description": "Invite link", + "example": "https://www.whatsapp.com/channel/111111111111111111111111" + }, + "preview": { + "type": "string", + "description": "Preview for channel's picture", + "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" + }, + "picture": { + "type": "string", + "description": "Channel's picture", + "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" + }, + "role": { + "enum": ["OWNER", "ADMIN", "SUBSCRIBER", "GUEST"], + "type": "string" + }, + "description": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "subscribersCount": { + "type": "number" + } + }, + "required": ["id", "name", "invite", "role", "verified", "subscribersCount"] + }, + "CreateChannelRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Channel Name" + }, + "description": { + "type": "string", + "example": "Channel Description" + }, + "picture": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + } + }, + "required": ["name"] + }, + "ChannelMessage": { + "type": "object", + "properties": { + "reactions": { + "type": "object", + "example": { + "👍": 10, + "❤️": 5 + }, + "additionalProperties": { + "type": "number" + } + }, + "message": { + "$ref": "#/components/schemas/WAMessage" + }, + "viewCount": { + "type": "number" + } + }, + "required": ["reactions", "message", "viewCount"] + }, + "ChannelSearchByView": { + "type": "object", + "properties": { + "view": { + "type": "string", + "default": "RECOMMENDED" + }, + "countries": { + "default": ["US"], + "type": "array", + "items": { + "type": "string" + } + }, + "categories": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "limit": { + "type": "number", + "default": 50 + }, + "startCursor": { + "type": "string", + "default": "" + } + }, + "required": ["view", "countries", "categories", "limit", "startCursor"] + }, + "ChannelPagination": { + "type": "object", + "properties": { + "startCursor": { + "type": "string", + "nullable": true + }, + "endCursor": { + "type": "string", + "nullable": true + }, + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + } + }, + "required": ["startCursor", "endCursor", "hasNextPage", "hasPreviousPage"] + }, + "ChannelPublicInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Newsletter id", + "example": "123123123123@newsletter" + }, + "name": { + "type": "string", + "description": "Channel name", + "example": "Channel Name" + }, + "invite": { + "type": "string", + "description": "Invite link", + "example": "https://www.whatsapp.com/channel/111111111111111111111111" + }, + "preview": { + "type": "string", + "description": "Preview for channel's picture", + "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" + }, + "picture": { + "type": "string", + "description": "Channel's picture", + "example": "https://mmg.whatsapp.net/m1/v/t24/An&_nc_cat=10" + }, + "description": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "subscribersCount": { + "type": "number" + } + }, + "required": ["id", "name", "invite", "verified", "subscribersCount"] + }, + "ChannelListResult": { + "type": "object", + "properties": { + "page": { + "$ref": "#/components/schemas/ChannelPagination" + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelPublicInfo" + } + } + }, + "required": ["page", "channels"] + }, + "ChannelSearchByText": { + "type": "object", + "properties": { + "text": { + "type": "string", + "default": "Donald Trump" + }, + "categories": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "limit": { + "type": "number", + "default": 50 + }, + "startCursor": { + "type": "string", + "default": "" + } + }, + "required": ["text", "categories", "limit", "startCursor"] + }, + "ChannelView": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["value", "name"] + }, + "ChannelCountry": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["code", "name"] + }, + "ChannelCategory": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["value", "name"] + }, + "TextStatus": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Pre-generated status message id", + "example": "BBBBBBBBBBBBBBBBB", + "default": null + }, + "contacts": { + "description": "Contact list to send the status to.", + "example": null, + "type": "array", + "items": { + "type": "string" + } + }, + "text": { + "type": "string", + "default": "Have a look! https://github.com/" + }, + "backgroundColor": { + "type": "string", + "default": "#38b42f" + }, + "font": { + "type": "number", + "default": 0 + }, + "linkPreview": { + "type": "boolean", + "default": true + }, + "linkPreviewHighQuality": { + "type": "boolean", + "default": false + } + }, + "required": ["text", "backgroundColor", "font"] + }, + "ImageStatus": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Pre-generated status message id", + "example": "BBBBBBBBBBBBBBBBB", + "default": null + }, + "contacts": { + "description": "Contact list to send the status to.", + "example": null, + "type": "array", + "items": { + "type": "string" + } + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/RemoteFile" + }, + { + "$ref": "#/components/schemas/BinaryFile" + } + ] + }, + "caption": { + "type": "string" + } + }, + "required": ["file"] + }, + "VoiceStatus": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Pre-generated status message id", + "example": "BBBBBBBBBBBBBBBBB", + "default": null + }, + "contacts": { + "description": "Contact list to send the status to.", + "example": null, + "type": "array", + "items": { + "type": "string" + } + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/VoiceRemoteFile" + }, + { + "$ref": "#/components/schemas/VoiceBinaryFile" + } + ] + }, + "backgroundColor": { + "type": "string", + "default": "#38b42f" + } + }, + "required": ["file", "backgroundColor"] + }, + "VideoStatus": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Pre-generated status message id", + "example": "BBBBBBBBBBBBBBBBB", + "default": null + }, + "contacts": { + "description": "Contact list to send the status to.", + "example": null, + "type": "array", + "items": { + "type": "string" + } + }, + "file": { + "oneOf": [ + { + "$ref": "#/components/schemas/VideoRemoteFile" + }, + { + "$ref": "#/components/schemas/VideoBinaryFile" + } + ] + }, + "caption": { + "type": "string" + } + }, + "required": ["file"] + }, + "DeleteStatusRequest": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Status message id to delete", + "example": "AAAAAAAAAAAAAAAAA", + "default": null + }, + "contacts": { + "description": "Contact list to send the status to.", + "example": null, + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "NewMessageIDResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Pre-generated message id", + "example": "BBBBBBBBBBBBBBBBB" + } + }, + "required": ["id"] + }, + "Label": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "1", + "description": "Label ID" + }, + "name": { + "type": "string", + "example": "Lead", + "description": "Label name" + }, + "color": { + "type": "number", + "example": 0, + "description": "Color number, not hex" + }, + "colorHex": { + "type": "string", + "example": "#ff9485", + "description": "Color in hex" + } + }, + "required": ["id", "name", "color", "colorHex"] + }, + "LabelBody": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Lead", + "description": "Label name" + }, + "colorHex": { + "type": "string", + "example": "#ff9485", + "description": "Color in hex" + }, + "color": { + "type": "number", + "example": null, + "description": "Color number, not hex" + } + }, + "required": ["name"] + }, + "LabelID": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "1", + "description": "Label ID" + } + }, + "required": ["id"] + }, + "SetLabelsRequest": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LabelID" + } + } + }, + "required": ["labels"] + }, + "ContactRequest": { + "type": "object", + "properties": { + "contactId": { + "type": "string", + "example": "11111111111@c.us" + }, + "session": { + "type": "string", + "default": "default" + } + }, + "required": ["contactId", "session"] + }, + "LidToPhoneNumber": { + "type": "object", + "properties": { + "lid": { + "type": "string", + "description": "Linked ID for the user", + "example": "1111111@lid" + }, + "pn": { + "type": "string", + "description": "Phone number (chat id) for the user", + "example": "3333333@c.us" + } + } + }, + "CountResponse": { + "type": "object", + "properties": { + "count": { + "type": "number", + "default": 0 + } + }, + "required": ["count"] + }, + "Participant": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "123456789@c.us" + } + }, + "required": ["id"] + }, + "CreateGroupRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Participant" + } + } + }, + "required": ["name", "participants"] + }, + "JoinGroupRequest": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Group code (123) or url (https://chat.whatsapp.com/123)", + "example": "https://chat.whatsapp.com/1234567890abcdef" + } + }, + "required": ["code"] + }, + "JoinGroupResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Group ID", + "example": "123@g.us" + } + }, + "required": ["id"] + }, + "DescriptionRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + }, + "required": ["description"] + }, + "SubjectRequest": { + "type": "object", + "properties": { + "subject": { + "type": "string" + } + }, + "required": ["subject"] + }, + "SettingsSecurityChangeInfo": { + "type": "object", + "properties": { + "adminsOnly": { + "type": "boolean", + "default": true + } + }, + "required": ["adminsOnly"] + }, + "ParticipantsRequest": { + "type": "object", + "properties": { + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Participant" + } + } + }, + "required": ["participants"] + }, + "WAHASessionPresence": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "description": "Chat ID - either group id or contact id", + "example": "11111111111@c.us" + }, + "presence": { + "type": "string", + "enum": ["offline", "online", "typing", "recording", "paused"] + } + }, + "required": ["chatId", "presence"] + }, + "WAHAPresenceData": { + "type": "object", + "properties": { + "participant": { + "type": "string", + "description": "Chat ID - participant or contact id", + "example": "11111111111@c.us" + }, + "lastSeen": { + "type": "number", + "example": 1686568773 + }, + "lastKnownPresence": { + "type": "string", + "enum": ["offline", "online", "typing", "recording", "paused"] + } + }, + "required": ["participant", "lastKnownPresence"] + }, + "WAHAChatPresences": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Chat ID - either group id or contact id", + "example": "11111111111@c.us" + }, + "presences": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WAHAPresenceData" + } + } + }, + "required": ["id", "presences"] + }, + "EventLocation": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the location", + "example": "Luxe Nail Studio 💅" + } + }, + "required": ["name"] + }, + "EventMessage": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the event", + "example": "John's Nail Appointment 💅" + }, + "description": { + "type": "string", + "description": "Description of the event", + "example": "It's time for your nail care session! 🌟\\n\\nYou'll be getting a *classic gel manicure* – clean, polished, and long-lasting. 💖\\n\\n📍 *Location:* Luxe Nail Studio\\nWe're on the *2nd floor of the Plaza Mall*, next to the flower shop. Look for the *pink neon sign*!\\n\\nFeel free to arrive *5–10 mins early* so we can get started on time 😊" + }, + "startTime": { + "type": "number", + "description": "Start time of the event (Unix timestamp in seconds)", + "example": 2063137000 + }, + "endTime": { + "type": "number", + "description": "End time of the event (Unix timestamp in seconds)", + "example": null + }, + "location": { + "description": "Location of the event", + "allOf": [ + { + "$ref": "#/components/schemas/EventLocation" + } + ] + }, + "extraGuestsAllowed": { + "type": "boolean", + "description": "Whether extra guests are allowed", + "example": false + } + }, + "required": ["name", "startTime"] + }, + "EventMessageRequest": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "example": "11111111111@c.us" + }, + "reply_to": { + "type": "string", + "description": "The ID of the message to reply to - false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA", + "example": null + }, + "event": { + "$ref": "#/components/schemas/EventMessage" + } + }, + "required": ["chatId", "event"] + }, + "PingResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "default": "pong" + } + }, + "required": ["message"] + }, + "WAHAEnvironment": { + "type": "object", + "properties": { + "version": { + "type": "string", + "example": "YYYY.MM.BUILD" + }, + "engine": { + "type": "string", + "example": "WEBJS" + }, + "tier": { + "type": "string", + "example": "PLUS" + }, + "browser": { + "type": "string", + "example": "/usr/path/to/bin/google-chrome" + } + }, + "required": ["version", "engine", "tier", "browser"] + }, + "WorkerInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "waha", + "description": "The worker ID." + } + }, + "required": ["id"] + }, + "ServerStatusResponse": { + "type": "object", + "properties": { + "startTimestamp": { + "type": "number", + "example": 1723788847247, + "description": "The timestamp when the server started (milliseconds)." + }, + "uptime": { + "type": "number", + "example": 3600000, + "description": "The uptime of the server in milliseconds." + }, + "worker": { + "$ref": "#/components/schemas/WorkerInfo" + } + }, + "required": ["startTimestamp", "uptime", "worker"] + }, + "StopRequest": { + "type": "object", + "properties": { + "force": { + "type": "boolean", + "default": false, + "example": false, + "description": "By default, it gracefully stops the server, but you can force it to terminate immediately." + } + } + }, + "StopResponse": { + "type": "object", + "properties": { + "stopping": { + "type": "boolean", + "default": true, + "example": true, + "description": "Always 'true' if the server is stopping." + } + }, + "required": ["stopping"] + }, + "WASessionStatusBody": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "default" + }, + "status": { + "type": "string", + "enum": ["STOPPED", "STARTING", "SCAN_QR_CODE", "WORKING", "FAILED"] + } + }, + "required": ["name", "status"] + }, + "WAHAWebhookSessionStatus": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "session.status", + "description": "The event is triggered when the session status changes." + }, + "payload": { + "$ref": "#/components/schemas/WASessionStatusBody" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookMessage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "message", + "description": "Incoming message." + }, + "payload": { + "$ref": "#/components/schemas/WAMessage" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAReaction": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "Reaction to the message. Either the reaction (emoji) or empty string to remove the reaction" + }, + "messageId": { + "type": "string", + "description": "Message ID for the message to react to", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + } + }, + "required": ["text", "messageId"] + }, + "WAMessageReaction": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "timestamp": { + "type": "number", + "description": "Unix timestamp for when the message was created", + "example": 1666943582 + }, + "from": { + "type": "string", + "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", + "example": "11111111111@c.us" + }, + "fromMe": { + "type": "boolean", + "description": "Indicates if the message was sent by the current user" + }, + "source": { + "enum": ["api", "app"], + "type": "string", + "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", + "example": "api" + }, + "to": { + "type": "string", + "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", + "example": "11111111111@c.us" + }, + "participant": { + "type": "string", + "description": "For groups - participant who sent the message" + }, + "reaction": { + "description": "Reaction to the message. Either the reaction (emoji) or empty string to remove the reaction", + "allOf": [ + { + "$ref": "#/components/schemas/WAReaction" + } + ] + } + }, + "required": ["id", "timestamp", "from", "fromMe", "source", "to", "participant", "reaction"] + }, + "WAHAWebhookMessageReaction": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "message.reaction", + "description": "The event is triggered when a user reacts or removes a reaction." + }, + "payload": { + "$ref": "#/components/schemas/WAMessageReaction" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookMessageAny": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "message.any", + "description": "Fired on all message creations, including your own." + }, + "payload": { + "$ref": "#/components/schemas/WAMessage" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAMessageAckBody": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "from": { + "type": "string", + "example": "11111111111@c.us" + }, + "to": { + "type": "string", + "example": "11111111111@c.us" + }, + "participant": { + "type": "string", + "example": "11111111111@c.us" + }, + "fromMe": { + "type": "boolean" + }, + "ack": { + "type": "number", + "enum": [-1, 0, 1, 2, 3, 4] + }, + "ackName": { + "type": "string" + }, + "_data": { + "type": "object" + } + }, + "required": ["id", "from", "to", "participant", "fromMe", "ack", "ackName"] + }, + "WAHAWebhookMessageAck": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "message.ack", + "description": "Receive events when server or recipient gets the message, read or played it." + }, + "payload": { + "$ref": "#/components/schemas/WAMessageAckBody" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAMessageRevokedBody": { + "type": "object", + "properties": { + "after": { + "$ref": "#/components/schemas/WAMessage" + }, + "before": { + "$ref": "#/components/schemas/WAMessage" + }, + "_data": { + "type": "object" + } + } + }, + "WAHAWebhookMessageRevoked": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "message.revoked", + "description": "The event is triggered when a user, whether it be you or any other participant, revokes a previously sent message." + }, + "payload": { + "$ref": "#/components/schemas/WAMessageRevokedBody" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "GroupParticipant": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "123456789@c.us" + }, + "role": { + "enum": ["left", "participant", "admin", "superadmin"], + "type": "string", + "example": "participant" + } + }, + "required": ["id", "role"] + }, + "GroupInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "123456789@g.us" + }, + "subject": { + "type": "string", + "example": "Group Name" + }, + "description": { + "type": "string", + "example": "Group Description" + }, + "invite": { + "type": "string", + "description": "Invite URL", + "example": "https://chat.whatsapp.com/1234567890abcdef" + }, + "membersCanAddNewMember": { + "type": "boolean", + "description": "Members can add new members" + }, + "membersCanSendMessages": { + "type": "boolean", + "description": "Members can send messages to the group" + }, + "newMembersApprovalRequired": { + "type": "boolean", + "description": "Admin approval required for new members" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GroupParticipant" + } + } + }, + "required": ["id", "subject", "description", "membersCanAddNewMember", "membersCanSendMessages", "newMembersApprovalRequired", "participants"] + }, + "GroupV2JoinEvent": { + "type": "object", + "properties": { + "timestamp": { + "type": "number", + "description": "Unix timestamp", + "example": 1666943582 + }, + "group": { + "$ref": "#/components/schemas/GroupInfo" + }, + "_data": { + "type": "object" + } + }, + "required": ["timestamp", "group", "_data"] + }, + "WebhookGroupV2Join": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.v2.join", + "description": "When you joined or were added to a group" + }, + "payload": { + "$ref": "#/components/schemas/GroupV2JoinEvent" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "GroupId": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "123456789@g.us" + } + }, + "required": ["id"] + }, + "GroupV2LeaveEvent": { + "type": "object", + "properties": { + "timestamp": { + "type": "number", + "description": "Unix timestamp", + "example": 1666943582 + }, + "group": { + "$ref": "#/components/schemas/GroupId" + }, + "_data": { + "type": "object" + } + }, + "required": ["timestamp", "group", "_data"] + }, + "WebhookGroupV2Leave": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.v2.leave", + "description": "When you left or were removed from a group" + }, + "payload": { + "$ref": "#/components/schemas/GroupV2LeaveEvent" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "GroupV2UpdateEvent": { + "type": "object", + "properties": { + "timestamp": { + "type": "number", + "description": "Unix timestamp", + "example": 1666943582 + }, + "group": { + "type": "object" + }, + "_data": { + "type": "object" + } + }, + "required": ["timestamp", "group", "_data"] + }, + "WebhookGroupV2Update": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.v2.update", + "description": "When group info is updated" + }, + "payload": { + "$ref": "#/components/schemas/GroupV2UpdateEvent" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "GroupV2ParticipantsEvent": { + "type": "object", + "properties": { + "type": { + "enum": ["join", "leave", "promote", "demote"], + "type": "string", + "description": "Type of the event" + }, + "timestamp": { + "type": "number", + "description": "Unix timestamp", + "example": 1666943582 + }, + "group": { + "$ref": "#/components/schemas/GroupId" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GroupParticipant" + } + }, + "_data": { + "type": "object" + } + }, + "required": ["type", "timestamp", "group", "participants", "_data"] + }, + "WebhookGroupV2Participants": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.v2.participants", + "description": "When participants changed - join, leave, promote to admin" + }, + "payload": { + "$ref": "#/components/schemas/GroupV2ParticipantsEvent" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookPresenceUpdate": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "presence.update", + "description": "The most recent presence information for a chat." + }, + "payload": { + "$ref": "#/components/schemas/WAHAChatPresences" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "PollVote": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "selectedOptions": { + "description": "Option that user has selected", + "example": ["Awesome!"], + "type": "array", + "items": { + "type": "string" + } + }, + "timestamp": { + "type": "number", + "description": "Timestamp, ms", + "example": 1692861369 + }, + "to": { + "type": "string" + }, + "from": { + "type": "string" + }, + "fromMe": { + "type": "boolean" + }, + "participant": { + "type": "string" + } + }, + "required": ["id", "selectedOptions", "timestamp", "to", "from", "fromMe"] + }, + "MessageDestination": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "to": { + "type": "string" + }, + "from": { + "type": "string" + }, + "fromMe": { + "type": "boolean" + }, + "participant": { + "type": "string" + } + }, + "required": ["id", "to", "from", "fromMe"] + }, + "PollVotePayload": { + "type": "object", + "properties": { + "vote": { + "$ref": "#/components/schemas/PollVote" + }, + "poll": { + "$ref": "#/components/schemas/MessageDestination" + }, + "_data": { + "type": "object" + } + }, + "required": ["vote", "poll"] + }, + "WAHAWebhookPollVote": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "poll.vote", + "description": "With this event, you receive new votes for the poll sent." + }, + "payload": { + "$ref": "#/components/schemas/PollVotePayload" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookPollVoteFailed": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "poll.vote.failed", + "description": "There may be cases when it fails to decrypt a vote from the user. Read more about how to handle such events in the documentations." + }, + "payload": { + "$ref": "#/components/schemas/PollVotePayload" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "ChatArchiveEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "11111111111@c.us" + }, + "archived": { + "type": "boolean" + }, + "timestamp": { + "type": "number" + } + }, + "required": ["id", "archived", "timestamp"] + }, + "WAHAWebhookChatArchive": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "chat.archive", + "description": "The event is triggered when the chat is archived or unarchived" + }, + "payload": { + "$ref": "#/components/schemas/ChatArchiveEvent" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "CallData": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Call ID", + "example": "ABCDEFGABCDEFGABCDEFGABCDEFG" + }, + "from": { + "type": "string", + "example": "11111111111@c.us" + }, + "timestamp": { + "type": "number" + }, + "isVideo": { + "type": "boolean" + }, + "isGroup": { + "type": "boolean" + } + }, + "required": ["id", "timestamp", "isVideo", "isGroup"] + }, + "WAHAWebhookCallReceived": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "call.received", + "description": "The event is triggered when the call is received by the user." + }, + "payload": { + "$ref": "#/components/schemas/CallData" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookCallAccepted": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "call.accepted", + "description": "The event is triggered when the call is accepted by the user." + }, + "payload": { + "$ref": "#/components/schemas/CallData" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookCallRejected": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "call.rejected", + "description": "The event is triggered when the call is rejected by the user." + }, + "payload": { + "$ref": "#/components/schemas/CallData" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookLabelUpsert": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "label.upsert", + "description": "The event is triggered when a label is created or updated" + }, + "payload": { + "$ref": "#/components/schemas/Label" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookLabelDeleted": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "label.deleted", + "description": "The event is triggered when a label is deleted" + }, + "payload": { + "$ref": "#/components/schemas/Label" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "LabelChatAssociation": { + "type": "object", + "properties": { + "labelId": { + "type": "string", + "example": "1", + "description": "Label ID" + }, + "chatId": { + "type": "string", + "description": "Chat ID", + "example": "11111111111@c.us" + }, + "label": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/Label" + } + ] + } + }, + "required": ["labelId", "chatId", "label"] + }, + "WAHAWebhookLabelChatAdded": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "label.chat.added", + "description": "The event is triggered when a label is added to a chat" + }, + "payload": { + "$ref": "#/components/schemas/LabelChatAssociation" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookLabelChatDeleted": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "label.chat.deleted", + "description": "The event is triggered when a label is deleted from a chat" + }, + "payload": { + "$ref": "#/components/schemas/LabelChatAssociation" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "EventResponse": { + "type": "object", + "properties": { + "response": { + "type": "string", + "enum": ["UNKNOWN", "GOING", "NOT_GOING", "MAYBE"] + }, + "timestampMs": { + "type": "number" + }, + "extraGuestCount": { + "type": "number" + } + }, + "required": ["response", "timestampMs", "extraGuestCount"] + }, + "EventResponsePayload": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Message ID", + "example": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA" + }, + "timestamp": { + "type": "number", + "description": "Unix timestamp for when the message was created", + "example": 1666943582 + }, + "from": { + "type": "string", + "description": "ID for the Chat that this message was sent to, except if the message was sent by the current user ", + "example": "11111111111@c.us" + }, + "fromMe": { + "type": "boolean", + "description": "Indicates if the message was sent by the current user" + }, + "source": { + "enum": ["api", "app"], + "type": "string", + "description": "The device that sent the message - either API or APP. Available in events (webhooks/websockets) only and only \"fromMe: true\" messages.", + "example": "api" + }, + "to": { + "type": "string", + "description": "\n* ID for who this message is for.\n* If the message is sent by the current user, it will be the Chat to which the message is being sent.\n* If the message is sent by another user, it will be the ID for the current user.\n", + "example": "11111111111@c.us" + }, + "participant": { + "type": "string", + "description": "For groups - participant who sent the message" + }, + "_data": { + "type": "object", + "description": "Message in a raw format that we get from WhatsApp. May be changed anytime, use it with caution! It depends a lot on the underlying backend." + }, + "eventCreationKey": { + "$ref": "#/components/schemas/MessageDestination" + }, + "eventResponse": { + "$ref": "#/components/schemas/EventResponse" + } + }, + "required": ["id", "timestamp", "from", "fromMe", "source", "to", "participant", "eventCreationKey"] + }, + "WAHAWebhookEventResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "event.response", + "description": "The event is triggered when the event response is received." + }, + "payload": { + "$ref": "#/components/schemas/EventResponsePayload" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookEventResponseFailed": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "event.response.failed", + "description": "The event is triggered when the event response is failed to decrypt." + }, + "payload": { + "$ref": "#/components/schemas/EventResponsePayload" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "EnginePayload": { + "type": "object", + "properties": { + "event": { + "type": "string" + }, + "data": { + "type": "object" + } + }, + "required": ["event", "data"] + }, + "WAHAWebhookEngineEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "engine.event", + "description": "Internal engine event." + }, + "payload": { + "$ref": "#/components/schemas/EnginePayload" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookGroupJoin": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.join", + "description": "Some one join a group.", + "deprecated": true + }, + "payload": { + "type": "object" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookGroupLeave": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "group.leave", + "description": "Some one left a group.", + "deprecated": true + }, + "payload": { + "type": "object" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + }, + "WAHAWebhookStateChange": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa", + "description": "Unique identifier for the event - lower case ULID format. https://github.com/ulid/spec" + }, + "timestamp": { + "type": "number", + "example": 1634567890123, + "description": "Unix timestamp (ms) for when the event was created." + }, + "session": { + "type": "string", + "example": "default" + }, + "metadata": { + "example": { + "user.id": "123", + "user.email": "email@example.com" + }, + "description": "Metadata for the session.", + "allOf": [ + { + "$ref": "#/components/schemas/Map" + } + ] + }, + "engine": { + "enum": ["WEBJS", "NOWEB", "GOWS"], + "type": "string", + "example": "WEBJS" + }, + "event": { + "enum": ["session.status", "message", "message.reaction", "message.any", "message.ack", "message.waiting", "message.revoked", "state.change", "group.join", "group.leave", "group.v2.join", "group.v2.leave", "group.v2.update", "group.v2.participants", "presence.update", "poll.vote", "poll.vote.failed", "chat.archive", "call.received", "call.accepted", "call.rejected", "label.upsert", "label.deleted", "label.chat.added", "label.chat.deleted", "event.response", "event.response.failed", "engine.event"], + "type": "object", + "default": "state.change", + "description": "It’s an internal engine’s state, not session status.", + "deprecated": true + }, + "payload": { + "type": "object" + }, + "me": { + "$ref": "#/components/schemas/MeInfo" + }, + "environment": { + "$ref": "#/components/schemas/WAHAEnvironment" + } + }, + "required": ["id", "timestamp", "session", "engine", "event", "payload", "environment"] + } + } + }, + "externalDocs": { + "description": "WAHA - WhatsApp HTTP API", + "url": "https://waha.devlike.pro/" + }, + "webhooks": { + "session.status": { + "post": { + "summary": "The event is triggered when the session status changes.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookSessionStatus" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "message": { + "post": { + "summary": "Incoming message.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookMessage" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "message.reaction": { + "post": { + "summary": "The event is triggered when a user reacts or removes a reaction.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookMessageReaction" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "message.any": { + "post": { + "summary": "Fired on all message creations, including your own.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookMessageAny" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "message.ack": { + "post": { + "summary": "Receive events when server or recipient gets the message, read or played it.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookMessageAck" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "message.revoked": { + "post": { + "summary": "The event is triggered when a user, whether it be you or any other participant, revokes a previously sent message.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookMessageRevoked" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.v2.join": { + "post": { + "summary": "When you joined or were added to a group", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookGroupV2Join" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.v2.leave": { + "post": { + "summary": "When you left or were removed from a group", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookGroupV2Leave" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.v2.update": { + "post": { + "summary": "When group info is updated", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookGroupV2Update" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.v2.participants": { + "post": { + "summary": "When participants changed - join, leave, promote to admin", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookGroupV2Participants" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "presence.update": { + "post": { + "summary": "The most recent presence information for a chat.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookPresenceUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "poll.vote": { + "post": { + "summary": "With this event, you receive new votes for the poll sent.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookPollVote" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "poll.vote.failed": { + "post": { + "summary": "There may be cases when it fails to decrypt a vote from the user. Read more about how to handle such events in the documentations.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookPollVoteFailed" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "chat.archive": { + "post": { + "summary": "The event is triggered when the chat is archived or unarchived", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookChatArchive" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "call.received": { + "post": { + "summary": "The event is triggered when the call is received by the user.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookCallReceived" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "call.accepted": { + "post": { + "summary": "The event is triggered when the call is accepted by the user.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookCallAccepted" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "call.rejected": { + "post": { + "summary": "The event is triggered when the call is rejected by the user.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookCallRejected" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "label.upsert": { + "post": { + "summary": "The event is triggered when a label is created or updated", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookLabelUpsert" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "label.deleted": { + "post": { + "summary": "The event is triggered when a label is deleted", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookLabelDeleted" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "label.chat.added": { + "post": { + "summary": "The event is triggered when a label is added to a chat", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookLabelChatAdded" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "label.chat.deleted": { + "post": { + "summary": "The event is triggered when a label is deleted from a chat", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookLabelChatDeleted" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "event.response": { + "post": { + "summary": "The event is triggered when the event response is received.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookEventResponse" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "event.response.failed": { + "post": { + "summary": "The event is triggered when the event response is failed to decrypt.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookEventResponseFailed" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "engine.event": { + "post": { + "summary": "Internal engine event.", + "deprecated": false, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookEngineEvent" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.join": { + "post": { + "summary": "Some one join a group.", + "deprecated": true, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookGroupJoin" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "group.leave": { + "post": { + "summary": "Some one left a group.", + "deprecated": true, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookGroupLeave" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + }, + "state.change": { + "post": { + "summary": "It’s an internal engine’s state, not session status.", + "deprecated": true, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAHAWebhookStateChange" + } + } + } + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully" + } + } + } + } + } +} diff --git a/static/swagger/swagger-initializer.js b/static/swagger/swagger-initializer.js index 1e4c816ea..ed7d7ed48 100644 --- a/static/swagger/swagger-initializer.js +++ b/static/swagger/swagger-initializer.js @@ -1,20 +1,15 @@ -window.onload = function() { - // - - // 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" - }); - - // -}; +window.onload = function () { + // + + // 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' + }); + + // +}; diff --git a/static/swagger/swagger-ui-bundle.js b/static/swagger/swagger-ui-bundle.js index c7cb5a8c1..e9f5ca064 100644 --- a/static/swagger/swagger-ui-bundle.js +++ b/static/swagger/swagger-ui-bundle.js @@ -1,3 +1,49262 @@ -/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ -!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=/^.+(:|:)/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>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>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=j)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+j.toString(16)+" bytes");return 0|i}function byteLength(i,s){if(Buffer.isBuffer(i))return i.length;if(ArrayBuffer.isView(i)||isInstance(i,ArrayBuffer))return i.byteLength;if("string"!=typeof i)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof i);const u=i.length,m=arguments.length>2&&!0===arguments[2];if(!m&&0===u)return 0;let v=!1;for(;;)switch(s){case"ascii":case"latin1":case"binary":return u;case"utf8":case"utf-8":return utf8ToBytes(i).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*u;case"hex":return u>>>1;case"base64":return base64ToBytes(i).length;default:if(v)return m?-1:utf8ToBytes(i).length;s=(""+s).toLowerCase(),v=!0}}function slowToString(i,s,u){let m=!1;if((void 0===s||s<0)&&(s=0),s>this.length)return"";if((void 0===u||u>this.length)&&(u=this.length),u<=0)return"";if((u>>>=0)<=(s>>>=0))return"";for(i||(i="utf8");;)switch(i){case"hex":return hexSlice(this,s,u);case"utf8":case"utf-8":return utf8Slice(this,s,u);case"ascii":return asciiSlice(this,s,u);case"latin1":case"binary":return latin1Slice(this,s,u);case"base64":return base64Slice(this,s,u);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,s,u);default:if(m)throw new TypeError("Unknown encoding: "+i);i=(i+"").toLowerCase(),m=!0}}function swap(i,s,u){const m=i[s];i[s]=i[u],i[u]=m}function bidirectionalIndexOf(i,s,u,m,v){if(0===i.length)return-1;if("string"==typeof u?(m=u,u=0):u>2147483647?u=2147483647:u<-2147483648&&(u=-2147483648),numberIsNaN(u=+u)&&(u=v?0:i.length-1),u<0&&(u=i.length+u),u>=i.length){if(v)return-1;u=i.length-1}else if(u<0){if(!v)return-1;u=0}if("string"==typeof s&&(s=Buffer.from(s,m)),Buffer.isBuffer(s))return 0===s.length?-1:arrayIndexOf(i,s,u,m,v);if("number"==typeof s)return s&=255,"function"==typeof Uint8Array.prototype.indexOf?v?Uint8Array.prototype.indexOf.call(i,s,u):Uint8Array.prototype.lastIndexOf.call(i,s,u):arrayIndexOf(i,[s],u,m,v);throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(i,s,u,m,v){let _,j=1,M=i.length,$=s.length;if(void 0!==m&&("ucs2"===(m=String(m).toLowerCase())||"ucs-2"===m||"utf16le"===m||"utf-16le"===m)){if(i.length<2||s.length<2)return-1;j=2,M/=2,$/=2,u/=2}function read(i,s){return 1===j?i[s]:i.readUInt16BE(s*j)}if(v){let m=-1;for(_=u;_M&&(u=M-$),_=u;_>=0;_--){let u=!0;for(let m=0;m<$;m++)if(read(i,_+m)!==read(s,m)){u=!1;break}if(u)return _}return-1}function hexWrite(i,s,u,m){u=Number(u)||0;const v=i.length-u;m?(m=Number(m))>v&&(m=v):m=v;const _=s.length;let j;for(m>_/2&&(m=_/2),j=0;j>8,v=u%256,_.push(v),_.push(m);return _}(s,i.length-u),i,u,m)}function base64Slice(i,s,u){return 0===s&&u===i.length?m.fromByteArray(i):m.fromByteArray(i.slice(s,u))}function utf8Slice(i,s,u){u=Math.min(i.length,u);const m=[];let v=s;for(;v239?4:s>223?3:s>191?2:1;if(v+j<=u){let u,m,M,$;switch(j){case 1:s<128&&(_=s);break;case 2:u=i[v+1],128==(192&u)&&($=(31&s)<<6|63&u,$>127&&(_=$));break;case 3:u=i[v+1],m=i[v+2],128==(192&u)&&128==(192&m)&&($=(15&s)<<12|(63&u)<<6|63&m,$>2047&&($<55296||$>57343)&&(_=$));break;case 4:u=i[v+1],m=i[v+2],M=i[v+3],128==(192&u)&&128==(192&m)&&128==(192&M)&&($=(15&s)<<18|(63&u)<<12|(63&m)<<6|63&M,$>65535&&$<1114112&&(_=$))}}null===_?(_=65533,j=1):_>65535&&(_-=65536,m.push(_>>>10&1023|55296),_=56320|1023&_),m.push(_),v+=j}return function decodeCodePointsArray(i){const s=i.length;if(s<=M)return String.fromCharCode.apply(String,i);let u="",m=0;for(;mm.length?(Buffer.isBuffer(s)||(s=Buffer.from(s)),s.copy(m,v)):Uint8Array.prototype.set.call(m,s,v);else{if(!Buffer.isBuffer(s))throw new TypeError('"list" argument must be an Array of Buffers');s.copy(m,v)}v+=s.length}return m},Buffer.byteLength=byteLength,Buffer.prototype._isBuffer=!0,Buffer.prototype.swap16=function swap16(){const i=this.length;if(i%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let s=0;su&&(i+=" ... "),""},_&&(Buffer.prototype[_]=Buffer.prototype.inspect),Buffer.prototype.compare=function compare(i,s,u,m,v){if(isInstance(i,Uint8Array)&&(i=Buffer.from(i,i.offset,i.byteLength)),!Buffer.isBuffer(i))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof i);if(void 0===s&&(s=0),void 0===u&&(u=i?i.length:0),void 0===m&&(m=0),void 0===v&&(v=this.length),s<0||u>i.length||m<0||v>this.length)throw new RangeError("out of range index");if(m>=v&&s>=u)return 0;if(m>=v)return-1;if(s>=u)return 1;if(this===i)return 0;let _=(v>>>=0)-(m>>>=0),j=(u>>>=0)-(s>>>=0);const M=Math.min(_,j),$=this.slice(m,v),W=i.slice(s,u);for(let i=0;i>>=0,isFinite(u)?(u>>>=0,void 0===m&&(m="utf8")):(m=u,u=void 0)}const v=this.length-s;if((void 0===u||u>v)&&(u=v),i.length>0&&(u<0||s<0)||s>this.length)throw new RangeError("Attempt to write outside buffer bounds");m||(m="utf8");let _=!1;for(;;)switch(m){case"hex":return hexWrite(this,i,s,u);case"utf8":case"utf-8":return utf8Write(this,i,s,u);case"ascii":case"latin1":case"binary":return asciiWrite(this,i,s,u);case"base64":return base64Write(this,i,s,u);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,i,s,u);default:if(_)throw new TypeError("Unknown encoding: "+m);m=(""+m).toLowerCase(),_=!0}},Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};const M=4096;function asciiSlice(i,s,u){let m="";u=Math.min(i.length,u);for(let v=s;vm)&&(u=m);let v="";for(let m=s;mu)throw new RangeError("Trying to access beyond buffer length")}function checkInt(i,s,u,m,v,_){if(!Buffer.isBuffer(i))throw new TypeError('"buffer" argument must be a Buffer instance');if(s>v||s<_)throw new RangeError('"value" argument is out of bounds');if(u+m>i.length)throw new RangeError("Index out of range")}function wrtBigUInt64LE(i,s,u,m,v){checkIntBI(s,m,v,i,u,7);let _=Number(s&BigInt(4294967295));i[u++]=_,_>>=8,i[u++]=_,_>>=8,i[u++]=_,_>>=8,i[u++]=_;let j=Number(s>>BigInt(32)&BigInt(4294967295));return i[u++]=j,j>>=8,i[u++]=j,j>>=8,i[u++]=j,j>>=8,i[u++]=j,u}function wrtBigUInt64BE(i,s,u,m,v){checkIntBI(s,m,v,i,u,7);let _=Number(s&BigInt(4294967295));i[u+7]=_,_>>=8,i[u+6]=_,_>>=8,i[u+5]=_,_>>=8,i[u+4]=_;let j=Number(s>>BigInt(32)&BigInt(4294967295));return i[u+3]=j,j>>=8,i[u+2]=j,j>>=8,i[u+1]=j,j>>=8,i[u]=j,u+8}function checkIEEE754(i,s,u,m,v,_){if(u+m>i.length)throw new RangeError("Index out of range");if(u<0)throw new RangeError("Index out of range")}function writeFloat(i,s,u,m,_){return s=+s,u>>>=0,_||checkIEEE754(i,0,u,4),v.write(i,s,u,m,23,4),u+4}function writeDouble(i,s,u,m,_){return s=+s,u>>>=0,_||checkIEEE754(i,0,u,8),v.write(i,s,u,m,52,8),u+8}Buffer.prototype.slice=function slice(i,s){const u=this.length;(i=~~i)<0?(i+=u)<0&&(i=0):i>u&&(i=u),(s=void 0===s?u:~~s)<0?(s+=u)<0&&(s=0):s>u&&(s=u),s>>=0,s>>>=0,u||checkOffset(i,s,this.length);let m=this[i],v=1,_=0;for(;++_>>=0,s>>>=0,u||checkOffset(i,s,this.length);let m=this[i+--s],v=1;for(;s>0&&(v*=256);)m+=this[i+--s]*v;return m},Buffer.prototype.readUint8=Buffer.prototype.readUInt8=function readUInt8(i,s){return i>>>=0,s||checkOffset(i,1,this.length),this[i]},Buffer.prototype.readUint16LE=Buffer.prototype.readUInt16LE=function readUInt16LE(i,s){return i>>>=0,s||checkOffset(i,2,this.length),this[i]|this[i+1]<<8},Buffer.prototype.readUint16BE=Buffer.prototype.readUInt16BE=function readUInt16BE(i,s){return i>>>=0,s||checkOffset(i,2,this.length),this[i]<<8|this[i+1]},Buffer.prototype.readUint32LE=Buffer.prototype.readUInt32LE=function readUInt32LE(i,s){return i>>>=0,s||checkOffset(i,4,this.length),(this[i]|this[i+1]<<8|this[i+2]<<16)+16777216*this[i+3]},Buffer.prototype.readUint32BE=Buffer.prototype.readUInt32BE=function readUInt32BE(i,s){return i>>>=0,s||checkOffset(i,4,this.length),16777216*this[i]+(this[i+1]<<16|this[i+2]<<8|this[i+3])},Buffer.prototype.readBigUInt64LE=defineBigIntMethod((function readBigUInt64LE(i){validateNumber(i>>>=0,"offset");const s=this[i],u=this[i+7];void 0!==s&&void 0!==u||boundsError(i,this.length-8);const m=s+256*this[++i]+65536*this[++i]+this[++i]*2**24,v=this[++i]+256*this[++i]+65536*this[++i]+u*2**24;return BigInt(m)+(BigInt(v)<>>=0,"offset");const s=this[i],u=this[i+7];void 0!==s&&void 0!==u||boundsError(i,this.length-8);const m=s*2**24+65536*this[++i]+256*this[++i]+this[++i],v=this[++i]*2**24+65536*this[++i]+256*this[++i]+u;return(BigInt(m)<>>=0,s>>>=0,u||checkOffset(i,s,this.length);let m=this[i],v=1,_=0;for(;++_=v&&(m-=Math.pow(2,8*s)),m},Buffer.prototype.readIntBE=function readIntBE(i,s,u){i>>>=0,s>>>=0,u||checkOffset(i,s,this.length);let m=s,v=1,_=this[i+--m];for(;m>0&&(v*=256);)_+=this[i+--m]*v;return v*=128,_>=v&&(_-=Math.pow(2,8*s)),_},Buffer.prototype.readInt8=function readInt8(i,s){return i>>>=0,s||checkOffset(i,1,this.length),128&this[i]?-1*(255-this[i]+1):this[i]},Buffer.prototype.readInt16LE=function readInt16LE(i,s){i>>>=0,s||checkOffset(i,2,this.length);const u=this[i]|this[i+1]<<8;return 32768&u?4294901760|u:u},Buffer.prototype.readInt16BE=function readInt16BE(i,s){i>>>=0,s||checkOffset(i,2,this.length);const u=this[i+1]|this[i]<<8;return 32768&u?4294901760|u:u},Buffer.prototype.readInt32LE=function readInt32LE(i,s){return i>>>=0,s||checkOffset(i,4,this.length),this[i]|this[i+1]<<8|this[i+2]<<16|this[i+3]<<24},Buffer.prototype.readInt32BE=function readInt32BE(i,s){return i>>>=0,s||checkOffset(i,4,this.length),this[i]<<24|this[i+1]<<16|this[i+2]<<8|this[i+3]},Buffer.prototype.readBigInt64LE=defineBigIntMethod((function readBigInt64LE(i){validateNumber(i>>>=0,"offset");const s=this[i],u=this[i+7];void 0!==s&&void 0!==u||boundsError(i,this.length-8);const m=this[i+4]+256*this[i+5]+65536*this[i+6]+(u<<24);return(BigInt(m)<>>=0,"offset");const s=this[i],u=this[i+7];void 0!==s&&void 0!==u||boundsError(i,this.length-8);const m=(s<<24)+65536*this[++i]+256*this[++i]+this[++i];return(BigInt(m)<>>=0,s||checkOffset(i,4,this.length),v.read(this,i,!0,23,4)},Buffer.prototype.readFloatBE=function readFloatBE(i,s){return i>>>=0,s||checkOffset(i,4,this.length),v.read(this,i,!1,23,4)},Buffer.prototype.readDoubleLE=function readDoubleLE(i,s){return i>>>=0,s||checkOffset(i,8,this.length),v.read(this,i,!0,52,8)},Buffer.prototype.readDoubleBE=function readDoubleBE(i,s){return i>>>=0,s||checkOffset(i,8,this.length),v.read(this,i,!1,52,8)},Buffer.prototype.writeUintLE=Buffer.prototype.writeUIntLE=function writeUIntLE(i,s,u,m){if(i=+i,s>>>=0,u>>>=0,!m){checkInt(this,i,s,u,Math.pow(2,8*u)-1,0)}let v=1,_=0;for(this[s]=255&i;++_>>=0,u>>>=0,!m){checkInt(this,i,s,u,Math.pow(2,8*u)-1,0)}let v=u-1,_=1;for(this[s+v]=255&i;--v>=0&&(_*=256);)this[s+v]=i/_&255;return s+u},Buffer.prototype.writeUint8=Buffer.prototype.writeUInt8=function writeUInt8(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,1,255,0),this[s]=255&i,s+1},Buffer.prototype.writeUint16LE=Buffer.prototype.writeUInt16LE=function writeUInt16LE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,2,65535,0),this[s]=255&i,this[s+1]=i>>>8,s+2},Buffer.prototype.writeUint16BE=Buffer.prototype.writeUInt16BE=function writeUInt16BE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,2,65535,0),this[s]=i>>>8,this[s+1]=255&i,s+2},Buffer.prototype.writeUint32LE=Buffer.prototype.writeUInt32LE=function writeUInt32LE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,4,4294967295,0),this[s+3]=i>>>24,this[s+2]=i>>>16,this[s+1]=i>>>8,this[s]=255&i,s+4},Buffer.prototype.writeUint32BE=Buffer.prototype.writeUInt32BE=function writeUInt32BE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,4,4294967295,0),this[s]=i>>>24,this[s+1]=i>>>16,this[s+2]=i>>>8,this[s+3]=255&i,s+4},Buffer.prototype.writeBigUInt64LE=defineBigIntMethod((function writeBigUInt64LE(i,s=0){return wrtBigUInt64LE(this,i,s,BigInt(0),BigInt("0xffffffffffffffff"))})),Buffer.prototype.writeBigUInt64BE=defineBigIntMethod((function writeBigUInt64BE(i,s=0){return wrtBigUInt64BE(this,i,s,BigInt(0),BigInt("0xffffffffffffffff"))})),Buffer.prototype.writeIntLE=function writeIntLE(i,s,u,m){if(i=+i,s>>>=0,!m){const m=Math.pow(2,8*u-1);checkInt(this,i,s,u,m-1,-m)}let v=0,_=1,j=0;for(this[s]=255&i;++v>0)-j&255;return s+u},Buffer.prototype.writeIntBE=function writeIntBE(i,s,u,m){if(i=+i,s>>>=0,!m){const m=Math.pow(2,8*u-1);checkInt(this,i,s,u,m-1,-m)}let v=u-1,_=1,j=0;for(this[s+v]=255&i;--v>=0&&(_*=256);)i<0&&0===j&&0!==this[s+v+1]&&(j=1),this[s+v]=(i/_>>0)-j&255;return s+u},Buffer.prototype.writeInt8=function writeInt8(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,1,127,-128),i<0&&(i=255+i+1),this[s]=255&i,s+1},Buffer.prototype.writeInt16LE=function writeInt16LE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,2,32767,-32768),this[s]=255&i,this[s+1]=i>>>8,s+2},Buffer.prototype.writeInt16BE=function writeInt16BE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,2,32767,-32768),this[s]=i>>>8,this[s+1]=255&i,s+2},Buffer.prototype.writeInt32LE=function writeInt32LE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,4,2147483647,-2147483648),this[s]=255&i,this[s+1]=i>>>8,this[s+2]=i>>>16,this[s+3]=i>>>24,s+4},Buffer.prototype.writeInt32BE=function writeInt32BE(i,s,u){return i=+i,s>>>=0,u||checkInt(this,i,s,4,2147483647,-2147483648),i<0&&(i=4294967295+i+1),this[s]=i>>>24,this[s+1]=i>>>16,this[s+2]=i>>>8,this[s+3]=255&i,s+4},Buffer.prototype.writeBigInt64LE=defineBigIntMethod((function writeBigInt64LE(i,s=0){return wrtBigUInt64LE(this,i,s,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),Buffer.prototype.writeBigInt64BE=defineBigIntMethod((function writeBigInt64BE(i,s=0){return wrtBigUInt64BE(this,i,s,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),Buffer.prototype.writeFloatLE=function writeFloatLE(i,s,u){return writeFloat(this,i,s,!0,u)},Buffer.prototype.writeFloatBE=function writeFloatBE(i,s,u){return writeFloat(this,i,s,!1,u)},Buffer.prototype.writeDoubleLE=function writeDoubleLE(i,s,u){return writeDouble(this,i,s,!0,u)},Buffer.prototype.writeDoubleBE=function writeDoubleBE(i,s,u){return writeDouble(this,i,s,!1,u)},Buffer.prototype.copy=function copy(i,s,u,m){if(!Buffer.isBuffer(i))throw new TypeError("argument should be a Buffer");if(u||(u=0),m||0===m||(m=this.length),s>=i.length&&(s=i.length),s||(s=0),m>0&&m=this.length)throw new RangeError("Index out of range");if(m<0)throw new RangeError("sourceEnd out of bounds");m>this.length&&(m=this.length),i.length-s>>=0,u=void 0===u?this.length:u>>>0,i||(i=0),"number"==typeof i)for(v=s;v=m+4;u-=3)s=`_${i.slice(u-3,u)}${s}`;return`${i.slice(0,u)}${s}`}function checkIntBI(i,s,u,m,v,_){if(i>u||i3?0===s||s===BigInt(0)?`>= 0${m} and < 2${m} ** ${8*(_+1)}${m}`:`>= -(2${m} ** ${8*(_+1)-1}${m}) and < 2 ** ${8*(_+1)-1}${m}`:`>= ${s}${m} and <= ${u}${m}`,new $.ERR_OUT_OF_RANGE("value",v,i)}!function checkBounds(i,s,u){validateNumber(s,"offset"),void 0!==i[s]&&void 0!==i[s+u]||boundsError(s,i.length-(u+1))}(m,v,_)}function validateNumber(i,s){if("number"!=typeof i)throw new $.ERR_INVALID_ARG_TYPE(s,"number",i)}function boundsError(i,s,u){if(Math.floor(i)!==i)throw validateNumber(i,u),new $.ERR_OUT_OF_RANGE(u||"offset","an integer",i);if(s<0)throw new $.ERR_BUFFER_OUT_OF_BOUNDS;throw new $.ERR_OUT_OF_RANGE(u||"offset",`>= ${u?1:0} and <= ${s}`,i)}E("ERR_BUFFER_OUT_OF_BOUNDS",(function(i){return i?`${i} is outside of buffer bounds`:"Attempt to access memory outside buffer bounds"}),RangeError),E("ERR_INVALID_ARG_TYPE",(function(i,s){return`The "${i}" argument must be of type number. Received type ${typeof s}`}),TypeError),E("ERR_OUT_OF_RANGE",(function(i,s,u){let m=`The value of "${i}" is out of range.`,v=u;return Number.isInteger(u)&&Math.abs(u)>2**32?v=addNumericalSeparator(String(u)):"bigint"==typeof u&&(v=String(u),(u>BigInt(2)**BigInt(32)||u<-(BigInt(2)**BigInt(32)))&&(v=addNumericalSeparator(v)),v+="n"),m+=` It must be ${s}. Received ${v}`,m}),RangeError);const W=/[^+/0-9A-Za-z-_]/g;function utf8ToBytes(i,s){let u;s=s||1/0;const m=i.length;let v=null;const _=[];for(let j=0;j55295&&u<57344){if(!v){if(u>56319){(s-=3)>-1&&_.push(239,191,189);continue}if(j+1===m){(s-=3)>-1&&_.push(239,191,189);continue}v=u;continue}if(u<56320){(s-=3)>-1&&_.push(239,191,189),v=u;continue}u=65536+(v-55296<<10|u-56320)}else v&&(s-=3)>-1&&_.push(239,191,189);if(v=null,u<128){if((s-=1)<0)break;_.push(u)}else if(u<2048){if((s-=2)<0)break;_.push(u>>6|192,63&u|128)}else if(u<65536){if((s-=3)<0)break;_.push(u>>12|224,u>>6&63|128,63&u|128)}else{if(!(u<1114112))throw new Error("Invalid code point");if((s-=4)<0)break;_.push(u>>18|240,u>>12&63|128,u>>6&63|128,63&u|128)}}return _}function base64ToBytes(i){return m.toByteArray(function base64clean(i){if((i=(i=i.split("=")[0]).trim().replace(W,"")).length<2)return"";for(;i.length%4!=0;)i+="=";return i}(i))}function blitBuffer(i,s,u,m){let v;for(v=0;v=s.length||v>=i.length);++v)s[v+u]=i[v];return v}function isInstance(i,s){return i instanceof s||null!=i&&null!=i.constructor&&null!=i.constructor.name&&i.constructor.name===s.name}function numberIsNaN(i){return i!=i}const X=function(){const i="0123456789abcdef",s=new Array(256);for(let u=0;u<16;++u){const m=16*u;for(let v=0;v<16;++v)s[m+v]=i[u]+i[v]}return s}();function defineBigIntMethod(i){return"undefined"==typeof BigInt?BufferBigIntNotDefined:i}function BufferBigIntNotDefined(){throw new Error("BigInt not supported")}},21924:(i,s,u)=>{"use strict";var m=u(40210),v=u(55559),_=v(m("String.prototype.indexOf"));i.exports=function callBoundIntrinsic(i,s){var u=m(i,!!s);return"function"==typeof u&&_(i,".prototype.")>-1?v(u):u}},55559:(i,s,u)=>{"use strict";var m=u(58612),v=u(40210),_=v("%Function.prototype.apply%"),j=v("%Function.prototype.call%"),M=v("%Reflect.apply%",!0)||m.call(j,_),$=v("%Object.getOwnPropertyDescriptor%",!0),W=v("%Object.defineProperty%",!0),X=v("%Math.max%");if(W)try{W({},"a",{value:1})}catch(i){W=null}i.exports=function callBind(i){var s=M(m,j,arguments);$&&W&&($(s,"length").configurable&&W(s,"length",{value:1+X(0,i.length-(arguments.length-1))}));return s};var Y=function applyBind(){return M(m,_,arguments)};W?W(i.exports,"apply",{value:Y}):i.exports.apply=Y},94184:(i,s)=>{var u;!function(){"use strict";var m={}.hasOwnProperty;function classNames(){for(var i=[],s=0;s{"use strict";s.parse=function parse(i,s){if("string"!=typeof i)throw new TypeError("argument str must be a string");var u={},m=(s||{}).decode||decode,v=0;for(;v{"use strict";var m=u(11742),v={"text/plain":"Text","text/html":"Url",default:"Text"};i.exports=function copy(i,s){var u,_,j,M,$,W,X=!1;s||(s={}),u=s.debug||!1;try{if(j=m(),M=document.createRange(),$=document.getSelection(),(W=document.createElement("span")).textContent=i,W.ariaHidden="true",W.style.all="unset",W.style.position="fixed",W.style.top=0,W.style.clip="rect(0, 0, 0, 0)",W.style.whiteSpace="pre",W.style.webkitUserSelect="text",W.style.MozUserSelect="text",W.style.msUserSelect="text",W.style.userSelect="text",W.addEventListener("copy",(function(m){if(m.stopPropagation(),s.format)if(m.preventDefault(),void 0===m.clipboardData){u&&console.warn("unable to use e.clipboardData"),u&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var _=v[s.format]||v.default;window.clipboardData.setData(_,i)}else m.clipboardData.clearData(),m.clipboardData.setData(s.format,i);s.onCopy&&(m.preventDefault(),s.onCopy(m.clipboardData))})),document.body.appendChild(W),M.selectNodeContents(W),$.addRange(M),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");X=!0}catch(m){u&&console.error("unable to copy using execCommand: ",m),u&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(s.format||"text",i),s.onCopy&&s.onCopy(window.clipboardData),X=!0}catch(m){u&&console.error("unable to copy using clipboardData: ",m),u&&console.error("falling back to prompt"),_=function format(i){var s=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return i.replace(/#{\s*key\s*}/g,s)}("message"in s?s.message:"Copy to clipboard: #{key}, Enter"),window.prompt(_,i)}}finally{$&&("function"==typeof $.removeRange?$.removeRange(M):$.removeAllRanges()),W&&document.body.removeChild(W),j()}return X}},44101:(i,s,u)=>{var m=u(18957);i.exports=m},90093:(i,s,u)=>{var m=u(28196);i.exports=m},65362:(i,s,u)=>{var m=u(63383);i.exports=m},50415:(i,s,u)=>{u(61181),u(47627),u(24415),u(66274),u(77971);var m=u(54058);i.exports=m.AggregateError},27700:(i,s,u)=>{u(73381);var m=u(35703);i.exports=m("Function").bind},16246:(i,s,u)=>{var m=u(7046),v=u(27700),_=Function.prototype;i.exports=function(i){var s=i.bind;return i===_||m(_,i)&&s===_.bind?v:s}},45999:(i,s,u)=>{u(49221);var m=u(54058);i.exports=m.Object.assign},16121:(i,s,u)=>{i.exports=u(38644)},14122:(i,s,u)=>{i.exports=u(89097)},60269:(i,s,u)=>{i.exports=u(76936)},38644:(i,s,u)=>{u(89731);var m=u(44101);i.exports=m},89097:(i,s,u)=>{var m=u(90093);i.exports=m},76936:(i,s,u)=>{var m=u(65362);i.exports=m},24883:(i,s,u)=>{var m=u(57475),v=u(69826),_=TypeError;i.exports=function(i){if(m(i))return i;throw _(v(i)+" is not a function")}},11851:(i,s,u)=>{var m=u(57475),v=String,_=TypeError;i.exports=function(i){if("object"==typeof i||m(i))return i;throw _("Can't set "+v(i)+" as a prototype")}},18479:i=>{i.exports=function(){}},96059:(i,s,u)=>{var m=u(10941),v=String,_=TypeError;i.exports=function(i){if(m(i))return i;throw _(v(i)+" is not an object")}},31692:(i,s,u)=>{var m=u(74529),v=u(59413),_=u(10623),createMethod=function(i){return function(s,u,j){var M,$=m(s),W=_($),X=v(j,W);if(i&&u!=u){for(;W>X;)if((M=$[X++])!=M)return!0}else for(;W>X;X++)if((i||X in $)&&$[X]===u)return i||X||0;return!i&&-1}};i.exports={includes:createMethod(!0),indexOf:createMethod(!1)}},93765:(i,s,u)=>{var m=u(95329);i.exports=m([].slice)},82532:(i,s,u)=>{var m=u(95329),v=m({}.toString),_=m("".slice);i.exports=function(i){return _(v(i),8,-1)}},9697:(i,s,u)=>{var m=u(22885),v=u(57475),_=u(82532),j=u(99813)("toStringTag"),M=Object,$="Arguments"==_(function(){return arguments}());i.exports=m?_:function(i){var s,u,m;return void 0===i?"Undefined":null===i?"Null":"string"==typeof(u=function(i,s){try{return i[s]}catch(i){}}(s=M(i),j))?u:$?_(s):"Object"==(m=_(s))&&v(s.callee)?"Arguments":m}},23489:(i,s,u)=>{var m=u(90953),v=u(31136),_=u(49677),j=u(65988);i.exports=function(i,s,u){for(var M=v(s),$=j.f,W=_.f,X=0;X{var m=u(95981);i.exports=!m((function(){function F(){}return F.prototype.constructor=null,Object.getPrototypeOf(new F)!==F.prototype}))},23538:i=>{i.exports=function(i,s){return{value:i,done:s}}},32029:(i,s,u)=>{var m=u(55746),v=u(65988),_=u(31887);i.exports=m?function(i,s,u){return v.f(i,s,_(1,u))}:function(i,s,u){return i[s]=u,i}},31887:i=>{i.exports=function(i,s){return{enumerable:!(1&i),configurable:!(2&i),writable:!(4&i),value:s}}},95929:(i,s,u)=>{var m=u(32029);i.exports=function(i,s,u,v){return v&&v.enumerable?i[s]=u:m(i,s,u),i}},75609:(i,s,u)=>{var m=u(21899),v=Object.defineProperty;i.exports=function(i,s){try{v(m,i,{value:s,configurable:!0,writable:!0})}catch(u){m[i]=s}return s}},55746:(i,s,u)=>{var m=u(95981);i.exports=!m((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},76616:i=>{var s="object"==typeof document&&document.all,u=void 0===s&&void 0!==s;i.exports={all:s,IS_HTMLDDA:u}},61333:(i,s,u)=>{var m=u(21899),v=u(10941),_=m.document,j=v(_)&&v(_.createElement);i.exports=function(i){return j?_.createElement(i):{}}},63281:i=>{i.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},2861:i=>{i.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},53385:(i,s,u)=>{var m,v,_=u(21899),j=u(2861),M=_.process,$=_.Deno,W=M&&M.versions||$&&$.version,X=W&&W.v8;X&&(v=(m=X.split("."))[0]>0&&m[0]<4?1:+(m[0]+m[1])),!v&&j&&(!(m=j.match(/Edge\/(\d+)/))||m[1]>=74)&&(m=j.match(/Chrome\/(\d+)/))&&(v=+m[1]),i.exports=v},35703:(i,s,u)=>{var m=u(54058);i.exports=function(i){return m[i+"Prototype"]}},56759:i=>{i.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},53995:(i,s,u)=>{var m=u(95329),v=Error,_=m("".replace),j=String(v("zxcasd").stack),M=/\n\s*at [^:]*:[^\n]*/,$=M.test(j);i.exports=function(i,s){if($&&"string"==typeof i&&!v.prepareStackTrace)for(;s--;)i=_(i,M,"");return i}},79585:(i,s,u)=>{var m=u(32029),v=u(53995),_=u(18780),j=Error.captureStackTrace;i.exports=function(i,s,u,M){_&&(j?j(i,s):m(i,"stack",v(u,M)))}},18780:(i,s,u)=>{var m=u(95981),v=u(31887);i.exports=!m((function(){var i=Error("a");return!("stack"in i)||(Object.defineProperty(i,"stack",v(1,7)),7!==i.stack)}))},76887:(i,s,u)=>{"use strict";var m=u(21899),v=u(79730),_=u(97484),j=u(57475),M=u(49677).f,$=u(37252),W=u(54058),X=u(86843),Y=u(32029),Z=u(90953),wrapConstructor=function(i){var Wrapper=function(s,u,m){if(this instanceof Wrapper){switch(arguments.length){case 0:return new i;case 1:return new i(s);case 2:return new i(s,u)}return new i(s,u,m)}return v(i,this,arguments)};return Wrapper.prototype=i.prototype,Wrapper};i.exports=function(i,s){var u,v,ee,ae,ie,le,ce,pe,de,fe=i.target,ye=i.global,be=i.stat,_e=i.proto,we=ye?m:be?m[fe]:(m[fe]||{}).prototype,Se=ye?W:W[fe]||Y(W,fe,{})[fe],xe=Se.prototype;for(ae in s)v=!(u=$(ye?ae:fe+(be?".":"#")+ae,i.forced))&&we&&Z(we,ae),le=Se[ae],v&&(ce=i.dontCallGetSet?(de=M(we,ae))&&de.value:we[ae]),ie=v&&ce?ce:s[ae],v&&typeof le==typeof ie||(pe=i.bind&&v?X(ie,m):i.wrap&&v?wrapConstructor(ie):_e&&j(ie)?_(ie):ie,(i.sham||ie&&ie.sham||le&&le.sham)&&Y(pe,"sham",!0),Y(Se,ae,pe),_e&&(Z(W,ee=fe+"Prototype")||Y(W,ee,{}),Y(W[ee],ae,ie),i.real&&xe&&(u||!xe[ae])&&Y(xe,ae,ie)))}},95981:i=>{i.exports=function(i){try{return!!i()}catch(i){return!0}}},79730:(i,s,u)=>{var m=u(18285),v=Function.prototype,_=v.apply,j=v.call;i.exports="object"==typeof Reflect&&Reflect.apply||(m?j.bind(_):function(){return j.apply(_,arguments)})},86843:(i,s,u)=>{var m=u(97484),v=u(24883),_=u(18285),j=m(m.bind);i.exports=function(i,s){return v(i),void 0===s?i:_?j(i,s):function(){return i.apply(s,arguments)}}},18285:(i,s,u)=>{var m=u(95981);i.exports=!m((function(){var i=function(){}.bind();return"function"!=typeof i||i.hasOwnProperty("prototype")}))},98308:(i,s,u)=>{"use strict";var m=u(95329),v=u(24883),_=u(10941),j=u(90953),M=u(93765),$=u(18285),W=Function,X=m([].concat),Y=m([].join),Z={};i.exports=$?W.bind:function bind(i){var s=v(this),u=s.prototype,m=M(arguments,1),$=function bound(){var u=X(m,M(arguments));return this instanceof $?function(i,s,u){if(!j(Z,s)){for(var m=[],v=0;v{var m=u(18285),v=Function.prototype.call;i.exports=m?v.bind(v):function(){return v.apply(v,arguments)}},79417:(i,s,u)=>{var m=u(55746),v=u(90953),_=Function.prototype,j=m&&Object.getOwnPropertyDescriptor,M=v(_,"name"),$=M&&"something"===function something(){}.name,W=M&&(!m||m&&j(_,"name").configurable);i.exports={EXISTS:M,PROPER:$,CONFIGURABLE:W}},45526:(i,s,u)=>{var m=u(95329),v=u(24883);i.exports=function(i,s,u){try{return m(v(Object.getOwnPropertyDescriptor(i,s)[u]))}catch(i){}}},97484:(i,s,u)=>{var m=u(82532),v=u(95329);i.exports=function(i){if("Function"===m(i))return v(i)}},95329:(i,s,u)=>{var m=u(18285),v=Function.prototype,_=v.call,j=m&&v.bind.bind(_,_);i.exports=m?j:function(i){return function(){return _.apply(i,arguments)}}},626:(i,s,u)=>{var m=u(54058),v=u(21899),_=u(57475),aFunction=function(i){return _(i)?i:void 0};i.exports=function(i,s){return arguments.length<2?aFunction(m[i])||aFunction(v[i]):m[i]&&m[i][s]||v[i]&&v[i][s]}},22902:(i,s,u)=>{var m=u(9697),v=u(14229),_=u(82119),j=u(12077),M=u(99813)("iterator");i.exports=function(i){if(!_(i))return v(i,M)||v(i,"@@iterator")||j[m(i)]}},53476:(i,s,u)=>{var m=u(78834),v=u(24883),_=u(96059),j=u(69826),M=u(22902),$=TypeError;i.exports=function(i,s){var u=arguments.length<2?M(i):s;if(v(u))return _(m(u,i));throw $(j(i)+" is not iterable")}},14229:(i,s,u)=>{var m=u(24883),v=u(82119);i.exports=function(i,s){var u=i[s];return v(u)?void 0:m(u)}},21899:function(i,s,u){var check=function(i){return i&&i.Math==Math&&i};i.exports=check("object"==typeof globalThis&&globalThis)||check("object"==typeof window&&window)||check("object"==typeof self&&self)||check("object"==typeof u.g&&u.g)||function(){return this}()||this||Function("return this")()},90953:(i,s,u)=>{var m=u(95329),v=u(89678),_=m({}.hasOwnProperty);i.exports=Object.hasOwn||function hasOwn(i,s){return _(v(i),s)}},27748:i=>{i.exports={}},15463:(i,s,u)=>{var m=u(626);i.exports=m("document","documentElement")},2840:(i,s,u)=>{var m=u(55746),v=u(95981),_=u(61333);i.exports=!m&&!v((function(){return 7!=Object.defineProperty(_("div"),"a",{get:function(){return 7}}).a}))},37026:(i,s,u)=>{var m=u(95329),v=u(95981),_=u(82532),j=Object,M=m("".split);i.exports=v((function(){return!j("z").propertyIsEnumerable(0)}))?function(i){return"String"==_(i)?M(i,""):j(i)}:j},70926:(i,s,u)=>{var m=u(57475),v=u(10941),_=u(88929);i.exports=function(i,s,u){var j,M;return _&&m(j=s.constructor)&&j!==u&&v(M=j.prototype)&&M!==u.prototype&&_(i,M),i}},53794:(i,s,u)=>{var m=u(10941),v=u(32029);i.exports=function(i,s){m(s)&&"cause"in s&&v(i,"cause",s.cause)}},45402:(i,s,u)=>{var m,v,_,j=u(47093),M=u(21899),$=u(10941),W=u(32029),X=u(90953),Y=u(63030),Z=u(44262),ee=u(27748),ae="Object already initialized",ie=M.TypeError,le=M.WeakMap;if(j||Y.state){var ce=Y.state||(Y.state=new le);ce.get=ce.get,ce.has=ce.has,ce.set=ce.set,m=function(i,s){if(ce.has(i))throw ie(ae);return s.facade=i,ce.set(i,s),s},v=function(i){return ce.get(i)||{}},_=function(i){return ce.has(i)}}else{var pe=Z("state");ee[pe]=!0,m=function(i,s){if(X(i,pe))throw ie(ae);return s.facade=i,W(i,pe,s),s},v=function(i){return X(i,pe)?i[pe]:{}},_=function(i){return X(i,pe)}}i.exports={set:m,get:v,has:_,enforce:function(i){return _(i)?v(i):m(i,{})},getterFor:function(i){return function(s){var u;if(!$(s)||(u=v(s)).type!==i)throw ie("Incompatible receiver, "+i+" required");return u}}}},6782:(i,s,u)=>{var m=u(99813),v=u(12077),_=m("iterator"),j=Array.prototype;i.exports=function(i){return void 0!==i&&(v.Array===i||j[_]===i)}},57475:(i,s,u)=>{var m=u(76616),v=m.all;i.exports=m.IS_HTMLDDA?function(i){return"function"==typeof i||i===v}:function(i){return"function"==typeof i}},37252:(i,s,u)=>{var m=u(95981),v=u(57475),_=/#|\.prototype\./,isForced=function(i,s){var u=M[j(i)];return u==W||u!=$&&(v(s)?m(s):!!s)},j=isForced.normalize=function(i){return String(i).replace(_,".").toLowerCase()},M=isForced.data={},$=isForced.NATIVE="N",W=isForced.POLYFILL="P";i.exports=isForced},82119:i=>{i.exports=function(i){return null==i}},10941:(i,s,u)=>{var m=u(57475),v=u(76616),_=v.all;i.exports=v.IS_HTMLDDA?function(i){return"object"==typeof i?null!==i:m(i)||i===_}:function(i){return"object"==typeof i?null!==i:m(i)}},82529:i=>{i.exports=!0},56664:(i,s,u)=>{var m=u(626),v=u(57475),_=u(7046),j=u(32302),M=Object;i.exports=j?function(i){return"symbol"==typeof i}:function(i){var s=m("Symbol");return v(s)&&_(s.prototype,M(i))}},93091:(i,s,u)=>{var m=u(86843),v=u(78834),_=u(96059),j=u(69826),M=u(6782),$=u(10623),W=u(7046),X=u(53476),Y=u(22902),Z=u(7609),ee=TypeError,Result=function(i,s){this.stopped=i,this.result=s},ae=Result.prototype;i.exports=function(i,s,u){var ie,le,ce,pe,de,fe,ye,be=u&&u.that,_e=!(!u||!u.AS_ENTRIES),we=!(!u||!u.IS_RECORD),Se=!(!u||!u.IS_ITERATOR),xe=!(!u||!u.INTERRUPTED),Pe=m(s,be),stop=function(i){return ie&&Z(ie,"normal",i),new Result(!0,i)},callFn=function(i){return _e?(_(i),xe?Pe(i[0],i[1],stop):Pe(i[0],i[1])):xe?Pe(i,stop):Pe(i)};if(we)ie=i.iterator;else if(Se)ie=i;else{if(!(le=Y(i)))throw ee(j(i)+" is not iterable");if(M(le)){for(ce=0,pe=$(i);pe>ce;ce++)if((de=callFn(i[ce]))&&W(ae,de))return de;return new Result(!1)}ie=X(i,le)}for(fe=we?i.next:ie.next;!(ye=v(fe,ie)).done;){try{de=callFn(ye.value)}catch(i){Z(ie,"throw",i)}if("object"==typeof de&&de&&W(ae,de))return de}return new Result(!1)}},7609:(i,s,u)=>{var m=u(78834),v=u(96059),_=u(14229);i.exports=function(i,s,u){var j,M;v(i);try{if(!(j=_(i,"return"))){if("throw"===s)throw u;return u}j=m(j,i)}catch(i){M=!0,j=i}if("throw"===s)throw u;if(M)throw j;return v(j),u}},53847:(i,s,u)=>{"use strict";var m=u(35143).IteratorPrototype,v=u(29290),_=u(31887),j=u(90904),M=u(12077),returnThis=function(){return this};i.exports=function(i,s,u,$){var W=s+" Iterator";return i.prototype=v(m,{next:_(+!$,u)}),j(i,W,!1,!0),M[W]=returnThis,i}},75105:(i,s,u)=>{"use strict";var m=u(76887),v=u(78834),_=u(82529),j=u(79417),M=u(57475),$=u(53847),W=u(249),X=u(88929),Y=u(90904),Z=u(32029),ee=u(95929),ae=u(99813),ie=u(12077),le=u(35143),ce=j.PROPER,pe=j.CONFIGURABLE,de=le.IteratorPrototype,fe=le.BUGGY_SAFARI_ITERATORS,ye=ae("iterator"),be="keys",_e="values",we="entries",returnThis=function(){return this};i.exports=function(i,s,u,j,ae,le,Se){$(u,s,j);var xe,Pe,Ie,getIterationMethod=function(i){if(i===ae&&Ve)return Ve;if(!fe&&i in qe)return qe[i];switch(i){case be:return function keys(){return new u(this,i)};case _e:return function values(){return new u(this,i)};case we:return function entries(){return new u(this,i)}}return function(){return new u(this)}},Te=s+" Iterator",Re=!1,qe=i.prototype,ze=qe[ye]||qe["@@iterator"]||ae&&qe[ae],Ve=!fe&&ze||getIterationMethod(ae),We="Array"==s&&qe.entries||ze;if(We&&(xe=W(We.call(new i)))!==Object.prototype&&xe.next&&(_||W(xe)===de||(X?X(xe,de):M(xe[ye])||ee(xe,ye,returnThis)),Y(xe,Te,!0,!0),_&&(ie[Te]=returnThis)),ce&&ae==_e&&ze&&ze.name!==_e&&(!_&&pe?Z(qe,"name",_e):(Re=!0,Ve=function values(){return v(ze,this)})),ae)if(Pe={values:getIterationMethod(_e),keys:le?Ve:getIterationMethod(be),entries:getIterationMethod(we)},Se)for(Ie in Pe)(fe||Re||!(Ie in qe))&&ee(qe,Ie,Pe[Ie]);else m({target:s,proto:!0,forced:fe||Re},Pe);return _&&!Se||qe[ye]===Ve||ee(qe,ye,Ve,{name:ae}),ie[s]=Ve,Pe}},35143:(i,s,u)=>{"use strict";var m,v,_,j=u(95981),M=u(57475),$=u(10941),W=u(29290),X=u(249),Y=u(95929),Z=u(99813),ee=u(82529),ae=Z("iterator"),ie=!1;[].keys&&("next"in(_=[].keys())?(v=X(X(_)))!==Object.prototype&&(m=v):ie=!0),!$(m)||j((function(){var i={};return m[ae].call(i)!==i}))?m={}:ee&&(m=W(m)),M(m[ae])||Y(m,ae,(function(){return this})),i.exports={IteratorPrototype:m,BUGGY_SAFARI_ITERATORS:ie}},12077:i=>{i.exports={}},10623:(i,s,u)=>{var m=u(43057);i.exports=function(i){return m(i.length)}},35331:i=>{var s=Math.ceil,u=Math.floor;i.exports=Math.trunc||function trunc(i){var m=+i;return(m>0?u:s)(m)}},14649:(i,s,u)=>{var m=u(85803);i.exports=function(i,s){return void 0===i?arguments.length<2?"":s:m(i)}},24420:(i,s,u)=>{"use strict";var m=u(55746),v=u(95329),_=u(78834),j=u(95981),M=u(14771),$=u(87857),W=u(36760),X=u(89678),Y=u(37026),Z=Object.assign,ee=Object.defineProperty,ae=v([].concat);i.exports=!Z||j((function(){if(m&&1!==Z({b:1},Z(ee({},"a",{enumerable:!0,get:function(){ee(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var i={},s={},u=Symbol(),v="abcdefghijklmnopqrst";return i[u]=7,v.split("").forEach((function(i){s[i]=i})),7!=Z({},i)[u]||M(Z({},s)).join("")!=v}))?function assign(i,s){for(var u=X(i),v=arguments.length,j=1,Z=$.f,ee=W.f;v>j;)for(var ie,le=Y(arguments[j++]),ce=Z?ae(M(le),Z(le)):M(le),pe=ce.length,de=0;pe>de;)ie=ce[de++],m&&!_(ee,le,ie)||(u[ie]=le[ie]);return u}:Z},29290:(i,s,u)=>{var m,v=u(96059),_=u(59938),j=u(56759),M=u(27748),$=u(15463),W=u(61333),X=u(44262),Y="prototype",Z="script",ee=X("IE_PROTO"),EmptyConstructor=function(){},scriptTag=function(i){return"<"+Z+">"+i+""},NullProtoObjectViaActiveX=function(i){i.write(scriptTag("")),i.close();var s=i.parentWindow.Object;return i=null,s},NullProtoObject=function(){try{m=new ActiveXObject("htmlfile")}catch(i){}var i,s,u;NullProtoObject="undefined"!=typeof document?document.domain&&m?NullProtoObjectViaActiveX(m):(s=W("iframe"),u="java"+Z+":",s.style.display="none",$.appendChild(s),s.src=String(u),(i=s.contentWindow.document).open(),i.write(scriptTag("document.F=Object")),i.close(),i.F):NullProtoObjectViaActiveX(m);for(var v=j.length;v--;)delete NullProtoObject[Y][j[v]];return NullProtoObject()};M[ee]=!0,i.exports=Object.create||function create(i,s){var u;return null!==i?(EmptyConstructor[Y]=v(i),u=new EmptyConstructor,EmptyConstructor[Y]=null,u[ee]=i):u=NullProtoObject(),void 0===s?u:_.f(u,s)}},59938:(i,s,u)=>{var m=u(55746),v=u(83937),_=u(65988),j=u(96059),M=u(74529),$=u(14771);s.f=m&&!v?Object.defineProperties:function defineProperties(i,s){j(i);for(var u,m=M(s),v=$(s),W=v.length,X=0;W>X;)_.f(i,u=v[X++],m[u]);return i}},65988:(i,s,u)=>{var m=u(55746),v=u(2840),_=u(83937),j=u(96059),M=u(83894),$=TypeError,W=Object.defineProperty,X=Object.getOwnPropertyDescriptor,Y="enumerable",Z="configurable",ee="writable";s.f=m?_?function defineProperty(i,s,u){if(j(i),s=M(s),j(u),"function"==typeof i&&"prototype"===s&&"value"in u&&ee in u&&!u[ee]){var m=X(i,s);m&&m[ee]&&(i[s]=u.value,u={configurable:Z in u?u[Z]:m[Z],enumerable:Y in u?u[Y]:m[Y],writable:!1})}return W(i,s,u)}:W:function defineProperty(i,s,u){if(j(i),s=M(s),j(u),v)try{return W(i,s,u)}catch(i){}if("get"in u||"set"in u)throw $("Accessors not supported");return"value"in u&&(i[s]=u.value),i}},49677:(i,s,u)=>{var m=u(55746),v=u(78834),_=u(36760),j=u(31887),M=u(74529),$=u(83894),W=u(90953),X=u(2840),Y=Object.getOwnPropertyDescriptor;s.f=m?Y:function getOwnPropertyDescriptor(i,s){if(i=M(i),s=$(s),X)try{return Y(i,s)}catch(i){}if(W(i,s))return j(!v(_.f,i,s),i[s])}},10946:(i,s,u)=>{var m=u(55629),v=u(56759).concat("length","prototype");s.f=Object.getOwnPropertyNames||function getOwnPropertyNames(i){return m(i,v)}},87857:(i,s)=>{s.f=Object.getOwnPropertySymbols},249:(i,s,u)=>{var m=u(90953),v=u(57475),_=u(89678),j=u(44262),M=u(91310),$=j("IE_PROTO"),W=Object,X=W.prototype;i.exports=M?W.getPrototypeOf:function(i){var s=_(i);if(m(s,$))return s[$];var u=s.constructor;return v(u)&&s instanceof u?u.prototype:s instanceof W?X:null}},7046:(i,s,u)=>{var m=u(95329);i.exports=m({}.isPrototypeOf)},55629:(i,s,u)=>{var m=u(95329),v=u(90953),_=u(74529),j=u(31692).indexOf,M=u(27748),$=m([].push);i.exports=function(i,s){var u,m=_(i),W=0,X=[];for(u in m)!v(M,u)&&v(m,u)&&$(X,u);for(;s.length>W;)v(m,u=s[W++])&&(~j(X,u)||$(X,u));return X}},14771:(i,s,u)=>{var m=u(55629),v=u(56759);i.exports=Object.keys||function keys(i){return m(i,v)}},36760:(i,s)=>{"use strict";var u={}.propertyIsEnumerable,m=Object.getOwnPropertyDescriptor,v=m&&!u.call({1:2},1);s.f=v?function propertyIsEnumerable(i){var s=m(this,i);return!!s&&s.enumerable}:u},88929:(i,s,u)=>{var m=u(45526),v=u(96059),_=u(11851);i.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var i,s=!1,u={};try{(i=m(Object.prototype,"__proto__","set"))(u,[]),s=u instanceof Array}catch(i){}return function setPrototypeOf(u,m){return v(u),_(m),s?i(u,m):u.__proto__=m,u}}():void 0)},95623:(i,s,u)=>{"use strict";var m=u(22885),v=u(9697);i.exports=m?{}.toString:function toString(){return"[object "+v(this)+"]"}},39811:(i,s,u)=>{var m=u(78834),v=u(57475),_=u(10941),j=TypeError;i.exports=function(i,s){var u,M;if("string"===s&&v(u=i.toString)&&!_(M=m(u,i)))return M;if(v(u=i.valueOf)&&!_(M=m(u,i)))return M;if("string"!==s&&v(u=i.toString)&&!_(M=m(u,i)))return M;throw j("Can't convert object to primitive value")}},31136:(i,s,u)=>{var m=u(626),v=u(95329),_=u(10946),j=u(87857),M=u(96059),$=v([].concat);i.exports=m("Reflect","ownKeys")||function ownKeys(i){var s=_.f(M(i)),u=j.f;return u?$(s,u(i)):s}},54058:i=>{i.exports={}},9056:(i,s,u)=>{var m=u(65988).f;i.exports=function(i,s,u){u in i||m(i,u,{configurable:!0,get:function(){return s[u]},set:function(i){s[u]=i}})}},48219:(i,s,u)=>{var m=u(82119),v=TypeError;i.exports=function(i){if(m(i))throw v("Can't call method on "+i);return i}},90904:(i,s,u)=>{var m=u(22885),v=u(65988).f,_=u(32029),j=u(90953),M=u(95623),$=u(99813)("toStringTag");i.exports=function(i,s,u,W){if(i){var X=u?i:i.prototype;j(X,$)||v(X,$,{configurable:!0,value:s}),W&&!m&&_(X,"toString",M)}}},44262:(i,s,u)=>{var m=u(68726),v=u(99418),_=m("keys");i.exports=function(i){return _[i]||(_[i]=v(i))}},63030:(i,s,u)=>{var m=u(21899),v=u(75609),_="__core-js_shared__",j=m[_]||v(_,{});i.exports=j},68726:(i,s,u)=>{var m=u(82529),v=u(63030);(i.exports=function(i,s){return v[i]||(v[i]=void 0!==s?s:{})})("versions",[]).push({version:"3.31.1",mode:m?"pure":"global",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.31.1/LICENSE",source:"https://github.com/zloirock/core-js"})},64620:(i,s,u)=>{var m=u(95329),v=u(62435),_=u(85803),j=u(48219),M=m("".charAt),$=m("".charCodeAt),W=m("".slice),createMethod=function(i){return function(s,u){var m,X,Y=_(j(s)),Z=v(u),ee=Y.length;return Z<0||Z>=ee?i?"":void 0:(m=$(Y,Z))<55296||m>56319||Z+1===ee||(X=$(Y,Z+1))<56320||X>57343?i?M(Y,Z):m:i?W(Y,Z,Z+2):X-56320+(m-55296<<10)+65536}};i.exports={codeAt:createMethod(!1),charAt:createMethod(!0)}},63405:(i,s,u)=>{var m=u(53385),v=u(95981),_=u(21899).String;i.exports=!!Object.getOwnPropertySymbols&&!v((function(){var i=Symbol();return!_(i)||!(Object(i)instanceof Symbol)||!Symbol.sham&&m&&m<41}))},59413:(i,s,u)=>{var m=u(62435),v=Math.max,_=Math.min;i.exports=function(i,s){var u=m(i);return u<0?v(u+s,0):_(u,s)}},74529:(i,s,u)=>{var m=u(37026),v=u(48219);i.exports=function(i){return m(v(i))}},62435:(i,s,u)=>{var m=u(35331);i.exports=function(i){var s=+i;return s!=s||0===s?0:m(s)}},43057:(i,s,u)=>{var m=u(62435),v=Math.min;i.exports=function(i){return i>0?v(m(i),9007199254740991):0}},89678:(i,s,u)=>{var m=u(48219),v=Object;i.exports=function(i){return v(m(i))}},46935:(i,s,u)=>{var m=u(78834),v=u(10941),_=u(56664),j=u(14229),M=u(39811),$=u(99813),W=TypeError,X=$("toPrimitive");i.exports=function(i,s){if(!v(i)||_(i))return i;var u,$=j(i,X);if($){if(void 0===s&&(s="default"),u=m($,i,s),!v(u)||_(u))return u;throw W("Can't convert object to primitive value")}return void 0===s&&(s="number"),M(i,s)}},83894:(i,s,u)=>{var m=u(46935),v=u(56664);i.exports=function(i){var s=m(i,"string");return v(s)?s:s+""}},22885:(i,s,u)=>{var m={};m[u(99813)("toStringTag")]="z",i.exports="[object z]"===String(m)},85803:(i,s,u)=>{var m=u(9697),v=String;i.exports=function(i){if("Symbol"===m(i))throw TypeError("Cannot convert a Symbol value to a string");return v(i)}},69826:i=>{var s=String;i.exports=function(i){try{return s(i)}catch(i){return"Object"}}},99418:(i,s,u)=>{var m=u(95329),v=0,_=Math.random(),j=m(1..toString);i.exports=function(i){return"Symbol("+(void 0===i?"":i)+")_"+j(++v+_,36)}},32302:(i,s,u)=>{var m=u(63405);i.exports=m&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},83937:(i,s,u)=>{var m=u(55746),v=u(95981);i.exports=m&&v((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},47093:(i,s,u)=>{var m=u(21899),v=u(57475),_=m.WeakMap;i.exports=v(_)&&/native code/.test(String(_))},99813:(i,s,u)=>{var m=u(21899),v=u(68726),_=u(90953),j=u(99418),M=u(63405),$=u(32302),W=m.Symbol,X=v("wks"),Y=$?W.for||W:W&&W.withoutSetter||j;i.exports=function(i){return _(X,i)||(X[i]=M&&_(W,i)?W[i]:Y("Symbol."+i)),X[i]}},62864:(i,s,u)=>{"use strict";var m=u(626),v=u(90953),_=u(32029),j=u(7046),M=u(88929),$=u(23489),W=u(9056),X=u(70926),Y=u(14649),Z=u(53794),ee=u(79585),ae=u(55746),ie=u(82529);i.exports=function(i,s,u,le){var ce="stackTraceLimit",pe=le?2:1,de=i.split("."),fe=de[de.length-1],ye=m.apply(null,de);if(ye){var be=ye.prototype;if(!ie&&v(be,"cause")&&delete be.cause,!u)return ye;var _e=m("Error"),we=s((function(i,s){var u=Y(le?s:i,void 0),m=le?new ye(i):new ye;return void 0!==u&&_(m,"message",u),ee(m,we,m.stack,2),this&&j(be,this)&&X(m,this,we),arguments.length>pe&&Z(m,arguments[pe]),m}));if(we.prototype=be,"Error"!==fe?M?M(we,_e):$(we,_e,{name:!0}):ae&&ce in ye&&(W(we,ye,ce),W(we,ye,"prepareStackTrace")),$(we,ye),!ie)try{be.name!==fe&&_(be,"name",fe),be.constructor=we}catch(i){}return we}}},24415:(i,s,u)=>{var m=u(76887),v=u(626),_=u(79730),j=u(95981),M=u(62864),$="AggregateError",W=v($),X=!j((function(){return 1!==W([1]).errors[0]}))&&j((function(){return 7!==W([1],$,{cause:7}).cause}));m({global:!0,constructor:!0,arity:2,forced:X},{AggregateError:M($,(function(i){return function AggregateError(s,u){return _(i,this,arguments)}}),X,!0)})},49812:(i,s,u)=>{"use strict";var m=u(76887),v=u(7046),_=u(249),j=u(88929),M=u(23489),$=u(29290),W=u(32029),X=u(31887),Y=u(53794),Z=u(79585),ee=u(93091),ae=u(14649),ie=u(99813)("toStringTag"),le=Error,ce=[].push,pe=function AggregateError(i,s){var u,m=v(de,this);j?u=j(le(),m?_(this):de):(u=m?this:$(de),W(u,ie,"Error")),void 0!==s&&W(u,"message",ae(s)),Z(u,pe,u.stack,1),arguments.length>2&&Y(u,arguments[2]);var M=[];return ee(i,ce,{that:M}),W(u,"errors",M),u};j?j(pe,le):M(pe,le,{name:!0});var de=pe.prototype=$(le.prototype,{constructor:X(1,pe),message:X(1,""),name:X(1,"AggregateError")});m({global:!0,constructor:!0,arity:2},{AggregateError:pe})},47627:(i,s,u)=>{u(49812)},66274:(i,s,u)=>{"use strict";var m=u(74529),v=u(18479),_=u(12077),j=u(45402),M=u(65988).f,$=u(75105),W=u(23538),X=u(82529),Y=u(55746),Z="Array Iterator",ee=j.set,ae=j.getterFor(Z);i.exports=$(Array,"Array",(function(i,s){ee(this,{type:Z,target:m(i),index:0,kind:s})}),(function(){var i=ae(this),s=i.target,u=i.kind,m=i.index++;return!s||m>=s.length?(i.target=void 0,W(void 0,!0)):W("keys"==u?m:"values"==u?s[m]:[m,s[m]],!1)}),"values");var ie=_.Arguments=_.Array;if(v("keys"),v("values"),v("entries"),!X&&Y&&"values"!==ie.name)try{M(ie,"name",{value:"values"})}catch(i){}},61181:(i,s,u)=>{var m=u(76887),v=u(21899),_=u(79730),j=u(62864),M="WebAssembly",$=v[M],W=7!==Error("e",{cause:7}).cause,exportGlobalErrorCauseWrapper=function(i,s){var u={};u[i]=j(i,s,W),m({global:!0,constructor:!0,arity:1,forced:W},u)},exportWebAssemblyErrorCauseWrapper=function(i,s){if($&&$[i]){var u={};u[i]=j(M+"."+i,s,W),m({target:M,stat:!0,constructor:!0,arity:1,forced:W},u)}};exportGlobalErrorCauseWrapper("Error",(function(i){return function Error(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("EvalError",(function(i){return function EvalError(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("RangeError",(function(i){return function RangeError(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("ReferenceError",(function(i){return function ReferenceError(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("SyntaxError",(function(i){return function SyntaxError(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("TypeError",(function(i){return function TypeError(s){return _(i,this,arguments)}})),exportGlobalErrorCauseWrapper("URIError",(function(i){return function URIError(s){return _(i,this,arguments)}})),exportWebAssemblyErrorCauseWrapper("CompileError",(function(i){return function CompileError(s){return _(i,this,arguments)}})),exportWebAssemblyErrorCauseWrapper("LinkError",(function(i){return function LinkError(s){return _(i,this,arguments)}})),exportWebAssemblyErrorCauseWrapper("RuntimeError",(function(i){return function RuntimeError(s){return _(i,this,arguments)}}))},73381:(i,s,u)=>{var m=u(76887),v=u(98308);m({target:"Function",proto:!0,forced:Function.bind!==v},{bind:v})},49221:(i,s,u)=>{var m=u(76887),v=u(24420);m({target:"Object",stat:!0,arity:2,forced:Object.assign!==v},{assign:v})},77971:(i,s,u)=>{"use strict";var m=u(64620).charAt,v=u(85803),_=u(45402),j=u(75105),M=u(23538),$="String Iterator",W=_.set,X=_.getterFor($);j(String,"String",(function(i){W(this,{type:$,string:v(i),index:0})}),(function next(){var i,s=X(this),u=s.string,v=s.index;return v>=u.length?M(void 0,!0):(i=m(u,v),s.index+=i.length,M(i,!1))}))},89731:(i,s,u)=>{u(47627)},7634:(i,s,u)=>{u(66274);var m=u(63281),v=u(21899),_=u(9697),j=u(32029),M=u(12077),$=u(99813)("toStringTag");for(var W in m){var X=v[W],Y=X&&X.prototype;Y&&_(Y)!==$&&j(Y,$,W),M[W]=M.Array}},18957:(i,s,u)=>{u(89731);var m=u(50415);u(7634),i.exports=m},28196:(i,s,u)=>{var m=u(16246);i.exports=m},63383:(i,s,u)=>{var m=u(45999);i.exports=m},8269:function(i,s,u){var m;m=void 0!==u.g?u.g:this,i.exports=function(i){if(i.CSS&&i.CSS.escape)return i.CSS.escape;var cssEscape=function(i){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var s,u=String(i),m=u.length,v=-1,_="",j=u.charCodeAt(0);++v=1&&s<=31||127==s||0==v&&s>=48&&s<=57||1==v&&s>=48&&s<=57&&45==j?"\\"+s.toString(16)+" ":0==v&&1==m&&45==s||!(s>=128||45==s||95==s||s>=48&&s<=57||s>=65&&s<=90||s>=97&&s<=122)?"\\"+u.charAt(v):u.charAt(v):_+="�";return _};return i.CSS||(i.CSS={}),i.CSS.escape=cssEscape,cssEscape}(m)},27698:(i,s,u)=>{"use strict";var m=u(48764).Buffer;function isSpecificValue(i){return i instanceof m||i instanceof Date||i instanceof RegExp}function cloneSpecificValue(i){if(i instanceof m){var s=m.alloc?m.alloc(i.length):new m(i.length);return i.copy(s),s}if(i instanceof Date)return new Date(i.getTime());if(i instanceof RegExp)return new RegExp(i);throw new Error("Unexpected situation")}function deepCloneArray(i){var s=[];return i.forEach((function(i,u){"object"==typeof i&&null!==i?Array.isArray(i)?s[u]=deepCloneArray(i):isSpecificValue(i)?s[u]=cloneSpecificValue(i):s[u]=v({},i):s[u]=i})),s}function safeGetProperty(i,s){return"__proto__"===s?void 0:i[s]}var v=i.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var i,s,u=arguments[0];return Array.prototype.slice.call(arguments,1).forEach((function(m){"object"!=typeof m||null===m||Array.isArray(m)||Object.keys(m).forEach((function(_){return s=safeGetProperty(u,_),(i=safeGetProperty(m,_))===u?void 0:"object"!=typeof i||null===i?void(u[_]=i):Array.isArray(i)?void(u[_]=deepCloneArray(i)):isSpecificValue(i)?void(u[_]=cloneSpecificValue(i)):"object"!=typeof s||null===s||Array.isArray(s)?void(u[_]=v({},i)):void(u[_]=v(s,i))}))})),u}},9996:i=>{"use strict";var s=function isMergeableObject(i){return function isNonNullObject(i){return!!i&&"object"==typeof i}(i)&&!function isSpecial(i){var s=Object.prototype.toString.call(i);return"[object RegExp]"===s||"[object Date]"===s||function isReactElement(i){return i.$$typeof===u}(i)}(i)};var u="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function cloneUnlessOtherwiseSpecified(i,s){return!1!==s.clone&&s.isMergeableObject(i)?deepmerge(function emptyTarget(i){return Array.isArray(i)?[]:{}}(i),i,s):i}function defaultArrayMerge(i,s,u){return i.concat(s).map((function(i){return cloneUnlessOtherwiseSpecified(i,u)}))}function getKeys(i){return Object.keys(i).concat(function getEnumerableOwnPropertySymbols(i){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(i).filter((function(s){return Object.propertyIsEnumerable.call(i,s)})):[]}(i))}function propertyIsOnObject(i,s){try{return s in i}catch(i){return!1}}function mergeObject(i,s,u){var m={};return u.isMergeableObject(i)&&getKeys(i).forEach((function(s){m[s]=cloneUnlessOtherwiseSpecified(i[s],u)})),getKeys(s).forEach((function(v){(function propertyIsUnsafe(i,s){return propertyIsOnObject(i,s)&&!(Object.hasOwnProperty.call(i,s)&&Object.propertyIsEnumerable.call(i,s))})(i,v)||(propertyIsOnObject(i,v)&&u.isMergeableObject(s[v])?m[v]=function getMergeFunction(i,s){if(!s.customMerge)return deepmerge;var u=s.customMerge(i);return"function"==typeof u?u:deepmerge}(v,u)(i[v],s[v],u):m[v]=cloneUnlessOtherwiseSpecified(s[v],u))})),m}function deepmerge(i,u,m){(m=m||{}).arrayMerge=m.arrayMerge||defaultArrayMerge,m.isMergeableObject=m.isMergeableObject||s,m.cloneUnlessOtherwiseSpecified=cloneUnlessOtherwiseSpecified;var v=Array.isArray(u);return v===Array.isArray(i)?v?m.arrayMerge(i,u,m):mergeObject(i,u,m):cloneUnlessOtherwiseSpecified(u,m)}deepmerge.all=function deepmergeAll(i,s){if(!Array.isArray(i))throw new Error("first argument should be an array");return i.reduce((function(i,u){return deepmerge(i,u,s)}),{})};var m=deepmerge;i.exports=m},27856:function(i){i.exports=function(){"use strict";const{entries:i,setPrototypeOf:s,isFrozen:u,getPrototypeOf:m,getOwnPropertyDescriptor:v}=Object;let{freeze:_,seal:j,create:M}=Object,{apply:$,construct:W}="undefined"!=typeof Reflect&&Reflect;$||($=function apply(i,s,u){return i.apply(s,u)}),_||(_=function freeze(i){return i}),j||(j=function seal(i){return i}),W||(W=function construct(i,s){return new i(...s)});const X=unapply(Array.prototype.forEach),Y=unapply(Array.prototype.pop),Z=unapply(Array.prototype.push),ee=unapply(String.prototype.toLowerCase),ae=unapply(String.prototype.toString),ie=unapply(String.prototype.match),le=unapply(String.prototype.replace),ce=unapply(String.prototype.indexOf),pe=unapply(String.prototype.trim),de=unapply(RegExp.prototype.test),fe=unconstruct(TypeError);function unapply(i){return function(s){for(var u=arguments.length,m=new Array(u>1?u-1:0),v=1;v/gm),We=j(/\${[\w\W]*}/gm),He=j(/^data-[\-\w.\u00B7-\uFFFF]/),Xe=j(/^aria-[\-\w]+$/),Ye=j(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Qe=j(/^(?:\w+script|data):/i),et=j(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),tt=j(/^html$/i);var rt=Object.freeze({__proto__:null,MUSTACHE_EXPR:ze,ERB_EXPR:Ve,TMPLIT_EXPR:We,DATA_ATTR:He,ARIA_ATTR:Xe,IS_ALLOWED_URI:Ye,IS_SCRIPT_OR_DATA:Qe,ATTR_WHITESPACE:et,DOCTYPE_NAME:tt});const getGlobal=()=>"undefined"==typeof window?null:window,nt=function _createTrustedTypesPolicy(i,s){if("object"!=typeof i||"function"!=typeof i.createPolicy)return null;let u=null;const m="data-tt-policy-suffix";s&&s.hasAttribute(m)&&(u=s.getAttribute(m));const v="dompurify"+(u?"#"+u:"");try{return i.createPolicy(v,{createHTML:i=>i,createScriptURL:i=>i})}catch(i){return console.warn("TrustedTypes policy "+v+" could not be created."),null}};function createDOMPurify(){let s=arguments.length>0&&void 0!==arguments[0]?arguments[0]:getGlobal();const DOMPurify=i=>createDOMPurify(i);if(DOMPurify.version="3.0.5",DOMPurify.removed=[],!s||!s.document||9!==s.document.nodeType)return DOMPurify.isSupported=!1,DOMPurify;const u=s.document,m=u.currentScript;let{document:v}=s;const{DocumentFragment:j,HTMLTemplateElement:M,Node:$,Element:W,NodeFilter:ze,NamedNodeMap:Ve=s.NamedNodeMap||s.MozNamedAttrMap,HTMLFormElement:We,DOMParser:He,trustedTypes:Xe}=s,Qe=W.prototype,et=lookupGetter(Qe,"cloneNode"),ot=lookupGetter(Qe,"nextSibling"),at=lookupGetter(Qe,"childNodes"),it=lookupGetter(Qe,"parentNode");if("function"==typeof M){const i=v.createElement("template");i.content&&i.content.ownerDocument&&(v=i.content.ownerDocument)}let st,lt="";const{implementation:ct,createNodeIterator:ut,createDocumentFragment:pt,getElementsByTagName:ht}=v,{importNode:dt}=u;let mt={};DOMPurify.isSupported="function"==typeof i&&"function"==typeof it&&ct&&void 0!==ct.createHTMLDocument;const{MUSTACHE_EXPR:gt,ERB_EXPR:yt,TMPLIT_EXPR:vt,DATA_ATTR:bt,ARIA_ATTR:_t,IS_SCRIPT_OR_DATA:Et,ATTR_WHITESPACE:wt}=rt;let{IS_ALLOWED_URI:St}=rt,xt=null;const kt=addToSet({},[...ye,...be,..._e,...Se,...Pe]);let Ot=null;const At=addToSet({},[...Ie,...Te,...Re,...qe]);let Ct=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),jt=null,Pt=null,It=!0,Nt=!0,Tt=!1,Mt=!0,Rt=!1,Bt=!1,Dt=!1,Lt=!1,Ft=!1,qt=!1,$t=!1,zt=!0,Ut=!1;const Vt="user-content-";let Wt=!0,Kt=!1,Ht={},Jt=null;const Gt=addToSet({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Xt=null;const Yt=addToSet({},["audio","video","img","source","image","track"]);let Qt=null;const Zt=addToSet({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),er="http://www.w3.org/1998/Math/MathML",tr="http://www.w3.org/2000/svg",rr="http://www.w3.org/1999/xhtml";let nr=rr,ar=!1,ir=null;const sr=addToSet({},[er,tr,rr],ae);let lr;const cr=["application/xhtml+xml","text/html"],ur="text/html";let pr,dr=null;const fr=v.createElement("form"),mr=function isRegexOrFunction(i){return i instanceof RegExp||i instanceof Function},gr=function _parseConfig(i){if(!dr||dr!==i){if(i&&"object"==typeof i||(i={}),i=clone(i),lr=lr=-1===cr.indexOf(i.PARSER_MEDIA_TYPE)?ur:i.PARSER_MEDIA_TYPE,pr="application/xhtml+xml"===lr?ae:ee,xt="ALLOWED_TAGS"in i?addToSet({},i.ALLOWED_TAGS,pr):kt,Ot="ALLOWED_ATTR"in i?addToSet({},i.ALLOWED_ATTR,pr):At,ir="ALLOWED_NAMESPACES"in i?addToSet({},i.ALLOWED_NAMESPACES,ae):sr,Qt="ADD_URI_SAFE_ATTR"in i?addToSet(clone(Zt),i.ADD_URI_SAFE_ATTR,pr):Zt,Xt="ADD_DATA_URI_TAGS"in i?addToSet(clone(Yt),i.ADD_DATA_URI_TAGS,pr):Yt,Jt="FORBID_CONTENTS"in i?addToSet({},i.FORBID_CONTENTS,pr):Gt,jt="FORBID_TAGS"in i?addToSet({},i.FORBID_TAGS,pr):{},Pt="FORBID_ATTR"in i?addToSet({},i.FORBID_ATTR,pr):{},Ht="USE_PROFILES"in i&&i.USE_PROFILES,It=!1!==i.ALLOW_ARIA_ATTR,Nt=!1!==i.ALLOW_DATA_ATTR,Tt=i.ALLOW_UNKNOWN_PROTOCOLS||!1,Mt=!1!==i.ALLOW_SELF_CLOSE_IN_ATTR,Rt=i.SAFE_FOR_TEMPLATES||!1,Bt=i.WHOLE_DOCUMENT||!1,Ft=i.RETURN_DOM||!1,qt=i.RETURN_DOM_FRAGMENT||!1,$t=i.RETURN_TRUSTED_TYPE||!1,Lt=i.FORCE_BODY||!1,zt=!1!==i.SANITIZE_DOM,Ut=i.SANITIZE_NAMED_PROPS||!1,Wt=!1!==i.KEEP_CONTENT,Kt=i.IN_PLACE||!1,St=i.ALLOWED_URI_REGEXP||Ye,nr=i.NAMESPACE||rr,Ct=i.CUSTOM_ELEMENT_HANDLING||{},i.CUSTOM_ELEMENT_HANDLING&&mr(i.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ct.tagNameCheck=i.CUSTOM_ELEMENT_HANDLING.tagNameCheck),i.CUSTOM_ELEMENT_HANDLING&&mr(i.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ct.attributeNameCheck=i.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),i.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof i.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ct.allowCustomizedBuiltInElements=i.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Rt&&(Nt=!1),qt&&(Ft=!0),Ht&&(xt=addToSet({},[...Pe]),Ot=[],!0===Ht.html&&(addToSet(xt,ye),addToSet(Ot,Ie)),!0===Ht.svg&&(addToSet(xt,be),addToSet(Ot,Te),addToSet(Ot,qe)),!0===Ht.svgFilters&&(addToSet(xt,_e),addToSet(Ot,Te),addToSet(Ot,qe)),!0===Ht.mathMl&&(addToSet(xt,Se),addToSet(Ot,Re),addToSet(Ot,qe))),i.ADD_TAGS&&(xt===kt&&(xt=clone(xt)),addToSet(xt,i.ADD_TAGS,pr)),i.ADD_ATTR&&(Ot===At&&(Ot=clone(Ot)),addToSet(Ot,i.ADD_ATTR,pr)),i.ADD_URI_SAFE_ATTR&&addToSet(Qt,i.ADD_URI_SAFE_ATTR,pr),i.FORBID_CONTENTS&&(Jt===Gt&&(Jt=clone(Jt)),addToSet(Jt,i.FORBID_CONTENTS,pr)),Wt&&(xt["#text"]=!0),Bt&&addToSet(xt,["html","head","body"]),xt.table&&(addToSet(xt,["tbody"]),delete jt.tbody),i.TRUSTED_TYPES_POLICY){if("function"!=typeof i.TRUSTED_TYPES_POLICY.createHTML)throw fe('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof i.TRUSTED_TYPES_POLICY.createScriptURL)throw fe('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');st=i.TRUSTED_TYPES_POLICY,lt=st.createHTML("")}else void 0===st&&(st=nt(Xe,m)),null!==st&&"string"==typeof lt&&(lt=st.createHTML(""));_&&_(i),dr=i}},yr=addToSet({},["mi","mo","mn","ms","mtext"]),vr=addToSet({},["foreignobject","desc","title","annotation-xml"]),br=addToSet({},["title","style","font","a","script"]),_r=addToSet({},be);addToSet(_r,_e),addToSet(_r,we);const Er=addToSet({},Se);addToSet(Er,xe);const wr=function _checkValidNamespace(i){let s=it(i);s&&s.tagName||(s={namespaceURI:nr,tagName:"template"});const u=ee(i.tagName),m=ee(s.tagName);return!!ir[i.namespaceURI]&&(i.namespaceURI===tr?s.namespaceURI===rr?"svg"===u:s.namespaceURI===er?"svg"===u&&("annotation-xml"===m||yr[m]):Boolean(_r[u]):i.namespaceURI===er?s.namespaceURI===rr?"math"===u:s.namespaceURI===tr?"math"===u&&vr[m]:Boolean(Er[u]):i.namespaceURI===rr?!(s.namespaceURI===tr&&!vr[m])&&!(s.namespaceURI===er&&!yr[m])&&!Er[u]&&(br[u]||!_r[u]):!("application/xhtml+xml"!==lr||!ir[i.namespaceURI]))},Sr=function _forceRemove(i){Z(DOMPurify.removed,{element:i});try{i.parentNode.removeChild(i)}catch(s){i.remove()}},xr=function _removeAttribute(i,s){try{Z(DOMPurify.removed,{attribute:s.getAttributeNode(i),from:s})}catch(i){Z(DOMPurify.removed,{attribute:null,from:s})}if(s.removeAttribute(i),"is"===i&&!Ot[i])if(Ft||qt)try{Sr(s)}catch(i){}else try{s.setAttribute(i,"")}catch(i){}},kr=function _initDocument(i){let s,u;if(Lt)i=""+i;else{const s=ie(i,/^[\r\n\t ]+/);u=s&&s[0]}"application/xhtml+xml"===lr&&nr===rr&&(i=''+i+"");const m=st?st.createHTML(i):i;if(nr===rr)try{s=(new He).parseFromString(m,lr)}catch(i){}if(!s||!s.documentElement){s=ct.createDocument(nr,"template",null);try{s.documentElement.innerHTML=ar?lt:m}catch(i){}}const _=s.body||s.documentElement;return i&&u&&_.insertBefore(v.createTextNode(u),_.childNodes[0]||null),nr===rr?ht.call(s,Bt?"html":"body")[0]:Bt?s.documentElement:_},Or=function _createIterator(i){return ut.call(i.ownerDocument||i,i,ze.SHOW_ELEMENT|ze.SHOW_COMMENT|ze.SHOW_TEXT,null,!1)},Ar=function _isClobbered(i){return i instanceof We&&("string"!=typeof i.nodeName||"string"!=typeof i.textContent||"function"!=typeof i.removeChild||!(i.attributes instanceof Ve)||"function"!=typeof i.removeAttribute||"function"!=typeof i.setAttribute||"string"!=typeof i.namespaceURI||"function"!=typeof i.insertBefore||"function"!=typeof i.hasChildNodes)},Cr=function _isNode(i){return"object"==typeof $?i instanceof $:i&&"object"==typeof i&&"number"==typeof i.nodeType&&"string"==typeof i.nodeName},jr=function _executeHook(i,s,u){mt[i]&&X(mt[i],(i=>{i.call(DOMPurify,s,u,dr)}))},Pr=function _sanitizeElements(i){let s;if(jr("beforeSanitizeElements",i,null),Ar(i))return Sr(i),!0;const u=pr(i.nodeName);if(jr("uponSanitizeElement",i,{tagName:u,allowedTags:xt}),i.hasChildNodes()&&!Cr(i.firstElementChild)&&(!Cr(i.content)||!Cr(i.content.firstElementChild))&&de(/<[/\w]/g,i.innerHTML)&&de(/<[/\w]/g,i.textContent))return Sr(i),!0;if(!xt[u]||jt[u]){if(!jt[u]&&Nr(u)){if(Ct.tagNameCheck instanceof RegExp&&de(Ct.tagNameCheck,u))return!1;if(Ct.tagNameCheck instanceof Function&&Ct.tagNameCheck(u))return!1}if(Wt&&!Jt[u]){const s=it(i)||i.parentNode,u=at(i)||i.childNodes;if(u&&s)for(let m=u.length-1;m>=0;--m)s.insertBefore(et(u[m],!0),ot(i))}return Sr(i),!0}return i instanceof W&&!wr(i)?(Sr(i),!0):"noscript"!==u&&"noembed"!==u&&"noframes"!==u||!de(/<\/no(script|embed|frames)/i,i.innerHTML)?(Rt&&3===i.nodeType&&(s=i.textContent,s=le(s,gt," "),s=le(s,yt," "),s=le(s,vt," "),i.textContent!==s&&(Z(DOMPurify.removed,{element:i.cloneNode()}),i.textContent=s)),jr("afterSanitizeElements",i,null),!1):(Sr(i),!0)},Ir=function _isValidAttribute(i,s,u){if(zt&&("id"===s||"name"===s)&&(u in v||u in fr))return!1;if(Nt&&!Pt[s]&&de(bt,s));else if(It&&de(_t,s));else if(!Ot[s]||Pt[s]){if(!(Nr(i)&&(Ct.tagNameCheck instanceof RegExp&&de(Ct.tagNameCheck,i)||Ct.tagNameCheck instanceof Function&&Ct.tagNameCheck(i))&&(Ct.attributeNameCheck instanceof RegExp&&de(Ct.attributeNameCheck,s)||Ct.attributeNameCheck instanceof Function&&Ct.attributeNameCheck(s))||"is"===s&&Ct.allowCustomizedBuiltInElements&&(Ct.tagNameCheck instanceof RegExp&&de(Ct.tagNameCheck,u)||Ct.tagNameCheck instanceof Function&&Ct.tagNameCheck(u))))return!1}else if(Qt[s]);else if(de(St,le(u,wt,"")));else if("src"!==s&&"xlink:href"!==s&&"href"!==s||"script"===i||0!==ce(u,"data:")||!Xt[i])if(Tt&&!de(Et,le(u,wt,"")));else if(u)return!1;return!0},Nr=function _basicCustomElementTest(i){return i.indexOf("-")>0},Tr=function _sanitizeAttributes(i){let s,u,m,v;jr("beforeSanitizeAttributes",i,null);const{attributes:_}=i;if(!_)return;const j={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Ot};for(v=_.length;v--;){s=_[v];const{name:M,namespaceURI:$}=s;if(u="value"===M?s.value:pe(s.value),m=pr(M),j.attrName=m,j.attrValue=u,j.keepAttr=!0,j.forceKeepAttr=void 0,jr("uponSanitizeAttribute",i,j),u=j.attrValue,j.forceKeepAttr)continue;if(xr(M,i),!j.keepAttr)continue;if(!Mt&&de(/\/>/i,u)){xr(M,i);continue}Rt&&(u=le(u,gt," "),u=le(u,yt," "),u=le(u,vt," "));const W=pr(i.nodeName);if(Ir(W,m,u)){if(!Ut||"id"!==m&&"name"!==m||(xr(M,i),u=Vt+u),st&&"object"==typeof Xe&&"function"==typeof Xe.getAttributeType)if($);else switch(Xe.getAttributeType(W,m)){case"TrustedHTML":u=st.createHTML(u);break;case"TrustedScriptURL":u=st.createScriptURL(u)}try{$?i.setAttributeNS($,M,u):i.setAttribute(M,u),Y(DOMPurify.removed)}catch(i){}}}jr("afterSanitizeAttributes",i,null)},Mr=function _sanitizeShadowDOM(i){let s;const u=Or(i);for(jr("beforeSanitizeShadowDOM",i,null);s=u.nextNode();)jr("uponSanitizeShadowNode",s,null),Pr(s)||(s.content instanceof j&&_sanitizeShadowDOM(s.content),Tr(s));jr("afterSanitizeShadowDOM",i,null)};return DOMPurify.sanitize=function(i){let s,m,v,_,M=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(ar=!i,ar&&(i="\x3c!--\x3e"),"string"!=typeof i&&!Cr(i)){if("function"!=typeof i.toString)throw fe("toString is not a function");if("string"!=typeof(i=i.toString()))throw fe("dirty is not a string, aborting")}if(!DOMPurify.isSupported)return i;if(Dt||gr(M),DOMPurify.removed=[],"string"==typeof i&&(Kt=!1),Kt){if(i.nodeName){const s=pr(i.nodeName);if(!xt[s]||jt[s])throw fe("root node is forbidden and cannot be sanitized in-place")}}else if(i instanceof $)s=kr("\x3c!----\x3e"),m=s.ownerDocument.importNode(i,!0),1===m.nodeType&&"BODY"===m.nodeName||"HTML"===m.nodeName?s=m:s.appendChild(m);else{if(!Ft&&!Rt&&!Bt&&-1===i.indexOf("<"))return st&&$t?st.createHTML(i):i;if(s=kr(i),!s)return Ft?null:$t?lt:""}s&&Lt&&Sr(s.firstChild);const W=Or(Kt?i:s);for(;v=W.nextNode();)Pr(v)||(v.content instanceof j&&Mr(v.content),Tr(v));if(Kt)return i;if(Ft){if(qt)for(_=pt.call(s.ownerDocument);s.firstChild;)_.appendChild(s.firstChild);else _=s;return(Ot.shadowroot||Ot.shadowrootmode)&&(_=dt.call(u,_,!0)),_}let X=Bt?s.outerHTML:s.innerHTML;return Bt&&xt["!doctype"]&&s.ownerDocument&&s.ownerDocument.doctype&&s.ownerDocument.doctype.name&&de(tt,s.ownerDocument.doctype.name)&&(X="\n"+X),Rt&&(X=le(X,gt," "),X=le(X,yt," "),X=le(X,vt," ")),st&&$t?st.createHTML(X):X},DOMPurify.setConfig=function(i){gr(i),Dt=!0},DOMPurify.clearConfig=function(){dr=null,Dt=!1},DOMPurify.isValidAttribute=function(i,s,u){dr||gr({});const m=pr(i),v=pr(s);return Ir(m,v,u)},DOMPurify.addHook=function(i,s){"function"==typeof s&&(mt[i]=mt[i]||[],Z(mt[i],s))},DOMPurify.removeHook=function(i){if(mt[i])return Y(mt[i])},DOMPurify.removeHooks=function(i){mt[i]&&(mt[i]=[])},DOMPurify.removeAllHooks=function(){mt={}},DOMPurify}return createDOMPurify()}()},69450:i=>{"use strict";class SubRange{constructor(i,s){this.low=i,this.high=s,this.length=1+s-i}overlaps(i){return!(this.highi.high)}touches(i){return!(this.high+1i.high)}add(i){return new SubRange(Math.min(this.low,i.low),Math.max(this.high,i.high))}subtract(i){return i.low<=this.low&&i.high>=this.high?[]:i.low>this.low&&i.highi+s.length),0)}add(i,s){var _add=i=>{for(var s=0;s{for(var s=0;s{for(var s=0;s{for(var u=s.low;u<=s.high;)i.push(u),u++;return i}),[])}subranges(){return this.ranges.map((i=>({low:i.low,high:i.high,length:1+i.high-i.low})))}}i.exports=DRange},17187:i=>{"use strict";var s,u="object"==typeof Reflect?Reflect:null,m=u&&"function"==typeof u.apply?u.apply:function ReflectApply(i,s,u){return Function.prototype.apply.call(i,s,u)};s=u&&"function"==typeof u.ownKeys?u.ownKeys:Object.getOwnPropertySymbols?function ReflectOwnKeys(i){return Object.getOwnPropertyNames(i).concat(Object.getOwnPropertySymbols(i))}:function ReflectOwnKeys(i){return Object.getOwnPropertyNames(i)};var v=Number.isNaN||function NumberIsNaN(i){return i!=i};function EventEmitter(){EventEmitter.init.call(this)}i.exports=EventEmitter,i.exports.once=function once(i,s){return new Promise((function(u,m){function errorListener(u){i.removeListener(s,resolver),m(u)}function resolver(){"function"==typeof i.removeListener&&i.removeListener("error",errorListener),u([].slice.call(arguments))}eventTargetAgnosticAddListener(i,s,resolver,{once:!0}),"error"!==s&&function addErrorHandlerIfEventEmitter(i,s,u){"function"==typeof i.on&&eventTargetAgnosticAddListener(i,"error",s,u)}(i,errorListener,{once:!0})}))},EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._eventsCount=0,EventEmitter.prototype._maxListeners=void 0;var _=10;function checkListener(i){if("function"!=typeof i)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof i)}function _getMaxListeners(i){return void 0===i._maxListeners?EventEmitter.defaultMaxListeners:i._maxListeners}function _addListener(i,s,u,m){var v,_,j;if(checkListener(u),void 0===(_=i._events)?(_=i._events=Object.create(null),i._eventsCount=0):(void 0!==_.newListener&&(i.emit("newListener",s,u.listener?u.listener:u),_=i._events),j=_[s]),void 0===j)j=_[s]=u,++i._eventsCount;else if("function"==typeof j?j=_[s]=m?[u,j]:[j,u]:m?j.unshift(u):j.push(u),(v=_getMaxListeners(i))>0&&j.length>v&&!j.warned){j.warned=!0;var M=new Error("Possible EventEmitter memory leak detected. "+j.length+" "+String(s)+" listeners added. Use emitter.setMaxListeners() to increase limit");M.name="MaxListenersExceededWarning",M.emitter=i,M.type=s,M.count=j.length,function ProcessEmitWarning(i){console&&console.warn&&console.warn(i)}(M)}return i}function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(i,s,u){var m={fired:!1,wrapFn:void 0,target:i,type:s,listener:u},v=onceWrapper.bind(m);return v.listener=u,m.wrapFn=v,v}function _listeners(i,s,u){var m=i._events;if(void 0===m)return[];var v=m[s];return void 0===v?[]:"function"==typeof v?u?[v.listener||v]:[v]:u?function unwrapListeners(i){for(var s=new Array(i.length),u=0;u0&&(j=s[0]),j instanceof Error)throw j;var M=new Error("Unhandled error."+(j?" ("+j.message+")":""));throw M.context=j,M}var $=_[i];if(void 0===$)return!1;if("function"==typeof $)m($,this,s);else{var W=$.length,X=arrayClone($,W);for(u=0;u=0;_--)if(u[_]===s||u[_].listener===s){j=u[_].listener,v=_;break}if(v<0)return this;0===v?u.shift():function spliceOne(i,s){for(;s+1=0;m--)this.removeListener(i,s[m]);return this},EventEmitter.prototype.listeners=function listeners(i){return _listeners(this,i,!0)},EventEmitter.prototype.rawListeners=function rawListeners(i){return _listeners(this,i,!1)},EventEmitter.listenerCount=function(i,s){return"function"==typeof i.listenerCount?i.listenerCount(s):listenerCount.call(i,s)},EventEmitter.prototype.listenerCount=listenerCount,EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?s(this._events):[]}},21102:(i,s,u)=>{"use strict";var m=u(46291),v=create(Error);function create(i){return FormattedError.displayName=i.displayName||i.name,FormattedError;function FormattedError(s){return s&&(s=m.apply(null,arguments)),new i(s)}}i.exports=v,v.eval=create(EvalError),v.range=create(RangeError),v.reference=create(ReferenceError),v.syntax=create(SyntaxError),v.type=create(TypeError),v.uri=create(URIError),v.create=create},46291:i=>{!function(){var s;function format(i){for(var s,u,m,v,_=1,j=[].slice.call(arguments),M=0,$=i.length,W="",X=!1,Y=!1,nextArg=function(){return j[_++]},slurpNumber=function(){for(var u="";/\d/.test(i[M]);)u+=i[M++],s=i[M];return u.length>0?parseInt(u):null};M<$;++M)if(s=i[M],X)switch(X=!1,"."==s?(Y=!1,s=i[++M]):"0"==s&&"."==i[M+1]?(Y=!0,s=i[M+=2]):Y=!0,v=slurpNumber(),s){case"b":W+=parseInt(nextArg(),10).toString(2);break;case"c":W+="string"==typeof(u=nextArg())||u instanceof String?u:String.fromCharCode(parseInt(u,10));break;case"d":W+=parseInt(nextArg(),10);break;case"f":m=String(parseFloat(nextArg()).toFixed(v||6)),W+=Y?m:m.replace(/^0/,"");break;case"j":W+=JSON.stringify(nextArg());break;case"o":W+="0"+parseInt(nextArg(),10).toString(8);break;case"s":W+=nextArg();break;case"x":W+="0x"+parseInt(nextArg(),10).toString(16);break;case"X":W+="0x"+parseInt(nextArg(),10).toString(16).toUpperCase();break;default:W+=s}else"%"===s?X=!0:W+=s;return W}(s=i.exports=format).format=format,s.vsprintf=function vsprintf(i,s){return format.apply(null,[i].concat(s))},"undefined"!=typeof console&&"function"==typeof console.log&&(s.printf=function printf(){console.log(format.apply(null,arguments))})}()},17648:i=>{"use strict";var s=Array.prototype.slice,u=Object.prototype.toString;i.exports=function bind(i){var m=this;if("function"!=typeof m||"[object Function]"!==u.call(m))throw new TypeError("Function.prototype.bind called on incompatible "+m);for(var v,_=s.call(arguments,1),j=Math.max(0,m.length-_.length),M=[],$=0;${"use strict";var m=u(17648);i.exports=Function.prototype.bind||m},40210:(i,s,u)=>{"use strict";var m,v=SyntaxError,_=Function,j=TypeError,getEvalledConstructor=function(i){try{return _('"use strict"; return ('+i+").constructor;")()}catch(i){}},M=Object.getOwnPropertyDescriptor;if(M)try{M({},"")}catch(i){M=null}var throwTypeError=function(){throw new j},$=M?function(){try{return throwTypeError}catch(i){try{return M(arguments,"callee").get}catch(i){return throwTypeError}}}():throwTypeError,W=u(41405)(),X=u(28185)(),Y=Object.getPrototypeOf||(X?function(i){return i.__proto__}:null),Z={},ee="undefined"!=typeof Uint8Array&&Y?Y(Uint8Array):m,ae={"%AggregateError%":"undefined"==typeof AggregateError?m:AggregateError,"%Array%":Array,"%ArrayBuffer%":"undefined"==typeof ArrayBuffer?m:ArrayBuffer,"%ArrayIteratorPrototype%":W&&Y?Y([][Symbol.iterator]()):m,"%AsyncFromSyncIteratorPrototype%":m,"%AsyncFunction%":Z,"%AsyncGenerator%":Z,"%AsyncGeneratorFunction%":Z,"%AsyncIteratorPrototype%":Z,"%Atomics%":"undefined"==typeof Atomics?m:Atomics,"%BigInt%":"undefined"==typeof BigInt?m:BigInt,"%BigInt64Array%":"undefined"==typeof BigInt64Array?m:BigInt64Array,"%BigUint64Array%":"undefined"==typeof BigUint64Array?m:BigUint64Array,"%Boolean%":Boolean,"%DataView%":"undefined"==typeof DataView?m:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%eval%":eval,"%EvalError%":EvalError,"%Float32Array%":"undefined"==typeof Float32Array?m:Float32Array,"%Float64Array%":"undefined"==typeof Float64Array?m:Float64Array,"%FinalizationRegistry%":"undefined"==typeof FinalizationRegistry?m:FinalizationRegistry,"%Function%":_,"%GeneratorFunction%":Z,"%Int8Array%":"undefined"==typeof Int8Array?m:Int8Array,"%Int16Array%":"undefined"==typeof Int16Array?m:Int16Array,"%Int32Array%":"undefined"==typeof Int32Array?m:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":W&&Y?Y(Y([][Symbol.iterator]())):m,"%JSON%":"object"==typeof JSON?JSON:m,"%Map%":"undefined"==typeof Map?m:Map,"%MapIteratorPrototype%":"undefined"!=typeof Map&&W&&Y?Y((new Map)[Symbol.iterator]()):m,"%Math%":Math,"%Number%":Number,"%Object%":Object,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":"undefined"==typeof Promise?m:Promise,"%Proxy%":"undefined"==typeof Proxy?m:Proxy,"%RangeError%":RangeError,"%ReferenceError%":ReferenceError,"%Reflect%":"undefined"==typeof Reflect?m:Reflect,"%RegExp%":RegExp,"%Set%":"undefined"==typeof Set?m:Set,"%SetIteratorPrototype%":"undefined"!=typeof Set&&W&&Y?Y((new Set)[Symbol.iterator]()):m,"%SharedArrayBuffer%":"undefined"==typeof SharedArrayBuffer?m:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":W&&Y?Y(""[Symbol.iterator]()):m,"%Symbol%":W?Symbol:m,"%SyntaxError%":v,"%ThrowTypeError%":$,"%TypedArray%":ee,"%TypeError%":j,"%Uint8Array%":"undefined"==typeof Uint8Array?m:Uint8Array,"%Uint8ClampedArray%":"undefined"==typeof Uint8ClampedArray?m:Uint8ClampedArray,"%Uint16Array%":"undefined"==typeof Uint16Array?m:Uint16Array,"%Uint32Array%":"undefined"==typeof Uint32Array?m:Uint32Array,"%URIError%":URIError,"%WeakMap%":"undefined"==typeof WeakMap?m:WeakMap,"%WeakRef%":"undefined"==typeof WeakRef?m:WeakRef,"%WeakSet%":"undefined"==typeof WeakSet?m:WeakSet};if(Y)try{null.error}catch(i){var ie=Y(Y(i));ae["%Error.prototype%"]=ie}var le=function doEval(i){var s;if("%AsyncFunction%"===i)s=getEvalledConstructor("async function () {}");else if("%GeneratorFunction%"===i)s=getEvalledConstructor("function* () {}");else if("%AsyncGeneratorFunction%"===i)s=getEvalledConstructor("async function* () {}");else if("%AsyncGenerator%"===i){var u=doEval("%AsyncGeneratorFunction%");u&&(s=u.prototype)}else if("%AsyncIteratorPrototype%"===i){var m=doEval("%AsyncGenerator%");m&&Y&&(s=Y(m.prototype))}return ae[i]=s,s},ce={"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},pe=u(58612),de=u(17642),fe=pe.call(Function.call,Array.prototype.concat),ye=pe.call(Function.apply,Array.prototype.splice),be=pe.call(Function.call,String.prototype.replace),_e=pe.call(Function.call,String.prototype.slice),we=pe.call(Function.call,RegExp.prototype.exec),Se=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,xe=/\\(\\)?/g,Pe=function getBaseIntrinsic(i,s){var u,m=i;if(de(ce,m)&&(m="%"+(u=ce[m])[0]+"%"),de(ae,m)){var _=ae[m];if(_===Z&&(_=le(m)),void 0===_&&!s)throw new j("intrinsic "+i+" exists, but is not available. Please file an issue!");return{alias:u,name:m,value:_}}throw new v("intrinsic "+i+" does not exist!")};i.exports=function GetIntrinsic(i,s){if("string"!=typeof i||0===i.length)throw new j("intrinsic name must be a non-empty string");if(arguments.length>1&&"boolean"!=typeof s)throw new j('"allowMissing" argument must be a boolean');if(null===we(/^%?[^%]*%?$/,i))throw new v("`%` may not be present anywhere but at the beginning and end of the intrinsic name");var u=function stringToPath(i){var s=_e(i,0,1),u=_e(i,-1);if("%"===s&&"%"!==u)throw new v("invalid intrinsic syntax, expected closing `%`");if("%"===u&&"%"!==s)throw new v("invalid intrinsic syntax, expected opening `%`");var m=[];return be(i,Se,(function(i,s,u,v){m[m.length]=u?be(v,xe,"$1"):s||i})),m}(i),m=u.length>0?u[0]:"",_=Pe("%"+m+"%",s),$=_.name,W=_.value,X=!1,Y=_.alias;Y&&(m=Y[0],ye(u,fe([0,1],Y)));for(var Z=1,ee=!0;Z=u.length){var pe=M(W,ie);W=(ee=!!pe)&&"get"in pe&&!("originalValue"in pe.get)?pe.get:W[ie]}else ee=de(W,ie),W=W[ie];ee&&!X&&(ae[$]=W)}}return W}},28185:i=>{"use strict";var s={foo:{}},u=Object;i.exports=function hasProto(){return{__proto__:s}.foo===s.foo&&!({__proto__:null}instanceof u)}},41405:(i,s,u)=>{"use strict";var m="undefined"!=typeof Symbol&&Symbol,v=u(55419);i.exports=function hasNativeSymbols(){return"function"==typeof m&&("function"==typeof Symbol&&("symbol"==typeof m("foo")&&("symbol"==typeof Symbol("bar")&&v())))}},55419:i=>{"use strict";i.exports=function hasSymbols(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"==typeof Symbol.iterator)return!0;var i={},s=Symbol("test"),u=Object(s);if("string"==typeof s)return!1;if("[object Symbol]"!==Object.prototype.toString.call(s))return!1;if("[object Symbol]"!==Object.prototype.toString.call(u))return!1;for(s in i[s]=42,i)return!1;if("function"==typeof Object.keys&&0!==Object.keys(i).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(i).length)return!1;var m=Object.getOwnPropertySymbols(i);if(1!==m.length||m[0]!==s)return!1;if(!Object.prototype.propertyIsEnumerable.call(i,s))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){var v=Object.getOwnPropertyDescriptor(i,s);if(42!==v.value||!0!==v.enumerable)return!1}return!0}},17642:(i,s,u)=>{"use strict";var m=u(58612);i.exports=m.call(Function.call,Object.prototype.hasOwnProperty)},47802:i=>{function deepFreeze(i){return i instanceof Map?i.clear=i.delete=i.set=function(){throw new Error("map is read-only")}:i instanceof Set&&(i.add=i.clear=i.delete=function(){throw new Error("set is read-only")}),Object.freeze(i),Object.getOwnPropertyNames(i).forEach((function(s){var u=i[s];"object"!=typeof u||Object.isFrozen(u)||deepFreeze(u)})),i}var s=deepFreeze,u=deepFreeze;s.default=u;class Response{constructor(i){void 0===i.data&&(i.data={}),this.data=i.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function escapeHTML(i){return i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function inherit(i,...s){const u=Object.create(null);for(const s in i)u[s]=i[s];return s.forEach((function(i){for(const s in i)u[s]=i[s]})),u}const emitsWrappingTags=i=>!!i.kind;class HTMLRenderer{constructor(i,s){this.buffer="",this.classPrefix=s.classPrefix,i.walk(this)}addText(i){this.buffer+=escapeHTML(i)}openNode(i){if(!emitsWrappingTags(i))return;let s=i.kind;i.sublanguage||(s=`${this.classPrefix}${s}`),this.span(s)}closeNode(i){emitsWrappingTags(i)&&(this.buffer+="")}value(){return this.buffer}span(i){this.buffer+=``}}class TokenTree{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(i){this.top.children.push(i)}openNode(i){const s={kind:i,children:[]};this.add(s),this.stack.push(s)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(i){return this.constructor._walk(i,this.rootNode)}static _walk(i,s){return"string"==typeof s?i.addText(s):s.children&&(i.openNode(s),s.children.forEach((s=>this._walk(i,s))),i.closeNode(s)),i}static _collapse(i){"string"!=typeof i&&i.children&&(i.children.every((i=>"string"==typeof i))?i.children=[i.children.join("")]:i.children.forEach((i=>{TokenTree._collapse(i)})))}}class TokenTreeEmitter extends TokenTree{constructor(i){super(),this.options=i}addKeyword(i,s){""!==i&&(this.openNode(s),this.addText(i),this.closeNode())}addText(i){""!==i&&this.add(i)}addSublanguage(i,s){const u=i.root;u.kind=s,u.sublanguage=!0,this.add(u)}toHTML(){return new HTMLRenderer(this,this.options).value()}finalize(){return!0}}function source(i){return i?"string"==typeof i?i:i.source:null}const m=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;const v="[a-zA-Z]\\w*",_="[a-zA-Z_]\\w*",j="\\b\\d+(\\.\\d+)?",M="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",$="\\b(0b[01]+)",W={begin:"\\\\[\\s\\S]",relevance:0},X={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[W]},Y={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[W]},Z={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},COMMENT=function(i,s,u={}){const m=inherit({className:"comment",begin:i,end:s,contains:[]},u);return m.contains.push(Z),m.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),m},ee=COMMENT("//","$"),ae=COMMENT("/\\*","\\*/"),ie=COMMENT("#","$"),le={className:"number",begin:j,relevance:0},ce={className:"number",begin:M,relevance:0},pe={className:"number",begin:$,relevance:0},de={className:"number",begin:j+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},fe={begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[W,{begin:/\[/,end:/\]/,relevance:0,contains:[W]}]}]},ye={className:"title",begin:v,relevance:0},be={className:"title",begin:_,relevance:0},_e={begin:"\\.\\s*"+_,relevance:0};var we=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:v,UNDERSCORE_IDENT_RE:_,NUMBER_RE:j,C_NUMBER_RE:M,BINARY_NUMBER_RE:$,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(i={})=>{const s=/^#![ ]*\//;return i.binary&&(i.begin=function concat(...i){return i.map((i=>source(i))).join("")}(s,/.*\b/,i.binary,/\b.*/)),inherit({className:"meta",begin:s,end:/$/,relevance:0,"on:begin":(i,s)=>{0!==i.index&&s.ignoreMatch()}},i)},BACKSLASH_ESCAPE:W,APOS_STRING_MODE:X,QUOTE_STRING_MODE:Y,PHRASAL_WORDS_MODE:Z,COMMENT,C_LINE_COMMENT_MODE:ee,C_BLOCK_COMMENT_MODE:ae,HASH_COMMENT_MODE:ie,NUMBER_MODE:le,C_NUMBER_MODE:ce,BINARY_NUMBER_MODE:pe,CSS_NUMBER_MODE:de,REGEXP_MODE:fe,TITLE_MODE:ye,UNDERSCORE_TITLE_MODE:be,METHOD_GUARD:_e,END_SAME_AS_BEGIN:function(i){return Object.assign(i,{"on:begin":(i,s)=>{s.data._beginMatch=i[1]},"on:end":(i,s)=>{s.data._beginMatch!==i[1]&&s.ignoreMatch()}})}});function skipIfhasPrecedingDot(i,s){"."===i.input[i.index-1]&&s.ignoreMatch()}function beginKeywords(i,s){s&&i.beginKeywords&&(i.begin="\\b("+i.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",i.__beforeBegin=skipIfhasPrecedingDot,i.keywords=i.keywords||i.beginKeywords,delete i.beginKeywords,void 0===i.relevance&&(i.relevance=0))}function compileIllegal(i,s){Array.isArray(i.illegal)&&(i.illegal=function either(...i){return"("+i.map((i=>source(i))).join("|")+")"}(...i.illegal))}function compileMatch(i,s){if(i.match){if(i.begin||i.end)throw new Error("begin & end are not supported with match");i.begin=i.match,delete i.match}}function compileRelevance(i,s){void 0===i.relevance&&(i.relevance=1)}const Se=["of","and","for","in","not","or","if","then","parent","list","value"],xe="keyword";function compileKeywords(i,s,u=xe){const m={};return"string"==typeof i?compileList(u,i.split(" ")):Array.isArray(i)?compileList(u,i):Object.keys(i).forEach((function(u){Object.assign(m,compileKeywords(i[u],s,u))})),m;function compileList(i,u){s&&(u=u.map((i=>i.toLowerCase()))),u.forEach((function(s){const u=s.split("|");m[u[0]]=[i,scoreForKeyword(u[0],u[1])]}))}}function scoreForKeyword(i,s){return s?Number(s):function commonKeyword(i){return Se.includes(i.toLowerCase())}(i)?0:1}function compileLanguage(i,{plugins:s}){function langRe(s,u){return new RegExp(source(s),"m"+(i.case_insensitive?"i":"")+(u?"g":""))}class MultiRegex{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(i,s){s.position=this.position++,this.matchIndexes[this.matchAt]=s,this.regexes.push([s,i]),this.matchAt+=function countMatchGroups(i){return new RegExp(i.toString()+"|").exec("").length-1}(i)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const i=this.regexes.map((i=>i[1]));this.matcherRe=langRe(function join(i,s="|"){let u=0;return i.map((i=>{u+=1;const s=u;let v=source(i),_="";for(;v.length>0;){const i=m.exec(v);if(!i){_+=v;break}_+=v.substring(0,i.index),v=v.substring(i.index+i[0].length),"\\"===i[0][0]&&i[1]?_+="\\"+String(Number(i[1])+s):(_+=i[0],"("===i[0]&&u++)}return _})).map((i=>`(${i})`)).join(s)}(i),!0),this.lastIndex=0}exec(i){this.matcherRe.lastIndex=this.lastIndex;const s=this.matcherRe.exec(i);if(!s)return null;const u=s.findIndex(((i,s)=>s>0&&void 0!==i)),m=this.matchIndexes[u];return s.splice(0,u),Object.assign(s,m)}}class ResumableMultiRegex{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(i){if(this.multiRegexes[i])return this.multiRegexes[i];const s=new MultiRegex;return this.rules.slice(i).forEach((([i,u])=>s.addRule(i,u))),s.compile(),this.multiRegexes[i]=s,s}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(i,s){this.rules.push([i,s]),"begin"===s.type&&this.count++}exec(i){const s=this.getMatcher(this.regexIndex);s.lastIndex=this.lastIndex;let u=s.exec(i);if(this.resumingScanAtSamePosition())if(u&&u.index===this.lastIndex);else{const s=this.getMatcher(0);s.lastIndex=this.lastIndex+1,u=s.exec(i)}return u&&(this.regexIndex+=u.position+1,this.regexIndex===this.count&&this.considerAll()),u}}if(i.compilerExtensions||(i.compilerExtensions=[]),i.contains&&i.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return i.classNameAliases=inherit(i.classNameAliases||{}),function compileMode(s,u){const m=s;if(s.isCompiled)return m;[compileMatch].forEach((i=>i(s,u))),i.compilerExtensions.forEach((i=>i(s,u))),s.__beforeBegin=null,[beginKeywords,compileIllegal,compileRelevance].forEach((i=>i(s,u))),s.isCompiled=!0;let v=null;if("object"==typeof s.keywords&&(v=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=compileKeywords(s.keywords,i.case_insensitive)),s.lexemes&&v)throw new Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return v=v||s.lexemes||/\w+/,m.keywordPatternRe=langRe(v,!0),u&&(s.begin||(s.begin=/\B|\b/),m.beginRe=langRe(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(m.endRe=langRe(s.end)),m.terminatorEnd=source(s.end)||"",s.endsWithParent&&u.terminatorEnd&&(m.terminatorEnd+=(s.end?"|":"")+u.terminatorEnd)),s.illegal&&(m.illegalRe=langRe(s.illegal)),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(i){return function expandOrCloneMode(i){i.variants&&!i.cachedVariants&&(i.cachedVariants=i.variants.map((function(s){return inherit(i,{variants:null},s)})));if(i.cachedVariants)return i.cachedVariants;if(dependencyOnParent(i))return inherit(i,{starts:i.starts?inherit(i.starts):null});if(Object.isFrozen(i))return inherit(i);return i}("self"===i?s:i)}))),s.contains.forEach((function(i){compileMode(i,m)})),s.starts&&compileMode(s.starts,u),m.matcher=function buildModeRegex(i){const s=new ResumableMultiRegex;return i.contains.forEach((i=>s.addRule(i.begin,{rule:i,type:"begin"}))),i.terminatorEnd&&s.addRule(i.terminatorEnd,{type:"end"}),i.illegal&&s.addRule(i.illegal,{type:"illegal"}),s}(m),m}(i)}function dependencyOnParent(i){return!!i&&(i.endsWithParent||dependencyOnParent(i.starts))}function BuildVuePlugin(i){const s={props:["language","code","autodetect"],data:function(){return{detectedLanguage:"",unknownLanguage:!1}},computed:{className(){return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){if(!this.autoDetect&&!i.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`),this.unknownLanguage=!0,escapeHTML(this.code);let s={};return this.autoDetect?(s=i.highlightAuto(this.code),this.detectedLanguage=s.language):(s=i.highlight(this.language,this.code,this.ignoreIllegals),this.detectedLanguage=this.language),s.value},autoDetect(){return!this.language||function hasValueOrEmptyAttribute(i){return Boolean(i||""===i)}(this.autodetect)},ignoreIllegals:()=>!0},render(i){return i("pre",{},[i("code",{class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{Component:s,VuePlugin:{install(i){i.component("highlightjs",s)}}}}const Pe={"after:highlightElement":({el:i,result:s,text:u})=>{const m=nodeStream(i);if(!m.length)return;const v=document.createElement("div");v.innerHTML=s.value,s.value=function mergeStreams(i,s,u){let m=0,v="";const _=[];function selectStream(){return i.length&&s.length?i[0].offset!==s[0].offset?i[0].offset"}function close(i){v+=""}function render(i){("start"===i.event?open:close)(i.node)}for(;i.length||s.length;){let s=selectStream();if(v+=escapeHTML(u.substring(m,s[0].offset)),m=s[0].offset,s===i){_.reverse().forEach(close);do{render(s.splice(0,1)[0]),s=selectStream()}while(s===i&&s.length&&s[0].offset===m);_.reverse().forEach(open)}else"start"===s[0].event?_.push(s[0].node):_.pop(),render(s.splice(0,1)[0])}return v+escapeHTML(u.substr(m))}(m,nodeStream(v),u)}};function tag(i){return i.nodeName.toLowerCase()}function nodeStream(i){const s=[];return function _nodeStream(i,u){for(let m=i.firstChild;m;m=m.nextSibling)3===m.nodeType?u+=m.nodeValue.length:1===m.nodeType&&(s.push({event:"start",offset:u,node:m}),u=_nodeStream(m,u),tag(m).match(/br|hr|img|input/)||s.push({event:"stop",offset:u,node:m}));return u}(i,0),s}const Ie={},error=i=>{console.error(i)},warn=(i,...s)=>{console.log(`WARN: ${i}`,...s)},deprecated=(i,s)=>{Ie[`${i}/${s}`]||(console.log(`Deprecated as of ${i}. ${s}`),Ie[`${i}/${s}`]=!0)},Te=escapeHTML,Re=inherit,qe=Symbol("nomatch");var ze=function(i){const u=Object.create(null),m=Object.create(null),v=[];let _=!0;const j=/(^(<[^>]+>|\t|)+|\n)/gm,M="Could not find the language '{}', did you forget to load/include a language module?",$={disableAutodetect:!0,name:"Plain text",contains:[]};let W={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:TokenTreeEmitter};function shouldNotHighlight(i){return W.noHighlightRe.test(i)}function highlight(i,s,u,m){let v="",_="";"object"==typeof s?(v=i,u=s.ignoreIllegals,_=s.language,m=void 0):(deprecated("10.7.0","highlight(lang, code, ...args) has been deprecated."),deprecated("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),_=i,v=s);const j={code:v,language:_};fire("before:highlight",j);const M=j.result?j.result:_highlight(j.language,j.code,u,m);return M.code=j.code,fire("after:highlight",M),M}function _highlight(i,s,m,j){function keywordData(i,s){const u=X.case_insensitive?s[0].toLowerCase():s[0];return Object.prototype.hasOwnProperty.call(i.keywords,u)&&i.keywords[u]}function processBuffer(){null!=ee.subLanguage?function processSubLanguage(){if(""===le)return;let i=null;if("string"==typeof ee.subLanguage){if(!u[ee.subLanguage])return void ie.addText(le);i=_highlight(ee.subLanguage,le,!0,ae[ee.subLanguage]),ae[ee.subLanguage]=i.top}else i=highlightAuto(le,ee.subLanguage.length?ee.subLanguage:null);ee.relevance>0&&(ce+=i.relevance),ie.addSublanguage(i.emitter,i.language)}():function processKeywords(){if(!ee.keywords)return void ie.addText(le);let i=0;ee.keywordPatternRe.lastIndex=0;let s=ee.keywordPatternRe.exec(le),u="";for(;s;){u+=le.substring(i,s.index);const m=keywordData(ee,s);if(m){const[i,v]=m;if(ie.addText(u),u="",ce+=v,i.startsWith("_"))u+=s[0];else{const u=X.classNameAliases[i]||i;ie.addKeyword(s[0],u)}}else u+=s[0];i=ee.keywordPatternRe.lastIndex,s=ee.keywordPatternRe.exec(le)}u+=le.substr(i),ie.addText(u)}(),le=""}function startNewMode(i){return i.className&&ie.openNode(X.classNameAliases[i.className]||i.className),ee=Object.create(i,{parent:{value:ee}}),ee}function endOfMode(i,s,u){let m=function startsWith(i,s){const u=i&&i.exec(s);return u&&0===u.index}(i.endRe,u);if(m){if(i["on:end"]){const u=new Response(i);i["on:end"](s,u),u.isMatchIgnored&&(m=!1)}if(m){for(;i.endsParent&&i.parent;)i=i.parent;return i}}if(i.endsWithParent)return endOfMode(i.parent,s,u)}function doIgnore(i){return 0===ee.matcher.regexIndex?(le+=i[0],1):(fe=!0,0)}function doBeginMatch(i){const s=i[0],u=i.rule,m=new Response(u),v=[u.__beforeBegin,u["on:begin"]];for(const u of v)if(u&&(u(i,m),m.isMatchIgnored))return doIgnore(s);return u&&u.endSameAsBegin&&(u.endRe=function escape(i){return new RegExp(i.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")}(s)),u.skip?le+=s:(u.excludeBegin&&(le+=s),processBuffer(),u.returnBegin||u.excludeBegin||(le=s)),startNewMode(u),u.returnBegin?0:s.length}function doEndMatch(i){const u=i[0],m=s.substr(i.index),v=endOfMode(ee,i,m);if(!v)return qe;const _=ee;_.skip?le+=u:(_.returnEnd||_.excludeEnd||(le+=u),processBuffer(),_.excludeEnd&&(le=u));do{ee.className&&ie.closeNode(),ee.skip||ee.subLanguage||(ce+=ee.relevance),ee=ee.parent}while(ee!==v.parent);return v.starts&&(v.endSameAsBegin&&(v.starts.endRe=v.endRe),startNewMode(v.starts)),_.returnEnd?0:u.length}let $={};function processLexeme(u,v){const j=v&&v[0];if(le+=u,null==j)return processBuffer(),0;if("begin"===$.type&&"end"===v.type&&$.index===v.index&&""===j){if(le+=s.slice(v.index,v.index+1),!_){const s=new Error("0 width match regex");throw s.languageName=i,s.badRule=$.rule,s}return 1}if($=v,"begin"===v.type)return doBeginMatch(v);if("illegal"===v.type&&!m){const i=new Error('Illegal lexeme "'+j+'" for mode "'+(ee.className||"")+'"');throw i.mode=ee,i}if("end"===v.type){const i=doEndMatch(v);if(i!==qe)return i}if("illegal"===v.type&&""===j)return 1;if(de>1e5&&de>3*v.index){throw new Error("potential infinite loop, way more iterations than matches")}return le+=j,j.length}const X=getLanguage(i);if(!X)throw error(M.replace("{}",i)),new Error('Unknown language: "'+i+'"');const Y=compileLanguage(X,{plugins:v});let Z="",ee=j||Y;const ae={},ie=new W.__emitter(W);!function processContinuations(){const i=[];for(let s=ee;s!==X;s=s.parent)s.className&&i.unshift(s.className);i.forEach((i=>ie.openNode(i)))}();let le="",ce=0,pe=0,de=0,fe=!1;try{for(ee.matcher.considerAll();;){de++,fe?fe=!1:ee.matcher.considerAll(),ee.matcher.lastIndex=pe;const i=ee.matcher.exec(s);if(!i)break;const u=processLexeme(s.substring(pe,i.index),i);pe=i.index+u}return processLexeme(s.substr(pe)),ie.closeAllNodes(),ie.finalize(),Z=ie.toHTML(),{relevance:Math.floor(ce),value:Z,language:i,illegal:!1,emitter:ie,top:ee}}catch(u){if(u.message&&u.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:u.message,context:s.slice(pe-100,pe+100),mode:u.mode},sofar:Z,relevance:0,value:Te(s),emitter:ie};if(_)return{illegal:!1,relevance:0,value:Te(s),emitter:ie,language:i,top:ee,errorRaised:u};throw u}}function highlightAuto(i,s){s=s||W.languages||Object.keys(u);const m=function justTextHighlightResult(i){const s={relevance:0,emitter:new W.__emitter(W),value:Te(i),illegal:!1,top:$};return s.emitter.addText(i),s}(i),v=s.filter(getLanguage).filter(autoDetection).map((s=>_highlight(s,i,!1)));v.unshift(m);const _=v.sort(((i,s)=>{if(i.relevance!==s.relevance)return s.relevance-i.relevance;if(i.language&&s.language){if(getLanguage(i.language).supersetOf===s.language)return 1;if(getLanguage(s.language).supersetOf===i.language)return-1}return 0})),[j,M]=_,X=j;return X.second_best=M,X}const X={"before:highlightElement":({el:i})=>{W.useBR&&(i.innerHTML=i.innerHTML.replace(/\n/g,"").replace(//g,"\n"))},"after:highlightElement":({result:i})=>{W.useBR&&(i.value=i.value.replace(/\n/g,"
"))}},Y=/^(<[^>]+>|\t)+/gm,Z={"after:highlightElement":({result:i})=>{W.tabReplace&&(i.value=i.value.replace(Y,(i=>i.replace(/\t/g,W.tabReplace))))}};function highlightElement(i){let s=null;const u=function blockLanguage(i){let s=i.className+" ";s+=i.parentNode?i.parentNode.className:"";const u=W.languageDetectRe.exec(s);if(u){const s=getLanguage(u[1]);return s||(warn(M.replace("{}",u[1])),warn("Falling back to no-highlight mode for this block.",i)),s?u[1]:"no-highlight"}return s.split(/\s+/).find((i=>shouldNotHighlight(i)||getLanguage(i)))}(i);if(shouldNotHighlight(u))return;fire("before:highlightElement",{el:i,language:u}),s=i;const v=s.textContent,_=u?highlight(v,{language:u,ignoreIllegals:!0}):highlightAuto(v);fire("after:highlightElement",{el:i,result:_,text:v}),i.innerHTML=_.value,function updateClassName(i,s,u){const v=s?m[s]:u;i.classList.add("hljs"),v&&i.classList.add(v)}(i,u,_.language),i.result={language:_.language,re:_.relevance,relavance:_.relevance},_.second_best&&(i.second_best={language:_.second_best.language,re:_.second_best.relevance,relavance:_.second_best.relevance})}const initHighlighting=()=>{if(initHighlighting.called)return;initHighlighting.called=!0,deprecated("10.6.0","initHighlighting() is deprecated. Use highlightAll() instead.");document.querySelectorAll("pre code").forEach(highlightElement)};let ee=!1;function highlightAll(){if("loading"===document.readyState)return void(ee=!0);document.querySelectorAll("pre code").forEach(highlightElement)}function getLanguage(i){return i=(i||"").toLowerCase(),u[i]||u[m[i]]}function registerAliases(i,{languageName:s}){"string"==typeof i&&(i=[i]),i.forEach((i=>{m[i.toLowerCase()]=s}))}function autoDetection(i){const s=getLanguage(i);return s&&!s.disableAutodetect}function fire(i,s){const u=i;v.forEach((function(i){i[u]&&i[u](s)}))}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(function boot(){ee&&highlightAll()}),!1),Object.assign(i,{highlight,highlightAuto,highlightAll,fixMarkup:function deprecateFixMarkup(i){return deprecated("10.2.0","fixMarkup will be removed entirely in v11.0"),deprecated("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"),function fixMarkup(i){return W.tabReplace||W.useBR?i.replace(j,(i=>"\n"===i?W.useBR?"
":i:W.tabReplace?i.replace(/\t/g,W.tabReplace):i)):i}(i)},highlightElement,highlightBlock:function deprecateHighlightBlock(i){return deprecated("10.7.0","highlightBlock will be removed entirely in v12.0"),deprecated("10.7.0","Please use highlightElement now."),highlightElement(i)},configure:function configure(i){i.useBR&&(deprecated("10.3.0","'useBR' will be removed entirely in v11.0"),deprecated("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")),W=Re(W,i)},initHighlighting,initHighlightingOnLoad:function initHighlightingOnLoad(){deprecated("10.6.0","initHighlightingOnLoad() is deprecated. Use highlightAll() instead."),ee=!0},registerLanguage:function registerLanguage(s,m){let v=null;try{v=m(i)}catch(i){if(error("Language definition for '{}' could not be registered.".replace("{}",s)),!_)throw i;error(i),v=$}v.name||(v.name=s),u[s]=v,v.rawDefinition=m.bind(null,i),v.aliases&®isterAliases(v.aliases,{languageName:s})},unregisterLanguage:function unregisterLanguage(i){delete u[i];for(const s of Object.keys(m))m[s]===i&&delete m[s]},listLanguages:function listLanguages(){return Object.keys(u)},getLanguage,registerAliases,requireLanguage:function requireLanguage(i){deprecated("10.4.0","requireLanguage will be removed entirely in v11."),deprecated("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844");const s=getLanguage(i);if(s)return s;throw new Error("The '{}' language is required, but not loaded.".replace("{}",i))},autoDetection,inherit:Re,addPlugin:function addPlugin(i){!function upgradePluginAPI(i){i["before:highlightBlock"]&&!i["before:highlightElement"]&&(i["before:highlightElement"]=s=>{i["before:highlightBlock"](Object.assign({block:s.el},s))}),i["after:highlightBlock"]&&!i["after:highlightElement"]&&(i["after:highlightElement"]=s=>{i["after:highlightBlock"](Object.assign({block:s.el},s))})}(i),v.push(i)},vuePlugin:BuildVuePlugin(i).VuePlugin}),i.debugMode=function(){_=!1},i.safeMode=function(){_=!0},i.versionString="10.7.3";for(const i in we)"object"==typeof we[i]&&s(we[i]);return Object.assign(i,we),i.addPlugin(X),i.addPlugin(Pe),i.addPlugin(Z),i}({});i.exports=ze},61519:i=>{function concat(...i){return i.map((i=>function source(i){return i?"string"==typeof i?i:i.source:null}(i))).join("")}i.exports=function bash(i){const s={},u={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[s]}]};Object.assign(s,{className:"variable",variants:[{begin:concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},u]});const m={className:"subst",begin:/\$\(/,end:/\)/,contains:[i.BACKSLASH_ESCAPE]},v={begin:/<<-?\s*(?=\w+)/,starts:{contains:[i.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},_={className:"string",begin:/"/,end:/"/,contains:[i.BACKSLASH_ESCAPE,s,m]};m.contains.push(_);const j={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},i.NUMBER_MODE,s]},M=i.SHEBANG({binary:`(${["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"].join("|")})`,relevance:10}),$={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[i.inherit(i.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp"},contains:[M,i.SHEBANG(),$,j,i.HASH_COMMENT_MODE,v,_,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}},30786:i=>{function concat(...i){return i.map((i=>function source(i){return i?"string"==typeof i?i:i.source:null}(i))).join("")}i.exports=function http(i){const s="HTTP/(2|1\\.[01])",u={className:"attribute",begin:concat("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},m=[u,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+s+" \\d{3})",end:/$/,contains:[{className:"meta",begin:s},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:m}},{begin:"(?=^[A-Z]+ (.*?) "+s+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:s},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:m}},i.inherit(u,{relevance:0})]}}},96344:i=>{const s="[A-Za-z$_][0-9A-Za-z$_]*",u=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],m=["true","false","null","undefined","NaN","Infinity"],v=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function lookahead(i){return concat("(?=",i,")")}function concat(...i){return i.map((i=>function source(i){return i?"string"==typeof i?i:i.source:null}(i))).join("")}i.exports=function javascript(i){const _=s,j="<>",M="",$={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(i,s)=>{const u=i[0].length+i.index,m=i.input[u];"<"!==m?">"===m&&(((i,{after:s})=>{const u="",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:i.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:W,contains:ye}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:j,end:M},{begin:$.begin,"on:begin":$.isTrulyOpeningTag,end:$.end}],subLanguage:"xml",contains:[{begin:$.begin,end:$.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:W,contains:["self",i.inherit(i.TITLE_MODE,{begin:_}),be],illegal:/%/},{beginKeywords:"while if switch catch for"},{className:"function",begin:i.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,contains:[be,i.inherit(i.TITLE_MODE,{begin:_})]},{variants:[{begin:"\\."+_},{begin:"\\$"+_}],relevance:0},{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{beginKeywords:"extends"},i.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,end:/[{;]/,excludeEnd:!0,contains:[i.inherit(i.TITLE_MODE,{begin:_}),"self",be]},{begin:"(get|set)\\s+(?="+_+"\\()",end:/\{/,keywords:"get set",contains:[i.inherit(i.TITLE_MODE,{begin:_}),{begin:/\(\)/},be]},{begin:/\$[(.]/}]}}},82026:i=>{i.exports=function json(i){const s={literal:"true false null"},u=[i.C_LINE_COMMENT_MODE,i.C_BLOCK_COMMENT_MODE],m=[i.QUOTE_STRING_MODE,i.C_NUMBER_MODE],v={end:",",endsWithParent:!0,excludeEnd:!0,contains:m,keywords:s},_={begin:/\{/,end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/,contains:[i.BACKSLASH_ESCAPE],illegal:"\\n"},i.inherit(v,{begin:/:/})].concat(u),illegal:"\\S"},j={begin:"\\[",end:"\\]",contains:[i.inherit(v)],illegal:"\\S"};return m.push(_,j),u.forEach((function(i){m.push(i)})),{name:"JSON",contains:m,keywords:s,illegal:"\\S"}}},66336:i=>{i.exports=function powershell(i){const s={$pattern:/-?[A-z\.\-]+\b/,keyword:"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter",built_in:"ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write"},u={begin:"`[\\s\\S]",relevance:0},m={className:"variable",variants:[{begin:/\$\B/},{className:"keyword",begin:/\$this/},{begin:/\$[\w\d][\w\d_:]*/}]},v={className:"string",variants:[{begin:/"/,end:/"/},{begin:/@"/,end:/^"@/}],contains:[u,m,{className:"variable",begin:/\$[A-z]/,end:/[^A-z]/}]},_={className:"string",variants:[{begin:/'/,end:/'/},{begin:/@'/,end:/^'@/}]},j=i.inherit(i.COMMENT(null,null),{variants:[{begin:/#/,end:/$/},{begin:/<#/,end:/#>/}],contains:[{className:"doctag",variants:[{begin:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{begin:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/}]}]}),M={className:"built_in",variants:[{begin:"(".concat("Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where",")+(-)[\\w\\d]+")}]},$={className:"class",beginKeywords:"class enum",end:/\s*[{]/,excludeEnd:!0,relevance:0,contains:[i.TITLE_MODE]},W={className:"function",begin:/function\s+/,end:/\s*\{|$/,excludeEnd:!0,returnBegin:!0,relevance:0,contains:[{begin:"function",relevance:0,className:"keyword"},{className:"title",begin:/\w[\w\d]*((-)[\w\d]+)*/,relevance:0},{begin:/\(/,end:/\)/,className:"params",relevance:0,contains:[m]}]},X={begin:/using\s/,end:/$/,returnBegin:!0,contains:[v,_,{className:"keyword",begin:/(using|assembly|command|module|namespace|type)/}]},Y={variants:[{className:"operator",begin:"(".concat("-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor",")\\b")},{className:"literal",begin:/(-)[\w\d]+/,relevance:0}]},Z={className:"function",begin:/\[.*\]\s*[\w]+[ ]??\(/,end:/$/,returnBegin:!0,relevance:0,contains:[{className:"keyword",begin:"(".concat(s.keyword.toString().replace(/\s/g,"|"),")\\b"),endsParent:!0,relevance:0},i.inherit(i.TITLE_MODE,{endsParent:!0})]},ee=[Z,j,u,i.NUMBER_MODE,v,_,M,m,{className:"literal",begin:/\$(null|true|false)\b/},{className:"selector-tag",begin:/@\B/,relevance:0}],ae={begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[].concat("self",ee,{begin:"("+["string","char","byte","int","long","bool","decimal","single","double","DateTime","xml","array","hashtable","void"].join("|")+")",className:"built_in",relevance:0},{className:"type",begin:/[\.\w\d]+/,relevance:0})};return Z.contains.unshift(ae),{name:"PowerShell",aliases:["ps","ps1"],case_insensitive:!0,keywords:s,contains:ee.concat($,W,X,Y,ae)}}},42157:i=>{function source(i){return i?"string"==typeof i?i:i.source:null}function lookahead(i){return concat("(?=",i,")")}function concat(...i){return i.map((i=>source(i))).join("")}function either(...i){return"("+i.map((i=>source(i))).join("|")+")"}i.exports=function xml(i){const s=concat(/[A-Z_]/,function optional(i){return concat("(",i,")?")}(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),u={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},m={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},v=i.inherit(m,{begin:/\(/,end:/\)/}),_=i.inherit(i.APOS_STRING_MODE,{className:"meta-string"}),j=i.inherit(i.QUOTE_STRING_MODE,{className:"meta-string"}),M={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[m,j,_,v,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[m,v,j,_]}]}]},i.COMMENT(//,{relevance:10}),{begin://,relevance:10},u,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[M],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[M],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:s,relevance:0,starts:M}]},{className:"tag",begin:concat(/<\//,lookahead(concat(s,/>/))),contains:[{className:"name",begin:s,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}},54587:i=>{i.exports=function yaml(i){var s="true false yes no null",u="[\\w#;/?:@&=+$,.~*'()[\\]]+",m={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[i.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},v=i.inherit(m,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),_={className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},j={end:",",endsWithParent:!0,excludeEnd:!0,keywords:s,relevance:0},M={begin:/\{/,end:/\}/,contains:[j],illegal:"\\n",relevance:0},$={begin:"\\[",end:"\\]",contains:[j],illegal:"\\n",relevance:0},W=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+u},{className:"type",begin:"!<"+u+">"},{className:"type",begin:"!"+u},{className:"type",begin:"!!"+u},{className:"meta",begin:"&"+i.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+i.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},i.HASH_COMMENT_MODE,{beginKeywords:s,keywords:{literal:s}},_,{className:"number",begin:i.C_NUMBER_RE+"\\b",relevance:0},M,$,m],X=[...W];return X.pop(),X.push(v),j.contains=X,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:W}}},8679:(i,s,u)=>{"use strict";var m=u(59864),v={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},_={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},j={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},M={};function getStatics(i){return m.isMemo(i)?j:M[i.$$typeof]||v}M[m.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},M[m.Memo]=j;var $=Object.defineProperty,W=Object.getOwnPropertyNames,X=Object.getOwnPropertySymbols,Y=Object.getOwnPropertyDescriptor,Z=Object.getPrototypeOf,ee=Object.prototype;i.exports=function hoistNonReactStatics(i,s,u){if("string"!=typeof s){if(ee){var m=Z(s);m&&m!==ee&&hoistNonReactStatics(i,m,u)}var v=W(s);X&&(v=v.concat(X(s)));for(var j=getStatics(i),M=getStatics(s),ae=0;ae{s.read=function(i,s,u,m,v){var _,j,M=8*v-m-1,$=(1<>1,X=-7,Y=u?v-1:0,Z=u?-1:1,ee=i[s+Y];for(Y+=Z,_=ee&(1<<-X)-1,ee>>=-X,X+=M;X>0;_=256*_+i[s+Y],Y+=Z,X-=8);for(j=_&(1<<-X)-1,_>>=-X,X+=m;X>0;j=256*j+i[s+Y],Y+=Z,X-=8);if(0===_)_=1-W;else{if(_===$)return j?NaN:1/0*(ee?-1:1);j+=Math.pow(2,m),_-=W}return(ee?-1:1)*j*Math.pow(2,_-m)},s.write=function(i,s,u,m,v,_){var j,M,$,W=8*_-v-1,X=(1<>1,Z=23===v?Math.pow(2,-24)-Math.pow(2,-77):0,ee=m?0:_-1,ae=m?1:-1,ie=s<0||0===s&&1/s<0?1:0;for(s=Math.abs(s),isNaN(s)||s===1/0?(M=isNaN(s)?1:0,j=X):(j=Math.floor(Math.log(s)/Math.LN2),s*($=Math.pow(2,-j))<1&&(j--,$*=2),(s+=j+Y>=1?Z/$:Z*Math.pow(2,1-Y))*$>=2&&(j++,$/=2),j+Y>=X?(M=0,j=X):j+Y>=1?(M=(s*$-1)*Math.pow(2,v),j+=Y):(M=s*Math.pow(2,Y-1)*Math.pow(2,v),j=0));v>=8;i[u+ee]=255&M,ee+=ae,M/=256,v-=8);for(j=j<0;i[u+ee]=255&j,ee+=ae,j/=256,W-=8);i[u+ee-ae]|=128*ie}},43393:function(i){i.exports=function(){"use strict";var i=Array.prototype.slice;function createClass(i,s){s&&(i.prototype=Object.create(s.prototype)),i.prototype.constructor=i}function Iterable(i){return isIterable(i)?i:Seq(i)}function KeyedIterable(i){return isKeyed(i)?i:KeyedSeq(i)}function IndexedIterable(i){return isIndexed(i)?i:IndexedSeq(i)}function SetIterable(i){return isIterable(i)&&!isAssociative(i)?i:SetSeq(i)}function isIterable(i){return!(!i||!i[s])}function isKeyed(i){return!(!i||!i[u])}function isIndexed(i){return!(!i||!i[m])}function isAssociative(i){return isKeyed(i)||isIndexed(i)}function isOrdered(i){return!(!i||!i[v])}createClass(KeyedIterable,Iterable),createClass(IndexedIterable,Iterable),createClass(SetIterable,Iterable),Iterable.isIterable=isIterable,Iterable.isKeyed=isKeyed,Iterable.isIndexed=isIndexed,Iterable.isAssociative=isAssociative,Iterable.isOrdered=isOrdered,Iterable.Keyed=KeyedIterable,Iterable.Indexed=IndexedIterable,Iterable.Set=SetIterable;var s="@@__IMMUTABLE_ITERABLE__@@",u="@@__IMMUTABLE_KEYED__@@",m="@@__IMMUTABLE_INDEXED__@@",v="@@__IMMUTABLE_ORDERED__@@",_="delete",j=5,M=1<>>0;if(""+u!==s||4294967295===u)return NaN;s=u}return s<0?ensureSize(i)+s:s}function returnTrue(){return!0}function wholeSlice(i,s,u){return(0===i||void 0!==u&&i<=-u)&&(void 0===s||void 0!==u&&s>=u)}function resolveBegin(i,s){return resolveIndex(i,s,0)}function resolveEnd(i,s){return resolveIndex(i,s,s)}function resolveIndex(i,s,u){return void 0===i?u:i<0?Math.max(0,s+i):void 0===s?i:Math.min(s,i)}var Z=0,ee=1,ae=2,ie="function"==typeof Symbol&&Symbol.iterator,le="@@iterator",ce=ie||le;function Iterator(i){this.next=i}function iteratorValue(i,s,u,m){var v=0===i?s:1===i?u:[s,u];return m?m.value=v:m={value:v,done:!1},m}function iteratorDone(){return{value:void 0,done:!0}}function hasIterator(i){return!!getIteratorFn(i)}function isIterator(i){return i&&"function"==typeof i.next}function getIterator(i){var s=getIteratorFn(i);return s&&s.call(i)}function getIteratorFn(i){var s=i&&(ie&&i[ie]||i[le]);if("function"==typeof s)return s}function isArrayLike(i){return i&&"number"==typeof i.length}function Seq(i){return null==i?emptySequence():isIterable(i)?i.toSeq():seqFromValue(i)}function KeyedSeq(i){return null==i?emptySequence().toKeyedSeq():isIterable(i)?isKeyed(i)?i.toSeq():i.fromEntrySeq():keyedSeqFromValue(i)}function IndexedSeq(i){return null==i?emptySequence():isIterable(i)?isKeyed(i)?i.entrySeq():i.toIndexedSeq():indexedSeqFromValue(i)}function SetSeq(i){return(null==i?emptySequence():isIterable(i)?isKeyed(i)?i.entrySeq():i:indexedSeqFromValue(i)).toSetSeq()}Iterator.prototype.toString=function(){return"[Iterator]"},Iterator.KEYS=Z,Iterator.VALUES=ee,Iterator.ENTRIES=ae,Iterator.prototype.inspect=Iterator.prototype.toSource=function(){return this.toString()},Iterator.prototype[ce]=function(){return this},createClass(Seq,Iterable),Seq.of=function(){return Seq(arguments)},Seq.prototype.toSeq=function(){return this},Seq.prototype.toString=function(){return this.__toString("Seq {","}")},Seq.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},Seq.prototype.__iterate=function(i,s){return seqIterate(this,i,s,!0)},Seq.prototype.__iterator=function(i,s){return seqIterator(this,i,s,!0)},createClass(KeyedSeq,Seq),KeyedSeq.prototype.toKeyedSeq=function(){return this},createClass(IndexedSeq,Seq),IndexedSeq.of=function(){return IndexedSeq(arguments)},IndexedSeq.prototype.toIndexedSeq=function(){return this},IndexedSeq.prototype.toString=function(){return this.__toString("Seq [","]")},IndexedSeq.prototype.__iterate=function(i,s){return seqIterate(this,i,s,!1)},IndexedSeq.prototype.__iterator=function(i,s){return seqIterator(this,i,s,!1)},createClass(SetSeq,Seq),SetSeq.of=function(){return SetSeq(arguments)},SetSeq.prototype.toSetSeq=function(){return this},Seq.isSeq=isSeq,Seq.Keyed=KeyedSeq,Seq.Set=SetSeq,Seq.Indexed=IndexedSeq;var pe,de,fe,ye="@@__IMMUTABLE_SEQ__@@";function ArraySeq(i){this._array=i,this.size=i.length}function ObjectSeq(i){var s=Object.keys(i);this._object=i,this._keys=s,this.size=s.length}function IterableSeq(i){this._iterable=i,this.size=i.length||i.size}function IteratorSeq(i){this._iterator=i,this._iteratorCache=[]}function isSeq(i){return!(!i||!i[ye])}function emptySequence(){return pe||(pe=new ArraySeq([]))}function keyedSeqFromValue(i){var s=Array.isArray(i)?new ArraySeq(i).fromEntrySeq():isIterator(i)?new IteratorSeq(i).fromEntrySeq():hasIterator(i)?new IterableSeq(i).fromEntrySeq():"object"==typeof i?new ObjectSeq(i):void 0;if(!s)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+i);return s}function indexedSeqFromValue(i){var s=maybeIndexedSeqFromValue(i);if(!s)throw new TypeError("Expected Array or iterable object of values: "+i);return s}function seqFromValue(i){var s=maybeIndexedSeqFromValue(i)||"object"==typeof i&&new ObjectSeq(i);if(!s)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+i);return s}function maybeIndexedSeqFromValue(i){return isArrayLike(i)?new ArraySeq(i):isIterator(i)?new IteratorSeq(i):hasIterator(i)?new IterableSeq(i):void 0}function seqIterate(i,s,u,m){var v=i._cache;if(v){for(var _=v.length-1,j=0;j<=_;j++){var M=v[u?_-j:j];if(!1===s(M[1],m?M[0]:j,i))return j+1}return j}return i.__iterateUncached(s,u)}function seqIterator(i,s,u,m){var v=i._cache;if(v){var _=v.length-1,j=0;return new Iterator((function(){var i=v[u?_-j:j];return j++>_?iteratorDone():iteratorValue(s,m?i[0]:j-1,i[1])}))}return i.__iteratorUncached(s,u)}function fromJS(i,s){return s?fromJSWith(s,i,"",{"":i}):fromJSDefault(i)}function fromJSWith(i,s,u,m){return Array.isArray(s)?i.call(m,u,IndexedSeq(s).map((function(u,m){return fromJSWith(i,u,m,s)}))):isPlainObj(s)?i.call(m,u,KeyedSeq(s).map((function(u,m){return fromJSWith(i,u,m,s)}))):s}function fromJSDefault(i){return Array.isArray(i)?IndexedSeq(i).map(fromJSDefault).toList():isPlainObj(i)?KeyedSeq(i).map(fromJSDefault).toMap():i}function isPlainObj(i){return i&&(i.constructor===Object||void 0===i.constructor)}function is(i,s){if(i===s||i!=i&&s!=s)return!0;if(!i||!s)return!1;if("function"==typeof i.valueOf&&"function"==typeof s.valueOf){if((i=i.valueOf())===(s=s.valueOf())||i!=i&&s!=s)return!0;if(!i||!s)return!1}return!("function"!=typeof i.equals||"function"!=typeof s.equals||!i.equals(s))}function deepEqual(i,s){if(i===s)return!0;if(!isIterable(s)||void 0!==i.size&&void 0!==s.size&&i.size!==s.size||void 0!==i.__hash&&void 0!==s.__hash&&i.__hash!==s.__hash||isKeyed(i)!==isKeyed(s)||isIndexed(i)!==isIndexed(s)||isOrdered(i)!==isOrdered(s))return!1;if(0===i.size&&0===s.size)return!0;var u=!isAssociative(i);if(isOrdered(i)){var m=i.entries();return s.every((function(i,s){var v=m.next().value;return v&&is(v[1],i)&&(u||is(v[0],s))}))&&m.next().done}var v=!1;if(void 0===i.size)if(void 0===s.size)"function"==typeof i.cacheResult&&i.cacheResult();else{v=!0;var _=i;i=s,s=_}var j=!0,M=s.__iterate((function(s,m){if(u?!i.has(s):v?!is(s,i.get(m,W)):!is(i.get(m,W),s))return j=!1,!1}));return j&&i.size===M}function Repeat(i,s){if(!(this instanceof Repeat))return new Repeat(i,s);if(this._value=i,this.size=void 0===s?1/0:Math.max(0,s),0===this.size){if(de)return de;de=this}}function invariant(i,s){if(!i)throw new Error(s)}function Range(i,s,u){if(!(this instanceof Range))return new Range(i,s,u);if(invariant(0!==u,"Cannot step a Range by 0"),i=i||0,void 0===s&&(s=1/0),u=void 0===u?1:Math.abs(u),sm?iteratorDone():iteratorValue(i,v,u[s?m-v++:v++])}))},createClass(ObjectSeq,KeyedSeq),ObjectSeq.prototype.get=function(i,s){return void 0===s||this.has(i)?this._object[i]:s},ObjectSeq.prototype.has=function(i){return this._object.hasOwnProperty(i)},ObjectSeq.prototype.__iterate=function(i,s){for(var u=this._object,m=this._keys,v=m.length-1,_=0;_<=v;_++){var j=m[s?v-_:_];if(!1===i(u[j],j,this))return _+1}return _},ObjectSeq.prototype.__iterator=function(i,s){var u=this._object,m=this._keys,v=m.length-1,_=0;return new Iterator((function(){var j=m[s?v-_:_];return _++>v?iteratorDone():iteratorValue(i,j,u[j])}))},ObjectSeq.prototype[v]=!0,createClass(IterableSeq,IndexedSeq),IterableSeq.prototype.__iterateUncached=function(i,s){if(s)return this.cacheResult().__iterate(i,s);var u=getIterator(this._iterable),m=0;if(isIterator(u))for(var v;!(v=u.next()).done&&!1!==i(v.value,m++,this););return m},IterableSeq.prototype.__iteratorUncached=function(i,s){if(s)return this.cacheResult().__iterator(i,s);var u=getIterator(this._iterable);if(!isIterator(u))return new Iterator(iteratorDone);var m=0;return new Iterator((function(){var s=u.next();return s.done?s:iteratorValue(i,m++,s.value)}))},createClass(IteratorSeq,IndexedSeq),IteratorSeq.prototype.__iterateUncached=function(i,s){if(s)return this.cacheResult().__iterate(i,s);for(var u,m=this._iterator,v=this._iteratorCache,_=0;_=m.length){var s=u.next();if(s.done)return s;m[v]=s.value}return iteratorValue(i,v,m[v++])}))},createClass(Repeat,IndexedSeq),Repeat.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Repeat.prototype.get=function(i,s){return this.has(i)?this._value:s},Repeat.prototype.includes=function(i){return is(this._value,i)},Repeat.prototype.slice=function(i,s){var u=this.size;return wholeSlice(i,s,u)?this:new Repeat(this._value,resolveEnd(s,u)-resolveBegin(i,u))},Repeat.prototype.reverse=function(){return this},Repeat.prototype.indexOf=function(i){return is(this._value,i)?0:-1},Repeat.prototype.lastIndexOf=function(i){return is(this._value,i)?this.size:-1},Repeat.prototype.__iterate=function(i,s){for(var u=0;u=0&&s=0&&uu?iteratorDone():iteratorValue(i,_++,j)}))},Range.prototype.equals=function(i){return i instanceof Range?this._start===i._start&&this._end===i._end&&this._step===i._step:deepEqual(this,i)},createClass(Collection,Iterable),createClass(KeyedCollection,Collection),createClass(IndexedCollection,Collection),createClass(SetCollection,Collection),Collection.Keyed=KeyedCollection,Collection.Indexed=IndexedCollection,Collection.Set=SetCollection;var be="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function imul(i,s){var u=65535&(i|=0),m=65535&(s|=0);return u*m+((i>>>16)*m+u*(s>>>16)<<16>>>0)|0};function smi(i){return i>>>1&1073741824|3221225471&i}function hash(i){if(!1===i||null==i)return 0;if("function"==typeof i.valueOf&&(!1===(i=i.valueOf())||null==i))return 0;if(!0===i)return 1;var s=typeof i;if("number"===s){if(i!=i||i===1/0)return 0;var u=0|i;for(u!==i&&(u^=4294967295*i);i>4294967295;)u^=i/=4294967295;return smi(u)}if("string"===s)return i.length>Te?cachedHashString(i):hashString(i);if("function"==typeof i.hashCode)return i.hashCode();if("object"===s)return hashJSObj(i);if("function"==typeof i.toString)return hashString(i.toString());throw new Error("Value type "+s+" cannot be hashed.")}function cachedHashString(i){var s=ze[i];return void 0===s&&(s=hashString(i),qe===Re&&(qe=0,ze={}),qe++,ze[i]=s),s}function hashString(i){for(var s=0,u=0;u0)switch(i.nodeType){case 1:return i.uniqueID;case 9:return i.documentElement&&i.documentElement.uniqueID}}var Se,xe="function"==typeof WeakMap;xe&&(Se=new WeakMap);var Pe=0,Ie="__immutablehash__";"function"==typeof Symbol&&(Ie=Symbol(Ie));var Te=16,Re=255,qe=0,ze={};function assertNotInfinite(i){invariant(i!==1/0,"Cannot perform this action with an infinite size.")}function Map(i){return null==i?emptyMap():isMap(i)&&!isOrdered(i)?i:emptyMap().withMutations((function(s){var u=KeyedIterable(i);assertNotInfinite(u.size),u.forEach((function(i,u){return s.set(u,i)}))}))}function isMap(i){return!(!i||!i[We])}createClass(Map,KeyedCollection),Map.of=function(){var s=i.call(arguments,0);return emptyMap().withMutations((function(i){for(var u=0;u=s.length)throw new Error("Missing value for key: "+s[u]);i.set(s[u],s[u+1])}}))},Map.prototype.toString=function(){return this.__toString("Map {","}")},Map.prototype.get=function(i,s){return this._root?this._root.get(0,void 0,i,s):s},Map.prototype.set=function(i,s){return updateMap(this,i,s)},Map.prototype.setIn=function(i,s){return this.updateIn(i,W,(function(){return s}))},Map.prototype.remove=function(i){return updateMap(this,i,W)},Map.prototype.deleteIn=function(i){return this.updateIn(i,(function(){return W}))},Map.prototype.update=function(i,s,u){return 1===arguments.length?i(this):this.updateIn([i],s,u)},Map.prototype.updateIn=function(i,s,u){u||(u=s,s=void 0);var m=updateInDeepMap(this,forceIterator(i),s,u);return m===W?void 0:m},Map.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):emptyMap()},Map.prototype.merge=function(){return mergeIntoMapWith(this,void 0,arguments)},Map.prototype.mergeWith=function(s){return mergeIntoMapWith(this,s,i.call(arguments,1))},Map.prototype.mergeIn=function(s){var u=i.call(arguments,1);return this.updateIn(s,emptyMap(),(function(i){return"function"==typeof i.merge?i.merge.apply(i,u):u[u.length-1]}))},Map.prototype.mergeDeep=function(){return mergeIntoMapWith(this,deepMerger,arguments)},Map.prototype.mergeDeepWith=function(s){var u=i.call(arguments,1);return mergeIntoMapWith(this,deepMergerWith(s),u)},Map.prototype.mergeDeepIn=function(s){var u=i.call(arguments,1);return this.updateIn(s,emptyMap(),(function(i){return"function"==typeof i.mergeDeep?i.mergeDeep.apply(i,u):u[u.length-1]}))},Map.prototype.sort=function(i){return OrderedMap(sortFactory(this,i))},Map.prototype.sortBy=function(i,s){return OrderedMap(sortFactory(this,s,i))},Map.prototype.withMutations=function(i){var s=this.asMutable();return i(s),s.wasAltered()?s.__ensureOwner(this.__ownerID):this},Map.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new OwnerID)},Map.prototype.asImmutable=function(){return this.__ensureOwner()},Map.prototype.wasAltered=function(){return this.__altered},Map.prototype.__iterator=function(i,s){return new MapIterator(this,i,s)},Map.prototype.__iterate=function(i,s){var u=this,m=0;return this._root&&this._root.iterate((function(s){return m++,i(s[1],s[0],u)}),s),m},Map.prototype.__ensureOwner=function(i){return i===this.__ownerID?this:i?makeMap(this.size,this._root,i,this.__hash):(this.__ownerID=i,this.__altered=!1,this)},Map.isMap=isMap;var Ve,We="@@__IMMUTABLE_MAP__@@",He=Map.prototype;function ArrayMapNode(i,s){this.ownerID=i,this.entries=s}function BitmapIndexedNode(i,s,u){this.ownerID=i,this.bitmap=s,this.nodes=u}function HashArrayMapNode(i,s,u){this.ownerID=i,this.count=s,this.nodes=u}function HashCollisionNode(i,s,u){this.ownerID=i,this.keyHash=s,this.entries=u}function ValueNode(i,s,u){this.ownerID=i,this.keyHash=s,this.entry=u}function MapIterator(i,s,u){this._type=s,this._reverse=u,this._stack=i._root&&mapIteratorFrame(i._root)}function mapIteratorValue(i,s){return iteratorValue(i,s[0],s[1])}function mapIteratorFrame(i,s){return{node:i,index:0,__prev:s}}function makeMap(i,s,u,m){var v=Object.create(He);return v.size=i,v._root=s,v.__ownerID=u,v.__hash=m,v.__altered=!1,v}function emptyMap(){return Ve||(Ve=makeMap(0))}function updateMap(i,s,u){var m,v;if(i._root){var _=MakeRef(X),j=MakeRef(Y);if(m=updateNode(i._root,i.__ownerID,0,void 0,s,u,_,j),!j.value)return i;v=i.size+(_.value?u===W?-1:1:0)}else{if(u===W)return i;v=1,m=new ArrayMapNode(i.__ownerID,[[s,u]])}return i.__ownerID?(i.size=v,i._root=m,i.__hash=void 0,i.__altered=!0,i):m?makeMap(v,m):emptyMap()}function updateNode(i,s,u,m,v,_,j,M){return i?i.update(s,u,m,v,_,j,M):_===W?i:(SetRef(M),SetRef(j),new ValueNode(s,m,[v,_]))}function isLeafNode(i){return i.constructor===ValueNode||i.constructor===HashCollisionNode}function mergeIntoNode(i,s,u,m,v){if(i.keyHash===m)return new HashCollisionNode(s,m,[i.entry,v]);var _,M=(0===u?i.keyHash:i.keyHash>>>u)&$,W=(0===u?m:m>>>u)&$;return new BitmapIndexedNode(s,1<>>=1)j[$]=1&u?s[_++]:void 0;return j[m]=v,new HashArrayMapNode(i,_+1,j)}function mergeIntoMapWith(i,s,u){for(var m=[],v=0;v>1&1431655765))+(i>>2&858993459))+(i>>4)&252645135,i+=i>>8,127&(i+=i>>16)}function setIn(i,s,u,m){var v=m?i:arrCopy(i);return v[s]=u,v}function spliceIn(i,s,u,m){var v=i.length+1;if(m&&s+1===v)return i[s]=u,i;for(var _=new Array(v),j=0,M=0;M=Xe)return createNodes(i,$,m,v);var ee=i&&i===this.ownerID,ae=ee?$:arrCopy($);return Z?M?X===Y-1?ae.pop():ae[X]=ae.pop():ae[X]=[m,v]:ae.push([m,v]),ee?(this.entries=ae,this):new ArrayMapNode(i,ae)}},BitmapIndexedNode.prototype.get=function(i,s,u,m){void 0===s&&(s=hash(u));var v=1<<((0===i?s:s>>>i)&$),_=this.bitmap;return 0==(_&v)?m:this.nodes[popCount(_&v-1)].get(i+j,s,u,m)},BitmapIndexedNode.prototype.update=function(i,s,u,m,v,_,M){void 0===u&&(u=hash(m));var X=(0===s?u:u>>>s)&$,Y=1<=Ye)return expandNodes(i,ie,Z,X,ce);if(ee&&!ce&&2===ie.length&&isLeafNode(ie[1^ae]))return ie[1^ae];if(ee&&ce&&1===ie.length&&isLeafNode(ce))return ce;var pe=i&&i===this.ownerID,de=ee?ce?Z:Z^Y:Z|Y,fe=ee?ce?setIn(ie,ae,ce,pe):spliceOut(ie,ae,pe):spliceIn(ie,ae,ce,pe);return pe?(this.bitmap=de,this.nodes=fe,this):new BitmapIndexedNode(i,de,fe)},HashArrayMapNode.prototype.get=function(i,s,u,m){void 0===s&&(s=hash(u));var v=(0===i?s:s>>>i)&$,_=this.nodes[v];return _?_.get(i+j,s,u,m):m},HashArrayMapNode.prototype.update=function(i,s,u,m,v,_,M){void 0===u&&(u=hash(m));var X=(0===s?u:u>>>s)&$,Y=v===W,Z=this.nodes,ee=Z[X];if(Y&&!ee)return this;var ae=updateNode(ee,i,s+j,u,m,v,_,M);if(ae===ee)return this;var ie=this.count;if(ee){if(!ae&&--ie0&&m=0&&i>>s&$;if(m>=this.array.length)return new VNode([],i);var v,_=0===m;if(s>0){var M=this.array[m];if((v=M&&M.removeBefore(i,s-j,u))===M&&_)return this}if(_&&!v)return this;var W=editableVNode(this,i);if(!_)for(var X=0;X>>s&$;if(v>=this.array.length)return this;if(s>0){var _=this.array[v];if((m=_&&_.removeAfter(i,s-j,u))===_&&v===this.array.length-1)return this}var M=editableVNode(this,i);return M.array.splice(v+1),m&&(M.array[v]=m),M};var rt,nt,ot={};function iterateList(i,s){var u=i._origin,m=i._capacity,v=getTailOffset(m),_=i._tail;return iterateNodeOrLeaf(i._root,i._level,0);function iterateNodeOrLeaf(i,s,u){return 0===s?iterateLeaf(i,u):iterateNode(i,s,u)}function iterateLeaf(i,j){var $=j===v?_&&_.array:i&&i.array,W=j>u?0:u-j,X=m-j;return X>M&&(X=M),function(){if(W===X)return ot;var i=s?--X:W++;return $&&$[i]}}function iterateNode(i,v,_){var $,W=i&&i.array,X=_>u?0:u-_>>v,Y=1+(m-_>>v);return Y>M&&(Y=M),function(){for(;;){if($){var i=$();if(i!==ot)return i;$=null}if(X===Y)return ot;var u=s?--Y:X++;$=iterateNodeOrLeaf(W&&W[u],v-j,_+(u<=i.size||s<0)return i.withMutations((function(i){s<0?setListBounds(i,s).set(0,u):setListBounds(i,0,s+1).set(s,u)}));s+=i._origin;var m=i._tail,v=i._root,_=MakeRef(Y);return s>=getTailOffset(i._capacity)?m=updateVNode(m,i.__ownerID,0,s,u,_):v=updateVNode(v,i.__ownerID,i._level,s,u,_),_.value?i.__ownerID?(i._root=v,i._tail=m,i.__hash=void 0,i.__altered=!0,i):makeList(i._origin,i._capacity,i._level,v,m):i}function updateVNode(i,s,u,m,v,_){var M,W=m>>>u&$,X=i&&W0){var Y=i&&i.array[W],Z=updateVNode(Y,s,u-j,m,v,_);return Z===Y?i:((M=editableVNode(i,s)).array[W]=Z,M)}return X&&i.array[W]===v?i:(SetRef(_),M=editableVNode(i,s),void 0===v&&W===M.array.length-1?M.array.pop():M.array[W]=v,M)}function editableVNode(i,s){return s&&i&&s===i.ownerID?i:new VNode(i?i.array.slice():[],s)}function listNodeFor(i,s){if(s>=getTailOffset(i._capacity))return i._tail;if(s<1<0;)u=u.array[s>>>m&$],m-=j;return u}}function setListBounds(i,s,u){void 0!==s&&(s|=0),void 0!==u&&(u|=0);var m=i.__ownerID||new OwnerID,v=i._origin,_=i._capacity,M=v+s,W=void 0===u?_:u<0?_+u:v+u;if(M===v&&W===_)return i;if(M>=W)return i.clear();for(var X=i._level,Y=i._root,Z=0;M+Z<0;)Y=new VNode(Y&&Y.array.length?[void 0,Y]:[],m),Z+=1<<(X+=j);Z&&(M+=Z,v+=Z,W+=Z,_+=Z);for(var ee=getTailOffset(_),ae=getTailOffset(W);ae>=1<ee?new VNode([],m):ie;if(ie&&ae>ee&&M<_&&ie.array.length){for(var ce=Y=editableVNode(Y,m),pe=X;pe>j;pe-=j){var de=ee>>>pe&$;ce=ce.array[de]=editableVNode(ce.array[de],m)}ce.array[ee>>>j&$]=ie}if(W<_&&(le=le&&le.removeAfter(m,0,W)),M>=ae)M-=ae,W-=ae,X=j,Y=null,le=le&&le.removeBefore(m,0,M);else if(M>v||ae>>X&$;if(fe!==ae>>>X&$)break;fe&&(Z+=(1<v&&(Y=Y.removeBefore(m,X,M-Z)),Y&&aev&&(v=M.size),isIterable(j)||(M=M.map((function(i){return fromJS(i)}))),m.push(M)}return v>i.size&&(i=i.setSize(v)),mergeIntoCollectionWith(i,s,m)}function getTailOffset(i){return i>>j<=M&&j.size>=2*_.size?(m=(v=j.filter((function(i,s){return void 0!==i&&$!==s}))).toKeyedSeq().map((function(i){return i[0]})).flip().toMap(),i.__ownerID&&(m.__ownerID=v.__ownerID=i.__ownerID)):(m=_.remove(s),v=$===j.size-1?j.pop():j.set($,void 0))}else if(X){if(u===j.get($)[1])return i;m=_,v=j.set($,[s,u])}else m=_.set(s,j.size),v=j.set(j.size,[s,u]);return i.__ownerID?(i.size=m.size,i._map=m,i._list=v,i.__hash=void 0,i):makeOrderedMap(m,v)}function ToKeyedSequence(i,s){this._iter=i,this._useKeys=s,this.size=i.size}function ToIndexedSequence(i){this._iter=i,this.size=i.size}function ToSetSequence(i){this._iter=i,this.size=i.size}function FromEntriesSequence(i){this._iter=i,this.size=i.size}function flipFactory(i){var s=makeSequence(i);return s._iter=i,s.size=i.size,s.flip=function(){return i},s.reverse=function(){var s=i.reverse.apply(this);return s.flip=function(){return i.reverse()},s},s.has=function(s){return i.includes(s)},s.includes=function(s){return i.has(s)},s.cacheResult=cacheResultThrough,s.__iterateUncached=function(s,u){var m=this;return i.__iterate((function(i,u){return!1!==s(u,i,m)}),u)},s.__iteratorUncached=function(s,u){if(s===ae){var m=i.__iterator(s,u);return new Iterator((function(){var i=m.next();if(!i.done){var s=i.value[0];i.value[0]=i.value[1],i.value[1]=s}return i}))}return i.__iterator(s===ee?Z:ee,u)},s}function mapFactory(i,s,u){var m=makeSequence(i);return m.size=i.size,m.has=function(s){return i.has(s)},m.get=function(m,v){var _=i.get(m,W);return _===W?v:s.call(u,_,m,i)},m.__iterateUncached=function(m,v){var _=this;return i.__iterate((function(i,v,j){return!1!==m(s.call(u,i,v,j),v,_)}),v)},m.__iteratorUncached=function(m,v){var _=i.__iterator(ae,v);return new Iterator((function(){var v=_.next();if(v.done)return v;var j=v.value,M=j[0];return iteratorValue(m,M,s.call(u,j[1],M,i),v)}))},m}function reverseFactory(i,s){var u=makeSequence(i);return u._iter=i,u.size=i.size,u.reverse=function(){return i},i.flip&&(u.flip=function(){var s=flipFactory(i);return s.reverse=function(){return i.flip()},s}),u.get=function(u,m){return i.get(s?u:-1-u,m)},u.has=function(u){return i.has(s?u:-1-u)},u.includes=function(s){return i.includes(s)},u.cacheResult=cacheResultThrough,u.__iterate=function(s,u){var m=this;return i.__iterate((function(i,u){return s(i,u,m)}),!u)},u.__iterator=function(s,u){return i.__iterator(s,!u)},u}function filterFactory(i,s,u,m){var v=makeSequence(i);return m&&(v.has=function(m){var v=i.get(m,W);return v!==W&&!!s.call(u,v,m,i)},v.get=function(m,v){var _=i.get(m,W);return _!==W&&s.call(u,_,m,i)?_:v}),v.__iterateUncached=function(v,_){var j=this,M=0;return i.__iterate((function(i,_,$){if(s.call(u,i,_,$))return M++,v(i,m?_:M-1,j)}),_),M},v.__iteratorUncached=function(v,_){var j=i.__iterator(ae,_),M=0;return new Iterator((function(){for(;;){var _=j.next();if(_.done)return _;var $=_.value,W=$[0],X=$[1];if(s.call(u,X,W,i))return iteratorValue(v,m?W:M++,X,_)}}))},v}function countByFactory(i,s,u){var m=Map().asMutable();return i.__iterate((function(v,_){m.update(s.call(u,v,_,i),0,(function(i){return i+1}))})),m.asImmutable()}function groupByFactory(i,s,u){var m=isKeyed(i),v=(isOrdered(i)?OrderedMap():Map()).asMutable();i.__iterate((function(_,j){v.update(s.call(u,_,j,i),(function(i){return(i=i||[]).push(m?[j,_]:_),i}))}));var _=iterableClass(i);return v.map((function(s){return reify(i,_(s))}))}function sliceFactory(i,s,u,m){var v=i.size;if(void 0!==s&&(s|=0),void 0!==u&&(u===1/0?u=v:u|=0),wholeSlice(s,u,v))return i;var _=resolveBegin(s,v),j=resolveEnd(u,v);if(_!=_||j!=j)return sliceFactory(i.toSeq().cacheResult(),s,u,m);var M,$=j-_;$==$&&(M=$<0?0:$);var W=makeSequence(i);return W.size=0===M?M:i.size&&M||void 0,!m&&isSeq(i)&&M>=0&&(W.get=function(s,u){return(s=wrapIndex(this,s))>=0&&sM)return iteratorDone();var i=v.next();return m||s===ee?i:iteratorValue(s,$-1,s===Z?void 0:i.value[1],i)}))},W}function takeWhileFactory(i,s,u){var m=makeSequence(i);return m.__iterateUncached=function(m,v){var _=this;if(v)return this.cacheResult().__iterate(m,v);var j=0;return i.__iterate((function(i,v,M){return s.call(u,i,v,M)&&++j&&m(i,v,_)})),j},m.__iteratorUncached=function(m,v){var _=this;if(v)return this.cacheResult().__iterator(m,v);var j=i.__iterator(ae,v),M=!0;return new Iterator((function(){if(!M)return iteratorDone();var i=j.next();if(i.done)return i;var v=i.value,$=v[0],W=v[1];return s.call(u,W,$,_)?m===ae?i:iteratorValue(m,$,W,i):(M=!1,iteratorDone())}))},m}function skipWhileFactory(i,s,u,m){var v=makeSequence(i);return v.__iterateUncached=function(v,_){var j=this;if(_)return this.cacheResult().__iterate(v,_);var M=!0,$=0;return i.__iterate((function(i,_,W){if(!M||!(M=s.call(u,i,_,W)))return $++,v(i,m?_:$-1,j)})),$},v.__iteratorUncached=function(v,_){var j=this;if(_)return this.cacheResult().__iterator(v,_);var M=i.__iterator(ae,_),$=!0,W=0;return new Iterator((function(){var i,_,X;do{if((i=M.next()).done)return m||v===ee?i:iteratorValue(v,W++,v===Z?void 0:i.value[1],i);var Y=i.value;_=Y[0],X=Y[1],$&&($=s.call(u,X,_,j))}while($);return v===ae?i:iteratorValue(v,_,X,i)}))},v}function concatFactory(i,s){var u=isKeyed(i),m=[i].concat(s).map((function(i){return isIterable(i)?u&&(i=KeyedIterable(i)):i=u?keyedSeqFromValue(i):indexedSeqFromValue(Array.isArray(i)?i:[i]),i})).filter((function(i){return 0!==i.size}));if(0===m.length)return i;if(1===m.length){var v=m[0];if(v===i||u&&isKeyed(v)||isIndexed(i)&&isIndexed(v))return v}var _=new ArraySeq(m);return u?_=_.toKeyedSeq():isIndexed(i)||(_=_.toSetSeq()),(_=_.flatten(!0)).size=m.reduce((function(i,s){if(void 0!==i){var u=s.size;if(void 0!==u)return i+u}}),0),_}function flattenFactory(i,s,u){var m=makeSequence(i);return m.__iterateUncached=function(m,v){var _=0,j=!1;function flatDeep(i,M){var $=this;i.__iterate((function(i,v){return(!s||M0}function zipWithFactory(i,s,u){var m=makeSequence(i);return m.size=new ArraySeq(u).map((function(i){return i.size})).min(),m.__iterate=function(i,s){for(var u,m=this.__iterator(ee,s),v=0;!(u=m.next()).done&&!1!==i(u.value,v++,this););return v},m.__iteratorUncached=function(i,m){var v=u.map((function(i){return i=Iterable(i),getIterator(m?i.reverse():i)})),_=0,j=!1;return new Iterator((function(){var u;return j||(u=v.map((function(i){return i.next()})),j=u.some((function(i){return i.done}))),j?iteratorDone():iteratorValue(i,_++,s.apply(null,u.map((function(i){return i.value}))))}))},m}function reify(i,s){return isSeq(i)?s:i.constructor(s)}function validateEntry(i){if(i!==Object(i))throw new TypeError("Expected [K, V] tuple: "+i)}function resolveSize(i){return assertNotInfinite(i.size),ensureSize(i)}function iterableClass(i){return isKeyed(i)?KeyedIterable:isIndexed(i)?IndexedIterable:SetIterable}function makeSequence(i){return Object.create((isKeyed(i)?KeyedSeq:isIndexed(i)?IndexedSeq:SetSeq).prototype)}function cacheResultThrough(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):Seq.prototype.cacheResult.call(this)}function defaultComparator(i,s){return i>s?1:i=0;u--)s={value:arguments[u],next:s};return this.__ownerID?(this.size=i,this._head=s,this.__hash=void 0,this.__altered=!0,this):makeStack(i,s)},Stack.prototype.pushAll=function(i){if(0===(i=IndexedIterable(i)).size)return this;assertNotInfinite(i.size);var s=this.size,u=this._head;return i.reverse().forEach((function(i){s++,u={value:i,next:u}})),this.__ownerID?(this.size=s,this._head=u,this.__hash=void 0,this.__altered=!0,this):makeStack(s,u)},Stack.prototype.pop=function(){return this.slice(1)},Stack.prototype.unshift=function(){return this.push.apply(this,arguments)},Stack.prototype.unshiftAll=function(i){return this.pushAll(i)},Stack.prototype.shift=function(){return this.pop.apply(this,arguments)},Stack.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):emptyStack()},Stack.prototype.slice=function(i,s){if(wholeSlice(i,s,this.size))return this;var u=resolveBegin(i,this.size);if(resolveEnd(s,this.size)!==this.size)return IndexedCollection.prototype.slice.call(this,i,s);for(var m=this.size-u,v=this._head;u--;)v=v.next;return this.__ownerID?(this.size=m,this._head=v,this.__hash=void 0,this.__altered=!0,this):makeStack(m,v)},Stack.prototype.__ensureOwner=function(i){return i===this.__ownerID?this:i?makeStack(this.size,this._head,i,this.__hash):(this.__ownerID=i,this.__altered=!1,this)},Stack.prototype.__iterate=function(i,s){if(s)return this.reverse().__iterate(i);for(var u=0,m=this._head;m&&!1!==i(m.value,u++,this);)m=m.next;return u},Stack.prototype.__iterator=function(i,s){if(s)return this.reverse().__iterator(i);var u=0,m=this._head;return new Iterator((function(){if(m){var s=m.value;return m=m.next,iteratorValue(i,u++,s)}return iteratorDone()}))},Stack.isStack=isStack;var pt,ht="@@__IMMUTABLE_STACK__@@",dt=Stack.prototype;function makeStack(i,s,u,m){var v=Object.create(dt);return v.size=i,v._head=s,v.__ownerID=u,v.__hash=m,v.__altered=!1,v}function emptyStack(){return pt||(pt=makeStack(0))}function mixin(i,s){var keyCopier=function(u){i.prototype[u]=s[u]};return Object.keys(s).forEach(keyCopier),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(s).forEach(keyCopier),i}dt[ht]=!0,dt.withMutations=He.withMutations,dt.asMutable=He.asMutable,dt.asImmutable=He.asImmutable,dt.wasAltered=He.wasAltered,Iterable.Iterator=Iterator,mixin(Iterable,{toArray:function(){assertNotInfinite(this.size);var i=new Array(this.size||0);return this.valueSeq().__iterate((function(s,u){i[u]=s})),i},toIndexedSeq:function(){return new ToIndexedSequence(this)},toJS:function(){return this.toSeq().map((function(i){return i&&"function"==typeof i.toJS?i.toJS():i})).__toJS()},toJSON:function(){return this.toSeq().map((function(i){return i&&"function"==typeof i.toJSON?i.toJSON():i})).__toJS()},toKeyedSeq:function(){return new ToKeyedSequence(this,!0)},toMap:function(){return Map(this.toKeyedSeq())},toObject:function(){assertNotInfinite(this.size);var i={};return this.__iterate((function(s,u){i[u]=s})),i},toOrderedMap:function(){return OrderedMap(this.toKeyedSeq())},toOrderedSet:function(){return OrderedSet(isKeyed(this)?this.valueSeq():this)},toSet:function(){return Set(isKeyed(this)?this.valueSeq():this)},toSetSeq:function(){return new ToSetSequence(this)},toSeq:function(){return isIndexed(this)?this.toIndexedSeq():isKeyed(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Stack(isKeyed(this)?this.valueSeq():this)},toList:function(){return List(isKeyed(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(i,s){return 0===this.size?i+s:i+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+s},concat:function(){return reify(this,concatFactory(this,i.call(arguments,0)))},includes:function(i){return this.some((function(s){return is(s,i)}))},entries:function(){return this.__iterator(ae)},every:function(i,s){assertNotInfinite(this.size);var u=!0;return this.__iterate((function(m,v,_){if(!i.call(s,m,v,_))return u=!1,!1})),u},filter:function(i,s){return reify(this,filterFactory(this,i,s,!0))},find:function(i,s,u){var m=this.findEntry(i,s);return m?m[1]:u},forEach:function(i,s){return assertNotInfinite(this.size),this.__iterate(s?i.bind(s):i)},join:function(i){assertNotInfinite(this.size),i=void 0!==i?""+i:",";var s="",u=!0;return this.__iterate((function(m){u?u=!1:s+=i,s+=null!=m?m.toString():""})),s},keys:function(){return this.__iterator(Z)},map:function(i,s){return reify(this,mapFactory(this,i,s))},reduce:function(i,s,u){var m,v;return assertNotInfinite(this.size),arguments.length<2?v=!0:m=s,this.__iterate((function(s,_,j){v?(v=!1,m=s):m=i.call(u,m,s,_,j)})),m},reduceRight:function(i,s,u){var m=this.toKeyedSeq().reverse();return m.reduce.apply(m,arguments)},reverse:function(){return reify(this,reverseFactory(this,!0))},slice:function(i,s){return reify(this,sliceFactory(this,i,s,!0))},some:function(i,s){return!this.every(not(i),s)},sort:function(i){return reify(this,sortFactory(this,i))},values:function(){return this.__iterator(ee)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(i,s){return ensureSize(i?this.toSeq().filter(i,s):this)},countBy:function(i,s){return countByFactory(this,i,s)},equals:function(i){return deepEqual(this,i)},entrySeq:function(){var i=this;if(i._cache)return new ArraySeq(i._cache);var s=i.toSeq().map(entryMapper).toIndexedSeq();return s.fromEntrySeq=function(){return i.toSeq()},s},filterNot:function(i,s){return this.filter(not(i),s)},findEntry:function(i,s,u){var m=u;return this.__iterate((function(u,v,_){if(i.call(s,u,v,_))return m=[v,u],!1})),m},findKey:function(i,s){var u=this.findEntry(i,s);return u&&u[0]},findLast:function(i,s,u){return this.toKeyedSeq().reverse().find(i,s,u)},findLastEntry:function(i,s,u){return this.toKeyedSeq().reverse().findEntry(i,s,u)},findLastKey:function(i,s){return this.toKeyedSeq().reverse().findKey(i,s)},first:function(){return this.find(returnTrue)},flatMap:function(i,s){return reify(this,flatMapFactory(this,i,s))},flatten:function(i){return reify(this,flattenFactory(this,i,!0))},fromEntrySeq:function(){return new FromEntriesSequence(this)},get:function(i,s){return this.find((function(s,u){return is(u,i)}),void 0,s)},getIn:function(i,s){for(var u,m=this,v=forceIterator(i);!(u=v.next()).done;){var _=u.value;if((m=m&&m.get?m.get(_,W):W)===W)return s}return m},groupBy:function(i,s){return groupByFactory(this,i,s)},has:function(i){return this.get(i,W)!==W},hasIn:function(i){return this.getIn(i,W)!==W},isSubset:function(i){return i="function"==typeof i.includes?i:Iterable(i),this.every((function(s){return i.includes(s)}))},isSuperset:function(i){return(i="function"==typeof i.isSubset?i:Iterable(i)).isSubset(this)},keyOf:function(i){return this.findKey((function(s){return is(s,i)}))},keySeq:function(){return this.toSeq().map(keyMapper).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(i){return this.toKeyedSeq().reverse().keyOf(i)},max:function(i){return maxFactory(this,i)},maxBy:function(i,s){return maxFactory(this,s,i)},min:function(i){return maxFactory(this,i?neg(i):defaultNegComparator)},minBy:function(i,s){return maxFactory(this,s?neg(s):defaultNegComparator,i)},rest:function(){return this.slice(1)},skip:function(i){return this.slice(Math.max(0,i))},skipLast:function(i){return reify(this,this.toSeq().reverse().skip(i).reverse())},skipWhile:function(i,s){return reify(this,skipWhileFactory(this,i,s,!0))},skipUntil:function(i,s){return this.skipWhile(not(i),s)},sortBy:function(i,s){return reify(this,sortFactory(this,s,i))},take:function(i){return this.slice(0,Math.max(0,i))},takeLast:function(i){return reify(this,this.toSeq().reverse().take(i).reverse())},takeWhile:function(i,s){return reify(this,takeWhileFactory(this,i,s))},takeUntil:function(i,s){return this.takeWhile(not(i),s)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=hashIterable(this))}});var mt=Iterable.prototype;mt[s]=!0,mt[ce]=mt.values,mt.__toJS=mt.toArray,mt.__toStringMapper=quoteString,mt.inspect=mt.toSource=function(){return this.toString()},mt.chain=mt.flatMap,mt.contains=mt.includes,mixin(KeyedIterable,{flip:function(){return reify(this,flipFactory(this))},mapEntries:function(i,s){var u=this,m=0;return reify(this,this.toSeq().map((function(v,_){return i.call(s,[_,v],m++,u)})).fromEntrySeq())},mapKeys:function(i,s){var u=this;return reify(this,this.toSeq().flip().map((function(m,v){return i.call(s,m,v,u)})).flip())}});var gt=KeyedIterable.prototype;function keyMapper(i,s){return s}function entryMapper(i,s){return[s,i]}function not(i){return function(){return!i.apply(this,arguments)}}function neg(i){return function(){return-i.apply(this,arguments)}}function quoteString(i){return"string"==typeof i?JSON.stringify(i):String(i)}function defaultZipper(){return arrCopy(arguments)}function defaultNegComparator(i,s){return is?-1:0}function hashIterable(i){if(i.size===1/0)return 0;var s=isOrdered(i),u=isKeyed(i),m=s?1:0;return murmurHashOfSize(i.__iterate(u?s?function(i,s){m=31*m+hashMerge(hash(i),hash(s))|0}:function(i,s){m=m+hashMerge(hash(i),hash(s))|0}:s?function(i){m=31*m+hash(i)|0}:function(i){m=m+hash(i)|0}),m)}function murmurHashOfSize(i,s){return s=be(s,3432918353),s=be(s<<15|s>>>-15,461845907),s=be(s<<13|s>>>-13,5),s=be((s=(s+3864292196|0)^i)^s>>>16,2246822507),s=smi((s=be(s^s>>>13,3266489909))^s>>>16)}function hashMerge(i,s){return i^s+2654435769+(i<<6)+(i>>2)|0}return gt[u]=!0,gt[ce]=mt.entries,gt.__toJS=mt.toObject,gt.__toStringMapper=function(i,s){return JSON.stringify(s)+": "+quoteString(i)},mixin(IndexedIterable,{toKeyedSeq:function(){return new ToKeyedSequence(this,!1)},filter:function(i,s){return reify(this,filterFactory(this,i,s,!1))},findIndex:function(i,s){var u=this.findEntry(i,s);return u?u[0]:-1},indexOf:function(i){var s=this.keyOf(i);return void 0===s?-1:s},lastIndexOf:function(i){var s=this.lastKeyOf(i);return void 0===s?-1:s},reverse:function(){return reify(this,reverseFactory(this,!1))},slice:function(i,s){return reify(this,sliceFactory(this,i,s,!1))},splice:function(i,s){var u=arguments.length;if(s=Math.max(0|s,0),0===u||2===u&&!s)return this;i=resolveBegin(i,i<0?this.count():this.size);var m=this.slice(0,i);return reify(this,1===u?m:m.concat(arrCopy(arguments,2),this.slice(i+s)))},findLastIndex:function(i,s){var u=this.findLastEntry(i,s);return u?u[0]:-1},first:function(){return this.get(0)},flatten:function(i){return reify(this,flattenFactory(this,i,!1))},get:function(i,s){return(i=wrapIndex(this,i))<0||this.size===1/0||void 0!==this.size&&i>this.size?s:this.find((function(s,u){return u===i}),void 0,s)},has:function(i){return(i=wrapIndex(this,i))>=0&&(void 0!==this.size?this.size===1/0||i{"function"==typeof Object.create?i.exports=function inherits(i,s){s&&(i.super_=s,i.prototype=Object.create(s.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}))}:i.exports=function inherits(i,s){if(s){i.super_=s;var TempCtor=function(){};TempCtor.prototype=s.prototype,i.prototype=new TempCtor,i.prototype.constructor=i}}},35823:i=>{i.exports=function(i,s,u,m){var v=new Blob(void 0!==m?[m,i]:[i],{type:u||"application/octet-stream"});if(void 0!==window.navigator.msSaveBlob)window.navigator.msSaveBlob(v,s);else{var _=window.URL&&window.URL.createObjectURL?window.URL.createObjectURL(v):window.webkitURL.createObjectURL(v),j=document.createElement("a");j.style.display="none",j.href=_,j.setAttribute("download",s),void 0===j.download&&j.setAttribute("target","_blank"),document.body.appendChild(j),j.click(),setTimeout((function(){document.body.removeChild(j),window.URL.revokeObjectURL(_)}),200)}}},91296:(i,s,u)=>{var m=NaN,v="[object Symbol]",_=/^\s+|\s+$/g,j=/^[-+]0x[0-9a-f]+$/i,M=/^0b[01]+$/i,$=/^0o[0-7]+$/i,W=parseInt,X="object"==typeof u.g&&u.g&&u.g.Object===Object&&u.g,Y="object"==typeof self&&self&&self.Object===Object&&self,Z=X||Y||Function("return this")(),ee=Object.prototype.toString,ae=Math.max,ie=Math.min,now=function(){return Z.Date.now()};function isObject(i){var s=typeof i;return!!i&&("object"==s||"function"==s)}function toNumber(i){if("number"==typeof i)return i;if(function isSymbol(i){return"symbol"==typeof i||function isObjectLike(i){return!!i&&"object"==typeof i}(i)&&ee.call(i)==v}(i))return m;if(isObject(i)){var s="function"==typeof i.valueOf?i.valueOf():i;i=isObject(s)?s+"":s}if("string"!=typeof i)return 0===i?i:+i;i=i.replace(_,"");var u=M.test(i);return u||$.test(i)?W(i.slice(2),u?2:8):j.test(i)?m:+i}i.exports=function debounce(i,s,u){var m,v,_,j,M,$,W=0,X=!1,Y=!1,Z=!0;if("function"!=typeof i)throw new TypeError("Expected a function");function invokeFunc(s){var u=m,_=v;return m=v=void 0,W=s,j=i.apply(_,u)}function shouldInvoke(i){var u=i-$;return void 0===$||u>=s||u<0||Y&&i-W>=_}function timerExpired(){var i=now();if(shouldInvoke(i))return trailingEdge(i);M=setTimeout(timerExpired,function remainingWait(i){var u=s-(i-$);return Y?ie(u,_-(i-W)):u}(i))}function trailingEdge(i){return M=void 0,Z&&m?invokeFunc(i):(m=v=void 0,j)}function debounced(){var i=now(),u=shouldInvoke(i);if(m=arguments,v=this,$=i,u){if(void 0===M)return function leadingEdge(i){return W=i,M=setTimeout(timerExpired,s),X?invokeFunc(i):j}($);if(Y)return M=setTimeout(timerExpired,s),invokeFunc($)}return void 0===M&&(M=setTimeout(timerExpired,s)),j}return s=toNumber(s)||0,isObject(u)&&(X=!!u.leading,_=(Y="maxWait"in u)?ae(toNumber(u.maxWait)||0,s):_,Z="trailing"in u?!!u.trailing:Z),debounced.cancel=function cancel(){void 0!==M&&clearTimeout(M),W=0,m=$=v=M=void 0},debounced.flush=function flush(){return void 0===M?j:trailingEdge(now())},debounced}},18552:(i,s,u)=>{var m=u(10852)(u(55639),"DataView");i.exports=m},1989:(i,s,u)=>{var m=u(51789),v=u(80401),_=u(57667),j=u(21327),M=u(81866);function Hash(i){var s=-1,u=null==i?0:i.length;for(this.clear();++s{var m=u(3118),v=u(9435);function LazyWrapper(i){this.__wrapped__=i,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}LazyWrapper.prototype=m(v.prototype),LazyWrapper.prototype.constructor=LazyWrapper,i.exports=LazyWrapper},38407:(i,s,u)=>{var m=u(27040),v=u(14125),_=u(82117),j=u(67518),M=u(54705);function ListCache(i){var s=-1,u=null==i?0:i.length;for(this.clear();++s{var m=u(3118),v=u(9435);function LodashWrapper(i,s){this.__wrapped__=i,this.__actions__=[],this.__chain__=!!s,this.__index__=0,this.__values__=void 0}LodashWrapper.prototype=m(v.prototype),LodashWrapper.prototype.constructor=LodashWrapper,i.exports=LodashWrapper},57071:(i,s,u)=>{var m=u(10852)(u(55639),"Map");i.exports=m},83369:(i,s,u)=>{var m=u(24785),v=u(11285),_=u(96e3),j=u(49916),M=u(95265);function MapCache(i){var s=-1,u=null==i?0:i.length;for(this.clear();++s{var m=u(10852)(u(55639),"Promise");i.exports=m},58525:(i,s,u)=>{var m=u(10852)(u(55639),"Set");i.exports=m},88668:(i,s,u)=>{var m=u(83369),v=u(90619),_=u(72385);function SetCache(i){var s=-1,u=null==i?0:i.length;for(this.__data__=new m;++s{var m=u(38407),v=u(37465),_=u(63779),j=u(67599),M=u(44758),$=u(34309);function Stack(i){var s=this.__data__=new m(i);this.size=s.size}Stack.prototype.clear=v,Stack.prototype.delete=_,Stack.prototype.get=j,Stack.prototype.has=M,Stack.prototype.set=$,i.exports=Stack},62705:(i,s,u)=>{var m=u(55639).Symbol;i.exports=m},11149:(i,s,u)=>{var m=u(55639).Uint8Array;i.exports=m},70577:(i,s,u)=>{var m=u(10852)(u(55639),"WeakMap");i.exports=m},96874:i=>{i.exports=function apply(i,s,u){switch(u.length){case 0:return i.call(s);case 1:return i.call(s,u[0]);case 2:return i.call(s,u[0],u[1]);case 3:return i.call(s,u[0],u[1],u[2])}return i.apply(s,u)}},77412:i=>{i.exports=function arrayEach(i,s){for(var u=-1,m=null==i?0:i.length;++u{i.exports=function arrayFilter(i,s){for(var u=-1,m=null==i?0:i.length,v=0,_=[];++u{var m=u(42118);i.exports=function arrayIncludes(i,s){return!!(null==i?0:i.length)&&m(i,s,0)>-1}},14636:(i,s,u)=>{var m=u(22545),v=u(35694),_=u(1469),j=u(44144),M=u(65776),$=u(36719),W=Object.prototype.hasOwnProperty;i.exports=function arrayLikeKeys(i,s){var u=_(i),X=!u&&v(i),Y=!u&&!X&&j(i),Z=!u&&!X&&!Y&&$(i),ee=u||X||Y||Z,ae=ee?m(i.length,String):[],ie=ae.length;for(var le in i)!s&&!W.call(i,le)||ee&&("length"==le||Y&&("offset"==le||"parent"==le)||Z&&("buffer"==le||"byteLength"==le||"byteOffset"==le)||M(le,ie))||ae.push(le);return ae}},29932:i=>{i.exports=function arrayMap(i,s){for(var u=-1,m=null==i?0:i.length,v=Array(m);++u{i.exports=function arrayPush(i,s){for(var u=-1,m=s.length,v=i.length;++u{i.exports=function arrayReduce(i,s,u,m){var v=-1,_=null==i?0:i.length;for(m&&_&&(u=i[++v]);++v<_;)u=s(u,i[v],v,i);return u}},82908:i=>{i.exports=function arraySome(i,s){for(var u=-1,m=null==i?0:i.length;++u{i.exports=function asciiToArray(i){return i.split("")}},49029:i=>{var s=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;i.exports=function asciiWords(i){return i.match(s)||[]}},86556:(i,s,u)=>{var m=u(89465),v=u(77813);i.exports=function assignMergeValue(i,s,u){(void 0!==u&&!v(i[s],u)||void 0===u&&!(s in i))&&m(i,s,u)}},34865:(i,s,u)=>{var m=u(89465),v=u(77813),_=Object.prototype.hasOwnProperty;i.exports=function assignValue(i,s,u){var j=i[s];_.call(i,s)&&v(j,u)&&(void 0!==u||s in i)||m(i,s,u)}},18470:(i,s,u)=>{var m=u(77813);i.exports=function assocIndexOf(i,s){for(var u=i.length;u--;)if(m(i[u][0],s))return u;return-1}},44037:(i,s,u)=>{var m=u(98363),v=u(3674);i.exports=function baseAssign(i,s){return i&&m(s,v(s),i)}},63886:(i,s,u)=>{var m=u(98363),v=u(81704);i.exports=function baseAssignIn(i,s){return i&&m(s,v(s),i)}},89465:(i,s,u)=>{var m=u(38777);i.exports=function baseAssignValue(i,s,u){"__proto__"==s&&m?m(i,s,{configurable:!0,enumerable:!0,value:u,writable:!0}):i[s]=u}},85990:(i,s,u)=>{var m=u(46384),v=u(77412),_=u(34865),j=u(44037),M=u(63886),$=u(64626),W=u(278),X=u(18805),Y=u(1911),Z=u(58234),ee=u(46904),ae=u(64160),ie=u(43824),le=u(29148),ce=u(38517),pe=u(1469),de=u(44144),fe=u(56688),ye=u(13218),be=u(72928),_e=u(3674),we=u(81704),Se="[object Arguments]",xe="[object Function]",Pe="[object Object]",Ie={};Ie[Se]=Ie["[object Array]"]=Ie["[object ArrayBuffer]"]=Ie["[object DataView]"]=Ie["[object Boolean]"]=Ie["[object Date]"]=Ie["[object Float32Array]"]=Ie["[object Float64Array]"]=Ie["[object Int8Array]"]=Ie["[object Int16Array]"]=Ie["[object Int32Array]"]=Ie["[object Map]"]=Ie["[object Number]"]=Ie[Pe]=Ie["[object RegExp]"]=Ie["[object Set]"]=Ie["[object String]"]=Ie["[object Symbol]"]=Ie["[object Uint8Array]"]=Ie["[object Uint8ClampedArray]"]=Ie["[object Uint16Array]"]=Ie["[object Uint32Array]"]=!0,Ie["[object Error]"]=Ie[xe]=Ie["[object WeakMap]"]=!1,i.exports=function baseClone(i,s,u,Te,Re,qe){var ze,Ve=1&s,We=2&s,He=4&s;if(u&&(ze=Re?u(i,Te,Re,qe):u(i)),void 0!==ze)return ze;if(!ye(i))return i;var Xe=pe(i);if(Xe){if(ze=ie(i),!Ve)return W(i,ze)}else{var Ye=ae(i),Qe=Ye==xe||"[object GeneratorFunction]"==Ye;if(de(i))return $(i,Ve);if(Ye==Pe||Ye==Se||Qe&&!Re){if(ze=We||Qe?{}:ce(i),!Ve)return We?Y(i,M(ze,i)):X(i,j(ze,i))}else{if(!Ie[Ye])return Re?i:{};ze=le(i,Ye,Ve)}}qe||(qe=new m);var et=qe.get(i);if(et)return et;qe.set(i,ze),be(i)?i.forEach((function(m){ze.add(baseClone(m,s,u,m,i,qe))})):fe(i)&&i.forEach((function(m,v){ze.set(v,baseClone(m,s,u,v,i,qe))}));var tt=Xe?void 0:(He?We?ee:Z:We?we:_e)(i);return v(tt||i,(function(m,v){tt&&(m=i[v=m]),_(ze,v,baseClone(m,s,u,v,i,qe))})),ze}},3118:(i,s,u)=>{var m=u(13218),v=Object.create,_=function(){function object(){}return function(i){if(!m(i))return{};if(v)return v(i);object.prototype=i;var s=new object;return object.prototype=void 0,s}}();i.exports=_},89881:(i,s,u)=>{var m=u(47816),v=u(99291)(m);i.exports=v},41848:i=>{i.exports=function baseFindIndex(i,s,u,m){for(var v=i.length,_=u+(m?1:-1);m?_--:++_{var m=u(62488),v=u(37285);i.exports=function baseFlatten(i,s,u,_,j){var M=-1,$=i.length;for(u||(u=v),j||(j=[]);++M<$;){var W=i[M];s>0&&u(W)?s>1?baseFlatten(W,s-1,u,_,j):m(j,W):_||(j[j.length]=W)}return j}},28483:(i,s,u)=>{var m=u(25063)();i.exports=m},47816:(i,s,u)=>{var m=u(28483),v=u(3674);i.exports=function baseForOwn(i,s){return i&&m(i,s,v)}},97786:(i,s,u)=>{var m=u(71811),v=u(40327);i.exports=function baseGet(i,s){for(var u=0,_=(s=m(s,i)).length;null!=i&&u<_;)i=i[v(s[u++])];return u&&u==_?i:void 0}},68866:(i,s,u)=>{var m=u(62488),v=u(1469);i.exports=function baseGetAllKeys(i,s,u){var _=s(i);return v(i)?_:m(_,u(i))}},44239:(i,s,u)=>{var m=u(62705),v=u(89607),_=u(2333),j=m?m.toStringTag:void 0;i.exports=function baseGetTag(i){return null==i?void 0===i?"[object Undefined]":"[object Null]":j&&j in Object(i)?v(i):_(i)}},13:i=>{i.exports=function baseHasIn(i,s){return null!=i&&s in Object(i)}},42118:(i,s,u)=>{var m=u(41848),v=u(62722),_=u(42351);i.exports=function baseIndexOf(i,s,u){return s==s?_(i,s,u):m(i,v,u)}},9454:(i,s,u)=>{var m=u(44239),v=u(37005);i.exports=function baseIsArguments(i){return v(i)&&"[object Arguments]"==m(i)}},90939:(i,s,u)=>{var m=u(2492),v=u(37005);i.exports=function baseIsEqual(i,s,u,_,j){return i===s||(null==i||null==s||!v(i)&&!v(s)?i!=i&&s!=s:m(i,s,u,_,baseIsEqual,j))}},2492:(i,s,u)=>{var m=u(46384),v=u(67114),_=u(18351),j=u(16096),M=u(64160),$=u(1469),W=u(44144),X=u(36719),Y="[object Arguments]",Z="[object Array]",ee="[object Object]",ae=Object.prototype.hasOwnProperty;i.exports=function baseIsEqualDeep(i,s,u,ie,le,ce){var pe=$(i),de=$(s),fe=pe?Z:M(i),ye=de?Z:M(s),be=(fe=fe==Y?ee:fe)==ee,_e=(ye=ye==Y?ee:ye)==ee,we=fe==ye;if(we&&W(i)){if(!W(s))return!1;pe=!0,be=!1}if(we&&!be)return ce||(ce=new m),pe||X(i)?v(i,s,u,ie,le,ce):_(i,s,fe,u,ie,le,ce);if(!(1&u)){var Se=be&&ae.call(i,"__wrapped__"),xe=_e&&ae.call(s,"__wrapped__");if(Se||xe){var Pe=Se?i.value():i,Ie=xe?s.value():s;return ce||(ce=new m),le(Pe,Ie,u,ie,ce)}}return!!we&&(ce||(ce=new m),j(i,s,u,ie,le,ce))}},25588:(i,s,u)=>{var m=u(64160),v=u(37005);i.exports=function baseIsMap(i){return v(i)&&"[object Map]"==m(i)}},2958:(i,s,u)=>{var m=u(46384),v=u(90939);i.exports=function baseIsMatch(i,s,u,_){var j=u.length,M=j,$=!_;if(null==i)return!M;for(i=Object(i);j--;){var W=u[j];if($&&W[2]?W[1]!==i[W[0]]:!(W[0]in i))return!1}for(;++j{i.exports=function baseIsNaN(i){return i!=i}},28458:(i,s,u)=>{var m=u(23560),v=u(15346),_=u(13218),j=u(80346),M=/^\[object .+?Constructor\]$/,$=Function.prototype,W=Object.prototype,X=$.toString,Y=W.hasOwnProperty,Z=RegExp("^"+X.call(Y).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");i.exports=function baseIsNative(i){return!(!_(i)||v(i))&&(m(i)?Z:M).test(j(i))}},29221:(i,s,u)=>{var m=u(64160),v=u(37005);i.exports=function baseIsSet(i){return v(i)&&"[object Set]"==m(i)}},38749:(i,s,u)=>{var m=u(44239),v=u(41780),_=u(37005),j={};j["[object Float32Array]"]=j["[object Float64Array]"]=j["[object Int8Array]"]=j["[object Int16Array]"]=j["[object Int32Array]"]=j["[object Uint8Array]"]=j["[object Uint8ClampedArray]"]=j["[object Uint16Array]"]=j["[object Uint32Array]"]=!0,j["[object Arguments]"]=j["[object Array]"]=j["[object ArrayBuffer]"]=j["[object Boolean]"]=j["[object DataView]"]=j["[object Date]"]=j["[object Error]"]=j["[object Function]"]=j["[object Map]"]=j["[object Number]"]=j["[object Object]"]=j["[object RegExp]"]=j["[object Set]"]=j["[object String]"]=j["[object WeakMap]"]=!1,i.exports=function baseIsTypedArray(i){return _(i)&&v(i.length)&&!!j[m(i)]}},67206:(i,s,u)=>{var m=u(91573),v=u(16432),_=u(6557),j=u(1469),M=u(39601);i.exports=function baseIteratee(i){return"function"==typeof i?i:null==i?_:"object"==typeof i?j(i)?v(i[0],i[1]):m(i):M(i)}},280:(i,s,u)=>{var m=u(25726),v=u(86916),_=Object.prototype.hasOwnProperty;i.exports=function baseKeys(i){if(!m(i))return v(i);var s=[];for(var u in Object(i))_.call(i,u)&&"constructor"!=u&&s.push(u);return s}},10313:(i,s,u)=>{var m=u(13218),v=u(25726),_=u(33498),j=Object.prototype.hasOwnProperty;i.exports=function baseKeysIn(i){if(!m(i))return _(i);var s=v(i),u=[];for(var M in i)("constructor"!=M||!s&&j.call(i,M))&&u.push(M);return u}},9435:i=>{i.exports=function baseLodash(){}},91573:(i,s,u)=>{var m=u(2958),v=u(1499),_=u(42634);i.exports=function baseMatches(i){var s=v(i);return 1==s.length&&s[0][2]?_(s[0][0],s[0][1]):function(u){return u===i||m(u,i,s)}}},16432:(i,s,u)=>{var m=u(90939),v=u(27361),_=u(79095),j=u(15403),M=u(89162),$=u(42634),W=u(40327);i.exports=function baseMatchesProperty(i,s){return j(i)&&M(s)?$(W(i),s):function(u){var j=v(u,i);return void 0===j&&j===s?_(u,i):m(s,j,3)}}},42980:(i,s,u)=>{var m=u(46384),v=u(86556),_=u(28483),j=u(59783),M=u(13218),$=u(81704),W=u(36390);i.exports=function baseMerge(i,s,u,X,Y){i!==s&&_(s,(function(_,$){if(Y||(Y=new m),M(_))j(i,s,$,u,baseMerge,X,Y);else{var Z=X?X(W(i,$),_,$+"",i,s,Y):void 0;void 0===Z&&(Z=_),v(i,$,Z)}}),$)}},59783:(i,s,u)=>{var m=u(86556),v=u(64626),_=u(77133),j=u(278),M=u(38517),$=u(35694),W=u(1469),X=u(29246),Y=u(44144),Z=u(23560),ee=u(13218),ae=u(68630),ie=u(36719),le=u(36390),ce=u(59881);i.exports=function baseMergeDeep(i,s,u,pe,de,fe,ye){var be=le(i,u),_e=le(s,u),we=ye.get(_e);if(we)m(i,u,we);else{var Se=fe?fe(be,_e,u+"",i,s,ye):void 0,xe=void 0===Se;if(xe){var Pe=W(_e),Ie=!Pe&&Y(_e),Te=!Pe&&!Ie&&ie(_e);Se=_e,Pe||Ie||Te?W(be)?Se=be:X(be)?Se=j(be):Ie?(xe=!1,Se=v(_e,!0)):Te?(xe=!1,Se=_(_e,!0)):Se=[]:ae(_e)||$(_e)?(Se=be,$(be)?Se=ce(be):ee(be)&&!Z(be)||(Se=M(_e))):xe=!1}xe&&(ye.set(_e,Se),de(Se,_e,pe,fe,ye),ye.delete(_e)),m(i,u,Se)}}},40371:i=>{i.exports=function baseProperty(i){return function(s){return null==s?void 0:s[i]}}},79152:(i,s,u)=>{var m=u(97786);i.exports=function basePropertyDeep(i){return function(s){return m(s,i)}}},18674:i=>{i.exports=function basePropertyOf(i){return function(s){return null==i?void 0:i[s]}}},10107:i=>{i.exports=function baseReduce(i,s,u,m,v){return v(i,(function(i,v,_){u=m?(m=!1,i):s(u,i,v,_)})),u}},5976:(i,s,u)=>{var m=u(6557),v=u(45357),_=u(30061);i.exports=function baseRest(i,s){return _(v(i,s,m),i+"")}},10611:(i,s,u)=>{var m=u(34865),v=u(71811),_=u(65776),j=u(13218),M=u(40327);i.exports=function baseSet(i,s,u,$){if(!j(i))return i;for(var W=-1,X=(s=v(s,i)).length,Y=X-1,Z=i;null!=Z&&++W{var m=u(6557),v=u(89250),_=v?function(i,s){return v.set(i,s),i}:m;i.exports=_},56560:(i,s,u)=>{var m=u(75703),v=u(38777),_=u(6557),j=v?function(i,s){return v(i,"toString",{configurable:!0,enumerable:!1,value:m(s),writable:!0})}:_;i.exports=j},14259:i=>{i.exports=function baseSlice(i,s,u){var m=-1,v=i.length;s<0&&(s=-s>v?0:v+s),(u=u>v?v:u)<0&&(u+=v),v=s>u?0:u-s>>>0,s>>>=0;for(var _=Array(v);++m{var m=u(89881);i.exports=function baseSome(i,s){var u;return m(i,(function(i,m,v){return!(u=s(i,m,v))})),!!u}},22545:i=>{i.exports=function baseTimes(i,s){for(var u=-1,m=Array(i);++u{var m=u(62705),v=u(29932),_=u(1469),j=u(33448),M=m?m.prototype:void 0,$=M?M.toString:void 0;i.exports=function baseToString(i){if("string"==typeof i)return i;if(_(i))return v(i,baseToString)+"";if(j(i))return $?$.call(i):"";var s=i+"";return"0"==s&&1/i==-Infinity?"-0":s}},27561:(i,s,u)=>{var m=u(67990),v=/^\s+/;i.exports=function baseTrim(i){return i?i.slice(0,m(i)+1).replace(v,""):i}},7518:i=>{i.exports=function baseUnary(i){return function(s){return i(s)}}},57406:(i,s,u)=>{var m=u(71811),v=u(10928),_=u(40292),j=u(40327);i.exports=function baseUnset(i,s){return s=m(s,i),null==(i=_(i,s))||delete i[j(v(s))]}},1757:i=>{i.exports=function baseZipObject(i,s,u){for(var m=-1,v=i.length,_=s.length,j={};++m{i.exports=function cacheHas(i,s){return i.has(s)}},71811:(i,s,u)=>{var m=u(1469),v=u(15403),_=u(55514),j=u(79833);i.exports=function castPath(i,s){return m(i)?i:v(i,s)?[i]:_(j(i))}},40180:(i,s,u)=>{var m=u(14259);i.exports=function castSlice(i,s,u){var v=i.length;return u=void 0===u?v:u,!s&&u>=v?i:m(i,s,u)}},74318:(i,s,u)=>{var m=u(11149);i.exports=function cloneArrayBuffer(i){var s=new i.constructor(i.byteLength);return new m(s).set(new m(i)),s}},64626:(i,s,u)=>{i=u.nmd(i);var m=u(55639),v=s&&!s.nodeType&&s,_=v&&i&&!i.nodeType&&i,j=_&&_.exports===v?m.Buffer:void 0,M=j?j.allocUnsafe:void 0;i.exports=function cloneBuffer(i,s){if(s)return i.slice();var u=i.length,m=M?M(u):new i.constructor(u);return i.copy(m),m}},57157:(i,s,u)=>{var m=u(74318);i.exports=function cloneDataView(i,s){var u=s?m(i.buffer):i.buffer;return new i.constructor(u,i.byteOffset,i.byteLength)}},93147:i=>{var s=/\w*$/;i.exports=function cloneRegExp(i){var u=new i.constructor(i.source,s.exec(i));return u.lastIndex=i.lastIndex,u}},40419:(i,s,u)=>{var m=u(62705),v=m?m.prototype:void 0,_=v?v.valueOf:void 0;i.exports=function cloneSymbol(i){return _?Object(_.call(i)):{}}},77133:(i,s,u)=>{var m=u(74318);i.exports=function cloneTypedArray(i,s){var u=s?m(i.buffer):i.buffer;return new i.constructor(u,i.byteOffset,i.length)}},52157:i=>{var s=Math.max;i.exports=function composeArgs(i,u,m,v){for(var _=-1,j=i.length,M=m.length,$=-1,W=u.length,X=s(j-M,0),Y=Array(W+X),Z=!v;++${var s=Math.max;i.exports=function composeArgsRight(i,u,m,v){for(var _=-1,j=i.length,M=-1,$=m.length,W=-1,X=u.length,Y=s(j-$,0),Z=Array(Y+X),ee=!v;++_{i.exports=function copyArray(i,s){var u=-1,m=i.length;for(s||(s=Array(m));++u{var m=u(34865),v=u(89465);i.exports=function copyObject(i,s,u,_){var j=!u;u||(u={});for(var M=-1,$=s.length;++M<$;){var W=s[M],X=_?_(u[W],i[W],W,u,i):void 0;void 0===X&&(X=i[W]),j?v(u,W,X):m(u,W,X)}return u}},18805:(i,s,u)=>{var m=u(98363),v=u(99551);i.exports=function copySymbols(i,s){return m(i,v(i),s)}},1911:(i,s,u)=>{var m=u(98363),v=u(51442);i.exports=function copySymbolsIn(i,s){return m(i,v(i),s)}},14429:(i,s,u)=>{var m=u(55639)["__core-js_shared__"];i.exports=m},97991:i=>{i.exports=function countHolders(i,s){for(var u=i.length,m=0;u--;)i[u]===s&&++m;return m}},21463:(i,s,u)=>{var m=u(5976),v=u(16612);i.exports=function createAssigner(i){return m((function(s,u){var m=-1,_=u.length,j=_>1?u[_-1]:void 0,M=_>2?u[2]:void 0;for(j=i.length>3&&"function"==typeof j?(_--,j):void 0,M&&v(u[0],u[1],M)&&(j=_<3?void 0:j,_=1),s=Object(s);++m<_;){var $=u[m];$&&i(s,$,m,j)}return s}))}},99291:(i,s,u)=>{var m=u(98612);i.exports=function createBaseEach(i,s){return function(u,v){if(null==u)return u;if(!m(u))return i(u,v);for(var _=u.length,j=s?_:-1,M=Object(u);(s?j--:++j<_)&&!1!==v(M[j],j,M););return u}}},25063:i=>{i.exports=function createBaseFor(i){return function(s,u,m){for(var v=-1,_=Object(s),j=m(s),M=j.length;M--;){var $=j[i?M:++v];if(!1===u(_[$],$,_))break}return s}}},22402:(i,s,u)=>{var m=u(71774),v=u(55639);i.exports=function createBind(i,s,u){var _=1&s,j=m(i);return function wrapper(){return(this&&this!==v&&this instanceof wrapper?j:i).apply(_?u:this,arguments)}}},98805:(i,s,u)=>{var m=u(40180),v=u(62689),_=u(83140),j=u(79833);i.exports=function createCaseFirst(i){return function(s){s=j(s);var u=v(s)?_(s):void 0,M=u?u[0]:s.charAt(0),$=u?m(u,1).join(""):s.slice(1);return M[i]()+$}}},35393:(i,s,u)=>{var m=u(62663),v=u(53816),_=u(58748),j=RegExp("['’]","g");i.exports=function createCompounder(i){return function(s){return m(_(v(s).replace(j,"")),i,"")}}},71774:(i,s,u)=>{var m=u(3118),v=u(13218);i.exports=function createCtor(i){return function(){var s=arguments;switch(s.length){case 0:return new i;case 1:return new i(s[0]);case 2:return new i(s[0],s[1]);case 3:return new i(s[0],s[1],s[2]);case 4:return new i(s[0],s[1],s[2],s[3]);case 5:return new i(s[0],s[1],s[2],s[3],s[4]);case 6:return new i(s[0],s[1],s[2],s[3],s[4],s[5]);case 7:return new i(s[0],s[1],s[2],s[3],s[4],s[5],s[6])}var u=m(i.prototype),_=i.apply(u,s);return v(_)?_:u}}},46347:(i,s,u)=>{var m=u(96874),v=u(71774),_=u(86935),j=u(94487),M=u(20893),$=u(46460),W=u(55639);i.exports=function createCurry(i,s,u){var X=v(i);return function wrapper(){for(var v=arguments.length,Y=Array(v),Z=v,ee=M(wrapper);Z--;)Y[Z]=arguments[Z];var ae=v<3&&Y[0]!==ee&&Y[v-1]!==ee?[]:$(Y,ee);return(v-=ae.length){var m=u(67206),v=u(98612),_=u(3674);i.exports=function createFind(i){return function(s,u,j){var M=Object(s);if(!v(s)){var $=m(u,3);s=_(s),u=function(i){return $(M[i],i,M)}}var W=i(s,u,j);return W>-1?M[$?s[W]:W]:void 0}}},86935:(i,s,u)=>{var m=u(52157),v=u(14054),_=u(97991),j=u(71774),M=u(94487),$=u(20893),W=u(90451),X=u(46460),Y=u(55639);i.exports=function createHybrid(i,s,u,Z,ee,ae,ie,le,ce,pe){var de=128&s,fe=1&s,ye=2&s,be=24&s,_e=512&s,we=ye?void 0:j(i);return function wrapper(){for(var Se=arguments.length,xe=Array(Se),Pe=Se;Pe--;)xe[Pe]=arguments[Pe];if(be)var Ie=$(wrapper),Te=_(xe,Ie);if(Z&&(xe=m(xe,Z,ee,be)),ae&&(xe=v(xe,ae,ie,be)),Se-=Te,be&&Se1&&xe.reverse(),de&&ce{var m=u(96874),v=u(71774),_=u(55639);i.exports=function createPartial(i,s,u,j){var M=1&s,$=v(i);return function wrapper(){for(var s=-1,v=arguments.length,W=-1,X=j.length,Y=Array(X+v),Z=this&&this!==_&&this instanceof wrapper?$:i;++W{var m=u(86528),v=u(258),_=u(69255);i.exports=function createRecurry(i,s,u,j,M,$,W,X,Y,Z){var ee=8&s;s|=ee?32:64,4&(s&=~(ee?64:32))||(s&=-4);var ae=[i,s,M,ee?$:void 0,ee?W:void 0,ee?void 0:$,ee?void 0:W,X,Y,Z],ie=u.apply(void 0,ae);return m(i)&&v(ie,ae),ie.placeholder=j,_(ie,i,s)}},97727:(i,s,u)=>{var m=u(28045),v=u(22402),_=u(46347),j=u(86935),M=u(84375),$=u(66833),W=u(63833),X=u(258),Y=u(69255),Z=u(40554),ee=Math.max;i.exports=function createWrap(i,s,u,ae,ie,le,ce,pe){var de=2&s;if(!de&&"function"!=typeof i)throw new TypeError("Expected a function");var fe=ae?ae.length:0;if(fe||(s&=-97,ae=ie=void 0),ce=void 0===ce?ce:ee(Z(ce),0),pe=void 0===pe?pe:Z(pe),fe-=ie?ie.length:0,64&s){var ye=ae,be=ie;ae=ie=void 0}var _e=de?void 0:$(i),we=[i,s,u,ae,ie,ye,be,le,ce,pe];if(_e&&W(we,_e),i=we[0],s=we[1],u=we[2],ae=we[3],ie=we[4],!(pe=we[9]=void 0===we[9]?de?0:i.length:ee(we[9]-fe,0))&&24&s&&(s&=-25),s&&1!=s)Se=8==s||16==s?_(i,s,pe):32!=s&&33!=s||ie.length?j.apply(void 0,we):M(i,s,u,ae);else var Se=v(i,s,u);return Y((_e?m:X)(Se,we),i,s)}},60696:(i,s,u)=>{var m=u(68630);i.exports=function customOmitClone(i){return m(i)?void 0:i}},69389:(i,s,u)=>{var m=u(18674)({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"});i.exports=m},38777:(i,s,u)=>{var m=u(10852),v=function(){try{var i=m(Object,"defineProperty");return i({},"",{}),i}catch(i){}}();i.exports=v},67114:(i,s,u)=>{var m=u(88668),v=u(82908),_=u(74757);i.exports=function equalArrays(i,s,u,j,M,$){var W=1&u,X=i.length,Y=s.length;if(X!=Y&&!(W&&Y>X))return!1;var Z=$.get(i),ee=$.get(s);if(Z&&ee)return Z==s&&ee==i;var ae=-1,ie=!0,le=2&u?new m:void 0;for($.set(i,s),$.set(s,i);++ae{var m=u(62705),v=u(11149),_=u(77813),j=u(67114),M=u(68776),$=u(21814),W=m?m.prototype:void 0,X=W?W.valueOf:void 0;i.exports=function equalByTag(i,s,u,m,W,Y,Z){switch(u){case"[object DataView]":if(i.byteLength!=s.byteLength||i.byteOffset!=s.byteOffset)return!1;i=i.buffer,s=s.buffer;case"[object ArrayBuffer]":return!(i.byteLength!=s.byteLength||!Y(new v(i),new v(s)));case"[object Boolean]":case"[object Date]":case"[object Number]":return _(+i,+s);case"[object Error]":return i.name==s.name&&i.message==s.message;case"[object RegExp]":case"[object String]":return i==s+"";case"[object Map]":var ee=M;case"[object Set]":var ae=1&m;if(ee||(ee=$),i.size!=s.size&&!ae)return!1;var ie=Z.get(i);if(ie)return ie==s;m|=2,Z.set(i,s);var le=j(ee(i),ee(s),m,W,Y,Z);return Z.delete(i),le;case"[object Symbol]":if(X)return X.call(i)==X.call(s)}return!1}},16096:(i,s,u)=>{var m=u(58234),v=Object.prototype.hasOwnProperty;i.exports=function equalObjects(i,s,u,_,j,M){var $=1&u,W=m(i),X=W.length;if(X!=m(s).length&&!$)return!1;for(var Y=X;Y--;){var Z=W[Y];if(!($?Z in s:v.call(s,Z)))return!1}var ee=M.get(i),ae=M.get(s);if(ee&&ae)return ee==s&&ae==i;var ie=!0;M.set(i,s),M.set(s,i);for(var le=$;++Y{var m=u(85564),v=u(45357),_=u(30061);i.exports=function flatRest(i){return _(v(i,void 0,m),i+"")}},31957:(i,s,u)=>{var m="object"==typeof u.g&&u.g&&u.g.Object===Object&&u.g;i.exports=m},58234:(i,s,u)=>{var m=u(68866),v=u(99551),_=u(3674);i.exports=function getAllKeys(i){return m(i,_,v)}},46904:(i,s,u)=>{var m=u(68866),v=u(51442),_=u(81704);i.exports=function getAllKeysIn(i){return m(i,_,v)}},66833:(i,s,u)=>{var m=u(89250),v=u(50308),_=m?function(i){return m.get(i)}:v;i.exports=_},97658:(i,s,u)=>{var m=u(52060),v=Object.prototype.hasOwnProperty;i.exports=function getFuncName(i){for(var s=i.name+"",u=m[s],_=v.call(m,s)?u.length:0;_--;){var j=u[_],M=j.func;if(null==M||M==i)return j.name}return s}},20893:i=>{i.exports=function getHolder(i){return i.placeholder}},45050:(i,s,u)=>{var m=u(37019);i.exports=function getMapData(i,s){var u=i.__data__;return m(s)?u["string"==typeof s?"string":"hash"]:u.map}},1499:(i,s,u)=>{var m=u(89162),v=u(3674);i.exports=function getMatchData(i){for(var s=v(i),u=s.length;u--;){var _=s[u],j=i[_];s[u]=[_,j,m(j)]}return s}},10852:(i,s,u)=>{var m=u(28458),v=u(47801);i.exports=function getNative(i,s){var u=v(i,s);return m(u)?u:void 0}},85924:(i,s,u)=>{var m=u(5569)(Object.getPrototypeOf,Object);i.exports=m},89607:(i,s,u)=>{var m=u(62705),v=Object.prototype,_=v.hasOwnProperty,j=v.toString,M=m?m.toStringTag:void 0;i.exports=function getRawTag(i){var s=_.call(i,M),u=i[M];try{i[M]=void 0;var m=!0}catch(i){}var v=j.call(i);return m&&(s?i[M]=u:delete i[M]),v}},99551:(i,s,u)=>{var m=u(34963),v=u(70479),_=Object.prototype.propertyIsEnumerable,j=Object.getOwnPropertySymbols,M=j?function(i){return null==i?[]:(i=Object(i),m(j(i),(function(s){return _.call(i,s)})))}:v;i.exports=M},51442:(i,s,u)=>{var m=u(62488),v=u(85924),_=u(99551),j=u(70479),M=Object.getOwnPropertySymbols?function(i){for(var s=[];i;)m(s,_(i)),i=v(i);return s}:j;i.exports=M},64160:(i,s,u)=>{var m=u(18552),v=u(57071),_=u(53818),j=u(58525),M=u(70577),$=u(44239),W=u(80346),X="[object Map]",Y="[object Promise]",Z="[object Set]",ee="[object WeakMap]",ae="[object DataView]",ie=W(m),le=W(v),ce=W(_),pe=W(j),de=W(M),fe=$;(m&&fe(new m(new ArrayBuffer(1)))!=ae||v&&fe(new v)!=X||_&&fe(_.resolve())!=Y||j&&fe(new j)!=Z||M&&fe(new M)!=ee)&&(fe=function(i){var s=$(i),u="[object Object]"==s?i.constructor:void 0,m=u?W(u):"";if(m)switch(m){case ie:return ae;case le:return X;case ce:return Y;case pe:return Z;case de:return ee}return s}),i.exports=fe},47801:i=>{i.exports=function getValue(i,s){return null==i?void 0:i[s]}},58775:i=>{var s=/\{\n\/\* \[wrapped with (.+)\] \*/,u=/,? & /;i.exports=function getWrapDetails(i){var m=i.match(s);return m?m[1].split(u):[]}},222:(i,s,u)=>{var m=u(71811),v=u(35694),_=u(1469),j=u(65776),M=u(41780),$=u(40327);i.exports=function hasPath(i,s,u){for(var W=-1,X=(s=m(s,i)).length,Y=!1;++W{var s=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]");i.exports=function hasUnicode(i){return s.test(i)}},93157:i=>{var s=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;i.exports=function hasUnicodeWord(i){return s.test(i)}},51789:(i,s,u)=>{var m=u(94536);i.exports=function hashClear(){this.__data__=m?m(null):{},this.size=0}},80401:i=>{i.exports=function hashDelete(i){var s=this.has(i)&&delete this.__data__[i];return this.size-=s?1:0,s}},57667:(i,s,u)=>{var m=u(94536),v=Object.prototype.hasOwnProperty;i.exports=function hashGet(i){var s=this.__data__;if(m){var u=s[i];return"__lodash_hash_undefined__"===u?void 0:u}return v.call(s,i)?s[i]:void 0}},21327:(i,s,u)=>{var m=u(94536),v=Object.prototype.hasOwnProperty;i.exports=function hashHas(i){var s=this.__data__;return m?void 0!==s[i]:v.call(s,i)}},81866:(i,s,u)=>{var m=u(94536);i.exports=function hashSet(i,s){var u=this.__data__;return this.size+=this.has(i)?0:1,u[i]=m&&void 0===s?"__lodash_hash_undefined__":s,this}},43824:i=>{var s=Object.prototype.hasOwnProperty;i.exports=function initCloneArray(i){var u=i.length,m=new i.constructor(u);return u&&"string"==typeof i[0]&&s.call(i,"index")&&(m.index=i.index,m.input=i.input),m}},29148:(i,s,u)=>{var m=u(74318),v=u(57157),_=u(93147),j=u(40419),M=u(77133);i.exports=function initCloneByTag(i,s,u){var $=i.constructor;switch(s){case"[object ArrayBuffer]":return m(i);case"[object Boolean]":case"[object Date]":return new $(+i);case"[object DataView]":return v(i,u);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return M(i,u);case"[object Map]":case"[object Set]":return new $;case"[object Number]":case"[object String]":return new $(i);case"[object RegExp]":return _(i);case"[object Symbol]":return j(i)}}},38517:(i,s,u)=>{var m=u(3118),v=u(85924),_=u(25726);i.exports=function initCloneObject(i){return"function"!=typeof i.constructor||_(i)?{}:m(v(i))}},83112:i=>{var s=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/;i.exports=function insertWrapDetails(i,u){var m=u.length;if(!m)return i;var v=m-1;return u[v]=(m>1?"& ":"")+u[v],u=u.join(m>2?", ":" "),i.replace(s,"{\n/* [wrapped with "+u+"] */\n")}},37285:(i,s,u)=>{var m=u(62705),v=u(35694),_=u(1469),j=m?m.isConcatSpreadable:void 0;i.exports=function isFlattenable(i){return _(i)||v(i)||!!(j&&i&&i[j])}},65776:i=>{var s=/^(?:0|[1-9]\d*)$/;i.exports=function isIndex(i,u){var m=typeof i;return!!(u=null==u?9007199254740991:u)&&("number"==m||"symbol"!=m&&s.test(i))&&i>-1&&i%1==0&&i{var m=u(77813),v=u(98612),_=u(65776),j=u(13218);i.exports=function isIterateeCall(i,s,u){if(!j(u))return!1;var M=typeof s;return!!("number"==M?v(u)&&_(s,u.length):"string"==M&&s in u)&&m(u[s],i)}},15403:(i,s,u)=>{var m=u(1469),v=u(33448),_=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,j=/^\w*$/;i.exports=function isKey(i,s){if(m(i))return!1;var u=typeof i;return!("number"!=u&&"symbol"!=u&&"boolean"!=u&&null!=i&&!v(i))||(j.test(i)||!_.test(i)||null!=s&&i in Object(s))}},37019:i=>{i.exports=function isKeyable(i){var s=typeof i;return"string"==s||"number"==s||"symbol"==s||"boolean"==s?"__proto__"!==i:null===i}},86528:(i,s,u)=>{var m=u(96425),v=u(66833),_=u(97658),j=u(8111);i.exports=function isLaziable(i){var s=_(i),u=j[s];if("function"!=typeof u||!(s in m.prototype))return!1;if(i===u)return!0;var M=v(u);return!!M&&i===M[0]}},15346:(i,s,u)=>{var m,v=u(14429),_=(m=/[^.]+$/.exec(v&&v.keys&&v.keys.IE_PROTO||""))?"Symbol(src)_1."+m:"";i.exports=function isMasked(i){return!!_&&_ in i}},25726:i=>{var s=Object.prototype;i.exports=function isPrototype(i){var u=i&&i.constructor;return i===("function"==typeof u&&u.prototype||s)}},89162:(i,s,u)=>{var m=u(13218);i.exports=function isStrictComparable(i){return i==i&&!m(i)}},27040:i=>{i.exports=function listCacheClear(){this.__data__=[],this.size=0}},14125:(i,s,u)=>{var m=u(18470),v=Array.prototype.splice;i.exports=function listCacheDelete(i){var s=this.__data__,u=m(s,i);return!(u<0)&&(u==s.length-1?s.pop():v.call(s,u,1),--this.size,!0)}},82117:(i,s,u)=>{var m=u(18470);i.exports=function listCacheGet(i){var s=this.__data__,u=m(s,i);return u<0?void 0:s[u][1]}},67518:(i,s,u)=>{var m=u(18470);i.exports=function listCacheHas(i){return m(this.__data__,i)>-1}},54705:(i,s,u)=>{var m=u(18470);i.exports=function listCacheSet(i,s){var u=this.__data__,v=m(u,i);return v<0?(++this.size,u.push([i,s])):u[v][1]=s,this}},24785:(i,s,u)=>{var m=u(1989),v=u(38407),_=u(57071);i.exports=function mapCacheClear(){this.size=0,this.__data__={hash:new m,map:new(_||v),string:new m}}},11285:(i,s,u)=>{var m=u(45050);i.exports=function mapCacheDelete(i){var s=m(this,i).delete(i);return this.size-=s?1:0,s}},96e3:(i,s,u)=>{var m=u(45050);i.exports=function mapCacheGet(i){return m(this,i).get(i)}},49916:(i,s,u)=>{var m=u(45050);i.exports=function mapCacheHas(i){return m(this,i).has(i)}},95265:(i,s,u)=>{var m=u(45050);i.exports=function mapCacheSet(i,s){var u=m(this,i),v=u.size;return u.set(i,s),this.size+=u.size==v?0:1,this}},68776:i=>{i.exports=function mapToArray(i){var s=-1,u=Array(i.size);return i.forEach((function(i,m){u[++s]=[m,i]})),u}},42634:i=>{i.exports=function matchesStrictComparable(i,s){return function(u){return null!=u&&(u[i]===s&&(void 0!==s||i in Object(u)))}}},24523:(i,s,u)=>{var m=u(88306);i.exports=function memoizeCapped(i){var s=m(i,(function(i){return 500===u.size&&u.clear(),i})),u=s.cache;return s}},63833:(i,s,u)=>{var m=u(52157),v=u(14054),_=u(46460),j="__lodash_placeholder__",M=128,$=Math.min;i.exports=function mergeData(i,s){var u=i[1],W=s[1],X=u|W,Y=X<131,Z=W==M&&8==u||W==M&&256==u&&i[7].length<=s[8]||384==W&&s[7].length<=s[8]&&8==u;if(!Y&&!Z)return i;1&W&&(i[2]=s[2],X|=1&u?0:4);var ee=s[3];if(ee){var ae=i[3];i[3]=ae?m(ae,ee,s[4]):ee,i[4]=ae?_(i[3],j):s[4]}return(ee=s[5])&&(ae=i[5],i[5]=ae?v(ae,ee,s[6]):ee,i[6]=ae?_(i[5],j):s[6]),(ee=s[7])&&(i[7]=ee),W&M&&(i[8]=null==i[8]?s[8]:$(i[8],s[8])),null==i[9]&&(i[9]=s[9]),i[0]=s[0],i[1]=X,i}},89250:(i,s,u)=>{var m=u(70577),v=m&&new m;i.exports=v},94536:(i,s,u)=>{var m=u(10852)(Object,"create");i.exports=m},86916:(i,s,u)=>{var m=u(5569)(Object.keys,Object);i.exports=m},33498:i=>{i.exports=function nativeKeysIn(i){var s=[];if(null!=i)for(var u in Object(i))s.push(u);return s}},31167:(i,s,u)=>{i=u.nmd(i);var m=u(31957),v=s&&!s.nodeType&&s,_=v&&i&&!i.nodeType&&i,j=_&&_.exports===v&&m.process,M=function(){try{var i=_&&_.require&&_.require("util").types;return i||j&&j.binding&&j.binding("util")}catch(i){}}();i.exports=M},2333:i=>{var s=Object.prototype.toString;i.exports=function objectToString(i){return s.call(i)}},5569:i=>{i.exports=function overArg(i,s){return function(u){return i(s(u))}}},45357:(i,s,u)=>{var m=u(96874),v=Math.max;i.exports=function overRest(i,s,u){return s=v(void 0===s?i.length-1:s,0),function(){for(var _=arguments,j=-1,M=v(_.length-s,0),$=Array(M);++j{var m=u(97786),v=u(14259);i.exports=function parent(i,s){return s.length<2?i:m(i,v(s,0,-1))}},52060:i=>{i.exports={}},90451:(i,s,u)=>{var m=u(278),v=u(65776),_=Math.min;i.exports=function reorder(i,s){for(var u=i.length,j=_(s.length,u),M=m(i);j--;){var $=s[j];i[j]=v($,u)?M[$]:void 0}return i}},46460:i=>{var s="__lodash_placeholder__";i.exports=function replaceHolders(i,u){for(var m=-1,v=i.length,_=0,j=[];++m{var m=u(31957),v="object"==typeof self&&self&&self.Object===Object&&self,_=m||v||Function("return this")();i.exports=_},36390:i=>{i.exports=function safeGet(i,s){if(("constructor"!==s||"function"!=typeof i[s])&&"__proto__"!=s)return i[s]}},90619:i=>{i.exports=function setCacheAdd(i){return this.__data__.set(i,"__lodash_hash_undefined__"),this}},72385:i=>{i.exports=function setCacheHas(i){return this.__data__.has(i)}},258:(i,s,u)=>{var m=u(28045),v=u(21275)(m);i.exports=v},21814:i=>{i.exports=function setToArray(i){var s=-1,u=Array(i.size);return i.forEach((function(i){u[++s]=i})),u}},30061:(i,s,u)=>{var m=u(56560),v=u(21275)(m);i.exports=v},69255:(i,s,u)=>{var m=u(58775),v=u(83112),_=u(30061),j=u(87241);i.exports=function setWrapToString(i,s,u){var M=s+"";return _(i,v(M,j(m(M),u)))}},21275:i=>{var s=Date.now;i.exports=function shortOut(i){var u=0,m=0;return function(){var v=s(),_=16-(v-m);if(m=v,_>0){if(++u>=800)return arguments[0]}else u=0;return i.apply(void 0,arguments)}}},37465:(i,s,u)=>{var m=u(38407);i.exports=function stackClear(){this.__data__=new m,this.size=0}},63779:i=>{i.exports=function stackDelete(i){var s=this.__data__,u=s.delete(i);return this.size=s.size,u}},67599:i=>{i.exports=function stackGet(i){return this.__data__.get(i)}},44758:i=>{i.exports=function stackHas(i){return this.__data__.has(i)}},34309:(i,s,u)=>{var m=u(38407),v=u(57071),_=u(83369);i.exports=function stackSet(i,s){var u=this.__data__;if(u instanceof m){var j=u.__data__;if(!v||j.length<199)return j.push([i,s]),this.size=++u.size,this;u=this.__data__=new _(j)}return u.set(i,s),this.size=u.size,this}},42351:i=>{i.exports=function strictIndexOf(i,s,u){for(var m=u-1,v=i.length;++m{var m=u(44286),v=u(62689),_=u(676);i.exports=function stringToArray(i){return v(i)?_(i):m(i)}},55514:(i,s,u)=>{var m=u(24523),v=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,_=/\\(\\)?/g,j=m((function(i){var s=[];return 46===i.charCodeAt(0)&&s.push(""),i.replace(v,(function(i,u,m,v){s.push(m?v.replace(_,"$1"):u||i)})),s}));i.exports=j},40327:(i,s,u)=>{var m=u(33448);i.exports=function toKey(i){if("string"==typeof i||m(i))return i;var s=i+"";return"0"==s&&1/i==-Infinity?"-0":s}},80346:i=>{var s=Function.prototype.toString;i.exports=function toSource(i){if(null!=i){try{return s.call(i)}catch(i){}try{return i+""}catch(i){}}return""}},67990:i=>{var s=/\s/;i.exports=function trimmedEndIndex(i){for(var u=i.length;u--&&s.test(i.charAt(u)););return u}},676:i=>{var s="\\ud800-\\udfff",u="["+s+"]",m="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",v="\\ud83c[\\udffb-\\udfff]",_="[^"+s+"]",j="(?:\\ud83c[\\udde6-\\uddff]){2}",M="[\\ud800-\\udbff][\\udc00-\\udfff]",$="(?:"+m+"|"+v+")"+"?",W="[\\ufe0e\\ufe0f]?",X=W+$+("(?:\\u200d(?:"+[_,j,M].join("|")+")"+W+$+")*"),Y="(?:"+[_+m+"?",m,j,M,u].join("|")+")",Z=RegExp(v+"(?="+v+")|"+Y+X,"g");i.exports=function unicodeToArray(i){return i.match(Z)||[]}},2757:i=>{var s="\\ud800-\\udfff",u="\\u2700-\\u27bf",m="a-z\\xdf-\\xf6\\xf8-\\xff",v="A-Z\\xc0-\\xd6\\xd8-\\xde",_="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",j="["+_+"]",M="\\d+",$="["+u+"]",W="["+m+"]",X="[^"+s+_+M+u+m+v+"]",Y="(?:\\ud83c[\\udde6-\\uddff]){2}",Z="[\\ud800-\\udbff][\\udc00-\\udfff]",ee="["+v+"]",ae="(?:"+W+"|"+X+")",ie="(?:"+ee+"|"+X+")",le="(?:['’](?:d|ll|m|re|s|t|ve))?",ce="(?:['’](?:D|LL|M|RE|S|T|VE))?",pe="(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?",de="[\\ufe0e\\ufe0f]?",fe=de+pe+("(?:\\u200d(?:"+["[^"+s+"]",Y,Z].join("|")+")"+de+pe+")*"),ye="(?:"+[$,Y,Z].join("|")+")"+fe,be=RegExp([ee+"?"+W+"+"+le+"(?="+[j,ee,"$"].join("|")+")",ie+"+"+ce+"(?="+[j,ee+ae,"$"].join("|")+")",ee+"?"+ae+"+"+le,ee+"+"+ce,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",M,ye].join("|"),"g");i.exports=function unicodeWords(i){return i.match(be)||[]}},87241:(i,s,u)=>{var m=u(77412),v=u(47443),_=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]];i.exports=function updateWrapDetails(i,s){return m(_,(function(u){var m="_."+u[0];s&u[1]&&!v(i,m)&&i.push(m)})),i.sort()}},21913:(i,s,u)=>{var m=u(96425),v=u(7548),_=u(278);i.exports=function wrapperClone(i){if(i instanceof m)return i.clone();var s=new v(i.__wrapped__,i.__chain__);return s.__actions__=_(i.__actions__),s.__index__=i.__index__,s.__values__=i.__values__,s}},39514:(i,s,u)=>{var m=u(97727);i.exports=function ary(i,s,u){return s=u?void 0:s,s=i&&null==s?i.length:s,m(i,128,void 0,void 0,void 0,void 0,s)}},68929:(i,s,u)=>{var m=u(48403),v=u(35393)((function(i,s,u){return s=s.toLowerCase(),i+(u?m(s):s)}));i.exports=v},48403:(i,s,u)=>{var m=u(79833),v=u(11700);i.exports=function capitalize(i){return v(m(i).toLowerCase())}},66678:(i,s,u)=>{var m=u(85990);i.exports=function clone(i){return m(i,4)}},75703:i=>{i.exports=function constant(i){return function(){return i}}},40087:(i,s,u)=>{var m=u(97727);function curry(i,s,u){var v=m(i,8,void 0,void 0,void 0,void 0,void 0,s=u?void 0:s);return v.placeholder=curry.placeholder,v}curry.placeholder={},i.exports=curry},23279:(i,s,u)=>{var m=u(13218),v=u(7771),_=u(14841),j=Math.max,M=Math.min;i.exports=function debounce(i,s,u){var $,W,X,Y,Z,ee,ae=0,ie=!1,le=!1,ce=!0;if("function"!=typeof i)throw new TypeError("Expected a function");function invokeFunc(s){var u=$,m=W;return $=W=void 0,ae=s,Y=i.apply(m,u)}function shouldInvoke(i){var u=i-ee;return void 0===ee||u>=s||u<0||le&&i-ae>=X}function timerExpired(){var i=v();if(shouldInvoke(i))return trailingEdge(i);Z=setTimeout(timerExpired,function remainingWait(i){var u=s-(i-ee);return le?M(u,X-(i-ae)):u}(i))}function trailingEdge(i){return Z=void 0,ce&&$?invokeFunc(i):($=W=void 0,Y)}function debounced(){var i=v(),u=shouldInvoke(i);if($=arguments,W=this,ee=i,u){if(void 0===Z)return function leadingEdge(i){return ae=i,Z=setTimeout(timerExpired,s),ie?invokeFunc(i):Y}(ee);if(le)return clearTimeout(Z),Z=setTimeout(timerExpired,s),invokeFunc(ee)}return void 0===Z&&(Z=setTimeout(timerExpired,s)),Y}return s=_(s)||0,m(u)&&(ie=!!u.leading,X=(le="maxWait"in u)?j(_(u.maxWait)||0,s):X,ce="trailing"in u?!!u.trailing:ce),debounced.cancel=function cancel(){void 0!==Z&&clearTimeout(Z),ae=0,$=ee=W=Z=void 0},debounced.flush=function flush(){return void 0===Z?Y:trailingEdge(v())},debounced}},53816:(i,s,u)=>{var m=u(69389),v=u(79833),_=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,j=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g");i.exports=function deburr(i){return(i=v(i))&&i.replace(_,m).replace(j,"")}},77813:i=>{i.exports=function eq(i,s){return i===s||i!=i&&s!=s}},13311:(i,s,u)=>{var m=u(67740)(u(30998));i.exports=m},30998:(i,s,u)=>{var m=u(41848),v=u(67206),_=u(40554),j=Math.max;i.exports=function findIndex(i,s,u){var M=null==i?0:i.length;if(!M)return-1;var $=null==u?0:_(u);return $<0&&($=j(M+$,0)),m(i,v(s,3),$)}},85564:(i,s,u)=>{var m=u(21078);i.exports=function flatten(i){return(null==i?0:i.length)?m(i,1):[]}},84599:(i,s,u)=>{var m=u(68836),v=u(69306),_=Array.prototype.push;function baseAry(i,s){return 2==s?function(s,u){return i(s,u)}:function(s){return i(s)}}function cloneArray(i){for(var s=i?i.length:0,u=Array(s);s--;)u[s]=i[s];return u}function wrapImmutable(i,s){return function(){var u=arguments.length;if(u){for(var m=Array(u);u--;)m[u]=arguments[u];var v=m[0]=s.apply(void 0,m);return i.apply(void 0,m),v}}}i.exports=function baseConvert(i,s,u,j){var M="function"==typeof s,$=s===Object(s);if($&&(j=u,u=s,s=void 0),null==u)throw new TypeError;j||(j={});var W={cap:!("cap"in j)||j.cap,curry:!("curry"in j)||j.curry,fixed:!("fixed"in j)||j.fixed,immutable:!("immutable"in j)||j.immutable,rearg:!("rearg"in j)||j.rearg},X=M?u:v,Y="curry"in j&&j.curry,Z="fixed"in j&&j.fixed,ee="rearg"in j&&j.rearg,ae=M?u.runInContext():void 0,ie=M?u:{ary:i.ary,assign:i.assign,clone:i.clone,curry:i.curry,forEach:i.forEach,isArray:i.isArray,isError:i.isError,isFunction:i.isFunction,isWeakMap:i.isWeakMap,iteratee:i.iteratee,keys:i.keys,rearg:i.rearg,toInteger:i.toInteger,toPath:i.toPath},le=ie.ary,ce=ie.assign,pe=ie.clone,de=ie.curry,fe=ie.forEach,ye=ie.isArray,be=ie.isError,_e=ie.isFunction,we=ie.isWeakMap,Se=ie.keys,xe=ie.rearg,Pe=ie.toInteger,Ie=ie.toPath,Te=Se(m.aryMethod),Re={castArray:function(i){return function(){var s=arguments[0];return ye(s)?i(cloneArray(s)):i.apply(void 0,arguments)}},iteratee:function(i){return function(){var s=arguments[1],u=i(arguments[0],s),m=u.length;return W.cap&&"number"==typeof s?(s=s>2?s-2:1,m&&m<=s?u:baseAry(u,s)):u}},mixin:function(i){return function(s){var u=this;if(!_e(u))return i(u,Object(s));var m=[];return fe(Se(s),(function(i){_e(s[i])&&m.push([i,u.prototype[i]])})),i(u,Object(s)),fe(m,(function(i){var s=i[1];_e(s)?u.prototype[i[0]]=s:delete u.prototype[i[0]]})),u}},nthArg:function(i){return function(s){var u=s<0?1:Pe(s)+1;return de(i(s),u)}},rearg:function(i){return function(s,u){var m=u?u.length:0;return de(i(s,u),m)}},runInContext:function(s){return function(u){return baseConvert(i,s(u),j)}}};function castCap(i,s){if(W.cap){var u=m.iterateeRearg[i];if(u)return function iterateeRearg(i,s){return overArg(i,(function(i){var u=s.length;return function baseArity(i,s){return 2==s?function(s,u){return i.apply(void 0,arguments)}:function(s){return i.apply(void 0,arguments)}}(xe(baseAry(i,u),s),u)}))}(s,u);var v=!M&&m.iterateeAry[i];if(v)return function iterateeAry(i,s){return overArg(i,(function(i){return"function"==typeof i?baseAry(i,s):i}))}(s,v)}return s}function castFixed(i,s,u){if(W.fixed&&(Z||!m.skipFixed[i])){var v=m.methodSpread[i],j=v&&v.start;return void 0===j?le(s,u):function flatSpread(i,s){return function(){for(var u=arguments.length,m=u-1,v=Array(u);u--;)v[u]=arguments[u];var j=v[s],M=v.slice(0,s);return j&&_.apply(M,j),s!=m&&_.apply(M,v.slice(s+1)),i.apply(this,M)}}(s,j)}return s}function castRearg(i,s,u){return W.rearg&&u>1&&(ee||!m.skipRearg[i])?xe(s,m.methodRearg[i]||m.aryRearg[u]):s}function cloneByPath(i,s){for(var u=-1,m=(s=Ie(s)).length,v=m-1,_=pe(Object(i)),j=_;null!=j&&++u1?de(s,u):s}(0,v=castCap(_,v),i),!1}})),!v})),v||(v=j),v==s&&(v=Y?de(v,1):function(){return s.apply(this,arguments)}),v.convert=createConverter(_,s),v.placeholder=s.placeholder=u,v}if(!$)return wrap(s,u,X);var qe=u,ze=[];return fe(Te,(function(i){fe(m.aryMethod[i],(function(i){var s=qe[m.remap[i]||i];s&&ze.push([i,wrap(i,s,qe)])}))})),fe(Se(qe),(function(i){var s=qe[i];if("function"==typeof s){for(var u=ze.length;u--;)if(ze[u][0]==i)return;s.convert=createConverter(i,s),ze.push([i,s])}})),fe(ze,(function(i){qe[i[0]]=i[1]})),qe.convert=function convertLib(i){return qe.runInContext.convert(i)(void 0)},qe.placeholder=qe,fe(Se(qe),(function(i){fe(m.realToAlias[i]||[],(function(s){qe[s]=qe[i]}))})),qe}},68836:(i,s)=>{s.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},s.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},s.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},s.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},s.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},s.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},s.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},s.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},s.realToAlias=function(){var i=Object.prototype.hasOwnProperty,u=s.aliasToReal,m={};for(var v in u){var _=u[v];i.call(m,_)?m[_].push(v):m[_]=[v]}return m}(),s.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},s.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},s.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},4269:(i,s,u)=>{i.exports={ary:u(39514),assign:u(44037),clone:u(66678),curry:u(40087),forEach:u(77412),isArray:u(1469),isError:u(64647),isFunction:u(23560),isWeakMap:u(81018),iteratee:u(72594),keys:u(280),rearg:u(4963),toInteger:u(40554),toPath:u(30084)}},72700:(i,s,u)=>{i.exports=u(28252)},92822:(i,s,u)=>{var m=u(84599),v=u(4269);i.exports=function convert(i,s,u){return m(v,i,s,u)}},69306:i=>{i.exports={}},28252:(i,s,u)=>{var m=u(92822)("set",u(36968));m.placeholder=u(69306),i.exports=m},27361:(i,s,u)=>{var m=u(97786);i.exports=function get(i,s,u){var v=null==i?void 0:m(i,s);return void 0===v?u:v}},79095:(i,s,u)=>{var m=u(13),v=u(222);i.exports=function hasIn(i,s){return null!=i&&v(i,s,m)}},6557:i=>{i.exports=function identity(i){return i}},35694:(i,s,u)=>{var m=u(9454),v=u(37005),_=Object.prototype,j=_.hasOwnProperty,M=_.propertyIsEnumerable,$=m(function(){return arguments}())?m:function(i){return v(i)&&j.call(i,"callee")&&!M.call(i,"callee")};i.exports=$},1469:i=>{var s=Array.isArray;i.exports=s},98612:(i,s,u)=>{var m=u(23560),v=u(41780);i.exports=function isArrayLike(i){return null!=i&&v(i.length)&&!m(i)}},29246:(i,s,u)=>{var m=u(98612),v=u(37005);i.exports=function isArrayLikeObject(i){return v(i)&&m(i)}},51584:(i,s,u)=>{var m=u(44239),v=u(37005);i.exports=function isBoolean(i){return!0===i||!1===i||v(i)&&"[object Boolean]"==m(i)}},44144:(i,s,u)=>{i=u.nmd(i);var m=u(55639),v=u(95062),_=s&&!s.nodeType&&s,j=_&&i&&!i.nodeType&&i,M=j&&j.exports===_?m.Buffer:void 0,$=(M?M.isBuffer:void 0)||v;i.exports=$},41609:(i,s,u)=>{var m=u(280),v=u(64160),_=u(35694),j=u(1469),M=u(98612),$=u(44144),W=u(25726),X=u(36719),Y=Object.prototype.hasOwnProperty;i.exports=function isEmpty(i){if(null==i)return!0;if(M(i)&&(j(i)||"string"==typeof i||"function"==typeof i.splice||$(i)||X(i)||_(i)))return!i.length;var s=v(i);if("[object Map]"==s||"[object Set]"==s)return!i.size;if(W(i))return!m(i).length;for(var u in i)if(Y.call(i,u))return!1;return!0}},18446:(i,s,u)=>{var m=u(90939);i.exports=function isEqual(i,s){return m(i,s)}},64647:(i,s,u)=>{var m=u(44239),v=u(37005),_=u(68630);i.exports=function isError(i){if(!v(i))return!1;var s=m(i);return"[object Error]"==s||"[object DOMException]"==s||"string"==typeof i.message&&"string"==typeof i.name&&!_(i)}},23560:(i,s,u)=>{var m=u(44239),v=u(13218);i.exports=function isFunction(i){if(!v(i))return!1;var s=m(i);return"[object Function]"==s||"[object GeneratorFunction]"==s||"[object AsyncFunction]"==s||"[object Proxy]"==s}},41780:i=>{i.exports=function isLength(i){return"number"==typeof i&&i>-1&&i%1==0&&i<=9007199254740991}},56688:(i,s,u)=>{var m=u(25588),v=u(7518),_=u(31167),j=_&&_.isMap,M=j?v(j):m;i.exports=M},45220:i=>{i.exports=function isNull(i){return null===i}},81763:(i,s,u)=>{var m=u(44239),v=u(37005);i.exports=function isNumber(i){return"number"==typeof i||v(i)&&"[object Number]"==m(i)}},13218:i=>{i.exports=function isObject(i){var s=typeof i;return null!=i&&("object"==s||"function"==s)}},37005:i=>{i.exports=function isObjectLike(i){return null!=i&&"object"==typeof i}},68630:(i,s,u)=>{var m=u(44239),v=u(85924),_=u(37005),j=Function.prototype,M=Object.prototype,$=j.toString,W=M.hasOwnProperty,X=$.call(Object);i.exports=function isPlainObject(i){if(!_(i)||"[object Object]"!=m(i))return!1;var s=v(i);if(null===s)return!0;var u=W.call(s,"constructor")&&s.constructor;return"function"==typeof u&&u instanceof u&&$.call(u)==X}},72928:(i,s,u)=>{var m=u(29221),v=u(7518),_=u(31167),j=_&&_.isSet,M=j?v(j):m;i.exports=M},47037:(i,s,u)=>{var m=u(44239),v=u(1469),_=u(37005);i.exports=function isString(i){return"string"==typeof i||!v(i)&&_(i)&&"[object String]"==m(i)}},33448:(i,s,u)=>{var m=u(44239),v=u(37005);i.exports=function isSymbol(i){return"symbol"==typeof i||v(i)&&"[object Symbol]"==m(i)}},36719:(i,s,u)=>{var m=u(38749),v=u(7518),_=u(31167),j=_&&_.isTypedArray,M=j?v(j):m;i.exports=M},81018:(i,s,u)=>{var m=u(64160),v=u(37005);i.exports=function isWeakMap(i){return v(i)&&"[object WeakMap]"==m(i)}},72594:(i,s,u)=>{var m=u(85990),v=u(67206);i.exports=function iteratee(i){return v("function"==typeof i?i:m(i,1))}},3674:(i,s,u)=>{var m=u(14636),v=u(280),_=u(98612);i.exports=function keys(i){return _(i)?m(i):v(i)}},81704:(i,s,u)=>{var m=u(14636),v=u(10313),_=u(98612);i.exports=function keysIn(i){return _(i)?m(i,!0):v(i)}},10928:i=>{i.exports=function last(i){var s=null==i?0:i.length;return s?i[s-1]:void 0}},88306:(i,s,u)=>{var m=u(83369);function memoize(i,s){if("function"!=typeof i||null!=s&&"function"!=typeof s)throw new TypeError("Expected a function");var memoized=function(){var u=arguments,m=s?s.apply(this,u):u[0],v=memoized.cache;if(v.has(m))return v.get(m);var _=i.apply(this,u);return memoized.cache=v.set(m,_)||v,_};return memoized.cache=new(memoize.Cache||m),memoized}memoize.Cache=m,i.exports=memoize},82492:(i,s,u)=>{var m=u(42980),v=u(21463)((function(i,s,u){m(i,s,u)}));i.exports=v},94885:i=>{i.exports=function negate(i){if("function"!=typeof i)throw new TypeError("Expected a function");return function(){var s=arguments;switch(s.length){case 0:return!i.call(this);case 1:return!i.call(this,s[0]);case 2:return!i.call(this,s[0],s[1]);case 3:return!i.call(this,s[0],s[1],s[2])}return!i.apply(this,s)}}},50308:i=>{i.exports=function noop(){}},7771:(i,s,u)=>{var m=u(55639);i.exports=function(){return m.Date.now()}},57557:(i,s,u)=>{var m=u(29932),v=u(85990),_=u(57406),j=u(71811),M=u(98363),$=u(60696),W=u(99021),X=u(46904),Y=W((function(i,s){var u={};if(null==i)return u;var W=!1;s=m(s,(function(s){return s=j(s,i),W||(W=s.length>1),s})),M(i,X(i),u),W&&(u=v(u,7,$));for(var Y=s.length;Y--;)_(u,s[Y]);return u}));i.exports=Y},39601:(i,s,u)=>{var m=u(40371),v=u(79152),_=u(15403),j=u(40327);i.exports=function property(i){return _(i)?m(j(i)):v(i)}},4963:(i,s,u)=>{var m=u(97727),v=u(99021),_=v((function(i,s){return m(i,256,void 0,void 0,void 0,s)}));i.exports=_},54061:(i,s,u)=>{var m=u(62663),v=u(89881),_=u(67206),j=u(10107),M=u(1469);i.exports=function reduce(i,s,u){var $=M(i)?m:j,W=arguments.length<3;return $(i,_(s,4),u,W,v)}},36968:(i,s,u)=>{var m=u(10611);i.exports=function set(i,s,u){return null==i?i:m(i,s,u)}},59704:(i,s,u)=>{var m=u(82908),v=u(67206),_=u(5076),j=u(1469),M=u(16612);i.exports=function some(i,s,u){var $=j(i)?m:_;return u&&M(i,s,u)&&(s=void 0),$(i,v(s,3))}},70479:i=>{i.exports=function stubArray(){return[]}},95062:i=>{i.exports=function stubFalse(){return!1}},18601:(i,s,u)=>{var m=u(14841),v=1/0;i.exports=function toFinite(i){return i?(i=m(i))===v||i===-1/0?17976931348623157e292*(i<0?-1:1):i==i?i:0:0===i?i:0}},40554:(i,s,u)=>{var m=u(18601);i.exports=function toInteger(i){var s=m(i),u=s%1;return s==s?u?s-u:s:0}},7334:(i,s,u)=>{var m=u(79833);i.exports=function toLower(i){return m(i).toLowerCase()}},14841:(i,s,u)=>{var m=u(27561),v=u(13218),_=u(33448),j=/^[-+]0x[0-9a-f]+$/i,M=/^0b[01]+$/i,$=/^0o[0-7]+$/i,W=parseInt;i.exports=function toNumber(i){if("number"==typeof i)return i;if(_(i))return NaN;if(v(i)){var s="function"==typeof i.valueOf?i.valueOf():i;i=v(s)?s+"":s}if("string"!=typeof i)return 0===i?i:+i;i=m(i);var u=M.test(i);return u||$.test(i)?W(i.slice(2),u?2:8):j.test(i)?NaN:+i}},30084:(i,s,u)=>{var m=u(29932),v=u(278),_=u(1469),j=u(33448),M=u(55514),$=u(40327),W=u(79833);i.exports=function toPath(i){return _(i)?m(i,$):j(i)?[i]:v(M(W(i)))}},59881:(i,s,u)=>{var m=u(98363),v=u(81704);i.exports=function toPlainObject(i){return m(i,v(i))}},79833:(i,s,u)=>{var m=u(80531);i.exports=function toString(i){return null==i?"":m(i)}},11700:(i,s,u)=>{var m=u(98805)("toUpperCase");i.exports=m},58748:(i,s,u)=>{var m=u(49029),v=u(93157),_=u(79833),j=u(2757);i.exports=function words(i,s,u){return i=_(i),void 0===(s=u?void 0:s)?v(i)?j(i):m(i):i.match(s)||[]}},8111:(i,s,u)=>{var m=u(96425),v=u(7548),_=u(9435),j=u(1469),M=u(37005),$=u(21913),W=Object.prototype.hasOwnProperty;function lodash(i){if(M(i)&&!j(i)&&!(i instanceof m)){if(i instanceof v)return i;if(W.call(i,"__wrapped__"))return $(i)}return new v(i)}lodash.prototype=_.prototype,lodash.prototype.constructor=lodash,i.exports=lodash},7287:(i,s,u)=>{var m=u(34865),v=u(1757);i.exports=function zipObject(i,s){return v(i||[],s||[],m)}},96470:(i,s,u)=>{"use strict";var m=u(47802),v=u(21102);s.highlight=highlight,s.highlightAuto=function highlightAuto(i,s){var u,j,M,$,W=s||{},X=W.subset||m.listLanguages(),Y=W.prefix,Z=X.length,ee=-1;null==Y&&(Y=_);if("string"!=typeof i)throw v("Expected `string` for value, got `%s`",i);j={relevance:0,language:null,value:[]},u={relevance:0,language:null,value:[]};for(;++eej.relevance&&(j=M),M.relevance>u.relevance&&(j=u,u=M));j.language&&(u.secondBest=j);return u},s.registerLanguage=function registerLanguage(i,s){m.registerLanguage(i,s)},s.listLanguages=function listLanguages(){return m.listLanguages()},s.registerAlias=function registerAlias(i,s){var u,v=i;s&&((v={})[i]=s);for(u in v)m.registerAliases(v[u],{languageName:u})},Emitter.prototype.addText=function text(i){var s,u,m=this.stack;if(""===i)return;s=m[m.length-1],(u=s.children[s.children.length-1])&&"text"===u.type?u.value+=i:s.children.push({type:"text",value:i})},Emitter.prototype.addKeyword=function addKeyword(i,s){this.openNode(s),this.addText(i),this.closeNode()},Emitter.prototype.addSublanguage=function addSublanguage(i,s){var u=this.stack,m=u[u.length-1],v=i.rootNode.children,_=s?{type:"element",tagName:"span",properties:{className:[s]},children:v}:v;m.children=m.children.concat(_)},Emitter.prototype.openNode=function open(i){var s=this.stack,u=this.options.classPrefix+i,m=s[s.length-1],v={type:"element",tagName:"span",properties:{className:[u]},children:[]};m.children.push(v),s.push(v)},Emitter.prototype.closeNode=function close(){this.stack.pop()},Emitter.prototype.closeAllNodes=noop,Emitter.prototype.finalize=noop,Emitter.prototype.toHTML=function toHtmlNoop(){return""};var _="hljs-";function highlight(i,s,u){var j,M=m.configure({}),$=(u||{}).prefix;if("string"!=typeof i)throw v("Expected `string` for name, got `%s`",i);if(!m.getLanguage(i))throw v("Unknown language: `%s` is not registered",i);if("string"!=typeof s)throw v("Expected `string` for value, got `%s`",s);if(null==$&&($=_),m.configure({__emitter:Emitter,classPrefix:$}),j=m.highlight(s,{language:i,ignoreIllegals:!0}),m.configure(M||{}),j.errorRaised)throw j.errorRaised;return{relevance:j.relevance,language:j.language,value:j.emitter.rootNode.children}}function Emitter(i){this.options=i,this.rootNode={children:[]},this.stack=[this.rootNode]}function noop(){}},42566:(i,s,u)=>{const m=u(94885);function coerceElementMatchingCallback(i){return"string"==typeof i?s=>s.element===i:i.constructor&&i.extend?s=>s instanceof i:i}class ArraySlice{constructor(i){this.elements=i||[]}toValue(){return this.elements.map((i=>i.toValue()))}map(i,s){return this.elements.map(i,s)}flatMap(i,s){return this.map(i,s).reduce(((i,s)=>i.concat(s)),[])}compactMap(i,s){const u=[];return this.forEach((m=>{const v=i.bind(s)(m);v&&u.push(v)})),u}filter(i,s){return i=coerceElementMatchingCallback(i),new ArraySlice(this.elements.filter(i,s))}reject(i,s){return i=coerceElementMatchingCallback(i),new ArraySlice(this.elements.filter(m(i),s))}find(i,s){return i=coerceElementMatchingCallback(i),this.elements.find(i,s)}forEach(i,s){this.elements.forEach(i,s)}reduce(i,s){return this.elements.reduce(i,s)}includes(i){return this.elements.some((s=>s.equals(i)))}shift(){return this.elements.shift()}unshift(i){this.elements.unshift(this.refract(i))}push(i){return this.elements.push(this.refract(i)),this}add(i){this.push(i)}get(i){return this.elements[i]}getValue(i){const s=this.elements[i];if(s)return s.toValue()}get length(){return this.elements.length}get isEmpty(){return 0===this.elements.length}get first(){return this.elements[0]}}"undefined"!=typeof Symbol&&(ArraySlice.prototype[Symbol.iterator]=function symbol(){return this.elements[Symbol.iterator]()}),i.exports=ArraySlice},17645:i=>{class KeyValuePair{constructor(i,s){this.key=i,this.value=s}clone(){const i=new KeyValuePair;return this.key&&(i.key=this.key.clone()),this.value&&(i.value=this.value.clone()),i}}i.exports=KeyValuePair},78520:(i,s,u)=>{const m=u(45220),v=u(47037),_=u(81763),j=u(51584),M=u(13218),$=u(28219),W=u(99829);class Namespace{constructor(i){this.elementMap={},this.elementDetection=[],this.Element=W.Element,this.KeyValuePair=W.KeyValuePair,i&&i.noDefault||this.useDefault(),this._attributeElementKeys=[],this._attributeElementArrayKeys=[]}use(i){return i.namespace&&i.namespace({base:this}),i.load&&i.load({base:this}),this}useDefault(){return this.register("null",W.NullElement).register("string",W.StringElement).register("number",W.NumberElement).register("boolean",W.BooleanElement).register("array",W.ArrayElement).register("object",W.ObjectElement).register("member",W.MemberElement).register("ref",W.RefElement).register("link",W.LinkElement),this.detect(m,W.NullElement,!1).detect(v,W.StringElement,!1).detect(_,W.NumberElement,!1).detect(j,W.BooleanElement,!1).detect(Array.isArray,W.ArrayElement,!1).detect(M,W.ObjectElement,!1),this}register(i,s){return this._elements=void 0,this.elementMap[i]=s,this}unregister(i){return this._elements=void 0,delete this.elementMap[i],this}detect(i,s,u){return void 0===u||u?this.elementDetection.unshift([i,s]):this.elementDetection.push([i,s]),this}toElement(i){if(i instanceof this.Element)return i;let s;for(let u=0;u{const s=i[0].toUpperCase()+i.substr(1);this._elements[s]=this.elementMap[i]}))),this._elements}get serialiser(){return new $(this)}}$.prototype.Namespace=Namespace,i.exports=Namespace},87526:(i,s,u)=>{const m=u(94885),v=u(42566);class ObjectSlice extends v{map(i,s){return this.elements.map((u=>i.bind(s)(u.value,u.key,u)))}filter(i,s){return new ObjectSlice(this.elements.filter((u=>i.bind(s)(u.value,u.key,u))))}reject(i,s){return this.filter(m(i.bind(s)))}forEach(i,s){return this.elements.forEach(((u,m)=>{i.bind(s)(u.value,u.key,u,m)}))}keys(){return this.map(((i,s)=>s.toValue()))}values(){return this.map((i=>i.toValue()))}}i.exports=ObjectSlice},99829:(i,s,u)=>{const m=u(3079),v=u(96295),_=u(16036),j=u(91090),M=u(18866),$=u(35804),W=u(5946),X=u(76735),Y=u(59964),Z=u(38588),ee=u(42566),ae=u(87526),ie=u(17645);function refract(i){if(i instanceof m)return i;if("string"==typeof i)return new _(i);if("number"==typeof i)return new j(i);if("boolean"==typeof i)return new M(i);if(null===i)return new v;if(Array.isArray(i))return new $(i.map(refract));if("object"==typeof i){return new X(i)}return i}m.prototype.ObjectElement=X,m.prototype.RefElement=Z,m.prototype.MemberElement=W,m.prototype.refract=refract,ee.prototype.refract=refract,i.exports={Element:m,NullElement:v,StringElement:_,NumberElement:j,BooleanElement:M,ArrayElement:$,MemberElement:W,ObjectElement:X,LinkElement:Y,RefElement:Z,refract,ArraySlice:ee,ObjectSlice:ae,KeyValuePair:ie}},59964:(i,s,u)=>{const m=u(3079);i.exports=class LinkElement extends m{constructor(i,s,u){super(i||[],s,u),this.element="link"}get relation(){return this.attributes.get("relation")}set relation(i){this.attributes.set("relation",i)}get href(){return this.attributes.get("href")}set href(i){this.attributes.set("href",i)}}},38588:(i,s,u)=>{const m=u(3079);i.exports=class RefElement extends m{constructor(i,s,u){super(i||[],s,u),this.element="ref",this.path||(this.path="element")}get path(){return this.attributes.get("path")}set path(i){this.attributes.set("path",i)}}},43500:(i,s,u)=>{const m=u(78520),v=u(99829);s.lS=m,u(17645),s.O4=v.ArraySlice,v.ObjectSlice,s.W_=v.Element,s.RP=v.StringElement,s.VL=v.NumberElement,s.hh=v.BooleanElement,s.zr=v.NullElement,s.ON=v.ArrayElement,s.Sb=v.ObjectElement,s.c6=v.MemberElement,s.tK=v.RefElement,s.EA=v.LinkElement,s.Qc=v.refract,u(28219),u(3414)},35804:(i,s,u)=>{const m=u(94885),v=u(3079),_=u(42566);class ArrayElement extends v{constructor(i,s,u){super(i||[],s,u),this.element="array"}primitive(){return"array"}get(i){return this.content[i]}getValue(i){const s=this.get(i);if(s)return s.toValue()}getIndex(i){return this.content[i]}set(i,s){return this.content[i]=this.refract(s),this}remove(i){const s=this.content.splice(i,1);return s.length?s[0]:null}map(i,s){return this.content.map(i,s)}flatMap(i,s){return this.map(i,s).reduce(((i,s)=>i.concat(s)),[])}compactMap(i,s){const u=[];return this.forEach((m=>{const v=i.bind(s)(m);v&&u.push(v)})),u}filter(i,s){return new _(this.content.filter(i,s))}reject(i,s){return this.filter(m(i),s)}reduce(i,s){let u,m;void 0!==s?(u=0,m=this.refract(s)):(u=1,m="object"===this.primitive()?this.first.value:this.first);for(let s=u;s{i.bind(s)(u,this.refract(m))}))}shift(){return this.content.shift()}unshift(i){this.content.unshift(this.refract(i))}push(i){return this.content.push(this.refract(i)),this}add(i){this.push(i)}findElements(i,s){const u=s||{},m=!!u.recursive,v=void 0===u.results?[]:u.results;return this.forEach(((s,u,_)=>{m&&void 0!==s.findElements&&s.findElements(i,{results:v,recursive:m}),i(s,u,_)&&v.push(s)})),v}find(i){return new _(this.findElements(i,{recursive:!0}))}findByElement(i){return this.find((s=>s.element===i))}findByClass(i){return this.find((s=>s.classes.includes(i)))}getById(i){return this.find((s=>s.id.toValue()===i)).first}includes(i){return this.content.some((s=>s.equals(i)))}contains(i){return this.includes(i)}empty(){return new this.constructor([])}"fantasy-land/empty"(){return this.empty()}concat(i){return new this.constructor(this.content.concat(i.content))}"fantasy-land/concat"(i){return this.concat(i)}"fantasy-land/map"(i){return new this.constructor(this.map(i))}"fantasy-land/chain"(i){return this.map((s=>i(s)),this).reduce(((i,s)=>i.concat(s)),this.empty())}"fantasy-land/filter"(i){return new this.constructor(this.content.filter(i))}"fantasy-land/reduce"(i,s){return this.content.reduce(i,s)}get length(){return this.content.length}get isEmpty(){return 0===this.content.length}get first(){return this.getIndex(0)}get second(){return this.getIndex(1)}get last(){return this.getIndex(this.length-1)}}ArrayElement.empty=function empty(){return new this},ArrayElement["fantasy-land/empty"]=ArrayElement.empty,"undefined"!=typeof Symbol&&(ArrayElement.prototype[Symbol.iterator]=function symbol(){return this.content[Symbol.iterator]()}),i.exports=ArrayElement},18866:(i,s,u)=>{const m=u(3079);i.exports=class BooleanElement extends m{constructor(i,s,u){super(i,s,u),this.element="boolean"}primitive(){return"boolean"}}},3079:(i,s,u)=>{const m=u(18446),v=u(17645),_=u(42566);class Element{constructor(i,s,u){s&&(this.meta=s),u&&(this.attributes=u),this.content=i}freeze(){Object.isFrozen(this)||(this._meta&&(this.meta.parent=this,this.meta.freeze()),this._attributes&&(this.attributes.parent=this,this.attributes.freeze()),this.children.forEach((i=>{i.parent=this,i.freeze()}),this),this.content&&Array.isArray(this.content)&&Object.freeze(this.content),Object.freeze(this))}primitive(){}clone(){const i=new this.constructor;return i.element=this.element,this.meta.length&&(i._meta=this.meta.clone()),this.attributes.length&&(i._attributes=this.attributes.clone()),this.content?this.content.clone?i.content=this.content.clone():Array.isArray(this.content)?i.content=this.content.map((i=>i.clone())):i.content=this.content:i.content=this.content,i}toValue(){return this.content instanceof Element?this.content.toValue():this.content instanceof v?{key:this.content.key.toValue(),value:this.content.value?this.content.value.toValue():void 0}:this.content&&this.content.map?this.content.map((i=>i.toValue()),this):this.content}toRef(i){if(""===this.id.toValue())throw Error("Cannot create reference to an element that does not contain an ID");const s=new this.RefElement(this.id.toValue());return i&&(s.path=i),s}findRecursive(...i){if(arguments.length>1&&!this.isFrozen)throw new Error("Cannot find recursive with multiple element names without first freezing the element. Call `element.freeze()`");const s=i.pop();let u=new _;const append=(i,s)=>(i.push(s),i),checkElement=(i,u)=>{u.element===s&&i.push(u);const m=u.findRecursive(s);return m&&m.reduce(append,i),u.content instanceof v&&(u.content.key&&checkElement(i,u.content.key),u.content.value&&checkElement(i,u.content.value)),i};return this.content&&(this.content.element&&checkElement(u,this.content),Array.isArray(this.content)&&this.content.reduce(checkElement,u)),i.isEmpty||(u=u.filter((s=>{let u=s.parents.map((i=>i.element));for(const s in i){const m=i[s],v=u.indexOf(m);if(-1===v)return!1;u=u.splice(0,v)}return!0}))),u}set(i){return this.content=i,this}equals(i){return m(this.toValue(),i)}getMetaProperty(i,s){if(!this.meta.hasKey(i)){if(this.isFrozen){const i=this.refract(s);return i.freeze(),i}this.meta.set(i,s)}return this.meta.get(i)}setMetaProperty(i,s){this.meta.set(i,s)}get element(){return this._storedElement||"element"}set element(i){this._storedElement=i}get content(){return this._content}set content(i){if(i instanceof Element)this._content=i;else if(i instanceof _)this.content=i.elements;else if("string"==typeof i||"number"==typeof i||"boolean"==typeof i||"null"===i||null==i)this._content=i;else if(i instanceof v)this._content=i;else if(Array.isArray(i))this._content=i.map(this.refract);else{if("object"!=typeof i)throw new Error("Cannot set content to given value");this._content=Object.keys(i).map((s=>new this.MemberElement(s,i[s])))}}get meta(){if(!this._meta){if(this.isFrozen){const i=new this.ObjectElement;return i.freeze(),i}this._meta=new this.ObjectElement}return this._meta}set meta(i){i instanceof this.ObjectElement?this._meta=i:this.meta.set(i||{})}get attributes(){if(!this._attributes){if(this.isFrozen){const i=new this.ObjectElement;return i.freeze(),i}this._attributes=new this.ObjectElement}return this._attributes}set attributes(i){i instanceof this.ObjectElement?this._attributes=i:this.attributes.set(i||{})}get id(){return this.getMetaProperty("id","")}set id(i){this.setMetaProperty("id",i)}get classes(){return this.getMetaProperty("classes",[])}set classes(i){this.setMetaProperty("classes",i)}get title(){return this.getMetaProperty("title","")}set title(i){this.setMetaProperty("title",i)}get description(){return this.getMetaProperty("description","")}set description(i){this.setMetaProperty("description",i)}get links(){return this.getMetaProperty("links",[])}set links(i){this.setMetaProperty("links",i)}get isFrozen(){return Object.isFrozen(this)}get parents(){let{parent:i}=this;const s=new _;for(;i;)s.push(i),i=i.parent;return s}get children(){if(Array.isArray(this.content))return new _(this.content);if(this.content instanceof v){const i=new _([this.content.key]);return this.content.value&&i.push(this.content.value),i}return this.content instanceof Element?new _([this.content]):new _}get recursiveChildren(){const i=new _;return this.children.forEach((s=>{i.push(s),s.recursiveChildren.forEach((s=>{i.push(s)}))})),i}}i.exports=Element},5946:(i,s,u)=>{const m=u(17645),v=u(3079);i.exports=class MemberElement extends v{constructor(i,s,u,v){super(new m,u,v),this.element="member",this.key=i,this.value=s}get key(){return this.content.key}set key(i){this.content.key=this.refract(i)}get value(){return this.content.value}set value(i){this.content.value=this.refract(i)}}},96295:(i,s,u)=>{const m=u(3079);i.exports=class NullElement extends m{constructor(i,s,u){super(i||null,s,u),this.element="null"}primitive(){return"null"}set(){return new Error("Cannot set the value of null")}}},91090:(i,s,u)=>{const m=u(3079);i.exports=class NumberElement extends m{constructor(i,s,u){super(i,s,u),this.element="number"}primitive(){return"number"}}},76735:(i,s,u)=>{const m=u(94885),v=u(13218),_=u(35804),j=u(5946),M=u(87526);i.exports=class ObjectElement extends _{constructor(i,s,u){super(i||[],s,u),this.element="object"}primitive(){return"object"}toValue(){return this.content.reduce(((i,s)=>(i[s.key.toValue()]=s.value?s.value.toValue():void 0,i)),{})}get(i){const s=this.getMember(i);if(s)return s.value}getMember(i){if(void 0!==i)return this.content.find((s=>s.key.toValue()===i))}remove(i){let s=null;return this.content=this.content.filter((u=>u.key.toValue()!==i||(s=u,!1))),s}getKey(i){const s=this.getMember(i);if(s)return s.key}set(i,s){if(v(i))return Object.keys(i).forEach((s=>{this.set(s,i[s])})),this;const u=i,m=this.getMember(u);return m?m.value=s:this.content.push(new j(u,s)),this}keys(){return this.content.map((i=>i.key.toValue()))}values(){return this.content.map((i=>i.value.toValue()))}hasKey(i){return this.content.some((s=>s.key.equals(i)))}items(){return this.content.map((i=>[i.key.toValue(),i.value.toValue()]))}map(i,s){return this.content.map((u=>i.bind(s)(u.value,u.key,u)))}compactMap(i,s){const u=[];return this.forEach(((m,v,_)=>{const j=i.bind(s)(m,v,_);j&&u.push(j)})),u}filter(i,s){return new M(this.content).filter(i,s)}reject(i,s){return this.filter(m(i),s)}forEach(i,s){return this.content.forEach((u=>i.bind(s)(u.value,u.key,u)))}}},16036:(i,s,u)=>{const m=u(3079);i.exports=class StringElement extends m{constructor(i,s,u){super(i,s,u),this.element="string"}primitive(){return"string"}get length(){return this.content.length}}},3414:(i,s,u)=>{const m=u(28219);i.exports=class JSON06Serialiser extends m{serialise(i){if(!(i instanceof this.namespace.elements.Element))throw new TypeError(`Given element \`${i}\` is not an Element instance`);let s;i._attributes&&i.attributes.get("variable")&&(s=i.attributes.get("variable"));const u={element:i.element};i._meta&&i._meta.length>0&&(u.meta=this.serialiseObject(i.meta));const m="enum"===i.element||-1!==i.attributes.keys().indexOf("enumerations");if(m){const s=this.enumSerialiseAttributes(i);s&&(u.attributes=s)}else if(i._attributes&&i._attributes.length>0){let{attributes:m}=i;m.get("metadata")&&(m=m.clone(),m.set("meta",m.get("metadata")),m.remove("metadata")),"member"===i.element&&s&&(m=m.clone(),m.remove("variable")),m.length>0&&(u.attributes=this.serialiseObject(m))}if(m)u.content=this.enumSerialiseContent(i,u);else if(this[`${i.element}SerialiseContent`])u.content=this[`${i.element}SerialiseContent`](i,u);else if(void 0!==i.content){let m;s&&i.content.key?(m=i.content.clone(),m.key.attributes.set("variable",s),m=this.serialiseContent(m)):m=this.serialiseContent(i.content),this.shouldSerialiseContent(i,m)&&(u.content=m)}else this.shouldSerialiseContent(i,i.content)&&i instanceof this.namespace.elements.Array&&(u.content=[]);return u}shouldSerialiseContent(i,s){return"parseResult"===i.element||"httpRequest"===i.element||"httpResponse"===i.element||"category"===i.element||"link"===i.element||void 0!==s&&(!Array.isArray(s)||0!==s.length)}refSerialiseContent(i,s){return delete s.attributes,{href:i.toValue(),path:i.path.toValue()}}sourceMapSerialiseContent(i){return i.toValue()}dataStructureSerialiseContent(i){return[this.serialiseContent(i.content)]}enumSerialiseAttributes(i){const s=i.attributes.clone(),u=s.remove("enumerations")||new this.namespace.elements.Array([]),m=s.get("default");let v=s.get("samples")||new this.namespace.elements.Array([]);if(m&&m.content&&(m.content.attributes&&m.content.attributes.remove("typeAttributes"),s.set("default",new this.namespace.elements.Array([m.content]))),v.forEach((i=>{i.content&&i.content.element&&i.content.attributes.remove("typeAttributes")})),i.content&&0!==u.length&&v.unshift(i.content),v=v.map((i=>i instanceof this.namespace.elements.Array?[i]:new this.namespace.elements.Array([i.content]))),v.length&&s.set("samples",v),s.length>0)return this.serialiseObject(s)}enumSerialiseContent(i){if(i._attributes){const s=i.attributes.get("enumerations");if(s&&s.length>0)return s.content.map((i=>{const s=i.clone();return s.attributes.remove("typeAttributes"),this.serialise(s)}))}if(i.content){const s=i.content.clone();return s.attributes.remove("typeAttributes"),[this.serialise(s)]}return[]}deserialise(i){if("string"==typeof i)return new this.namespace.elements.String(i);if("number"==typeof i)return new this.namespace.elements.Number(i);if("boolean"==typeof i)return new this.namespace.elements.Boolean(i);if(null===i)return new this.namespace.elements.Null;if(Array.isArray(i))return new this.namespace.elements.Array(i.map(this.deserialise,this));const s=this.namespace.getElementClass(i.element),u=new s;u.element!==i.element&&(u.element=i.element),i.meta&&this.deserialiseObject(i.meta,u.meta),i.attributes&&this.deserialiseObject(i.attributes,u.attributes);const m=this.deserialiseContent(i.content);if(void 0===m&&null!==u.content||(u.content=m),"enum"===u.element){u.content&&u.attributes.set("enumerations",u.content);let i=u.attributes.get("samples");if(u.attributes.remove("samples"),i){const m=i;i=new this.namespace.elements.Array,m.forEach((m=>{m.forEach((m=>{const v=new s(m);v.element=u.element,i.push(v)}))}));const v=i.shift();u.content=v?v.content:void 0,u.attributes.set("samples",i)}else u.content=void 0;let m=u.attributes.get("default");if(m&&m.length>0){m=m.get(0);const i=new s(m);i.element=u.element,u.attributes.set("default",i)}}else if("dataStructure"===u.element&&Array.isArray(u.content))[u.content]=u.content;else if("category"===u.element){const i=u.attributes.get("meta");i&&(u.attributes.set("metadata",i),u.attributes.remove("meta"))}else"member"===u.element&&u.key&&u.key._attributes&&u.key._attributes.getValue("variable")&&(u.attributes.set("variable",u.key.attributes.get("variable")),u.key.attributes.remove("variable"));return u}serialiseContent(i){if(i instanceof this.namespace.elements.Element)return this.serialise(i);if(i instanceof this.namespace.KeyValuePair){const s={key:this.serialise(i.key)};return i.value&&(s.value=this.serialise(i.value)),s}return i&&i.map?i.map(this.serialise,this):i}deserialiseContent(i){if(i){if(i.element)return this.deserialise(i);if(i.key){const s=new this.namespace.KeyValuePair(this.deserialise(i.key));return i.value&&(s.value=this.deserialise(i.value)),s}if(i.map)return i.map(this.deserialise,this)}return i}shouldRefract(i){return!!(i._attributes&&i.attributes.keys().length||i._meta&&i.meta.keys().length)||"enum"!==i.element&&(i.element!==i.primitive()||"member"===i.element)}convertKeyToRefract(i,s){return this.shouldRefract(s)?this.serialise(s):"enum"===s.element?this.serialiseEnum(s):"array"===s.element?s.map((s=>this.shouldRefract(s)||"default"===i?this.serialise(s):"array"===s.element||"object"===s.element||"enum"===s.element?s.children.map((i=>this.serialise(i))):s.toValue())):"object"===s.element?(s.content||[]).map(this.serialise,this):s.toValue()}serialiseEnum(i){return i.children.map((i=>this.serialise(i)))}serialiseObject(i){const s={};return i.forEach(((i,u)=>{if(i){const m=u.toValue();s[m]=this.convertKeyToRefract(m,i)}})),s}deserialiseObject(i,s){Object.keys(i).forEach((u=>{s.set(u,this.deserialise(i[u]))}))}}},28219:i=>{i.exports=class JSONSerialiser{constructor(i){this.namespace=i||new this.Namespace}serialise(i){if(!(i instanceof this.namespace.elements.Element))throw new TypeError(`Given element \`${i}\` is not an Element instance`);const s={element:i.element};i._meta&&i._meta.length>0&&(s.meta=this.serialiseObject(i.meta)),i._attributes&&i._attributes.length>0&&(s.attributes=this.serialiseObject(i.attributes));const u=this.serialiseContent(i.content);return void 0!==u&&(s.content=u),s}deserialise(i){if(!i.element)throw new Error("Given value is not an object containing an element name");const s=new(this.namespace.getElementClass(i.element));s.element!==i.element&&(s.element=i.element),i.meta&&this.deserialiseObject(i.meta,s.meta),i.attributes&&this.deserialiseObject(i.attributes,s.attributes);const u=this.deserialiseContent(i.content);return void 0===u&&null!==s.content||(s.content=u),s}serialiseContent(i){if(i instanceof this.namespace.elements.Element)return this.serialise(i);if(i instanceof this.namespace.KeyValuePair){const s={key:this.serialise(i.key)};return i.value&&(s.value=this.serialise(i.value)),s}if(i&&i.map){if(0===i.length)return;return i.map(this.serialise,this)}return i}deserialiseContent(i){if(i){if(i.element)return this.deserialise(i);if(i.key){const s=new this.namespace.KeyValuePair(this.deserialise(i.key));return i.value&&(s.value=this.deserialise(i.value)),s}if(i.map)return i.map(this.deserialise,this)}return i}serialiseObject(i){const s={};if(i.forEach(((i,u)=>{i&&(s[u.toValue()]=this.serialise(i))})),0!==Object.keys(s).length)return s}deserialiseObject(i,s){Object.keys(i).forEach((u=>{s.set(u,this.deserialise(i[u]))}))}}},27418:i=>{"use strict";var s=Object.getOwnPropertySymbols,u=Object.prototype.hasOwnProperty,m=Object.prototype.propertyIsEnumerable;i.exports=function shouldUseNative(){try{if(!Object.assign)return!1;var i=new String("abc");if(i[5]="de","5"===Object.getOwnPropertyNames(i)[0])return!1;for(var s={},u=0;u<10;u++)s["_"+String.fromCharCode(u)]=u;if("0123456789"!==Object.getOwnPropertyNames(s).map((function(i){return s[i]})).join(""))return!1;var m={};return"abcdefghijklmnopqrst".split("").forEach((function(i){m[i]=i})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},m)).join("")}catch(i){return!1}}()?Object.assign:function(i,v){for(var _,j,M=function toObject(i){if(null==i)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(i)}(i),$=1;${var m="function"==typeof Map&&Map.prototype,v=Object.getOwnPropertyDescriptor&&m?Object.getOwnPropertyDescriptor(Map.prototype,"size"):null,_=m&&v&&"function"==typeof v.get?v.get:null,j=m&&Map.prototype.forEach,M="function"==typeof Set&&Set.prototype,$=Object.getOwnPropertyDescriptor&&M?Object.getOwnPropertyDescriptor(Set.prototype,"size"):null,W=M&&$&&"function"==typeof $.get?$.get:null,X=M&&Set.prototype.forEach,Y="function"==typeof WeakMap&&WeakMap.prototype?WeakMap.prototype.has:null,Z="function"==typeof WeakSet&&WeakSet.prototype?WeakSet.prototype.has:null,ee="function"==typeof WeakRef&&WeakRef.prototype?WeakRef.prototype.deref:null,ae=Boolean.prototype.valueOf,ie=Object.prototype.toString,le=Function.prototype.toString,ce=String.prototype.match,pe=String.prototype.slice,de=String.prototype.replace,fe=String.prototype.toUpperCase,ye=String.prototype.toLowerCase,be=RegExp.prototype.test,_e=Array.prototype.concat,we=Array.prototype.join,Se=Array.prototype.slice,xe=Math.floor,Pe="function"==typeof BigInt?BigInt.prototype.valueOf:null,Ie=Object.getOwnPropertySymbols,Te="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?Symbol.prototype.toString:null,Re="function"==typeof Symbol&&"object"==typeof Symbol.iterator,qe="function"==typeof Symbol&&Symbol.toStringTag&&(typeof Symbol.toStringTag===Re||"symbol")?Symbol.toStringTag:null,ze=Object.prototype.propertyIsEnumerable,Ve=("function"==typeof Reflect?Reflect.getPrototypeOf:Object.getPrototypeOf)||([].__proto__===Array.prototype?function(i){return i.__proto__}:null);function addNumericSeparator(i,s){if(i===1/0||i===-1/0||i!=i||i&&i>-1e3&&i<1e3||be.call(/e/,s))return s;var u=/[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;if("number"==typeof i){var m=i<0?-xe(-i):xe(i);if(m!==i){var v=String(m),_=pe.call(s,v.length+1);return de.call(v,u,"$&_")+"."+de.call(de.call(_,/([0-9]{3})/g,"$&_"),/_$/,"")}}return de.call(s,u,"$&_")}var We=u(24654),He=We.custom,Xe=isSymbol(He)?He:null;function wrapQuotes(i,s,u){var m="double"===(u.quoteStyle||s)?'"':"'";return m+i+m}function quote(i){return de.call(String(i),/"/g,""")}function isArray(i){return!("[object Array]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}function isRegExp(i){return!("[object RegExp]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}function isSymbol(i){if(Re)return i&&"object"==typeof i&&i instanceof Symbol;if("symbol"==typeof i)return!0;if(!i||"object"!=typeof i||!Te)return!1;try{return Te.call(i),!0}catch(i){}return!1}i.exports=function inspect_(i,s,u,m){var v=s||{};if(has(v,"quoteStyle")&&"single"!==v.quoteStyle&&"double"!==v.quoteStyle)throw new TypeError('option "quoteStyle" must be "single" or "double"');if(has(v,"maxStringLength")&&("number"==typeof v.maxStringLength?v.maxStringLength<0&&v.maxStringLength!==1/0:null!==v.maxStringLength))throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');var M=!has(v,"customInspect")||v.customInspect;if("boolean"!=typeof M&&"symbol"!==M)throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`");if(has(v,"indent")&&null!==v.indent&&"\t"!==v.indent&&!(parseInt(v.indent,10)===v.indent&&v.indent>0))throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');if(has(v,"numericSeparator")&&"boolean"!=typeof v.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var $=v.numericSeparator;if(void 0===i)return"undefined";if(null===i)return"null";if("boolean"==typeof i)return i?"true":"false";if("string"==typeof i)return inspectString(i,v);if("number"==typeof i){if(0===i)return 1/0/i>0?"0":"-0";var ie=String(i);return $?addNumericSeparator(i,ie):ie}if("bigint"==typeof i){var fe=String(i)+"n";return $?addNumericSeparator(i,fe):fe}var be=void 0===v.depth?5:v.depth;if(void 0===u&&(u=0),u>=be&&be>0&&"object"==typeof i)return isArray(i)?"[Array]":"[Object]";var xe=function getIndent(i,s){var u;if("\t"===i.indent)u="\t";else{if(!("number"==typeof i.indent&&i.indent>0))return null;u=we.call(Array(i.indent+1)," ")}return{base:u,prev:we.call(Array(s+1),u)}}(v,u);if(void 0===m)m=[];else if(indexOf(m,i)>=0)return"[Circular]";function inspect(i,s,_){if(s&&(m=Se.call(m)).push(s),_){var j={depth:v.depth};return has(v,"quoteStyle")&&(j.quoteStyle=v.quoteStyle),inspect_(i,j,u+1,m)}return inspect_(i,v,u+1,m)}if("function"==typeof i&&!isRegExp(i)){var Ie=function nameOf(i){if(i.name)return i.name;var s=ce.call(le.call(i),/^function\s*([\w$]+)/);if(s)return s[1];return null}(i),He=arrObjKeys(i,inspect);return"[Function"+(Ie?": "+Ie:" (anonymous)")+"]"+(He.length>0?" { "+we.call(He,", ")+" }":"")}if(isSymbol(i)){var Ye=Re?de.call(String(i),/^(Symbol\(.*\))_[^)]*$/,"$1"):Te.call(i);return"object"!=typeof i||Re?Ye:markBoxed(Ye)}if(function isElement(i){if(!i||"object"!=typeof i)return!1;if("undefined"!=typeof HTMLElement&&i instanceof HTMLElement)return!0;return"string"==typeof i.nodeName&&"function"==typeof i.getAttribute}(i)){for(var Qe="<"+ye.call(String(i.nodeName)),et=i.attributes||[],tt=0;tt"}if(isArray(i)){if(0===i.length)return"[]";var rt=arrObjKeys(i,inspect);return xe&&!function singleLineValues(i){for(var s=0;s=0)return!1;return!0}(rt)?"["+indentedJoin(rt,xe)+"]":"[ "+we.call(rt,", ")+" ]"}if(function isError(i){return!("[object Error]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}(i)){var nt=arrObjKeys(i,inspect);return"cause"in Error.prototype||!("cause"in i)||ze.call(i,"cause")?0===nt.length?"["+String(i)+"]":"{ ["+String(i)+"] "+we.call(nt,", ")+" }":"{ ["+String(i)+"] "+we.call(_e.call("[cause]: "+inspect(i.cause),nt),", ")+" }"}if("object"==typeof i&&M){if(Xe&&"function"==typeof i[Xe]&&We)return We(i,{depth:be-u});if("symbol"!==M&&"function"==typeof i.inspect)return i.inspect()}if(function isMap(i){if(!_||!i||"object"!=typeof i)return!1;try{_.call(i);try{W.call(i)}catch(i){return!0}return i instanceof Map}catch(i){}return!1}(i)){var ot=[];return j&&j.call(i,(function(s,u){ot.push(inspect(u,i,!0)+" => "+inspect(s,i))})),collectionOf("Map",_.call(i),ot,xe)}if(function isSet(i){if(!W||!i||"object"!=typeof i)return!1;try{W.call(i);try{_.call(i)}catch(i){return!0}return i instanceof Set}catch(i){}return!1}(i)){var at=[];return X&&X.call(i,(function(s){at.push(inspect(s,i))})),collectionOf("Set",W.call(i),at,xe)}if(function isWeakMap(i){if(!Y||!i||"object"!=typeof i)return!1;try{Y.call(i,Y);try{Z.call(i,Z)}catch(i){return!0}return i instanceof WeakMap}catch(i){}return!1}(i))return weakCollectionOf("WeakMap");if(function isWeakSet(i){if(!Z||!i||"object"!=typeof i)return!1;try{Z.call(i,Z);try{Y.call(i,Y)}catch(i){return!0}return i instanceof WeakSet}catch(i){}return!1}(i))return weakCollectionOf("WeakSet");if(function isWeakRef(i){if(!ee||!i||"object"!=typeof i)return!1;try{return ee.call(i),!0}catch(i){}return!1}(i))return weakCollectionOf("WeakRef");if(function isNumber(i){return!("[object Number]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}(i))return markBoxed(inspect(Number(i)));if(function isBigInt(i){if(!i||"object"!=typeof i||!Pe)return!1;try{return Pe.call(i),!0}catch(i){}return!1}(i))return markBoxed(inspect(Pe.call(i)));if(function isBoolean(i){return!("[object Boolean]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}(i))return markBoxed(ae.call(i));if(function isString(i){return!("[object String]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}(i))return markBoxed(inspect(String(i)));if(!function isDate(i){return!("[object Date]"!==toStr(i)||qe&&"object"==typeof i&&qe in i)}(i)&&!isRegExp(i)){var it=arrObjKeys(i,inspect),st=Ve?Ve(i)===Object.prototype:i instanceof Object||i.constructor===Object,lt=i instanceof Object?"":"null prototype",ct=!st&&qe&&Object(i)===i&&qe in i?pe.call(toStr(i),8,-1):lt?"Object":"",ut=(st||"function"!=typeof i.constructor?"":i.constructor.name?i.constructor.name+" ":"")+(ct||lt?"["+we.call(_e.call([],ct||[],lt||[]),": ")+"] ":"");return 0===it.length?ut+"{}":xe?ut+"{"+indentedJoin(it,xe)+"}":ut+"{ "+we.call(it,", ")+" }"}return String(i)};var Ye=Object.prototype.hasOwnProperty||function(i){return i in this};function has(i,s){return Ye.call(i,s)}function toStr(i){return ie.call(i)}function indexOf(i,s){if(i.indexOf)return i.indexOf(s);for(var u=0,m=i.length;us.maxStringLength){var u=i.length-s.maxStringLength,m="... "+u+" more character"+(u>1?"s":"");return inspectString(pe.call(i,0,s.maxStringLength),s)+m}return wrapQuotes(de.call(de.call(i,/(['\\])/g,"\\$1"),/[\x00-\x1f]/g,lowbyte),"single",s)}function lowbyte(i){var s=i.charCodeAt(0),u={8:"b",9:"t",10:"n",12:"f",13:"r"}[s];return u?"\\"+u:"\\x"+(s<16?"0":"")+fe.call(s.toString(16))}function markBoxed(i){return"Object("+i+")"}function weakCollectionOf(i){return i+" { ? }"}function collectionOf(i,s,u,m){return i+" ("+s+") {"+(m?indentedJoin(u,m):we.call(u,", "))+"}"}function indentedJoin(i,s){if(0===i.length)return"";var u="\n"+s.prev+s.base;return u+we.call(i,","+u)+"\n"+s.prev}function arrObjKeys(i,s){var u=isArray(i),m=[];if(u){m.length=i.length;for(var v=0;v{var s,u,m=i.exports={};function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}function runTimeout(i){if(s===setTimeout)return setTimeout(i,0);if((s===defaultSetTimout||!s)&&setTimeout)return s=setTimeout,setTimeout(i,0);try{return s(i,0)}catch(u){try{return s.call(null,i,0)}catch(u){return s.call(this,i,0)}}}!function(){try{s="function"==typeof setTimeout?setTimeout:defaultSetTimout}catch(i){s=defaultSetTimout}try{u="function"==typeof clearTimeout?clearTimeout:defaultClearTimeout}catch(i){u=defaultClearTimeout}}();var v,_=[],j=!1,M=-1;function cleanUpNextTick(){j&&v&&(j=!1,v.length?_=v.concat(_):M=-1,_.length&&drainQueue())}function drainQueue(){if(!j){var i=runTimeout(cleanUpNextTick);j=!0;for(var s=_.length;s;){for(v=_,_=[];++M1)for(var u=1;u{"use strict";var m=u(50414);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,i.exports=function(){function shim(i,s,u,v,_,j){if(j!==m){var M=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw M.name="Invariant Violation",M}}function getShim(){return shim}shim.isRequired=shim;var i={array:shim,bigint:shim,bool:shim,func:shim,number:shim,object:shim,string:shim,symbol:shim,any:shim,arrayOf:getShim,element:shim,elementType:shim,instanceOf:getShim,node:shim,objectOf:getShim,oneOf:getShim,oneOfType:getShim,shape:getShim,exact:getShim,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return i.PropTypes=i,i}},45697:(i,s,u)=>{i.exports=u(92703)()},50414:i=>{"use strict";i.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},55798:i=>{"use strict";var s=String.prototype.replace,u=/%20/g,m="RFC1738",v="RFC3986";i.exports={default:v,formatters:{RFC1738:function(i){return s.call(i,u,"+")},RFC3986:function(i){return String(i)}},RFC1738:m,RFC3986:v}},80129:(i,s,u)=>{"use strict";var m=u(58261),v=u(55235),_=u(55798);i.exports={formats:_,parse:v,stringify:m}},55235:(i,s,u)=>{"use strict";var m=u(12769),v=Object.prototype.hasOwnProperty,_=Array.isArray,j={allowDots:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decoder:m.decode,delimiter:"&",depth:5,ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictNullHandling:!1},interpretNumericEntities=function(i){return i.replace(/&#(\d+);/g,(function(i,s){return String.fromCharCode(parseInt(s,10))}))},parseArrayValue=function(i,s){return i&&"string"==typeof i&&s.comma&&i.indexOf(",")>-1?i.split(","):i},M=function parseQueryStringKeys(i,s,u,m){if(i){var _=u.allowDots?i.replace(/\.([^.[]+)/g,"[$1]"):i,j=/(\[[^[\]]*])/g,M=u.depth>0&&/(\[[^[\]]*])/.exec(_),$=M?_.slice(0,M.index):_,W=[];if($){if(!u.plainObjects&&v.call(Object.prototype,$)&&!u.allowPrototypes)return;W.push($)}for(var X=0;u.depth>0&&null!==(M=j.exec(_))&&X=0;--_){var j,M=i[_];if("[]"===M&&u.parseArrays)j=[].concat(v);else{j=u.plainObjects?Object.create(null):{};var $="["===M.charAt(0)&&"]"===M.charAt(M.length-1)?M.slice(1,-1):M,W=parseInt($,10);u.parseArrays||""!==$?!isNaN(W)&&M!==$&&String(W)===$&&W>=0&&u.parseArrays&&W<=u.arrayLimit?(j=[])[W]=v:"__proto__"!==$&&(j[$]=v):j={0:v}}v=j}return v}(W,s,u,m)}};i.exports=function(i,s){var u=function normalizeParseOptions(i){if(!i)return j;if(null!==i.decoder&&void 0!==i.decoder&&"function"!=typeof i.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==i.charset&&"utf-8"!==i.charset&&"iso-8859-1"!==i.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var s=void 0===i.charset?j.charset:i.charset;return{allowDots:void 0===i.allowDots?j.allowDots:!!i.allowDots,allowPrototypes:"boolean"==typeof i.allowPrototypes?i.allowPrototypes:j.allowPrototypes,allowSparse:"boolean"==typeof i.allowSparse?i.allowSparse:j.allowSparse,arrayLimit:"number"==typeof i.arrayLimit?i.arrayLimit:j.arrayLimit,charset:s,charsetSentinel:"boolean"==typeof i.charsetSentinel?i.charsetSentinel:j.charsetSentinel,comma:"boolean"==typeof i.comma?i.comma:j.comma,decoder:"function"==typeof i.decoder?i.decoder:j.decoder,delimiter:"string"==typeof i.delimiter||m.isRegExp(i.delimiter)?i.delimiter:j.delimiter,depth:"number"==typeof i.depth||!1===i.depth?+i.depth:j.depth,ignoreQueryPrefix:!0===i.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof i.interpretNumericEntities?i.interpretNumericEntities:j.interpretNumericEntities,parameterLimit:"number"==typeof i.parameterLimit?i.parameterLimit:j.parameterLimit,parseArrays:!1!==i.parseArrays,plainObjects:"boolean"==typeof i.plainObjects?i.plainObjects:j.plainObjects,strictNullHandling:"boolean"==typeof i.strictNullHandling?i.strictNullHandling:j.strictNullHandling}}(s);if(""===i||null==i)return u.plainObjects?Object.create(null):{};for(var $="string"==typeof i?function parseQueryStringValues(i,s){var u,M={},$=s.ignoreQueryPrefix?i.replace(/^\?/,""):i,W=s.parameterLimit===1/0?void 0:s.parameterLimit,X=$.split(s.delimiter,W),Y=-1,Z=s.charset;if(s.charsetSentinel)for(u=0;u-1&&(ae=_(ae)?[ae]:ae),v.call(M,ee)?M[ee]=m.combine(M[ee],ae):M[ee]=ae}return M}(i,u):i,W=u.plainObjects?Object.create(null):{},X=Object.keys($),Y=0;Y{"use strict";var m=u(37478),v=u(12769),_=u(55798),j=Object.prototype.hasOwnProperty,M={brackets:function brackets(i){return i+"[]"},comma:"comma",indices:function indices(i,s){return i+"["+s+"]"},repeat:function repeat(i){return i}},$=Array.isArray,W=String.prototype.split,X=Array.prototype.push,pushToArray=function(i,s){X.apply(i,$(s)?s:[s])},Y=Date.prototype.toISOString,Z=_.default,ee={addQueryPrefix:!1,allowDots:!1,charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encoder:v.encode,encodeValuesOnly:!1,format:Z,formatter:_.formatters[Z],indices:!1,serializeDate:function serializeDate(i){return Y.call(i)},skipNulls:!1,strictNullHandling:!1},ae={},ie=function stringify(i,s,u,_,j,M,X,Y,Z,ie,le,ce,pe,de,fe,ye){for(var be=i,_e=ye,we=0,Se=!1;void 0!==(_e=_e.get(ae))&&!Se;){var xe=_e.get(i);if(we+=1,void 0!==xe){if(xe===we)throw new RangeError("Cyclic object value");Se=!0}void 0===_e.get(ae)&&(we=0)}if("function"==typeof Y?be=Y(s,be):be instanceof Date?be=le(be):"comma"===u&&$(be)&&(be=v.maybeMap(be,(function(i){return i instanceof Date?le(i):i}))),null===be){if(j)return X&&!de?X(s,ee.encoder,fe,"key",ce):s;be=""}if(function isNonNullishPrimitive(i){return"string"==typeof i||"number"==typeof i||"boolean"==typeof i||"symbol"==typeof i||"bigint"==typeof i}(be)||v.isBuffer(be)){if(X){var Pe=de?s:X(s,ee.encoder,fe,"key",ce);if("comma"===u&&de){for(var Ie=W.call(String(be),","),Te="",Re=0;Re0?be.join(",")||null:void 0}];else if($(Y))qe=Y;else{var Ve=Object.keys(be);qe=Z?Ve.sort(Z):Ve}for(var We=_&&$(be)&&1===be.length?s+"[]":s,He=0;He0?fe+de:""}},12769:(i,s,u)=>{"use strict";var m=u(55798),v=Object.prototype.hasOwnProperty,_=Array.isArray,j=function(){for(var i=[],s=0;s<256;++s)i.push("%"+((s<16?"0":"")+s.toString(16)).toUpperCase());return i}(),M=function arrayToObject(i,s){for(var u=s&&s.plainObjects?Object.create(null):{},m=0;m1;){var s=i.pop(),u=s.obj[s.prop];if(_(u)){for(var m=[],v=0;v=48&&X<=57||X>=65&&X<=90||X>=97&&X<=122||_===m.RFC1738&&(40===X||41===X)?$+=M.charAt(W):X<128?$+=j[X]:X<2048?$+=j[192|X>>6]+j[128|63&X]:X<55296||X>=57344?$+=j[224|X>>12]+j[128|X>>6&63]+j[128|63&X]:(W+=1,X=65536+((1023&X)<<10|1023&M.charCodeAt(W)),$+=j[240|X>>18]+j[128|X>>12&63]+j[128|X>>6&63]+j[128|63&X])}return $},isBuffer:function isBuffer(i){return!(!i||"object"!=typeof i)&&!!(i.constructor&&i.constructor.isBuffer&&i.constructor.isBuffer(i))},isRegExp:function isRegExp(i){return"[object RegExp]"===Object.prototype.toString.call(i)},maybeMap:function maybeMap(i,s){if(_(i)){for(var u=[],m=0;m{"use strict";var u=Object.prototype.hasOwnProperty;function decode(i){try{return decodeURIComponent(i.replace(/\+/g," "))}catch(i){return null}}function encode(i){try{return encodeURIComponent(i)}catch(i){return null}}s.stringify=function querystringify(i,s){s=s||"";var m,v,_=[];for(v in"string"!=typeof s&&(s="?"),i)if(u.call(i,v)){if((m=i[v])||null!=m&&!isNaN(m)||(m=""),v=encode(v),m=encode(m),null===v||null===m)continue;_.push(v+"="+m)}return _.length?s+_.join("&"):""},s.parse=function querystring(i){for(var s,u=/([^=?#&]+)=?([^&]*)/g,m={};s=u.exec(i);){var v=decode(s[1]),_=decode(s[2]);null===v||null===_||v in m||(m[v]=_)}return m}},14419:(i,s,u)=>{const m=u(60697),v=u(69450),_=m.types;i.exports=class RandExp{constructor(i,s){if(this._setDefaults(i),i instanceof RegExp)this.ignoreCase=i.ignoreCase,this.multiline=i.multiline,i=i.source;else{if("string"!=typeof i)throw new Error("Expected a regexp or string");this.ignoreCase=s&&-1!==s.indexOf("i"),this.multiline=s&&-1!==s.indexOf("m")}this.tokens=m(i)}_setDefaults(i){this.max=null!=i.max?i.max:null!=RandExp.prototype.max?RandExp.prototype.max:100,this.defaultRange=i.defaultRange?i.defaultRange:this.defaultRange.clone(),i.randInt&&(this.randInt=i.randInt)}gen(){return this._gen(this.tokens,[])}_gen(i,s){var u,m,v,j,M;switch(i.type){case _.ROOT:case _.GROUP:if(i.followedBy||i.notFollowedBy)return"";for(i.remember&&void 0===i.groupNumber&&(i.groupNumber=s.push(null)-1),m="",j=0,M=(u=i.options?this._randSelect(i.options):i.stack).length;j{"use strict";var m=u(34155),v=65536,_=4294967295;var j=u(89509).Buffer,M=u.g.crypto||u.g.msCrypto;M&&M.getRandomValues?i.exports=function randomBytes(i,s){if(i>_)throw new RangeError("requested too many random bytes");var u=j.allocUnsafe(i);if(i>0)if(i>v)for(var $=0;${"use strict";function _typeof(i){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(i){return typeof i}:function(i){return i&&"function"==typeof Symbol&&i.constructor===Symbol&&i!==Symbol.prototype?"symbol":typeof i},_typeof(i)}Object.defineProperty(s,"__esModule",{value:!0}),s.CopyToClipboard=void 0;var m=_interopRequireDefault(u(67294)),v=_interopRequireDefault(u(20640)),_=["text","onCopy","options","children"];function _interopRequireDefault(i){return i&&i.__esModule?i:{default:i}}function ownKeys(i,s){var u=Object.keys(i);if(Object.getOwnPropertySymbols){var m=Object.getOwnPropertySymbols(i);s&&(m=m.filter((function(s){return Object.getOwnPropertyDescriptor(i,s).enumerable}))),u.push.apply(u,m)}return u}function _objectSpread(i){for(var s=1;s=0||(v[u]=i[u]);return v}(i,s);if(Object.getOwnPropertySymbols){var _=Object.getOwnPropertySymbols(i);for(m=0;m<_.length;m++)u=_[m],s.indexOf(u)>=0||Object.prototype.propertyIsEnumerable.call(i,u)&&(v[u]=i[u])}return v}function _defineProperties(i,s){for(var u=0;u{"use strict";var m=u(74300).CopyToClipboard;m.CopyToClipboard=m,i.exports=m},53441:(i,s,u)=>{"use strict";function _typeof(i){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(i){return typeof i}:function(i){return i&&"function"==typeof Symbol&&i.constructor===Symbol&&i!==Symbol.prototype?"symbol":typeof i},_typeof(i)}Object.defineProperty(s,"__esModule",{value:!0}),s.DebounceInput=void 0;var m=_interopRequireDefault(u(67294)),v=_interopRequireDefault(u(91296)),_=["element","onChange","value","minLength","debounceTimeout","forceNotifyByEnter","forceNotifyOnBlur","onKeyDown","onBlur","inputRef"];function _interopRequireDefault(i){return i&&i.__esModule?i:{default:i}}function _objectWithoutProperties(i,s){if(null==i)return{};var u,m,v=function _objectWithoutPropertiesLoose(i,s){if(null==i)return{};var u,m,v={},_=Object.keys(i);for(m=0;m<_.length;m++)u=_[m],s.indexOf(u)>=0||(v[u]=i[u]);return v}(i,s);if(Object.getOwnPropertySymbols){var _=Object.getOwnPropertySymbols(i);for(m=0;m<_.length;m++)u=_[m],s.indexOf(u)>=0||Object.prototype.propertyIsEnumerable.call(i,u)&&(v[u]=i[u])}return v}function ownKeys(i,s){var u=Object.keys(i);if(Object.getOwnPropertySymbols){var m=Object.getOwnPropertySymbols(i);s&&(m=m.filter((function(s){return Object.getOwnPropertyDescriptor(i,s).enumerable}))),u.push.apply(u,m)}return u}function _objectSpread(i){for(var s=1;s=m?u.notify(i):s.length>v.length&&u.notify(_objectSpread(_objectSpread({},i),{},{target:_objectSpread(_objectSpread({},i.target),{},{value:""})}))}))})),_defineProperty(_assertThisInitialized(u),"onKeyDown",(function(i){"Enter"===i.key&&u.forceNotify(i);var s=u.props.onKeyDown;s&&(i.persist(),s(i))})),_defineProperty(_assertThisInitialized(u),"onBlur",(function(i){u.forceNotify(i);var s=u.props.onBlur;s&&(i.persist(),s(i))})),_defineProperty(_assertThisInitialized(u),"createNotifier",(function(i){if(i<0)u.notify=function(){return null};else if(0===i)u.notify=u.doNotify;else{var s=(0,v.default)((function(i){u.isDebouncing=!1,u.doNotify(i)}),i);u.notify=function(i){u.isDebouncing=!0,s(i)},u.flush=function(){return s.flush()},u.cancel=function(){u.isDebouncing=!1,s.cancel()}}})),_defineProperty(_assertThisInitialized(u),"doNotify",(function(){u.props.onChange.apply(void 0,arguments)})),_defineProperty(_assertThisInitialized(u),"forceNotify",(function(i){var s=u.props.debounceTimeout;if(u.isDebouncing||!(s>0)){u.cancel&&u.cancel();var m=u.state.value,v=u.props.minLength;m.length>=v?u.doNotify(i):u.doNotify(_objectSpread(_objectSpread({},i),{},{target:_objectSpread(_objectSpread({},i.target),{},{value:m})}))}})),u.isDebouncing=!1,u.state={value:void 0===i.value||null===i.value?"":i.value};var m=u.props.debounceTimeout;return u.createNotifier(m),u}return function _createClass(i,s,u){return s&&_defineProperties(i.prototype,s),u&&_defineProperties(i,u),Object.defineProperty(i,"prototype",{writable:!1}),i}(DebounceInput,[{key:"componentDidUpdate",value:function componentDidUpdate(i){if(!this.isDebouncing){var s=this.props,u=s.value,m=s.debounceTimeout,v=i.debounceTimeout,_=i.value,j=this.state.value;void 0!==u&&_!==u&&j!==u&&this.setState({value:u}),m!==v&&this.createNotifier(m)}}},{key:"componentWillUnmount",value:function componentWillUnmount(){this.flush&&this.flush()}},{key:"render",value:function render(){var i,s,u=this.props,v=u.element,j=(u.onChange,u.value,u.minLength,u.debounceTimeout,u.forceNotifyByEnter),M=u.forceNotifyOnBlur,$=u.onKeyDown,W=u.onBlur,X=u.inputRef,Y=_objectWithoutProperties(u,_),Z=this.state.value;i=j?{onKeyDown:this.onKeyDown}:$?{onKeyDown:$}:{},s=M?{onBlur:this.onBlur}:W?{onBlur:W}:{};var ee=X?{ref:X}:{};return m.default.createElement(v,_objectSpread(_objectSpread(_objectSpread(_objectSpread({},Y),{},{onChange:this.onChange,value:Z},i),s),ee))}}]),DebounceInput}(m.default.PureComponent);s.DebounceInput=j,_defineProperty(j,"defaultProps",{element:"input",type:"text",onKeyDown:void 0,onBlur:void 0,value:void 0,minLength:0,debounceTimeout:100,forceNotifyByEnter:!0,forceNotifyOnBlur:!0,inputRef:void 0})},775:(i,s,u)=>{"use strict";var m=u(53441).DebounceInput;m.DebounceInput=m,i.exports=m},64448:(i,s,u)=>{"use strict";var m=u(67294),v=u(27418),_=u(63840);function y(i){for(var s="https://reactjs.org/docs/error-decoder.html?invariant="+i,u=1;u
'); + } + value() { + return this.buffer; + } + span(i) { + this.buffer += ``; + } + } + class TokenTree { + constructor() { + (this.rootNode = { children: [] }), (this.stack = [this.rootNode]); + } + get top() { + return this.stack[this.stack.length - 1]; + } + get root() { + return this.rootNode; + } + add(i) { + this.top.children.push(i); + } + openNode(i) { + const s = { kind: i, children: [] }; + this.add(s), this.stack.push(s); + } + closeNode() { + if (this.stack.length > 1) return this.stack.pop(); + } + closeAllNodes() { + for (; this.closeNode(); ); + } + toJSON() { + return JSON.stringify(this.rootNode, null, 4); + } + walk(i) { + return this.constructor._walk(i, this.rootNode); + } + static _walk(i, s) { + return 'string' == typeof s ? i.addText(s) : s.children && (i.openNode(s), s.children.forEach((s) => this._walk(i, s)), i.closeNode(s)), i; + } + static _collapse(i) { + 'string' != typeof i && + i.children && + (i.children.every((i) => 'string' == typeof i) ? + (i.children = [i.children.join('')]) + : i.children.forEach((i) => { + TokenTree._collapse(i); + })); + } + } + class TokenTreeEmitter extends TokenTree { + constructor(i) { + super(), (this.options = i); + } + addKeyword(i, s) { + '' !== i && (this.openNode(s), this.addText(i), this.closeNode()); + } + addText(i) { + '' !== i && this.add(i); + } + addSublanguage(i, s) { + const u = i.root; + (u.kind = s), (u.sublanguage = !0), this.add(u); + } + toHTML() { + return new HTMLRenderer(this, this.options).value(); + } + finalize() { + return !0; + } + } + function source(i) { + return ( + i ? + 'string' == typeof i ? + i + : i.source + : null + ); + } + const m = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; + const v = '[a-zA-Z]\\w*', + _ = '[a-zA-Z_]\\w*', + j = '\\b\\d+(\\.\\d+)?', + M = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)', + $ = '\\b(0b[01]+)', + W = { begin: '\\\\[\\s\\S]', relevance: 0 }, + X = { className: 'string', begin: "'", end: "'", illegal: '\\n', contains: [W] }, + Y = { className: 'string', begin: '"', end: '"', illegal: '\\n', contains: [W] }, + Z = { begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ }, + COMMENT = function (i, s, u = {}) { + const m = inherit({ className: 'comment', begin: i, end: s, contains: [] }, u); + return m.contains.push(Z), m.contains.push({ className: 'doctag', begin: '(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):', relevance: 0 }), m; + }, + ee = COMMENT('//', '$'), + ae = COMMENT('/\\*', '\\*/'), + ie = COMMENT('#', '$'), + le = { className: 'number', begin: j, relevance: 0 }, + ce = { className: 'number', begin: M, relevance: 0 }, + pe = { className: 'number', begin: $, relevance: 0 }, + de = { className: 'number', begin: j + '(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?', relevance: 0 }, + fe = { begin: /(?=\/[^/\n]*\/)/, contains: [{ className: 'regexp', begin: /\//, end: /\/[gimuy]*/, illegal: /\n/, contains: [W, { begin: /\[/, end: /\]/, relevance: 0, contains: [W] }] }] }, + ye = { className: 'title', begin: v, relevance: 0 }, + be = { className: 'title', begin: _, relevance: 0 }, + _e = { begin: '\\.\\s*' + _, relevance: 0 }; + var we = Object.freeze({ + __proto__: null, + MATCH_NOTHING_RE: /\b\B/, + IDENT_RE: v, + UNDERSCORE_IDENT_RE: _, + NUMBER_RE: j, + C_NUMBER_RE: M, + BINARY_NUMBER_RE: $, + RE_STARTERS_RE: '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~', + SHEBANG: (i = {}) => { + const s = /^#![ ]*\//; + return ( + i.binary && + (i.begin = (function concat(...i) { + return i.map((i) => source(i)).join(''); + })(s, /.*\b/, i.binary, /\b.*/)), + inherit( + { + 'className': 'meta', + 'begin': s, + 'end': /$/, + 'relevance': 0, + 'on:begin': (i, s) => { + 0 !== i.index && s.ignoreMatch(); + } + }, + i + ) + ); + }, + BACKSLASH_ESCAPE: W, + APOS_STRING_MODE: X, + QUOTE_STRING_MODE: Y, + PHRASAL_WORDS_MODE: Z, + COMMENT, + C_LINE_COMMENT_MODE: ee, + C_BLOCK_COMMENT_MODE: ae, + HASH_COMMENT_MODE: ie, + NUMBER_MODE: le, + C_NUMBER_MODE: ce, + BINARY_NUMBER_MODE: pe, + CSS_NUMBER_MODE: de, + REGEXP_MODE: fe, + TITLE_MODE: ye, + UNDERSCORE_TITLE_MODE: be, + METHOD_GUARD: _e, + END_SAME_AS_BEGIN: function (i) { + return Object.assign(i, { + 'on:begin': (i, s) => { + s.data._beginMatch = i[1]; + }, + 'on:end': (i, s) => { + s.data._beginMatch !== i[1] && s.ignoreMatch(); + } + }); + } + }); + function skipIfhasPrecedingDot(i, s) { + '.' === i.input[i.index - 1] && s.ignoreMatch(); + } + function beginKeywords(i, s) { + s && i.beginKeywords && ((i.begin = '\\b(' + i.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'), (i.__beforeBegin = skipIfhasPrecedingDot), (i.keywords = i.keywords || i.beginKeywords), delete i.beginKeywords, void 0 === i.relevance && (i.relevance = 0)); + } + function compileIllegal(i, s) { + Array.isArray(i.illegal) && + (i.illegal = (function either(...i) { + return '(' + i.map((i) => source(i)).join('|') + ')'; + })(...i.illegal)); + } + function compileMatch(i, s) { + if (i.match) { + if (i.begin || i.end) throw new Error('begin & end are not supported with match'); + (i.begin = i.match), delete i.match; + } + } + function compileRelevance(i, s) { + void 0 === i.relevance && (i.relevance = 1); + } + const Se = ['of', 'and', 'for', 'in', 'not', 'or', 'if', 'then', 'parent', 'list', 'value'], + xe = 'keyword'; + function compileKeywords(i, s, u = xe) { + const m = {}; + return ( + 'string' == typeof i ? compileList(u, i.split(' ')) + : Array.isArray(i) ? compileList(u, i) + : Object.keys(i).forEach(function (u) { + Object.assign(m, compileKeywords(i[u], s, u)); + }), + m + ); + function compileList(i, u) { + s && (u = u.map((i) => i.toLowerCase())), + u.forEach(function (s) { + const u = s.split('|'); + m[u[0]] = [i, scoreForKeyword(u[0], u[1])]; + }); + } + } + function scoreForKeyword(i, s) { + return ( + s ? Number(s) + : ( + (function commonKeyword(i) { + return Se.includes(i.toLowerCase()); + })(i) + ) ? + 0 + : 1 + ); + } + function compileLanguage(i, { plugins: s }) { + function langRe(s, u) { + return new RegExp(source(s), 'm' + (i.case_insensitive ? 'i' : '') + (u ? 'g' : '')); + } + class MultiRegex { + constructor() { + (this.matchIndexes = {}), (this.regexes = []), (this.matchAt = 1), (this.position = 0); + } + addRule(i, s) { + (s.position = this.position++), + (this.matchIndexes[this.matchAt] = s), + this.regexes.push([s, i]), + (this.matchAt += + (function countMatchGroups(i) { + return new RegExp(i.toString() + '|').exec('').length - 1; + })(i) + 1); + } + compile() { + 0 === this.regexes.length && (this.exec = () => null); + const i = this.regexes.map((i) => i[1]); + (this.matcherRe = langRe( + (function join(i, s = '|') { + let u = 0; + return i + .map((i) => { + u += 1; + const s = u; + let v = source(i), + _ = ''; + for (; v.length > 0; ) { + const i = m.exec(v); + if (!i) { + _ += v; + break; + } + (_ += v.substring(0, i.index)), (v = v.substring(i.index + i[0].length)), '\\' === i[0][0] && i[1] ? (_ += '\\' + String(Number(i[1]) + s)) : ((_ += i[0]), '(' === i[0] && u++); + } + return _; + }) + .map((i) => `(${i})`) + .join(s); + })(i), + !0 + )), + (this.lastIndex = 0); + } + exec(i) { + this.matcherRe.lastIndex = this.lastIndex; + const s = this.matcherRe.exec(i); + if (!s) return null; + const u = s.findIndex((i, s) => s > 0 && void 0 !== i), + m = this.matchIndexes[u]; + return s.splice(0, u), Object.assign(s, m); + } + } + class ResumableMultiRegex { + constructor() { + (this.rules = []), (this.multiRegexes = []), (this.count = 0), (this.lastIndex = 0), (this.regexIndex = 0); + } + getMatcher(i) { + if (this.multiRegexes[i]) return this.multiRegexes[i]; + const s = new MultiRegex(); + return this.rules.slice(i).forEach(([i, u]) => s.addRule(i, u)), s.compile(), (this.multiRegexes[i] = s), s; + } + resumingScanAtSamePosition() { + return 0 !== this.regexIndex; + } + considerAll() { + this.regexIndex = 0; + } + addRule(i, s) { + this.rules.push([i, s]), 'begin' === s.type && this.count++; + } + exec(i) { + const s = this.getMatcher(this.regexIndex); + s.lastIndex = this.lastIndex; + let u = s.exec(i); + if (this.resumingScanAtSamePosition()) + if (u && u.index === this.lastIndex); + else { + const s = this.getMatcher(0); + (s.lastIndex = this.lastIndex + 1), (u = s.exec(i)); + } + return u && ((this.regexIndex += u.position + 1), this.regexIndex === this.count && this.considerAll()), u; + } + } + if ((i.compilerExtensions || (i.compilerExtensions = []), i.contains && i.contains.includes('self'))) throw new Error('ERR: contains `self` is not supported at the top-level of a language. See documentation.'); + return ( + (i.classNameAliases = inherit(i.classNameAliases || {})), + (function compileMode(s, u) { + const m = s; + if (s.isCompiled) return m; + [compileMatch].forEach((i) => i(s, u)), i.compilerExtensions.forEach((i) => i(s, u)), (s.__beforeBegin = null), [beginKeywords, compileIllegal, compileRelevance].forEach((i) => i(s, u)), (s.isCompiled = !0); + let v = null; + if (('object' == typeof s.keywords && ((v = s.keywords.$pattern), delete s.keywords.$pattern), s.keywords && (s.keywords = compileKeywords(s.keywords, i.case_insensitive)), s.lexemes && v)) throw new Error('ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) '); + return ( + (v = v || s.lexemes || /\w+/), + (m.keywordPatternRe = langRe(v, !0)), + u && (s.begin || (s.begin = /\B|\b/), (m.beginRe = langRe(s.begin)), s.endSameAsBegin && (s.end = s.begin), s.end || s.endsWithParent || (s.end = /\B|\b/), s.end && (m.endRe = langRe(s.end)), (m.terminatorEnd = source(s.end) || ''), s.endsWithParent && u.terminatorEnd && (m.terminatorEnd += (s.end ? '|' : '') + u.terminatorEnd)), + s.illegal && (m.illegalRe = langRe(s.illegal)), + s.contains || (s.contains = []), + (s.contains = [].concat( + ...s.contains.map(function (i) { + return (function expandOrCloneMode(i) { + i.variants && + !i.cachedVariants && + (i.cachedVariants = i.variants.map(function (s) { + return inherit(i, { variants: null }, s); + })); + if (i.cachedVariants) return i.cachedVariants; + if (dependencyOnParent(i)) return inherit(i, { starts: i.starts ? inherit(i.starts) : null }); + if (Object.isFrozen(i)) return inherit(i); + return i; + })('self' === i ? s : i); + }) + )), + s.contains.forEach(function (i) { + compileMode(i, m); + }), + s.starts && compileMode(s.starts, u), + (m.matcher = (function buildModeRegex(i) { + const s = new ResumableMultiRegex(); + return i.contains.forEach((i) => s.addRule(i.begin, { rule: i, type: 'begin' })), i.terminatorEnd && s.addRule(i.terminatorEnd, { type: 'end' }), i.illegal && s.addRule(i.illegal, { type: 'illegal' }), s; + })(m)), + m + ); + })(i) + ); + } + function dependencyOnParent(i) { + return !!i && (i.endsWithParent || dependencyOnParent(i.starts)); + } + function BuildVuePlugin(i) { + const s = { + props: ['language', 'code', 'autodetect'], + data: function () { + return { detectedLanguage: '', unknownLanguage: !1 }; + }, + computed: { + className() { + return this.unknownLanguage ? '' : 'hljs ' + this.detectedLanguage; + }, + highlighted() { + if (!this.autoDetect && !i.getLanguage(this.language)) return console.warn(`The language "${this.language}" you specified could not be found.`), (this.unknownLanguage = !0), escapeHTML(this.code); + let s = {}; + return this.autoDetect ? ((s = i.highlightAuto(this.code)), (this.detectedLanguage = s.language)) : ((s = i.highlight(this.language, this.code, this.ignoreIllegals)), (this.detectedLanguage = this.language)), s.value; + }, + autoDetect() { + return ( + !this.language || + (function hasValueOrEmptyAttribute(i) { + return Boolean(i || '' === i); + })(this.autodetect) + ); + }, + ignoreIllegals: () => !0 + }, + render(i) { + return i('pre', {}, [i('code', { class: this.className, domProps: { innerHTML: this.highlighted } })]); + } + }; + return { + Component: s, + VuePlugin: { + install(i) { + i.component('highlightjs', s); + } + } + }; + } + const Pe = { + 'after:highlightElement': ({ el: i, result: s, text: u }) => { + const m = nodeStream(i); + if (!m.length) return; + const v = document.createElement('div'); + (v.innerHTML = s.value), + (s.value = (function mergeStreams(i, s, u) { + let m = 0, + v = ''; + const _ = []; + function selectStream() { + return ( + i.length && s.length ? + i[0].offset !== s[0].offset ? + i[0].offset < s[0].offset ? + i + : s + : 'start' === s[0].event ? i + : s + : i.length ? i + : s + ); + } + function open(i) { + function attributeString(i) { + return ' ' + i.nodeName + '="' + escapeHTML(i.value) + '"'; + } + v += '<' + tag(i) + [].map.call(i.attributes, attributeString).join('') + '>'; + } + function close(i) { + v += ''; + } + function render(i) { + ('start' === i.event ? open : close)(i.node); + } + for (; i.length || s.length; ) { + let s = selectStream(); + if (((v += escapeHTML(u.substring(m, s[0].offset))), (m = s[0].offset), s === i)) { + _.reverse().forEach(close); + do { + render(s.splice(0, 1)[0]), (s = selectStream()); + } while (s === i && s.length && s[0].offset === m); + _.reverse().forEach(open); + } else 'start' === s[0].event ? _.push(s[0].node) : _.pop(), render(s.splice(0, 1)[0]); + } + return v + escapeHTML(u.substr(m)); + })(m, nodeStream(v), u)); + } + }; + function tag(i) { + return i.nodeName.toLowerCase(); + } + function nodeStream(i) { + const s = []; + return ( + (function _nodeStream(i, u) { + for (let m = i.firstChild; m; m = m.nextSibling) 3 === m.nodeType ? (u += m.nodeValue.length) : 1 === m.nodeType && (s.push({ event: 'start', offset: u, node: m }), (u = _nodeStream(m, u)), tag(m).match(/br|hr|img|input/) || s.push({ event: 'stop', offset: u, node: m })); + return u; + })(i, 0), + s + ); + } + const Ie = {}, + error = (i) => { + console.error(i); + }, + warn = (i, ...s) => { + console.log(`WARN: ${i}`, ...s); + }, + deprecated = (i, s) => { + Ie[`${i}/${s}`] || (console.log(`Deprecated as of ${i}. ${s}`), (Ie[`${i}/${s}`] = !0)); + }, + Te = escapeHTML, + Re = inherit, + qe = Symbol('nomatch'); + var ze = (function (i) { + const u = Object.create(null), + m = Object.create(null), + v = []; + let _ = !0; + const j = /(^(<[^>]+>|\t|)+|\n)/gm, + M = "Could not find the language '{}', did you forget to load/include a language module?", + $ = { disableAutodetect: !0, name: 'Plain text', contains: [] }; + let W = { noHighlightRe: /^(no-?highlight)$/i, languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, classPrefix: 'hljs-', tabReplace: null, useBR: !1, languages: null, __emitter: TokenTreeEmitter }; + function shouldNotHighlight(i) { + return W.noHighlightRe.test(i); + } + function highlight(i, s, u, m) { + let v = '', + _ = ''; + 'object' == typeof s ? ((v = i), (u = s.ignoreIllegals), (_ = s.language), (m = void 0)) : (deprecated('10.7.0', 'highlight(lang, code, ...args) has been deprecated.'), deprecated('10.7.0', 'Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277'), (_ = i), (v = s)); + const j = { code: v, language: _ }; + fire('before:highlight', j); + const M = j.result ? j.result : _highlight(j.language, j.code, u, m); + return (M.code = j.code), fire('after:highlight', M), M; + } + function _highlight(i, s, m, j) { + function keywordData(i, s) { + const u = X.case_insensitive ? s[0].toLowerCase() : s[0]; + return Object.prototype.hasOwnProperty.call(i.keywords, u) && i.keywords[u]; + } + function processBuffer() { + null != ee.subLanguage ? + (function processSubLanguage() { + if ('' === le) return; + let i = null; + if ('string' == typeof ee.subLanguage) { + if (!u[ee.subLanguage]) return void ie.addText(le); + (i = _highlight(ee.subLanguage, le, !0, ae[ee.subLanguage])), (ae[ee.subLanguage] = i.top); + } else i = highlightAuto(le, ee.subLanguage.length ? ee.subLanguage : null); + ee.relevance > 0 && (ce += i.relevance), ie.addSublanguage(i.emitter, i.language); + })() + : (function processKeywords() { + if (!ee.keywords) return void ie.addText(le); + let i = 0; + ee.keywordPatternRe.lastIndex = 0; + let s = ee.keywordPatternRe.exec(le), + u = ''; + for (; s; ) { + u += le.substring(i, s.index); + const m = keywordData(ee, s); + if (m) { + const [i, v] = m; + if ((ie.addText(u), (u = ''), (ce += v), i.startsWith('_'))) u += s[0]; + else { + const u = X.classNameAliases[i] || i; + ie.addKeyword(s[0], u); + } + } else u += s[0]; + (i = ee.keywordPatternRe.lastIndex), (s = ee.keywordPatternRe.exec(le)); + } + (u += le.substr(i)), ie.addText(u); + })(), + (le = ''); + } + function startNewMode(i) { + return i.className && ie.openNode(X.classNameAliases[i.className] || i.className), (ee = Object.create(i, { parent: { value: ee } })), ee; + } + function endOfMode(i, s, u) { + let m = (function startsWith(i, s) { + const u = i && i.exec(s); + return u && 0 === u.index; + })(i.endRe, u); + if (m) { + if (i['on:end']) { + const u = new Response(i); + i['on:end'](s, u), u.isMatchIgnored && (m = !1); + } + if (m) { + for (; i.endsParent && i.parent; ) i = i.parent; + return i; + } + } + if (i.endsWithParent) return endOfMode(i.parent, s, u); + } + function doIgnore(i) { + return 0 === ee.matcher.regexIndex ? ((le += i[0]), 1) : ((fe = !0), 0); + } + function doBeginMatch(i) { + const s = i[0], + u = i.rule, + m = new Response(u), + v = [u.__beforeBegin, u['on:begin']]; + for (const u of v) if (u && (u(i, m), m.isMatchIgnored)) return doIgnore(s); + return ( + u && + u.endSameAsBegin && + (u.endRe = (function escape(i) { + return new RegExp(i.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm'); + })(s)), + u.skip ? (le += s) : (u.excludeBegin && (le += s), processBuffer(), u.returnBegin || u.excludeBegin || (le = s)), + startNewMode(u), + u.returnBegin ? 0 : s.length + ); + } + function doEndMatch(i) { + const u = i[0], + m = s.substr(i.index), + v = endOfMode(ee, i, m); + if (!v) return qe; + const _ = ee; + _.skip ? (le += u) : (_.returnEnd || _.excludeEnd || (le += u), processBuffer(), _.excludeEnd && (le = u)); + do { + ee.className && ie.closeNode(), ee.skip || ee.subLanguage || (ce += ee.relevance), (ee = ee.parent); + } while (ee !== v.parent); + return v.starts && (v.endSameAsBegin && (v.starts.endRe = v.endRe), startNewMode(v.starts)), _.returnEnd ? 0 : u.length; + } + let $ = {}; + function processLexeme(u, v) { + const j = v && v[0]; + if (((le += u), null == j)) return processBuffer(), 0; + if ('begin' === $.type && 'end' === v.type && $.index === v.index && '' === j) { + if (((le += s.slice(v.index, v.index + 1)), !_)) { + const s = new Error('0 width match regex'); + throw ((s.languageName = i), (s.badRule = $.rule), s); + } + return 1; + } + if ((($ = v), 'begin' === v.type)) return doBeginMatch(v); + if ('illegal' === v.type && !m) { + const i = new Error('Illegal lexeme "' + j + '" for mode "' + (ee.className || '') + '"'); + throw ((i.mode = ee), i); + } + if ('end' === v.type) { + const i = doEndMatch(v); + if (i !== qe) return i; + } + if ('illegal' === v.type && '' === j) return 1; + if (de > 1e5 && de > 3 * v.index) { + throw new Error('potential infinite loop, way more iterations than matches'); + } + return (le += j), j.length; + } + const X = getLanguage(i); + if (!X) throw (error(M.replace('{}', i)), new Error('Unknown language: "' + i + '"')); + const Y = compileLanguage(X, { plugins: v }); + let Z = '', + ee = j || Y; + const ae = {}, + ie = new W.__emitter(W); + !(function processContinuations() { + const i = []; + for (let s = ee; s !== X; s = s.parent) s.className && i.unshift(s.className); + i.forEach((i) => ie.openNode(i)); + })(); + let le = '', + ce = 0, + pe = 0, + de = 0, + fe = !1; + try { + for (ee.matcher.considerAll(); ; ) { + de++, fe ? (fe = !1) : ee.matcher.considerAll(), (ee.matcher.lastIndex = pe); + const i = ee.matcher.exec(s); + if (!i) break; + const u = processLexeme(s.substring(pe, i.index), i); + pe = i.index + u; + } + return processLexeme(s.substr(pe)), ie.closeAllNodes(), ie.finalize(), (Z = ie.toHTML()), { relevance: Math.floor(ce), value: Z, language: i, illegal: !1, emitter: ie, top: ee }; + } catch (u) { + if (u.message && u.message.includes('Illegal')) return { illegal: !0, illegalBy: { msg: u.message, context: s.slice(pe - 100, pe + 100), mode: u.mode }, sofar: Z, relevance: 0, value: Te(s), emitter: ie }; + if (_) return { illegal: !1, relevance: 0, value: Te(s), emitter: ie, language: i, top: ee, errorRaised: u }; + throw u; + } + } + function highlightAuto(i, s) { + s = s || W.languages || Object.keys(u); + const m = (function justTextHighlightResult(i) { + const s = { relevance: 0, emitter: new W.__emitter(W), value: Te(i), illegal: !1, top: $ }; + return s.emitter.addText(i), s; + })(i), + v = s + .filter(getLanguage) + .filter(autoDetection) + .map((s) => _highlight(s, i, !1)); + v.unshift(m); + const _ = v.sort((i, s) => { + if (i.relevance !== s.relevance) return s.relevance - i.relevance; + if (i.language && s.language) { + if (getLanguage(i.language).supersetOf === s.language) return 1; + if (getLanguage(s.language).supersetOf === i.language) return -1; + } + return 0; + }), + [j, M] = _, + X = j; + return (X.second_best = M), X; + } + const X = { + 'before:highlightElement': ({ el: i }) => { + W.useBR && (i.innerHTML = i.innerHTML.replace(/\n/g, '').replace(//g, '\n')); + }, + 'after:highlightElement': ({ result: i }) => { + W.useBR && (i.value = i.value.replace(/\n/g, '
')); + } + }, + Y = /^(<[^>]+>|\t)+/gm, + Z = { + 'after:highlightElement': ({ result: i }) => { + W.tabReplace && (i.value = i.value.replace(Y, (i) => i.replace(/\t/g, W.tabReplace))); + } + }; + function highlightElement(i) { + let s = null; + const u = (function blockLanguage(i) { + let s = i.className + ' '; + s += i.parentNode ? i.parentNode.className : ''; + const u = W.languageDetectRe.exec(s); + if (u) { + const s = getLanguage(u[1]); + return s || (warn(M.replace('{}', u[1])), warn('Falling back to no-highlight mode for this block.', i)), s ? u[1] : 'no-highlight'; + } + return s.split(/\s+/).find((i) => shouldNotHighlight(i) || getLanguage(i)); + })(i); + if (shouldNotHighlight(u)) return; + fire('before:highlightElement', { el: i, language: u }), (s = i); + const v = s.textContent, + _ = u ? highlight(v, { language: u, ignoreIllegals: !0 }) : highlightAuto(v); + fire('after:highlightElement', { el: i, result: _, text: v }), + (i.innerHTML = _.value), + (function updateClassName(i, s, u) { + const v = s ? m[s] : u; + i.classList.add('hljs'), v && i.classList.add(v); + })(i, u, _.language), + (i.result = { language: _.language, re: _.relevance, relavance: _.relevance }), + _.second_best && (i.second_best = { language: _.second_best.language, re: _.second_best.relevance, relavance: _.second_best.relevance }); + } + const initHighlighting = () => { + if (initHighlighting.called) return; + (initHighlighting.called = !0), deprecated('10.6.0', 'initHighlighting() is deprecated. Use highlightAll() instead.'); + document.querySelectorAll('pre code').forEach(highlightElement); + }; + let ee = !1; + function highlightAll() { + if ('loading' === document.readyState) return void (ee = !0); + document.querySelectorAll('pre code').forEach(highlightElement); + } + function getLanguage(i) { + return (i = (i || '').toLowerCase()), u[i] || u[m[i]]; + } + function registerAliases(i, { languageName: s }) { + 'string' == typeof i && (i = [i]), + i.forEach((i) => { + m[i.toLowerCase()] = s; + }); + } + function autoDetection(i) { + const s = getLanguage(i); + return s && !s.disableAutodetect; + } + function fire(i, s) { + const u = i; + v.forEach(function (i) { + i[u] && i[u](s); + }); + } + 'undefined' != typeof window && + window.addEventListener && + window.addEventListener( + 'DOMContentLoaded', + function boot() { + ee && highlightAll(); + }, + !1 + ), + Object.assign(i, { + highlight, + highlightAuto, + highlightAll, + fixMarkup: function deprecateFixMarkup(i) { + return ( + deprecated('10.2.0', 'fixMarkup will be removed entirely in v11.0'), + deprecated('10.2.0', 'Please see https://github.com/highlightjs/highlight.js/issues/2534'), + (function fixMarkup(i) { + return W.tabReplace || W.useBR ? + i.replace(j, (i) => + '\n' === i ? + W.useBR ? + '
' + : i + : W.tabReplace ? i.replace(/\t/g, W.tabReplace) + : i + ) + : i; + })(i) + ); + }, + highlightElement, + highlightBlock: function deprecateHighlightBlock(i) { + return deprecated('10.7.0', 'highlightBlock will be removed entirely in v12.0'), deprecated('10.7.0', 'Please use highlightElement now.'), highlightElement(i); + }, + configure: function configure(i) { + i.useBR && (deprecated('10.3.0', "'useBR' will be removed entirely in v11.0"), deprecated('10.3.0', 'Please see https://github.com/highlightjs/highlight.js/issues/2559')), (W = Re(W, i)); + }, + initHighlighting, + initHighlightingOnLoad: function initHighlightingOnLoad() { + deprecated('10.6.0', 'initHighlightingOnLoad() is deprecated. Use highlightAll() instead.'), (ee = !0); + }, + registerLanguage: function registerLanguage(s, m) { + let v = null; + try { + v = m(i); + } catch (i) { + if ((error("Language definition for '{}' could not be registered.".replace('{}', s)), !_)) throw i; + error(i), (v = $); + } + v.name || (v.name = s), (u[s] = v), (v.rawDefinition = m.bind(null, i)), v.aliases && registerAliases(v.aliases, { languageName: s }); + }, + unregisterLanguage: function unregisterLanguage(i) { + delete u[i]; + for (const s of Object.keys(m)) m[s] === i && delete m[s]; + }, + listLanguages: function listLanguages() { + return Object.keys(u); + }, + getLanguage, + registerAliases, + requireLanguage: function requireLanguage(i) { + deprecated('10.4.0', 'requireLanguage will be removed entirely in v11.'), deprecated('10.4.0', 'Please see https://github.com/highlightjs/highlight.js/pull/2844'); + const s = getLanguage(i); + if (s) return s; + throw new Error("The '{}' language is required, but not loaded.".replace('{}', i)); + }, + autoDetection, + inherit: Re, + addPlugin: function addPlugin(i) { + !(function upgradePluginAPI(i) { + i['before:highlightBlock'] && + !i['before:highlightElement'] && + (i['before:highlightElement'] = (s) => { + i['before:highlightBlock'](Object.assign({ block: s.el }, s)); + }), + i['after:highlightBlock'] && + !i['after:highlightElement'] && + (i['after:highlightElement'] = (s) => { + i['after:highlightBlock'](Object.assign({ block: s.el }, s)); + }); + })(i), + v.push(i); + }, + vuePlugin: BuildVuePlugin(i).VuePlugin + }), + (i.debugMode = function () { + _ = !1; + }), + (i.safeMode = function () { + _ = !0; + }), + (i.versionString = '10.7.3'); + for (const i in we) 'object' == typeof we[i] && s(we[i]); + return Object.assign(i, we), i.addPlugin(X), i.addPlugin(Pe), i.addPlugin(Z), i; + })({}); + i.exports = ze; + }, + 61519: (i) => { + function concat(...i) { + return i + .map((i) => + (function source(i) { + return ( + i ? + 'string' == typeof i ? + i + : i.source + : null + ); + })(i) + ) + .join(''); + } + i.exports = function bash(i) { + const s = {}, + u = { begin: /\$\{/, end: /\}/, contains: ['self', { begin: /:-/, contains: [s] }] }; + Object.assign(s, { className: 'variable', variants: [{ begin: concat(/\$[\w\d#@][\w\d_]*/, '(?![\\w\\d])(?![$])') }, u] }); + const m = { className: 'subst', begin: /\$\(/, end: /\)/, contains: [i.BACKSLASH_ESCAPE] }, + v = { begin: /<<-?\s*(?=\w+)/, starts: { contains: [i.END_SAME_AS_BEGIN({ begin: /(\w+)/, end: /(\w+)/, className: 'string' })] } }, + _ = { className: 'string', begin: /"/, end: /"/, contains: [i.BACKSLASH_ESCAPE, s, m] }; + m.contains.push(_); + const j = { begin: /\$\(\(/, end: /\)\)/, contains: [{ begin: /\d+#[0-9a-f]+/, className: 'number' }, i.NUMBER_MODE, s] }, + M = i.SHEBANG({ binary: `(${['fish', 'bash', 'zsh', 'sh', 'csh', 'ksh', 'tcsh', 'dash', 'scsh'].join('|')})`, relevance: 10 }), + $ = { className: 'function', begin: /\w[\w\d_]*\s*\(\s*\)\s*\{/, returnBegin: !0, contains: [i.inherit(i.TITLE_MODE, { begin: /\w[\w\d_]*/ })], relevance: 0 }; + return { name: 'Bash', aliases: ['sh', 'zsh'], keywords: { $pattern: /\b[a-z._-]+\b/, keyword: 'if then else elif fi for while in do done case esac function', literal: 'true false', built_in: 'break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp' }, contains: [M, i.SHEBANG(), $, j, i.HASH_COMMENT_MODE, v, _, { className: '', begin: /\\"/ }, { className: 'string', begin: /'/, end: /'/ }, s] }; + }; + }, + 30786: (i) => { + function concat(...i) { + return i + .map((i) => + (function source(i) { + return ( + i ? + 'string' == typeof i ? + i + : i.source + : null + ); + })(i) + ) + .join(''); + } + i.exports = function http(i) { + const s = 'HTTP/(2|1\\.[01])', + u = { className: 'attribute', begin: concat('^', /[A-Za-z][A-Za-z0-9-]*/, '(?=\\:\\s)'), starts: { contains: [{ className: 'punctuation', begin: /: /, relevance: 0, starts: { end: '$', relevance: 0 } }] } }, + m = [u, { begin: '\\n\\n', starts: { subLanguage: [], endsWithParent: !0 } }]; + return { + name: 'HTTP', + aliases: ['https'], + illegal: /\S/, + contains: [ + { + begin: '^(?=' + s + ' \\d{3})', + end: /$/, + contains: [ + { className: 'meta', begin: s }, + { className: 'number', begin: '\\b\\d{3}\\b' } + ], + starts: { end: /\b\B/, illegal: /\S/, contains: m } + }, + { + begin: '(?=^[A-Z]+ (.*?) ' + s + '$)', + end: /$/, + contains: [ + { className: 'string', begin: ' ', end: ' ', excludeBegin: !0, excludeEnd: !0 }, + { className: 'meta', begin: s }, + { className: 'keyword', begin: '[A-Z]+' } + ], + starts: { end: /\b\B/, illegal: /\S/, contains: m } + }, + i.inherit(u, { relevance: 0 }) + ] + }; + }; + }, + 96344: (i) => { + const s = '[A-Za-z$_][0-9A-Za-z$_]*', + u = ['as', 'in', 'of', 'if', 'for', 'while', 'finally', 'var', 'new', 'function', 'do', 'return', 'void', 'else', 'break', 'catch', 'instanceof', 'with', 'throw', 'case', 'default', 'try', 'switch', 'continue', 'typeof', 'delete', 'let', 'yield', 'const', 'class', 'debugger', 'async', 'await', 'static', 'import', 'from', 'export', 'extends'], + m = ['true', 'false', 'null', 'undefined', 'NaN', 'Infinity'], + v = [].concat(['setInterval', 'setTimeout', 'clearInterval', 'clearTimeout', 'require', 'exports', 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', 'unescape'], ['arguments', 'this', 'super', 'console', 'window', 'document', 'localStorage', 'module', 'global'], ['Intl', 'DataView', 'Number', 'Math', 'Date', 'String', 'RegExp', 'Object', 'Function', 'Boolean', 'Error', 'Symbol', 'Set', 'Map', 'WeakSet', 'WeakMap', 'Proxy', 'Reflect', 'JSON', 'Promise', 'Float64Array', 'Int16Array', 'Int32Array', 'Int8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Array', 'Uint8Array', 'Uint8ClampedArray', 'ArrayBuffer', 'BigInt64Array', 'BigUint64Array', 'BigInt'], ['EvalError', 'InternalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError']); + function lookahead(i) { + return concat('(?=', i, ')'); + } + function concat(...i) { + return i + .map((i) => + (function source(i) { + return ( + i ? + 'string' == typeof i ? + i + : i.source + : null + ); + })(i) + ) + .join(''); + } + i.exports = function javascript(i) { + const _ = s, + j = '<>', + M = '', + $ = { + begin: /<[A-Za-z0-9\\._:-]+/, + end: /\/[A-Za-z0-9\\._:-]+>|\/>/, + isTrulyOpeningTag: (i, s) => { + const u = i[0].length + i.index, + m = i.input[u]; + '<' !== m ? + '>' === m && + (((i, { after: s }) => { + const u = '', + returnBegin: !0, + end: '\\s*=>', + contains: [ + { + className: 'params', + variants: [ + { begin: i.UNDERSCORE_IDENT_RE, relevance: 0 }, + { className: null, begin: /\(\s*\)/, skip: !0 }, + { begin: /\(/, end: /\)/, excludeBegin: !0, excludeEnd: !0, keywords: W, contains: ye } + ] + } + ] + }, + { begin: /,/, relevance: 0 }, + { className: '', begin: /\s/, end: /\s*/, skip: !0 }, + { + variants: [ + { begin: j, end: M }, + { 'begin': $.begin, 'on:begin': $.isTrulyOpeningTag, 'end': $.end } + ], + subLanguage: 'xml', + contains: [{ begin: $.begin, end: $.end, skip: !0, contains: ['self'] }] + } + ], + relevance: 0 + }, + { className: 'function', beginKeywords: 'function', end: /[{;]/, excludeEnd: !0, keywords: W, contains: ['self', i.inherit(i.TITLE_MODE, { begin: _ }), be], illegal: /%/ }, + { beginKeywords: 'while if switch catch for' }, + { className: 'function', begin: i.UNDERSCORE_IDENT_RE + '\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{', returnBegin: !0, contains: [be, i.inherit(i.TITLE_MODE, { begin: _ })] }, + { variants: [{ begin: '\\.' + _ }, { begin: '\\$' + _ }], relevance: 0 }, + { className: 'class', beginKeywords: 'class', end: /[{;=]/, excludeEnd: !0, illegal: /[:"[\]]/, contains: [{ beginKeywords: 'extends' }, i.UNDERSCORE_TITLE_MODE] }, + { begin: /\b(?=constructor)/, end: /[{;]/, excludeEnd: !0, contains: [i.inherit(i.TITLE_MODE, { begin: _ }), 'self', be] }, + { begin: '(get|set)\\s+(?=' + _ + '\\()', end: /\{/, keywords: 'get set', contains: [i.inherit(i.TITLE_MODE, { begin: _ }), { begin: /\(\)/ }, be] }, + { begin: /\$[(.]/ } + ] + }; + }; + }, + 82026: (i) => { + i.exports = function json(i) { + const s = { literal: 'true false null' }, + u = [i.C_LINE_COMMENT_MODE, i.C_BLOCK_COMMENT_MODE], + m = [i.QUOTE_STRING_MODE, i.C_NUMBER_MODE], + v = { end: ',', endsWithParent: !0, excludeEnd: !0, contains: m, keywords: s }, + _ = { begin: /\{/, end: /\}/, contains: [{ className: 'attr', begin: /"/, end: /"/, contains: [i.BACKSLASH_ESCAPE], illegal: '\\n' }, i.inherit(v, { begin: /:/ })].concat(u), illegal: '\\S' }, + j = { begin: '\\[', end: '\\]', contains: [i.inherit(v)], illegal: '\\S' }; + return ( + m.push(_, j), + u.forEach(function (i) { + m.push(i); + }), + { name: 'JSON', contains: m, keywords: s, illegal: '\\S' } + ); + }; + }, + 66336: (i) => { + i.exports = function powershell(i) { + const s = { $pattern: /-?[A-z\.\-]+\b/, keyword: 'if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter', built_in: 'ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write' }, + u = { begin: '`[\\s\\S]', relevance: 0 }, + m = { className: 'variable', variants: [{ begin: /\$\B/ }, { className: 'keyword', begin: /\$this/ }, { begin: /\$[\w\d][\w\d_:]*/ }] }, + v = { + className: 'string', + variants: [ + { begin: /"/, end: /"/ }, + { begin: /@"/, end: /^"@/ } + ], + contains: [u, m, { className: 'variable', begin: /\$[A-z]/, end: /[^A-z]/ }] + }, + _ = { + className: 'string', + variants: [ + { begin: /'/, end: /'/ }, + { begin: /@'/, end: /^'@/ } + ] + }, + j = i.inherit(i.COMMENT(null, null), { + variants: [ + { begin: /#/, end: /$/ }, + { begin: /<#/, end: /#>/ } + ], + contains: [{ className: 'doctag', variants: [{ begin: /\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/ }, { begin: /\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/ }] }] + }), + M = { className: 'built_in', variants: [{ begin: '('.concat('Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where', ')+(-)[\\w\\d]+') }] }, + $ = { className: 'class', beginKeywords: 'class enum', end: /\s*[{]/, excludeEnd: !0, relevance: 0, contains: [i.TITLE_MODE] }, + W = { + className: 'function', + begin: /function\s+/, + end: /\s*\{|$/, + excludeEnd: !0, + returnBegin: !0, + relevance: 0, + contains: [ + { begin: 'function', relevance: 0, className: 'keyword' }, + { className: 'title', begin: /\w[\w\d]*((-)[\w\d]+)*/, relevance: 0 }, + { begin: /\(/, end: /\)/, className: 'params', relevance: 0, contains: [m] } + ] + }, + X = { begin: /using\s/, end: /$/, returnBegin: !0, contains: [v, _, { className: 'keyword', begin: /(using|assembly|command|module|namespace|type)/ }] }, + Y = { + variants: [ + { className: 'operator', begin: '('.concat('-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor', ')\\b') }, + { className: 'literal', begin: /(-)[\w\d]+/, relevance: 0 } + ] + }, + Z = { className: 'function', begin: /\[.*\]\s*[\w]+[ ]??\(/, end: /$/, returnBegin: !0, relevance: 0, contains: [{ className: 'keyword', begin: '('.concat(s.keyword.toString().replace(/\s/g, '|'), ')\\b'), endsParent: !0, relevance: 0 }, i.inherit(i.TITLE_MODE, { endsParent: !0 })] }, + ee = [Z, j, u, i.NUMBER_MODE, v, _, M, m, { className: 'literal', begin: /\$(null|true|false)\b/ }, { className: 'selector-tag', begin: /@\B/, relevance: 0 }], + ae = { begin: /\[/, end: /\]/, excludeBegin: !0, excludeEnd: !0, relevance: 0, contains: [].concat('self', ee, { begin: '(' + ['string', 'char', 'byte', 'int', 'long', 'bool', 'decimal', 'single', 'double', 'DateTime', 'xml', 'array', 'hashtable', 'void'].join('|') + ')', className: 'built_in', relevance: 0 }, { className: 'type', begin: /[\.\w\d]+/, relevance: 0 }) }; + return Z.contains.unshift(ae), { name: 'PowerShell', aliases: ['ps', 'ps1'], case_insensitive: !0, keywords: s, contains: ee.concat($, W, X, Y, ae) }; + }; + }, + 42157: (i) => { + function source(i) { + return ( + i ? + 'string' == typeof i ? + i + : i.source + : null + ); + } + function lookahead(i) { + return concat('(?=', i, ')'); + } + function concat(...i) { + return i.map((i) => source(i)).join(''); + } + function either(...i) { + return '(' + i.map((i) => source(i)).join('|') + ')'; + } + i.exports = function xml(i) { + const s = concat( + /[A-Z_]/, + (function optional(i) { + return concat('(', i, ')?'); + })(/[A-Z0-9_.-]*:/), + /[A-Z0-9_.-]*/ + ), + u = { className: 'symbol', begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/ }, + m = { begin: /\s/, contains: [{ className: 'meta-keyword', begin: /#?[a-z_][a-z1-9_-]+/, illegal: /\n/ }] }, + v = i.inherit(m, { begin: /\(/, end: /\)/ }), + _ = i.inherit(i.APOS_STRING_MODE, { className: 'meta-string' }), + j = i.inherit(i.QUOTE_STRING_MODE, { className: 'meta-string' }), + M = { + endsWithParent: !0, + illegal: /`]+/ }] }] } + ] + }; + return { + name: 'HTML, XML', + aliases: ['html', 'xhtml', 'rss', 'atom', 'xjb', 'xsd', 'xsl', 'plist', 'wsf', 'svg'], + case_insensitive: !0, + contains: [ + { className: 'meta', begin: //, relevance: 10, contains: [m, j, _, v, { begin: /\[/, end: /\]/, contains: [{ className: 'meta', begin: //, contains: [m, v, j, _] }] }] }, + i.COMMENT(//, { relevance: 10 }), + { begin: //, relevance: 10 }, + u, + { className: 'meta', begin: /<\?xml/, end: /\?>/, relevance: 10 }, + { className: 'tag', begin: /)/, end: />/, keywords: { name: 'style' }, contains: [M], starts: { end: /<\/style>/, returnEnd: !0, subLanguage: ['css', 'xml'] } }, + { className: 'tag', begin: /)/, end: />/, keywords: { name: 'script' }, contains: [M], starts: { end: /<\/script>/, returnEnd: !0, subLanguage: ['javascript', 'handlebars', 'xml'] } }, + { className: 'tag', begin: /<>|<\/>/ }, + { className: 'tag', begin: concat(//, />/, /\s/)))), end: /\/?>/, contains: [{ className: 'name', begin: s, relevance: 0, starts: M }] }, + { + className: 'tag', + begin: concat(/<\//, lookahead(concat(s, />/))), + contains: [ + { className: 'name', begin: s, relevance: 0 }, + { begin: />/, relevance: 0, endsParent: !0 } + ] + } + ] + }; + }; + }, + 54587: (i) => { + i.exports = function yaml(i) { + var s = 'true false yes no null', + u = "[\\w#;/?:@&=+$,.~*'()[\\]]+", + m = { + className: 'string', + relevance: 0, + variants: [{ begin: /'/, end: /'/ }, { begin: /"/, end: /"/ }, { begin: /\S+/ }], + contains: [ + i.BACKSLASH_ESCAPE, + { + className: 'template-variable', + variants: [ + { begin: /\{\{/, end: /\}\}/ }, + { begin: /%\{/, end: /\}/ } + ] + } + ] + }, + v = i.inherit(m, { variants: [{ begin: /'/, end: /'/ }, { begin: /"/, end: /"/ }, { begin: /[^\s,{}[\]]+/ }] }), + _ = { className: 'number', begin: '\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b' }, + j = { end: ',', endsWithParent: !0, excludeEnd: !0, keywords: s, relevance: 0 }, + M = { begin: /\{/, end: /\}/, contains: [j], illegal: '\\n', relevance: 0 }, + $ = { begin: '\\[', end: '\\]', contains: [j], illegal: '\\n', relevance: 0 }, + W = [{ className: 'attr', variants: [{ begin: '\\w[\\w :\\/.-]*:(?=[ \t]|$)' }, { begin: '"\\w[\\w :\\/.-]*":(?=[ \t]|$)' }, { begin: "'\\w[\\w :\\/.-]*':(?=[ \t]|$)" }] }, { className: 'meta', begin: '^---\\s*$', relevance: 10 }, { className: 'string', begin: '[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*' }, { begin: '<%[%=-]?', end: '[%-]?%>', subLanguage: 'ruby', excludeBegin: !0, excludeEnd: !0, relevance: 0 }, { className: 'type', begin: '!\\w+!' + u }, { className: 'type', begin: '!<' + u + '>' }, { className: 'type', begin: '!' + u }, { className: 'type', begin: '!!' + u }, { className: 'meta', begin: '&' + i.UNDERSCORE_IDENT_RE + '$' }, { className: 'meta', begin: '\\*' + i.UNDERSCORE_IDENT_RE + '$' }, { className: 'bullet', begin: '-(?=[ ]|$)', relevance: 0 }, i.HASH_COMMENT_MODE, { beginKeywords: s, keywords: { literal: s } }, _, { className: 'number', begin: i.C_NUMBER_RE + '\\b', relevance: 0 }, M, $, m], + X = [...W]; + return X.pop(), X.push(v), (j.contains = X), { name: 'YAML', case_insensitive: !0, aliases: ['yml'], contains: W }; + }; + }, + 8679: (i, s, u) => { + 'use strict'; + var m = u(59864), + v = { childContextTypes: !0, contextType: !0, contextTypes: !0, defaultProps: !0, displayName: !0, getDefaultProps: !0, getDerivedStateFromError: !0, getDerivedStateFromProps: !0, mixins: !0, propTypes: !0, type: !0 }, + _ = { name: !0, length: !0, prototype: !0, caller: !0, callee: !0, arguments: !0, arity: !0 }, + j = { $$typeof: !0, compare: !0, defaultProps: !0, displayName: !0, propTypes: !0, type: !0 }, + M = {}; + function getStatics(i) { + return m.isMemo(i) ? j : M[i.$$typeof] || v; + } + (M[m.ForwardRef] = { $$typeof: !0, render: !0, defaultProps: !0, displayName: !0, propTypes: !0 }), (M[m.Memo] = j); + var $ = Object.defineProperty, + W = Object.getOwnPropertyNames, + X = Object.getOwnPropertySymbols, + Y = Object.getOwnPropertyDescriptor, + Z = Object.getPrototypeOf, + ee = Object.prototype; + i.exports = function hoistNonReactStatics(i, s, u) { + if ('string' != typeof s) { + if (ee) { + var m = Z(s); + m && m !== ee && hoistNonReactStatics(i, m, u); + } + var v = W(s); + X && (v = v.concat(X(s))); + for (var j = getStatics(i), M = getStatics(s), ae = 0; ae < v.length; ++ae) { + var ie = v[ae]; + if (!(_[ie] || (u && u[ie]) || (M && M[ie]) || (j && j[ie]))) { + var le = Y(s, ie); + try { + $(i, ie, le); + } catch (i) {} + } + } + } + return i; + }; + }, + 80645: (i, s) => { + (s.read = function (i, s, u, m, v) { + var _, + j, + M = 8 * v - m - 1, + $ = (1 << M) - 1, + W = $ >> 1, + X = -7, + Y = u ? v - 1 : 0, + Z = u ? -1 : 1, + ee = i[s + Y]; + for (Y += Z, _ = ee & ((1 << -X) - 1), ee >>= -X, X += M; X > 0; _ = 256 * _ + i[s + Y], Y += Z, X -= 8); + for (j = _ & ((1 << -X) - 1), _ >>= -X, X += m; X > 0; j = 256 * j + i[s + Y], Y += Z, X -= 8); + if (0 === _) _ = 1 - W; + else { + if (_ === $) return j ? NaN : (1 / 0) * (ee ? -1 : 1); + (j += Math.pow(2, m)), (_ -= W); + } + return (ee ? -1 : 1) * j * Math.pow(2, _ - m); + }), + (s.write = function (i, s, u, m, v, _) { + var j, + M, + $, + W = 8 * _ - v - 1, + X = (1 << W) - 1, + Y = X >> 1, + Z = 23 === v ? Math.pow(2, -24) - Math.pow(2, -77) : 0, + ee = m ? 0 : _ - 1, + ae = m ? 1 : -1, + ie = s < 0 || (0 === s && 1 / s < 0) ? 1 : 0; + for ( + s = Math.abs(s), + isNaN(s) || s === 1 / 0 ? + ((M = isNaN(s) ? 1 : 0), (j = X)) + : ((j = Math.floor(Math.log(s) / Math.LN2)), + s * ($ = Math.pow(2, -j)) < 1 && (j--, ($ *= 2)), + (s += j + Y >= 1 ? Z / $ : Z * Math.pow(2, 1 - Y)) * $ >= 2 && (j++, ($ /= 2)), + j + Y >= X ? ((M = 0), (j = X)) + : j + Y >= 1 ? ((M = (s * $ - 1) * Math.pow(2, v)), (j += Y)) + : ((M = s * Math.pow(2, Y - 1) * Math.pow(2, v)), (j = 0))); + v >= 8; + i[u + ee] = 255 & M, ee += ae, M /= 256, v -= 8 + ); + for (j = (j << v) | M, W += v; W > 0; i[u + ee] = 255 & j, ee += ae, j /= 256, W -= 8); + i[u + ee - ae] |= 128 * ie; + }); + }, + 43393: function (i) { + i.exports = (function () { + 'use strict'; + var i = Array.prototype.slice; + function createClass(i, s) { + s && (i.prototype = Object.create(s.prototype)), (i.prototype.constructor = i); + } + function Iterable(i) { + return isIterable(i) ? i : Seq(i); + } + function KeyedIterable(i) { + return isKeyed(i) ? i : KeyedSeq(i); + } + function IndexedIterable(i) { + return isIndexed(i) ? i : IndexedSeq(i); + } + function SetIterable(i) { + return isIterable(i) && !isAssociative(i) ? i : SetSeq(i); + } + function isIterable(i) { + return !(!i || !i[s]); + } + function isKeyed(i) { + return !(!i || !i[u]); + } + function isIndexed(i) { + return !(!i || !i[m]); + } + function isAssociative(i) { + return isKeyed(i) || isIndexed(i); + } + function isOrdered(i) { + return !(!i || !i[v]); + } + createClass(KeyedIterable, Iterable), createClass(IndexedIterable, Iterable), createClass(SetIterable, Iterable), (Iterable.isIterable = isIterable), (Iterable.isKeyed = isKeyed), (Iterable.isIndexed = isIndexed), (Iterable.isAssociative = isAssociative), (Iterable.isOrdered = isOrdered), (Iterable.Keyed = KeyedIterable), (Iterable.Indexed = IndexedIterable), (Iterable.Set = SetIterable); + var s = '@@__IMMUTABLE_ITERABLE__@@', + u = '@@__IMMUTABLE_KEYED__@@', + m = '@@__IMMUTABLE_INDEXED__@@', + v = '@@__IMMUTABLE_ORDERED__@@', + _ = 'delete', + j = 5, + M = 1 << j, + $ = M - 1, + W = {}, + X = { value: !1 }, + Y = { value: !1 }; + function MakeRef(i) { + return (i.value = !1), i; + } + function SetRef(i) { + i && (i.value = !0); + } + function OwnerID() {} + function arrCopy(i, s) { + s = s || 0; + for (var u = Math.max(0, i.length - s), m = new Array(u), v = 0; v < u; v++) m[v] = i[v + s]; + return m; + } + function ensureSize(i) { + return void 0 === i.size && (i.size = i.__iterate(returnTrue)), i.size; + } + function wrapIndex(i, s) { + if ('number' != typeof s) { + var u = s >>> 0; + if ('' + u !== s || 4294967295 === u) return NaN; + s = u; + } + return s < 0 ? ensureSize(i) + s : s; + } + function returnTrue() { + return !0; + } + function wholeSlice(i, s, u) { + return (0 === i || (void 0 !== u && i <= -u)) && (void 0 === s || (void 0 !== u && s >= u)); + } + function resolveBegin(i, s) { + return resolveIndex(i, s, 0); + } + function resolveEnd(i, s) { + return resolveIndex(i, s, s); + } + function resolveIndex(i, s, u) { + return ( + void 0 === i ? u + : i < 0 ? Math.max(0, s + i) + : void 0 === s ? i + : Math.min(s, i) + ); + } + var Z = 0, + ee = 1, + ae = 2, + ie = 'function' == typeof Symbol && Symbol.iterator, + le = '@@iterator', + ce = ie || le; + function Iterator(i) { + this.next = i; + } + function iteratorValue(i, s, u, m) { + var v = + 0 === i ? s + : 1 === i ? u + : [s, u]; + return m ? (m.value = v) : (m = { value: v, done: !1 }), m; + } + function iteratorDone() { + return { value: void 0, done: !0 }; + } + function hasIterator(i) { + return !!getIteratorFn(i); + } + function isIterator(i) { + return i && 'function' == typeof i.next; + } + function getIterator(i) { + var s = getIteratorFn(i); + return s && s.call(i); + } + function getIteratorFn(i) { + var s = i && ((ie && i[ie]) || i[le]); + if ('function' == typeof s) return s; + } + function isArrayLike(i) { + return i && 'number' == typeof i.length; + } + function Seq(i) { + return ( + null == i ? emptySequence() + : isIterable(i) ? i.toSeq() + : seqFromValue(i) + ); + } + function KeyedSeq(i) { + return ( + null == i ? emptySequence().toKeyedSeq() + : isIterable(i) ? + isKeyed(i) ? i.toSeq() + : i.fromEntrySeq() + : keyedSeqFromValue(i) + ); + } + function IndexedSeq(i) { + return ( + null == i ? emptySequence() + : isIterable(i) ? + isKeyed(i) ? i.entrySeq() + : i.toIndexedSeq() + : indexedSeqFromValue(i) + ); + } + function SetSeq(i) { + return ( + null == i ? emptySequence() + : isIterable(i) ? + isKeyed(i) ? i.entrySeq() + : i + : indexedSeqFromValue(i)).toSetSeq(); + } + (Iterator.prototype.toString = function () { + return '[Iterator]'; + }), + (Iterator.KEYS = Z), + (Iterator.VALUES = ee), + (Iterator.ENTRIES = ae), + (Iterator.prototype.inspect = Iterator.prototype.toSource = + function () { + return this.toString(); + }), + (Iterator.prototype[ce] = function () { + return this; + }), + createClass(Seq, Iterable), + (Seq.of = function () { + return Seq(arguments); + }), + (Seq.prototype.toSeq = function () { + return this; + }), + (Seq.prototype.toString = function () { + return this.__toString('Seq {', '}'); + }), + (Seq.prototype.cacheResult = function () { + return !this._cache && this.__iterateUncached && ((this._cache = this.entrySeq().toArray()), (this.size = this._cache.length)), this; + }), + (Seq.prototype.__iterate = function (i, s) { + return seqIterate(this, i, s, !0); + }), + (Seq.prototype.__iterator = function (i, s) { + return seqIterator(this, i, s, !0); + }), + createClass(KeyedSeq, Seq), + (KeyedSeq.prototype.toKeyedSeq = function () { + return this; + }), + createClass(IndexedSeq, Seq), + (IndexedSeq.of = function () { + return IndexedSeq(arguments); + }), + (IndexedSeq.prototype.toIndexedSeq = function () { + return this; + }), + (IndexedSeq.prototype.toString = function () { + return this.__toString('Seq [', ']'); + }), + (IndexedSeq.prototype.__iterate = function (i, s) { + return seqIterate(this, i, s, !1); + }), + (IndexedSeq.prototype.__iterator = function (i, s) { + return seqIterator(this, i, s, !1); + }), + createClass(SetSeq, Seq), + (SetSeq.of = function () { + return SetSeq(arguments); + }), + (SetSeq.prototype.toSetSeq = function () { + return this; + }), + (Seq.isSeq = isSeq), + (Seq.Keyed = KeyedSeq), + (Seq.Set = SetSeq), + (Seq.Indexed = IndexedSeq); + var pe, + de, + fe, + ye = '@@__IMMUTABLE_SEQ__@@'; + function ArraySeq(i) { + (this._array = i), (this.size = i.length); + } + function ObjectSeq(i) { + var s = Object.keys(i); + (this._object = i), (this._keys = s), (this.size = s.length); + } + function IterableSeq(i) { + (this._iterable = i), (this.size = i.length || i.size); + } + function IteratorSeq(i) { + (this._iterator = i), (this._iteratorCache = []); + } + function isSeq(i) { + return !(!i || !i[ye]); + } + function emptySequence() { + return pe || (pe = new ArraySeq([])); + } + function keyedSeqFromValue(i) { + var s = + Array.isArray(i) ? new ArraySeq(i).fromEntrySeq() + : isIterator(i) ? new IteratorSeq(i).fromEntrySeq() + : hasIterator(i) ? new IterableSeq(i).fromEntrySeq() + : 'object' == typeof i ? new ObjectSeq(i) + : void 0; + if (!s) throw new TypeError('Expected Array or iterable object of [k, v] entries, or keyed object: ' + i); + return s; + } + function indexedSeqFromValue(i) { + var s = maybeIndexedSeqFromValue(i); + if (!s) throw new TypeError('Expected Array or iterable object of values: ' + i); + return s; + } + function seqFromValue(i) { + var s = maybeIndexedSeqFromValue(i) || ('object' == typeof i && new ObjectSeq(i)); + if (!s) throw new TypeError('Expected Array or iterable object of values, or keyed object: ' + i); + return s; + } + function maybeIndexedSeqFromValue(i) { + return ( + isArrayLike(i) ? new ArraySeq(i) + : isIterator(i) ? new IteratorSeq(i) + : hasIterator(i) ? new IterableSeq(i) + : void 0 + ); + } + function seqIterate(i, s, u, m) { + var v = i._cache; + if (v) { + for (var _ = v.length - 1, j = 0; j <= _; j++) { + var M = v[u ? _ - j : j]; + if (!1 === s(M[1], m ? M[0] : j, i)) return j + 1; + } + return j; + } + return i.__iterateUncached(s, u); + } + function seqIterator(i, s, u, m) { + var v = i._cache; + if (v) { + var _ = v.length - 1, + j = 0; + return new Iterator(function () { + var i = v[u ? _ - j : j]; + return j++ > _ ? iteratorDone() : iteratorValue(s, m ? i[0] : j - 1, i[1]); + }); + } + return i.__iteratorUncached(s, u); + } + function fromJS(i, s) { + return s ? fromJSWith(s, i, '', { '': i }) : fromJSDefault(i); + } + function fromJSWith(i, s, u, m) { + return ( + Array.isArray(s) ? + i.call( + m, + u, + IndexedSeq(s).map(function (u, m) { + return fromJSWith(i, u, m, s); + }) + ) + : isPlainObj(s) ? + i.call( + m, + u, + KeyedSeq(s).map(function (u, m) { + return fromJSWith(i, u, m, s); + }) + ) + : s + ); + } + function fromJSDefault(i) { + return ( + Array.isArray(i) ? IndexedSeq(i).map(fromJSDefault).toList() + : isPlainObj(i) ? KeyedSeq(i).map(fromJSDefault).toMap() + : i + ); + } + function isPlainObj(i) { + return i && (i.constructor === Object || void 0 === i.constructor); + } + function is(i, s) { + if (i === s || (i != i && s != s)) return !0; + if (!i || !s) return !1; + if ('function' == typeof i.valueOf && 'function' == typeof s.valueOf) { + if ((i = i.valueOf()) === (s = s.valueOf()) || (i != i && s != s)) return !0; + if (!i || !s) return !1; + } + return !('function' != typeof i.equals || 'function' != typeof s.equals || !i.equals(s)); + } + function deepEqual(i, s) { + if (i === s) return !0; + if (!isIterable(s) || (void 0 !== i.size && void 0 !== s.size && i.size !== s.size) || (void 0 !== i.__hash && void 0 !== s.__hash && i.__hash !== s.__hash) || isKeyed(i) !== isKeyed(s) || isIndexed(i) !== isIndexed(s) || isOrdered(i) !== isOrdered(s)) return !1; + if (0 === i.size && 0 === s.size) return !0; + var u = !isAssociative(i); + if (isOrdered(i)) { + var m = i.entries(); + return ( + s.every(function (i, s) { + var v = m.next().value; + return v && is(v[1], i) && (u || is(v[0], s)); + }) && m.next().done + ); + } + var v = !1; + if (void 0 === i.size) + if (void 0 === s.size) 'function' == typeof i.cacheResult && i.cacheResult(); + else { + v = !0; + var _ = i; + (i = s), (s = _); + } + var j = !0, + M = s.__iterate(function (s, m) { + if ( + u ? !i.has(s) + : v ? !is(s, i.get(m, W)) + : !is(i.get(m, W), s) + ) + return (j = !1), !1; + }); + return j && i.size === M; + } + function Repeat(i, s) { + if (!(this instanceof Repeat)) return new Repeat(i, s); + if (((this._value = i), (this.size = void 0 === s ? 1 / 0 : Math.max(0, s)), 0 === this.size)) { + if (de) return de; + de = this; + } + } + function invariant(i, s) { + if (!i) throw new Error(s); + } + function Range(i, s, u) { + if (!(this instanceof Range)) return new Range(i, s, u); + if ((invariant(0 !== u, 'Cannot step a Range by 0'), (i = i || 0), void 0 === s && (s = 1 / 0), (u = void 0 === u ? 1 : Math.abs(u)), s < i && (u = -u), (this._start = i), (this._end = s), (this._step = u), (this.size = Math.max(0, Math.ceil((s - i) / u - 1) + 1)), 0 === this.size)) { + if (fe) return fe; + fe = this; + } + } + function Collection() { + throw TypeError('Abstract'); + } + function KeyedCollection() {} + function IndexedCollection() {} + function SetCollection() {} + (Seq.prototype[ye] = !0), + createClass(ArraySeq, IndexedSeq), + (ArraySeq.prototype.get = function (i, s) { + return this.has(i) ? this._array[wrapIndex(this, i)] : s; + }), + (ArraySeq.prototype.__iterate = function (i, s) { + for (var u = this._array, m = u.length - 1, v = 0; v <= m; v++) if (!1 === i(u[s ? m - v : v], v, this)) return v + 1; + return v; + }), + (ArraySeq.prototype.__iterator = function (i, s) { + var u = this._array, + m = u.length - 1, + v = 0; + return new Iterator(function () { + return v > m ? iteratorDone() : iteratorValue(i, v, u[s ? m - v++ : v++]); + }); + }), + createClass(ObjectSeq, KeyedSeq), + (ObjectSeq.prototype.get = function (i, s) { + return void 0 === s || this.has(i) ? this._object[i] : s; + }), + (ObjectSeq.prototype.has = function (i) { + return this._object.hasOwnProperty(i); + }), + (ObjectSeq.prototype.__iterate = function (i, s) { + for (var u = this._object, m = this._keys, v = m.length - 1, _ = 0; _ <= v; _++) { + var j = m[s ? v - _ : _]; + if (!1 === i(u[j], j, this)) return _ + 1; + } + return _; + }), + (ObjectSeq.prototype.__iterator = function (i, s) { + var u = this._object, + m = this._keys, + v = m.length - 1, + _ = 0; + return new Iterator(function () { + var j = m[s ? v - _ : _]; + return _++ > v ? iteratorDone() : iteratorValue(i, j, u[j]); + }); + }), + (ObjectSeq.prototype[v] = !0), + createClass(IterableSeq, IndexedSeq), + (IterableSeq.prototype.__iterateUncached = function (i, s) { + if (s) return this.cacheResult().__iterate(i, s); + var u = getIterator(this._iterable), + m = 0; + if (isIterator(u)) for (var v; !(v = u.next()).done && !1 !== i(v.value, m++, this); ); + return m; + }), + (IterableSeq.prototype.__iteratorUncached = function (i, s) { + if (s) return this.cacheResult().__iterator(i, s); + var u = getIterator(this._iterable); + if (!isIterator(u)) return new Iterator(iteratorDone); + var m = 0; + return new Iterator(function () { + var s = u.next(); + return s.done ? s : iteratorValue(i, m++, s.value); + }); + }), + createClass(IteratorSeq, IndexedSeq), + (IteratorSeq.prototype.__iterateUncached = function (i, s) { + if (s) return this.cacheResult().__iterate(i, s); + for (var u, m = this._iterator, v = this._iteratorCache, _ = 0; _ < v.length; ) if (!1 === i(v[_], _++, this)) return _; + for (; !(u = m.next()).done; ) { + var j = u.value; + if (((v[_] = j), !1 === i(j, _++, this))) break; + } + return _; + }), + (IteratorSeq.prototype.__iteratorUncached = function (i, s) { + if (s) return this.cacheResult().__iterator(i, s); + var u = this._iterator, + m = this._iteratorCache, + v = 0; + return new Iterator(function () { + if (v >= m.length) { + var s = u.next(); + if (s.done) return s; + m[v] = s.value; + } + return iteratorValue(i, v, m[v++]); + }); + }), + createClass(Repeat, IndexedSeq), + (Repeat.prototype.toString = function () { + return 0 === this.size ? 'Repeat []' : 'Repeat [ ' + this._value + ' ' + this.size + ' times ]'; + }), + (Repeat.prototype.get = function (i, s) { + return this.has(i) ? this._value : s; + }), + (Repeat.prototype.includes = function (i) { + return is(this._value, i); + }), + (Repeat.prototype.slice = function (i, s) { + var u = this.size; + return wholeSlice(i, s, u) ? this : new Repeat(this._value, resolveEnd(s, u) - resolveBegin(i, u)); + }), + (Repeat.prototype.reverse = function () { + return this; + }), + (Repeat.prototype.indexOf = function (i) { + return is(this._value, i) ? 0 : -1; + }), + (Repeat.prototype.lastIndexOf = function (i) { + return is(this._value, i) ? this.size : -1; + }), + (Repeat.prototype.__iterate = function (i, s) { + for (var u = 0; u < this.size; u++) if (!1 === i(this._value, u, this)) return u + 1; + return u; + }), + (Repeat.prototype.__iterator = function (i, s) { + var u = this, + m = 0; + return new Iterator(function () { + return m < u.size ? iteratorValue(i, m++, u._value) : iteratorDone(); + }); + }), + (Repeat.prototype.equals = function (i) { + return i instanceof Repeat ? is(this._value, i._value) : deepEqual(i); + }), + createClass(Range, IndexedSeq), + (Range.prototype.toString = function () { + return 0 === this.size ? 'Range []' : 'Range [ ' + this._start + '...' + this._end + (1 !== this._step ? ' by ' + this._step : '') + ' ]'; + }), + (Range.prototype.get = function (i, s) { + return this.has(i) ? this._start + wrapIndex(this, i) * this._step : s; + }), + (Range.prototype.includes = function (i) { + var s = (i - this._start) / this._step; + return s >= 0 && s < this.size && s === Math.floor(s); + }), + (Range.prototype.slice = function (i, s) { + return wholeSlice(i, s, this.size) ? this : ((i = resolveBegin(i, this.size)), (s = resolveEnd(s, this.size)) <= i ? new Range(0, 0) : new Range(this.get(i, this._end), this.get(s, this._end), this._step)); + }), + (Range.prototype.indexOf = function (i) { + var s = i - this._start; + if (s % this._step == 0) { + var u = s / this._step; + if (u >= 0 && u < this.size) return u; + } + return -1; + }), + (Range.prototype.lastIndexOf = function (i) { + return this.indexOf(i); + }), + (Range.prototype.__iterate = function (i, s) { + for (var u = this.size - 1, m = this._step, v = s ? this._start + u * m : this._start, _ = 0; _ <= u; _++) { + if (!1 === i(v, _, this)) return _ + 1; + v += s ? -m : m; + } + return _; + }), + (Range.prototype.__iterator = function (i, s) { + var u = this.size - 1, + m = this._step, + v = s ? this._start + u * m : this._start, + _ = 0; + return new Iterator(function () { + var j = v; + return (v += s ? -m : m), _ > u ? iteratorDone() : iteratorValue(i, _++, j); + }); + }), + (Range.prototype.equals = function (i) { + return i instanceof Range ? this._start === i._start && this._end === i._end && this._step === i._step : deepEqual(this, i); + }), + createClass(Collection, Iterable), + createClass(KeyedCollection, Collection), + createClass(IndexedCollection, Collection), + createClass(SetCollection, Collection), + (Collection.Keyed = KeyedCollection), + (Collection.Indexed = IndexedCollection), + (Collection.Set = SetCollection); + var be = + 'function' == typeof Math.imul && -2 === Math.imul(4294967295, 2) ? + Math.imul + : function imul(i, s) { + var u = 65535 & (i |= 0), + m = 65535 & (s |= 0); + return (u * m + ((((i >>> 16) * m + u * (s >>> 16)) << 16) >>> 0)) | 0; + }; + function smi(i) { + return ((i >>> 1) & 1073741824) | (3221225471 & i); + } + function hash(i) { + if (!1 === i || null == i) return 0; + if ('function' == typeof i.valueOf && (!1 === (i = i.valueOf()) || null == i)) return 0; + if (!0 === i) return 1; + var s = typeof i; + if ('number' === s) { + if (i != i || i === 1 / 0) return 0; + var u = 0 | i; + for (u !== i && (u ^= 4294967295 * i); i > 4294967295; ) u ^= i /= 4294967295; + return smi(u); + } + if ('string' === s) return i.length > Te ? cachedHashString(i) : hashString(i); + if ('function' == typeof i.hashCode) return i.hashCode(); + if ('object' === s) return hashJSObj(i); + if ('function' == typeof i.toString) return hashString(i.toString()); + throw new Error('Value type ' + s + ' cannot be hashed.'); + } + function cachedHashString(i) { + var s = ze[i]; + return void 0 === s && ((s = hashString(i)), qe === Re && ((qe = 0), (ze = {})), qe++, (ze[i] = s)), s; + } + function hashString(i) { + for (var s = 0, u = 0; u < i.length; u++) s = (31 * s + i.charCodeAt(u)) | 0; + return smi(s); + } + function hashJSObj(i) { + var s; + if (xe && void 0 !== (s = Se.get(i))) return s; + if (void 0 !== (s = i[Ie])) return s; + if (!we) { + if (void 0 !== (s = i.propertyIsEnumerable && i.propertyIsEnumerable[Ie])) return s; + if (void 0 !== (s = getIENodeHash(i))) return s; + } + if (((s = ++Pe), 1073741824 & Pe && (Pe = 0), xe)) Se.set(i, s); + else { + if (void 0 !== _e && !1 === _e(i)) throw new Error('Non-extensible objects are not allowed as keys.'); + if (we) Object.defineProperty(i, Ie, { enumerable: !1, configurable: !1, writable: !1, value: s }); + else if (void 0 !== i.propertyIsEnumerable && i.propertyIsEnumerable === i.constructor.prototype.propertyIsEnumerable) + (i.propertyIsEnumerable = function () { + return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments); + }), + (i.propertyIsEnumerable[Ie] = s); + else { + if (void 0 === i.nodeType) throw new Error('Unable to set a non-enumerable property on object.'); + i[Ie] = s; + } + } + return s; + } + var _e = Object.isExtensible, + we = (function () { + try { + return Object.defineProperty({}, '@', {}), !0; + } catch (i) { + return !1; + } + })(); + function getIENodeHash(i) { + if (i && i.nodeType > 0) + switch (i.nodeType) { + case 1: + return i.uniqueID; + case 9: + return i.documentElement && i.documentElement.uniqueID; + } + } + var Se, + xe = 'function' == typeof WeakMap; + xe && (Se = new WeakMap()); + var Pe = 0, + Ie = '__immutablehash__'; + 'function' == typeof Symbol && (Ie = Symbol(Ie)); + var Te = 16, + Re = 255, + qe = 0, + ze = {}; + function assertNotInfinite(i) { + invariant(i !== 1 / 0, 'Cannot perform this action with an infinite size.'); + } + function Map(i) { + return ( + null == i ? emptyMap() + : isMap(i) && !isOrdered(i) ? i + : emptyMap().withMutations(function (s) { + var u = KeyedIterable(i); + assertNotInfinite(u.size), + u.forEach(function (i, u) { + return s.set(u, i); + }); + }) + ); + } + function isMap(i) { + return !(!i || !i[We]); + } + createClass(Map, KeyedCollection), + (Map.of = function () { + var s = i.call(arguments, 0); + return emptyMap().withMutations(function (i) { + for (var u = 0; u < s.length; u += 2) { + if (u + 1 >= s.length) throw new Error('Missing value for key: ' + s[u]); + i.set(s[u], s[u + 1]); + } + }); + }), + (Map.prototype.toString = function () { + return this.__toString('Map {', '}'); + }), + (Map.prototype.get = function (i, s) { + return this._root ? this._root.get(0, void 0, i, s) : s; + }), + (Map.prototype.set = function (i, s) { + return updateMap(this, i, s); + }), + (Map.prototype.setIn = function (i, s) { + return this.updateIn(i, W, function () { + return s; + }); + }), + (Map.prototype.remove = function (i) { + return updateMap(this, i, W); + }), + (Map.prototype.deleteIn = function (i) { + return this.updateIn(i, function () { + return W; + }); + }), + (Map.prototype.update = function (i, s, u) { + return 1 === arguments.length ? i(this) : this.updateIn([i], s, u); + }), + (Map.prototype.updateIn = function (i, s, u) { + u || ((u = s), (s = void 0)); + var m = updateInDeepMap(this, forceIterator(i), s, u); + return m === W ? void 0 : m; + }), + (Map.prototype.clear = function () { + return ( + 0 === this.size ? this + : this.__ownerID ? ((this.size = 0), (this._root = null), (this.__hash = void 0), (this.__altered = !0), this) + : emptyMap() + ); + }), + (Map.prototype.merge = function () { + return mergeIntoMapWith(this, void 0, arguments); + }), + (Map.prototype.mergeWith = function (s) { + return mergeIntoMapWith(this, s, i.call(arguments, 1)); + }), + (Map.prototype.mergeIn = function (s) { + var u = i.call(arguments, 1); + return this.updateIn(s, emptyMap(), function (i) { + return 'function' == typeof i.merge ? i.merge.apply(i, u) : u[u.length - 1]; + }); + }), + (Map.prototype.mergeDeep = function () { + return mergeIntoMapWith(this, deepMerger, arguments); + }), + (Map.prototype.mergeDeepWith = function (s) { + var u = i.call(arguments, 1); + return mergeIntoMapWith(this, deepMergerWith(s), u); + }), + (Map.prototype.mergeDeepIn = function (s) { + var u = i.call(arguments, 1); + return this.updateIn(s, emptyMap(), function (i) { + return 'function' == typeof i.mergeDeep ? i.mergeDeep.apply(i, u) : u[u.length - 1]; + }); + }), + (Map.prototype.sort = function (i) { + return OrderedMap(sortFactory(this, i)); + }), + (Map.prototype.sortBy = function (i, s) { + return OrderedMap(sortFactory(this, s, i)); + }), + (Map.prototype.withMutations = function (i) { + var s = this.asMutable(); + return i(s), s.wasAltered() ? s.__ensureOwner(this.__ownerID) : this; + }), + (Map.prototype.asMutable = function () { + return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); + }), + (Map.prototype.asImmutable = function () { + return this.__ensureOwner(); + }), + (Map.prototype.wasAltered = function () { + return this.__altered; + }), + (Map.prototype.__iterator = function (i, s) { + return new MapIterator(this, i, s); + }), + (Map.prototype.__iterate = function (i, s) { + var u = this, + m = 0; + return ( + this._root && + this._root.iterate(function (s) { + return m++, i(s[1], s[0], u); + }, s), + m + ); + }), + (Map.prototype.__ensureOwner = function (i) { + return ( + i === this.__ownerID ? this + : i ? makeMap(this.size, this._root, i, this.__hash) + : ((this.__ownerID = i), (this.__altered = !1), this) + ); + }), + (Map.isMap = isMap); + var Ve, + We = '@@__IMMUTABLE_MAP__@@', + He = Map.prototype; + function ArrayMapNode(i, s) { + (this.ownerID = i), (this.entries = s); + } + function BitmapIndexedNode(i, s, u) { + (this.ownerID = i), (this.bitmap = s), (this.nodes = u); + } + function HashArrayMapNode(i, s, u) { + (this.ownerID = i), (this.count = s), (this.nodes = u); + } + function HashCollisionNode(i, s, u) { + (this.ownerID = i), (this.keyHash = s), (this.entries = u); + } + function ValueNode(i, s, u) { + (this.ownerID = i), (this.keyHash = s), (this.entry = u); + } + function MapIterator(i, s, u) { + (this._type = s), (this._reverse = u), (this._stack = i._root && mapIteratorFrame(i._root)); + } + function mapIteratorValue(i, s) { + return iteratorValue(i, s[0], s[1]); + } + function mapIteratorFrame(i, s) { + return { node: i, index: 0, __prev: s }; + } + function makeMap(i, s, u, m) { + var v = Object.create(He); + return (v.size = i), (v._root = s), (v.__ownerID = u), (v.__hash = m), (v.__altered = !1), v; + } + function emptyMap() { + return Ve || (Ve = makeMap(0)); + } + function updateMap(i, s, u) { + var m, v; + if (i._root) { + var _ = MakeRef(X), + j = MakeRef(Y); + if (((m = updateNode(i._root, i.__ownerID, 0, void 0, s, u, _, j)), !j.value)) return i; + v = + i.size + + (_.value ? + u === W ? + -1 + : 1 + : 0); + } else { + if (u === W) return i; + (v = 1), (m = new ArrayMapNode(i.__ownerID, [[s, u]])); + } + return ( + i.__ownerID ? ((i.size = v), (i._root = m), (i.__hash = void 0), (i.__altered = !0), i) + : m ? makeMap(v, m) + : emptyMap() + ); + } + function updateNode(i, s, u, m, v, _, j, M) { + return ( + i ? i.update(s, u, m, v, _, j, M) + : _ === W ? i + : (SetRef(M), SetRef(j), new ValueNode(s, m, [v, _])) + ); + } + function isLeafNode(i) { + return i.constructor === ValueNode || i.constructor === HashCollisionNode; + } + function mergeIntoNode(i, s, u, m, v) { + if (i.keyHash === m) return new HashCollisionNode(s, m, [i.entry, v]); + var _, + M = (0 === u ? i.keyHash : i.keyHash >>> u) & $, + W = (0 === u ? m : m >>> u) & $; + return new BitmapIndexedNode(s, (1 << M) | (1 << W), M === W ? [mergeIntoNode(i, s, u + j, m, v)] : ((_ = new ValueNode(s, m, v)), M < W ? [i, _] : [_, i])); + } + function createNodes(i, s, u, m) { + i || (i = new OwnerID()); + for (var v = new ValueNode(i, hash(u), [u, m]), _ = 0; _ < s.length; _++) { + var j = s[_]; + v = v.update(i, 0, void 0, j[0], j[1]); + } + return v; + } + function packNodes(i, s, u, m) { + for (var v = 0, _ = 0, j = new Array(u), M = 0, $ = 1, W = s.length; M < W; M++, $ <<= 1) { + var X = s[M]; + void 0 !== X && M !== m && ((v |= $), (j[_++] = X)); + } + return new BitmapIndexedNode(i, v, j); + } + function expandNodes(i, s, u, m, v) { + for (var _ = 0, j = new Array(M), $ = 0; 0 !== u; $++, u >>>= 1) j[$] = 1 & u ? s[_++] : void 0; + return (j[m] = v), new HashArrayMapNode(i, _ + 1, j); + } + function mergeIntoMapWith(i, s, u) { + for (var m = [], v = 0; v < u.length; v++) { + var _ = u[v], + j = KeyedIterable(_); + isIterable(_) || + (j = j.map(function (i) { + return fromJS(i); + })), + m.push(j); + } + return mergeIntoCollectionWith(i, s, m); + } + function deepMerger(i, s, u) { + return ( + i && i.mergeDeep && isIterable(s) ? i.mergeDeep(s) + : is(i, s) ? i + : s + ); + } + function deepMergerWith(i) { + return function (s, u, m) { + if (s && s.mergeDeepWith && isIterable(u)) return s.mergeDeepWith(i, u); + var v = i(s, u, m); + return is(s, v) ? s : v; + }; + } + function mergeIntoCollectionWith(i, s, u) { + return ( + ( + 0 === + (u = u.filter(function (i) { + return 0 !== i.size; + })).length + ) ? + i + : 0 !== i.size || i.__ownerID || 1 !== u.length ? + i.withMutations(function (i) { + for ( + var m = + s ? + function (u, m) { + i.update(m, W, function (i) { + return i === W ? u : s(i, u, m); + }); + } + : function (s, u) { + i.set(u, s); + }, + v = 0; + v < u.length; + v++ + ) + u[v].forEach(m); + }) + : i.constructor(u[0]) + ); + } + function updateInDeepMap(i, s, u, m) { + var v = i === W, + _ = s.next(); + if (_.done) { + var j = v ? u : i, + M = m(j); + return M === j ? i : M; + } + invariant(v || (i && i.set), 'invalid keyPath'); + var $ = _.value, + X = v ? W : i.get($, W), + Y = updateInDeepMap(X, s, u, m); + return ( + Y === X ? i + : Y === W ? i.remove($) + : (v ? emptyMap() : i).set($, Y) + ); + } + function popCount(i) { + return (i = ((i = (858993459 & (i -= (i >> 1) & 1431655765)) + ((i >> 2) & 858993459)) + (i >> 4)) & 252645135), (i += i >> 8), 127 & (i += i >> 16); + } + function setIn(i, s, u, m) { + var v = m ? i : arrCopy(i); + return (v[s] = u), v; + } + function spliceIn(i, s, u, m) { + var v = i.length + 1; + if (m && s + 1 === v) return (i[s] = u), i; + for (var _ = new Array(v), j = 0, M = 0; M < v; M++) M === s ? ((_[M] = u), (j = -1)) : (_[M] = i[M + j]); + return _; + } + function spliceOut(i, s, u) { + var m = i.length - 1; + if (u && s === m) return i.pop(), i; + for (var v = new Array(m), _ = 0, j = 0; j < m; j++) j === s && (_ = 1), (v[j] = i[j + _]); + return v; + } + (He[We] = !0), + (He[_] = He.remove), + (He.removeIn = He.deleteIn), + (ArrayMapNode.prototype.get = function (i, s, u, m) { + for (var v = this.entries, _ = 0, j = v.length; _ < j; _++) if (is(u, v[_][0])) return v[_][1]; + return m; + }), + (ArrayMapNode.prototype.update = function (i, s, u, m, v, _, j) { + for (var M = v === W, $ = this.entries, X = 0, Y = $.length; X < Y && !is(m, $[X][0]); X++); + var Z = X < Y; + if (Z ? $[X][1] === v : M) return this; + if ((SetRef(j), (M || !Z) && SetRef(_), !M || 1 !== $.length)) { + if (!Z && !M && $.length >= Xe) return createNodes(i, $, m, v); + var ee = i && i === this.ownerID, + ae = ee ? $ : arrCopy($); + return ( + Z ? + M ? + X === Y - 1 ? + ae.pop() + : (ae[X] = ae.pop()) + : (ae[X] = [m, v]) + : ae.push([m, v]), + ee ? ((this.entries = ae), this) : new ArrayMapNode(i, ae) + ); + } + }), + (BitmapIndexedNode.prototype.get = function (i, s, u, m) { + void 0 === s && (s = hash(u)); + var v = 1 << ((0 === i ? s : s >>> i) & $), + _ = this.bitmap; + return 0 == (_ & v) ? m : this.nodes[popCount(_ & (v - 1))].get(i + j, s, u, m); + }), + (BitmapIndexedNode.prototype.update = function (i, s, u, m, v, _, M) { + void 0 === u && (u = hash(m)); + var X = (0 === s ? u : u >>> s) & $, + Y = 1 << X, + Z = this.bitmap, + ee = 0 != (Z & Y); + if (!ee && v === W) return this; + var ae = popCount(Z & (Y - 1)), + ie = this.nodes, + le = ee ? ie[ae] : void 0, + ce = updateNode(le, i, s + j, u, m, v, _, M); + if (ce === le) return this; + if (!ee && ce && ie.length >= Ye) return expandNodes(i, ie, Z, X, ce); + if (ee && !ce && 2 === ie.length && isLeafNode(ie[1 ^ ae])) return ie[1 ^ ae]; + if (ee && ce && 1 === ie.length && isLeafNode(ce)) return ce; + var pe = i && i === this.ownerID, + de = + ee ? + ce ? Z + : Z ^ Y + : Z | Y, + fe = + ee ? + ce ? setIn(ie, ae, ce, pe) + : spliceOut(ie, ae, pe) + : spliceIn(ie, ae, ce, pe); + return pe ? ((this.bitmap = de), (this.nodes = fe), this) : new BitmapIndexedNode(i, de, fe); + }), + (HashArrayMapNode.prototype.get = function (i, s, u, m) { + void 0 === s && (s = hash(u)); + var v = (0 === i ? s : s >>> i) & $, + _ = this.nodes[v]; + return _ ? _.get(i + j, s, u, m) : m; + }), + (HashArrayMapNode.prototype.update = function (i, s, u, m, v, _, M) { + void 0 === u && (u = hash(m)); + var X = (0 === s ? u : u >>> s) & $, + Y = v === W, + Z = this.nodes, + ee = Z[X]; + if (Y && !ee) return this; + var ae = updateNode(ee, i, s + j, u, m, v, _, M); + if (ae === ee) return this; + var ie = this.count; + if (ee) { + if (!ae && --ie < Qe) return packNodes(i, Z, ie, X); + } else ie++; + var le = i && i === this.ownerID, + ce = setIn(Z, X, ae, le); + return le ? ((this.count = ie), (this.nodes = ce), this) : new HashArrayMapNode(i, ie, ce); + }), + (HashCollisionNode.prototype.get = function (i, s, u, m) { + for (var v = this.entries, _ = 0, j = v.length; _ < j; _++) if (is(u, v[_][0])) return v[_][1]; + return m; + }), + (HashCollisionNode.prototype.update = function (i, s, u, m, v, _, j) { + void 0 === u && (u = hash(m)); + var M = v === W; + if (u !== this.keyHash) return M ? this : (SetRef(j), SetRef(_), mergeIntoNode(this, i, s, u, [m, v])); + for (var $ = this.entries, X = 0, Y = $.length; X < Y && !is(m, $[X][0]); X++); + var Z = X < Y; + if (Z ? $[X][1] === v : M) return this; + if ((SetRef(j), (M || !Z) && SetRef(_), M && 2 === Y)) return new ValueNode(i, this.keyHash, $[1 ^ X]); + var ee = i && i === this.ownerID, + ae = ee ? $ : arrCopy($); + return ( + Z ? + M ? + X === Y - 1 ? + ae.pop() + : (ae[X] = ae.pop()) + : (ae[X] = [m, v]) + : ae.push([m, v]), + ee ? ((this.entries = ae), this) : new HashCollisionNode(i, this.keyHash, ae) + ); + }), + (ValueNode.prototype.get = function (i, s, u, m) { + return is(u, this.entry[0]) ? this.entry[1] : m; + }), + (ValueNode.prototype.update = function (i, s, u, m, v, _, j) { + var M = v === W, + $ = is(m, this.entry[0]); + return ( + $ ? v === this.entry[1] : M + ) ? + this + : (SetRef(j), + M ? void SetRef(_) + : $ ? + i && i === this.ownerID ? + ((this.entry[1] = v), this) + : new ValueNode(i, this.keyHash, [m, v]) + : (SetRef(_), mergeIntoNode(this, i, s, hash(m), [m, v]))); + }), + (ArrayMapNode.prototype.iterate = HashCollisionNode.prototype.iterate = + function (i, s) { + for (var u = this.entries, m = 0, v = u.length - 1; m <= v; m++) if (!1 === i(u[s ? v - m : m])) return !1; + }), + (BitmapIndexedNode.prototype.iterate = HashArrayMapNode.prototype.iterate = + function (i, s) { + for (var u = this.nodes, m = 0, v = u.length - 1; m <= v; m++) { + var _ = u[s ? v - m : m]; + if (_ && !1 === _.iterate(i, s)) return !1; + } + }), + (ValueNode.prototype.iterate = function (i, s) { + return i(this.entry); + }), + createClass(MapIterator, Iterator), + (MapIterator.prototype.next = function () { + for (var i = this._type, s = this._stack; s; ) { + var u, + m = s.node, + v = s.index++; + if (m.entry) { + if (0 === v) return mapIteratorValue(i, m.entry); + } else if (m.entries) { + if (v <= (u = m.entries.length - 1)) return mapIteratorValue(i, m.entries[this._reverse ? u - v : v]); + } else if (v <= (u = m.nodes.length - 1)) { + var _ = m.nodes[this._reverse ? u - v : v]; + if (_) { + if (_.entry) return mapIteratorValue(i, _.entry); + s = this._stack = mapIteratorFrame(_, s); + } + continue; + } + s = this._stack = this._stack.__prev; + } + return iteratorDone(); + }); + var Xe = M / 4, + Ye = M / 2, + Qe = M / 4; + function List(i) { + var s = emptyList(); + if (null == i) return s; + if (isList(i)) return i; + var u = IndexedIterable(i), + m = u.size; + return 0 === m ? s : ( + (assertNotInfinite(m), + m > 0 && m < M ? + makeList(0, m, j, null, new VNode(u.toArray())) + : s.withMutations(function (i) { + i.setSize(m), + u.forEach(function (s, u) { + return i.set(u, s); + }); + })) + ); + } + function isList(i) { + return !(!i || !i[et]); + } + createClass(List, IndexedCollection), + (List.of = function () { + return this(arguments); + }), + (List.prototype.toString = function () { + return this.__toString('List [', ']'); + }), + (List.prototype.get = function (i, s) { + if ((i = wrapIndex(this, i)) >= 0 && i < this.size) { + var u = listNodeFor(this, (i += this._origin)); + return u && u.array[i & $]; + } + return s; + }), + (List.prototype.set = function (i, s) { + return updateList(this, i, s); + }), + (List.prototype.remove = function (i) { + return ( + this.has(i) ? + 0 === i ? this.shift() + : i === this.size - 1 ? this.pop() + : this.splice(i, 1) + : this + ); + }), + (List.prototype.insert = function (i, s) { + return this.splice(i, 0, s); + }), + (List.prototype.clear = function () { + return ( + 0 === this.size ? this + : this.__ownerID ? ((this.size = this._origin = this._capacity = 0), (this._level = j), (this._root = this._tail = null), (this.__hash = void 0), (this.__altered = !0), this) + : emptyList() + ); + }), + (List.prototype.push = function () { + var i = arguments, + s = this.size; + return this.withMutations(function (u) { + setListBounds(u, 0, s + i.length); + for (var m = 0; m < i.length; m++) u.set(s + m, i[m]); + }); + }), + (List.prototype.pop = function () { + return setListBounds(this, 0, -1); + }), + (List.prototype.unshift = function () { + var i = arguments; + return this.withMutations(function (s) { + setListBounds(s, -i.length); + for (var u = 0; u < i.length; u++) s.set(u, i[u]); + }); + }), + (List.prototype.shift = function () { + return setListBounds(this, 1); + }), + (List.prototype.merge = function () { + return mergeIntoListWith(this, void 0, arguments); + }), + (List.prototype.mergeWith = function (s) { + return mergeIntoListWith(this, s, i.call(arguments, 1)); + }), + (List.prototype.mergeDeep = function () { + return mergeIntoListWith(this, deepMerger, arguments); + }), + (List.prototype.mergeDeepWith = function (s) { + var u = i.call(arguments, 1); + return mergeIntoListWith(this, deepMergerWith(s), u); + }), + (List.prototype.setSize = function (i) { + return setListBounds(this, 0, i); + }), + (List.prototype.slice = function (i, s) { + var u = this.size; + return wholeSlice(i, s, u) ? this : setListBounds(this, resolveBegin(i, u), resolveEnd(s, u)); + }), + (List.prototype.__iterator = function (i, s) { + var u = 0, + m = iterateList(this, s); + return new Iterator(function () { + var s = m(); + return s === ot ? iteratorDone() : iteratorValue(i, u++, s); + }); + }), + (List.prototype.__iterate = function (i, s) { + for (var u, m = 0, v = iterateList(this, s); (u = v()) !== ot && !1 !== i(u, m++, this); ); + return m; + }), + (List.prototype.__ensureOwner = function (i) { + return ( + i === this.__ownerID ? this + : i ? makeList(this._origin, this._capacity, this._level, this._root, this._tail, i, this.__hash) + : ((this.__ownerID = i), this) + ); + }), + (List.isList = isList); + var et = '@@__IMMUTABLE_LIST__@@', + tt = List.prototype; + function VNode(i, s) { + (this.array = i), (this.ownerID = s); + } + (tt[et] = !0), + (tt[_] = tt.remove), + (tt.setIn = He.setIn), + (tt.deleteIn = tt.removeIn = He.removeIn), + (tt.update = He.update), + (tt.updateIn = He.updateIn), + (tt.mergeIn = He.mergeIn), + (tt.mergeDeepIn = He.mergeDeepIn), + (tt.withMutations = He.withMutations), + (tt.asMutable = He.asMutable), + (tt.asImmutable = He.asImmutable), + (tt.wasAltered = He.wasAltered), + (VNode.prototype.removeBefore = function (i, s, u) { + if (u === s ? 1 << s : 0 === this.array.length) return this; + var m = (u >>> s) & $; + if (m >= this.array.length) return new VNode([], i); + var v, + _ = 0 === m; + if (s > 0) { + var M = this.array[m]; + if ((v = M && M.removeBefore(i, s - j, u)) === M && _) return this; + } + if (_ && !v) return this; + var W = editableVNode(this, i); + if (!_) for (var X = 0; X < m; X++) W.array[X] = void 0; + return v && (W.array[m] = v), W; + }), + (VNode.prototype.removeAfter = function (i, s, u) { + if (u === (s ? 1 << s : 0) || 0 === this.array.length) return this; + var m, + v = ((u - 1) >>> s) & $; + if (v >= this.array.length) return this; + if (s > 0) { + var _ = this.array[v]; + if ((m = _ && _.removeAfter(i, s - j, u)) === _ && v === this.array.length - 1) return this; + } + var M = editableVNode(this, i); + return M.array.splice(v + 1), m && (M.array[v] = m), M; + }); + var rt, + nt, + ot = {}; + function iterateList(i, s) { + var u = i._origin, + m = i._capacity, + v = getTailOffset(m), + _ = i._tail; + return iterateNodeOrLeaf(i._root, i._level, 0); + function iterateNodeOrLeaf(i, s, u) { + return 0 === s ? iterateLeaf(i, u) : iterateNode(i, s, u); + } + function iterateLeaf(i, j) { + var $ = j === v ? _ && _.array : i && i.array, + W = j > u ? 0 : u - j, + X = m - j; + return ( + X > M && (X = M), + function () { + if (W === X) return ot; + var i = s ? --X : W++; + return $ && $[i]; + } + ); + } + function iterateNode(i, v, _) { + var $, + W = i && i.array, + X = _ > u ? 0 : (u - _) >> v, + Y = 1 + ((m - _) >> v); + return ( + Y > M && (Y = M), + function () { + for (;;) { + if ($) { + var i = $(); + if (i !== ot) return i; + $ = null; + } + if (X === Y) return ot; + var u = s ? --Y : X++; + $ = iterateNodeOrLeaf(W && W[u], v - j, _ + (u << v)); + } + } + ); + } + } + function makeList(i, s, u, m, v, _, j) { + var M = Object.create(tt); + return (M.size = s - i), (M._origin = i), (M._capacity = s), (M._level = u), (M._root = m), (M._tail = v), (M.__ownerID = _), (M.__hash = j), (M.__altered = !1), M; + } + function emptyList() { + return rt || (rt = makeList(0, 0, j)); + } + function updateList(i, s, u) { + if ((s = wrapIndex(i, s)) != s) return i; + if (s >= i.size || s < 0) + return i.withMutations(function (i) { + s < 0 ? setListBounds(i, s).set(0, u) : setListBounds(i, 0, s + 1).set(s, u); + }); + s += i._origin; + var m = i._tail, + v = i._root, + _ = MakeRef(Y); + return ( + s >= getTailOffset(i._capacity) ? (m = updateVNode(m, i.__ownerID, 0, s, u, _)) : (v = updateVNode(v, i.__ownerID, i._level, s, u, _)), + _.value ? + i.__ownerID ? + ((i._root = v), (i._tail = m), (i.__hash = void 0), (i.__altered = !0), i) + : makeList(i._origin, i._capacity, i._level, v, m) + : i + ); + } + function updateVNode(i, s, u, m, v, _) { + var M, + W = (m >>> u) & $, + X = i && W < i.array.length; + if (!X && void 0 === v) return i; + if (u > 0) { + var Y = i && i.array[W], + Z = updateVNode(Y, s, u - j, m, v, _); + return Z === Y ? i : (((M = editableVNode(i, s)).array[W] = Z), M); + } + return X && i.array[W] === v ? i : (SetRef(_), (M = editableVNode(i, s)), void 0 === v && W === M.array.length - 1 ? M.array.pop() : (M.array[W] = v), M); + } + function editableVNode(i, s) { + return s && i && s === i.ownerID ? i : new VNode(i ? i.array.slice() : [], s); + } + function listNodeFor(i, s) { + if (s >= getTailOffset(i._capacity)) return i._tail; + if (s < 1 << (i._level + j)) { + for (var u = i._root, m = i._level; u && m > 0; ) (u = u.array[(s >>> m) & $]), (m -= j); + return u; + } + } + function setListBounds(i, s, u) { + void 0 !== s && (s |= 0), void 0 !== u && (u |= 0); + var m = i.__ownerID || new OwnerID(), + v = i._origin, + _ = i._capacity, + M = v + s, + W = + void 0 === u ? _ + : u < 0 ? _ + u + : v + u; + if (M === v && W === _) return i; + if (M >= W) return i.clear(); + for (var X = i._level, Y = i._root, Z = 0; M + Z < 0; ) (Y = new VNode(Y && Y.array.length ? [void 0, Y] : [], m)), (Z += 1 << (X += j)); + Z && ((M += Z), (v += Z), (W += Z), (_ += Z)); + for (var ee = getTailOffset(_), ae = getTailOffset(W); ae >= 1 << (X + j); ) (Y = new VNode(Y && Y.array.length ? [Y] : [], m)), (X += j); + var ie = i._tail, + le = + ae < ee ? listNodeFor(i, W - 1) + : ae > ee ? new VNode([], m) + : ie; + if (ie && ae > ee && M < _ && ie.array.length) { + for (var ce = (Y = editableVNode(Y, m)), pe = X; pe > j; pe -= j) { + var de = (ee >>> pe) & $; + ce = ce.array[de] = editableVNode(ce.array[de], m); + } + ce.array[(ee >>> j) & $] = ie; + } + if ((W < _ && (le = le && le.removeAfter(m, 0, W)), M >= ae)) (M -= ae), (W -= ae), (X = j), (Y = null), (le = le && le.removeBefore(m, 0, M)); + else if (M > v || ae < ee) { + for (Z = 0; Y; ) { + var fe = (M >>> X) & $; + if ((fe !== ae >>> X) & $) break; + fe && (Z += (1 << X) * fe), (X -= j), (Y = Y.array[fe]); + } + Y && M > v && (Y = Y.removeBefore(m, X, M - Z)), Y && ae < ee && (Y = Y.removeAfter(m, X, ae - Z)), Z && ((M -= Z), (W -= Z)); + } + return i.__ownerID ? ((i.size = W - M), (i._origin = M), (i._capacity = W), (i._level = X), (i._root = Y), (i._tail = le), (i.__hash = void 0), (i.__altered = !0), i) : makeList(M, W, X, Y, le); + } + function mergeIntoListWith(i, s, u) { + for (var m = [], v = 0, _ = 0; _ < u.length; _++) { + var j = u[_], + M = IndexedIterable(j); + M.size > v && (v = M.size), + isIterable(j) || + (M = M.map(function (i) { + return fromJS(i); + })), + m.push(M); + } + return v > i.size && (i = i.setSize(v)), mergeIntoCollectionWith(i, s, m); + } + function getTailOffset(i) { + return i < M ? 0 : ((i - 1) >>> j) << j; + } + function OrderedMap(i) { + return ( + null == i ? emptyOrderedMap() + : isOrderedMap(i) ? i + : emptyOrderedMap().withMutations(function (s) { + var u = KeyedIterable(i); + assertNotInfinite(u.size), + u.forEach(function (i, u) { + return s.set(u, i); + }); + }) + ); + } + function isOrderedMap(i) { + return isMap(i) && isOrdered(i); + } + function makeOrderedMap(i, s, u, m) { + var v = Object.create(OrderedMap.prototype); + return (v.size = i ? i.size : 0), (v._map = i), (v._list = s), (v.__ownerID = u), (v.__hash = m), v; + } + function emptyOrderedMap() { + return nt || (nt = makeOrderedMap(emptyMap(), emptyList())); + } + function updateOrderedMap(i, s, u) { + var m, + v, + _ = i._map, + j = i._list, + $ = _.get(s), + X = void 0 !== $; + if (u === W) { + if (!X) return i; + j.size >= M && j.size >= 2 * _.size ? + ((m = (v = j.filter(function (i, s) { + return void 0 !== i && $ !== s; + })) + .toKeyedSeq() + .map(function (i) { + return i[0]; + }) + .flip() + .toMap()), + i.__ownerID && (m.__ownerID = v.__ownerID = i.__ownerID)) + : ((m = _.remove(s)), (v = $ === j.size - 1 ? j.pop() : j.set($, void 0))); + } else if (X) { + if (u === j.get($)[1]) return i; + (m = _), (v = j.set($, [s, u])); + } else (m = _.set(s, j.size)), (v = j.set(j.size, [s, u])); + return i.__ownerID ? ((i.size = m.size), (i._map = m), (i._list = v), (i.__hash = void 0), i) : makeOrderedMap(m, v); + } + function ToKeyedSequence(i, s) { + (this._iter = i), (this._useKeys = s), (this.size = i.size); + } + function ToIndexedSequence(i) { + (this._iter = i), (this.size = i.size); + } + function ToSetSequence(i) { + (this._iter = i), (this.size = i.size); + } + function FromEntriesSequence(i) { + (this._iter = i), (this.size = i.size); + } + function flipFactory(i) { + var s = makeSequence(i); + return ( + (s._iter = i), + (s.size = i.size), + (s.flip = function () { + return i; + }), + (s.reverse = function () { + var s = i.reverse.apply(this); + return ( + (s.flip = function () { + return i.reverse(); + }), + s + ); + }), + (s.has = function (s) { + return i.includes(s); + }), + (s.includes = function (s) { + return i.has(s); + }), + (s.cacheResult = cacheResultThrough), + (s.__iterateUncached = function (s, u) { + var m = this; + return i.__iterate(function (i, u) { + return !1 !== s(u, i, m); + }, u); + }), + (s.__iteratorUncached = function (s, u) { + if (s === ae) { + var m = i.__iterator(s, u); + return new Iterator(function () { + var i = m.next(); + if (!i.done) { + var s = i.value[0]; + (i.value[0] = i.value[1]), (i.value[1] = s); + } + return i; + }); + } + return i.__iterator(s === ee ? Z : ee, u); + }), + s + ); + } + function mapFactory(i, s, u) { + var m = makeSequence(i); + return ( + (m.size = i.size), + (m.has = function (s) { + return i.has(s); + }), + (m.get = function (m, v) { + var _ = i.get(m, W); + return _ === W ? v : s.call(u, _, m, i); + }), + (m.__iterateUncached = function (m, v) { + var _ = this; + return i.__iterate(function (i, v, j) { + return !1 !== m(s.call(u, i, v, j), v, _); + }, v); + }), + (m.__iteratorUncached = function (m, v) { + var _ = i.__iterator(ae, v); + return new Iterator(function () { + var v = _.next(); + if (v.done) return v; + var j = v.value, + M = j[0]; + return iteratorValue(m, M, s.call(u, j[1], M, i), v); + }); + }), + m + ); + } + function reverseFactory(i, s) { + var u = makeSequence(i); + return ( + (u._iter = i), + (u.size = i.size), + (u.reverse = function () { + return i; + }), + i.flip && + (u.flip = function () { + var s = flipFactory(i); + return ( + (s.reverse = function () { + return i.flip(); + }), + s + ); + }), + (u.get = function (u, m) { + return i.get(s ? u : -1 - u, m); + }), + (u.has = function (u) { + return i.has(s ? u : -1 - u); + }), + (u.includes = function (s) { + return i.includes(s); + }), + (u.cacheResult = cacheResultThrough), + (u.__iterate = function (s, u) { + var m = this; + return i.__iterate(function (i, u) { + return s(i, u, m); + }, !u); + }), + (u.__iterator = function (s, u) { + return i.__iterator(s, !u); + }), + u + ); + } + function filterFactory(i, s, u, m) { + var v = makeSequence(i); + return ( + m && + ((v.has = function (m) { + var v = i.get(m, W); + return v !== W && !!s.call(u, v, m, i); + }), + (v.get = function (m, v) { + var _ = i.get(m, W); + return _ !== W && s.call(u, _, m, i) ? _ : v; + })), + (v.__iterateUncached = function (v, _) { + var j = this, + M = 0; + return ( + i.__iterate(function (i, _, $) { + if (s.call(u, i, _, $)) return M++, v(i, m ? _ : M - 1, j); + }, _), + M + ); + }), + (v.__iteratorUncached = function (v, _) { + var j = i.__iterator(ae, _), + M = 0; + return new Iterator(function () { + for (;;) { + var _ = j.next(); + if (_.done) return _; + var $ = _.value, + W = $[0], + X = $[1]; + if (s.call(u, X, W, i)) return iteratorValue(v, m ? W : M++, X, _); + } + }); + }), + v + ); + } + function countByFactory(i, s, u) { + var m = Map().asMutable(); + return ( + i.__iterate(function (v, _) { + m.update(s.call(u, v, _, i), 0, function (i) { + return i + 1; + }); + }), + m.asImmutable() + ); + } + function groupByFactory(i, s, u) { + var m = isKeyed(i), + v = (isOrdered(i) ? OrderedMap() : Map()).asMutable(); + i.__iterate(function (_, j) { + v.update(s.call(u, _, j, i), function (i) { + return (i = i || []).push(m ? [j, _] : _), i; + }); + }); + var _ = iterableClass(i); + return v.map(function (s) { + return reify(i, _(s)); + }); + } + function sliceFactory(i, s, u, m) { + var v = i.size; + if ((void 0 !== s && (s |= 0), void 0 !== u && (u === 1 / 0 ? (u = v) : (u |= 0)), wholeSlice(s, u, v))) return i; + var _ = resolveBegin(s, v), + j = resolveEnd(u, v); + if (_ != _ || j != j) return sliceFactory(i.toSeq().cacheResult(), s, u, m); + var M, + $ = j - _; + $ == $ && (M = $ < 0 ? 0 : $); + var W = makeSequence(i); + return ( + (W.size = 0 === M ? M : (i.size && M) || void 0), + !m && + isSeq(i) && + M >= 0 && + (W.get = function (s, u) { + return (s = wrapIndex(this, s)) >= 0 && s < M ? i.get(s + _, u) : u; + }), + (W.__iterateUncached = function (s, u) { + var v = this; + if (0 === M) return 0; + if (u) return this.cacheResult().__iterate(s, u); + var j = 0, + $ = !0, + W = 0; + return ( + i.__iterate(function (i, u) { + if (!$ || !($ = j++ < _)) return W++, !1 !== s(i, m ? u : W - 1, v) && W !== M; + }), + W + ); + }), + (W.__iteratorUncached = function (s, u) { + if (0 !== M && u) return this.cacheResult().__iterator(s, u); + var v = 0 !== M && i.__iterator(s, u), + j = 0, + $ = 0; + return new Iterator(function () { + for (; j++ < _; ) v.next(); + if (++$ > M) return iteratorDone(); + var i = v.next(); + return m || s === ee ? i : iteratorValue(s, $ - 1, s === Z ? void 0 : i.value[1], i); + }); + }), + W + ); + } + function takeWhileFactory(i, s, u) { + var m = makeSequence(i); + return ( + (m.__iterateUncached = function (m, v) { + var _ = this; + if (v) return this.cacheResult().__iterate(m, v); + var j = 0; + return ( + i.__iterate(function (i, v, M) { + return s.call(u, i, v, M) && ++j && m(i, v, _); + }), + j + ); + }), + (m.__iteratorUncached = function (m, v) { + var _ = this; + if (v) return this.cacheResult().__iterator(m, v); + var j = i.__iterator(ae, v), + M = !0; + return new Iterator(function () { + if (!M) return iteratorDone(); + var i = j.next(); + if (i.done) return i; + var v = i.value, + $ = v[0], + W = v[1]; + return ( + s.call(u, W, $, _) ? + m === ae ? + i + : iteratorValue(m, $, W, i) + : ((M = !1), iteratorDone()) + ); + }); + }), + m + ); + } + function skipWhileFactory(i, s, u, m) { + var v = makeSequence(i); + return ( + (v.__iterateUncached = function (v, _) { + var j = this; + if (_) return this.cacheResult().__iterate(v, _); + var M = !0, + $ = 0; + return ( + i.__iterate(function (i, _, W) { + if (!M || !(M = s.call(u, i, _, W))) return $++, v(i, m ? _ : $ - 1, j); + }), + $ + ); + }), + (v.__iteratorUncached = function (v, _) { + var j = this; + if (_) return this.cacheResult().__iterator(v, _); + var M = i.__iterator(ae, _), + $ = !0, + W = 0; + return new Iterator(function () { + var i, _, X; + do { + if ((i = M.next()).done) return m || v === ee ? i : iteratorValue(v, W++, v === Z ? void 0 : i.value[1], i); + var Y = i.value; + (_ = Y[0]), (X = Y[1]), $ && ($ = s.call(u, X, _, j)); + } while ($); + return v === ae ? i : iteratorValue(v, _, X, i); + }); + }), + v + ); + } + function concatFactory(i, s) { + var u = isKeyed(i), + m = [i] + .concat(s) + .map(function (i) { + return isIterable(i) ? u && (i = KeyedIterable(i)) : (i = u ? keyedSeqFromValue(i) : indexedSeqFromValue(Array.isArray(i) ? i : [i])), i; + }) + .filter(function (i) { + return 0 !== i.size; + }); + if (0 === m.length) return i; + if (1 === m.length) { + var v = m[0]; + if (v === i || (u && isKeyed(v)) || (isIndexed(i) && isIndexed(v))) return v; + } + var _ = new ArraySeq(m); + return ( + u ? (_ = _.toKeyedSeq()) : isIndexed(i) || (_ = _.toSetSeq()), + ((_ = _.flatten(!0)).size = m.reduce(function (i, s) { + if (void 0 !== i) { + var u = s.size; + if (void 0 !== u) return i + u; + } + }, 0)), + _ + ); + } + function flattenFactory(i, s, u) { + var m = makeSequence(i); + return ( + (m.__iterateUncached = function (m, v) { + var _ = 0, + j = !1; + function flatDeep(i, M) { + var $ = this; + i.__iterate(function (i, v) { + return (!s || M < s) && isIterable(i) ? flatDeep(i, M + 1) : !1 === m(i, u ? v : _++, $) && (j = !0), !j; + }, v); + } + return flatDeep(i, 0), _; + }), + (m.__iteratorUncached = function (m, v) { + var _ = i.__iterator(m, v), + j = [], + M = 0; + return new Iterator(function () { + for (; _; ) { + var i = _.next(); + if (!1 === i.done) { + var $ = i.value; + if ((m === ae && ($ = $[1]), (s && !(j.length < s)) || !isIterable($))) return u ? i : iteratorValue(m, M++, $, i); + j.push(_), (_ = $.__iterator(m, v)); + } else _ = j.pop(); + } + return iteratorDone(); + }); + }), + m + ); + } + function flatMapFactory(i, s, u) { + var m = iterableClass(i); + return i + .toSeq() + .map(function (v, _) { + return m(s.call(u, v, _, i)); + }) + .flatten(!0); + } + function interposeFactory(i, s) { + var u = makeSequence(i); + return ( + (u.size = i.size && 2 * i.size - 1), + (u.__iterateUncached = function (u, m) { + var v = this, + _ = 0; + return ( + i.__iterate(function (i, m) { + return (!_ || !1 !== u(s, _++, v)) && !1 !== u(i, _++, v); + }, m), + _ + ); + }), + (u.__iteratorUncached = function (u, m) { + var v, + _ = i.__iterator(ee, m), + j = 0; + return new Iterator(function () { + return ( + (!v || j % 2) && (v = _.next()).done ? v + : j % 2 ? iteratorValue(u, j++, s) + : iteratorValue(u, j++, v.value, v) + ); + }); + }), + u + ); + } + function sortFactory(i, s, u) { + s || (s = defaultComparator); + var m = isKeyed(i), + v = 0, + _ = i + .toSeq() + .map(function (s, m) { + return [m, s, v++, u ? u(s, m, i) : s]; + }) + .toArray(); + return ( + _.sort(function (i, u) { + return s(i[3], u[3]) || i[2] - u[2]; + }).forEach( + m ? + function (i, s) { + _[s].length = 2; + } + : function (i, s) { + _[s] = i[1]; + } + ), + m ? KeyedSeq(_) + : isIndexed(i) ? IndexedSeq(_) + : SetSeq(_) + ); + } + function maxFactory(i, s, u) { + if ((s || (s = defaultComparator), u)) { + var m = i + .toSeq() + .map(function (s, m) { + return [s, u(s, m, i)]; + }) + .reduce(function (i, u) { + return maxCompare(s, i[1], u[1]) ? u : i; + }); + return m && m[0]; + } + return i.reduce(function (i, u) { + return maxCompare(s, i, u) ? u : i; + }); + } + function maxCompare(i, s, u) { + var m = i(u, s); + return (0 === m && u !== s && (null == u || u != u)) || m > 0; + } + function zipWithFactory(i, s, u) { + var m = makeSequence(i); + return ( + (m.size = new ArraySeq(u) + .map(function (i) { + return i.size; + }) + .min()), + (m.__iterate = function (i, s) { + for (var u, m = this.__iterator(ee, s), v = 0; !(u = m.next()).done && !1 !== i(u.value, v++, this); ); + return v; + }), + (m.__iteratorUncached = function (i, m) { + var v = u.map(function (i) { + return (i = Iterable(i)), getIterator(m ? i.reverse() : i); + }), + _ = 0, + j = !1; + return new Iterator(function () { + var u; + return ( + j || + ((u = v.map(function (i) { + return i.next(); + })), + (j = u.some(function (i) { + return i.done; + }))), + j ? iteratorDone() : ( + iteratorValue( + i, + _++, + s.apply( + null, + u.map(function (i) { + return i.value; + }) + ) + ) + ) + ); + }); + }), + m + ); + } + function reify(i, s) { + return isSeq(i) ? s : i.constructor(s); + } + function validateEntry(i) { + if (i !== Object(i)) throw new TypeError('Expected [K, V] tuple: ' + i); + } + function resolveSize(i) { + return assertNotInfinite(i.size), ensureSize(i); + } + function iterableClass(i) { + return ( + isKeyed(i) ? KeyedIterable + : isIndexed(i) ? IndexedIterable + : SetIterable + ); + } + function makeSequence(i) { + return Object.create( + (isKeyed(i) ? KeyedSeq + : isIndexed(i) ? IndexedSeq + : SetSeq + ).prototype + ); + } + function cacheResultThrough() { + return this._iter.cacheResult ? (this._iter.cacheResult(), (this.size = this._iter.size), this) : Seq.prototype.cacheResult.call(this); + } + function defaultComparator(i, s) { + return ( + i > s ? 1 + : i < s ? -1 + : 0 + ); + } + function forceIterator(i) { + var s = getIterator(i); + if (!s) { + if (!isArrayLike(i)) throw new TypeError('Expected iterable or array-like: ' + i); + s = getIterator(Iterable(i)); + } + return s; + } + function Record(i, s) { + var u, + m = function Record(_) { + if (_ instanceof m) return _; + if (!(this instanceof m)) return new m(_); + if (!u) { + u = !0; + var j = Object.keys(i); + setProps(v, j), (v.size = j.length), (v._name = s), (v._keys = j), (v._defaultValues = i); + } + this._map = Map(_); + }, + v = (m.prototype = Object.create(at)); + return (v.constructor = m), m; + } + createClass(OrderedMap, Map), + (OrderedMap.of = function () { + return this(arguments); + }), + (OrderedMap.prototype.toString = function () { + return this.__toString('OrderedMap {', '}'); + }), + (OrderedMap.prototype.get = function (i, s) { + var u = this._map.get(i); + return void 0 !== u ? this._list.get(u)[1] : s; + }), + (OrderedMap.prototype.clear = function () { + return ( + 0 === this.size ? this + : this.__ownerID ? ((this.size = 0), this._map.clear(), this._list.clear(), this) + : emptyOrderedMap() + ); + }), + (OrderedMap.prototype.set = function (i, s) { + return updateOrderedMap(this, i, s); + }), + (OrderedMap.prototype.remove = function (i) { + return updateOrderedMap(this, i, W); + }), + (OrderedMap.prototype.wasAltered = function () { + return this._map.wasAltered() || this._list.wasAltered(); + }), + (OrderedMap.prototype.__iterate = function (i, s) { + var u = this; + return this._list.__iterate(function (s) { + return s && i(s[1], s[0], u); + }, s); + }), + (OrderedMap.prototype.__iterator = function (i, s) { + return this._list.fromEntrySeq().__iterator(i, s); + }), + (OrderedMap.prototype.__ensureOwner = function (i) { + if (i === this.__ownerID) return this; + var s = this._map.__ensureOwner(i), + u = this._list.__ensureOwner(i); + return i ? makeOrderedMap(s, u, i, this.__hash) : ((this.__ownerID = i), (this._map = s), (this._list = u), this); + }), + (OrderedMap.isOrderedMap = isOrderedMap), + (OrderedMap.prototype[v] = !0), + (OrderedMap.prototype[_] = OrderedMap.prototype.remove), + createClass(ToKeyedSequence, KeyedSeq), + (ToKeyedSequence.prototype.get = function (i, s) { + return this._iter.get(i, s); + }), + (ToKeyedSequence.prototype.has = function (i) { + return this._iter.has(i); + }), + (ToKeyedSequence.prototype.valueSeq = function () { + return this._iter.valueSeq(); + }), + (ToKeyedSequence.prototype.reverse = function () { + var i = this, + s = reverseFactory(this, !0); + return ( + this._useKeys || + (s.valueSeq = function () { + return i._iter.toSeq().reverse(); + }), + s + ); + }), + (ToKeyedSequence.prototype.map = function (i, s) { + var u = this, + m = mapFactory(this, i, s); + return ( + this._useKeys || + (m.valueSeq = function () { + return u._iter.toSeq().map(i, s); + }), + m + ); + }), + (ToKeyedSequence.prototype.__iterate = function (i, s) { + var u, + m = this; + return this._iter.__iterate( + this._useKeys ? + function (s, u) { + return i(s, u, m); + } + : ((u = s ? resolveSize(this) : 0), + function (v) { + return i(v, s ? --u : u++, m); + }), + s + ); + }), + (ToKeyedSequence.prototype.__iterator = function (i, s) { + if (this._useKeys) return this._iter.__iterator(i, s); + var u = this._iter.__iterator(ee, s), + m = s ? resolveSize(this) : 0; + return new Iterator(function () { + var v = u.next(); + return v.done ? v : iteratorValue(i, s ? --m : m++, v.value, v); + }); + }), + (ToKeyedSequence.prototype[v] = !0), + createClass(ToIndexedSequence, IndexedSeq), + (ToIndexedSequence.prototype.includes = function (i) { + return this._iter.includes(i); + }), + (ToIndexedSequence.prototype.__iterate = function (i, s) { + var u = this, + m = 0; + return this._iter.__iterate(function (s) { + return i(s, m++, u); + }, s); + }), + (ToIndexedSequence.prototype.__iterator = function (i, s) { + var u = this._iter.__iterator(ee, s), + m = 0; + return new Iterator(function () { + var s = u.next(); + return s.done ? s : iteratorValue(i, m++, s.value, s); + }); + }), + createClass(ToSetSequence, SetSeq), + (ToSetSequence.prototype.has = function (i) { + return this._iter.includes(i); + }), + (ToSetSequence.prototype.__iterate = function (i, s) { + var u = this; + return this._iter.__iterate(function (s) { + return i(s, s, u); + }, s); + }), + (ToSetSequence.prototype.__iterator = function (i, s) { + var u = this._iter.__iterator(ee, s); + return new Iterator(function () { + var s = u.next(); + return s.done ? s : iteratorValue(i, s.value, s.value, s); + }); + }), + createClass(FromEntriesSequence, KeyedSeq), + (FromEntriesSequence.prototype.entrySeq = function () { + return this._iter.toSeq(); + }), + (FromEntriesSequence.prototype.__iterate = function (i, s) { + var u = this; + return this._iter.__iterate(function (s) { + if (s) { + validateEntry(s); + var m = isIterable(s); + return i(m ? s.get(1) : s[1], m ? s.get(0) : s[0], u); + } + }, s); + }), + (FromEntriesSequence.prototype.__iterator = function (i, s) { + var u = this._iter.__iterator(ee, s); + return new Iterator(function () { + for (;;) { + var s = u.next(); + if (s.done) return s; + var m = s.value; + if (m) { + validateEntry(m); + var v = isIterable(m); + return iteratorValue(i, v ? m.get(0) : m[0], v ? m.get(1) : m[1], s); + } + } + }); + }), + (ToIndexedSequence.prototype.cacheResult = ToKeyedSequence.prototype.cacheResult = ToSetSequence.prototype.cacheResult = FromEntriesSequence.prototype.cacheResult = cacheResultThrough), + createClass(Record, KeyedCollection), + (Record.prototype.toString = function () { + return this.__toString(recordName(this) + ' {', '}'); + }), + (Record.prototype.has = function (i) { + return this._defaultValues.hasOwnProperty(i); + }), + (Record.prototype.get = function (i, s) { + if (!this.has(i)) return s; + var u = this._defaultValues[i]; + return this._map ? this._map.get(i, u) : u; + }), + (Record.prototype.clear = function () { + if (this.__ownerID) return this._map && this._map.clear(), this; + var i = this.constructor; + return i._empty || (i._empty = makeRecord(this, emptyMap())); + }), + (Record.prototype.set = function (i, s) { + if (!this.has(i)) throw new Error('Cannot set unknown key "' + i + '" on ' + recordName(this)); + if (this._map && !this._map.has(i) && s === this._defaultValues[i]) return this; + var u = this._map && this._map.set(i, s); + return this.__ownerID || u === this._map ? this : makeRecord(this, u); + }), + (Record.prototype.remove = function (i) { + if (!this.has(i)) return this; + var s = this._map && this._map.remove(i); + return this.__ownerID || s === this._map ? this : makeRecord(this, s); + }), + (Record.prototype.wasAltered = function () { + return this._map.wasAltered(); + }), + (Record.prototype.__iterator = function (i, s) { + var u = this; + return KeyedIterable(this._defaultValues) + .map(function (i, s) { + return u.get(s); + }) + .__iterator(i, s); + }), + (Record.prototype.__iterate = function (i, s) { + var u = this; + return KeyedIterable(this._defaultValues) + .map(function (i, s) { + return u.get(s); + }) + .__iterate(i, s); + }), + (Record.prototype.__ensureOwner = function (i) { + if (i === this.__ownerID) return this; + var s = this._map && this._map.__ensureOwner(i); + return i ? makeRecord(this, s, i) : ((this.__ownerID = i), (this._map = s), this); + }); + var at = Record.prototype; + function makeRecord(i, s, u) { + var m = Object.create(Object.getPrototypeOf(i)); + return (m._map = s), (m.__ownerID = u), m; + } + function recordName(i) { + return i._name || i.constructor.name || 'Record'; + } + function setProps(i, s) { + try { + s.forEach(setProp.bind(void 0, i)); + } catch (i) {} + } + function setProp(i, s) { + Object.defineProperty(i, s, { + get: function () { + return this.get(s); + }, + set: function (i) { + invariant(this.__ownerID, 'Cannot set on an immutable record.'), this.set(s, i); + } + }); + } + function Set(i) { + return ( + null == i ? emptySet() + : isSet(i) && !isOrdered(i) ? i + : emptySet().withMutations(function (s) { + var u = SetIterable(i); + assertNotInfinite(u.size), + u.forEach(function (i) { + return s.add(i); + }); + }) + ); + } + function isSet(i) { + return !(!i || !i[st]); + } + (at[_] = at.remove), + (at.deleteIn = at.removeIn = He.removeIn), + (at.merge = He.merge), + (at.mergeWith = He.mergeWith), + (at.mergeIn = He.mergeIn), + (at.mergeDeep = He.mergeDeep), + (at.mergeDeepWith = He.mergeDeepWith), + (at.mergeDeepIn = He.mergeDeepIn), + (at.setIn = He.setIn), + (at.update = He.update), + (at.updateIn = He.updateIn), + (at.withMutations = He.withMutations), + (at.asMutable = He.asMutable), + (at.asImmutable = He.asImmutable), + createClass(Set, SetCollection), + (Set.of = function () { + return this(arguments); + }), + (Set.fromKeys = function (i) { + return this(KeyedIterable(i).keySeq()); + }), + (Set.prototype.toString = function () { + return this.__toString('Set {', '}'); + }), + (Set.prototype.has = function (i) { + return this._map.has(i); + }), + (Set.prototype.add = function (i) { + return updateSet(this, this._map.set(i, !0)); + }), + (Set.prototype.remove = function (i) { + return updateSet(this, this._map.remove(i)); + }), + (Set.prototype.clear = function () { + return updateSet(this, this._map.clear()); + }), + (Set.prototype.union = function () { + var s = i.call(arguments, 0); + return ( + ( + 0 === + (s = s.filter(function (i) { + return 0 !== i.size; + })).length + ) ? + this + : 0 !== this.size || this.__ownerID || 1 !== s.length ? + this.withMutations(function (i) { + for (var u = 0; u < s.length; u++) + SetIterable(s[u]).forEach(function (s) { + return i.add(s); + }); + }) + : this.constructor(s[0]) + ); + }), + (Set.prototype.intersect = function () { + var s = i.call(arguments, 0); + if (0 === s.length) return this; + s = s.map(function (i) { + return SetIterable(i); + }); + var u = this; + return this.withMutations(function (i) { + u.forEach(function (u) { + s.every(function (i) { + return i.includes(u); + }) || i.remove(u); + }); + }); + }), + (Set.prototype.subtract = function () { + var s = i.call(arguments, 0); + if (0 === s.length) return this; + s = s.map(function (i) { + return SetIterable(i); + }); + var u = this; + return this.withMutations(function (i) { + u.forEach(function (u) { + s.some(function (i) { + return i.includes(u); + }) && i.remove(u); + }); + }); + }), + (Set.prototype.merge = function () { + return this.union.apply(this, arguments); + }), + (Set.prototype.mergeWith = function (s) { + var u = i.call(arguments, 1); + return this.union.apply(this, u); + }), + (Set.prototype.sort = function (i) { + return OrderedSet(sortFactory(this, i)); + }), + (Set.prototype.sortBy = function (i, s) { + return OrderedSet(sortFactory(this, s, i)); + }), + (Set.prototype.wasAltered = function () { + return this._map.wasAltered(); + }), + (Set.prototype.__iterate = function (i, s) { + var u = this; + return this._map.__iterate(function (s, m) { + return i(m, m, u); + }, s); + }), + (Set.prototype.__iterator = function (i, s) { + return this._map + .map(function (i, s) { + return s; + }) + .__iterator(i, s); + }), + (Set.prototype.__ensureOwner = function (i) { + if (i === this.__ownerID) return this; + var s = this._map.__ensureOwner(i); + return i ? this.__make(s, i) : ((this.__ownerID = i), (this._map = s), this); + }), + (Set.isSet = isSet); + var it, + st = '@@__IMMUTABLE_SET__@@', + lt = Set.prototype; + function updateSet(i, s) { + return ( + i.__ownerID ? ((i.size = s.size), (i._map = s), i) + : s === i._map ? i + : 0 === s.size ? i.__empty() + : i.__make(s) + ); + } + function makeSet(i, s) { + var u = Object.create(lt); + return (u.size = i ? i.size : 0), (u._map = i), (u.__ownerID = s), u; + } + function emptySet() { + return it || (it = makeSet(emptyMap())); + } + function OrderedSet(i) { + return ( + null == i ? emptyOrderedSet() + : isOrderedSet(i) ? i + : emptyOrderedSet().withMutations(function (s) { + var u = SetIterable(i); + assertNotInfinite(u.size), + u.forEach(function (i) { + return s.add(i); + }); + }) + ); + } + function isOrderedSet(i) { + return isSet(i) && isOrdered(i); + } + (lt[st] = !0), + (lt[_] = lt.remove), + (lt.mergeDeep = lt.merge), + (lt.mergeDeepWith = lt.mergeWith), + (lt.withMutations = He.withMutations), + (lt.asMutable = He.asMutable), + (lt.asImmutable = He.asImmutable), + (lt.__empty = emptySet), + (lt.__make = makeSet), + createClass(OrderedSet, Set), + (OrderedSet.of = function () { + return this(arguments); + }), + (OrderedSet.fromKeys = function (i) { + return this(KeyedIterable(i).keySeq()); + }), + (OrderedSet.prototype.toString = function () { + return this.__toString('OrderedSet {', '}'); + }), + (OrderedSet.isOrderedSet = isOrderedSet); + var ct, + ut = OrderedSet.prototype; + function makeOrderedSet(i, s) { + var u = Object.create(ut); + return (u.size = i ? i.size : 0), (u._map = i), (u.__ownerID = s), u; + } + function emptyOrderedSet() { + return ct || (ct = makeOrderedSet(emptyOrderedMap())); + } + function Stack(i) { + return ( + null == i ? emptyStack() + : isStack(i) ? i + : emptyStack().unshiftAll(i) + ); + } + function isStack(i) { + return !(!i || !i[ht]); + } + (ut[v] = !0), + (ut.__empty = emptyOrderedSet), + (ut.__make = makeOrderedSet), + createClass(Stack, IndexedCollection), + (Stack.of = function () { + return this(arguments); + }), + (Stack.prototype.toString = function () { + return this.__toString('Stack [', ']'); + }), + (Stack.prototype.get = function (i, s) { + var u = this._head; + for (i = wrapIndex(this, i); u && i--; ) u = u.next; + return u ? u.value : s; + }), + (Stack.prototype.peek = function () { + return this._head && this._head.value; + }), + (Stack.prototype.push = function () { + if (0 === arguments.length) return this; + for (var i = this.size + arguments.length, s = this._head, u = arguments.length - 1; u >= 0; u--) s = { value: arguments[u], next: s }; + return this.__ownerID ? ((this.size = i), (this._head = s), (this.__hash = void 0), (this.__altered = !0), this) : makeStack(i, s); + }), + (Stack.prototype.pushAll = function (i) { + if (0 === (i = IndexedIterable(i)).size) return this; + assertNotInfinite(i.size); + var s = this.size, + u = this._head; + return ( + i.reverse().forEach(function (i) { + s++, (u = { value: i, next: u }); + }), + this.__ownerID ? ((this.size = s), (this._head = u), (this.__hash = void 0), (this.__altered = !0), this) : makeStack(s, u) + ); + }), + (Stack.prototype.pop = function () { + return this.slice(1); + }), + (Stack.prototype.unshift = function () { + return this.push.apply(this, arguments); + }), + (Stack.prototype.unshiftAll = function (i) { + return this.pushAll(i); + }), + (Stack.prototype.shift = function () { + return this.pop.apply(this, arguments); + }), + (Stack.prototype.clear = function () { + return ( + 0 === this.size ? this + : this.__ownerID ? ((this.size = 0), (this._head = void 0), (this.__hash = void 0), (this.__altered = !0), this) + : emptyStack() + ); + }), + (Stack.prototype.slice = function (i, s) { + if (wholeSlice(i, s, this.size)) return this; + var u = resolveBegin(i, this.size); + if (resolveEnd(s, this.size) !== this.size) return IndexedCollection.prototype.slice.call(this, i, s); + for (var m = this.size - u, v = this._head; u--; ) v = v.next; + return this.__ownerID ? ((this.size = m), (this._head = v), (this.__hash = void 0), (this.__altered = !0), this) : makeStack(m, v); + }), + (Stack.prototype.__ensureOwner = function (i) { + return ( + i === this.__ownerID ? this + : i ? makeStack(this.size, this._head, i, this.__hash) + : ((this.__ownerID = i), (this.__altered = !1), this) + ); + }), + (Stack.prototype.__iterate = function (i, s) { + if (s) return this.reverse().__iterate(i); + for (var u = 0, m = this._head; m && !1 !== i(m.value, u++, this); ) m = m.next; + return u; + }), + (Stack.prototype.__iterator = function (i, s) { + if (s) return this.reverse().__iterator(i); + var u = 0, + m = this._head; + return new Iterator(function () { + if (m) { + var s = m.value; + return (m = m.next), iteratorValue(i, u++, s); + } + return iteratorDone(); + }); + }), + (Stack.isStack = isStack); + var pt, + ht = '@@__IMMUTABLE_STACK__@@', + dt = Stack.prototype; + function makeStack(i, s, u, m) { + var v = Object.create(dt); + return (v.size = i), (v._head = s), (v.__ownerID = u), (v.__hash = m), (v.__altered = !1), v; + } + function emptyStack() { + return pt || (pt = makeStack(0)); + } + function mixin(i, s) { + var keyCopier = function (u) { + i.prototype[u] = s[u]; + }; + return Object.keys(s).forEach(keyCopier), Object.getOwnPropertySymbols && Object.getOwnPropertySymbols(s).forEach(keyCopier), i; + } + (dt[ht] = !0), + (dt.withMutations = He.withMutations), + (dt.asMutable = He.asMutable), + (dt.asImmutable = He.asImmutable), + (dt.wasAltered = He.wasAltered), + (Iterable.Iterator = Iterator), + mixin(Iterable, { + toArray: function () { + assertNotInfinite(this.size); + var i = new Array(this.size || 0); + return ( + this.valueSeq().__iterate(function (s, u) { + i[u] = s; + }), + i + ); + }, + toIndexedSeq: function () { + return new ToIndexedSequence(this); + }, + toJS: function () { + return this.toSeq() + .map(function (i) { + return i && 'function' == typeof i.toJS ? i.toJS() : i; + }) + .__toJS(); + }, + toJSON: function () { + return this.toSeq() + .map(function (i) { + return i && 'function' == typeof i.toJSON ? i.toJSON() : i; + }) + .__toJS(); + }, + toKeyedSeq: function () { + return new ToKeyedSequence(this, !0); + }, + toMap: function () { + return Map(this.toKeyedSeq()); + }, + toObject: function () { + assertNotInfinite(this.size); + var i = {}; + return ( + this.__iterate(function (s, u) { + i[u] = s; + }), + i + ); + }, + toOrderedMap: function () { + return OrderedMap(this.toKeyedSeq()); + }, + toOrderedSet: function () { + return OrderedSet(isKeyed(this) ? this.valueSeq() : this); + }, + toSet: function () { + return Set(isKeyed(this) ? this.valueSeq() : this); + }, + toSetSeq: function () { + return new ToSetSequence(this); + }, + toSeq: function () { + return ( + isIndexed(this) ? this.toIndexedSeq() + : isKeyed(this) ? this.toKeyedSeq() + : this.toSetSeq() + ); + }, + toStack: function () { + return Stack(isKeyed(this) ? this.valueSeq() : this); + }, + toList: function () { + return List(isKeyed(this) ? this.valueSeq() : this); + }, + toString: function () { + return '[Iterable]'; + }, + __toString: function (i, s) { + return 0 === this.size ? i + s : i + ' ' + this.toSeq().map(this.__toStringMapper).join(', ') + ' ' + s; + }, + concat: function () { + return reify(this, concatFactory(this, i.call(arguments, 0))); + }, + includes: function (i) { + return this.some(function (s) { + return is(s, i); + }); + }, + entries: function () { + return this.__iterator(ae); + }, + every: function (i, s) { + assertNotInfinite(this.size); + var u = !0; + return ( + this.__iterate(function (m, v, _) { + if (!i.call(s, m, v, _)) return (u = !1), !1; + }), + u + ); + }, + filter: function (i, s) { + return reify(this, filterFactory(this, i, s, !0)); + }, + find: function (i, s, u) { + var m = this.findEntry(i, s); + return m ? m[1] : u; + }, + forEach: function (i, s) { + return assertNotInfinite(this.size), this.__iterate(s ? i.bind(s) : i); + }, + join: function (i) { + assertNotInfinite(this.size), (i = void 0 !== i ? '' + i : ','); + var s = '', + u = !0; + return ( + this.__iterate(function (m) { + u ? (u = !1) : (s += i), (s += null != m ? m.toString() : ''); + }), + s + ); + }, + keys: function () { + return this.__iterator(Z); + }, + map: function (i, s) { + return reify(this, mapFactory(this, i, s)); + }, + reduce: function (i, s, u) { + var m, v; + return ( + assertNotInfinite(this.size), + arguments.length < 2 ? (v = !0) : (m = s), + this.__iterate(function (s, _, j) { + v ? ((v = !1), (m = s)) : (m = i.call(u, m, s, _, j)); + }), + m + ); + }, + reduceRight: function (i, s, u) { + var m = this.toKeyedSeq().reverse(); + return m.reduce.apply(m, arguments); + }, + reverse: function () { + return reify(this, reverseFactory(this, !0)); + }, + slice: function (i, s) { + return reify(this, sliceFactory(this, i, s, !0)); + }, + some: function (i, s) { + return !this.every(not(i), s); + }, + sort: function (i) { + return reify(this, sortFactory(this, i)); + }, + values: function () { + return this.__iterator(ee); + }, + butLast: function () { + return this.slice(0, -1); + }, + isEmpty: function () { + return void 0 !== this.size ? + 0 === this.size + : !this.some(function () { + return !0; + }); + }, + count: function (i, s) { + return ensureSize(i ? this.toSeq().filter(i, s) : this); + }, + countBy: function (i, s) { + return countByFactory(this, i, s); + }, + equals: function (i) { + return deepEqual(this, i); + }, + entrySeq: function () { + var i = this; + if (i._cache) return new ArraySeq(i._cache); + var s = i.toSeq().map(entryMapper).toIndexedSeq(); + return ( + (s.fromEntrySeq = function () { + return i.toSeq(); + }), + s + ); + }, + filterNot: function (i, s) { + return this.filter(not(i), s); + }, + findEntry: function (i, s, u) { + var m = u; + return ( + this.__iterate(function (u, v, _) { + if (i.call(s, u, v, _)) return (m = [v, u]), !1; + }), + m + ); + }, + findKey: function (i, s) { + var u = this.findEntry(i, s); + return u && u[0]; + }, + findLast: function (i, s, u) { + return this.toKeyedSeq().reverse().find(i, s, u); + }, + findLastEntry: function (i, s, u) { + return this.toKeyedSeq().reverse().findEntry(i, s, u); + }, + findLastKey: function (i, s) { + return this.toKeyedSeq().reverse().findKey(i, s); + }, + first: function () { + return this.find(returnTrue); + }, + flatMap: function (i, s) { + return reify(this, flatMapFactory(this, i, s)); + }, + flatten: function (i) { + return reify(this, flattenFactory(this, i, !0)); + }, + fromEntrySeq: function () { + return new FromEntriesSequence(this); + }, + get: function (i, s) { + return this.find( + function (s, u) { + return is(u, i); + }, + void 0, + s + ); + }, + getIn: function (i, s) { + for (var u, m = this, v = forceIterator(i); !(u = v.next()).done; ) { + var _ = u.value; + if ((m = m && m.get ? m.get(_, W) : W) === W) return s; + } + return m; + }, + groupBy: function (i, s) { + return groupByFactory(this, i, s); + }, + has: function (i) { + return this.get(i, W) !== W; + }, + hasIn: function (i) { + return this.getIn(i, W) !== W; + }, + isSubset: function (i) { + return ( + (i = 'function' == typeof i.includes ? i : Iterable(i)), + this.every(function (s) { + return i.includes(s); + }) + ); + }, + isSuperset: function (i) { + return (i = 'function' == typeof i.isSubset ? i : Iterable(i)).isSubset(this); + }, + keyOf: function (i) { + return this.findKey(function (s) { + return is(s, i); + }); + }, + keySeq: function () { + return this.toSeq().map(keyMapper).toIndexedSeq(); + }, + last: function () { + return this.toSeq().reverse().first(); + }, + lastKeyOf: function (i) { + return this.toKeyedSeq().reverse().keyOf(i); + }, + max: function (i) { + return maxFactory(this, i); + }, + maxBy: function (i, s) { + return maxFactory(this, s, i); + }, + min: function (i) { + return maxFactory(this, i ? neg(i) : defaultNegComparator); + }, + minBy: function (i, s) { + return maxFactory(this, s ? neg(s) : defaultNegComparator, i); + }, + rest: function () { + return this.slice(1); + }, + skip: function (i) { + return this.slice(Math.max(0, i)); + }, + skipLast: function (i) { + return reify(this, this.toSeq().reverse().skip(i).reverse()); + }, + skipWhile: function (i, s) { + return reify(this, skipWhileFactory(this, i, s, !0)); + }, + skipUntil: function (i, s) { + return this.skipWhile(not(i), s); + }, + sortBy: function (i, s) { + return reify(this, sortFactory(this, s, i)); + }, + take: function (i) { + return this.slice(0, Math.max(0, i)); + }, + takeLast: function (i) { + return reify(this, this.toSeq().reverse().take(i).reverse()); + }, + takeWhile: function (i, s) { + return reify(this, takeWhileFactory(this, i, s)); + }, + takeUntil: function (i, s) { + return this.takeWhile(not(i), s); + }, + valueSeq: function () { + return this.toIndexedSeq(); + }, + hashCode: function () { + return this.__hash || (this.__hash = hashIterable(this)); + } + }); + var mt = Iterable.prototype; + (mt[s] = !0), + (mt[ce] = mt.values), + (mt.__toJS = mt.toArray), + (mt.__toStringMapper = quoteString), + (mt.inspect = mt.toSource = + function () { + return this.toString(); + }), + (mt.chain = mt.flatMap), + (mt.contains = mt.includes), + mixin(KeyedIterable, { + flip: function () { + return reify(this, flipFactory(this)); + }, + mapEntries: function (i, s) { + var u = this, + m = 0; + return reify( + this, + this.toSeq() + .map(function (v, _) { + return i.call(s, [_, v], m++, u); + }) + .fromEntrySeq() + ); + }, + mapKeys: function (i, s) { + var u = this; + return reify( + this, + this.toSeq() + .flip() + .map(function (m, v) { + return i.call(s, m, v, u); + }) + .flip() + ); + } + }); + var gt = KeyedIterable.prototype; + function keyMapper(i, s) { + return s; + } + function entryMapper(i, s) { + return [s, i]; + } + function not(i) { + return function () { + return !i.apply(this, arguments); + }; + } + function neg(i) { + return function () { + return -i.apply(this, arguments); + }; + } + function quoteString(i) { + return 'string' == typeof i ? JSON.stringify(i) : String(i); + } + function defaultZipper() { + return arrCopy(arguments); + } + function defaultNegComparator(i, s) { + return ( + i < s ? 1 + : i > s ? -1 + : 0 + ); + } + function hashIterable(i) { + if (i.size === 1 / 0) return 0; + var s = isOrdered(i), + u = isKeyed(i), + m = s ? 1 : 0; + return murmurHashOfSize( + i.__iterate( + u ? + s ? + function (i, s) { + m = (31 * m + hashMerge(hash(i), hash(s))) | 0; + } + : function (i, s) { + m = (m + hashMerge(hash(i), hash(s))) | 0; + } + : s ? + function (i) { + m = (31 * m + hash(i)) | 0; + } + : function (i) { + m = (m + hash(i)) | 0; + } + ), + m + ); + } + function murmurHashOfSize(i, s) { + return (s = be(s, 3432918353)), (s = be((s << 15) | (s >>> -15), 461845907)), (s = be((s << 13) | (s >>> -13), 5)), (s = be((s = ((s + 3864292196) | 0) ^ i) ^ (s >>> 16), 2246822507)), (s = smi((s = be(s ^ (s >>> 13), 3266489909)) ^ (s >>> 16))); + } + function hashMerge(i, s) { + return (i ^ (s + 2654435769 + (i << 6) + (i >> 2))) | 0; + } + return ( + (gt[u] = !0), + (gt[ce] = mt.entries), + (gt.__toJS = mt.toObject), + (gt.__toStringMapper = function (i, s) { + return JSON.stringify(s) + ': ' + quoteString(i); + }), + mixin(IndexedIterable, { + toKeyedSeq: function () { + return new ToKeyedSequence(this, !1); + }, + filter: function (i, s) { + return reify(this, filterFactory(this, i, s, !1)); + }, + findIndex: function (i, s) { + var u = this.findEntry(i, s); + return u ? u[0] : -1; + }, + indexOf: function (i) { + var s = this.keyOf(i); + return void 0 === s ? -1 : s; + }, + lastIndexOf: function (i) { + var s = this.lastKeyOf(i); + return void 0 === s ? -1 : s; + }, + reverse: function () { + return reify(this, reverseFactory(this, !1)); + }, + slice: function (i, s) { + return reify(this, sliceFactory(this, i, s, !1)); + }, + splice: function (i, s) { + var u = arguments.length; + if (((s = Math.max(0 | s, 0)), 0 === u || (2 === u && !s))) return this; + i = resolveBegin(i, i < 0 ? this.count() : this.size); + var m = this.slice(0, i); + return reify(this, 1 === u ? m : m.concat(arrCopy(arguments, 2), this.slice(i + s))); + }, + findLastIndex: function (i, s) { + var u = this.findLastEntry(i, s); + return u ? u[0] : -1; + }, + first: function () { + return this.get(0); + }, + flatten: function (i) { + return reify(this, flattenFactory(this, i, !1)); + }, + get: function (i, s) { + return (i = wrapIndex(this, i)) < 0 || this.size === 1 / 0 || (void 0 !== this.size && i > this.size) ? + s + : this.find( + function (s, u) { + return u === i; + }, + void 0, + s + ); + }, + has: function (i) { + return (i = wrapIndex(this, i)) >= 0 && (void 0 !== this.size ? this.size === 1 / 0 || i < this.size : -1 !== this.indexOf(i)); + }, + interpose: function (i) { + return reify(this, interposeFactory(this, i)); + }, + interleave: function () { + var i = [this].concat(arrCopy(arguments)), + s = zipWithFactory(this.toSeq(), IndexedSeq.of, i), + u = s.flatten(!0); + return s.size && (u.size = s.size * i.length), reify(this, u); + }, + keySeq: function () { + return Range(0, this.size); + }, + last: function () { + return this.get(-1); + }, + skipWhile: function (i, s) { + return reify(this, skipWhileFactory(this, i, s, !1)); + }, + zip: function () { + return reify(this, zipWithFactory(this, defaultZipper, [this].concat(arrCopy(arguments)))); + }, + zipWith: function (i) { + var s = arrCopy(arguments); + return (s[0] = this), reify(this, zipWithFactory(this, i, s)); + } + }), + (IndexedIterable.prototype[m] = !0), + (IndexedIterable.prototype[v] = !0), + mixin(SetIterable, { + get: function (i, s) { + return this.has(i) ? i : s; + }, + includes: function (i) { + return this.has(i); + }, + keySeq: function () { + return this.valueSeq(); + } + }), + (SetIterable.prototype.has = mt.includes), + (SetIterable.prototype.contains = SetIterable.prototype.includes), + mixin(KeyedSeq, KeyedIterable.prototype), + mixin(IndexedSeq, IndexedIterable.prototype), + mixin(SetSeq, SetIterable.prototype), + mixin(KeyedCollection, KeyedIterable.prototype), + mixin(IndexedCollection, IndexedIterable.prototype), + mixin(SetCollection, SetIterable.prototype), + { Iterable, Seq, Collection, Map, OrderedMap, List, Stack, Set, OrderedSet, Record, Range, Repeat, is, fromJS } + ); + })(); + }, + 35717: (i) => { + 'function' == typeof Object.create ? + (i.exports = function inherits(i, s) { + s && ((i.super_ = s), (i.prototype = Object.create(s.prototype, { constructor: { value: i, enumerable: !1, writable: !0, configurable: !0 } }))); + }) + : (i.exports = function inherits(i, s) { + if (s) { + i.super_ = s; + var TempCtor = function () {}; + (TempCtor.prototype = s.prototype), (i.prototype = new TempCtor()), (i.prototype.constructor = i); + } + }); + }, + 35823: (i) => { + i.exports = function (i, s, u, m) { + var v = new Blob(void 0 !== m ? [m, i] : [i], { type: u || 'application/octet-stream' }); + if (void 0 !== window.navigator.msSaveBlob) window.navigator.msSaveBlob(v, s); + else { + var _ = window.URL && window.URL.createObjectURL ? window.URL.createObjectURL(v) : window.webkitURL.createObjectURL(v), + j = document.createElement('a'); + (j.style.display = 'none'), + (j.href = _), + j.setAttribute('download', s), + void 0 === j.download && j.setAttribute('target', '_blank'), + document.body.appendChild(j), + j.click(), + setTimeout(function () { + document.body.removeChild(j), window.URL.revokeObjectURL(_); + }, 200); + } + }; + }, + 91296: (i, s, u) => { + var m = NaN, + v = '[object Symbol]', + _ = /^\s+|\s+$/g, + j = /^[-+]0x[0-9a-f]+$/i, + M = /^0b[01]+$/i, + $ = /^0o[0-7]+$/i, + W = parseInt, + X = 'object' == typeof u.g && u.g && u.g.Object === Object && u.g, + Y = 'object' == typeof self && self && self.Object === Object && self, + Z = X || Y || Function('return this')(), + ee = Object.prototype.toString, + ae = Math.max, + ie = Math.min, + now = function () { + return Z.Date.now(); + }; + function isObject(i) { + var s = typeof i; + return !!i && ('object' == s || 'function' == s); + } + function toNumber(i) { + if ('number' == typeof i) return i; + if ( + (function isSymbol(i) { + return ( + 'symbol' == typeof i || + ((function isObjectLike(i) { + return !!i && 'object' == typeof i; + })(i) && + ee.call(i) == v) + ); + })(i) + ) + return m; + if (isObject(i)) { + var s = 'function' == typeof i.valueOf ? i.valueOf() : i; + i = isObject(s) ? s + '' : s; + } + if ('string' != typeof i) return 0 === i ? i : +i; + i = i.replace(_, ''); + var u = M.test(i); + return ( + u || $.test(i) ? W(i.slice(2), u ? 2 : 8) + : j.test(i) ? m + : +i + ); + } + i.exports = function debounce(i, s, u) { + var m, + v, + _, + j, + M, + $, + W = 0, + X = !1, + Y = !1, + Z = !0; + if ('function' != typeof i) throw new TypeError('Expected a function'); + function invokeFunc(s) { + var u = m, + _ = v; + return (m = v = void 0), (W = s), (j = i.apply(_, u)); + } + function shouldInvoke(i) { + var u = i - $; + return void 0 === $ || u >= s || u < 0 || (Y && i - W >= _); + } + function timerExpired() { + var i = now(); + if (shouldInvoke(i)) return trailingEdge(i); + M = setTimeout( + timerExpired, + (function remainingWait(i) { + var u = s - (i - $); + return Y ? ie(u, _ - (i - W)) : u; + })(i) + ); + } + function trailingEdge(i) { + return (M = void 0), Z && m ? invokeFunc(i) : ((m = v = void 0), j); + } + function debounced() { + var i = now(), + u = shouldInvoke(i); + if (((m = arguments), (v = this), ($ = i), u)) { + if (void 0 === M) + return (function leadingEdge(i) { + return (W = i), (M = setTimeout(timerExpired, s)), X ? invokeFunc(i) : j; + })($); + if (Y) return (M = setTimeout(timerExpired, s)), invokeFunc($); + } + return void 0 === M && (M = setTimeout(timerExpired, s)), j; + } + return ( + (s = toNumber(s) || 0), + isObject(u) && ((X = !!u.leading), (_ = (Y = 'maxWait' in u) ? ae(toNumber(u.maxWait) || 0, s) : _), (Z = 'trailing' in u ? !!u.trailing : Z)), + (debounced.cancel = function cancel() { + void 0 !== M && clearTimeout(M), (W = 0), (m = $ = v = M = void 0); + }), + (debounced.flush = function flush() { + return void 0 === M ? j : trailingEdge(now()); + }), + debounced + ); + }; + }, + 18552: (i, s, u) => { + var m = u(10852)(u(55639), 'DataView'); + i.exports = m; + }, + 1989: (i, s, u) => { + var m = u(51789), + v = u(80401), + _ = u(57667), + j = u(21327), + M = u(81866); + function Hash(i) { + var s = -1, + u = null == i ? 0 : i.length; + for (this.clear(); ++s < u; ) { + var m = i[s]; + this.set(m[0], m[1]); + } + } + (Hash.prototype.clear = m), (Hash.prototype.delete = v), (Hash.prototype.get = _), (Hash.prototype.has = j), (Hash.prototype.set = M), (i.exports = Hash); + }, + 96425: (i, s, u) => { + var m = u(3118), + v = u(9435); + function LazyWrapper(i) { + (this.__wrapped__ = i), (this.__actions__ = []), (this.__dir__ = 1), (this.__filtered__ = !1), (this.__iteratees__ = []), (this.__takeCount__ = 4294967295), (this.__views__ = []); + } + (LazyWrapper.prototype = m(v.prototype)), (LazyWrapper.prototype.constructor = LazyWrapper), (i.exports = LazyWrapper); + }, + 38407: (i, s, u) => { + var m = u(27040), + v = u(14125), + _ = u(82117), + j = u(67518), + M = u(54705); + function ListCache(i) { + var s = -1, + u = null == i ? 0 : i.length; + for (this.clear(); ++s < u; ) { + var m = i[s]; + this.set(m[0], m[1]); + } + } + (ListCache.prototype.clear = m), (ListCache.prototype.delete = v), (ListCache.prototype.get = _), (ListCache.prototype.has = j), (ListCache.prototype.set = M), (i.exports = ListCache); + }, + 7548: (i, s, u) => { + var m = u(3118), + v = u(9435); + function LodashWrapper(i, s) { + (this.__wrapped__ = i), (this.__actions__ = []), (this.__chain__ = !!s), (this.__index__ = 0), (this.__values__ = void 0); + } + (LodashWrapper.prototype = m(v.prototype)), (LodashWrapper.prototype.constructor = LodashWrapper), (i.exports = LodashWrapper); + }, + 57071: (i, s, u) => { + var m = u(10852)(u(55639), 'Map'); + i.exports = m; + }, + 83369: (i, s, u) => { + var m = u(24785), + v = u(11285), + _ = u(96e3), + j = u(49916), + M = u(95265); + function MapCache(i) { + var s = -1, + u = null == i ? 0 : i.length; + for (this.clear(); ++s < u; ) { + var m = i[s]; + this.set(m[0], m[1]); + } + } + (MapCache.prototype.clear = m), (MapCache.prototype.delete = v), (MapCache.prototype.get = _), (MapCache.prototype.has = j), (MapCache.prototype.set = M), (i.exports = MapCache); + }, + 53818: (i, s, u) => { + var m = u(10852)(u(55639), 'Promise'); + i.exports = m; + }, + 58525: (i, s, u) => { + var m = u(10852)(u(55639), 'Set'); + i.exports = m; + }, + 88668: (i, s, u) => { + var m = u(83369), + v = u(90619), + _ = u(72385); + function SetCache(i) { + var s = -1, + u = null == i ? 0 : i.length; + for (this.__data__ = new m(); ++s < u; ) this.add(i[s]); + } + (SetCache.prototype.add = SetCache.prototype.push = v), (SetCache.prototype.has = _), (i.exports = SetCache); + }, + 46384: (i, s, u) => { + var m = u(38407), + v = u(37465), + _ = u(63779), + j = u(67599), + M = u(44758), + $ = u(34309); + function Stack(i) { + var s = (this.__data__ = new m(i)); + this.size = s.size; + } + (Stack.prototype.clear = v), (Stack.prototype.delete = _), (Stack.prototype.get = j), (Stack.prototype.has = M), (Stack.prototype.set = $), (i.exports = Stack); + }, + 62705: (i, s, u) => { + var m = u(55639).Symbol; + i.exports = m; + }, + 11149: (i, s, u) => { + var m = u(55639).Uint8Array; + i.exports = m; + }, + 70577: (i, s, u) => { + var m = u(10852)(u(55639), 'WeakMap'); + i.exports = m; + }, + 96874: (i) => { + i.exports = function apply(i, s, u) { + switch (u.length) { + case 0: + return i.call(s); + case 1: + return i.call(s, u[0]); + case 2: + return i.call(s, u[0], u[1]); + case 3: + return i.call(s, u[0], u[1], u[2]); + } + return i.apply(s, u); + }; + }, + 77412: (i) => { + i.exports = function arrayEach(i, s) { + for (var u = -1, m = null == i ? 0 : i.length; ++u < m && !1 !== s(i[u], u, i); ); + return i; + }; + }, + 34963: (i) => { + i.exports = function arrayFilter(i, s) { + for (var u = -1, m = null == i ? 0 : i.length, v = 0, _ = []; ++u < m; ) { + var j = i[u]; + s(j, u, i) && (_[v++] = j); + } + return _; + }; + }, + 47443: (i, s, u) => { + var m = u(42118); + i.exports = function arrayIncludes(i, s) { + return !!(null == i ? 0 : i.length) && m(i, s, 0) > -1; + }; + }, + 14636: (i, s, u) => { + var m = u(22545), + v = u(35694), + _ = u(1469), + j = u(44144), + M = u(65776), + $ = u(36719), + W = Object.prototype.hasOwnProperty; + i.exports = function arrayLikeKeys(i, s) { + var u = _(i), + X = !u && v(i), + Y = !u && !X && j(i), + Z = !u && !X && !Y && $(i), + ee = u || X || Y || Z, + ae = ee ? m(i.length, String) : [], + ie = ae.length; + for (var le in i) (!s && !W.call(i, le)) || (ee && ('length' == le || (Y && ('offset' == le || 'parent' == le)) || (Z && ('buffer' == le || 'byteLength' == le || 'byteOffset' == le)) || M(le, ie))) || ae.push(le); + return ae; + }; + }, + 29932: (i) => { + i.exports = function arrayMap(i, s) { + for (var u = -1, m = null == i ? 0 : i.length, v = Array(m); ++u < m; ) v[u] = s(i[u], u, i); + return v; + }; + }, + 62488: (i) => { + i.exports = function arrayPush(i, s) { + for (var u = -1, m = s.length, v = i.length; ++u < m; ) i[v + u] = s[u]; + return i; + }; + }, + 62663: (i) => { + i.exports = function arrayReduce(i, s, u, m) { + var v = -1, + _ = null == i ? 0 : i.length; + for (m && _ && (u = i[++v]); ++v < _; ) u = s(u, i[v], v, i); + return u; + }; + }, + 82908: (i) => { + i.exports = function arraySome(i, s) { + for (var u = -1, m = null == i ? 0 : i.length; ++u < m; ) if (s(i[u], u, i)) return !0; + return !1; + }; + }, + 44286: (i) => { + i.exports = function asciiToArray(i) { + return i.split(''); + }; + }, + 49029: (i) => { + var s = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + i.exports = function asciiWords(i) { + return i.match(s) || []; + }; + }, + 86556: (i, s, u) => { + var m = u(89465), + v = u(77813); + i.exports = function assignMergeValue(i, s, u) { + ((void 0 !== u && !v(i[s], u)) || (void 0 === u && !(s in i))) && m(i, s, u); + }; + }, + 34865: (i, s, u) => { + var m = u(89465), + v = u(77813), + _ = Object.prototype.hasOwnProperty; + i.exports = function assignValue(i, s, u) { + var j = i[s]; + (_.call(i, s) && v(j, u) && (void 0 !== u || s in i)) || m(i, s, u); + }; + }, + 18470: (i, s, u) => { + var m = u(77813); + i.exports = function assocIndexOf(i, s) { + for (var u = i.length; u--; ) if (m(i[u][0], s)) return u; + return -1; + }; + }, + 44037: (i, s, u) => { + var m = u(98363), + v = u(3674); + i.exports = function baseAssign(i, s) { + return i && m(s, v(s), i); + }; + }, + 63886: (i, s, u) => { + var m = u(98363), + v = u(81704); + i.exports = function baseAssignIn(i, s) { + return i && m(s, v(s), i); + }; + }, + 89465: (i, s, u) => { + var m = u(38777); + i.exports = function baseAssignValue(i, s, u) { + '__proto__' == s && m ? m(i, s, { configurable: !0, enumerable: !0, value: u, writable: !0 }) : (i[s] = u); + }; + }, + 85990: (i, s, u) => { + var m = u(46384), + v = u(77412), + _ = u(34865), + j = u(44037), + M = u(63886), + $ = u(64626), + W = u(278), + X = u(18805), + Y = u(1911), + Z = u(58234), + ee = u(46904), + ae = u(64160), + ie = u(43824), + le = u(29148), + ce = u(38517), + pe = u(1469), + de = u(44144), + fe = u(56688), + ye = u(13218), + be = u(72928), + _e = u(3674), + we = u(81704), + Se = '[object Arguments]', + xe = '[object Function]', + Pe = '[object Object]', + Ie = {}; + (Ie[Se] = Ie['[object Array]'] = Ie['[object ArrayBuffer]'] = Ie['[object DataView]'] = Ie['[object Boolean]'] = Ie['[object Date]'] = Ie['[object Float32Array]'] = Ie['[object Float64Array]'] = Ie['[object Int8Array]'] = Ie['[object Int16Array]'] = Ie['[object Int32Array]'] = Ie['[object Map]'] = Ie['[object Number]'] = Ie[Pe] = Ie['[object RegExp]'] = Ie['[object Set]'] = Ie['[object String]'] = Ie['[object Symbol]'] = Ie['[object Uint8Array]'] = Ie['[object Uint8ClampedArray]'] = Ie['[object Uint16Array]'] = Ie['[object Uint32Array]'] = !0), + (Ie['[object Error]'] = Ie[xe] = Ie['[object WeakMap]'] = !1), + (i.exports = function baseClone(i, s, u, Te, Re, qe) { + var ze, + Ve = 1 & s, + We = 2 & s, + He = 4 & s; + if ((u && (ze = Re ? u(i, Te, Re, qe) : u(i)), void 0 !== ze)) return ze; + if (!ye(i)) return i; + var Xe = pe(i); + if (Xe) { + if (((ze = ie(i)), !Ve)) return W(i, ze); + } else { + var Ye = ae(i), + Qe = Ye == xe || '[object GeneratorFunction]' == Ye; + if (de(i)) return $(i, Ve); + if (Ye == Pe || Ye == Se || (Qe && !Re)) { + if (((ze = We || Qe ? {} : ce(i)), !Ve)) return We ? Y(i, M(ze, i)) : X(i, j(ze, i)); + } else { + if (!Ie[Ye]) return Re ? i : {}; + ze = le(i, Ye, Ve); + } + } + qe || (qe = new m()); + var et = qe.get(i); + if (et) return et; + qe.set(i, ze), + be(i) ? + i.forEach(function (m) { + ze.add(baseClone(m, s, u, m, i, qe)); + }) + : fe(i) && + i.forEach(function (m, v) { + ze.set(v, baseClone(m, s, u, v, i, qe)); + }); + var tt = + Xe ? void 0 : ( + (He ? + We ? ee + : Z + : We ? we + : _e)(i) + ); + return ( + v(tt || i, function (m, v) { + tt && (m = i[(v = m)]), _(ze, v, baseClone(m, s, u, v, i, qe)); + }), + ze + ); + }); + }, + 3118: (i, s, u) => { + var m = u(13218), + v = Object.create, + _ = (function () { + function object() {} + return function (i) { + if (!m(i)) return {}; + if (v) return v(i); + object.prototype = i; + var s = new object(); + return (object.prototype = void 0), s; + }; + })(); + i.exports = _; + }, + 89881: (i, s, u) => { + var m = u(47816), + v = u(99291)(m); + i.exports = v; + }, + 41848: (i) => { + i.exports = function baseFindIndex(i, s, u, m) { + for (var v = i.length, _ = u + (m ? 1 : -1); m ? _-- : ++_ < v; ) if (s(i[_], _, i)) return _; + return -1; + }; + }, + 21078: (i, s, u) => { + var m = u(62488), + v = u(37285); + i.exports = function baseFlatten(i, s, u, _, j) { + var M = -1, + $ = i.length; + for (u || (u = v), j || (j = []); ++M < $; ) { + var W = i[M]; + s > 0 && u(W) ? + s > 1 ? + baseFlatten(W, s - 1, u, _, j) + : m(j, W) + : _ || (j[j.length] = W); + } + return j; + }; + }, + 28483: (i, s, u) => { + var m = u(25063)(); + i.exports = m; + }, + 47816: (i, s, u) => { + var m = u(28483), + v = u(3674); + i.exports = function baseForOwn(i, s) { + return i && m(i, s, v); + }; + }, + 97786: (i, s, u) => { + var m = u(71811), + v = u(40327); + i.exports = function baseGet(i, s) { + for (var u = 0, _ = (s = m(s, i)).length; null != i && u < _; ) i = i[v(s[u++])]; + return u && u == _ ? i : void 0; + }; + }, + 68866: (i, s, u) => { + var m = u(62488), + v = u(1469); + i.exports = function baseGetAllKeys(i, s, u) { + var _ = s(i); + return v(i) ? _ : m(_, u(i)); + }; + }, + 44239: (i, s, u) => { + var m = u(62705), + v = u(89607), + _ = u(2333), + j = m ? m.toStringTag : void 0; + i.exports = function baseGetTag(i) { + return ( + null == i ? + void 0 === i ? + '[object Undefined]' + : '[object Null]' + : j && j in Object(i) ? v(i) + : _(i) + ); + }; + }, + 13: (i) => { + i.exports = function baseHasIn(i, s) { + return null != i && s in Object(i); + }; + }, + 42118: (i, s, u) => { + var m = u(41848), + v = u(62722), + _ = u(42351); + i.exports = function baseIndexOf(i, s, u) { + return s == s ? _(i, s, u) : m(i, v, u); + }; + }, + 9454: (i, s, u) => { + var m = u(44239), + v = u(37005); + i.exports = function baseIsArguments(i) { + return v(i) && '[object Arguments]' == m(i); + }; + }, + 90939: (i, s, u) => { + var m = u(2492), + v = u(37005); + i.exports = function baseIsEqual(i, s, u, _, j) { + return i === s || (null == i || null == s || (!v(i) && !v(s)) ? i != i && s != s : m(i, s, u, _, baseIsEqual, j)); + }; + }, + 2492: (i, s, u) => { + var m = u(46384), + v = u(67114), + _ = u(18351), + j = u(16096), + M = u(64160), + $ = u(1469), + W = u(44144), + X = u(36719), + Y = '[object Arguments]', + Z = '[object Array]', + ee = '[object Object]', + ae = Object.prototype.hasOwnProperty; + i.exports = function baseIsEqualDeep(i, s, u, ie, le, ce) { + var pe = $(i), + de = $(s), + fe = pe ? Z : M(i), + ye = de ? Z : M(s), + be = (fe = fe == Y ? ee : fe) == ee, + _e = (ye = ye == Y ? ee : ye) == ee, + we = fe == ye; + if (we && W(i)) { + if (!W(s)) return !1; + (pe = !0), (be = !1); + } + if (we && !be) return ce || (ce = new m()), pe || X(i) ? v(i, s, u, ie, le, ce) : _(i, s, fe, u, ie, le, ce); + if (!(1 & u)) { + var Se = be && ae.call(i, '__wrapped__'), + xe = _e && ae.call(s, '__wrapped__'); + if (Se || xe) { + var Pe = Se ? i.value() : i, + Ie = xe ? s.value() : s; + return ce || (ce = new m()), le(Pe, Ie, u, ie, ce); + } + } + return !!we && (ce || (ce = new m()), j(i, s, u, ie, le, ce)); + }; + }, + 25588: (i, s, u) => { + var m = u(64160), + v = u(37005); + i.exports = function baseIsMap(i) { + return v(i) && '[object Map]' == m(i); + }; + }, + 2958: (i, s, u) => { + var m = u(46384), + v = u(90939); + i.exports = function baseIsMatch(i, s, u, _) { + var j = u.length, + M = j, + $ = !_; + if (null == i) return !M; + for (i = Object(i); j--; ) { + var W = u[j]; + if ($ && W[2] ? W[1] !== i[W[0]] : !(W[0] in i)) return !1; + } + for (; ++j < M; ) { + var X = (W = u[j])[0], + Y = i[X], + Z = W[1]; + if ($ && W[2]) { + if (void 0 === Y && !(X in i)) return !1; + } else { + var ee = new m(); + if (_) var ae = _(Y, Z, X, i, s, ee); + if (!(void 0 === ae ? v(Z, Y, 3, _, ee) : ae)) return !1; + } + } + return !0; + }; + }, + 62722: (i) => { + i.exports = function baseIsNaN(i) { + return i != i; + }; + }, + 28458: (i, s, u) => { + var m = u(23560), + v = u(15346), + _ = u(13218), + j = u(80346), + M = /^\[object .+?Constructor\]$/, + $ = Function.prototype, + W = Object.prototype, + X = $.toString, + Y = W.hasOwnProperty, + Z = RegExp( + '^' + + X.call(Y) + .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + + '$' + ); + i.exports = function baseIsNative(i) { + return !(!_(i) || v(i)) && (m(i) ? Z : M).test(j(i)); + }; + }, + 29221: (i, s, u) => { + var m = u(64160), + v = u(37005); + i.exports = function baseIsSet(i) { + return v(i) && '[object Set]' == m(i); + }; + }, + 38749: (i, s, u) => { + var m = u(44239), + v = u(41780), + _ = u(37005), + j = {}; + (j['[object Float32Array]'] = j['[object Float64Array]'] = j['[object Int8Array]'] = j['[object Int16Array]'] = j['[object Int32Array]'] = j['[object Uint8Array]'] = j['[object Uint8ClampedArray]'] = j['[object Uint16Array]'] = j['[object Uint32Array]'] = !0), + (j['[object Arguments]'] = j['[object Array]'] = j['[object ArrayBuffer]'] = j['[object Boolean]'] = j['[object DataView]'] = j['[object Date]'] = j['[object Error]'] = j['[object Function]'] = j['[object Map]'] = j['[object Number]'] = j['[object Object]'] = j['[object RegExp]'] = j['[object Set]'] = j['[object String]'] = j['[object WeakMap]'] = !1), + (i.exports = function baseIsTypedArray(i) { + return _(i) && v(i.length) && !!j[m(i)]; + }); + }, + 67206: (i, s, u) => { + var m = u(91573), + v = u(16432), + _ = u(6557), + j = u(1469), + M = u(39601); + i.exports = function baseIteratee(i) { + return ( + 'function' == typeof i ? i + : null == i ? _ + : 'object' == typeof i ? + j(i) ? v(i[0], i[1]) + : m(i) + : M(i) + ); + }; + }, + 280: (i, s, u) => { + var m = u(25726), + v = u(86916), + _ = Object.prototype.hasOwnProperty; + i.exports = function baseKeys(i) { + if (!m(i)) return v(i); + var s = []; + for (var u in Object(i)) _.call(i, u) && 'constructor' != u && s.push(u); + return s; + }; + }, + 10313: (i, s, u) => { + var m = u(13218), + v = u(25726), + _ = u(33498), + j = Object.prototype.hasOwnProperty; + i.exports = function baseKeysIn(i) { + if (!m(i)) return _(i); + var s = v(i), + u = []; + for (var M in i) ('constructor' != M || (!s && j.call(i, M))) && u.push(M); + return u; + }; + }, + 9435: (i) => { + i.exports = function baseLodash() {}; + }, + 91573: (i, s, u) => { + var m = u(2958), + v = u(1499), + _ = u(42634); + i.exports = function baseMatches(i) { + var s = v(i); + return 1 == s.length && s[0][2] ? + _(s[0][0], s[0][1]) + : function (u) { + return u === i || m(u, i, s); + }; + }; + }, + 16432: (i, s, u) => { + var m = u(90939), + v = u(27361), + _ = u(79095), + j = u(15403), + M = u(89162), + $ = u(42634), + W = u(40327); + i.exports = function baseMatchesProperty(i, s) { + return j(i) && M(s) ? + $(W(i), s) + : function (u) { + var j = v(u, i); + return void 0 === j && j === s ? _(u, i) : m(s, j, 3); + }; + }; + }, + 42980: (i, s, u) => { + var m = u(46384), + v = u(86556), + _ = u(28483), + j = u(59783), + M = u(13218), + $ = u(81704), + W = u(36390); + i.exports = function baseMerge(i, s, u, X, Y) { + i !== s && + _( + s, + function (_, $) { + if ((Y || (Y = new m()), M(_))) j(i, s, $, u, baseMerge, X, Y); + else { + var Z = X ? X(W(i, $), _, $ + '', i, s, Y) : void 0; + void 0 === Z && (Z = _), v(i, $, Z); + } + }, + $ + ); + }; + }, + 59783: (i, s, u) => { + var m = u(86556), + v = u(64626), + _ = u(77133), + j = u(278), + M = u(38517), + $ = u(35694), + W = u(1469), + X = u(29246), + Y = u(44144), + Z = u(23560), + ee = u(13218), + ae = u(68630), + ie = u(36719), + le = u(36390), + ce = u(59881); + i.exports = function baseMergeDeep(i, s, u, pe, de, fe, ye) { + var be = le(i, u), + _e = le(s, u), + we = ye.get(_e); + if (we) m(i, u, we); + else { + var Se = fe ? fe(be, _e, u + '', i, s, ye) : void 0, + xe = void 0 === Se; + if (xe) { + var Pe = W(_e), + Ie = !Pe && Y(_e), + Te = !Pe && !Ie && ie(_e); + (Se = _e), + Pe || Ie || Te ? + W(be) ? (Se = be) + : X(be) ? (Se = j(be)) + : Ie ? ((xe = !1), (Se = v(_e, !0))) + : Te ? ((xe = !1), (Se = _(_e, !0))) + : (Se = []) + : ae(_e) || $(_e) ? ((Se = be), $(be) ? (Se = ce(be)) : (ee(be) && !Z(be)) || (Se = M(_e))) + : (xe = !1); + } + xe && (ye.set(_e, Se), de(Se, _e, pe, fe, ye), ye.delete(_e)), m(i, u, Se); + } + }; + }, + 40371: (i) => { + i.exports = function baseProperty(i) { + return function (s) { + return null == s ? void 0 : s[i]; + }; + }; + }, + 79152: (i, s, u) => { + var m = u(97786); + i.exports = function basePropertyDeep(i) { + return function (s) { + return m(s, i); + }; + }; + }, + 18674: (i) => { + i.exports = function basePropertyOf(i) { + return function (s) { + return null == i ? void 0 : i[s]; + }; + }; + }, + 10107: (i) => { + i.exports = function baseReduce(i, s, u, m, v) { + return ( + v(i, function (i, v, _) { + u = m ? ((m = !1), i) : s(u, i, v, _); + }), + u + ); + }; + }, + 5976: (i, s, u) => { + var m = u(6557), + v = u(45357), + _ = u(30061); + i.exports = function baseRest(i, s) { + return _(v(i, s, m), i + ''); + }; + }, + 10611: (i, s, u) => { + var m = u(34865), + v = u(71811), + _ = u(65776), + j = u(13218), + M = u(40327); + i.exports = function baseSet(i, s, u, $) { + if (!j(i)) return i; + for (var W = -1, X = (s = v(s, i)).length, Y = X - 1, Z = i; null != Z && ++W < X; ) { + var ee = M(s[W]), + ae = u; + if ('__proto__' === ee || 'constructor' === ee || 'prototype' === ee) return i; + if (W != Y) { + var ie = Z[ee]; + void 0 === (ae = $ ? $(ie, ee, Z) : void 0) && + (ae = + j(ie) ? ie + : _(s[W + 1]) ? [] + : {}); + } + m(Z, ee, ae), (Z = Z[ee]); + } + return i; + }; + }, + 28045: (i, s, u) => { + var m = u(6557), + v = u(89250), + _ = + v ? + function (i, s) { + return v.set(i, s), i; + } + : m; + i.exports = _; + }, + 56560: (i, s, u) => { + var m = u(75703), + v = u(38777), + _ = u(6557), + j = + v ? + function (i, s) { + return v(i, 'toString', { configurable: !0, enumerable: !1, value: m(s), writable: !0 }); + } + : _; + i.exports = j; + }, + 14259: (i) => { + i.exports = function baseSlice(i, s, u) { + var m = -1, + v = i.length; + s < 0 && (s = -s > v ? 0 : v + s), (u = u > v ? v : u) < 0 && (u += v), (v = s > u ? 0 : (u - s) >>> 0), (s >>>= 0); + for (var _ = Array(v); ++m < v; ) _[m] = i[m + s]; + return _; + }; + }, + 5076: (i, s, u) => { + var m = u(89881); + i.exports = function baseSome(i, s) { + var u; + return ( + m(i, function (i, m, v) { + return !(u = s(i, m, v)); + }), + !!u + ); + }; + }, + 22545: (i) => { + i.exports = function baseTimes(i, s) { + for (var u = -1, m = Array(i); ++u < i; ) m[u] = s(u); + return m; + }; + }, + 80531: (i, s, u) => { + var m = u(62705), + v = u(29932), + _ = u(1469), + j = u(33448), + M = m ? m.prototype : void 0, + $ = M ? M.toString : void 0; + i.exports = function baseToString(i) { + if ('string' == typeof i) return i; + if (_(i)) return v(i, baseToString) + ''; + if (j(i)) return $ ? $.call(i) : ''; + var s = i + ''; + return '0' == s && 1 / i == -Infinity ? '-0' : s; + }; + }, + 27561: (i, s, u) => { + var m = u(67990), + v = /^\s+/; + i.exports = function baseTrim(i) { + return i ? i.slice(0, m(i) + 1).replace(v, '') : i; + }; + }, + 7518: (i) => { + i.exports = function baseUnary(i) { + return function (s) { + return i(s); + }; + }; + }, + 57406: (i, s, u) => { + var m = u(71811), + v = u(10928), + _ = u(40292), + j = u(40327); + i.exports = function baseUnset(i, s) { + return (s = m(s, i)), null == (i = _(i, s)) || delete i[j(v(s))]; + }; + }, + 1757: (i) => { + i.exports = function baseZipObject(i, s, u) { + for (var m = -1, v = i.length, _ = s.length, j = {}; ++m < v; ) { + var M = m < _ ? s[m] : void 0; + u(j, i[m], M); + } + return j; + }; + }, + 74757: (i) => { + i.exports = function cacheHas(i, s) { + return i.has(s); + }; + }, + 71811: (i, s, u) => { + var m = u(1469), + v = u(15403), + _ = u(55514), + j = u(79833); + i.exports = function castPath(i, s) { + return ( + m(i) ? i + : v(i, s) ? [i] + : _(j(i)) + ); + }; + }, + 40180: (i, s, u) => { + var m = u(14259); + i.exports = function castSlice(i, s, u) { + var v = i.length; + return (u = void 0 === u ? v : u), !s && u >= v ? i : m(i, s, u); + }; + }, + 74318: (i, s, u) => { + var m = u(11149); + i.exports = function cloneArrayBuffer(i) { + var s = new i.constructor(i.byteLength); + return new m(s).set(new m(i)), s; + }; + }, + 64626: (i, s, u) => { + i = u.nmd(i); + var m = u(55639), + v = s && !s.nodeType && s, + _ = v && i && !i.nodeType && i, + j = _ && _.exports === v ? m.Buffer : void 0, + M = j ? j.allocUnsafe : void 0; + i.exports = function cloneBuffer(i, s) { + if (s) return i.slice(); + var u = i.length, + m = M ? M(u) : new i.constructor(u); + return i.copy(m), m; + }; + }, + 57157: (i, s, u) => { + var m = u(74318); + i.exports = function cloneDataView(i, s) { + var u = s ? m(i.buffer) : i.buffer; + return new i.constructor(u, i.byteOffset, i.byteLength); + }; + }, + 93147: (i) => { + var s = /\w*$/; + i.exports = function cloneRegExp(i) { + var u = new i.constructor(i.source, s.exec(i)); + return (u.lastIndex = i.lastIndex), u; + }; + }, + 40419: (i, s, u) => { + var m = u(62705), + v = m ? m.prototype : void 0, + _ = v ? v.valueOf : void 0; + i.exports = function cloneSymbol(i) { + return _ ? Object(_.call(i)) : {}; + }; + }, + 77133: (i, s, u) => { + var m = u(74318); + i.exports = function cloneTypedArray(i, s) { + var u = s ? m(i.buffer) : i.buffer; + return new i.constructor(u, i.byteOffset, i.length); + }; + }, + 52157: (i) => { + var s = Math.max; + i.exports = function composeArgs(i, u, m, v) { + for (var _ = -1, j = i.length, M = m.length, $ = -1, W = u.length, X = s(j - M, 0), Y = Array(W + X), Z = !v; ++$ < W; ) Y[$] = u[$]; + for (; ++_ < M; ) (Z || _ < j) && (Y[m[_]] = i[_]); + for (; X--; ) Y[$++] = i[_++]; + return Y; + }; + }, + 14054: (i) => { + var s = Math.max; + i.exports = function composeArgsRight(i, u, m, v) { + for (var _ = -1, j = i.length, M = -1, $ = m.length, W = -1, X = u.length, Y = s(j - $, 0), Z = Array(Y + X), ee = !v; ++_ < Y; ) Z[_] = i[_]; + for (var ae = _; ++W < X; ) Z[ae + W] = u[W]; + for (; ++M < $; ) (ee || _ < j) && (Z[ae + m[M]] = i[_++]); + return Z; + }; + }, + 278: (i) => { + i.exports = function copyArray(i, s) { + var u = -1, + m = i.length; + for (s || (s = Array(m)); ++u < m; ) s[u] = i[u]; + return s; + }; + }, + 98363: (i, s, u) => { + var m = u(34865), + v = u(89465); + i.exports = function copyObject(i, s, u, _) { + var j = !u; + u || (u = {}); + for (var M = -1, $ = s.length; ++M < $; ) { + var W = s[M], + X = _ ? _(u[W], i[W], W, u, i) : void 0; + void 0 === X && (X = i[W]), j ? v(u, W, X) : m(u, W, X); + } + return u; + }; + }, + 18805: (i, s, u) => { + var m = u(98363), + v = u(99551); + i.exports = function copySymbols(i, s) { + return m(i, v(i), s); + }; + }, + 1911: (i, s, u) => { + var m = u(98363), + v = u(51442); + i.exports = function copySymbolsIn(i, s) { + return m(i, v(i), s); + }; + }, + 14429: (i, s, u) => { + var m = u(55639)['__core-js_shared__']; + i.exports = m; + }, + 97991: (i) => { + i.exports = function countHolders(i, s) { + for (var u = i.length, m = 0; u--; ) i[u] === s && ++m; + return m; + }; + }, + 21463: (i, s, u) => { + var m = u(5976), + v = u(16612); + i.exports = function createAssigner(i) { + return m(function (s, u) { + var m = -1, + _ = u.length, + j = _ > 1 ? u[_ - 1] : void 0, + M = _ > 2 ? u[2] : void 0; + for (j = i.length > 3 && 'function' == typeof j ? (_--, j) : void 0, M && v(u[0], u[1], M) && ((j = _ < 3 ? void 0 : j), (_ = 1)), s = Object(s); ++m < _; ) { + var $ = u[m]; + $ && i(s, $, m, j); + } + return s; + }); + }; + }, + 99291: (i, s, u) => { + var m = u(98612); + i.exports = function createBaseEach(i, s) { + return function (u, v) { + if (null == u) return u; + if (!m(u)) return i(u, v); + for (var _ = u.length, j = s ? _ : -1, M = Object(u); (s ? j-- : ++j < _) && !1 !== v(M[j], j, M); ); + return u; + }; + }; + }, + 25063: (i) => { + i.exports = function createBaseFor(i) { + return function (s, u, m) { + for (var v = -1, _ = Object(s), j = m(s), M = j.length; M--; ) { + var $ = j[i ? M : ++v]; + if (!1 === u(_[$], $, _)) break; + } + return s; + }; + }; + }, + 22402: (i, s, u) => { + var m = u(71774), + v = u(55639); + i.exports = function createBind(i, s, u) { + var _ = 1 & s, + j = m(i); + return function wrapper() { + return (this && this !== v && this instanceof wrapper ? j : i).apply(_ ? u : this, arguments); + }; + }; + }, + 98805: (i, s, u) => { + var m = u(40180), + v = u(62689), + _ = u(83140), + j = u(79833); + i.exports = function createCaseFirst(i) { + return function (s) { + s = j(s); + var u = v(s) ? _(s) : void 0, + M = u ? u[0] : s.charAt(0), + $ = u ? m(u, 1).join('') : s.slice(1); + return M[i]() + $; + }; + }; + }, + 35393: (i, s, u) => { + var m = u(62663), + v = u(53816), + _ = u(58748), + j = RegExp("['’]", 'g'); + i.exports = function createCompounder(i) { + return function (s) { + return m(_(v(s).replace(j, '')), i, ''); + }; + }; + }, + 71774: (i, s, u) => { + var m = u(3118), + v = u(13218); + i.exports = function createCtor(i) { + return function () { + var s = arguments; + switch (s.length) { + case 0: + return new i(); + case 1: + return new i(s[0]); + case 2: + return new i(s[0], s[1]); + case 3: + return new i(s[0], s[1], s[2]); + case 4: + return new i(s[0], s[1], s[2], s[3]); + case 5: + return new i(s[0], s[1], s[2], s[3], s[4]); + case 6: + return new i(s[0], s[1], s[2], s[3], s[4], s[5]); + case 7: + return new i(s[0], s[1], s[2], s[3], s[4], s[5], s[6]); + } + var u = m(i.prototype), + _ = i.apply(u, s); + return v(_) ? _ : u; + }; + }; + }, + 46347: (i, s, u) => { + var m = u(96874), + v = u(71774), + _ = u(86935), + j = u(94487), + M = u(20893), + $ = u(46460), + W = u(55639); + i.exports = function createCurry(i, s, u) { + var X = v(i); + return function wrapper() { + for (var v = arguments.length, Y = Array(v), Z = v, ee = M(wrapper); Z--; ) Y[Z] = arguments[Z]; + var ae = v < 3 && Y[0] !== ee && Y[v - 1] !== ee ? [] : $(Y, ee); + return (v -= ae.length) < u ? j(i, s, _, wrapper.placeholder, void 0, Y, ae, void 0, void 0, u - v) : m(this && this !== W && this instanceof wrapper ? X : i, this, Y); + }; + }; + }, + 67740: (i, s, u) => { + var m = u(67206), + v = u(98612), + _ = u(3674); + i.exports = function createFind(i) { + return function (s, u, j) { + var M = Object(s); + if (!v(s)) { + var $ = m(u, 3); + (s = _(s)), + (u = function (i) { + return $(M[i], i, M); + }); + } + var W = i(s, u, j); + return W > -1 ? M[$ ? s[W] : W] : void 0; + }; + }; + }, + 86935: (i, s, u) => { + var m = u(52157), + v = u(14054), + _ = u(97991), + j = u(71774), + M = u(94487), + $ = u(20893), + W = u(90451), + X = u(46460), + Y = u(55639); + i.exports = function createHybrid(i, s, u, Z, ee, ae, ie, le, ce, pe) { + var de = 128 & s, + fe = 1 & s, + ye = 2 & s, + be = 24 & s, + _e = 512 & s, + we = ye ? void 0 : j(i); + return function wrapper() { + for (var Se = arguments.length, xe = Array(Se), Pe = Se; Pe--; ) xe[Pe] = arguments[Pe]; + if (be) + var Ie = $(wrapper), + Te = _(xe, Ie); + if ((Z && (xe = m(xe, Z, ee, be)), ae && (xe = v(xe, ae, ie, be)), (Se -= Te), be && Se < pe)) { + var Re = X(xe, Ie); + return M(i, s, createHybrid, wrapper.placeholder, u, xe, Re, le, ce, pe - Se); + } + var qe = fe ? u : this, + ze = ye ? qe[i] : i; + return (Se = xe.length), le ? (xe = W(xe, le)) : _e && Se > 1 && xe.reverse(), de && ce < Se && (xe.length = ce), this && this !== Y && this instanceof wrapper && (ze = we || j(ze)), ze.apply(qe, xe); + }; + }; + }, + 84375: (i, s, u) => { + var m = u(96874), + v = u(71774), + _ = u(55639); + i.exports = function createPartial(i, s, u, j) { + var M = 1 & s, + $ = v(i); + return function wrapper() { + for (var s = -1, v = arguments.length, W = -1, X = j.length, Y = Array(X + v), Z = this && this !== _ && this instanceof wrapper ? $ : i; ++W < X; ) Y[W] = j[W]; + for (; v--; ) Y[W++] = arguments[++s]; + return m(Z, M ? u : this, Y); + }; + }; + }, + 94487: (i, s, u) => { + var m = u(86528), + v = u(258), + _ = u(69255); + i.exports = function createRecurry(i, s, u, j, M, $, W, X, Y, Z) { + var ee = 8 & s; + (s |= ee ? 32 : 64), 4 & (s &= ~(ee ? 64 : 32)) || (s &= -4); + var ae = [i, s, M, ee ? $ : void 0, ee ? W : void 0, ee ? void 0 : $, ee ? void 0 : W, X, Y, Z], + ie = u.apply(void 0, ae); + return m(i) && v(ie, ae), (ie.placeholder = j), _(ie, i, s); + }; + }, + 97727: (i, s, u) => { + var m = u(28045), + v = u(22402), + _ = u(46347), + j = u(86935), + M = u(84375), + $ = u(66833), + W = u(63833), + X = u(258), + Y = u(69255), + Z = u(40554), + ee = Math.max; + i.exports = function createWrap(i, s, u, ae, ie, le, ce, pe) { + var de = 2 & s; + if (!de && 'function' != typeof i) throw new TypeError('Expected a function'); + var fe = ae ? ae.length : 0; + if ((fe || ((s &= -97), (ae = ie = void 0)), (ce = void 0 === ce ? ce : ee(Z(ce), 0)), (pe = void 0 === pe ? pe : Z(pe)), (fe -= ie ? ie.length : 0), 64 & s)) { + var ye = ae, + be = ie; + ae = ie = void 0; + } + var _e = de ? void 0 : $(i), + we = [i, s, u, ae, ie, ye, be, le, ce, pe]; + if ( + (_e && W(we, _e), + (i = we[0]), + (s = we[1]), + (u = we[2]), + (ae = we[3]), + (ie = we[4]), + !(pe = we[9] = + void 0 === we[9] ? + de ? 0 + : i.length + : ee(we[9] - fe, 0)) && + 24 & s && + (s &= -25), + s && 1 != s) + ) + Se = + 8 == s || 16 == s ? _(i, s, pe) + : (32 != s && 33 != s) || ie.length ? j.apply(void 0, we) + : M(i, s, u, ae); + else var Se = v(i, s, u); + return Y((_e ? m : X)(Se, we), i, s); + }; + }, + 60696: (i, s, u) => { + var m = u(68630); + i.exports = function customOmitClone(i) { + return m(i) ? void 0 : i; + }; + }, + 69389: (i, s, u) => { + var m = u(18674)({ À: 'A', Á: 'A', Â: 'A', Ã: 'A', Ä: 'A', Å: 'A', à: 'a', á: 'a', â: 'a', ã: 'a', ä: 'a', å: 'a', Ç: 'C', ç: 'c', Ð: 'D', ð: 'd', È: 'E', É: 'E', Ê: 'E', Ë: 'E', è: 'e', é: 'e', ê: 'e', ë: 'e', Ì: 'I', Í: 'I', Î: 'I', Ï: 'I', ì: 'i', í: 'i', î: 'i', ï: 'i', Ñ: 'N', ñ: 'n', Ò: 'O', Ó: 'O', Ô: 'O', Õ: 'O', Ö: 'O', Ø: 'O', ò: 'o', ó: 'o', ô: 'o', õ: 'o', ö: 'o', ø: 'o', Ù: 'U', Ú: 'U', Û: 'U', Ü: 'U', ù: 'u', ú: 'u', û: 'u', ü: 'u', Ý: 'Y', ý: 'y', ÿ: 'y', Æ: 'Ae', æ: 'ae', Þ: 'Th', þ: 'th', ß: 'ss', Ā: 'A', Ă: 'A', Ą: 'A', ā: 'a', ă: 'a', ą: 'a', Ć: 'C', Ĉ: 'C', Ċ: 'C', Č: 'C', ć: 'c', ĉ: 'c', ċ: 'c', č: 'c', Ď: 'D', Đ: 'D', ď: 'd', đ: 'd', Ē: 'E', Ĕ: 'E', Ė: 'E', Ę: 'E', Ě: 'E', ē: 'e', ĕ: 'e', ė: 'e', ę: 'e', ě: 'e', Ĝ: 'G', Ğ: 'G', Ġ: 'G', Ģ: 'G', ĝ: 'g', ğ: 'g', ġ: 'g', ģ: 'g', Ĥ: 'H', Ħ: 'H', ĥ: 'h', ħ: 'h', Ĩ: 'I', Ī: 'I', Ĭ: 'I', Į: 'I', İ: 'I', ĩ: 'i', ī: 'i', ĭ: 'i', į: 'i', ı: 'i', Ĵ: 'J', ĵ: 'j', Ķ: 'K', ķ: 'k', ĸ: 'k', Ĺ: 'L', Ļ: 'L', Ľ: 'L', Ŀ: 'L', Ł: 'L', ĺ: 'l', ļ: 'l', ľ: 'l', ŀ: 'l', ł: 'l', Ń: 'N', Ņ: 'N', Ň: 'N', Ŋ: 'N', ń: 'n', ņ: 'n', ň: 'n', ŋ: 'n', Ō: 'O', Ŏ: 'O', Ő: 'O', ō: 'o', ŏ: 'o', ő: 'o', Ŕ: 'R', Ŗ: 'R', Ř: 'R', ŕ: 'r', ŗ: 'r', ř: 'r', Ś: 'S', Ŝ: 'S', Ş: 'S', Š: 'S', ś: 's', ŝ: 's', ş: 's', š: 's', Ţ: 'T', Ť: 'T', Ŧ: 'T', ţ: 't', ť: 't', ŧ: 't', Ũ: 'U', Ū: 'U', Ŭ: 'U', Ů: 'U', Ű: 'U', Ų: 'U', ũ: 'u', ū: 'u', ŭ: 'u', ů: 'u', ű: 'u', ų: 'u', Ŵ: 'W', ŵ: 'w', Ŷ: 'Y', ŷ: 'y', Ÿ: 'Y', Ź: 'Z', Ż: 'Z', Ž: 'Z', ź: 'z', ż: 'z', ž: 'z', IJ: 'IJ', ij: 'ij', Œ: 'Oe', œ: 'oe', ʼn: "'n", ſ: 's' }); + i.exports = m; + }, + 38777: (i, s, u) => { + var m = u(10852), + v = (function () { + try { + var i = m(Object, 'defineProperty'); + return i({}, '', {}), i; + } catch (i) {} + })(); + i.exports = v; + }, + 67114: (i, s, u) => { + var m = u(88668), + v = u(82908), + _ = u(74757); + i.exports = function equalArrays(i, s, u, j, M, $) { + var W = 1 & u, + X = i.length, + Y = s.length; + if (X != Y && !(W && Y > X)) return !1; + var Z = $.get(i), + ee = $.get(s); + if (Z && ee) return Z == s && ee == i; + var ae = -1, + ie = !0, + le = 2 & u ? new m() : void 0; + for ($.set(i, s), $.set(s, i); ++ae < X; ) { + var ce = i[ae], + pe = s[ae]; + if (j) var de = W ? j(pe, ce, ae, s, i, $) : j(ce, pe, ae, i, s, $); + if (void 0 !== de) { + if (de) continue; + ie = !1; + break; + } + if (le) { + if ( + !v(s, function (i, s) { + if (!_(le, s) && (ce === i || M(ce, i, u, j, $))) return le.push(s); + }) + ) { + ie = !1; + break; + } + } else if (ce !== pe && !M(ce, pe, u, j, $)) { + ie = !1; + break; + } + } + return $.delete(i), $.delete(s), ie; + }; + }, + 18351: (i, s, u) => { + var m = u(62705), + v = u(11149), + _ = u(77813), + j = u(67114), + M = u(68776), + $ = u(21814), + W = m ? m.prototype : void 0, + X = W ? W.valueOf : void 0; + i.exports = function equalByTag(i, s, u, m, W, Y, Z) { + switch (u) { + case '[object DataView]': + if (i.byteLength != s.byteLength || i.byteOffset != s.byteOffset) return !1; + (i = i.buffer), (s = s.buffer); + case '[object ArrayBuffer]': + return !(i.byteLength != s.byteLength || !Y(new v(i), new v(s))); + case '[object Boolean]': + case '[object Date]': + case '[object Number]': + return _(+i, +s); + case '[object Error]': + return i.name == s.name && i.message == s.message; + case '[object RegExp]': + case '[object String]': + return i == s + ''; + case '[object Map]': + var ee = M; + case '[object Set]': + var ae = 1 & m; + if ((ee || (ee = $), i.size != s.size && !ae)) return !1; + var ie = Z.get(i); + if (ie) return ie == s; + (m |= 2), Z.set(i, s); + var le = j(ee(i), ee(s), m, W, Y, Z); + return Z.delete(i), le; + case '[object Symbol]': + if (X) return X.call(i) == X.call(s); + } + return !1; + }; + }, + 16096: (i, s, u) => { + var m = u(58234), + v = Object.prototype.hasOwnProperty; + i.exports = function equalObjects(i, s, u, _, j, M) { + var $ = 1 & u, + W = m(i), + X = W.length; + if (X != m(s).length && !$) return !1; + for (var Y = X; Y--; ) { + var Z = W[Y]; + if (!($ ? Z in s : v.call(s, Z))) return !1; + } + var ee = M.get(i), + ae = M.get(s); + if (ee && ae) return ee == s && ae == i; + var ie = !0; + M.set(i, s), M.set(s, i); + for (var le = $; ++Y < X; ) { + var ce = i[(Z = W[Y])], + pe = s[Z]; + if (_) var de = $ ? _(pe, ce, Z, s, i, M) : _(ce, pe, Z, i, s, M); + if (!(void 0 === de ? ce === pe || j(ce, pe, u, _, M) : de)) { + ie = !1; + break; + } + le || (le = 'constructor' == Z); + } + if (ie && !le) { + var fe = i.constructor, + ye = s.constructor; + fe == ye || !('constructor' in i) || !('constructor' in s) || ('function' == typeof fe && fe instanceof fe && 'function' == typeof ye && ye instanceof ye) || (ie = !1); + } + return M.delete(i), M.delete(s), ie; + }; + }, + 99021: (i, s, u) => { + var m = u(85564), + v = u(45357), + _ = u(30061); + i.exports = function flatRest(i) { + return _(v(i, void 0, m), i + ''); + }; + }, + 31957: (i, s, u) => { + var m = 'object' == typeof u.g && u.g && u.g.Object === Object && u.g; + i.exports = m; + }, + 58234: (i, s, u) => { + var m = u(68866), + v = u(99551), + _ = u(3674); + i.exports = function getAllKeys(i) { + return m(i, _, v); + }; + }, + 46904: (i, s, u) => { + var m = u(68866), + v = u(51442), + _ = u(81704); + i.exports = function getAllKeysIn(i) { + return m(i, _, v); + }; + }, + 66833: (i, s, u) => { + var m = u(89250), + v = u(50308), + _ = + m ? + function (i) { + return m.get(i); + } + : v; + i.exports = _; + }, + 97658: (i, s, u) => { + var m = u(52060), + v = Object.prototype.hasOwnProperty; + i.exports = function getFuncName(i) { + for (var s = i.name + '', u = m[s], _ = v.call(m, s) ? u.length : 0; _--; ) { + var j = u[_], + M = j.func; + if (null == M || M == i) return j.name; + } + return s; + }; + }, + 20893: (i) => { + i.exports = function getHolder(i) { + return i.placeholder; + }; + }, + 45050: (i, s, u) => { + var m = u(37019); + i.exports = function getMapData(i, s) { + var u = i.__data__; + return m(s) ? u['string' == typeof s ? 'string' : 'hash'] : u.map; + }; + }, + 1499: (i, s, u) => { + var m = u(89162), + v = u(3674); + i.exports = function getMatchData(i) { + for (var s = v(i), u = s.length; u--; ) { + var _ = s[u], + j = i[_]; + s[u] = [_, j, m(j)]; + } + return s; + }; + }, + 10852: (i, s, u) => { + var m = u(28458), + v = u(47801); + i.exports = function getNative(i, s) { + var u = v(i, s); + return m(u) ? u : void 0; + }; + }, + 85924: (i, s, u) => { + var m = u(5569)(Object.getPrototypeOf, Object); + i.exports = m; + }, + 89607: (i, s, u) => { + var m = u(62705), + v = Object.prototype, + _ = v.hasOwnProperty, + j = v.toString, + M = m ? m.toStringTag : void 0; + i.exports = function getRawTag(i) { + var s = _.call(i, M), + u = i[M]; + try { + i[M] = void 0; + var m = !0; + } catch (i) {} + var v = j.call(i); + return m && (s ? (i[M] = u) : delete i[M]), v; + }; + }, + 99551: (i, s, u) => { + var m = u(34963), + v = u(70479), + _ = Object.prototype.propertyIsEnumerable, + j = Object.getOwnPropertySymbols, + M = + j ? + function (i) { + return null == i ? + [] + : ((i = Object(i)), + m(j(i), function (s) { + return _.call(i, s); + })); + } + : v; + i.exports = M; + }, + 51442: (i, s, u) => { + var m = u(62488), + v = u(85924), + _ = u(99551), + j = u(70479), + M = + Object.getOwnPropertySymbols ? + function (i) { + for (var s = []; i; ) m(s, _(i)), (i = v(i)); + return s; + } + : j; + i.exports = M; + }, + 64160: (i, s, u) => { + var m = u(18552), + v = u(57071), + _ = u(53818), + j = u(58525), + M = u(70577), + $ = u(44239), + W = u(80346), + X = '[object Map]', + Y = '[object Promise]', + Z = '[object Set]', + ee = '[object WeakMap]', + ae = '[object DataView]', + ie = W(m), + le = W(v), + ce = W(_), + pe = W(j), + de = W(M), + fe = $; + ((m && fe(new m(new ArrayBuffer(1))) != ae) || (v && fe(new v()) != X) || (_ && fe(_.resolve()) != Y) || (j && fe(new j()) != Z) || (M && fe(new M()) != ee)) && + (fe = function (i) { + var s = $(i), + u = '[object Object]' == s ? i.constructor : void 0, + m = u ? W(u) : ''; + if (m) + switch (m) { + case ie: + return ae; + case le: + return X; + case ce: + return Y; + case pe: + return Z; + case de: + return ee; + } + return s; + }), + (i.exports = fe); + }, + 47801: (i) => { + i.exports = function getValue(i, s) { + return null == i ? void 0 : i[s]; + }; + }, + 58775: (i) => { + var s = /\{\n\/\* \[wrapped with (.+)\] \*/, + u = /,? & /; + i.exports = function getWrapDetails(i) { + var m = i.match(s); + return m ? m[1].split(u) : []; + }; + }, + 222: (i, s, u) => { + var m = u(71811), + v = u(35694), + _ = u(1469), + j = u(65776), + M = u(41780), + $ = u(40327); + i.exports = function hasPath(i, s, u) { + for (var W = -1, X = (s = m(s, i)).length, Y = !1; ++W < X; ) { + var Z = $(s[W]); + if (!(Y = null != i && u(i, Z))) break; + i = i[Z]; + } + return Y || ++W != X ? Y : !!(X = null == i ? 0 : i.length) && M(X) && j(Z, X) && (_(i) || v(i)); + }; + }, + 62689: (i) => { + var s = RegExp('[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]'); + i.exports = function hasUnicode(i) { + return s.test(i); + }; + }, + 93157: (i) => { + var s = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + i.exports = function hasUnicodeWord(i) { + return s.test(i); + }; + }, + 51789: (i, s, u) => { + var m = u(94536); + i.exports = function hashClear() { + (this.__data__ = m ? m(null) : {}), (this.size = 0); + }; + }, + 80401: (i) => { + i.exports = function hashDelete(i) { + var s = this.has(i) && delete this.__data__[i]; + return (this.size -= s ? 1 : 0), s; + }; + }, + 57667: (i, s, u) => { + var m = u(94536), + v = Object.prototype.hasOwnProperty; + i.exports = function hashGet(i) { + var s = this.__data__; + if (m) { + var u = s[i]; + return '__lodash_hash_undefined__' === u ? void 0 : u; + } + return v.call(s, i) ? s[i] : void 0; + }; + }, + 21327: (i, s, u) => { + var m = u(94536), + v = Object.prototype.hasOwnProperty; + i.exports = function hashHas(i) { + var s = this.__data__; + return m ? void 0 !== s[i] : v.call(s, i); + }; + }, + 81866: (i, s, u) => { + var m = u(94536); + i.exports = function hashSet(i, s) { + var u = this.__data__; + return (this.size += this.has(i) ? 0 : 1), (u[i] = m && void 0 === s ? '__lodash_hash_undefined__' : s), this; + }; + }, + 43824: (i) => { + var s = Object.prototype.hasOwnProperty; + i.exports = function initCloneArray(i) { + var u = i.length, + m = new i.constructor(u); + return u && 'string' == typeof i[0] && s.call(i, 'index') && ((m.index = i.index), (m.input = i.input)), m; + }; + }, + 29148: (i, s, u) => { + var m = u(74318), + v = u(57157), + _ = u(93147), + j = u(40419), + M = u(77133); + i.exports = function initCloneByTag(i, s, u) { + var $ = i.constructor; + switch (s) { + case '[object ArrayBuffer]': + return m(i); + case '[object Boolean]': + case '[object Date]': + return new $(+i); + case '[object DataView]': + return v(i, u); + case '[object Float32Array]': + case '[object Float64Array]': + case '[object Int8Array]': + case '[object Int16Array]': + case '[object Int32Array]': + case '[object Uint8Array]': + case '[object Uint8ClampedArray]': + case '[object Uint16Array]': + case '[object Uint32Array]': + return M(i, u); + case '[object Map]': + case '[object Set]': + return new $(); + case '[object Number]': + case '[object String]': + return new $(i); + case '[object RegExp]': + return _(i); + case '[object Symbol]': + return j(i); + } + }; + }, + 38517: (i, s, u) => { + var m = u(3118), + v = u(85924), + _ = u(25726); + i.exports = function initCloneObject(i) { + return 'function' != typeof i.constructor || _(i) ? {} : m(v(i)); + }; + }, + 83112: (i) => { + var s = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/; + i.exports = function insertWrapDetails(i, u) { + var m = u.length; + if (!m) return i; + var v = m - 1; + return (u[v] = (m > 1 ? '& ' : '') + u[v]), (u = u.join(m > 2 ? ', ' : ' ')), i.replace(s, '{\n/* [wrapped with ' + u + '] */\n'); + }; + }, + 37285: (i, s, u) => { + var m = u(62705), + v = u(35694), + _ = u(1469), + j = m ? m.isConcatSpreadable : void 0; + i.exports = function isFlattenable(i) { + return _(i) || v(i) || !!(j && i && i[j]); + }; + }, + 65776: (i) => { + var s = /^(?:0|[1-9]\d*)$/; + i.exports = function isIndex(i, u) { + var m = typeof i; + return !!(u = null == u ? 9007199254740991 : u) && ('number' == m || ('symbol' != m && s.test(i))) && i > -1 && i % 1 == 0 && i < u; + }; + }, + 16612: (i, s, u) => { + var m = u(77813), + v = u(98612), + _ = u(65776), + j = u(13218); + i.exports = function isIterateeCall(i, s, u) { + if (!j(u)) return !1; + var M = typeof s; + return !!('number' == M ? v(u) && _(s, u.length) : 'string' == M && s in u) && m(u[s], i); + }; + }, + 15403: (i, s, u) => { + var m = u(1469), + v = u(33448), + _ = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + j = /^\w*$/; + i.exports = function isKey(i, s) { + if (m(i)) return !1; + var u = typeof i; + return !('number' != u && 'symbol' != u && 'boolean' != u && null != i && !v(i)) || j.test(i) || !_.test(i) || (null != s && i in Object(s)); + }; + }, + 37019: (i) => { + i.exports = function isKeyable(i) { + var s = typeof i; + return 'string' == s || 'number' == s || 'symbol' == s || 'boolean' == s ? '__proto__' !== i : null === i; + }; + }, + 86528: (i, s, u) => { + var m = u(96425), + v = u(66833), + _ = u(97658), + j = u(8111); + i.exports = function isLaziable(i) { + var s = _(i), + u = j[s]; + if ('function' != typeof u || !(s in m.prototype)) return !1; + if (i === u) return !0; + var M = v(u); + return !!M && i === M[0]; + }; + }, + 15346: (i, s, u) => { + var m, + v = u(14429), + _ = (m = /[^.]+$/.exec((v && v.keys && v.keys.IE_PROTO) || '')) ? 'Symbol(src)_1.' + m : ''; + i.exports = function isMasked(i) { + return !!_ && _ in i; + }; + }, + 25726: (i) => { + var s = Object.prototype; + i.exports = function isPrototype(i) { + var u = i && i.constructor; + return i === (('function' == typeof u && u.prototype) || s); + }; + }, + 89162: (i, s, u) => { + var m = u(13218); + i.exports = function isStrictComparable(i) { + return i == i && !m(i); + }; + }, + 27040: (i) => { + i.exports = function listCacheClear() { + (this.__data__ = []), (this.size = 0); + }; + }, + 14125: (i, s, u) => { + var m = u(18470), + v = Array.prototype.splice; + i.exports = function listCacheDelete(i) { + var s = this.__data__, + u = m(s, i); + return !(u < 0) && (u == s.length - 1 ? s.pop() : v.call(s, u, 1), --this.size, !0); + }; + }, + 82117: (i, s, u) => { + var m = u(18470); + i.exports = function listCacheGet(i) { + var s = this.__data__, + u = m(s, i); + return u < 0 ? void 0 : s[u][1]; + }; + }, + 67518: (i, s, u) => { + var m = u(18470); + i.exports = function listCacheHas(i) { + return m(this.__data__, i) > -1; + }; + }, + 54705: (i, s, u) => { + var m = u(18470); + i.exports = function listCacheSet(i, s) { + var u = this.__data__, + v = m(u, i); + return v < 0 ? (++this.size, u.push([i, s])) : (u[v][1] = s), this; + }; + }, + 24785: (i, s, u) => { + var m = u(1989), + v = u(38407), + _ = u(57071); + i.exports = function mapCacheClear() { + (this.size = 0), (this.__data__ = { hash: new m(), map: new (_ || v)(), string: new m() }); + }; + }, + 11285: (i, s, u) => { + var m = u(45050); + i.exports = function mapCacheDelete(i) { + var s = m(this, i).delete(i); + return (this.size -= s ? 1 : 0), s; + }; + }, + 96e3: (i, s, u) => { + var m = u(45050); + i.exports = function mapCacheGet(i) { + return m(this, i).get(i); + }; + }, + 49916: (i, s, u) => { + var m = u(45050); + i.exports = function mapCacheHas(i) { + return m(this, i).has(i); + }; + }, + 95265: (i, s, u) => { + var m = u(45050); + i.exports = function mapCacheSet(i, s) { + var u = m(this, i), + v = u.size; + return u.set(i, s), (this.size += u.size == v ? 0 : 1), this; + }; + }, + 68776: (i) => { + i.exports = function mapToArray(i) { + var s = -1, + u = Array(i.size); + return ( + i.forEach(function (i, m) { + u[++s] = [m, i]; + }), + u + ); + }; + }, + 42634: (i) => { + i.exports = function matchesStrictComparable(i, s) { + return function (u) { + return null != u && u[i] === s && (void 0 !== s || i in Object(u)); + }; + }; + }, + 24523: (i, s, u) => { + var m = u(88306); + i.exports = function memoizeCapped(i) { + var s = m(i, function (i) { + return 500 === u.size && u.clear(), i; + }), + u = s.cache; + return s; + }; + }, + 63833: (i, s, u) => { + var m = u(52157), + v = u(14054), + _ = u(46460), + j = '__lodash_placeholder__', + M = 128, + $ = Math.min; + i.exports = function mergeData(i, s) { + var u = i[1], + W = s[1], + X = u | W, + Y = X < 131, + Z = (W == M && 8 == u) || (W == M && 256 == u && i[7].length <= s[8]) || (384 == W && s[7].length <= s[8] && 8 == u); + if (!Y && !Z) return i; + 1 & W && ((i[2] = s[2]), (X |= 1 & u ? 0 : 4)); + var ee = s[3]; + if (ee) { + var ae = i[3]; + (i[3] = ae ? m(ae, ee, s[4]) : ee), (i[4] = ae ? _(i[3], j) : s[4]); + } + return (ee = s[5]) && ((ae = i[5]), (i[5] = ae ? v(ae, ee, s[6]) : ee), (i[6] = ae ? _(i[5], j) : s[6])), (ee = s[7]) && (i[7] = ee), W & M && (i[8] = null == i[8] ? s[8] : $(i[8], s[8])), null == i[9] && (i[9] = s[9]), (i[0] = s[0]), (i[1] = X), i; + }; + }, + 89250: (i, s, u) => { + var m = u(70577), + v = m && new m(); + i.exports = v; + }, + 94536: (i, s, u) => { + var m = u(10852)(Object, 'create'); + i.exports = m; + }, + 86916: (i, s, u) => { + var m = u(5569)(Object.keys, Object); + i.exports = m; + }, + 33498: (i) => { + i.exports = function nativeKeysIn(i) { + var s = []; + if (null != i) for (var u in Object(i)) s.push(u); + return s; + }; + }, + 31167: (i, s, u) => { + i = u.nmd(i); + var m = u(31957), + v = s && !s.nodeType && s, + _ = v && i && !i.nodeType && i, + j = _ && _.exports === v && m.process, + M = (function () { + try { + var i = _ && _.require && _.require('util').types; + return i || (j && j.binding && j.binding('util')); + } catch (i) {} + })(); + i.exports = M; + }, + 2333: (i) => { + var s = Object.prototype.toString; + i.exports = function objectToString(i) { + return s.call(i); + }; + }, + 5569: (i) => { + i.exports = function overArg(i, s) { + return function (u) { + return i(s(u)); + }; + }; + }, + 45357: (i, s, u) => { + var m = u(96874), + v = Math.max; + i.exports = function overRest(i, s, u) { + return ( + (s = v(void 0 === s ? i.length - 1 : s, 0)), + function () { + for (var _ = arguments, j = -1, M = v(_.length - s, 0), $ = Array(M); ++j < M; ) $[j] = _[s + j]; + j = -1; + for (var W = Array(s + 1); ++j < s; ) W[j] = _[j]; + return (W[s] = u($)), m(i, this, W); + } + ); + }; + }, + 40292: (i, s, u) => { + var m = u(97786), + v = u(14259); + i.exports = function parent(i, s) { + return s.length < 2 ? i : m(i, v(s, 0, -1)); + }; + }, + 52060: (i) => { + i.exports = {}; + }, + 90451: (i, s, u) => { + var m = u(278), + v = u(65776), + _ = Math.min; + i.exports = function reorder(i, s) { + for (var u = i.length, j = _(s.length, u), M = m(i); j--; ) { + var $ = s[j]; + i[j] = v($, u) ? M[$] : void 0; + } + return i; + }; + }, + 46460: (i) => { + var s = '__lodash_placeholder__'; + i.exports = function replaceHolders(i, u) { + for (var m = -1, v = i.length, _ = 0, j = []; ++m < v; ) { + var M = i[m]; + (M !== u && M !== s) || ((i[m] = s), (j[_++] = m)); + } + return j; + }; + }, + 55639: (i, s, u) => { + var m = u(31957), + v = 'object' == typeof self && self && self.Object === Object && self, + _ = m || v || Function('return this')(); + i.exports = _; + }, + 36390: (i) => { + i.exports = function safeGet(i, s) { + if (('constructor' !== s || 'function' != typeof i[s]) && '__proto__' != s) return i[s]; + }; + }, + 90619: (i) => { + i.exports = function setCacheAdd(i) { + return this.__data__.set(i, '__lodash_hash_undefined__'), this; + }; + }, + 72385: (i) => { + i.exports = function setCacheHas(i) { + return this.__data__.has(i); + }; + }, + 258: (i, s, u) => { + var m = u(28045), + v = u(21275)(m); + i.exports = v; + }, + 21814: (i) => { + i.exports = function setToArray(i) { + var s = -1, + u = Array(i.size); + return ( + i.forEach(function (i) { + u[++s] = i; + }), + u + ); + }; + }, + 30061: (i, s, u) => { + var m = u(56560), + v = u(21275)(m); + i.exports = v; + }, + 69255: (i, s, u) => { + var m = u(58775), + v = u(83112), + _ = u(30061), + j = u(87241); + i.exports = function setWrapToString(i, s, u) { + var M = s + ''; + return _(i, v(M, j(m(M), u))); + }; + }, + 21275: (i) => { + var s = Date.now; + i.exports = function shortOut(i) { + var u = 0, + m = 0; + return function () { + var v = s(), + _ = 16 - (v - m); + if (((m = v), _ > 0)) { + if (++u >= 800) return arguments[0]; + } else u = 0; + return i.apply(void 0, arguments); + }; + }; + }, + 37465: (i, s, u) => { + var m = u(38407); + i.exports = function stackClear() { + (this.__data__ = new m()), (this.size = 0); + }; + }, + 63779: (i) => { + i.exports = function stackDelete(i) { + var s = this.__data__, + u = s.delete(i); + return (this.size = s.size), u; + }; + }, + 67599: (i) => { + i.exports = function stackGet(i) { + return this.__data__.get(i); + }; + }, + 44758: (i) => { + i.exports = function stackHas(i) { + return this.__data__.has(i); + }; + }, + 34309: (i, s, u) => { + var m = u(38407), + v = u(57071), + _ = u(83369); + i.exports = function stackSet(i, s) { + var u = this.__data__; + if (u instanceof m) { + var j = u.__data__; + if (!v || j.length < 199) return j.push([i, s]), (this.size = ++u.size), this; + u = this.__data__ = new _(j); + } + return u.set(i, s), (this.size = u.size), this; + }; + }, + 42351: (i) => { + i.exports = function strictIndexOf(i, s, u) { + for (var m = u - 1, v = i.length; ++m < v; ) if (i[m] === s) return m; + return -1; + }; + }, + 83140: (i, s, u) => { + var m = u(44286), + v = u(62689), + _ = u(676); + i.exports = function stringToArray(i) { + return v(i) ? _(i) : m(i); + }; + }, + 55514: (i, s, u) => { + var m = u(24523), + v = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, + _ = /\\(\\)?/g, + j = m(function (i) { + var s = []; + return ( + 46 === i.charCodeAt(0) && s.push(''), + i.replace(v, function (i, u, m, v) { + s.push(m ? v.replace(_, '$1') : u || i); + }), + s + ); + }); + i.exports = j; + }, + 40327: (i, s, u) => { + var m = u(33448); + i.exports = function toKey(i) { + if ('string' == typeof i || m(i)) return i; + var s = i + ''; + return '0' == s && 1 / i == -Infinity ? '-0' : s; + }; + }, + 80346: (i) => { + var s = Function.prototype.toString; + i.exports = function toSource(i) { + if (null != i) { + try { + return s.call(i); + } catch (i) {} + try { + return i + ''; + } catch (i) {} + } + return ''; + }; + }, + 67990: (i) => { + var s = /\s/; + i.exports = function trimmedEndIndex(i) { + for (var u = i.length; u-- && s.test(i.charAt(u)); ); + return u; + }; + }, + 676: (i) => { + var s = '\\ud800-\\udfff', + u = '[' + s + ']', + m = '[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]', + v = '\\ud83c[\\udffb-\\udfff]', + _ = '[^' + s + ']', + j = '(?:\\ud83c[\\udde6-\\uddff]){2}', + M = '[\\ud800-\\udbff][\\udc00-\\udfff]', + $ = '(?:' + m + '|' + v + ')' + '?', + W = '[\\ufe0e\\ufe0f]?', + X = W + $ + ('(?:\\u200d(?:' + [_, j, M].join('|') + ')' + W + $ + ')*'), + Y = '(?:' + [_ + m + '?', m, j, M, u].join('|') + ')', + Z = RegExp(v + '(?=' + v + ')|' + Y + X, 'g'); + i.exports = function unicodeToArray(i) { + return i.match(Z) || []; + }; + }, + 2757: (i) => { + var s = '\\ud800-\\udfff', + u = '\\u2700-\\u27bf', + m = 'a-z\\xdf-\\xf6\\xf8-\\xff', + v = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + _ = '\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + j = '[' + _ + ']', + M = '\\d+', + $ = '[' + u + ']', + W = '[' + m + ']', + X = '[^' + s + _ + M + u + m + v + ']', + Y = '(?:\\ud83c[\\udde6-\\uddff]){2}', + Z = '[\\ud800-\\udbff][\\udc00-\\udfff]', + ee = '[' + v + ']', + ae = '(?:' + W + '|' + X + ')', + ie = '(?:' + ee + '|' + X + ')', + le = "(?:['’](?:d|ll|m|re|s|t|ve))?", + ce = "(?:['’](?:D|LL|M|RE|S|T|VE))?", + pe = '(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?', + de = '[\\ufe0e\\ufe0f]?', + fe = de + pe + ('(?:\\u200d(?:' + ['[^' + s + ']', Y, Z].join('|') + ')' + de + pe + ')*'), + ye = '(?:' + [$, Y, Z].join('|') + ')' + fe, + be = RegExp([ee + '?' + W + '+' + le + '(?=' + [j, ee, '$'].join('|') + ')', ie + '+' + ce + '(?=' + [j, ee + ae, '$'].join('|') + ')', ee + '?' + ae + '+' + le, ee + '+' + ce, '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', M, ye].join('|'), 'g'); + i.exports = function unicodeWords(i) { + return i.match(be) || []; + }; + }, + 87241: (i, s, u) => { + var m = u(77412), + v = u(47443), + _ = [ + ['ary', 128], + ['bind', 1], + ['bindKey', 2], + ['curry', 8], + ['curryRight', 16], + ['flip', 512], + ['partial', 32], + ['partialRight', 64], + ['rearg', 256] + ]; + i.exports = function updateWrapDetails(i, s) { + return ( + m(_, function (u) { + var m = '_.' + u[0]; + s & u[1] && !v(i, m) && i.push(m); + }), + i.sort() + ); + }; + }, + 21913: (i, s, u) => { + var m = u(96425), + v = u(7548), + _ = u(278); + i.exports = function wrapperClone(i) { + if (i instanceof m) return i.clone(); + var s = new v(i.__wrapped__, i.__chain__); + return (s.__actions__ = _(i.__actions__)), (s.__index__ = i.__index__), (s.__values__ = i.__values__), s; + }; + }, + 39514: (i, s, u) => { + var m = u(97727); + i.exports = function ary(i, s, u) { + return (s = u ? void 0 : s), (s = i && null == s ? i.length : s), m(i, 128, void 0, void 0, void 0, void 0, s); + }; + }, + 68929: (i, s, u) => { + var m = u(48403), + v = u(35393)(function (i, s, u) { + return (s = s.toLowerCase()), i + (u ? m(s) : s); + }); + i.exports = v; + }, + 48403: (i, s, u) => { + var m = u(79833), + v = u(11700); + i.exports = function capitalize(i) { + return v(m(i).toLowerCase()); + }; + }, + 66678: (i, s, u) => { + var m = u(85990); + i.exports = function clone(i) { + return m(i, 4); + }; + }, + 75703: (i) => { + i.exports = function constant(i) { + return function () { + return i; + }; + }; + }, + 40087: (i, s, u) => { + var m = u(97727); + function curry(i, s, u) { + var v = m(i, 8, void 0, void 0, void 0, void 0, void 0, (s = u ? void 0 : s)); + return (v.placeholder = curry.placeholder), v; + } + (curry.placeholder = {}), (i.exports = curry); + }, + 23279: (i, s, u) => { + var m = u(13218), + v = u(7771), + _ = u(14841), + j = Math.max, + M = Math.min; + i.exports = function debounce(i, s, u) { + var $, + W, + X, + Y, + Z, + ee, + ae = 0, + ie = !1, + le = !1, + ce = !0; + if ('function' != typeof i) throw new TypeError('Expected a function'); + function invokeFunc(s) { + var u = $, + m = W; + return ($ = W = void 0), (ae = s), (Y = i.apply(m, u)); + } + function shouldInvoke(i) { + var u = i - ee; + return void 0 === ee || u >= s || u < 0 || (le && i - ae >= X); + } + function timerExpired() { + var i = v(); + if (shouldInvoke(i)) return trailingEdge(i); + Z = setTimeout( + timerExpired, + (function remainingWait(i) { + var u = s - (i - ee); + return le ? M(u, X - (i - ae)) : u; + })(i) + ); + } + function trailingEdge(i) { + return (Z = void 0), ce && $ ? invokeFunc(i) : (($ = W = void 0), Y); + } + function debounced() { + var i = v(), + u = shouldInvoke(i); + if ((($ = arguments), (W = this), (ee = i), u)) { + if (void 0 === Z) + return (function leadingEdge(i) { + return (ae = i), (Z = setTimeout(timerExpired, s)), ie ? invokeFunc(i) : Y; + })(ee); + if (le) return clearTimeout(Z), (Z = setTimeout(timerExpired, s)), invokeFunc(ee); + } + return void 0 === Z && (Z = setTimeout(timerExpired, s)), Y; + } + return ( + (s = _(s) || 0), + m(u) && ((ie = !!u.leading), (X = (le = 'maxWait' in u) ? j(_(u.maxWait) || 0, s) : X), (ce = 'trailing' in u ? !!u.trailing : ce)), + (debounced.cancel = function cancel() { + void 0 !== Z && clearTimeout(Z), (ae = 0), ($ = ee = W = Z = void 0); + }), + (debounced.flush = function flush() { + return void 0 === Z ? Y : trailingEdge(v()); + }), + debounced + ); + }; + }, + 53816: (i, s, u) => { + var m = u(69389), + v = u(79833), + _ = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g, + j = RegExp('[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]', 'g'); + i.exports = function deburr(i) { + return (i = v(i)) && i.replace(_, m).replace(j, ''); + }; + }, + 77813: (i) => { + i.exports = function eq(i, s) { + return i === s || (i != i && s != s); + }; + }, + 13311: (i, s, u) => { + var m = u(67740)(u(30998)); + i.exports = m; + }, + 30998: (i, s, u) => { + var m = u(41848), + v = u(67206), + _ = u(40554), + j = Math.max; + i.exports = function findIndex(i, s, u) { + var M = null == i ? 0 : i.length; + if (!M) return -1; + var $ = null == u ? 0 : _(u); + return $ < 0 && ($ = j(M + $, 0)), m(i, v(s, 3), $); + }; + }, + 85564: (i, s, u) => { + var m = u(21078); + i.exports = function flatten(i) { + return ( + null == i ? 0 : i.length + ) ? + m(i, 1) + : []; + }; + }, + 84599: (i, s, u) => { + var m = u(68836), + v = u(69306), + _ = Array.prototype.push; + function baseAry(i, s) { + return 2 == s ? + function (s, u) { + return i(s, u); + } + : function (s) { + return i(s); + }; + } + function cloneArray(i) { + for (var s = i ? i.length : 0, u = Array(s); s--; ) u[s] = i[s]; + return u; + } + function wrapImmutable(i, s) { + return function () { + var u = arguments.length; + if (u) { + for (var m = Array(u); u--; ) m[u] = arguments[u]; + var v = (m[0] = s.apply(void 0, m)); + return i.apply(void 0, m), v; + } + }; + } + i.exports = function baseConvert(i, s, u, j) { + var M = 'function' == typeof s, + $ = s === Object(s); + if (($ && ((j = u), (u = s), (s = void 0)), null == u)) throw new TypeError(); + j || (j = {}); + var W = { cap: !('cap' in j) || j.cap, curry: !('curry' in j) || j.curry, fixed: !('fixed' in j) || j.fixed, immutable: !('immutable' in j) || j.immutable, rearg: !('rearg' in j) || j.rearg }, + X = M ? u : v, + Y = 'curry' in j && j.curry, + Z = 'fixed' in j && j.fixed, + ee = 'rearg' in j && j.rearg, + ae = M ? u.runInContext() : void 0, + ie = M ? u : { ary: i.ary, assign: i.assign, clone: i.clone, curry: i.curry, forEach: i.forEach, isArray: i.isArray, isError: i.isError, isFunction: i.isFunction, isWeakMap: i.isWeakMap, iteratee: i.iteratee, keys: i.keys, rearg: i.rearg, toInteger: i.toInteger, toPath: i.toPath }, + le = ie.ary, + ce = ie.assign, + pe = ie.clone, + de = ie.curry, + fe = ie.forEach, + ye = ie.isArray, + be = ie.isError, + _e = ie.isFunction, + we = ie.isWeakMap, + Se = ie.keys, + xe = ie.rearg, + Pe = ie.toInteger, + Ie = ie.toPath, + Te = Se(m.aryMethod), + Re = { + castArray: function (i) { + return function () { + var s = arguments[0]; + return ye(s) ? i(cloneArray(s)) : i.apply(void 0, arguments); + }; + }, + iteratee: function (i) { + return function () { + var s = arguments[1], + u = i(arguments[0], s), + m = u.length; + return W.cap && 'number' == typeof s ? ((s = s > 2 ? s - 2 : 1), m && m <= s ? u : baseAry(u, s)) : u; + }; + }, + mixin: function (i) { + return function (s) { + var u = this; + if (!_e(u)) return i(u, Object(s)); + var m = []; + return ( + fe(Se(s), function (i) { + _e(s[i]) && m.push([i, u.prototype[i]]); + }), + i(u, Object(s)), + fe(m, function (i) { + var s = i[1]; + _e(s) ? (u.prototype[i[0]] = s) : delete u.prototype[i[0]]; + }), + u + ); + }; + }, + nthArg: function (i) { + return function (s) { + var u = s < 0 ? 1 : Pe(s) + 1; + return de(i(s), u); + }; + }, + rearg: function (i) { + return function (s, u) { + var m = u ? u.length : 0; + return de(i(s, u), m); + }; + }, + runInContext: function (s) { + return function (u) { + return baseConvert(i, s(u), j); + }; + } + }; + function castCap(i, s) { + if (W.cap) { + var u = m.iterateeRearg[i]; + if (u) + return (function iterateeRearg(i, s) { + return overArg(i, function (i) { + var u = s.length; + return (function baseArity(i, s) { + return 2 == s ? + function (s, u) { + return i.apply(void 0, arguments); + } + : function (s) { + return i.apply(void 0, arguments); + }; + })(xe(baseAry(i, u), s), u); + }); + })(s, u); + var v = !M && m.iterateeAry[i]; + if (v) + return (function iterateeAry(i, s) { + return overArg(i, function (i) { + return 'function' == typeof i ? baseAry(i, s) : i; + }); + })(s, v); + } + return s; + } + function castFixed(i, s, u) { + if (W.fixed && (Z || !m.skipFixed[i])) { + var v = m.methodSpread[i], + j = v && v.start; + return void 0 === j ? + le(s, u) + : (function flatSpread(i, s) { + return function () { + for (var u = arguments.length, m = u - 1, v = Array(u); u--; ) v[u] = arguments[u]; + var j = v[s], + M = v.slice(0, s); + return j && _.apply(M, j), s != m && _.apply(M, v.slice(s + 1)), i.apply(this, M); + }; + })(s, j); + } + return s; + } + function castRearg(i, s, u) { + return W.rearg && u > 1 && (ee || !m.skipRearg[i]) ? xe(s, m.methodRearg[i] || m.aryRearg[u]) : s; + } + function cloneByPath(i, s) { + for (var u = -1, m = (s = Ie(s)).length, v = m - 1, _ = pe(Object(i)), j = _; null != j && ++u < m; ) { + var M = s[u], + $ = j[M]; + null == $ || _e($) || be($) || we($) || (j[M] = pe(u == v ? $ : Object($))), (j = j[M]); + } + return _; + } + function createConverter(i, s) { + var u = m.aliasToReal[i] || i, + v = m.remap[u] || u, + _ = j; + return function (i) { + var m = M ? ae : ie, + j = M ? ae[v] : s, + $ = ce(ce({}, _), i); + return baseConvert(m, u, j, $); + }; + } + function overArg(i, s) { + return function () { + var u = arguments.length; + if (!u) return i(); + for (var m = Array(u); u--; ) m[u] = arguments[u]; + var v = W.rearg ? 0 : u - 1; + return (m[v] = s(m[v])), i.apply(void 0, m); + }; + } + function wrap(i, s, u) { + var v, + _ = m.aliasToReal[i] || i, + j = s, + M = Re[_]; + return ( + M ? + (j = M(s)) + : W.immutable && + (m.mutate.array[_] ? (j = wrapImmutable(s, cloneArray)) + : m.mutate.object[_] ? + (j = wrapImmutable( + s, + (function createCloner(i) { + return function (s) { + return i({}, s); + }; + })(s) + )) + : m.mutate.set[_] && (j = wrapImmutable(s, cloneByPath))), + fe(Te, function (i) { + return ( + fe(m.aryMethod[i], function (s) { + if (_ == s) { + var u = m.methodSpread[_], + M = u && u.afterRearg; + return ( + (v = M ? castFixed(_, castRearg(_, j, i), i) : castRearg(_, castFixed(_, j, i), i)), + (v = (function castCurry(i, s, u) { + return Y || (W.curry && u > 1) ? de(s, u) : s; + })(0, (v = castCap(_, v)), i)), + !1 + ); + } + }), + !v + ); + }), + v || (v = j), + v == s && + (v = + Y ? + de(v, 1) + : function () { + return s.apply(this, arguments); + }), + (v.convert = createConverter(_, s)), + (v.placeholder = s.placeholder = u), + v + ); + } + if (!$) return wrap(s, u, X); + var qe = u, + ze = []; + return ( + fe(Te, function (i) { + fe(m.aryMethod[i], function (i) { + var s = qe[m.remap[i] || i]; + s && ze.push([i, wrap(i, s, qe)]); + }); + }), + fe(Se(qe), function (i) { + var s = qe[i]; + if ('function' == typeof s) { + for (var u = ze.length; u--; ) if (ze[u][0] == i) return; + (s.convert = createConverter(i, s)), ze.push([i, s]); + } + }), + fe(ze, function (i) { + qe[i[0]] = i[1]; + }), + (qe.convert = function convertLib(i) { + return qe.runInContext.convert(i)(void 0); + }), + (qe.placeholder = qe), + fe(Se(qe), function (i) { + fe(m.realToAlias[i] || [], function (s) { + qe[s] = qe[i]; + }); + }), + qe + ); + }; + }, + 68836: (i, s) => { + (s.aliasToReal = { each: 'forEach', eachRight: 'forEachRight', entries: 'toPairs', entriesIn: 'toPairsIn', extend: 'assignIn', extendAll: 'assignInAll', extendAllWith: 'assignInAllWith', extendWith: 'assignInWith', first: 'head', conforms: 'conformsTo', matches: 'isMatch', property: 'get', __: 'placeholder', F: 'stubFalse', T: 'stubTrue', all: 'every', allPass: 'overEvery', always: 'constant', any: 'some', anyPass: 'overSome', apply: 'spread', assoc: 'set', assocPath: 'set', complement: 'negate', compose: 'flowRight', contains: 'includes', dissoc: 'unset', dissocPath: 'unset', dropLast: 'dropRight', dropLastWhile: 'dropRightWhile', equals: 'isEqual', identical: 'eq', indexBy: 'keyBy', init: 'initial', invertObj: 'invert', juxt: 'over', omitAll: 'omit', nAry: 'ary', path: 'get', pathEq: 'matchesProperty', pathOr: 'getOr', paths: 'at', pickAll: 'pick', pipe: 'flow', pluck: 'map', prop: 'get', propEq: 'matchesProperty', propOr: 'getOr', props: 'at', symmetricDifference: 'xor', symmetricDifferenceBy: 'xorBy', symmetricDifferenceWith: 'xorWith', takeLast: 'takeRight', takeLastWhile: 'takeRightWhile', unapply: 'rest', unnest: 'flatten', useWith: 'overArgs', where: 'conformsTo', whereEq: 'isMatch', zipObj: 'zipObject' }), + (s.aryMethod = { 1: ['assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome', 'rest', 'reverse', 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', 'uniqueId', 'words', 'zipAll'], 2: ['add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', 'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith', 'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN', 'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference', 'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', 'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex', 'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', 'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit', 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', 'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll', 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', 'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', 'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', 'zipObjectDeep'], 3: ['assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', 'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr', 'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith', 'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth', 'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd', 'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight', 'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', 'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy', 'xorWith', 'zipWith'], 4: ['fill', 'setWith', 'updateWith'] }), + (s.aryRearg = { 2: [1, 0], 3: [2, 0, 1], 4: [3, 2, 0, 1] }), + (s.iterateeAry = { dropRightWhile: 1, dropWhile: 1, every: 1, filter: 1, find: 1, findFrom: 1, findIndex: 1, findIndexFrom: 1, findKey: 1, findLast: 1, findLastFrom: 1, findLastIndex: 1, findLastIndexFrom: 1, findLastKey: 1, flatMap: 1, flatMapDeep: 1, flatMapDepth: 1, forEach: 1, forEachRight: 1, forIn: 1, forInRight: 1, forOwn: 1, forOwnRight: 1, map: 1, mapKeys: 1, mapValues: 1, partition: 1, reduce: 2, reduceRight: 2, reject: 1, remove: 1, some: 1, takeRightWhile: 1, takeWhile: 1, times: 1, transform: 2 }), + (s.iterateeRearg = { mapKeys: [1], reduceRight: [1, 0] }), + (s.methodRearg = { assignInAllWith: [1, 0], assignInWith: [1, 2, 0], assignAllWith: [1, 0], assignWith: [1, 2, 0], differenceBy: [1, 2, 0], differenceWith: [1, 2, 0], getOr: [2, 1, 0], intersectionBy: [1, 2, 0], intersectionWith: [1, 2, 0], isEqualWith: [1, 2, 0], isMatchWith: [2, 1, 0], mergeAllWith: [1, 0], mergeWith: [1, 2, 0], padChars: [2, 1, 0], padCharsEnd: [2, 1, 0], padCharsStart: [2, 1, 0], pullAllBy: [2, 1, 0], pullAllWith: [2, 1, 0], rangeStep: [1, 2, 0], rangeStepRight: [1, 2, 0], setWith: [3, 1, 2, 0], sortedIndexBy: [2, 1, 0], sortedLastIndexBy: [2, 1, 0], unionBy: [1, 2, 0], unionWith: [1, 2, 0], updateWith: [3, 1, 2, 0], xorBy: [1, 2, 0], xorWith: [1, 2, 0], zipWith: [1, 2, 0] }), + (s.methodSpread = { assignAll: { start: 0 }, assignAllWith: { start: 0 }, assignInAll: { start: 0 }, assignInAllWith: { start: 0 }, defaultsAll: { start: 0 }, defaultsDeepAll: { start: 0 }, invokeArgs: { start: 2 }, invokeArgsMap: { start: 2 }, mergeAll: { start: 0 }, mergeAllWith: { start: 0 }, partial: { start: 1 }, partialRight: { start: 1 }, without: { start: 1 }, zipAll: { start: 0 } }), + (s.mutate = { array: { fill: !0, pull: !0, pullAll: !0, pullAllBy: !0, pullAllWith: !0, pullAt: !0, remove: !0, reverse: !0 }, object: { assign: !0, assignAll: !0, assignAllWith: !0, assignIn: !0, assignInAll: !0, assignInAllWith: !0, assignInWith: !0, assignWith: !0, defaults: !0, defaultsAll: !0, defaultsDeep: !0, defaultsDeepAll: !0, merge: !0, mergeAll: !0, mergeAllWith: !0, mergeWith: !0 }, set: { set: !0, setWith: !0, unset: !0, update: !0, updateWith: !0 } }), + (s.realToAlias = (function () { + var i = Object.prototype.hasOwnProperty, + u = s.aliasToReal, + m = {}; + for (var v in u) { + var _ = u[v]; + i.call(m, _) ? m[_].push(v) : (m[_] = [v]); + } + return m; + })()), + (s.remap = { assignAll: 'assign', assignAllWith: 'assignWith', assignInAll: 'assignIn', assignInAllWith: 'assignInWith', curryN: 'curry', curryRightN: 'curryRight', defaultsAll: 'defaults', defaultsDeepAll: 'defaultsDeep', findFrom: 'find', findIndexFrom: 'findIndex', findLastFrom: 'findLast', findLastIndexFrom: 'findLastIndex', getOr: 'get', includesFrom: 'includes', indexOfFrom: 'indexOf', invokeArgs: 'invoke', invokeArgsMap: 'invokeMap', lastIndexOfFrom: 'lastIndexOf', mergeAll: 'merge', mergeAllWith: 'mergeWith', padChars: 'pad', padCharsEnd: 'padEnd', padCharsStart: 'padStart', propertyOf: 'get', rangeStep: 'range', rangeStepRight: 'rangeRight', restFrom: 'rest', spreadFrom: 'spread', trimChars: 'trim', trimCharsEnd: 'trimEnd', trimCharsStart: 'trimStart', zipAll: 'zip' }), + (s.skipFixed = { castArray: !0, flow: !0, flowRight: !0, iteratee: !0, mixin: !0, rearg: !0, runInContext: !0 }), + (s.skipRearg = { add: !0, assign: !0, assignIn: !0, bind: !0, bindKey: !0, concat: !0, difference: !0, divide: !0, eq: !0, gt: !0, gte: !0, isEqual: !0, lt: !0, lte: !0, matchesProperty: !0, merge: !0, multiply: !0, overArgs: !0, partial: !0, partialRight: !0, propertyOf: !0, random: !0, range: !0, rangeRight: !0, subtract: !0, zip: !0, zipObject: !0, zipObjectDeep: !0 }); + }, + 4269: (i, s, u) => { + i.exports = { ary: u(39514), assign: u(44037), clone: u(66678), curry: u(40087), forEach: u(77412), isArray: u(1469), isError: u(64647), isFunction: u(23560), isWeakMap: u(81018), iteratee: u(72594), keys: u(280), rearg: u(4963), toInteger: u(40554), toPath: u(30084) }; + }, + 72700: (i, s, u) => { + i.exports = u(28252); + }, + 92822: (i, s, u) => { + var m = u(84599), + v = u(4269); + i.exports = function convert(i, s, u) { + return m(v, i, s, u); + }; + }, + 69306: (i) => { + i.exports = {}; + }, + 28252: (i, s, u) => { + var m = u(92822)('set', u(36968)); + (m.placeholder = u(69306)), (i.exports = m); + }, + 27361: (i, s, u) => { + var m = u(97786); + i.exports = function get(i, s, u) { + var v = null == i ? void 0 : m(i, s); + return void 0 === v ? u : v; + }; + }, + 79095: (i, s, u) => { + var m = u(13), + v = u(222); + i.exports = function hasIn(i, s) { + return null != i && v(i, s, m); + }; + }, + 6557: (i) => { + i.exports = function identity(i) { + return i; + }; + }, + 35694: (i, s, u) => { + var m = u(9454), + v = u(37005), + _ = Object.prototype, + j = _.hasOwnProperty, + M = _.propertyIsEnumerable, + $ = + ( + m( + (function () { + return arguments; + })() + ) + ) ? + m + : function (i) { + return v(i) && j.call(i, 'callee') && !M.call(i, 'callee'); + }; + i.exports = $; + }, + 1469: (i) => { + var s = Array.isArray; + i.exports = s; + }, + 98612: (i, s, u) => { + var m = u(23560), + v = u(41780); + i.exports = function isArrayLike(i) { + return null != i && v(i.length) && !m(i); + }; + }, + 29246: (i, s, u) => { + var m = u(98612), + v = u(37005); + i.exports = function isArrayLikeObject(i) { + return v(i) && m(i); + }; + }, + 51584: (i, s, u) => { + var m = u(44239), + v = u(37005); + i.exports = function isBoolean(i) { + return !0 === i || !1 === i || (v(i) && '[object Boolean]' == m(i)); + }; + }, + 44144: (i, s, u) => { + i = u.nmd(i); + var m = u(55639), + v = u(95062), + _ = s && !s.nodeType && s, + j = _ && i && !i.nodeType && i, + M = j && j.exports === _ ? m.Buffer : void 0, + $ = (M ? M.isBuffer : void 0) || v; + i.exports = $; + }, + 41609: (i, s, u) => { + var m = u(280), + v = u(64160), + _ = u(35694), + j = u(1469), + M = u(98612), + $ = u(44144), + W = u(25726), + X = u(36719), + Y = Object.prototype.hasOwnProperty; + i.exports = function isEmpty(i) { + if (null == i) return !0; + if (M(i) && (j(i) || 'string' == typeof i || 'function' == typeof i.splice || $(i) || X(i) || _(i))) return !i.length; + var s = v(i); + if ('[object Map]' == s || '[object Set]' == s) return !i.size; + if (W(i)) return !m(i).length; + for (var u in i) if (Y.call(i, u)) return !1; + return !0; + }; + }, + 18446: (i, s, u) => { + var m = u(90939); + i.exports = function isEqual(i, s) { + return m(i, s); + }; + }, + 64647: (i, s, u) => { + var m = u(44239), + v = u(37005), + _ = u(68630); + i.exports = function isError(i) { + if (!v(i)) return !1; + var s = m(i); + return '[object Error]' == s || '[object DOMException]' == s || ('string' == typeof i.message && 'string' == typeof i.name && !_(i)); + }; + }, + 23560: (i, s, u) => { + var m = u(44239), + v = u(13218); + i.exports = function isFunction(i) { + if (!v(i)) return !1; + var s = m(i); + return '[object Function]' == s || '[object GeneratorFunction]' == s || '[object AsyncFunction]' == s || '[object Proxy]' == s; + }; + }, + 41780: (i) => { + i.exports = function isLength(i) { + return 'number' == typeof i && i > -1 && i % 1 == 0 && i <= 9007199254740991; + }; + }, + 56688: (i, s, u) => { + var m = u(25588), + v = u(7518), + _ = u(31167), + j = _ && _.isMap, + M = j ? v(j) : m; + i.exports = M; + }, + 45220: (i) => { + i.exports = function isNull(i) { + return null === i; + }; + }, + 81763: (i, s, u) => { + var m = u(44239), + v = u(37005); + i.exports = function isNumber(i) { + return 'number' == typeof i || (v(i) && '[object Number]' == m(i)); + }; + }, + 13218: (i) => { + i.exports = function isObject(i) { + var s = typeof i; + return null != i && ('object' == s || 'function' == s); + }; + }, + 37005: (i) => { + i.exports = function isObjectLike(i) { + return null != i && 'object' == typeof i; + }; + }, + 68630: (i, s, u) => { + var m = u(44239), + v = u(85924), + _ = u(37005), + j = Function.prototype, + M = Object.prototype, + $ = j.toString, + W = M.hasOwnProperty, + X = $.call(Object); + i.exports = function isPlainObject(i) { + if (!_(i) || '[object Object]' != m(i)) return !1; + var s = v(i); + if (null === s) return !0; + var u = W.call(s, 'constructor') && s.constructor; + return 'function' == typeof u && u instanceof u && $.call(u) == X; + }; + }, + 72928: (i, s, u) => { + var m = u(29221), + v = u(7518), + _ = u(31167), + j = _ && _.isSet, + M = j ? v(j) : m; + i.exports = M; + }, + 47037: (i, s, u) => { + var m = u(44239), + v = u(1469), + _ = u(37005); + i.exports = function isString(i) { + return 'string' == typeof i || (!v(i) && _(i) && '[object String]' == m(i)); + }; + }, + 33448: (i, s, u) => { + var m = u(44239), + v = u(37005); + i.exports = function isSymbol(i) { + return 'symbol' == typeof i || (v(i) && '[object Symbol]' == m(i)); + }; + }, + 36719: (i, s, u) => { + var m = u(38749), + v = u(7518), + _ = u(31167), + j = _ && _.isTypedArray, + M = j ? v(j) : m; + i.exports = M; + }, + 81018: (i, s, u) => { + var m = u(64160), + v = u(37005); + i.exports = function isWeakMap(i) { + return v(i) && '[object WeakMap]' == m(i); + }; + }, + 72594: (i, s, u) => { + var m = u(85990), + v = u(67206); + i.exports = function iteratee(i) { + return v('function' == typeof i ? i : m(i, 1)); + }; + }, + 3674: (i, s, u) => { + var m = u(14636), + v = u(280), + _ = u(98612); + i.exports = function keys(i) { + return _(i) ? m(i) : v(i); + }; + }, + 81704: (i, s, u) => { + var m = u(14636), + v = u(10313), + _ = u(98612); + i.exports = function keysIn(i) { + return _(i) ? m(i, !0) : v(i); + }; + }, + 10928: (i) => { + i.exports = function last(i) { + var s = null == i ? 0 : i.length; + return s ? i[s - 1] : void 0; + }; + }, + 88306: (i, s, u) => { + var m = u(83369); + function memoize(i, s) { + if ('function' != typeof i || (null != s && 'function' != typeof s)) throw new TypeError('Expected a function'); + var memoized = function () { + var u = arguments, + m = s ? s.apply(this, u) : u[0], + v = memoized.cache; + if (v.has(m)) return v.get(m); + var _ = i.apply(this, u); + return (memoized.cache = v.set(m, _) || v), _; + }; + return (memoized.cache = new (memoize.Cache || m)()), memoized; + } + (memoize.Cache = m), (i.exports = memoize); + }, + 82492: (i, s, u) => { + var m = u(42980), + v = u(21463)(function (i, s, u) { + m(i, s, u); + }); + i.exports = v; + }, + 94885: (i) => { + i.exports = function negate(i) { + if ('function' != typeof i) throw new TypeError('Expected a function'); + return function () { + var s = arguments; + switch (s.length) { + case 0: + return !i.call(this); + case 1: + return !i.call(this, s[0]); + case 2: + return !i.call(this, s[0], s[1]); + case 3: + return !i.call(this, s[0], s[1], s[2]); + } + return !i.apply(this, s); + }; + }; + }, + 50308: (i) => { + i.exports = function noop() {}; + }, + 7771: (i, s, u) => { + var m = u(55639); + i.exports = function () { + return m.Date.now(); + }; + }, + 57557: (i, s, u) => { + var m = u(29932), + v = u(85990), + _ = u(57406), + j = u(71811), + M = u(98363), + $ = u(60696), + W = u(99021), + X = u(46904), + Y = W(function (i, s) { + var u = {}; + if (null == i) return u; + var W = !1; + (s = m(s, function (s) { + return (s = j(s, i)), W || (W = s.length > 1), s; + })), + M(i, X(i), u), + W && (u = v(u, 7, $)); + for (var Y = s.length; Y--; ) _(u, s[Y]); + return u; + }); + i.exports = Y; + }, + 39601: (i, s, u) => { + var m = u(40371), + v = u(79152), + _ = u(15403), + j = u(40327); + i.exports = function property(i) { + return _(i) ? m(j(i)) : v(i); + }; + }, + 4963: (i, s, u) => { + var m = u(97727), + v = u(99021), + _ = v(function (i, s) { + return m(i, 256, void 0, void 0, void 0, s); + }); + i.exports = _; + }, + 54061: (i, s, u) => { + var m = u(62663), + v = u(89881), + _ = u(67206), + j = u(10107), + M = u(1469); + i.exports = function reduce(i, s, u) { + var $ = M(i) ? m : j, + W = arguments.length < 3; + return $(i, _(s, 4), u, W, v); + }; + }, + 36968: (i, s, u) => { + var m = u(10611); + i.exports = function set(i, s, u) { + return null == i ? i : m(i, s, u); + }; + }, + 59704: (i, s, u) => { + var m = u(82908), + v = u(67206), + _ = u(5076), + j = u(1469), + M = u(16612); + i.exports = function some(i, s, u) { + var $ = j(i) ? m : _; + return u && M(i, s, u) && (s = void 0), $(i, v(s, 3)); + }; + }, + 70479: (i) => { + i.exports = function stubArray() { + return []; + }; + }, + 95062: (i) => { + i.exports = function stubFalse() { + return !1; + }; + }, + 18601: (i, s, u) => { + var m = u(14841), + v = 1 / 0; + i.exports = function toFinite(i) { + return ( + i ? + (i = m(i)) === v || i === -1 / 0 ? 17976931348623157e292 * (i < 0 ? -1 : 1) + : i == i ? i + : 0 + : 0 === i ? i + : 0 + ); + }; + }, + 40554: (i, s, u) => { + var m = u(18601); + i.exports = function toInteger(i) { + var s = m(i), + u = s % 1; + return ( + s == s ? + u ? s - u + : s + : 0 + ); + }; + }, + 7334: (i, s, u) => { + var m = u(79833); + i.exports = function toLower(i) { + return m(i).toLowerCase(); + }; + }, + 14841: (i, s, u) => { + var m = u(27561), + v = u(13218), + _ = u(33448), + j = /^[-+]0x[0-9a-f]+$/i, + M = /^0b[01]+$/i, + $ = /^0o[0-7]+$/i, + W = parseInt; + i.exports = function toNumber(i) { + if ('number' == typeof i) return i; + if (_(i)) return NaN; + if (v(i)) { + var s = 'function' == typeof i.valueOf ? i.valueOf() : i; + i = v(s) ? s + '' : s; + } + if ('string' != typeof i) return 0 === i ? i : +i; + i = m(i); + var u = M.test(i); + return ( + u || $.test(i) ? W(i.slice(2), u ? 2 : 8) + : j.test(i) ? NaN + : +i + ); + }; + }, + 30084: (i, s, u) => { + var m = u(29932), + v = u(278), + _ = u(1469), + j = u(33448), + M = u(55514), + $ = u(40327), + W = u(79833); + i.exports = function toPath(i) { + return ( + _(i) ? m(i, $) + : j(i) ? [i] + : v(M(W(i))) + ); + }; + }, + 59881: (i, s, u) => { + var m = u(98363), + v = u(81704); + i.exports = function toPlainObject(i) { + return m(i, v(i)); + }; + }, + 79833: (i, s, u) => { + var m = u(80531); + i.exports = function toString(i) { + return null == i ? '' : m(i); + }; + }, + 11700: (i, s, u) => { + var m = u(98805)('toUpperCase'); + i.exports = m; + }, + 58748: (i, s, u) => { + var m = u(49029), + v = u(93157), + _ = u(79833), + j = u(2757); + i.exports = function words(i, s, u) { + return ( + (i = _(i)), + void 0 === (s = u ? void 0 : s) ? + v(i) ? j(i) + : m(i) + : i.match(s) || [] + ); + }; + }, + 8111: (i, s, u) => { + var m = u(96425), + v = u(7548), + _ = u(9435), + j = u(1469), + M = u(37005), + $ = u(21913), + W = Object.prototype.hasOwnProperty; + function lodash(i) { + if (M(i) && !j(i) && !(i instanceof m)) { + if (i instanceof v) return i; + if (W.call(i, '__wrapped__')) return $(i); + } + return new v(i); + } + (lodash.prototype = _.prototype), (lodash.prototype.constructor = lodash), (i.exports = lodash); + }, + 7287: (i, s, u) => { + var m = u(34865), + v = u(1757); + i.exports = function zipObject(i, s) { + return v(i || [], s || [], m); + }; + }, + 96470: (i, s, u) => { + 'use strict'; + var m = u(47802), + v = u(21102); + (s.highlight = highlight), + (s.highlightAuto = function highlightAuto(i, s) { + var u, + j, + M, + $, + W = s || {}, + X = W.subset || m.listLanguages(), + Y = W.prefix, + Z = X.length, + ee = -1; + null == Y && (Y = _); + if ('string' != typeof i) throw v('Expected `string` for value, got `%s`', i); + (j = { relevance: 0, language: null, value: [] }), (u = { relevance: 0, language: null, value: [] }); + for (; ++ee < Z; ) ($ = X[ee]), m.getLanguage($) && (((M = highlight($, i, s)).language = $), M.relevance > j.relevance && (j = M), M.relevance > u.relevance && ((j = u), (u = M))); + j.language && (u.secondBest = j); + return u; + }), + (s.registerLanguage = function registerLanguage(i, s) { + m.registerLanguage(i, s); + }), + (s.listLanguages = function listLanguages() { + return m.listLanguages(); + }), + (s.registerAlias = function registerAlias(i, s) { + var u, + v = i; + s && ((v = {})[i] = s); + for (u in v) m.registerAliases(v[u], { languageName: u }); + }), + (Emitter.prototype.addText = function text(i) { + var s, + u, + m = this.stack; + if ('' === i) return; + (s = m[m.length - 1]), (u = s.children[s.children.length - 1]) && 'text' === u.type ? (u.value += i) : s.children.push({ type: 'text', value: i }); + }), + (Emitter.prototype.addKeyword = function addKeyword(i, s) { + this.openNode(s), this.addText(i), this.closeNode(); + }), + (Emitter.prototype.addSublanguage = function addSublanguage(i, s) { + var u = this.stack, + m = u[u.length - 1], + v = i.rootNode.children, + _ = s ? { type: 'element', tagName: 'span', properties: { className: [s] }, children: v } : v; + m.children = m.children.concat(_); + }), + (Emitter.prototype.openNode = function open(i) { + var s = this.stack, + u = this.options.classPrefix + i, + m = s[s.length - 1], + v = { type: 'element', tagName: 'span', properties: { className: [u] }, children: [] }; + m.children.push(v), s.push(v); + }), + (Emitter.prototype.closeNode = function close() { + this.stack.pop(); + }), + (Emitter.prototype.closeAllNodes = noop), + (Emitter.prototype.finalize = noop), + (Emitter.prototype.toHTML = function toHtmlNoop() { + return ''; + }); + var _ = 'hljs-'; + function highlight(i, s, u) { + var j, + M = m.configure({}), + $ = (u || {}).prefix; + if ('string' != typeof i) throw v('Expected `string` for name, got `%s`', i); + if (!m.getLanguage(i)) throw v('Unknown language: `%s` is not registered', i); + if ('string' != typeof s) throw v('Expected `string` for value, got `%s`', s); + if ((null == $ && ($ = _), m.configure({ __emitter: Emitter, classPrefix: $ }), (j = m.highlight(s, { language: i, ignoreIllegals: !0 })), m.configure(M || {}), j.errorRaised)) throw j.errorRaised; + return { relevance: j.relevance, language: j.language, value: j.emitter.rootNode.children }; + } + function Emitter(i) { + (this.options = i), (this.rootNode = { children: [] }), (this.stack = [this.rootNode]); + } + function noop() {} + }, + 42566: (i, s, u) => { + const m = u(94885); + function coerceElementMatchingCallback(i) { + return ( + 'string' == typeof i ? (s) => s.element === i + : i.constructor && i.extend ? (s) => s instanceof i + : i + ); + } + class ArraySlice { + constructor(i) { + this.elements = i || []; + } + toValue() { + return this.elements.map((i) => i.toValue()); + } + map(i, s) { + return this.elements.map(i, s); + } + flatMap(i, s) { + return this.map(i, s).reduce((i, s) => i.concat(s), []); + } + compactMap(i, s) { + const u = []; + return ( + this.forEach((m) => { + const v = i.bind(s)(m); + v && u.push(v); + }), + u + ); + } + filter(i, s) { + return (i = coerceElementMatchingCallback(i)), new ArraySlice(this.elements.filter(i, s)); + } + reject(i, s) { + return (i = coerceElementMatchingCallback(i)), new ArraySlice(this.elements.filter(m(i), s)); + } + find(i, s) { + return (i = coerceElementMatchingCallback(i)), this.elements.find(i, s); + } + forEach(i, s) { + this.elements.forEach(i, s); + } + reduce(i, s) { + return this.elements.reduce(i, s); + } + includes(i) { + return this.elements.some((s) => s.equals(i)); + } + shift() { + return this.elements.shift(); + } + unshift(i) { + this.elements.unshift(this.refract(i)); + } + push(i) { + return this.elements.push(this.refract(i)), this; + } + add(i) { + this.push(i); + } + get(i) { + return this.elements[i]; + } + getValue(i) { + const s = this.elements[i]; + if (s) return s.toValue(); + } + get length() { + return this.elements.length; + } + get isEmpty() { + return 0 === this.elements.length; + } + get first() { + return this.elements[0]; + } + } + 'undefined' != typeof Symbol && + (ArraySlice.prototype[Symbol.iterator] = function symbol() { + return this.elements[Symbol.iterator](); + }), + (i.exports = ArraySlice); + }, + 17645: (i) => { + class KeyValuePair { + constructor(i, s) { + (this.key = i), (this.value = s); + } + clone() { + const i = new KeyValuePair(); + return this.key && (i.key = this.key.clone()), this.value && (i.value = this.value.clone()), i; + } + } + i.exports = KeyValuePair; + }, + 78520: (i, s, u) => { + const m = u(45220), + v = u(47037), + _ = u(81763), + j = u(51584), + M = u(13218), + $ = u(28219), + W = u(99829); + class Namespace { + constructor(i) { + (this.elementMap = {}), (this.elementDetection = []), (this.Element = W.Element), (this.KeyValuePair = W.KeyValuePair), (i && i.noDefault) || this.useDefault(), (this._attributeElementKeys = []), (this._attributeElementArrayKeys = []); + } + use(i) { + return i.namespace && i.namespace({ base: this }), i.load && i.load({ base: this }), this; + } + useDefault() { + return this.register('null', W.NullElement).register('string', W.StringElement).register('number', W.NumberElement).register('boolean', W.BooleanElement).register('array', W.ArrayElement).register('object', W.ObjectElement).register('member', W.MemberElement).register('ref', W.RefElement).register('link', W.LinkElement), this.detect(m, W.NullElement, !1).detect(v, W.StringElement, !1).detect(_, W.NumberElement, !1).detect(j, W.BooleanElement, !1).detect(Array.isArray, W.ArrayElement, !1).detect(M, W.ObjectElement, !1), this; + } + register(i, s) { + return (this._elements = void 0), (this.elementMap[i] = s), this; + } + unregister(i) { + return (this._elements = void 0), delete this.elementMap[i], this; + } + detect(i, s, u) { + return void 0 === u || u ? this.elementDetection.unshift([i, s]) : this.elementDetection.push([i, s]), this; + } + toElement(i) { + if (i instanceof this.Element) return i; + let s; + for (let u = 0; u < this.elementDetection.length; u += 1) { + const m = this.elementDetection[u][0], + v = this.elementDetection[u][1]; + if (m(i)) { + s = new v(i); + break; + } + } + return s; + } + getElementClass(i) { + const s = this.elementMap[i]; + return void 0 === s ? this.Element : s; + } + fromRefract(i) { + return this.serialiser.deserialise(i); + } + toRefract(i) { + return this.serialiser.serialise(i); + } + get elements() { + return ( + void 0 === this._elements && + ((this._elements = { Element: this.Element }), + Object.keys(this.elementMap).forEach((i) => { + const s = i[0].toUpperCase() + i.substr(1); + this._elements[s] = this.elementMap[i]; + })), + this._elements + ); + } + get serialiser() { + return new $(this); + } + } + ($.prototype.Namespace = Namespace), (i.exports = Namespace); + }, + 87526: (i, s, u) => { + const m = u(94885), + v = u(42566); + class ObjectSlice extends v { + map(i, s) { + return this.elements.map((u) => i.bind(s)(u.value, u.key, u)); + } + filter(i, s) { + return new ObjectSlice(this.elements.filter((u) => i.bind(s)(u.value, u.key, u))); + } + reject(i, s) { + return this.filter(m(i.bind(s))); + } + forEach(i, s) { + return this.elements.forEach((u, m) => { + i.bind(s)(u.value, u.key, u, m); + }); + } + keys() { + return this.map((i, s) => s.toValue()); + } + values() { + return this.map((i) => i.toValue()); + } + } + i.exports = ObjectSlice; + }, + 99829: (i, s, u) => { + const m = u(3079), + v = u(96295), + _ = u(16036), + j = u(91090), + M = u(18866), + $ = u(35804), + W = u(5946), + X = u(76735), + Y = u(59964), + Z = u(38588), + ee = u(42566), + ae = u(87526), + ie = u(17645); + function refract(i) { + if (i instanceof m) return i; + if ('string' == typeof i) return new _(i); + if ('number' == typeof i) return new j(i); + if ('boolean' == typeof i) return new M(i); + if (null === i) return new v(); + if (Array.isArray(i)) return new $(i.map(refract)); + if ('object' == typeof i) { + return new X(i); + } + return i; + } + (m.prototype.ObjectElement = X), (m.prototype.RefElement = Z), (m.prototype.MemberElement = W), (m.prototype.refract = refract), (ee.prototype.refract = refract), (i.exports = { Element: m, NullElement: v, StringElement: _, NumberElement: j, BooleanElement: M, ArrayElement: $, MemberElement: W, ObjectElement: X, LinkElement: Y, RefElement: Z, refract, ArraySlice: ee, ObjectSlice: ae, KeyValuePair: ie }); + }, + 59964: (i, s, u) => { + const m = u(3079); + i.exports = class LinkElement extends m { + constructor(i, s, u) { + super(i || [], s, u), (this.element = 'link'); + } + get relation() { + return this.attributes.get('relation'); + } + set relation(i) { + this.attributes.set('relation', i); + } + get href() { + return this.attributes.get('href'); + } + set href(i) { + this.attributes.set('href', i); + } + }; + }, + 38588: (i, s, u) => { + const m = u(3079); + i.exports = class RefElement extends m { + constructor(i, s, u) { + super(i || [], s, u), (this.element = 'ref'), this.path || (this.path = 'element'); + } + get path() { + return this.attributes.get('path'); + } + set path(i) { + this.attributes.set('path', i); + } + }; + }, + 43500: (i, s, u) => { + const m = u(78520), + v = u(99829); + (s.lS = m), u(17645), (s.O4 = v.ArraySlice), v.ObjectSlice, (s.W_ = v.Element), (s.RP = v.StringElement), (s.VL = v.NumberElement), (s.hh = v.BooleanElement), (s.zr = v.NullElement), (s.ON = v.ArrayElement), (s.Sb = v.ObjectElement), (s.c6 = v.MemberElement), (s.tK = v.RefElement), (s.EA = v.LinkElement), (s.Qc = v.refract), u(28219), u(3414); + }, + 35804: (i, s, u) => { + const m = u(94885), + v = u(3079), + _ = u(42566); + class ArrayElement extends v { + 'constructor'(i, s, u) { + super(i || [], s, u), (this.element = 'array'); + } + 'primitive'() { + return 'array'; + } + 'get'(i) { + return this.content[i]; + } + 'getValue'(i) { + const s = this.get(i); + if (s) return s.toValue(); + } + 'getIndex'(i) { + return this.content[i]; + } + 'set'(i, s) { + return (this.content[i] = this.refract(s)), this; + } + 'remove'(i) { + const s = this.content.splice(i, 1); + return s.length ? s[0] : null; + } + 'map'(i, s) { + return this.content.map(i, s); + } + 'flatMap'(i, s) { + return this.map(i, s).reduce((i, s) => i.concat(s), []); + } + 'compactMap'(i, s) { + const u = []; + return ( + this.forEach((m) => { + const v = i.bind(s)(m); + v && u.push(v); + }), + u + ); + } + 'filter'(i, s) { + return new _(this.content.filter(i, s)); + } + 'reject'(i, s) { + return this.filter(m(i), s); + } + 'reduce'(i, s) { + let u, m; + void 0 !== s ? ((u = 0), (m = this.refract(s))) : ((u = 1), (m = 'object' === this.primitive() ? this.first.value : this.first)); + for (let s = u; s < this.length; s += 1) { + const u = this.content[s]; + m = 'object' === this.primitive() ? this.refract(i(m, u.value, u.key, u, this)) : this.refract(i(m, u, s, this)); + } + return m; + } + 'forEach'(i, s) { + this.content.forEach((u, m) => { + i.bind(s)(u, this.refract(m)); + }); + } + 'shift'() { + return this.content.shift(); + } + 'unshift'(i) { + this.content.unshift(this.refract(i)); + } + 'push'(i) { + return this.content.push(this.refract(i)), this; + } + 'add'(i) { + this.push(i); + } + 'findElements'(i, s) { + const u = s || {}, + m = !!u.recursive, + v = void 0 === u.results ? [] : u.results; + return ( + this.forEach((s, u, _) => { + m && void 0 !== s.findElements && s.findElements(i, { results: v, recursive: m }), i(s, u, _) && v.push(s); + }), + v + ); + } + 'find'(i) { + return new _(this.findElements(i, { recursive: !0 })); + } + 'findByElement'(i) { + return this.find((s) => s.element === i); + } + 'findByClass'(i) { + return this.find((s) => s.classes.includes(i)); + } + 'getById'(i) { + return this.find((s) => s.id.toValue() === i).first; + } + 'includes'(i) { + return this.content.some((s) => s.equals(i)); + } + 'contains'(i) { + return this.includes(i); + } + 'empty'() { + return new this.constructor([]); + } + 'fantasy-land/empty'() { + return this.empty(); + } + 'concat'(i) { + return new this.constructor(this.content.concat(i.content)); + } + 'fantasy-land/concat'(i) { + return this.concat(i); + } + 'fantasy-land/map'(i) { + return new this.constructor(this.map(i)); + } + 'fantasy-land/chain'(i) { + return this.map((s) => i(s), this).reduce((i, s) => i.concat(s), this.empty()); + } + 'fantasy-land/filter'(i) { + return new this.constructor(this.content.filter(i)); + } + 'fantasy-land/reduce'(i, s) { + return this.content.reduce(i, s); + } + get 'length'() { + return this.content.length; + } + get 'isEmpty'() { + return 0 === this.content.length; + } + get 'first'() { + return this.getIndex(0); + } + get 'second'() { + return this.getIndex(1); + } + get 'last'() { + return this.getIndex(this.length - 1); + } + } + (ArrayElement.empty = function empty() { + return new this(); + }), + (ArrayElement['fantasy-land/empty'] = ArrayElement.empty), + 'undefined' != typeof Symbol && + (ArrayElement.prototype[Symbol.iterator] = function symbol() { + return this.content[Symbol.iterator](); + }), + (i.exports = ArrayElement); + }, + 18866: (i, s, u) => { + const m = u(3079); + i.exports = class BooleanElement extends m { + constructor(i, s, u) { + super(i, s, u), (this.element = 'boolean'); + } + primitive() { + return 'boolean'; + } + }; + }, + 3079: (i, s, u) => { + const m = u(18446), + v = u(17645), + _ = u(42566); + class Element { + constructor(i, s, u) { + s && (this.meta = s), u && (this.attributes = u), (this.content = i); + } + freeze() { + Object.isFrozen(this) || + (this._meta && ((this.meta.parent = this), this.meta.freeze()), + this._attributes && ((this.attributes.parent = this), this.attributes.freeze()), + this.children.forEach((i) => { + (i.parent = this), i.freeze(); + }, this), + this.content && Array.isArray(this.content) && Object.freeze(this.content), + Object.freeze(this)); + } + primitive() {} + clone() { + const i = new this.constructor(); + return ( + (i.element = this.element), + this.meta.length && (i._meta = this.meta.clone()), + this.attributes.length && (i._attributes = this.attributes.clone()), + this.content ? + this.content.clone ? (i.content = this.content.clone()) + : Array.isArray(this.content) ? (i.content = this.content.map((i) => i.clone())) + : (i.content = this.content) + : (i.content = this.content), + i + ); + } + toValue() { + return ( + this.content instanceof Element ? this.content.toValue() + : this.content instanceof v ? { key: this.content.key.toValue(), value: this.content.value ? this.content.value.toValue() : void 0 } + : this.content && this.content.map ? this.content.map((i) => i.toValue(), this) + : this.content + ); + } + toRef(i) { + if ('' === this.id.toValue()) throw Error('Cannot create reference to an element that does not contain an ID'); + const s = new this.RefElement(this.id.toValue()); + return i && (s.path = i), s; + } + findRecursive(...i) { + if (arguments.length > 1 && !this.isFrozen) throw new Error('Cannot find recursive with multiple element names without first freezing the element. Call `element.freeze()`'); + const s = i.pop(); + let u = new _(); + const append = (i, s) => (i.push(s), i), + checkElement = (i, u) => { + u.element === s && i.push(u); + const m = u.findRecursive(s); + return m && m.reduce(append, i), u.content instanceof v && (u.content.key && checkElement(i, u.content.key), u.content.value && checkElement(i, u.content.value)), i; + }; + return ( + this.content && (this.content.element && checkElement(u, this.content), Array.isArray(this.content) && this.content.reduce(checkElement, u)), + i.isEmpty || + (u = u.filter((s) => { + let u = s.parents.map((i) => i.element); + for (const s in i) { + const m = i[s], + v = u.indexOf(m); + if (-1 === v) return !1; + u = u.splice(0, v); + } + return !0; + })), + u + ); + } + set(i) { + return (this.content = i), this; + } + equals(i) { + return m(this.toValue(), i); + } + getMetaProperty(i, s) { + if (!this.meta.hasKey(i)) { + if (this.isFrozen) { + const i = this.refract(s); + return i.freeze(), i; + } + this.meta.set(i, s); + } + return this.meta.get(i); + } + setMetaProperty(i, s) { + this.meta.set(i, s); + } + get element() { + return this._storedElement || 'element'; + } + set element(i) { + this._storedElement = i; + } + get content() { + return this._content; + } + set content(i) { + if (i instanceof Element) this._content = i; + else if (i instanceof _) this.content = i.elements; + else if ('string' == typeof i || 'number' == typeof i || 'boolean' == typeof i || 'null' === i || null == i) this._content = i; + else if (i instanceof v) this._content = i; + else if (Array.isArray(i)) this._content = i.map(this.refract); + else { + if ('object' != typeof i) throw new Error('Cannot set content to given value'); + this._content = Object.keys(i).map((s) => new this.MemberElement(s, i[s])); + } + } + get meta() { + if (!this._meta) { + if (this.isFrozen) { + const i = new this.ObjectElement(); + return i.freeze(), i; + } + this._meta = new this.ObjectElement(); + } + return this._meta; + } + set meta(i) { + i instanceof this.ObjectElement ? (this._meta = i) : this.meta.set(i || {}); + } + get attributes() { + if (!this._attributes) { + if (this.isFrozen) { + const i = new this.ObjectElement(); + return i.freeze(), i; + } + this._attributes = new this.ObjectElement(); + } + return this._attributes; + } + set attributes(i) { + i instanceof this.ObjectElement ? (this._attributes = i) : this.attributes.set(i || {}); + } + get id() { + return this.getMetaProperty('id', ''); + } + set id(i) { + this.setMetaProperty('id', i); + } + get classes() { + return this.getMetaProperty('classes', []); + } + set classes(i) { + this.setMetaProperty('classes', i); + } + get title() { + return this.getMetaProperty('title', ''); + } + set title(i) { + this.setMetaProperty('title', i); + } + get description() { + return this.getMetaProperty('description', ''); + } + set description(i) { + this.setMetaProperty('description', i); + } + get links() { + return this.getMetaProperty('links', []); + } + set links(i) { + this.setMetaProperty('links', i); + } + get isFrozen() { + return Object.isFrozen(this); + } + get parents() { + let { parent: i } = this; + const s = new _(); + for (; i; ) s.push(i), (i = i.parent); + return s; + } + get children() { + if (Array.isArray(this.content)) return new _(this.content); + if (this.content instanceof v) { + const i = new _([this.content.key]); + return this.content.value && i.push(this.content.value), i; + } + return this.content instanceof Element ? new _([this.content]) : new _(); + } + get recursiveChildren() { + const i = new _(); + return ( + this.children.forEach((s) => { + i.push(s), + s.recursiveChildren.forEach((s) => { + i.push(s); + }); + }), + i + ); + } + } + i.exports = Element; + }, + 5946: (i, s, u) => { + const m = u(17645), + v = u(3079); + i.exports = class MemberElement extends v { + constructor(i, s, u, v) { + super(new m(), u, v), (this.element = 'member'), (this.key = i), (this.value = s); + } + get key() { + return this.content.key; + } + set key(i) { + this.content.key = this.refract(i); + } + get value() { + return this.content.value; + } + set value(i) { + this.content.value = this.refract(i); + } + }; + }, + 96295: (i, s, u) => { + const m = u(3079); + i.exports = class NullElement extends m { + constructor(i, s, u) { + super(i || null, s, u), (this.element = 'null'); + } + primitive() { + return 'null'; + } + set() { + return new Error('Cannot set the value of null'); + } + }; + }, + 91090: (i, s, u) => { + const m = u(3079); + i.exports = class NumberElement extends m { + constructor(i, s, u) { + super(i, s, u), (this.element = 'number'); + } + primitive() { + return 'number'; + } + }; + }, + 76735: (i, s, u) => { + const m = u(94885), + v = u(13218), + _ = u(35804), + j = u(5946), + M = u(87526); + i.exports = class ObjectElement extends _ { + constructor(i, s, u) { + super(i || [], s, u), (this.element = 'object'); + } + primitive() { + return 'object'; + } + toValue() { + return this.content.reduce((i, s) => ((i[s.key.toValue()] = s.value ? s.value.toValue() : void 0), i), {}); + } + get(i) { + const s = this.getMember(i); + if (s) return s.value; + } + getMember(i) { + if (void 0 !== i) return this.content.find((s) => s.key.toValue() === i); + } + remove(i) { + let s = null; + return (this.content = this.content.filter((u) => u.key.toValue() !== i || ((s = u), !1))), s; + } + getKey(i) { + const s = this.getMember(i); + if (s) return s.key; + } + set(i, s) { + if (v(i)) + return ( + Object.keys(i).forEach((s) => { + this.set(s, i[s]); + }), + this + ); + const u = i, + m = this.getMember(u); + return m ? (m.value = s) : this.content.push(new j(u, s)), this; + } + keys() { + return this.content.map((i) => i.key.toValue()); + } + values() { + return this.content.map((i) => i.value.toValue()); + } + hasKey(i) { + return this.content.some((s) => s.key.equals(i)); + } + items() { + return this.content.map((i) => [i.key.toValue(), i.value.toValue()]); + } + map(i, s) { + return this.content.map((u) => i.bind(s)(u.value, u.key, u)); + } + compactMap(i, s) { + const u = []; + return ( + this.forEach((m, v, _) => { + const j = i.bind(s)(m, v, _); + j && u.push(j); + }), + u + ); + } + filter(i, s) { + return new M(this.content).filter(i, s); + } + reject(i, s) { + return this.filter(m(i), s); + } + forEach(i, s) { + return this.content.forEach((u) => i.bind(s)(u.value, u.key, u)); + } + }; + }, + 16036: (i, s, u) => { + const m = u(3079); + i.exports = class StringElement extends m { + constructor(i, s, u) { + super(i, s, u), (this.element = 'string'); + } + primitive() { + return 'string'; + } + get length() { + return this.content.length; + } + }; + }, + 3414: (i, s, u) => { + const m = u(28219); + i.exports = class JSON06Serialiser extends m { + serialise(i) { + if (!(i instanceof this.namespace.elements.Element)) throw new TypeError(`Given element \`${i}\` is not an Element instance`); + let s; + i._attributes && i.attributes.get('variable') && (s = i.attributes.get('variable')); + const u = { element: i.element }; + i._meta && i._meta.length > 0 && (u.meta = this.serialiseObject(i.meta)); + const m = 'enum' === i.element || -1 !== i.attributes.keys().indexOf('enumerations'); + if (m) { + const s = this.enumSerialiseAttributes(i); + s && (u.attributes = s); + } else if (i._attributes && i._attributes.length > 0) { + let { attributes: m } = i; + m.get('metadata') && ((m = m.clone()), m.set('meta', m.get('metadata')), m.remove('metadata')), 'member' === i.element && s && ((m = m.clone()), m.remove('variable')), m.length > 0 && (u.attributes = this.serialiseObject(m)); + } + if (m) u.content = this.enumSerialiseContent(i, u); + else if (this[`${i.element}SerialiseContent`]) u.content = this[`${i.element}SerialiseContent`](i, u); + else if (void 0 !== i.content) { + let m; + s && i.content.key ? ((m = i.content.clone()), m.key.attributes.set('variable', s), (m = this.serialiseContent(m))) : (m = this.serialiseContent(i.content)), this.shouldSerialiseContent(i, m) && (u.content = m); + } else this.shouldSerialiseContent(i, i.content) && i instanceof this.namespace.elements.Array && (u.content = []); + return u; + } + shouldSerialiseContent(i, s) { + return 'parseResult' === i.element || 'httpRequest' === i.element || 'httpResponse' === i.element || 'category' === i.element || 'link' === i.element || (void 0 !== s && (!Array.isArray(s) || 0 !== s.length)); + } + refSerialiseContent(i, s) { + return delete s.attributes, { href: i.toValue(), path: i.path.toValue() }; + } + sourceMapSerialiseContent(i) { + return i.toValue(); + } + dataStructureSerialiseContent(i) { + return [this.serialiseContent(i.content)]; + } + enumSerialiseAttributes(i) { + const s = i.attributes.clone(), + u = s.remove('enumerations') || new this.namespace.elements.Array([]), + m = s.get('default'); + let v = s.get('samples') || new this.namespace.elements.Array([]); + if ( + (m && m.content && (m.content.attributes && m.content.attributes.remove('typeAttributes'), s.set('default', new this.namespace.elements.Array([m.content]))), + v.forEach((i) => { + i.content && i.content.element && i.content.attributes.remove('typeAttributes'); + }), + i.content && 0 !== u.length && v.unshift(i.content), + (v = v.map((i) => (i instanceof this.namespace.elements.Array ? [i] : new this.namespace.elements.Array([i.content])))), + v.length && s.set('samples', v), + s.length > 0) + ) + return this.serialiseObject(s); + } + enumSerialiseContent(i) { + if (i._attributes) { + const s = i.attributes.get('enumerations'); + if (s && s.length > 0) + return s.content.map((i) => { + const s = i.clone(); + return s.attributes.remove('typeAttributes'), this.serialise(s); + }); + } + if (i.content) { + const s = i.content.clone(); + return s.attributes.remove('typeAttributes'), [this.serialise(s)]; + } + return []; + } + deserialise(i) { + if ('string' == typeof i) return new this.namespace.elements.String(i); + if ('number' == typeof i) return new this.namespace.elements.Number(i); + if ('boolean' == typeof i) return new this.namespace.elements.Boolean(i); + if (null === i) return new this.namespace.elements.Null(); + if (Array.isArray(i)) return new this.namespace.elements.Array(i.map(this.deserialise, this)); + const s = this.namespace.getElementClass(i.element), + u = new s(); + u.element !== i.element && (u.element = i.element), i.meta && this.deserialiseObject(i.meta, u.meta), i.attributes && this.deserialiseObject(i.attributes, u.attributes); + const m = this.deserialiseContent(i.content); + if (((void 0 === m && null !== u.content) || (u.content = m), 'enum' === u.element)) { + u.content && u.attributes.set('enumerations', u.content); + let i = u.attributes.get('samples'); + if ((u.attributes.remove('samples'), i)) { + const m = i; + (i = new this.namespace.elements.Array()), + m.forEach((m) => { + m.forEach((m) => { + const v = new s(m); + (v.element = u.element), i.push(v); + }); + }); + const v = i.shift(); + (u.content = v ? v.content : void 0), u.attributes.set('samples', i); + } else u.content = void 0; + let m = u.attributes.get('default'); + if (m && m.length > 0) { + m = m.get(0); + const i = new s(m); + (i.element = u.element), u.attributes.set('default', i); + } + } else if ('dataStructure' === u.element && Array.isArray(u.content)) [u.content] = u.content; + else if ('category' === u.element) { + const i = u.attributes.get('meta'); + i && (u.attributes.set('metadata', i), u.attributes.remove('meta')); + } else 'member' === u.element && u.key && u.key._attributes && u.key._attributes.getValue('variable') && (u.attributes.set('variable', u.key.attributes.get('variable')), u.key.attributes.remove('variable')); + return u; + } + serialiseContent(i) { + if (i instanceof this.namespace.elements.Element) return this.serialise(i); + if (i instanceof this.namespace.KeyValuePair) { + const s = { key: this.serialise(i.key) }; + return i.value && (s.value = this.serialise(i.value)), s; + } + return i && i.map ? i.map(this.serialise, this) : i; + } + deserialiseContent(i) { + if (i) { + if (i.element) return this.deserialise(i); + if (i.key) { + const s = new this.namespace.KeyValuePair(this.deserialise(i.key)); + return i.value && (s.value = this.deserialise(i.value)), s; + } + if (i.map) return i.map(this.deserialise, this); + } + return i; + } + shouldRefract(i) { + return !!((i._attributes && i.attributes.keys().length) || (i._meta && i.meta.keys().length)) || ('enum' !== i.element && (i.element !== i.primitive() || 'member' === i.element)); + } + convertKeyToRefract(i, s) { + return ( + this.shouldRefract(s) ? this.serialise(s) + : 'enum' === s.element ? this.serialiseEnum(s) + : 'array' === s.element ? + s.map((s) => + this.shouldRefract(s) || 'default' === i ? this.serialise(s) + : 'array' === s.element || 'object' === s.element || 'enum' === s.element ? s.children.map((i) => this.serialise(i)) + : s.toValue() + ) + : 'object' === s.element ? (s.content || []).map(this.serialise, this) + : s.toValue() + ); + } + serialiseEnum(i) { + return i.children.map((i) => this.serialise(i)); + } + serialiseObject(i) { + const s = {}; + return ( + i.forEach((i, u) => { + if (i) { + const m = u.toValue(); + s[m] = this.convertKeyToRefract(m, i); + } + }), + s + ); + } + deserialiseObject(i, s) { + Object.keys(i).forEach((u) => { + s.set(u, this.deserialise(i[u])); + }); + } + }; + }, + 28219: (i) => { + i.exports = class JSONSerialiser { + constructor(i) { + this.namespace = i || new this.Namespace(); + } + serialise(i) { + if (!(i instanceof this.namespace.elements.Element)) throw new TypeError(`Given element \`${i}\` is not an Element instance`); + const s = { element: i.element }; + i._meta && i._meta.length > 0 && (s.meta = this.serialiseObject(i.meta)), i._attributes && i._attributes.length > 0 && (s.attributes = this.serialiseObject(i.attributes)); + const u = this.serialiseContent(i.content); + return void 0 !== u && (s.content = u), s; + } + deserialise(i) { + if (!i.element) throw new Error('Given value is not an object containing an element name'); + const s = new (this.namespace.getElementClass(i.element))(); + s.element !== i.element && (s.element = i.element), i.meta && this.deserialiseObject(i.meta, s.meta), i.attributes && this.deserialiseObject(i.attributes, s.attributes); + const u = this.deserialiseContent(i.content); + return (void 0 === u && null !== s.content) || (s.content = u), s; + } + serialiseContent(i) { + if (i instanceof this.namespace.elements.Element) return this.serialise(i); + if (i instanceof this.namespace.KeyValuePair) { + const s = { key: this.serialise(i.key) }; + return i.value && (s.value = this.serialise(i.value)), s; + } + if (i && i.map) { + if (0 === i.length) return; + return i.map(this.serialise, this); + } + return i; + } + deserialiseContent(i) { + if (i) { + if (i.element) return this.deserialise(i); + if (i.key) { + const s = new this.namespace.KeyValuePair(this.deserialise(i.key)); + return i.value && (s.value = this.deserialise(i.value)), s; + } + if (i.map) return i.map(this.deserialise, this); + } + return i; + } + serialiseObject(i) { + const s = {}; + if ( + (i.forEach((i, u) => { + i && (s[u.toValue()] = this.serialise(i)); + }), + 0 !== Object.keys(s).length) + ) + return s; + } + deserialiseObject(i, s) { + Object.keys(i).forEach((u) => { + s.set(u, this.deserialise(i[u])); + }); + } + }; + }, + 27418: (i) => { + 'use strict'; + var s = Object.getOwnPropertySymbols, + u = Object.prototype.hasOwnProperty, + m = Object.prototype.propertyIsEnumerable; + i.exports = + ( + (function shouldUseNative() { + try { + if (!Object.assign) return !1; + var i = new String('abc'); + if (((i[5] = 'de'), '5' === Object.getOwnPropertyNames(i)[0])) return !1; + for (var s = {}, u = 0; u < 10; u++) s['_' + String.fromCharCode(u)] = u; + if ( + '0123456789' !== + Object.getOwnPropertyNames(s) + .map(function (i) { + return s[i]; + }) + .join('') + ) + return !1; + var m = {}; + return ( + 'abcdefghijklmnopqrst'.split('').forEach(function (i) { + m[i] = i; + }), + 'abcdefghijklmnopqrst' === Object.keys(Object.assign({}, m)).join('') + ); + } catch (i) { + return !1; + } + })() + ) ? + Object.assign + : function (i, v) { + for ( + var _, + j, + M = (function toObject(i) { + if (null == i) throw new TypeError('Object.assign cannot be called with null or undefined'); + return Object(i); + })(i), + $ = 1; + $ < arguments.length; + $++ + ) { + for (var W in (_ = Object(arguments[$]))) u.call(_, W) && (M[W] = _[W]); + if (s) { + j = s(_); + for (var X = 0; X < j.length; X++) m.call(_, j[X]) && (M[j[X]] = _[j[X]]); + } + } + return M; + }; + }, + 70631: (i, s, u) => { + var m = 'function' == typeof Map && Map.prototype, + v = Object.getOwnPropertyDescriptor && m ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null, + _ = m && v && 'function' == typeof v.get ? v.get : null, + j = m && Map.prototype.forEach, + M = 'function' == typeof Set && Set.prototype, + $ = Object.getOwnPropertyDescriptor && M ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null, + W = M && $ && 'function' == typeof $.get ? $.get : null, + X = M && Set.prototype.forEach, + Y = 'function' == typeof WeakMap && WeakMap.prototype ? WeakMap.prototype.has : null, + Z = 'function' == typeof WeakSet && WeakSet.prototype ? WeakSet.prototype.has : null, + ee = 'function' == typeof WeakRef && WeakRef.prototype ? WeakRef.prototype.deref : null, + ae = Boolean.prototype.valueOf, + ie = Object.prototype.toString, + le = Function.prototype.toString, + ce = String.prototype.match, + pe = String.prototype.slice, + de = String.prototype.replace, + fe = String.prototype.toUpperCase, + ye = String.prototype.toLowerCase, + be = RegExp.prototype.test, + _e = Array.prototype.concat, + we = Array.prototype.join, + Se = Array.prototype.slice, + xe = Math.floor, + Pe = 'function' == typeof BigInt ? BigInt.prototype.valueOf : null, + Ie = Object.getOwnPropertySymbols, + Te = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? Symbol.prototype.toString : null, + Re = 'function' == typeof Symbol && 'object' == typeof Symbol.iterator, + qe = 'function' == typeof Symbol && Symbol.toStringTag && (typeof Symbol.toStringTag === Re || 'symbol') ? Symbol.toStringTag : null, + ze = Object.prototype.propertyIsEnumerable, + Ve = + ('function' == typeof Reflect ? Reflect.getPrototypeOf : Object.getPrototypeOf) || + ([].__proto__ === Array.prototype ? + function (i) { + return i.__proto__; + } + : null); + function addNumericSeparator(i, s) { + if (i === 1 / 0 || i === -1 / 0 || i != i || (i && i > -1e3 && i < 1e3) || be.call(/e/, s)) return s; + var u = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g; + if ('number' == typeof i) { + var m = i < 0 ? -xe(-i) : xe(i); + if (m !== i) { + var v = String(m), + _ = pe.call(s, v.length + 1); + return de.call(v, u, '$&_') + '.' + de.call(de.call(_, /([0-9]{3})/g, '$&_'), /_$/, ''); + } + } + return de.call(s, u, '$&_'); + } + var We = u(24654), + He = We.custom, + Xe = isSymbol(He) ? He : null; + function wrapQuotes(i, s, u) { + var m = 'double' === (u.quoteStyle || s) ? '"' : "'"; + return m + i + m; + } + function quote(i) { + return de.call(String(i), /"/g, '"'); + } + function isArray(i) { + return !('[object Array]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + } + function isRegExp(i) { + return !('[object RegExp]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + } + function isSymbol(i) { + if (Re) return i && 'object' == typeof i && i instanceof Symbol; + if ('symbol' == typeof i) return !0; + if (!i || 'object' != typeof i || !Te) return !1; + try { + return Te.call(i), !0; + } catch (i) {} + return !1; + } + i.exports = function inspect_(i, s, u, m) { + var v = s || {}; + if (has(v, 'quoteStyle') && 'single' !== v.quoteStyle && 'double' !== v.quoteStyle) throw new TypeError('option "quoteStyle" must be "single" or "double"'); + if (has(v, 'maxStringLength') && ('number' == typeof v.maxStringLength ? v.maxStringLength < 0 && v.maxStringLength !== 1 / 0 : null !== v.maxStringLength)) throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); + var M = !has(v, 'customInspect') || v.customInspect; + if ('boolean' != typeof M && 'symbol' !== M) throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`'); + if (has(v, 'indent') && null !== v.indent && '\t' !== v.indent && !(parseInt(v.indent, 10) === v.indent && v.indent > 0)) throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`'); + if (has(v, 'numericSeparator') && 'boolean' != typeof v.numericSeparator) throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`'); + var $ = v.numericSeparator; + if (void 0 === i) return 'undefined'; + if (null === i) return 'null'; + if ('boolean' == typeof i) return i ? 'true' : 'false'; + if ('string' == typeof i) return inspectString(i, v); + if ('number' == typeof i) { + if (0 === i) return 1 / 0 / i > 0 ? '0' : '-0'; + var ie = String(i); + return $ ? addNumericSeparator(i, ie) : ie; + } + if ('bigint' == typeof i) { + var fe = String(i) + 'n'; + return $ ? addNumericSeparator(i, fe) : fe; + } + var be = void 0 === v.depth ? 5 : v.depth; + if ((void 0 === u && (u = 0), u >= be && be > 0 && 'object' == typeof i)) return isArray(i) ? '[Array]' : '[Object]'; + var xe = (function getIndent(i, s) { + var u; + if ('\t' === i.indent) u = '\t'; + else { + if (!('number' == typeof i.indent && i.indent > 0)) return null; + u = we.call(Array(i.indent + 1), ' '); + } + return { base: u, prev: we.call(Array(s + 1), u) }; + })(v, u); + if (void 0 === m) m = []; + else if (indexOf(m, i) >= 0) return '[Circular]'; + function inspect(i, s, _) { + if ((s && (m = Se.call(m)).push(s), _)) { + var j = { depth: v.depth }; + return has(v, 'quoteStyle') && (j.quoteStyle = v.quoteStyle), inspect_(i, j, u + 1, m); + } + return inspect_(i, v, u + 1, m); + } + if ('function' == typeof i && !isRegExp(i)) { + var Ie = (function nameOf(i) { + if (i.name) return i.name; + var s = ce.call(le.call(i), /^function\s*([\w$]+)/); + if (s) return s[1]; + return null; + })(i), + He = arrObjKeys(i, inspect); + return '[Function' + (Ie ? ': ' + Ie : ' (anonymous)') + ']' + (He.length > 0 ? ' { ' + we.call(He, ', ') + ' }' : ''); + } + if (isSymbol(i)) { + var Ye = Re ? de.call(String(i), /^(Symbol\(.*\))_[^)]*$/, '$1') : Te.call(i); + return 'object' != typeof i || Re ? Ye : markBoxed(Ye); + } + if ( + (function isElement(i) { + if (!i || 'object' != typeof i) return !1; + if ('undefined' != typeof HTMLElement && i instanceof HTMLElement) return !0; + return 'string' == typeof i.nodeName && 'function' == typeof i.getAttribute; + })(i) + ) { + for (var Qe = '<' + ye.call(String(i.nodeName)), et = i.attributes || [], tt = 0; tt < et.length; tt++) Qe += ' ' + et[tt].name + '=' + wrapQuotes(quote(et[tt].value), 'double', v); + return (Qe += '>'), i.childNodes && i.childNodes.length && (Qe += '...'), (Qe += ''); + } + if (isArray(i)) { + if (0 === i.length) return '[]'; + var rt = arrObjKeys(i, inspect); + return ( + xe && + !(function singleLineValues(i) { + for (var s = 0; s < i.length; s++) if (indexOf(i[s], '\n') >= 0) return !1; + return !0; + })(rt) + ) ? + '[' + indentedJoin(rt, xe) + ']' + : '[ ' + we.call(rt, ', ') + ' ]'; + } + if ( + (function isError(i) { + return !('[object Error]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + })(i) + ) { + var nt = arrObjKeys(i, inspect); + return ( + 'cause' in Error.prototype || !('cause' in i) || ze.call(i, 'cause') ? + 0 === nt.length ? + '[' + String(i) + ']' + : '{ [' + String(i) + '] ' + we.call(nt, ', ') + ' }' + : '{ [' + String(i) + '] ' + we.call(_e.call('[cause]: ' + inspect(i.cause), nt), ', ') + ' }' + ); + } + if ('object' == typeof i && M) { + if (Xe && 'function' == typeof i[Xe] && We) return We(i, { depth: be - u }); + if ('symbol' !== M && 'function' == typeof i.inspect) return i.inspect(); + } + if ( + (function isMap(i) { + if (!_ || !i || 'object' != typeof i) return !1; + try { + _.call(i); + try { + W.call(i); + } catch (i) { + return !0; + } + return i instanceof Map; + } catch (i) {} + return !1; + })(i) + ) { + var ot = []; + return ( + j && + j.call(i, function (s, u) { + ot.push(inspect(u, i, !0) + ' => ' + inspect(s, i)); + }), + collectionOf('Map', _.call(i), ot, xe) + ); + } + if ( + (function isSet(i) { + if (!W || !i || 'object' != typeof i) return !1; + try { + W.call(i); + try { + _.call(i); + } catch (i) { + return !0; + } + return i instanceof Set; + } catch (i) {} + return !1; + })(i) + ) { + var at = []; + return ( + X && + X.call(i, function (s) { + at.push(inspect(s, i)); + }), + collectionOf('Set', W.call(i), at, xe) + ); + } + if ( + (function isWeakMap(i) { + if (!Y || !i || 'object' != typeof i) return !1; + try { + Y.call(i, Y); + try { + Z.call(i, Z); + } catch (i) { + return !0; + } + return i instanceof WeakMap; + } catch (i) {} + return !1; + })(i) + ) + return weakCollectionOf('WeakMap'); + if ( + (function isWeakSet(i) { + if (!Z || !i || 'object' != typeof i) return !1; + try { + Z.call(i, Z); + try { + Y.call(i, Y); + } catch (i) { + return !0; + } + return i instanceof WeakSet; + } catch (i) {} + return !1; + })(i) + ) + return weakCollectionOf('WeakSet'); + if ( + (function isWeakRef(i) { + if (!ee || !i || 'object' != typeof i) return !1; + try { + return ee.call(i), !0; + } catch (i) {} + return !1; + })(i) + ) + return weakCollectionOf('WeakRef'); + if ( + (function isNumber(i) { + return !('[object Number]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + })(i) + ) + return markBoxed(inspect(Number(i))); + if ( + (function isBigInt(i) { + if (!i || 'object' != typeof i || !Pe) return !1; + try { + return Pe.call(i), !0; + } catch (i) {} + return !1; + })(i) + ) + return markBoxed(inspect(Pe.call(i))); + if ( + (function isBoolean(i) { + return !('[object Boolean]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + })(i) + ) + return markBoxed(ae.call(i)); + if ( + (function isString(i) { + return !('[object String]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + })(i) + ) + return markBoxed(inspect(String(i))); + if ( + !(function isDate(i) { + return !('[object Date]' !== toStr(i) || (qe && 'object' == typeof i && qe in i)); + })(i) && + !isRegExp(i) + ) { + var it = arrObjKeys(i, inspect), + st = Ve ? Ve(i) === Object.prototype : i instanceof Object || i.constructor === Object, + lt = i instanceof Object ? '' : 'null prototype', + ct = + !st && qe && Object(i) === i && qe in i ? pe.call(toStr(i), 8, -1) + : lt ? 'Object' + : '', + ut = + (st || 'function' != typeof i.constructor ? '' + : i.constructor.name ? i.constructor.name + ' ' + : '') + (ct || lt ? '[' + we.call(_e.call([], ct || [], lt || []), ': ') + '] ' : ''); + return ( + 0 === it.length ? ut + '{}' + : xe ? ut + '{' + indentedJoin(it, xe) + '}' + : ut + '{ ' + we.call(it, ', ') + ' }' + ); + } + return String(i); + }; + var Ye = + Object.prototype.hasOwnProperty || + function (i) { + return i in this; + }; + function has(i, s) { + return Ye.call(i, s); + } + function toStr(i) { + return ie.call(i); + } + function indexOf(i, s) { + if (i.indexOf) return i.indexOf(s); + for (var u = 0, m = i.length; u < m; u++) if (i[u] === s) return u; + return -1; + } + function inspectString(i, s) { + if (i.length > s.maxStringLength) { + var u = i.length - s.maxStringLength, + m = '... ' + u + ' more character' + (u > 1 ? 's' : ''); + return inspectString(pe.call(i, 0, s.maxStringLength), s) + m; + } + return wrapQuotes(de.call(de.call(i, /(['\\])/g, '\\$1'), /[\x00-\x1f]/g, lowbyte), 'single', s); + } + function lowbyte(i) { + var s = i.charCodeAt(0), + u = { 8: 'b', 9: 't', 10: 'n', 12: 'f', 13: 'r' }[s]; + return u ? '\\' + u : '\\x' + (s < 16 ? '0' : '') + fe.call(s.toString(16)); + } + function markBoxed(i) { + return 'Object(' + i + ')'; + } + function weakCollectionOf(i) { + return i + ' { ? }'; + } + function collectionOf(i, s, u, m) { + return i + ' (' + s + ') {' + (m ? indentedJoin(u, m) : we.call(u, ', ')) + '}'; + } + function indentedJoin(i, s) { + if (0 === i.length) return ''; + var u = '\n' + s.prev + s.base; + return u + we.call(i, ',' + u) + '\n' + s.prev; + } + function arrObjKeys(i, s) { + var u = isArray(i), + m = []; + if (u) { + m.length = i.length; + for (var v = 0; v < i.length; v++) m[v] = has(i, v) ? s(i[v], i) : ''; + } + var _, + j = 'function' == typeof Ie ? Ie(i) : []; + if (Re) { + _ = {}; + for (var M = 0; M < j.length; M++) _['$' + j[M]] = j[M]; + } + for (var $ in i) has(i, $) && ((u && String(Number($)) === $ && $ < i.length) || (Re && _['$' + $] instanceof Symbol) || (be.call(/[^\w$]/, $) ? m.push(s($, i) + ': ' + s(i[$], i)) : m.push($ + ': ' + s(i[$], i)))); + if ('function' == typeof Ie) for (var W = 0; W < j.length; W++) ze.call(i, j[W]) && m.push('[' + s(j[W]) + ']: ' + s(i[j[W]], i)); + return m; + } + }, + 34155: (i) => { + var s, + u, + m = (i.exports = {}); + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout() { + throw new Error('clearTimeout has not been defined'); + } + function runTimeout(i) { + if (s === setTimeout) return setTimeout(i, 0); + if ((s === defaultSetTimout || !s) && setTimeout) return (s = setTimeout), setTimeout(i, 0); + try { + return s(i, 0); + } catch (u) { + try { + return s.call(null, i, 0); + } catch (u) { + return s.call(this, i, 0); + } + } + } + !(function () { + try { + s = 'function' == typeof setTimeout ? setTimeout : defaultSetTimout; + } catch (i) { + s = defaultSetTimout; + } + try { + u = 'function' == typeof clearTimeout ? clearTimeout : defaultClearTimeout; + } catch (i) { + u = defaultClearTimeout; + } + })(); + var v, + _ = [], + j = !1, + M = -1; + function cleanUpNextTick() { + j && v && ((j = !1), v.length ? (_ = v.concat(_)) : (M = -1), _.length && drainQueue()); + } + function drainQueue() { + if (!j) { + var i = runTimeout(cleanUpNextTick); + j = !0; + for (var s = _.length; s; ) { + for (v = _, _ = []; ++M < s; ) v && v[M].run(); + (M = -1), (s = _.length); + } + (v = null), + (j = !1), + (function runClearTimeout(i) { + if (u === clearTimeout) return clearTimeout(i); + if ((u === defaultClearTimeout || !u) && clearTimeout) return (u = clearTimeout), clearTimeout(i); + try { + return u(i); + } catch (s) { + try { + return u.call(null, i); + } catch (s) { + return u.call(this, i); + } + } + })(i); + } + } + function Item(i, s) { + (this.fun = i), (this.array = s); + } + function noop() {} + (m.nextTick = function (i) { + var s = new Array(arguments.length - 1); + if (arguments.length > 1) for (var u = 1; u < arguments.length; u++) s[u - 1] = arguments[u]; + _.push(new Item(i, s)), 1 !== _.length || j || runTimeout(drainQueue); + }), + (Item.prototype.run = function () { + this.fun.apply(null, this.array); + }), + (m.title = 'browser'), + (m.browser = !0), + (m.env = {}), + (m.argv = []), + (m.version = ''), + (m.versions = {}), + (m.on = noop), + (m.addListener = noop), + (m.once = noop), + (m.off = noop), + (m.removeListener = noop), + (m.removeAllListeners = noop), + (m.emit = noop), + (m.prependListener = noop), + (m.prependOnceListener = noop), + (m.listeners = function (i) { + return []; + }), + (m.binding = function (i) { + throw new Error('process.binding is not supported'); + }), + (m.cwd = function () { + return '/'; + }), + (m.chdir = function (i) { + throw new Error('process.chdir is not supported'); + }), + (m.umask = function () { + return 0; + }); + }, + 92703: (i, s, u) => { + 'use strict'; + var m = u(50414); + function emptyFunction() {} + function emptyFunctionWithReset() {} + (emptyFunctionWithReset.resetWarningCache = emptyFunction), + (i.exports = function () { + function shim(i, s, u, v, _, j) { + if (j !== m) { + var M = new Error('Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types'); + throw ((M.name = 'Invariant Violation'), M); + } + } + function getShim() { + return shim; + } + shim.isRequired = shim; + var i = { array: shim, bigint: shim, bool: shim, func: shim, number: shim, object: shim, string: shim, symbol: shim, any: shim, arrayOf: getShim, element: shim, elementType: shim, instanceOf: getShim, node: shim, objectOf: getShim, oneOf: getShim, oneOfType: getShim, shape: getShim, exact: getShim, checkPropTypes: emptyFunctionWithReset, resetWarningCache: emptyFunction }; + return (i.PropTypes = i), i; + }); + }, + 45697: (i, s, u) => { + i.exports = u(92703)(); + }, + 50414: (i) => { + 'use strict'; + i.exports = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; + }, + 55798: (i) => { + 'use strict'; + var s = String.prototype.replace, + u = /%20/g, + m = 'RFC1738', + v = 'RFC3986'; + i.exports = { + default: v, + formatters: { + RFC1738: function (i) { + return s.call(i, u, '+'); + }, + RFC3986: function (i) { + return String(i); + } + }, + RFC1738: m, + RFC3986: v + }; + }, + 80129: (i, s, u) => { + 'use strict'; + var m = u(58261), + v = u(55235), + _ = u(55798); + i.exports = { formats: _, parse: v, stringify: m }; + }, + 55235: (i, s, u) => { + 'use strict'; + var m = u(12769), + v = Object.prototype.hasOwnProperty, + _ = Array.isArray, + j = { allowDots: !1, allowPrototypes: !1, allowSparse: !1, arrayLimit: 20, charset: 'utf-8', charsetSentinel: !1, comma: !1, decoder: m.decode, delimiter: '&', depth: 5, ignoreQueryPrefix: !1, interpretNumericEntities: !1, parameterLimit: 1e3, parseArrays: !0, plainObjects: !1, strictNullHandling: !1 }, + interpretNumericEntities = function (i) { + return i.replace(/&#(\d+);/g, function (i, s) { + return String.fromCharCode(parseInt(s, 10)); + }); + }, + parseArrayValue = function (i, s) { + return i && 'string' == typeof i && s.comma && i.indexOf(',') > -1 ? i.split(',') : i; + }, + M = function parseQueryStringKeys(i, s, u, m) { + if (i) { + var _ = u.allowDots ? i.replace(/\.([^.[]+)/g, '[$1]') : i, + j = /(\[[^[\]]*])/g, + M = u.depth > 0 && /(\[[^[\]]*])/.exec(_), + $ = M ? _.slice(0, M.index) : _, + W = []; + if ($) { + if (!u.plainObjects && v.call(Object.prototype, $) && !u.allowPrototypes) return; + W.push($); + } + for (var X = 0; u.depth > 0 && null !== (M = j.exec(_)) && X < u.depth; ) { + if (((X += 1), !u.plainObjects && v.call(Object.prototype, M[1].slice(1, -1)) && !u.allowPrototypes)) return; + W.push(M[1]); + } + return ( + M && W.push('[' + _.slice(M.index) + ']'), + (function (i, s, u, m) { + for (var v = m ? s : parseArrayValue(s, u), _ = i.length - 1; _ >= 0; --_) { + var j, + M = i[_]; + if ('[]' === M && u.parseArrays) j = [].concat(v); + else { + j = u.plainObjects ? Object.create(null) : {}; + var $ = '[' === M.charAt(0) && ']' === M.charAt(M.length - 1) ? M.slice(1, -1) : M, + W = parseInt($, 10); + u.parseArrays || '' !== $ ? + !isNaN(W) && M !== $ && String(W) === $ && W >= 0 && u.parseArrays && W <= u.arrayLimit ? + ((j = [])[W] = v) + : '__proto__' !== $ && (j[$] = v) + : (j = { 0: v }); + } + v = j; + } + return v; + })(W, s, u, m) + ); + } + }; + i.exports = function (i, s) { + var u = (function normalizeParseOptions(i) { + if (!i) return j; + if (null !== i.decoder && void 0 !== i.decoder && 'function' != typeof i.decoder) throw new TypeError('Decoder has to be a function.'); + if (void 0 !== i.charset && 'utf-8' !== i.charset && 'iso-8859-1' !== i.charset) throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); + var s = void 0 === i.charset ? j.charset : i.charset; + return { allowDots: void 0 === i.allowDots ? j.allowDots : !!i.allowDots, allowPrototypes: 'boolean' == typeof i.allowPrototypes ? i.allowPrototypes : j.allowPrototypes, allowSparse: 'boolean' == typeof i.allowSparse ? i.allowSparse : j.allowSparse, arrayLimit: 'number' == typeof i.arrayLimit ? i.arrayLimit : j.arrayLimit, charset: s, charsetSentinel: 'boolean' == typeof i.charsetSentinel ? i.charsetSentinel : j.charsetSentinel, comma: 'boolean' == typeof i.comma ? i.comma : j.comma, decoder: 'function' == typeof i.decoder ? i.decoder : j.decoder, delimiter: 'string' == typeof i.delimiter || m.isRegExp(i.delimiter) ? i.delimiter : j.delimiter, depth: 'number' == typeof i.depth || !1 === i.depth ? +i.depth : j.depth, ignoreQueryPrefix: !0 === i.ignoreQueryPrefix, interpretNumericEntities: 'boolean' == typeof i.interpretNumericEntities ? i.interpretNumericEntities : j.interpretNumericEntities, parameterLimit: 'number' == typeof i.parameterLimit ? i.parameterLimit : j.parameterLimit, parseArrays: !1 !== i.parseArrays, plainObjects: 'boolean' == typeof i.plainObjects ? i.plainObjects : j.plainObjects, strictNullHandling: 'boolean' == typeof i.strictNullHandling ? i.strictNullHandling : j.strictNullHandling }; + })(s); + if ('' === i || null == i) return u.plainObjects ? Object.create(null) : {}; + for ( + var $ = + 'string' == typeof i ? + (function parseQueryStringValues(i, s) { + var u, + M = {}, + $ = s.ignoreQueryPrefix ? i.replace(/^\?/, '') : i, + W = s.parameterLimit === 1 / 0 ? void 0 : s.parameterLimit, + X = $.split(s.delimiter, W), + Y = -1, + Z = s.charset; + if (s.charsetSentinel) for (u = 0; u < X.length; ++u) 0 === X[u].indexOf('utf8=') && ('utf8=%E2%9C%93' === X[u] ? (Z = 'utf-8') : 'utf8=%26%2310003%3B' === X[u] && (Z = 'iso-8859-1'), (Y = u), (u = X.length)); + for (u = 0; u < X.length; ++u) + if (u !== Y) { + var ee, + ae, + ie = X[u], + le = ie.indexOf(']='), + ce = -1 === le ? ie.indexOf('=') : le + 1; + -1 === ce ? + ((ee = s.decoder(ie, j.decoder, Z, 'key')), (ae = s.strictNullHandling ? null : '')) + : ((ee = s.decoder(ie.slice(0, ce), j.decoder, Z, 'key')), + (ae = m.maybeMap(parseArrayValue(ie.slice(ce + 1), s), function (i) { + return s.decoder(i, j.decoder, Z, 'value'); + }))), + ae && s.interpretNumericEntities && 'iso-8859-1' === Z && (ae = interpretNumericEntities(ae)), + ie.indexOf('[]=') > -1 && (ae = _(ae) ? [ae] : ae), + v.call(M, ee) ? (M[ee] = m.combine(M[ee], ae)) : (M[ee] = ae); + } + return M; + })(i, u) + : i, + W = u.plainObjects ? Object.create(null) : {}, + X = Object.keys($), + Y = 0; + Y < X.length; + ++Y + ) { + var Z = X[Y], + ee = M(Z, $[Z], u, 'string' == typeof i); + W = m.merge(W, ee, u); + } + return !0 === u.allowSparse ? W : m.compact(W); + }; + }, + 58261: (i, s, u) => { + 'use strict'; + var m = u(37478), + v = u(12769), + _ = u(55798), + j = Object.prototype.hasOwnProperty, + M = { + brackets: function brackets(i) { + return i + '[]'; + }, + comma: 'comma', + indices: function indices(i, s) { + return i + '[' + s + ']'; + }, + repeat: function repeat(i) { + return i; + } + }, + $ = Array.isArray, + W = String.prototype.split, + X = Array.prototype.push, + pushToArray = function (i, s) { + X.apply(i, $(s) ? s : [s]); + }, + Y = Date.prototype.toISOString, + Z = _.default, + ee = { + addQueryPrefix: !1, + allowDots: !1, + charset: 'utf-8', + charsetSentinel: !1, + delimiter: '&', + encode: !0, + encoder: v.encode, + encodeValuesOnly: !1, + format: Z, + formatter: _.formatters[Z], + indices: !1, + serializeDate: function serializeDate(i) { + return Y.call(i); + }, + skipNulls: !1, + strictNullHandling: !1 + }, + ae = {}, + ie = function stringify(i, s, u, _, j, M, X, Y, Z, ie, le, ce, pe, de, fe, ye) { + for (var be = i, _e = ye, we = 0, Se = !1; void 0 !== (_e = _e.get(ae)) && !Se; ) { + var xe = _e.get(i); + if (((we += 1), void 0 !== xe)) { + if (xe === we) throw new RangeError('Cyclic object value'); + Se = !0; + } + void 0 === _e.get(ae) && (we = 0); + } + if ( + ('function' == typeof Y ? (be = Y(s, be)) + : be instanceof Date ? (be = le(be)) + : 'comma' === u && + $(be) && + (be = v.maybeMap(be, function (i) { + return i instanceof Date ? le(i) : i; + })), + null === be) + ) { + if (j) return X && !de ? X(s, ee.encoder, fe, 'key', ce) : s; + be = ''; + } + if ( + (function isNonNullishPrimitive(i) { + return 'string' == typeof i || 'number' == typeof i || 'boolean' == typeof i || 'symbol' == typeof i || 'bigint' == typeof i; + })(be) || + v.isBuffer(be) + ) { + if (X) { + var Pe = de ? s : X(s, ee.encoder, fe, 'key', ce); + if ('comma' === u && de) { + for (var Ie = W.call(String(be), ','), Te = '', Re = 0; Re < Ie.length; ++Re) Te += (0 === Re ? '' : ',') + pe(X(Ie[Re], ee.encoder, fe, 'value', ce)); + return [pe(Pe) + (_ && $(be) && 1 === Ie.length ? '[]' : '') + '=' + Te]; + } + return [pe(Pe) + '=' + pe(X(be, ee.encoder, fe, 'value', ce))]; + } + return [pe(s) + '=' + pe(String(be))]; + } + var qe, + ze = []; + if (void 0 === be) return ze; + if ('comma' === u && $(be)) qe = [{ value: be.length > 0 ? be.join(',') || null : void 0 }]; + else if ($(Y)) qe = Y; + else { + var Ve = Object.keys(be); + qe = Z ? Ve.sort(Z) : Ve; + } + for (var We = _ && $(be) && 1 === be.length ? s + '[]' : s, He = 0; He < qe.length; ++He) { + var Xe = qe[He], + Ye = 'object' == typeof Xe && void 0 !== Xe.value ? Xe.value : be[Xe]; + if (!M || null !== Ye) { + var Qe = + $(be) ? + 'function' == typeof u ? + u(We, Xe) + : We + : We + (ie ? '.' + Xe : '[' + Xe + ']'); + ye.set(i, we); + var et = m(); + et.set(ae, ye), pushToArray(ze, stringify(Ye, Qe, u, _, j, M, X, Y, Z, ie, le, ce, pe, de, fe, et)); + } + } + return ze; + }; + i.exports = function (i, s) { + var u, + v = i, + W = (function normalizeStringifyOptions(i) { + if (!i) return ee; + if (null !== i.encoder && void 0 !== i.encoder && 'function' != typeof i.encoder) throw new TypeError('Encoder has to be a function.'); + var s = i.charset || ee.charset; + if (void 0 !== i.charset && 'utf-8' !== i.charset && 'iso-8859-1' !== i.charset) throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); + var u = _.default; + if (void 0 !== i.format) { + if (!j.call(_.formatters, i.format)) throw new TypeError('Unknown format option provided.'); + u = i.format; + } + var m = _.formatters[u], + v = ee.filter; + return ('function' == typeof i.filter || $(i.filter)) && (v = i.filter), { addQueryPrefix: 'boolean' == typeof i.addQueryPrefix ? i.addQueryPrefix : ee.addQueryPrefix, allowDots: void 0 === i.allowDots ? ee.allowDots : !!i.allowDots, charset: s, charsetSentinel: 'boolean' == typeof i.charsetSentinel ? i.charsetSentinel : ee.charsetSentinel, delimiter: void 0 === i.delimiter ? ee.delimiter : i.delimiter, encode: 'boolean' == typeof i.encode ? i.encode : ee.encode, encoder: 'function' == typeof i.encoder ? i.encoder : ee.encoder, encodeValuesOnly: 'boolean' == typeof i.encodeValuesOnly ? i.encodeValuesOnly : ee.encodeValuesOnly, filter: v, format: u, formatter: m, serializeDate: 'function' == typeof i.serializeDate ? i.serializeDate : ee.serializeDate, skipNulls: 'boolean' == typeof i.skipNulls ? i.skipNulls : ee.skipNulls, sort: 'function' == typeof i.sort ? i.sort : null, strictNullHandling: 'boolean' == typeof i.strictNullHandling ? i.strictNullHandling : ee.strictNullHandling }; + })(s); + 'function' == typeof W.filter ? (v = (0, W.filter)('', v)) : $(W.filter) && (u = W.filter); + var X, + Y = []; + if ('object' != typeof v || null === v) return ''; + X = + s && s.arrayFormat in M ? s.arrayFormat + : s && 'indices' in s ? + s.indices ? + 'indices' + : 'repeat' + : 'indices'; + var Z = M[X]; + if (s && 'commaRoundTrip' in s && 'boolean' != typeof s.commaRoundTrip) throw new TypeError('`commaRoundTrip` must be a boolean, or absent'); + var ae = 'comma' === Z && s && s.commaRoundTrip; + u || (u = Object.keys(v)), W.sort && u.sort(W.sort); + for (var le = m(), ce = 0; ce < u.length; ++ce) { + var pe = u[ce]; + (W.skipNulls && null === v[pe]) || pushToArray(Y, ie(v[pe], pe, Z, ae, W.strictNullHandling, W.skipNulls, W.encode ? W.encoder : null, W.filter, W.sort, W.allowDots, W.serializeDate, W.format, W.formatter, W.encodeValuesOnly, W.charset, le)); + } + var de = Y.join(W.delimiter), + fe = !0 === W.addQueryPrefix ? '?' : ''; + return W.charsetSentinel && ('iso-8859-1' === W.charset ? (fe += 'utf8=%26%2310003%3B&') : (fe += 'utf8=%E2%9C%93&')), de.length > 0 ? fe + de : ''; + }; + }, + 12769: (i, s, u) => { + 'use strict'; + var m = u(55798), + v = Object.prototype.hasOwnProperty, + _ = Array.isArray, + j = (function () { + for (var i = [], s = 0; s < 256; ++s) i.push('%' + ((s < 16 ? '0' : '') + s.toString(16)).toUpperCase()); + return i; + })(), + M = function arrayToObject(i, s) { + for (var u = s && s.plainObjects ? Object.create(null) : {}, m = 0; m < i.length; ++m) void 0 !== i[m] && (u[m] = i[m]); + return u; + }; + i.exports = { + arrayToObject: M, + assign: function assignSingleSource(i, s) { + return Object.keys(s).reduce(function (i, u) { + return (i[u] = s[u]), i; + }, i); + }, + combine: function combine(i, s) { + return [].concat(i, s); + }, + compact: function compact(i) { + for (var s = [{ obj: { o: i }, prop: 'o' }], u = [], m = 0; m < s.length; ++m) + for (var v = s[m], j = v.obj[v.prop], M = Object.keys(j), $ = 0; $ < M.length; ++$) { + var W = M[$], + X = j[W]; + 'object' == typeof X && null !== X && -1 === u.indexOf(X) && (s.push({ obj: j, prop: W }), u.push(X)); + } + return ( + (function compactQueue(i) { + for (; i.length > 1; ) { + var s = i.pop(), + u = s.obj[s.prop]; + if (_(u)) { + for (var m = [], v = 0; v < u.length; ++v) void 0 !== u[v] && m.push(u[v]); + s.obj[s.prop] = m; + } + } + })(s), + i + ); + }, + decode: function (i, s, u) { + var m = i.replace(/\+/g, ' '); + if ('iso-8859-1' === u) return m.replace(/%[0-9a-f]{2}/gi, unescape); + try { + return decodeURIComponent(m); + } catch (i) { + return m; + } + }, + encode: function encode(i, s, u, v, _) { + if (0 === i.length) return i; + var M = i; + if (('symbol' == typeof i ? (M = Symbol.prototype.toString.call(i)) : 'string' != typeof i && (M = String(i)), 'iso-8859-1' === u)) + return escape(M).replace(/%u[0-9a-f]{4}/gi, function (i) { + return '%26%23' + parseInt(i.slice(2), 16) + '%3B'; + }); + for (var $ = '', W = 0; W < M.length; ++W) { + var X = M.charCodeAt(W); + 45 === X || 46 === X || 95 === X || 126 === X || (X >= 48 && X <= 57) || (X >= 65 && X <= 90) || (X >= 97 && X <= 122) || (_ === m.RFC1738 && (40 === X || 41 === X)) ? ($ += M.charAt(W)) + : X < 128 ? ($ += j[X]) + : X < 2048 ? ($ += j[192 | (X >> 6)] + j[128 | (63 & X)]) + : X < 55296 || X >= 57344 ? ($ += j[224 | (X >> 12)] + j[128 | ((X >> 6) & 63)] + j[128 | (63 & X)]) + : ((W += 1), (X = 65536 + (((1023 & X) << 10) | (1023 & M.charCodeAt(W)))), ($ += j[240 | (X >> 18)] + j[128 | ((X >> 12) & 63)] + j[128 | ((X >> 6) & 63)] + j[128 | (63 & X)])); + } + return $; + }, + isBuffer: function isBuffer(i) { + return !(!i || 'object' != typeof i) && !!(i.constructor && i.constructor.isBuffer && i.constructor.isBuffer(i)); + }, + isRegExp: function isRegExp(i) { + return '[object RegExp]' === Object.prototype.toString.call(i); + }, + maybeMap: function maybeMap(i, s) { + if (_(i)) { + for (var u = [], m = 0; m < i.length; m += 1) u.push(s(i[m])); + return u; + } + return s(i); + }, + merge: function merge(i, s, u) { + if (!s) return i; + if ('object' != typeof s) { + if (_(i)) i.push(s); + else { + if (!i || 'object' != typeof i) return [i, s]; + ((u && (u.plainObjects || u.allowPrototypes)) || !v.call(Object.prototype, s)) && (i[s] = !0); + } + return i; + } + if (!i || 'object' != typeof i) return [i].concat(s); + var m = i; + return ( + _(i) && !_(s) && (m = M(i, u)), + _(i) && _(s) ? + (s.forEach(function (s, m) { + if (v.call(i, m)) { + var _ = i[m]; + _ && 'object' == typeof _ && s && 'object' == typeof s ? (i[m] = merge(_, s, u)) : i.push(s); + } else i[m] = s; + }), + i) + : Object.keys(s).reduce(function (i, m) { + var _ = s[m]; + return v.call(i, m) ? (i[m] = merge(i[m], _, u)) : (i[m] = _), i; + }, m) + ); + } + }; + }, + 57129: (i, s) => { + 'use strict'; + var u = Object.prototype.hasOwnProperty; + function decode(i) { + try { + return decodeURIComponent(i.replace(/\+/g, ' ')); + } catch (i) { + return null; + } + } + function encode(i) { + try { + return encodeURIComponent(i); + } catch (i) { + return null; + } + } + (s.stringify = function querystringify(i, s) { + s = s || ''; + var m, + v, + _ = []; + for (v in ('string' != typeof s && (s = '?'), i)) + if (u.call(i, v)) { + if (((m = i[v]) || (null != m && !isNaN(m)) || (m = ''), (v = encode(v)), (m = encode(m)), null === v || null === m)) continue; + _.push(v + '=' + m); + } + return _.length ? s + _.join('&') : ''; + }), + (s.parse = function querystring(i) { + for (var s, u = /([^=?#&]+)=?([^&]*)/g, m = {}; (s = u.exec(i)); ) { + var v = decode(s[1]), + _ = decode(s[2]); + null === v || null === _ || v in m || (m[v] = _); + } + return m; + }); + }, + 14419: (i, s, u) => { + const m = u(60697), + v = u(69450), + _ = m.types; + i.exports = class RandExp { + constructor(i, s) { + if ((this._setDefaults(i), i instanceof RegExp)) (this.ignoreCase = i.ignoreCase), (this.multiline = i.multiline), (i = i.source); + else { + if ('string' != typeof i) throw new Error('Expected a regexp or string'); + (this.ignoreCase = s && -1 !== s.indexOf('i')), (this.multiline = s && -1 !== s.indexOf('m')); + } + this.tokens = m(i); + } + _setDefaults(i) { + (this.max = + null != i.max ? i.max + : null != RandExp.prototype.max ? RandExp.prototype.max + : 100), + (this.defaultRange = i.defaultRange ? i.defaultRange : this.defaultRange.clone()), + i.randInt && (this.randInt = i.randInt); + } + gen() { + return this._gen(this.tokens, []); + } + _gen(i, s) { + var u, m, v, j, M; + switch (i.type) { + case _.ROOT: + case _.GROUP: + if (i.followedBy || i.notFollowedBy) return ''; + for (i.remember && void 0 === i.groupNumber && (i.groupNumber = s.push(null) - 1), m = '', j = 0, M = (u = i.options ? this._randSelect(i.options) : i.stack).length; j < M; j++) m += this._gen(u[j], s); + return i.remember && (s[i.groupNumber] = m), m; + case _.POSITION: + return ''; + case _.SET: + var $ = this._expand(i); + return $.length ? String.fromCharCode(this._randSelect($)) : ''; + case _.REPETITION: + for (v = this.randInt(i.min, i.max === 1 / 0 ? i.min + this.max : i.max), m = '', j = 0; j < v; j++) m += this._gen(i.value, s); + return m; + case _.REFERENCE: + return s[i.value - 1] || ''; + case _.CHAR: + var W = this.ignoreCase && this._randBool() ? this._toOtherCase(i.value) : i.value; + return String.fromCharCode(W); + } + } + _toOtherCase(i) { + return ( + i + + (97 <= i && i <= 122 ? -32 + : 65 <= i && i <= 90 ? 32 + : 0) + ); + } + _randBool() { + return !this.randInt(0, 1); + } + _randSelect(i) { + return i instanceof v ? i.index(this.randInt(0, i.length - 1)) : i[this.randInt(0, i.length - 1)]; + } + _expand(i) { + if (i.type === m.types.CHAR) return new v(i.value); + if (i.type === m.types.RANGE) return new v(i.from, i.to); + { + let s = new v(); + for (let u = 0; u < i.set.length; u++) { + let m = this._expand(i.set[u]); + if ((s.add(m), this.ignoreCase)) + for (let i = 0; i < m.length; i++) { + let u = m.index(i), + v = this._toOtherCase(u); + u !== v && s.add(v); + } + } + return i.not ? this.defaultRange.clone().subtract(s) : this.defaultRange.clone().intersect(s); + } + } + randInt(i, s) { + return i + Math.floor(Math.random() * (1 + s - i)); + } + get defaultRange() { + return (this._range = this._range || new v(32, 126)); + } + set defaultRange(i) { + this._range = i; + } + static randexp(i, s) { + var u; + return 'string' == typeof i && (i = new RegExp(i, s)), void 0 === i._randexp ? ((u = new RandExp(i, s)), (i._randexp = u)) : (u = i._randexp)._setDefaults(i), u.gen(); + } + static sugar() { + RegExp.prototype.gen = function () { + return RandExp.randexp(this); + }; + } + }; + }, + 61798: (i, s, u) => { + 'use strict'; + var m = u(34155), + v = 65536, + _ = 4294967295; + var j = u(89509).Buffer, + M = u.g.crypto || u.g.msCrypto; + M && M.getRandomValues ? + (i.exports = function randomBytes(i, s) { + if (i > _) throw new RangeError('requested too many random bytes'); + var u = j.allocUnsafe(i); + if (i > 0) + if (i > v) for (var $ = 0; $ < i; $ += v) M.getRandomValues(u.slice($, $ + v)); + else M.getRandomValues(u); + if ('function' == typeof s) + return m.nextTick(function () { + s(null, u); + }); + return u; + }) + : (i.exports = function oldBrowser() { + throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11'); + }); + }, + 74300: (i, s, u) => { + 'use strict'; + function _typeof(i) { + return ( + (_typeof = + 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? + function (i) { + return typeof i; + } + : function (i) { + return i && 'function' == typeof Symbol && i.constructor === Symbol && i !== Symbol.prototype ? 'symbol' : typeof i; + }), + _typeof(i) + ); + } + Object.defineProperty(s, '__esModule', { value: !0 }), (s.CopyToClipboard = void 0); + var m = _interopRequireDefault(u(67294)), + v = _interopRequireDefault(u(20640)), + _ = ['text', 'onCopy', 'options', 'children']; + function _interopRequireDefault(i) { + return i && i.__esModule ? i : { default: i }; + } + function ownKeys(i, s) { + var u = Object.keys(i); + if (Object.getOwnPropertySymbols) { + var m = Object.getOwnPropertySymbols(i); + s && + (m = m.filter(function (s) { + return Object.getOwnPropertyDescriptor(i, s).enumerable; + })), + u.push.apply(u, m); + } + return u; + } + function _objectSpread(i) { + for (var s = 1; s < arguments.length; s++) { + var u = null != arguments[s] ? arguments[s] : {}; + s % 2 ? + ownKeys(Object(u), !0).forEach(function (s) { + _defineProperty(i, s, u[s]); + }) + : Object.getOwnPropertyDescriptors ? Object.defineProperties(i, Object.getOwnPropertyDescriptors(u)) + : ownKeys(Object(u)).forEach(function (s) { + Object.defineProperty(i, s, Object.getOwnPropertyDescriptor(u, s)); + }); + } + return i; + } + function _objectWithoutProperties(i, s) { + if (null == i) return {}; + var u, + m, + v = (function _objectWithoutPropertiesLoose(i, s) { + if (null == i) return {}; + var u, + m, + v = {}, + _ = Object.keys(i); + for (m = 0; m < _.length; m++) (u = _[m]), s.indexOf(u) >= 0 || (v[u] = i[u]); + return v; + })(i, s); + if (Object.getOwnPropertySymbols) { + var _ = Object.getOwnPropertySymbols(i); + for (m = 0; m < _.length; m++) (u = _[m]), s.indexOf(u) >= 0 || (Object.prototype.propertyIsEnumerable.call(i, u) && (v[u] = i[u])); + } + return v; + } + function _defineProperties(i, s) { + for (var u = 0; u < s.length; u++) { + var m = s[u]; + (m.enumerable = m.enumerable || !1), (m.configurable = !0), 'value' in m && (m.writable = !0), Object.defineProperty(i, m.key, m); + } + } + function _setPrototypeOf(i, s) { + return ( + (_setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(i, s) { + return (i.__proto__ = s), i; + }), + _setPrototypeOf(i, s) + ); + } + function _createSuper(i) { + var s = (function _isNativeReflectConstruct() { + if ('undefined' == typeof Reflect || !Reflect.construct) return !1; + if (Reflect.construct.sham) return !1; + if ('function' == typeof Proxy) return !0; + try { + return Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})), !0; + } catch (i) { + return !1; + } + })(); + return function _createSuperInternal() { + var u, + m = _getPrototypeOf(i); + if (s) { + var v = _getPrototypeOf(this).constructor; + u = Reflect.construct(m, arguments, v); + } else u = m.apply(this, arguments); + return (function _possibleConstructorReturn(i, s) { + if (s && ('object' === _typeof(s) || 'function' == typeof s)) return s; + if (void 0 !== s) throw new TypeError('Derived constructors may only return object or undefined'); + return _assertThisInitialized(i); + })(this, u); + }; + } + function _assertThisInitialized(i) { + if (void 0 === i) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return i; + } + function _getPrototypeOf(i) { + return ( + (_getPrototypeOf = + Object.setPrototypeOf ? + Object.getPrototypeOf + : function _getPrototypeOf(i) { + return i.__proto__ || Object.getPrototypeOf(i); + }), + _getPrototypeOf(i) + ); + } + function _defineProperty(i, s, u) { + return s in i ? Object.defineProperty(i, s, { value: u, enumerable: !0, configurable: !0, writable: !0 }) : (i[s] = u), i; + } + var j = (function (i) { + !(function _inherits(i, s) { + if ('function' != typeof s && null !== s) throw new TypeError('Super expression must either be null or a function'); + (i.prototype = Object.create(s && s.prototype, { constructor: { value: i, writable: !0, configurable: !0 } })), Object.defineProperty(i, 'prototype', { writable: !1 }), s && _setPrototypeOf(i, s); + })(CopyToClipboard, i); + var s = _createSuper(CopyToClipboard); + function CopyToClipboard() { + var i; + !(function _classCallCheck(i, s) { + if (!(i instanceof s)) throw new TypeError('Cannot call a class as a function'); + })(this, CopyToClipboard); + for (var u = arguments.length, _ = new Array(u), j = 0; j < u; j++) _[j] = arguments[j]; + return ( + _defineProperty(_assertThisInitialized((i = s.call.apply(s, [this].concat(_)))), 'onClick', function (s) { + var u = i.props, + _ = u.text, + j = u.onCopy, + M = u.children, + $ = u.options, + W = m.default.Children.only(M), + X = (0, v.default)(_, $); + j && j(_, X), W && W.props && 'function' == typeof W.props.onClick && W.props.onClick(s); + }), + i + ); + } + return ( + (function _createClass(i, s, u) { + return s && _defineProperties(i.prototype, s), u && _defineProperties(i, u), Object.defineProperty(i, 'prototype', { writable: !1 }), i; + })(CopyToClipboard, [ + { + key: 'render', + value: function render() { + var i = this.props, + s = (i.text, i.onCopy, i.options, i.children), + u = _objectWithoutProperties(i, _), + v = m.default.Children.only(s); + return m.default.cloneElement(v, _objectSpread(_objectSpread({}, u), {}, { onClick: this.onClick })); + } + } + ]), + CopyToClipboard + ); + })(m.default.PureComponent); + (s.CopyToClipboard = j), _defineProperty(j, 'defaultProps', { onCopy: void 0, options: void 0 }); + }, + 74855: (i, s, u) => { + 'use strict'; + var m = u(74300).CopyToClipboard; + (m.CopyToClipboard = m), (i.exports = m); + }, + 53441: (i, s, u) => { + 'use strict'; + function _typeof(i) { + return ( + (_typeof = + 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? + function (i) { + return typeof i; + } + : function (i) { + return i && 'function' == typeof Symbol && i.constructor === Symbol && i !== Symbol.prototype ? 'symbol' : typeof i; + }), + _typeof(i) + ); + } + Object.defineProperty(s, '__esModule', { value: !0 }), (s.DebounceInput = void 0); + var m = _interopRequireDefault(u(67294)), + v = _interopRequireDefault(u(91296)), + _ = ['element', 'onChange', 'value', 'minLength', 'debounceTimeout', 'forceNotifyByEnter', 'forceNotifyOnBlur', 'onKeyDown', 'onBlur', 'inputRef']; + function _interopRequireDefault(i) { + return i && i.__esModule ? i : { default: i }; + } + function _objectWithoutProperties(i, s) { + if (null == i) return {}; + var u, + m, + v = (function _objectWithoutPropertiesLoose(i, s) { + if (null == i) return {}; + var u, + m, + v = {}, + _ = Object.keys(i); + for (m = 0; m < _.length; m++) (u = _[m]), s.indexOf(u) >= 0 || (v[u] = i[u]); + return v; + })(i, s); + if (Object.getOwnPropertySymbols) { + var _ = Object.getOwnPropertySymbols(i); + for (m = 0; m < _.length; m++) (u = _[m]), s.indexOf(u) >= 0 || (Object.prototype.propertyIsEnumerable.call(i, u) && (v[u] = i[u])); + } + return v; + } + function ownKeys(i, s) { + var u = Object.keys(i); + if (Object.getOwnPropertySymbols) { + var m = Object.getOwnPropertySymbols(i); + s && + (m = m.filter(function (s) { + return Object.getOwnPropertyDescriptor(i, s).enumerable; + })), + u.push.apply(u, m); + } + return u; + } + function _objectSpread(i) { + for (var s = 1; s < arguments.length; s++) { + var u = null != arguments[s] ? arguments[s] : {}; + s % 2 ? + ownKeys(Object(u), !0).forEach(function (s) { + _defineProperty(i, s, u[s]); + }) + : Object.getOwnPropertyDescriptors ? Object.defineProperties(i, Object.getOwnPropertyDescriptors(u)) + : ownKeys(Object(u)).forEach(function (s) { + Object.defineProperty(i, s, Object.getOwnPropertyDescriptor(u, s)); + }); + } + return i; + } + function _defineProperties(i, s) { + for (var u = 0; u < s.length; u++) { + var m = s[u]; + (m.enumerable = m.enumerable || !1), (m.configurable = !0), 'value' in m && (m.writable = !0), Object.defineProperty(i, m.key, m); + } + } + function _setPrototypeOf(i, s) { + return ( + (_setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(i, s) { + return (i.__proto__ = s), i; + }), + _setPrototypeOf(i, s) + ); + } + function _createSuper(i) { + var s = (function _isNativeReflectConstruct() { + if ('undefined' == typeof Reflect || !Reflect.construct) return !1; + if (Reflect.construct.sham) return !1; + if ('function' == typeof Proxy) return !0; + try { + return Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})), !0; + } catch (i) { + return !1; + } + })(); + return function _createSuperInternal() { + var u, + m = _getPrototypeOf(i); + if (s) { + var v = _getPrototypeOf(this).constructor; + u = Reflect.construct(m, arguments, v); + } else u = m.apply(this, arguments); + return (function _possibleConstructorReturn(i, s) { + if (s && ('object' === _typeof(s) || 'function' == typeof s)) return s; + if (void 0 !== s) throw new TypeError('Derived constructors may only return object or undefined'); + return _assertThisInitialized(i); + })(this, u); + }; + } + function _assertThisInitialized(i) { + if (void 0 === i) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return i; + } + function _getPrototypeOf(i) { + return ( + (_getPrototypeOf = + Object.setPrototypeOf ? + Object.getPrototypeOf + : function _getPrototypeOf(i) { + return i.__proto__ || Object.getPrototypeOf(i); + }), + _getPrototypeOf(i) + ); + } + function _defineProperty(i, s, u) { + return s in i ? Object.defineProperty(i, s, { value: u, enumerable: !0, configurable: !0, writable: !0 }) : (i[s] = u), i; + } + var j = (function (i) { + !(function _inherits(i, s) { + if ('function' != typeof s && null !== s) throw new TypeError('Super expression must either be null or a function'); + (i.prototype = Object.create(s && s.prototype, { constructor: { value: i, writable: !0, configurable: !0 } })), Object.defineProperty(i, 'prototype', { writable: !1 }), s && _setPrototypeOf(i, s); + })(DebounceInput, i); + var s = _createSuper(DebounceInput); + function DebounceInput(i) { + var u; + !(function _classCallCheck(i, s) { + if (!(i instanceof s)) throw new TypeError('Cannot call a class as a function'); + })(this, DebounceInput), + _defineProperty(_assertThisInitialized((u = s.call(this, i))), 'onChange', function (i) { + i.persist(); + var s = u.state.value, + m = u.props.minLength; + u.setState({ value: i.target.value }, function () { + var v = u.state.value; + v.length >= m ? u.notify(i) : s.length > v.length && u.notify(_objectSpread(_objectSpread({}, i), {}, { target: _objectSpread(_objectSpread({}, i.target), {}, { value: '' }) })); + }); + }), + _defineProperty(_assertThisInitialized(u), 'onKeyDown', function (i) { + 'Enter' === i.key && u.forceNotify(i); + var s = u.props.onKeyDown; + s && (i.persist(), s(i)); + }), + _defineProperty(_assertThisInitialized(u), 'onBlur', function (i) { + u.forceNotify(i); + var s = u.props.onBlur; + s && (i.persist(), s(i)); + }), + _defineProperty(_assertThisInitialized(u), 'createNotifier', function (i) { + if (i < 0) + u.notify = function () { + return null; + }; + else if (0 === i) u.notify = u.doNotify; + else { + var s = (0, v.default)(function (i) { + (u.isDebouncing = !1), u.doNotify(i); + }, i); + (u.notify = function (i) { + (u.isDebouncing = !0), s(i); + }), + (u.flush = function () { + return s.flush(); + }), + (u.cancel = function () { + (u.isDebouncing = !1), s.cancel(); + }); + } + }), + _defineProperty(_assertThisInitialized(u), 'doNotify', function () { + u.props.onChange.apply(void 0, arguments); + }), + _defineProperty(_assertThisInitialized(u), 'forceNotify', function (i) { + var s = u.props.debounceTimeout; + if (u.isDebouncing || !(s > 0)) { + u.cancel && u.cancel(); + var m = u.state.value, + v = u.props.minLength; + m.length >= v ? u.doNotify(i) : u.doNotify(_objectSpread(_objectSpread({}, i), {}, { target: _objectSpread(_objectSpread({}, i.target), {}, { value: m }) })); + } + }), + (u.isDebouncing = !1), + (u.state = { value: void 0 === i.value || null === i.value ? '' : i.value }); + var m = u.props.debounceTimeout; + return u.createNotifier(m), u; + } + return ( + (function _createClass(i, s, u) { + return s && _defineProperties(i.prototype, s), u && _defineProperties(i, u), Object.defineProperty(i, 'prototype', { writable: !1 }), i; + })(DebounceInput, [ + { + key: 'componentDidUpdate', + value: function componentDidUpdate(i) { + if (!this.isDebouncing) { + var s = this.props, + u = s.value, + m = s.debounceTimeout, + v = i.debounceTimeout, + _ = i.value, + j = this.state.value; + void 0 !== u && _ !== u && j !== u && this.setState({ value: u }), m !== v && this.createNotifier(m); + } + } + }, + { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + this.flush && this.flush(); + } + }, + { + key: 'render', + value: function render() { + var i, + s, + u = this.props, + v = u.element, + j = (u.onChange, u.value, u.minLength, u.debounceTimeout, u.forceNotifyByEnter), + M = u.forceNotifyOnBlur, + $ = u.onKeyDown, + W = u.onBlur, + X = u.inputRef, + Y = _objectWithoutProperties(u, _), + Z = this.state.value; + (i = + j ? { onKeyDown: this.onKeyDown } + : $ ? { onKeyDown: $ } + : {}), + (s = + M ? { onBlur: this.onBlur } + : W ? { onBlur: W } + : {}); + var ee = X ? { ref: X } : {}; + return m.default.createElement(v, _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, Y), {}, { onChange: this.onChange, value: Z }, i), s), ee)); + } + } + ]), + DebounceInput + ); + })(m.default.PureComponent); + (s.DebounceInput = j), _defineProperty(j, 'defaultProps', { element: 'input', type: 'text', onKeyDown: void 0, onBlur: void 0, value: void 0, minLength: 0, debounceTimeout: 100, forceNotifyByEnter: !0, forceNotifyOnBlur: !0, inputRef: void 0 }); + }, + 775: (i, s, u) => { + 'use strict'; + var m = u(53441).DebounceInput; + (m.DebounceInput = m), (i.exports = m); + }, + 64448: (i, s, u) => { + 'use strict'; + var m = u(67294), + v = u(27418), + _ = u(63840); + function y(i) { + for (var s = 'https://reactjs.org/docs/error-decoder.html?invariant=' + i, u = 1; u < arguments.length; u++) s += '&args[]=' + encodeURIComponent(arguments[u]); + return 'Minified React error #' + i + '; visit ' + s + ' for the full message or use the non-minified dev environment for full errors and additional helpful warnings.'; + } + if (!m) throw Error(y(227)); + var j = new Set(), + M = {}; + function da(i, s) { + ea(i, s), ea(i + 'Capture', s); + } + function ea(i, s) { + for (M[i] = s, i = 0; i < s.length; i++) j.add(s[i]); + } + var $ = !('undefined' == typeof window || void 0 === window.document || void 0 === window.document.createElement), + W = /^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/, + X = Object.prototype.hasOwnProperty, + Y = {}, + Z = {}; + function B(i, s, u, m, v, _, j) { + (this.acceptsBooleans = 2 === s || 3 === s || 4 === s), (this.attributeName = m), (this.attributeNamespace = v), (this.mustUseProperty = u), (this.propertyName = i), (this.type = s), (this.sanitizeURL = _), (this.removeEmptyString = j); + } + var ee = {}; + 'children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style'.split(' ').forEach(function (i) { + ee[i] = new B(i, 0, !1, i, null, !1, !1); + }), + [ + ['acceptCharset', 'accept-charset'], + ['className', 'class'], + ['htmlFor', 'for'], + ['httpEquiv', 'http-equiv'] + ].forEach(function (i) { + var s = i[0]; + ee[s] = new B(s, 1, !1, i[1], null, !1, !1); + }), + ['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (i) { + ee[i] = new B(i, 2, !1, i.toLowerCase(), null, !1, !1); + }), + ['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (i) { + ee[i] = new B(i, 2, !1, i, null, !1, !1); + }), + 'allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope'.split(' ').forEach(function (i) { + ee[i] = new B(i, 3, !1, i.toLowerCase(), null, !1, !1); + }), + ['checked', 'multiple', 'muted', 'selected'].forEach(function (i) { + ee[i] = new B(i, 3, !0, i, null, !1, !1); + }), + ['capture', 'download'].forEach(function (i) { + ee[i] = new B(i, 4, !1, i, null, !1, !1); + }), + ['cols', 'rows', 'size', 'span'].forEach(function (i) { + ee[i] = new B(i, 6, !1, i, null, !1, !1); + }), + ['rowSpan', 'start'].forEach(function (i) { + ee[i] = new B(i, 5, !1, i.toLowerCase(), null, !1, !1); + }); + var ae = /[\-:]([a-z])/g; + function pa(i) { + return i[1].toUpperCase(); + } + function qa(i, s, u, m) { + var v = ee.hasOwnProperty(s) ? ee[s] : null; + (null !== v ? 0 === v.type : !m && 2 < s.length && ('o' === s[0] || 'O' === s[0]) && ('n' === s[1] || 'N' === s[1])) || + ((function na(i, s, u, m) { + if ( + null == s || + (function ma(i, s, u, m) { + if (null !== u && 0 === u.type) return !1; + switch (typeof s) { + case 'function': + case 'symbol': + return !0; + case 'boolean': + return !m && (null !== u ? !u.acceptsBooleans : 'data-' !== (i = i.toLowerCase().slice(0, 5)) && 'aria-' !== i); + default: + return !1; + } + })(i, s, u, m) + ) + return !0; + if (m) return !1; + if (null !== u) + switch (u.type) { + case 3: + return !s; + case 4: + return !1 === s; + case 5: + return isNaN(s); + case 6: + return isNaN(s) || 1 > s; + } + return !1; + })(s, u, v, m) && (u = null), + m || null === v ? + (function la(i) { + return !!X.call(Z, i) || (!X.call(Y, i) && (W.test(i) ? (Z[i] = !0) : ((Y[i] = !0), !1))); + })(s) && (null === u ? i.removeAttribute(s) : i.setAttribute(s, '' + u)) + : v.mustUseProperty ? (i[v.propertyName] = null === u ? 3 !== v.type && '' : u) + : ((s = v.attributeName), (m = v.attributeNamespace), null === u ? i.removeAttribute(s) : ((u = 3 === (v = v.type) || (4 === v && !0 === u) ? '' : '' + u), m ? i.setAttributeNS(m, s, u) : i.setAttribute(s, u)))); + } + 'accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height'.split(' ').forEach(function (i) { + var s = i.replace(ae, pa); + ee[s] = new B(s, 1, !1, i, null, !1, !1); + }), + 'xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type'.split(' ').forEach(function (i) { + var s = i.replace(ae, pa); + ee[s] = new B(s, 1, !1, i, 'http://www.w3.org/1999/xlink', !1, !1); + }), + ['xml:base', 'xml:lang', 'xml:space'].forEach(function (i) { + var s = i.replace(ae, pa); + ee[s] = new B(s, 1, !1, i, 'http://www.w3.org/XML/1998/namespace', !1, !1); + }), + ['tabIndex', 'crossOrigin'].forEach(function (i) { + ee[i] = new B(i, 1, !1, i.toLowerCase(), null, !1, !1); + }), + (ee.xlinkHref = new B('xlinkHref', 1, !1, 'xlink:href', 'http://www.w3.org/1999/xlink', !0, !1)), + ['src', 'href', 'action', 'formAction'].forEach(function (i) { + ee[i] = new B(i, 1, !1, i.toLowerCase(), null, !0, !0); + }); + var ie = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + le = 60103, + ce = 60106, + pe = 60107, + de = 60108, + fe = 60114, + ye = 60109, + be = 60110, + _e = 60112, + we = 60113, + Se = 60120, + xe = 60115, + Pe = 60116, + Ie = 60121, + Te = 60128, + Re = 60129, + qe = 60130, + ze = 60131; + if ('function' == typeof Symbol && Symbol.for) { + var Ve = Symbol.for; + (le = Ve('react.element')), (ce = Ve('react.portal')), (pe = Ve('react.fragment')), (de = Ve('react.strict_mode')), (fe = Ve('react.profiler')), (ye = Ve('react.provider')), (be = Ve('react.context')), (_e = Ve('react.forward_ref')), (we = Ve('react.suspense')), (Se = Ve('react.suspense_list')), (xe = Ve('react.memo')), (Pe = Ve('react.lazy')), (Ie = Ve('react.block')), Ve('react.scope'), (Te = Ve('react.opaque.id')), (Re = Ve('react.debug_trace_mode')), (qe = Ve('react.offscreen')), (ze = Ve('react.legacy_hidden')); + } + var We, + He = 'function' == typeof Symbol && Symbol.iterator; + function La(i) { + return ( + null === i || 'object' != typeof i ? null + : 'function' == typeof (i = (He && i[He]) || i['@@iterator']) ? i + : null + ); + } + function Na(i) { + if (void 0 === We) + try { + throw Error(); + } catch (i) { + var s = i.stack.trim().match(/\n( *(at )?)/); + We = (s && s[1]) || ''; + } + return '\n' + We + i; + } + var Xe = !1; + function Pa(i, s) { + if (!i || Xe) return ''; + Xe = !0; + var u = Error.prepareStackTrace; + Error.prepareStackTrace = void 0; + try { + if (s) + if ( + ((s = function () { + throw Error(); + }), + Object.defineProperty(s.prototype, 'props', { + set: function () { + throw Error(); + } + }), + 'object' == typeof Reflect && Reflect.construct) + ) { + try { + Reflect.construct(s, []); + } catch (i) { + var m = i; + } + Reflect.construct(i, [], s); + } else { + try { + s.call(); + } catch (i) { + m = i; + } + i.call(s.prototype); + } + else { + try { + throw Error(); + } catch (i) { + m = i; + } + i(); + } + } catch (i) { + if (i && m && 'string' == typeof i.stack) { + for (var v = i.stack.split('\n'), _ = m.stack.split('\n'), j = v.length - 1, M = _.length - 1; 1 <= j && 0 <= M && v[j] !== _[M]; ) M--; + for (; 1 <= j && 0 <= M; j--, M--) + if (v[j] !== _[M]) { + if (1 !== j || 1 !== M) + do { + if ((j--, 0 > --M || v[j] !== _[M])) return '\n' + v[j].replace(' at new ', ' at '); + } while (1 <= j && 0 <= M); + break; + } + } + } finally { + (Xe = !1), (Error.prepareStackTrace = u); + } + return (i = i ? i.displayName || i.name : '') ? Na(i) : ''; + } + function Qa(i) { + switch (i.tag) { + case 5: + return Na(i.type); + case 16: + return Na('Lazy'); + case 13: + return Na('Suspense'); + case 19: + return Na('SuspenseList'); + case 0: + case 2: + case 15: + return (i = Pa(i.type, !1)); + case 11: + return (i = Pa(i.type.render, !1)); + case 22: + return (i = Pa(i.type._render, !1)); + case 1: + return (i = Pa(i.type, !0)); + default: + return ''; + } + } + function Ra(i) { + if (null == i) return null; + if ('function' == typeof i) return i.displayName || i.name || null; + if ('string' == typeof i) return i; + switch (i) { + case pe: + return 'Fragment'; + case ce: + return 'Portal'; + case fe: + return 'Profiler'; + case de: + return 'StrictMode'; + case we: + return 'Suspense'; + case Se: + return 'SuspenseList'; + } + if ('object' == typeof i) + switch (i.$$typeof) { + case be: + return (i.displayName || 'Context') + '.Consumer'; + case ye: + return (i._context.displayName || 'Context') + '.Provider'; + case _e: + var s = i.render; + return (s = s.displayName || s.name || ''), i.displayName || ('' !== s ? 'ForwardRef(' + s + ')' : 'ForwardRef'); + case xe: + return Ra(i.type); + case Ie: + return Ra(i._render); + case Pe: + (s = i._payload), (i = i._init); + try { + return Ra(i(s)); + } catch (i) {} + } + return null; + } + function Sa(i) { + switch (typeof i) { + case 'boolean': + case 'number': + case 'object': + case 'string': + case 'undefined': + return i; + default: + return ''; + } + } + function Ta(i) { + var s = i.type; + return (i = i.nodeName) && 'input' === i.toLowerCase() && ('checkbox' === s || 'radio' === s); + } + function Va(i) { + i._valueTracker || + (i._valueTracker = (function Ua(i) { + var s = Ta(i) ? 'checked' : 'value', + u = Object.getOwnPropertyDescriptor(i.constructor.prototype, s), + m = '' + i[s]; + if (!i.hasOwnProperty(s) && void 0 !== u && 'function' == typeof u.get && 'function' == typeof u.set) { + var v = u.get, + _ = u.set; + return ( + Object.defineProperty(i, s, { + configurable: !0, + get: function () { + return v.call(this); + }, + set: function (i) { + (m = '' + i), _.call(this, i); + } + }), + Object.defineProperty(i, s, { enumerable: u.enumerable }), + { + getValue: function () { + return m; + }, + setValue: function (i) { + m = '' + i; + }, + stopTracking: function () { + (i._valueTracker = null), delete i[s]; + } + } + ); + } + })(i)); + } + function Wa(i) { + if (!i) return !1; + var s = i._valueTracker; + if (!s) return !0; + var u = s.getValue(), + m = ''; + return ( + i && + (m = + Ta(i) ? + i.checked ? + 'true' + : 'false' + : i.value), + (i = m) !== u && (s.setValue(i), !0) + ); + } + function Xa(i) { + if (void 0 === (i = i || ('undefined' != typeof document ? document : void 0))) return null; + try { + return i.activeElement || i.body; + } catch (s) { + return i.body; + } + } + function Ya(i, s) { + var u = s.checked; + return v({}, s, { defaultChecked: void 0, defaultValue: void 0, value: void 0, checked: null != u ? u : i._wrapperState.initialChecked }); + } + function Za(i, s) { + var u = null == s.defaultValue ? '' : s.defaultValue, + m = null != s.checked ? s.checked : s.defaultChecked; + (u = Sa(null != s.value ? s.value : u)), (i._wrapperState = { initialChecked: m, initialValue: u, controlled: 'checkbox' === s.type || 'radio' === s.type ? null != s.checked : null != s.value }); + } + function $a(i, s) { + null != (s = s.checked) && qa(i, 'checked', s, !1); + } + function ab(i, s) { + $a(i, s); + var u = Sa(s.value), + m = s.type; + if (null != u) 'number' === m ? ((0 === u && '' === i.value) || i.value != u) && (i.value = '' + u) : i.value !== '' + u && (i.value = '' + u); + else if ('submit' === m || 'reset' === m) return void i.removeAttribute('value'); + s.hasOwnProperty('value') ? bb(i, s.type, u) : s.hasOwnProperty('defaultValue') && bb(i, s.type, Sa(s.defaultValue)), null == s.checked && null != s.defaultChecked && (i.defaultChecked = !!s.defaultChecked); + } + function cb(i, s, u) { + if (s.hasOwnProperty('value') || s.hasOwnProperty('defaultValue')) { + var m = s.type; + if (!(('submit' !== m && 'reset' !== m) || (void 0 !== s.value && null !== s.value))) return; + (s = '' + i._wrapperState.initialValue), u || s === i.value || (i.value = s), (i.defaultValue = s); + } + '' !== (u = i.name) && (i.name = ''), (i.defaultChecked = !!i._wrapperState.initialChecked), '' !== u && (i.name = u); + } + function bb(i, s, u) { + ('number' === s && Xa(i.ownerDocument) === i) || (null == u ? (i.defaultValue = '' + i._wrapperState.initialValue) : i.defaultValue !== '' + u && (i.defaultValue = '' + u)); + } + function eb(i, s) { + return ( + (i = v({ children: void 0 }, s)), + (s = (function db(i) { + var s = ''; + return ( + m.Children.forEach(i, function (i) { + null != i && (s += i); + }), + s + ); + })(s.children)) && (i.children = s), + i + ); + } + function fb(i, s, u, m) { + if (((i = i.options), s)) { + s = {}; + for (var v = 0; v < u.length; v++) s['$' + u[v]] = !0; + for (u = 0; u < i.length; u++) (v = s.hasOwnProperty('$' + i[u].value)), i[u].selected !== v && (i[u].selected = v), v && m && (i[u].defaultSelected = !0); + } else { + for (u = '' + Sa(u), s = null, v = 0; v < i.length; v++) { + if (i[v].value === u) return (i[v].selected = !0), void (m && (i[v].defaultSelected = !0)); + null !== s || i[v].disabled || (s = i[v]); + } + null !== s && (s.selected = !0); + } + } + function gb(i, s) { + if (null != s.dangerouslySetInnerHTML) throw Error(y(91)); + return v({}, s, { value: void 0, defaultValue: void 0, children: '' + i._wrapperState.initialValue }); + } + function hb(i, s) { + var u = s.value; + if (null == u) { + if (((u = s.children), (s = s.defaultValue), null != u)) { + if (null != s) throw Error(y(92)); + if (Array.isArray(u)) { + if (!(1 >= u.length)) throw Error(y(93)); + u = u[0]; + } + s = u; + } + null == s && (s = ''), (u = s); + } + i._wrapperState = { initialValue: Sa(u) }; + } + function ib(i, s) { + var u = Sa(s.value), + m = Sa(s.defaultValue); + null != u && ((u = '' + u) !== i.value && (i.value = u), null == s.defaultValue && i.defaultValue !== u && (i.defaultValue = u)), null != m && (i.defaultValue = '' + m); + } + function jb(i) { + var s = i.textContent; + s === i._wrapperState.initialValue && '' !== s && null !== s && (i.value = s); + } + var Ye = { html: 'http://www.w3.org/1999/xhtml', mathml: 'http://www.w3.org/1998/Math/MathML', svg: 'http://www.w3.org/2000/svg' }; + function lb(i) { + switch (i) { + case 'svg': + return 'http://www.w3.org/2000/svg'; + case 'math': + return 'http://www.w3.org/1998/Math/MathML'; + default: + return 'http://www.w3.org/1999/xhtml'; + } + } + function mb(i, s) { + return ( + null == i || 'http://www.w3.org/1999/xhtml' === i ? lb(s) + : 'http://www.w3.org/2000/svg' === i && 'foreignObject' === s ? 'http://www.w3.org/1999/xhtml' + : i + ); + } + var Qe, + et, + tt = + ((et = function (i, s) { + if (i.namespaceURI !== Ye.svg || 'innerHTML' in i) i.innerHTML = s; + else { + for ((Qe = Qe || document.createElement('div')).innerHTML = '' + s.valueOf().toString() + '', s = Qe.firstChild; i.firstChild; ) i.removeChild(i.firstChild); + for (; s.firstChild; ) i.appendChild(s.firstChild); + } + }), + 'undefined' != typeof MSApp && MSApp.execUnsafeLocalFunction ? + function (i, s, u, m) { + MSApp.execUnsafeLocalFunction(function () { + return et(i, s); + }); + } + : et); + function pb(i, s) { + if (s) { + var u = i.firstChild; + if (u && u === i.lastChild && 3 === u.nodeType) return void (u.nodeValue = s); + } + i.textContent = s; + } + var rt = { animationIterationCount: !0, borderImageOutset: !0, borderImageSlice: !0, borderImageWidth: !0, boxFlex: !0, boxFlexGroup: !0, boxOrdinalGroup: !0, columnCount: !0, columns: !0, flex: !0, flexGrow: !0, flexPositive: !0, flexShrink: !0, flexNegative: !0, flexOrder: !0, gridArea: !0, gridRow: !0, gridRowEnd: !0, gridRowSpan: !0, gridRowStart: !0, gridColumn: !0, gridColumnEnd: !0, gridColumnSpan: !0, gridColumnStart: !0, fontWeight: !0, lineClamp: !0, lineHeight: !0, opacity: !0, order: !0, orphans: !0, tabSize: !0, widows: !0, zIndex: !0, zoom: !0, fillOpacity: !0, floodOpacity: !0, stopOpacity: !0, strokeDasharray: !0, strokeDashoffset: !0, strokeMiterlimit: !0, strokeOpacity: !0, strokeWidth: !0 }, + nt = ['Webkit', 'ms', 'Moz', 'O']; + function sb(i, s, u) { + return ( + null == s || 'boolean' == typeof s || '' === s ? '' + : u || 'number' != typeof s || 0 === s || (rt.hasOwnProperty(i) && rt[i]) ? ('' + s).trim() + : s + 'px' + ); + } + function tb(i, s) { + for (var u in ((i = i.style), s)) + if (s.hasOwnProperty(u)) { + var m = 0 === u.indexOf('--'), + v = sb(u, s[u], m); + 'float' === u && (u = 'cssFloat'), m ? i.setProperty(u, v) : (i[u] = v); + } + } + Object.keys(rt).forEach(function (i) { + nt.forEach(function (s) { + (s = s + i.charAt(0).toUpperCase() + i.substring(1)), (rt[s] = rt[i]); + }); + }); + var ot = v({ menuitem: !0 }, { area: !0, base: !0, br: !0, col: !0, embed: !0, hr: !0, img: !0, input: !0, keygen: !0, link: !0, meta: !0, param: !0, source: !0, track: !0, wbr: !0 }); + function vb(i, s) { + if (s) { + if (ot[i] && (null != s.children || null != s.dangerouslySetInnerHTML)) throw Error(y(137, i)); + if (null != s.dangerouslySetInnerHTML) { + if (null != s.children) throw Error(y(60)); + if ('object' != typeof s.dangerouslySetInnerHTML || !('__html' in s.dangerouslySetInnerHTML)) throw Error(y(61)); + } + if (null != s.style && 'object' != typeof s.style) throw Error(y(62)); + } + } + function wb(i, s) { + if (-1 === i.indexOf('-')) return 'string' == typeof s.is; + switch (i) { + case 'annotation-xml': + case 'color-profile': + case 'font-face': + case 'font-face-src': + case 'font-face-uri': + case 'font-face-format': + case 'font-face-name': + case 'missing-glyph': + return !1; + default: + return !0; + } + } + function xb(i) { + return (i = i.target || i.srcElement || window).correspondingUseElement && (i = i.correspondingUseElement), 3 === i.nodeType ? i.parentNode : i; + } + var at = null, + it = null, + st = null; + function Bb(i) { + if ((i = Cb(i))) { + if ('function' != typeof at) throw Error(y(280)); + var s = i.stateNode; + s && ((s = Db(s)), at(i.stateNode, i.type, s)); + } + } + function Eb(i) { + it ? + st ? st.push(i) + : (st = [i]) + : (it = i); + } + function Fb() { + if (it) { + var i = it, + s = st; + if (((st = it = null), Bb(i), s)) for (i = 0; i < s.length; i++) Bb(s[i]); + } + } + function Gb(i, s) { + return i(s); + } + function Hb(i, s, u, m, v) { + return i(s, u, m, v); + } + function Ib() {} + var lt = Gb, + ct = !1, + ut = !1; + function Mb() { + (null === it && null === st) || (Ib(), Fb()); + } + function Ob(i, s) { + var u = i.stateNode; + if (null === u) return null; + var m = Db(u); + if (null === m) return null; + u = m[s]; + e: switch (s) { + case 'onClick': + case 'onClickCapture': + case 'onDoubleClick': + case 'onDoubleClickCapture': + case 'onMouseDown': + case 'onMouseDownCapture': + case 'onMouseMove': + case 'onMouseMoveCapture': + case 'onMouseUp': + case 'onMouseUpCapture': + case 'onMouseEnter': + (m = !m.disabled) || (m = !('button' === (i = i.type) || 'input' === i || 'select' === i || 'textarea' === i)), (i = !m); + break e; + default: + i = !1; + } + if (i) return null; + if (u && 'function' != typeof u) throw Error(y(231, s, typeof u)); + return u; + } + var pt = !1; + if ($) + try { + var ht = {}; + Object.defineProperty(ht, 'passive', { + get: function () { + pt = !0; + } + }), + window.addEventListener('test', ht, ht), + window.removeEventListener('test', ht, ht); + } catch (et) { + pt = !1; + } + function Rb(i, s, u, m, v, _, j, M, $) { + var W = Array.prototype.slice.call(arguments, 3); + try { + s.apply(u, W); + } catch (i) { + this.onError(i); + } + } + var dt = !1, + mt = null, + gt = !1, + yt = null, + vt = { + onError: function (i) { + (dt = !0), (mt = i); + } + }; + function Xb(i, s, u, m, v, _, j, M, $) { + (dt = !1), (mt = null), Rb.apply(vt, arguments); + } + function Zb(i) { + var s = i, + u = i; + if (i.alternate) for (; s.return; ) s = s.return; + else { + i = s; + do { + 0 != (1026 & (s = i).flags) && (u = s.return), (i = s.return); + } while (i); + } + return 3 === s.tag ? u : null; + } + function $b(i) { + if (13 === i.tag) { + var s = i.memoizedState; + if ((null === s && null !== (i = i.alternate) && (s = i.memoizedState), null !== s)) return s.dehydrated; + } + return null; + } + function ac(i) { + if (Zb(i) !== i) throw Error(y(188)); + } + function cc(i) { + if ( + ((i = (function bc(i) { + var s = i.alternate; + if (!s) { + if (null === (s = Zb(i))) throw Error(y(188)); + return s !== i ? null : i; + } + for (var u = i, m = s; ; ) { + var v = u.return; + if (null === v) break; + var _ = v.alternate; + if (null === _) { + if (null !== (m = v.return)) { + u = m; + continue; + } + break; + } + if (v.child === _.child) { + for (_ = v.child; _; ) { + if (_ === u) return ac(v), i; + if (_ === m) return ac(v), s; + _ = _.sibling; + } + throw Error(y(188)); + } + if (u.return !== m.return) (u = v), (m = _); + else { + for (var j = !1, M = v.child; M; ) { + if (M === u) { + (j = !0), (u = v), (m = _); + break; + } + if (M === m) { + (j = !0), (m = v), (u = _); + break; + } + M = M.sibling; + } + if (!j) { + for (M = _.child; M; ) { + if (M === u) { + (j = !0), (u = _), (m = v); + break; + } + if (M === m) { + (j = !0), (m = _), (u = v); + break; + } + M = M.sibling; + } + if (!j) throw Error(y(189)); + } + } + if (u.alternate !== m) throw Error(y(190)); + } + if (3 !== u.tag) throw Error(y(188)); + return u.stateNode.current === u ? i : s; + })(i)), + !i) + ) + return null; + for (var s = i; ; ) { + if (5 === s.tag || 6 === s.tag) return s; + if (s.child) (s.child.return = s), (s = s.child); + else { + if (s === i) break; + for (; !s.sibling; ) { + if (!s.return || s.return === i) return null; + s = s.return; + } + (s.sibling.return = s.return), (s = s.sibling); + } + } + return null; + } + function dc(i, s) { + for (var u = i.alternate; null !== s; ) { + if (s === i || s === u) return !0; + s = s.return; + } + return !1; + } + var bt, + _t, + Et, + wt, + St = !1, + xt = [], + kt = null, + Ot = null, + At = null, + Ct = new Map(), + jt = new Map(), + Pt = [], + It = 'mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit'.split(' '); + function rc(i, s, u, m, v) { + return { blockedOn: i, domEventName: s, eventSystemFlags: 16 | u, nativeEvent: v, targetContainers: [m] }; + } + function sc(i, s) { + switch (i) { + case 'focusin': + case 'focusout': + kt = null; + break; + case 'dragenter': + case 'dragleave': + Ot = null; + break; + case 'mouseover': + case 'mouseout': + At = null; + break; + case 'pointerover': + case 'pointerout': + Ct.delete(s.pointerId); + break; + case 'gotpointercapture': + case 'lostpointercapture': + jt.delete(s.pointerId); + } + } + function tc(i, s, u, m, v, _) { + return null === i || i.nativeEvent !== _ ? ((i = rc(s, u, m, v, _)), null !== s && null !== (s = Cb(s)) && _t(s), i) : ((i.eventSystemFlags |= m), (s = i.targetContainers), null !== v && -1 === s.indexOf(v) && s.push(v), i); + } + function vc(i) { + var s = wc(i.target); + if (null !== s) { + var u = Zb(s); + if (null !== u) + if (13 === (s = u.tag)) { + if (null !== (s = $b(u))) + return ( + (i.blockedOn = s), + void wt(i.lanePriority, function () { + _.unstable_runWithPriority(i.priority, function () { + Et(u); + }); + }) + ); + } else if (3 === s && u.stateNode.hydrate) return void (i.blockedOn = 3 === u.tag ? u.stateNode.containerInfo : null); + } + i.blockedOn = null; + } + function xc(i) { + if (null !== i.blockedOn) return !1; + for (var s = i.targetContainers; 0 < s.length; ) { + var u = yc(i.domEventName, i.eventSystemFlags, s[0], i.nativeEvent); + if (null !== u) return null !== (s = Cb(u)) && _t(s), (i.blockedOn = u), !1; + s.shift(); + } + return !0; + } + function zc(i, s, u) { + xc(i) && u.delete(s); + } + function Ac() { + for (St = !1; 0 < xt.length; ) { + var i = xt[0]; + if (null !== i.blockedOn) { + null !== (i = Cb(i.blockedOn)) && bt(i); + break; + } + for (var s = i.targetContainers; 0 < s.length; ) { + var u = yc(i.domEventName, i.eventSystemFlags, s[0], i.nativeEvent); + if (null !== u) { + i.blockedOn = u; + break; + } + s.shift(); + } + null === i.blockedOn && xt.shift(); + } + null !== kt && xc(kt) && (kt = null), null !== Ot && xc(Ot) && (Ot = null), null !== At && xc(At) && (At = null), Ct.forEach(zc), jt.forEach(zc); + } + function Bc(i, s) { + i.blockedOn === s && ((i.blockedOn = null), St || ((St = !0), _.unstable_scheduleCallback(_.unstable_NormalPriority, Ac))); + } + function Cc(i) { + function b(s) { + return Bc(s, i); + } + if (0 < xt.length) { + Bc(xt[0], i); + for (var s = 1; s < xt.length; s++) { + var u = xt[s]; + u.blockedOn === i && (u.blockedOn = null); + } + } + for (null !== kt && Bc(kt, i), null !== Ot && Bc(Ot, i), null !== At && Bc(At, i), Ct.forEach(b), jt.forEach(b), s = 0; s < Pt.length; s++) (u = Pt[s]).blockedOn === i && (u.blockedOn = null); + for (; 0 < Pt.length && null === (s = Pt[0]).blockedOn; ) vc(s), null === s.blockedOn && Pt.shift(); + } + function Dc(i, s) { + var u = {}; + return (u[i.toLowerCase()] = s.toLowerCase()), (u['Webkit' + i] = 'webkit' + s), (u['Moz' + i] = 'moz' + s), u; + } + var Nt = { animationend: Dc('Animation', 'AnimationEnd'), animationiteration: Dc('Animation', 'AnimationIteration'), animationstart: Dc('Animation', 'AnimationStart'), transitionend: Dc('Transition', 'TransitionEnd') }, + Tt = {}, + Mt = {}; + function Hc(i) { + if (Tt[i]) return Tt[i]; + if (!Nt[i]) return i; + var s, + u = Nt[i]; + for (s in u) if (u.hasOwnProperty(s) && s in Mt) return (Tt[i] = u[s]); + return i; + } + $ && ((Mt = document.createElement('div').style), 'AnimationEvent' in window || (delete Nt.animationend.animation, delete Nt.animationiteration.animation, delete Nt.animationstart.animation), 'TransitionEvent' in window || delete Nt.transitionend.transition); + var Rt = Hc('animationend'), + Bt = Hc('animationiteration'), + Dt = Hc('animationstart'), + Lt = Hc('transitionend'), + Ft = new Map(), + qt = new Map(), + $t = ['abort', 'abort', Rt, 'animationEnd', Bt, 'animationIteration', Dt, 'animationStart', 'canplay', 'canPlay', 'canplaythrough', 'canPlayThrough', 'durationchange', 'durationChange', 'emptied', 'emptied', 'encrypted', 'encrypted', 'ended', 'ended', 'error', 'error', 'gotpointercapture', 'gotPointerCapture', 'load', 'load', 'loadeddata', 'loadedData', 'loadedmetadata', 'loadedMetadata', 'loadstart', 'loadStart', 'lostpointercapture', 'lostPointerCapture', 'playing', 'playing', 'progress', 'progress', 'seeking', 'seeking', 'stalled', 'stalled', 'suspend', 'suspend', 'timeupdate', 'timeUpdate', Lt, 'transitionEnd', 'waiting', 'waiting']; + function Pc(i, s) { + for (var u = 0; u < i.length; u += 2) { + var m = i[u], + v = i[u + 1]; + (v = 'on' + (v[0].toUpperCase() + v.slice(1))), qt.set(m, s), Ft.set(m, v), da(v, [m]); + } + } + (0, _.unstable_now)(); + var zt = 8; + function Rc(i) { + if (0 != (1 & i)) return (zt = 15), 1; + if (0 != (2 & i)) return (zt = 14), 2; + if (0 != (4 & i)) return (zt = 13), 4; + var s = 24 & i; + return ( + 0 !== s ? ((zt = 12), s) + : 0 != (32 & i) ? ((zt = 11), 32) + : 0 !== (s = 192 & i) ? ((zt = 10), s) + : 0 != (256 & i) ? ((zt = 9), 256) + : 0 !== (s = 3584 & i) ? ((zt = 8), s) + : 0 != (4096 & i) ? ((zt = 7), 4096) + : 0 !== (s = 4186112 & i) ? ((zt = 6), s) + : 0 !== (s = 62914560 & i) ? ((zt = 5), s) + : 67108864 & i ? ((zt = 4), 67108864) + : 0 != (134217728 & i) ? ((zt = 3), 134217728) + : 0 !== (s = 805306368 & i) ? ((zt = 2), s) + : 0 != (1073741824 & i) ? ((zt = 1), 1073741824) + : ((zt = 8), i) + ); + } + function Uc(i, s) { + var u = i.pendingLanes; + if (0 === u) return (zt = 0); + var m = 0, + v = 0, + _ = i.expiredLanes, + j = i.suspendedLanes, + M = i.pingedLanes; + if (0 !== _) (m = _), (v = zt = 15); + else if (0 !== (_ = 134217727 & u)) { + var $ = _ & ~j; + 0 !== $ ? ((m = Rc($)), (v = zt)) : 0 !== (M &= _) && ((m = Rc(M)), (v = zt)); + } else 0 !== (_ = u & ~j) ? ((m = Rc(_)), (v = zt)) : 0 !== M && ((m = Rc(M)), (v = zt)); + if (0 === m) return 0; + if (((m = u & (((0 > (m = 31 - Ut(m)) ? 0 : 1 << m) << 1) - 1)), 0 !== s && s !== m && 0 == (s & j))) { + if ((Rc(s), v <= zt)) return s; + zt = v; + } + if (0 !== (s = i.entangledLanes)) for (i = i.entanglements, s &= m; 0 < s; ) (v = 1 << (u = 31 - Ut(s))), (m |= i[u]), (s &= ~v); + return m; + } + function Wc(i) { + return ( + 0 !== (i = -1073741825 & i.pendingLanes) ? i + : 1073741824 & i ? 1073741824 + : 0 + ); + } + function Xc(i, s) { + switch (i) { + case 15: + return 1; + case 14: + return 2; + case 12: + return 0 === (i = Yc(24 & ~s)) ? Xc(10, s) : i; + case 10: + return 0 === (i = Yc(192 & ~s)) ? Xc(8, s) : i; + case 8: + return 0 === (i = Yc(3584 & ~s)) && 0 === (i = Yc(4186112 & ~s)) && (i = 512), i; + case 2: + return 0 === (s = Yc(805306368 & ~s)) && (s = 268435456), s; + } + throw Error(y(358, i)); + } + function Yc(i) { + return i & -i; + } + function Zc(i) { + for (var s = [], u = 0; 31 > u; u++) s.push(i); + return s; + } + function $c(i, s, u) { + i.pendingLanes |= s; + var m = s - 1; + (i.suspendedLanes &= m), (i.pingedLanes &= m), ((i = i.eventTimes)[(s = 31 - Ut(s))] = u); + } + var Ut = + Math.clz32 ? + Math.clz32 + : function ad(i) { + return 0 === i ? 32 : (31 - ((Vt(i) / Wt) | 0)) | 0; + }, + Vt = Math.log, + Wt = Math.LN2; + var Kt = _.unstable_UserBlockingPriority, + Ht = _.unstable_runWithPriority, + Jt = !0; + function gd(i, s, u, m) { + ct || Ib(); + var v = hd, + _ = ct; + ct = !0; + try { + Hb(v, i, s, u, m); + } finally { + (ct = _) || Mb(); + } + } + function id(i, s, u, m) { + Ht(Kt, hd.bind(null, i, s, u, m)); + } + function hd(i, s, u, m) { + var v; + if (Jt) + if ((v = 0 == (4 & s)) && 0 < xt.length && -1 < It.indexOf(i)) (i = rc(null, i, s, u, m)), xt.push(i); + else { + var _ = yc(i, s, u, m); + if (null === _) v && sc(i, m); + else { + if (v) { + if (-1 < It.indexOf(i)) return (i = rc(_, i, s, u, m)), void xt.push(i); + if ( + (function uc(i, s, u, m, v) { + switch (s) { + case 'focusin': + return (kt = tc(kt, i, s, u, m, v)), !0; + case 'dragenter': + return (Ot = tc(Ot, i, s, u, m, v)), !0; + case 'mouseover': + return (At = tc(At, i, s, u, m, v)), !0; + case 'pointerover': + var _ = v.pointerId; + return Ct.set(_, tc(Ct.get(_) || null, i, s, u, m, v)), !0; + case 'gotpointercapture': + return (_ = v.pointerId), jt.set(_, tc(jt.get(_) || null, i, s, u, m, v)), !0; + } + return !1; + })(_, i, s, u, m) + ) + return; + sc(i, m); + } + jd(i, s, m, null, u); + } + } + } + function yc(i, s, u, m) { + var v = xb(m); + if (null !== (v = wc(v))) { + var _ = Zb(v); + if (null === _) v = null; + else { + var j = _.tag; + if (13 === j) { + if (null !== (v = $b(_))) return v; + v = null; + } else if (3 === j) { + if (_.stateNode.hydrate) return 3 === _.tag ? _.stateNode.containerInfo : null; + v = null; + } else _ !== v && (v = null); + } + } + return jd(i, s, m, v, u), null; + } + var Gt = null, + Xt = null, + Yt = null; + function nd() { + if (Yt) return Yt; + var i, + s, + u = Xt, + m = u.length, + v = 'value' in Gt ? Gt.value : Gt.textContent, + _ = v.length; + for (i = 0; i < m && u[i] === v[i]; i++); + var j = m - i; + for (s = 1; s <= j && u[m - s] === v[_ - s]; s++); + return (Yt = v.slice(i, 1 < s ? 1 - s : void 0)); + } + function od(i) { + var s = i.keyCode; + return 'charCode' in i ? 0 === (i = i.charCode) && 13 === s && (i = 13) : (i = s), 10 === i && (i = 13), 32 <= i || 13 === i ? i : 0; + } + function pd() { + return !0; + } + function qd() { + return !1; + } + function rd(i) { + function b(s, u, m, v, _) { + for (var j in ((this._reactName = s), (this._targetInst = m), (this.type = u), (this.nativeEvent = v), (this.target = _), (this.currentTarget = null), i)) i.hasOwnProperty(j) && ((s = i[j]), (this[j] = s ? s(v) : v[j])); + return ( + (this.isDefaultPrevented = + ( + null != v.defaultPrevented ? v.defaultPrevented : !1 === v.returnValue + ) ? + pd + : qd), + (this.isPropagationStopped = qd), + this + ); + } + return ( + v(b.prototype, { + preventDefault: function () { + this.defaultPrevented = !0; + var i = this.nativeEvent; + i && (i.preventDefault ? i.preventDefault() : 'unknown' != typeof i.returnValue && (i.returnValue = !1), (this.isDefaultPrevented = pd)); + }, + stopPropagation: function () { + var i = this.nativeEvent; + i && (i.stopPropagation ? i.stopPropagation() : 'unknown' != typeof i.cancelBubble && (i.cancelBubble = !0), (this.isPropagationStopped = pd)); + }, + persist: function () {}, + isPersistent: pd + }), + b + ); + } + var Qt, + Zt, + er, + tr = { + eventPhase: 0, + bubbles: 0, + cancelable: 0, + timeStamp: function (i) { + return i.timeStamp || Date.now(); + }, + defaultPrevented: 0, + isTrusted: 0 + }, + rr = rd(tr), + nr = v({}, tr, { view: 0, detail: 0 }), + ar = rd(nr), + ir = v({}, nr, { + screenX: 0, + screenY: 0, + clientX: 0, + clientY: 0, + pageX: 0, + pageY: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + getModifierState: zd, + button: 0, + buttons: 0, + relatedTarget: function (i) { + return ( + void 0 === i.relatedTarget ? + i.fromElement === i.srcElement ? + i.toElement + : i.fromElement + : i.relatedTarget + ); + }, + movementX: function (i) { + return 'movementX' in i ? i.movementX : (i !== er && (er && 'mousemove' === i.type ? ((Qt = i.screenX - er.screenX), (Zt = i.screenY - er.screenY)) : (Zt = Qt = 0), (er = i)), Qt); + }, + movementY: function (i) { + return 'movementY' in i ? i.movementY : Zt; + } + }), + sr = rd(ir), + lr = rd(v({}, ir, { dataTransfer: 0 })), + cr = rd(v({}, nr, { relatedTarget: 0 })), + ur = rd(v({}, tr, { animationName: 0, elapsedTime: 0, pseudoElement: 0 })), + pr = v({}, tr, { + clipboardData: function (i) { + return 'clipboardData' in i ? i.clipboardData : window.clipboardData; + } + }), + dr = rd(pr), + fr = rd(v({}, tr, { data: 0 })), + mr = { Esc: 'Escape', Spacebar: ' ', Left: 'ArrowLeft', Up: 'ArrowUp', Right: 'ArrowRight', Down: 'ArrowDown', Del: 'Delete', Win: 'OS', Menu: 'ContextMenu', Apps: 'ContextMenu', Scroll: 'ScrollLock', MozPrintableKey: 'Unidentified' }, + gr = { 8: 'Backspace', 9: 'Tab', 12: 'Clear', 13: 'Enter', 16: 'Shift', 17: 'Control', 18: 'Alt', 19: 'Pause', 20: 'CapsLock', 27: 'Escape', 32: ' ', 33: 'PageUp', 34: 'PageDown', 35: 'End', 36: 'Home', 37: 'ArrowLeft', 38: 'ArrowUp', 39: 'ArrowRight', 40: 'ArrowDown', 45: 'Insert', 46: 'Delete', 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6', 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12', 144: 'NumLock', 145: 'ScrollLock', 224: 'Meta' }, + yr = { Alt: 'altKey', Control: 'ctrlKey', Meta: 'metaKey', Shift: 'shiftKey' }; + function Pd(i) { + var s = this.nativeEvent; + return s.getModifierState ? s.getModifierState(i) : !!(i = yr[i]) && !!s[i]; + } + function zd() { + return Pd; + } + var vr = v({}, nr, { + key: function (i) { + if (i.key) { + var s = mr[i.key] || i.key; + if ('Unidentified' !== s) return s; + } + return ( + 'keypress' === i.type ? + 13 === (i = od(i)) ? + 'Enter' + : String.fromCharCode(i) + : 'keydown' === i.type || 'keyup' === i.type ? gr[i.keyCode] || 'Unidentified' + : '' + ); + }, + code: 0, + location: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + repeat: 0, + locale: 0, + getModifierState: zd, + charCode: function (i) { + return 'keypress' === i.type ? od(i) : 0; + }, + keyCode: function (i) { + return 'keydown' === i.type || 'keyup' === i.type ? i.keyCode : 0; + }, + which: function (i) { + return ( + 'keypress' === i.type ? od(i) + : 'keydown' === i.type || 'keyup' === i.type ? i.keyCode + : 0 + ); + } + }), + br = rd(vr), + _r = rd(v({}, ir, { pointerId: 0, width: 0, height: 0, pressure: 0, tangentialPressure: 0, tiltX: 0, tiltY: 0, twist: 0, pointerType: 0, isPrimary: 0 })), + Er = rd(v({}, nr, { touches: 0, targetTouches: 0, changedTouches: 0, altKey: 0, metaKey: 0, ctrlKey: 0, shiftKey: 0, getModifierState: zd })), + wr = rd(v({}, tr, { propertyName: 0, elapsedTime: 0, pseudoElement: 0 })), + Sr = v({}, ir, { + deltaX: function (i) { + return ( + 'deltaX' in i ? i.deltaX + : 'wheelDeltaX' in i ? -i.wheelDeltaX + : 0 + ); + }, + deltaY: function (i) { + return ( + 'deltaY' in i ? i.deltaY + : 'wheelDeltaY' in i ? -i.wheelDeltaY + : 'wheelDelta' in i ? -i.wheelDelta + : 0 + ); + }, + deltaZ: 0, + deltaMode: 0 + }), + xr = rd(Sr), + kr = [9, 13, 27, 32], + Or = $ && 'CompositionEvent' in window, + Ar = null; + $ && 'documentMode' in document && (Ar = document.documentMode); + var Cr = $ && 'TextEvent' in window && !Ar, + jr = $ && (!Or || (Ar && 8 < Ar && 11 >= Ar)), + Pr = String.fromCharCode(32), + Ir = !1; + function ge(i, s) { + switch (i) { + case 'keyup': + return -1 !== kr.indexOf(s.keyCode); + case 'keydown': + return 229 !== s.keyCode; + case 'keypress': + case 'mousedown': + case 'focusout': + return !0; + default: + return !1; + } + } + function he(i) { + return 'object' == typeof (i = i.detail) && 'data' in i ? i.data : null; + } + var Nr = !1; + var Tr = { 'color': !0, 'date': !0, 'datetime': !0, 'datetime-local': !0, 'email': !0, 'month': !0, 'number': !0, 'password': !0, 'range': !0, 'search': !0, 'tel': !0, 'text': !0, 'time': !0, 'url': !0, 'week': !0 }; + function me(i) { + var s = i && i.nodeName && i.nodeName.toLowerCase(); + return 'input' === s ? !!Tr[i.type] : 'textarea' === s; + } + function ne(i, s, u, m) { + Eb(m), 0 < (s = oe(s, 'onChange')).length && ((u = new rr('onChange', 'change', null, u, m)), i.push({ event: u, listeners: s })); + } + var Mr = null, + Rr = null; + function re(i) { + se(i, 0); + } + function te(i) { + if (Wa(ue(i))) return i; + } + function ve(i, s) { + if ('change' === i) return s; + } + var Br = !1; + if ($) { + var Dr; + if ($) { + var Lr = 'oninput' in document; + if (!Lr) { + var Fr = document.createElement('div'); + Fr.setAttribute('oninput', 'return;'), (Lr = 'function' == typeof Fr.oninput); + } + Dr = Lr; + } else Dr = !1; + Br = Dr && (!document.documentMode || 9 < document.documentMode); + } + function Ae() { + Mr && (Mr.detachEvent('onpropertychange', Be), (Rr = Mr = null)); + } + function Be(i) { + if ('value' === i.propertyName && te(Rr)) { + var s = []; + if ((ne(s, Rr, i, xb(i)), (i = re), ct)) i(s); + else { + ct = !0; + try { + Gb(i, s); + } finally { + (ct = !1), Mb(); + } + } + } + } + function Ce(i, s, u) { + 'focusin' === i ? (Ae(), (Rr = u), (Mr = s).attachEvent('onpropertychange', Be)) : 'focusout' === i && Ae(); + } + function De(i) { + if ('selectionchange' === i || 'keyup' === i || 'keydown' === i) return te(Rr); + } + function Ee(i, s) { + if ('click' === i) return te(s); + } + function Fe(i, s) { + if ('input' === i || 'change' === i) return te(s); + } + var qr = + 'function' == typeof Object.is ? + Object.is + : function Ge(i, s) { + return (i === s && (0 !== i || 1 / i == 1 / s)) || (i != i && s != s); + }, + $r = Object.prototype.hasOwnProperty; + function Je(i, s) { + if (qr(i, s)) return !0; + if ('object' != typeof i || null === i || 'object' != typeof s || null === s) return !1; + var u = Object.keys(i), + m = Object.keys(s); + if (u.length !== m.length) return !1; + for (m = 0; m < u.length; m++) if (!$r.call(s, u[m]) || !qr(i[u[m]], s[u[m]])) return !1; + return !0; + } + function Ke(i) { + for (; i && i.firstChild; ) i = i.firstChild; + return i; + } + function Le(i, s) { + var u, + m = Ke(i); + for (i = 0; m; ) { + if (3 === m.nodeType) { + if (((u = i + m.textContent.length), i <= s && u >= s)) return { node: m, offset: s - i }; + i = u; + } + e: { + for (; m; ) { + if (m.nextSibling) { + m = m.nextSibling; + break e; + } + m = m.parentNode; + } + m = void 0; + } + m = Ke(m); + } + } + function Me(i, s) { + return ( + !(!i || !s) && + (i === s || + ((!i || 3 !== i.nodeType) && + (s && 3 === s.nodeType ? Me(i, s.parentNode) + : 'contains' in i ? i.contains(s) + : !!i.compareDocumentPosition && !!(16 & i.compareDocumentPosition(s))))) + ); + } + function Ne() { + for (var i = window, s = Xa(); s instanceof i.HTMLIFrameElement; ) { + try { + var u = 'string' == typeof s.contentWindow.location.href; + } catch (i) { + u = !1; + } + if (!u) break; + s = Xa((i = s.contentWindow).document); + } + return s; + } + function Oe(i) { + var s = i && i.nodeName && i.nodeName.toLowerCase(); + return s && (('input' === s && ('text' === i.type || 'search' === i.type || 'tel' === i.type || 'url' === i.type || 'password' === i.type)) || 'textarea' === s || 'true' === i.contentEditable); + } + var zr = $ && 'documentMode' in document && 11 >= document.documentMode, + Ur = null, + Vr = null, + Wr = null, + Kr = !1; + function Ue(i, s, u) { + var m = + u.window === u ? u.document + : 9 === u.nodeType ? u + : u.ownerDocument; + Kr || null == Ur || Ur !== Xa(m) || ('selectionStart' in (m = Ur) && Oe(m) ? (m = { start: m.selectionStart, end: m.selectionEnd }) : (m = { anchorNode: (m = ((m.ownerDocument && m.ownerDocument.defaultView) || window).getSelection()).anchorNode, anchorOffset: m.anchorOffset, focusNode: m.focusNode, focusOffset: m.focusOffset }), (Wr && Je(Wr, m)) || ((Wr = m), 0 < (m = oe(Vr, 'onSelect')).length && ((s = new rr('onSelect', 'select', null, s, u)), i.push({ event: s, listeners: m }), (s.target = Ur)))); + } + Pc('cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange'.split(' '), 0), Pc('drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel'.split(' '), 1), Pc($t, 2); + for (var Hr = 'change selectionchange textInput compositionstart compositionend compositionupdate'.split(' '), Jr = 0; Jr < Hr.length; Jr++) qt.set(Hr[Jr], 0); + ea('onMouseEnter', ['mouseout', 'mouseover']), ea('onMouseLeave', ['mouseout', 'mouseover']), ea('onPointerEnter', ['pointerout', 'pointerover']), ea('onPointerLeave', ['pointerout', 'pointerover']), da('onChange', 'change click focusin focusout input keydown keyup selectionchange'.split(' ')), da('onSelect', 'focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange'.split(' ')), da('onBeforeInput', ['compositionend', 'keypress', 'textInput', 'paste']), da('onCompositionEnd', 'compositionend focusout keydown keypress keyup mousedown'.split(' ')), da('onCompositionStart', 'compositionstart focusout keydown keypress keyup mousedown'.split(' ')), da('onCompositionUpdate', 'compositionupdate focusout keydown keypress keyup mousedown'.split(' ')); + var Gr = 'abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting'.split(' '), + Xr = new Set('cancel close invalid load scroll toggle'.split(' ').concat(Gr)); + function Ze(i, s, u) { + var m = i.type || 'unknown-event'; + (i.currentTarget = u), + (function Yb(i, s, u, m, v, _, j, M, $) { + if ((Xb.apply(this, arguments), dt)) { + if (!dt) throw Error(y(198)); + var W = mt; + (dt = !1), (mt = null), gt || ((gt = !0), (yt = W)); + } + })(m, s, void 0, i), + (i.currentTarget = null); + } + function se(i, s) { + s = 0 != (4 & s); + for (var u = 0; u < i.length; u++) { + var m = i[u], + v = m.event; + m = m.listeners; + e: { + var _ = void 0; + if (s) + for (var j = m.length - 1; 0 <= j; j--) { + var M = m[j], + $ = M.instance, + W = M.currentTarget; + if (((M = M.listener), $ !== _ && v.isPropagationStopped())) break e; + Ze(v, M, W), (_ = $); + } + else + for (j = 0; j < m.length; j++) { + if ((($ = (M = m[j]).instance), (W = M.currentTarget), (M = M.listener), $ !== _ && v.isPropagationStopped())) break e; + Ze(v, M, W), (_ = $); + } + } + } + if (gt) throw ((i = yt), (gt = !1), (yt = null), i); + } + function G(i, s) { + var u = $e(s), + m = i + '__bubble'; + u.has(m) || (af(s, i, 2, !1), u.add(m)); + } + var Yr = '_reactListening' + Math.random().toString(36).slice(2); + function cf(i) { + i[Yr] || + ((i[Yr] = !0), + j.forEach(function (s) { + Xr.has(s) || df(s, !1, i, null), df(s, !0, i, null); + })); + } + function df(i, s, u, m) { + var v = 4 < arguments.length && void 0 !== arguments[4] ? arguments[4] : 0, + _ = u; + if (('selectionchange' === i && 9 !== u.nodeType && (_ = u.ownerDocument), null !== m && !s && Xr.has(i))) { + if ('scroll' !== i) return; + (v |= 2), (_ = m); + } + var j = $e(_), + M = i + '__' + (s ? 'capture' : 'bubble'); + j.has(M) || (s && (v |= 4), af(_, i, v, s), j.add(M)); + } + function af(i, s, u, m) { + var v = qt.get(s); + switch (void 0 === v ? 2 : v) { + case 0: + v = gd; + break; + case 1: + v = id; + break; + default: + v = hd; + } + (u = v.bind(null, s, u, i)), + (v = void 0), + !pt || ('touchstart' !== s && 'touchmove' !== s && 'wheel' !== s) || (v = !0), + m ? + void 0 !== v ? + i.addEventListener(s, u, { capture: !0, passive: v }) + : i.addEventListener(s, u, !0) + : void 0 !== v ? i.addEventListener(s, u, { passive: v }) + : i.addEventListener(s, u, !1); + } + function jd(i, s, u, m, v) { + var _ = m; + if (0 == (1 & s) && 0 == (2 & s) && null !== m) + e: for (;;) { + if (null === m) return; + var j = m.tag; + if (3 === j || 4 === j) { + var M = m.stateNode.containerInfo; + if (M === v || (8 === M.nodeType && M.parentNode === v)) break; + if (4 === j) + for (j = m.return; null !== j; ) { + var $ = j.tag; + if ((3 === $ || 4 === $) && (($ = j.stateNode.containerInfo) === v || (8 === $.nodeType && $.parentNode === v))) return; + j = j.return; + } + for (; null !== M; ) { + if (null === (j = wc(M))) return; + if (5 === ($ = j.tag) || 6 === $) { + m = _ = j; + continue e; + } + M = M.parentNode; + } + } + m = m.return; + } + !(function Nb(i, s, u) { + if (ut) return i(s, u); + ut = !0; + try { + return lt(i, s, u); + } finally { + (ut = !1), Mb(); + } + })(function () { + var m = _, + v = xb(u), + j = []; + e: { + var M = Ft.get(i); + if (void 0 !== M) { + var $ = rr, + W = i; + switch (i) { + case 'keypress': + if (0 === od(u)) break e; + case 'keydown': + case 'keyup': + $ = br; + break; + case 'focusin': + (W = 'focus'), ($ = cr); + break; + case 'focusout': + (W = 'blur'), ($ = cr); + break; + case 'beforeblur': + case 'afterblur': + $ = cr; + break; + case 'click': + if (2 === u.button) break e; + case 'auxclick': + case 'dblclick': + case 'mousedown': + case 'mousemove': + case 'mouseup': + case 'mouseout': + case 'mouseover': + case 'contextmenu': + $ = sr; + break; + case 'drag': + case 'dragend': + case 'dragenter': + case 'dragexit': + case 'dragleave': + case 'dragover': + case 'dragstart': + case 'drop': + $ = lr; + break; + case 'touchcancel': + case 'touchend': + case 'touchmove': + case 'touchstart': + $ = Er; + break; + case Rt: + case Bt: + case Dt: + $ = ur; + break; + case Lt: + $ = wr; + break; + case 'scroll': + $ = ar; + break; + case 'wheel': + $ = xr; + break; + case 'copy': + case 'cut': + case 'paste': + $ = dr; + break; + case 'gotpointercapture': + case 'lostpointercapture': + case 'pointercancel': + case 'pointerdown': + case 'pointermove': + case 'pointerout': + case 'pointerover': + case 'pointerup': + $ = _r; + } + var X = 0 != (4 & s), + Y = !X && 'scroll' === i, + Z = + X ? + null !== M ? + M + 'Capture' + : null + : M; + X = []; + for (var ee, ae = m; null !== ae; ) { + var ie = (ee = ae).stateNode; + if ((5 === ee.tag && null !== ie && ((ee = ie), null !== Z && null != (ie = Ob(ae, Z)) && X.push(ef(ae, ie, ee))), Y)) break; + ae = ae.return; + } + 0 < X.length && ((M = new $(M, W, null, u, v)), j.push({ event: M, listeners: X })); + } + } + if (0 == (7 & s)) { + if ( + (($ = 'mouseout' === i || 'pointerout' === i), + (!(M = 'mouseover' === i || 'pointerover' === i) || 0 != (16 & s) || !(W = u.relatedTarget || u.fromElement) || (!wc(W) && !W[sn])) && + ($ || M) && + ((M = + v.window === v ? v + : (M = v.ownerDocument) ? M.defaultView || M.parentWindow + : window), + $ ? (($ = m), null !== (W = (W = u.relatedTarget || u.toElement) ? wc(W) : null) && (W !== (Y = Zb(W)) || (5 !== W.tag && 6 !== W.tag)) && (W = null)) : (($ = null), (W = m)), + $ !== W)) + ) { + if (((X = sr), (ie = 'onMouseLeave'), (Z = 'onMouseEnter'), (ae = 'mouse'), ('pointerout' !== i && 'pointerover' !== i) || ((X = _r), (ie = 'onPointerLeave'), (Z = 'onPointerEnter'), (ae = 'pointer')), (Y = null == $ ? M : ue($)), (ee = null == W ? M : ue(W)), ((M = new X(ie, ae + 'leave', $, u, v)).target = Y), (M.relatedTarget = ee), (ie = null), wc(v) === m && (((X = new X(Z, ae + 'enter', W, u, v)).target = ee), (X.relatedTarget = Y), (ie = X)), (Y = ie), $ && W)) + e: { + for (Z = W, ae = 0, ee = X = $; ee; ee = gf(ee)) ae++; + for (ee = 0, ie = Z; ie; ie = gf(ie)) ee++; + for (; 0 < ae - ee; ) (X = gf(X)), ae--; + for (; 0 < ee - ae; ) (Z = gf(Z)), ee--; + for (; ae--; ) { + if (X === Z || (null !== Z && X === Z.alternate)) break e; + (X = gf(X)), (Z = gf(Z)); + } + X = null; + } + else X = null; + null !== $ && hf(j, M, $, X, !1), null !== W && null !== Y && hf(j, Y, W, X, !0); + } + if ('select' === ($ = (M = m ? ue(m) : window).nodeName && M.nodeName.toLowerCase()) || ('input' === $ && 'file' === M.type)) var le = ve; + else if (me(M)) + if (Br) le = Fe; + else { + le = De; + var ce = Ce; + } + else ($ = M.nodeName) && 'input' === $.toLowerCase() && ('checkbox' === M.type || 'radio' === M.type) && (le = Ee); + switch ((le && (le = le(i, m)) ? ne(j, le, u, v) : (ce && ce(i, M, m), 'focusout' === i && (ce = M._wrapperState) && ce.controlled && 'number' === M.type && bb(M, 'number', M.value)), (ce = m ? ue(m) : window), i)) { + case 'focusin': + (me(ce) || 'true' === ce.contentEditable) && ((Ur = ce), (Vr = m), (Wr = null)); + break; + case 'focusout': + Wr = Vr = Ur = null; + break; + case 'mousedown': + Kr = !0; + break; + case 'contextmenu': + case 'mouseup': + case 'dragend': + (Kr = !1), Ue(j, u, v); + break; + case 'selectionchange': + if (zr) break; + case 'keydown': + case 'keyup': + Ue(j, u, v); + } + var pe; + if (Or) + e: { + switch (i) { + case 'compositionstart': + var de = 'onCompositionStart'; + break e; + case 'compositionend': + de = 'onCompositionEnd'; + break e; + case 'compositionupdate': + de = 'onCompositionUpdate'; + break e; + } + de = void 0; + } + else Nr ? ge(i, u) && (de = 'onCompositionEnd') : 'keydown' === i && 229 === u.keyCode && (de = 'onCompositionStart'); + de && (jr && 'ko' !== u.locale && (Nr || 'onCompositionStart' !== de ? 'onCompositionEnd' === de && Nr && (pe = nd()) : ((Xt = 'value' in (Gt = v) ? Gt.value : Gt.textContent), (Nr = !0))), 0 < (ce = oe(m, de)).length && ((de = new fr(de, i, null, u, v)), j.push({ event: de, listeners: ce }), pe ? (de.data = pe) : null !== (pe = he(u)) && (de.data = pe))), + (pe = + Cr ? + (function je(i, s) { + switch (i) { + case 'compositionend': + return he(s); + case 'keypress': + return 32 !== s.which ? null : ((Ir = !0), Pr); + case 'textInput': + return (i = s.data) === Pr && Ir ? null : i; + default: + return null; + } + })(i, u) + : (function ke(i, s) { + if (Nr) return 'compositionend' === i || (!Or && ge(i, s)) ? ((i = nd()), (Yt = Xt = Gt = null), (Nr = !1), i) : null; + switch (i) { + case 'paste': + default: + return null; + case 'keypress': + if (!(s.ctrlKey || s.altKey || s.metaKey) || (s.ctrlKey && s.altKey)) { + if (s.char && 1 < s.char.length) return s.char; + if (s.which) return String.fromCharCode(s.which); + } + return null; + case 'compositionend': + return jr && 'ko' !== s.locale ? null : s.data; + } + })(i, u)) && + 0 < (m = oe(m, 'onBeforeInput')).length && + ((v = new fr('onBeforeInput', 'beforeinput', null, u, v)), j.push({ event: v, listeners: m }), (v.data = pe)); + } + se(j, s); + }); + } + function ef(i, s, u) { + return { instance: i, listener: s, currentTarget: u }; + } + function oe(i, s) { + for (var u = s + 'Capture', m = []; null !== i; ) { + var v = i, + _ = v.stateNode; + 5 === v.tag && null !== _ && ((v = _), null != (_ = Ob(i, u)) && m.unshift(ef(i, _, v)), null != (_ = Ob(i, s)) && m.push(ef(i, _, v))), (i = i.return); + } + return m; + } + function gf(i) { + if (null === i) return null; + do { + i = i.return; + } while (i && 5 !== i.tag); + return i || null; + } + function hf(i, s, u, m, v) { + for (var _ = s._reactName, j = []; null !== u && u !== m; ) { + var M = u, + $ = M.alternate, + W = M.stateNode; + if (null !== $ && $ === m) break; + 5 === M.tag && null !== W && ((M = W), v ? null != ($ = Ob(u, _)) && j.unshift(ef(u, $, M)) : v || (null != ($ = Ob(u, _)) && j.push(ef(u, $, M)))), (u = u.return); + } + 0 !== j.length && i.push({ event: s, listeners: j }); + } + function jf() {} + var Qr = null, + Zr = null; + function mf(i, s) { + switch (i) { + case 'button': + case 'input': + case 'select': + case 'textarea': + return !!s.autoFocus; + } + return !1; + } + function nf(i, s) { + return 'textarea' === i || 'option' === i || 'noscript' === i || 'string' == typeof s.children || 'number' == typeof s.children || ('object' == typeof s.dangerouslySetInnerHTML && null !== s.dangerouslySetInnerHTML && null != s.dangerouslySetInnerHTML.__html); + } + var en = 'function' == typeof setTimeout ? setTimeout : void 0, + tn = 'function' == typeof clearTimeout ? clearTimeout : void 0; + function qf(i) { + 1 === i.nodeType ? (i.textContent = '') : 9 === i.nodeType && null != (i = i.body) && (i.textContent = ''); + } + function rf(i) { + for (; null != i; i = i.nextSibling) { + var s = i.nodeType; + if (1 === s || 3 === s) break; + } + return i; + } + function sf(i) { + i = i.previousSibling; + for (var s = 0; i; ) { + if (8 === i.nodeType) { + var u = i.data; + if ('$' === u || '$!' === u || '$?' === u) { + if (0 === s) return i; + s--; + } else '/$' === u && s++; + } + i = i.previousSibling; + } + return null; + } + var rn = 0; + var nn = Math.random().toString(36).slice(2), + on = '__reactFiber$' + nn, + an = '__reactProps$' + nn, + sn = '__reactContainer$' + nn, + ln = '__reactEvents$' + nn; + function wc(i) { + var s = i[on]; + if (s) return s; + for (var u = i.parentNode; u; ) { + if ((s = u[sn] || u[on])) { + if (((u = s.alternate), null !== s.child || (null !== u && null !== u.child))) + for (i = sf(i); null !== i; ) { + if ((u = i[on])) return u; + i = sf(i); + } + return s; + } + u = (i = u).parentNode; + } + return null; + } + function Cb(i) { + return !(i = i[on] || i[sn]) || (5 !== i.tag && 6 !== i.tag && 13 !== i.tag && 3 !== i.tag) ? null : i; + } + function ue(i) { + if (5 === i.tag || 6 === i.tag) return i.stateNode; + throw Error(y(33)); + } + function Db(i) { + return i[an] || null; + } + function $e(i) { + var s = i[ln]; + return void 0 === s && (s = i[ln] = new Set()), s; + } + var cn = [], + un = -1; + function Bf(i) { + return { current: i }; + } + function H(i) { + 0 > un || ((i.current = cn[un]), (cn[un] = null), un--); + } + function I(i, s) { + un++, (cn[un] = i.current), (i.current = s); + } + var pn = {}, + hn = Bf(pn), + dn = Bf(!1), + fn = pn; + function Ef(i, s) { + var u = i.type.contextTypes; + if (!u) return pn; + var m = i.stateNode; + if (m && m.__reactInternalMemoizedUnmaskedChildContext === s) return m.__reactInternalMemoizedMaskedChildContext; + var v, + _ = {}; + for (v in u) _[v] = s[v]; + return m && (((i = i.stateNode).__reactInternalMemoizedUnmaskedChildContext = s), (i.__reactInternalMemoizedMaskedChildContext = _)), _; + } + function Ff(i) { + return null != (i = i.childContextTypes); + } + function Gf() { + H(dn), H(hn); + } + function Hf(i, s, u) { + if (hn.current !== pn) throw Error(y(168)); + I(hn, s), I(dn, u); + } + function If(i, s, u) { + var m = i.stateNode; + if (((i = s.childContextTypes), 'function' != typeof m.getChildContext)) return u; + for (var _ in (m = m.getChildContext())) if (!(_ in i)) throw Error(y(108, Ra(s) || 'Unknown', _)); + return v({}, u, m); + } + function Jf(i) { + return (i = ((i = i.stateNode) && i.__reactInternalMemoizedMergedChildContext) || pn), (fn = hn.current), I(hn, i), I(dn, dn.current), !0; + } + function Kf(i, s, u) { + var m = i.stateNode; + if (!m) throw Error(y(169)); + u ? ((i = If(i, s, fn)), (m.__reactInternalMemoizedMergedChildContext = i), H(dn), H(hn), I(hn, i)) : H(dn), I(dn, u); + } + var mn = null, + gn = null, + yn = _.unstable_runWithPriority, + vn = _.unstable_scheduleCallback, + bn = _.unstable_cancelCallback, + _n = _.unstable_shouldYield, + En = _.unstable_requestPaint, + wn = _.unstable_now, + Sn = _.unstable_getCurrentPriorityLevel, + xn = _.unstable_ImmediatePriority, + kn = _.unstable_UserBlockingPriority, + On = _.unstable_NormalPriority, + An = _.unstable_LowPriority, + Cn = _.unstable_IdlePriority, + jn = {}, + Pn = void 0 !== En ? En : function () {}, + In = null, + Nn = null, + Tn = !1, + Mn = wn(), + Rn = + 1e4 > Mn ? wn : ( + function () { + return wn() - Mn; + } + ); + function eg() { + switch (Sn()) { + case xn: + return 99; + case kn: + return 98; + case On: + return 97; + case An: + return 96; + case Cn: + return 95; + default: + throw Error(y(332)); + } + } + function fg(i) { + switch (i) { + case 99: + return xn; + case 98: + return kn; + case 97: + return On; + case 96: + return An; + case 95: + return Cn; + default: + throw Error(y(332)); + } + } + function gg(i, s) { + return (i = fg(i)), yn(i, s); + } + function hg(i, s, u) { + return (i = fg(i)), vn(i, s, u); + } + function ig() { + if (null !== Nn) { + var i = Nn; + (Nn = null), bn(i); + } + jg(); + } + function jg() { + if (!Tn && null !== In) { + Tn = !0; + var i = 0; + try { + var s = In; + gg(99, function () { + for (; i < s.length; i++) { + var u = s[i]; + do { + u = u(!0); + } while (null !== u); + } + }), + (In = null); + } catch (s) { + throw (null !== In && (In = In.slice(i + 1)), vn(xn, ig), s); + } finally { + Tn = !1; + } + } + } + var Bn = ie.ReactCurrentBatchConfig; + function lg(i, s) { + if (i && i.defaultProps) { + for (var u in ((s = v({}, s)), (i = i.defaultProps))) void 0 === s[u] && (s[u] = i[u]); + return s; + } + return s; + } + var Dn = Bf(null), + Ln = null, + Fn = null, + qn = null; + function qg() { + qn = Fn = Ln = null; + } + function rg(i) { + var s = Dn.current; + H(Dn), (i.type._context._currentValue = s); + } + function sg(i, s) { + for (; null !== i; ) { + var u = i.alternate; + if ((i.childLanes & s) === s) { + if (null === u || (u.childLanes & s) === s) break; + u.childLanes |= s; + } else (i.childLanes |= s), null !== u && (u.childLanes |= s); + i = i.return; + } + } + function tg(i, s) { + (Ln = i), (qn = Fn = null), null !== (i = i.dependencies) && null !== i.firstContext && (0 != (i.lanes & s) && (go = !0), (i.firstContext = null)); + } + function vg(i, s) { + if (qn !== i && !1 !== s && 0 !== s) + if ((('number' == typeof s && 1073741823 !== s) || ((qn = i), (s = 1073741823)), (s = { context: i, observedBits: s, next: null }), null === Fn)) { + if (null === Ln) throw Error(y(308)); + (Fn = s), (Ln.dependencies = { lanes: 0, firstContext: s, responders: null }); + } else Fn = Fn.next = s; + return i._currentValue; + } + var $n = !1; + function xg(i) { + i.updateQueue = { baseState: i.memoizedState, firstBaseUpdate: null, lastBaseUpdate: null, shared: { pending: null }, effects: null }; + } + function yg(i, s) { + (i = i.updateQueue), s.updateQueue === i && (s.updateQueue = { baseState: i.baseState, firstBaseUpdate: i.firstBaseUpdate, lastBaseUpdate: i.lastBaseUpdate, shared: i.shared, effects: i.effects }); + } + function zg(i, s) { + return { eventTime: i, lane: s, tag: 0, payload: null, callback: null, next: null }; + } + function Ag(i, s) { + if (null !== (i = i.updateQueue)) { + var u = (i = i.shared).pending; + null === u ? (s.next = s) : ((s.next = u.next), (u.next = s)), (i.pending = s); + } + } + function Bg(i, s) { + var u = i.updateQueue, + m = i.alternate; + if (null !== m && u === (m = m.updateQueue)) { + var v = null, + _ = null; + if (null !== (u = u.firstBaseUpdate)) { + do { + var j = { eventTime: u.eventTime, lane: u.lane, tag: u.tag, payload: u.payload, callback: u.callback, next: null }; + null === _ ? (v = _ = j) : (_ = _.next = j), (u = u.next); + } while (null !== u); + null === _ ? (v = _ = s) : (_ = _.next = s); + } else v = _ = s; + return (u = { baseState: m.baseState, firstBaseUpdate: v, lastBaseUpdate: _, shared: m.shared, effects: m.effects }), void (i.updateQueue = u); + } + null === (i = u.lastBaseUpdate) ? (u.firstBaseUpdate = s) : (i.next = s), (u.lastBaseUpdate = s); + } + function Cg(i, s, u, m) { + var _ = i.updateQueue; + $n = !1; + var j = _.firstBaseUpdate, + M = _.lastBaseUpdate, + $ = _.shared.pending; + if (null !== $) { + _.shared.pending = null; + var W = $, + X = W.next; + (W.next = null), null === M ? (j = X) : (M.next = X), (M = W); + var Y = i.alternate; + if (null !== Y) { + var Z = (Y = Y.updateQueue).lastBaseUpdate; + Z !== M && (null === Z ? (Y.firstBaseUpdate = X) : (Z.next = X), (Y.lastBaseUpdate = W)); + } + } + if (null !== j) { + for (Z = _.baseState, M = 0, Y = X = W = null; ; ) { + $ = j.lane; + var ee = j.eventTime; + if ((m & $) === $) { + null !== Y && (Y = Y.next = { eventTime: ee, lane: 0, tag: j.tag, payload: j.payload, callback: j.callback, next: null }); + e: { + var ae = i, + ie = j; + switch ((($ = s), (ee = u), ie.tag)) { + case 1: + if ('function' == typeof (ae = ie.payload)) { + Z = ae.call(ee, Z, $); + break e; + } + Z = ae; + break e; + case 3: + ae.flags = (-4097 & ae.flags) | 64; + case 0: + if (null == ($ = 'function' == typeof (ae = ie.payload) ? ae.call(ee, Z, $) : ae)) break e; + Z = v({}, Z, $); + break e; + case 2: + $n = !0; + } + } + null !== j.callback && ((i.flags |= 32), null === ($ = _.effects) ? (_.effects = [j]) : $.push(j)); + } else (ee = { eventTime: ee, lane: $, tag: j.tag, payload: j.payload, callback: j.callback, next: null }), null === Y ? ((X = Y = ee), (W = Z)) : (Y = Y.next = ee), (M |= $); + if (null === (j = j.next)) { + if (null === ($ = _.shared.pending)) break; + (j = $.next), ($.next = null), (_.lastBaseUpdate = $), (_.shared.pending = null); + } + } + null === Y && (W = Z), (_.baseState = W), (_.firstBaseUpdate = X), (_.lastBaseUpdate = Y), (Bo |= M), (i.lanes = M), (i.memoizedState = Z); + } + } + function Eg(i, s, u) { + if (((i = s.effects), (s.effects = null), null !== i)) + for (s = 0; s < i.length; s++) { + var m = i[s], + v = m.callback; + if (null !== v) { + if (((m.callback = null), (m = u), 'function' != typeof v)) throw Error(y(191, v)); + v.call(m); + } + } + } + var zn = new m.Component().refs; + function Gg(i, s, u, m) { + (u = null == (u = u(m, (s = i.memoizedState))) ? s : v({}, s, u)), (i.memoizedState = u), 0 === i.lanes && (i.updateQueue.baseState = u); + } + var Un = { + isMounted: function (i) { + return !!(i = i._reactInternals) && Zb(i) === i; + }, + enqueueSetState: function (i, s, u) { + i = i._reactInternals; + var m = Hg(), + v = Ig(i), + _ = zg(m, v); + (_.payload = s), null != u && (_.callback = u), Ag(i, _), Jg(i, v, m); + }, + enqueueReplaceState: function (i, s, u) { + i = i._reactInternals; + var m = Hg(), + v = Ig(i), + _ = zg(m, v); + (_.tag = 1), (_.payload = s), null != u && (_.callback = u), Ag(i, _), Jg(i, v, m); + }, + enqueueForceUpdate: function (i, s) { + i = i._reactInternals; + var u = Hg(), + m = Ig(i), + v = zg(u, m); + (v.tag = 2), null != s && (v.callback = s), Ag(i, v), Jg(i, m, u); + } + }; + function Lg(i, s, u, m, v, _, j) { + return 'function' == typeof (i = i.stateNode).shouldComponentUpdate ? i.shouldComponentUpdate(m, _, j) : !s.prototype || !s.prototype.isPureReactComponent || !Je(u, m) || !Je(v, _); + } + function Mg(i, s, u) { + var m = !1, + v = pn, + _ = s.contextType; + return 'object' == typeof _ && null !== _ ? (_ = vg(_)) : ((v = Ff(s) ? fn : hn.current), (_ = (m = null != (m = s.contextTypes)) ? Ef(i, v) : pn)), (s = new s(u, _)), (i.memoizedState = null !== s.state && void 0 !== s.state ? s.state : null), (s.updater = Un), (i.stateNode = s), (s._reactInternals = i), m && (((i = i.stateNode).__reactInternalMemoizedUnmaskedChildContext = v), (i.__reactInternalMemoizedMaskedChildContext = _)), s; + } + function Ng(i, s, u, m) { + (i = s.state), 'function' == typeof s.componentWillReceiveProps && s.componentWillReceiveProps(u, m), 'function' == typeof s.UNSAFE_componentWillReceiveProps && s.UNSAFE_componentWillReceiveProps(u, m), s.state !== i && Un.enqueueReplaceState(s, s.state, null); + } + function Og(i, s, u, m) { + var v = i.stateNode; + (v.props = u), (v.state = i.memoizedState), (v.refs = zn), xg(i); + var _ = s.contextType; + 'object' == typeof _ && null !== _ ? (v.context = vg(_)) : ((_ = Ff(s) ? fn : hn.current), (v.context = Ef(i, _))), Cg(i, u, v, m), (v.state = i.memoizedState), 'function' == typeof (_ = s.getDerivedStateFromProps) && (Gg(i, s, _, u), (v.state = i.memoizedState)), 'function' == typeof s.getDerivedStateFromProps || 'function' == typeof v.getSnapshotBeforeUpdate || ('function' != typeof v.UNSAFE_componentWillMount && 'function' != typeof v.componentWillMount) || ((s = v.state), 'function' == typeof v.componentWillMount && v.componentWillMount(), 'function' == typeof v.UNSAFE_componentWillMount && v.UNSAFE_componentWillMount(), s !== v.state && Un.enqueueReplaceState(v, v.state, null), Cg(i, u, v, m), (v.state = i.memoizedState)), 'function' == typeof v.componentDidMount && (i.flags |= 4); + } + var Vn = Array.isArray; + function Qg(i, s, u) { + if (null !== (i = u.ref) && 'function' != typeof i && 'object' != typeof i) { + if (u._owner) { + if ((u = u._owner)) { + if (1 !== u.tag) throw Error(y(309)); + var m = u.stateNode; + } + if (!m) throw Error(y(147, i)); + var v = '' + i; + return null !== s && null !== s.ref && 'function' == typeof s.ref && s.ref._stringRef === v ? + s.ref + : ((s = function (i) { + var s = m.refs; + s === zn && (s = m.refs = {}), null === i ? delete s[v] : (s[v] = i); + }), + (s._stringRef = v), + s); + } + if ('string' != typeof i) throw Error(y(284)); + if (!u._owner) throw Error(y(290, i)); + } + return i; + } + function Rg(i, s) { + if ('textarea' !== i.type) throw Error(y(31, '[object Object]' === Object.prototype.toString.call(s) ? 'object with keys {' + Object.keys(s).join(', ') + '}' : s)); + } + function Sg(i) { + function b(s, u) { + if (i) { + var m = s.lastEffect; + null !== m ? ((m.nextEffect = u), (s.lastEffect = u)) : (s.firstEffect = s.lastEffect = u), (u.nextEffect = null), (u.flags = 8); + } + } + function c(s, u) { + if (!i) return null; + for (; null !== u; ) b(s, u), (u = u.sibling); + return null; + } + function d(i, s) { + for (i = new Map(); null !== s; ) null !== s.key ? i.set(s.key, s) : i.set(s.index, s), (s = s.sibling); + return i; + } + function e(i, s) { + return ((i = Tg(i, s)).index = 0), (i.sibling = null), i; + } + function f(s, u, m) { + return ( + (s.index = m), + i ? + null !== (m = s.alternate) ? + (m = m.index) < u ? + ((s.flags = 2), u) + : m + : ((s.flags = 2), u) + : u + ); + } + function g(s) { + return i && null === s.alternate && (s.flags = 2), s; + } + function h(i, s, u, m) { + return null === s || 6 !== s.tag ? (((s = Ug(u, i.mode, m)).return = i), s) : (((s = e(s, u)).return = i), s); + } + function k(i, s, u, m) { + return null !== s && s.elementType === u.type ? (((m = e(s, u.props)).ref = Qg(i, s, u)), (m.return = i), m) : (((m = Vg(u.type, u.key, u.props, null, i.mode, m)).ref = Qg(i, s, u)), (m.return = i), m); + } + function l(i, s, u, m) { + return null === s || 4 !== s.tag || s.stateNode.containerInfo !== u.containerInfo || s.stateNode.implementation !== u.implementation ? (((s = Wg(u, i.mode, m)).return = i), s) : (((s = e(s, u.children || [])).return = i), s); + } + function n(i, s, u, m, v) { + return null === s || 7 !== s.tag ? (((s = Xg(u, i.mode, m, v)).return = i), s) : (((s = e(s, u)).return = i), s); + } + function A(i, s, u) { + if ('string' == typeof s || 'number' == typeof s) return ((s = Ug('' + s, i.mode, u)).return = i), s; + if ('object' == typeof s && null !== s) { + switch (s.$$typeof) { + case le: + return ((u = Vg(s.type, s.key, s.props, null, i.mode, u)).ref = Qg(i, null, s)), (u.return = i), u; + case ce: + return ((s = Wg(s, i.mode, u)).return = i), s; + } + if (Vn(s) || La(s)) return ((s = Xg(s, i.mode, u, null)).return = i), s; + Rg(i, s); + } + return null; + } + function p(i, s, u, m) { + var v = null !== s ? s.key : null; + if ('string' == typeof u || 'number' == typeof u) return null !== v ? null : h(i, s, '' + u, m); + if ('object' == typeof u && null !== u) { + switch (u.$$typeof) { + case le: + return ( + u.key === v ? + u.type === pe ? + n(i, s, u.props.children, m, v) + : k(i, s, u, m) + : null + ); + case ce: + return u.key === v ? l(i, s, u, m) : null; + } + if (Vn(u) || La(u)) return null !== v ? null : n(i, s, u, m, null); + Rg(i, u); + } + return null; + } + function C(i, s, u, m, v) { + if ('string' == typeof m || 'number' == typeof m) return h(s, (i = i.get(u) || null), '' + m, v); + if ('object' == typeof m && null !== m) { + switch (m.$$typeof) { + case le: + return (i = i.get(null === m.key ? u : m.key) || null), m.type === pe ? n(s, i, m.props.children, v, m.key) : k(s, i, m, v); + case ce: + return l(s, (i = i.get(null === m.key ? u : m.key) || null), m, v); + } + if (Vn(m) || La(m)) return n(s, (i = i.get(u) || null), m, v, null); + Rg(s, m); + } + return null; + } + function x(s, u, m, v) { + for (var _ = null, j = null, M = u, $ = (u = 0), W = null; null !== M && $ < m.length; $++) { + M.index > $ ? ((W = M), (M = null)) : (W = M.sibling); + var X = p(s, M, m[$], v); + if (null === X) { + null === M && (M = W); + break; + } + i && M && null === X.alternate && b(s, M), (u = f(X, u, $)), null === j ? (_ = X) : (j.sibling = X), (j = X), (M = W); + } + if ($ === m.length) return c(s, M), _; + if (null === M) { + for (; $ < m.length; $++) null !== (M = A(s, m[$], v)) && ((u = f(M, u, $)), null === j ? (_ = M) : (j.sibling = M), (j = M)); + return _; + } + for (M = d(s, M); $ < m.length; $++) null !== (W = C(M, s, $, m[$], v)) && (i && null !== W.alternate && M.delete(null === W.key ? $ : W.key), (u = f(W, u, $)), null === j ? (_ = W) : (j.sibling = W), (j = W)); + return ( + i && + M.forEach(function (i) { + return b(s, i); + }), + _ + ); + } + function w(s, u, m, v) { + var _ = La(m); + if ('function' != typeof _) throw Error(y(150)); + if (null == (m = _.call(m))) throw Error(y(151)); + for (var j = (_ = null), M = u, $ = (u = 0), W = null, X = m.next(); null !== M && !X.done; $++, X = m.next()) { + M.index > $ ? ((W = M), (M = null)) : (W = M.sibling); + var Y = p(s, M, X.value, v); + if (null === Y) { + null === M && (M = W); + break; + } + i && M && null === Y.alternate && b(s, M), (u = f(Y, u, $)), null === j ? (_ = Y) : (j.sibling = Y), (j = Y), (M = W); + } + if (X.done) return c(s, M), _; + if (null === M) { + for (; !X.done; $++, X = m.next()) null !== (X = A(s, X.value, v)) && ((u = f(X, u, $)), null === j ? (_ = X) : (j.sibling = X), (j = X)); + return _; + } + for (M = d(s, M); !X.done; $++, X = m.next()) null !== (X = C(M, s, $, X.value, v)) && (i && null !== X.alternate && M.delete(null === X.key ? $ : X.key), (u = f(X, u, $)), null === j ? (_ = X) : (j.sibling = X), (j = X)); + return ( + i && + M.forEach(function (i) { + return b(s, i); + }), + _ + ); + } + return function (i, s, u, m) { + var v = 'object' == typeof u && null !== u && u.type === pe && null === u.key; + v && (u = u.props.children); + var _ = 'object' == typeof u && null !== u; + if (_) + switch (u.$$typeof) { + case le: + e: { + for (_ = u.key, v = s; null !== v; ) { + if (v.key === _) { + if (7 === v.tag) { + if (u.type === pe) { + c(i, v.sibling), ((s = e(v, u.props.children)).return = i), (i = s); + break e; + } + } else if (v.elementType === u.type) { + c(i, v.sibling), ((s = e(v, u.props)).ref = Qg(i, v, u)), (s.return = i), (i = s); + break e; + } + c(i, v); + break; + } + b(i, v), (v = v.sibling); + } + u.type === pe ? (((s = Xg(u.props.children, i.mode, m, u.key)).return = i), (i = s)) : (((m = Vg(u.type, u.key, u.props, null, i.mode, m)).ref = Qg(i, s, u)), (m.return = i), (i = m)); + } + return g(i); + case ce: + e: { + for (v = u.key; null !== s; ) { + if (s.key === v) { + if (4 === s.tag && s.stateNode.containerInfo === u.containerInfo && s.stateNode.implementation === u.implementation) { + c(i, s.sibling), ((s = e(s, u.children || [])).return = i), (i = s); + break e; + } + c(i, s); + break; + } + b(i, s), (s = s.sibling); + } + ((s = Wg(u, i.mode, m)).return = i), (i = s); + } + return g(i); + } + if ('string' == typeof u || 'number' == typeof u) return (u = '' + u), null !== s && 6 === s.tag ? (c(i, s.sibling), ((s = e(s, u)).return = i), (i = s)) : (c(i, s), ((s = Ug(u, i.mode, m)).return = i), (i = s)), g(i); + if (Vn(u)) return x(i, s, u, m); + if (La(u)) return w(i, s, u, m); + if ((_ && Rg(i, u), void 0 === u && !v)) + switch (i.tag) { + case 1: + case 22: + case 0: + case 11: + case 15: + throw Error(y(152, Ra(i.type) || 'Component')); + } + return c(i, s); + }; + } + var Wn = Sg(!0), + Kn = Sg(!1), + Hn = {}, + Jn = Bf(Hn), + Gn = Bf(Hn), + Xn = Bf(Hn); + function dh(i) { + if (i === Hn) throw Error(y(174)); + return i; + } + function eh(i, s) { + switch ((I(Xn, s), I(Gn, i), I(Jn, Hn), (i = s.nodeType))) { + case 9: + case 11: + s = (s = s.documentElement) ? s.namespaceURI : mb(null, ''); + break; + default: + s = mb((s = (i = 8 === i ? s.parentNode : s).namespaceURI || null), (i = i.tagName)); + } + H(Jn), I(Jn, s); + } + function fh() { + H(Jn), H(Gn), H(Xn); + } + function gh(i) { + dh(Xn.current); + var s = dh(Jn.current), + u = mb(s, i.type); + s !== u && (I(Gn, i), I(Jn, u)); + } + function hh(i) { + Gn.current === i && (H(Jn), H(Gn)); + } + var Yn = Bf(0); + function ih(i) { + for (var s = i; null !== s; ) { + if (13 === s.tag) { + var u = s.memoizedState; + if (null !== u && (null === (u = u.dehydrated) || '$?' === u.data || '$!' === u.data)) return s; + } else if (19 === s.tag && void 0 !== s.memoizedProps.revealOrder) { + if (0 != (64 & s.flags)) return s; + } else if (null !== s.child) { + (s.child.return = s), (s = s.child); + continue; + } + if (s === i) break; + for (; null === s.sibling; ) { + if (null === s.return || s.return === i) return null; + s = s.return; + } + (s.sibling.return = s.return), (s = s.sibling); + } + return null; + } + var Qn = null, + Zn = null, + eo = !1; + function mh(i, s) { + var u = nh(5, null, null, 0); + (u.elementType = 'DELETED'), (u.type = 'DELETED'), (u.stateNode = s), (u.return = i), (u.flags = 8), null !== i.lastEffect ? ((i.lastEffect.nextEffect = u), (i.lastEffect = u)) : (i.firstEffect = i.lastEffect = u); + } + function oh(i, s) { + switch (i.tag) { + case 5: + var u = i.type; + return null !== (s = 1 !== s.nodeType || u.toLowerCase() !== s.nodeName.toLowerCase() ? null : s) && ((i.stateNode = s), !0); + case 6: + return null !== (s = '' === i.pendingProps || 3 !== s.nodeType ? null : s) && ((i.stateNode = s), !0); + default: + return !1; + } + } + function ph(i) { + if (eo) { + var s = Zn; + if (s) { + var u = s; + if (!oh(i, s)) { + if (!(s = rf(u.nextSibling)) || !oh(i, s)) return (i.flags = (-1025 & i.flags) | 2), (eo = !1), void (Qn = i); + mh(Qn, u); + } + (Qn = i), (Zn = rf(s.firstChild)); + } else (i.flags = (-1025 & i.flags) | 2), (eo = !1), (Qn = i); + } + } + function qh(i) { + for (i = i.return; null !== i && 5 !== i.tag && 3 !== i.tag && 13 !== i.tag; ) i = i.return; + Qn = i; + } + function rh(i) { + if (i !== Qn) return !1; + if (!eo) return qh(i), (eo = !0), !1; + var s = i.type; + if (5 !== i.tag || ('head' !== s && 'body' !== s && !nf(s, i.memoizedProps))) for (s = Zn; s; ) mh(i, s), (s = rf(s.nextSibling)); + if ((qh(i), 13 === i.tag)) { + if (!(i = null !== (i = i.memoizedState) ? i.dehydrated : null)) throw Error(y(317)); + e: { + for (i = i.nextSibling, s = 0; i; ) { + if (8 === i.nodeType) { + var u = i.data; + if ('/$' === u) { + if (0 === s) { + Zn = rf(i.nextSibling); + break e; + } + s--; + } else ('$' !== u && '$!' !== u && '$?' !== u) || s++; + } + i = i.nextSibling; + } + Zn = null; + } + } else Zn = Qn ? rf(i.stateNode.nextSibling) : null; + return !0; + } + function sh() { + (Zn = Qn = null), (eo = !1); + } + var to = []; + function uh() { + for (var i = 0; i < to.length; i++) to[i]._workInProgressVersionPrimary = null; + to.length = 0; + } + var ro = ie.ReactCurrentDispatcher, + no = ie.ReactCurrentBatchConfig, + oo = 0, + ao = null, + io = null, + so = null, + lo = !1, + co = !1; + function Ah() { + throw Error(y(321)); + } + function Bh(i, s) { + if (null === s) return !1; + for (var u = 0; u < s.length && u < i.length; u++) if (!qr(i[u], s[u])) return !1; + return !0; + } + function Ch(i, s, u, m, v, _) { + if (((oo = _), (ao = s), (s.memoizedState = null), (s.updateQueue = null), (s.lanes = 0), (ro.current = null === i || null === i.memoizedState ? po : ho), (i = u(m, v)), co)) { + _ = 0; + do { + if (((co = !1), !(25 > _))) throw Error(y(301)); + (_ += 1), (so = io = null), (s.updateQueue = null), (ro.current = fo), (i = u(m, v)); + } while (co); + } + if (((ro.current = uo), (s = null !== io && null !== io.next), (oo = 0), (so = io = ao = null), (lo = !1), s)) throw Error(y(300)); + return i; + } + function Hh() { + var i = { memoizedState: null, baseState: null, baseQueue: null, queue: null, next: null }; + return null === so ? (ao.memoizedState = so = i) : (so = so.next = i), so; + } + function Ih() { + if (null === io) { + var i = ao.alternate; + i = null !== i ? i.memoizedState : null; + } else i = io.next; + var s = null === so ? ao.memoizedState : so.next; + if (null !== s) (so = s), (io = i); + else { + if (null === i) throw Error(y(310)); + (i = { memoizedState: (io = i).memoizedState, baseState: io.baseState, baseQueue: io.baseQueue, queue: io.queue, next: null }), null === so ? (ao.memoizedState = so = i) : (so = so.next = i); + } + return so; + } + function Jh(i, s) { + return 'function' == typeof s ? s(i) : s; + } + function Kh(i) { + var s = Ih(), + u = s.queue; + if (null === u) throw Error(y(311)); + u.lastRenderedReducer = i; + var m = io, + v = m.baseQueue, + _ = u.pending; + if (null !== _) { + if (null !== v) { + var j = v.next; + (v.next = _.next), (_.next = j); + } + (m.baseQueue = v = _), (u.pending = null); + } + if (null !== v) { + (v = v.next), (m = m.baseState); + var M = (j = _ = null), + $ = v; + do { + var W = $.lane; + if ((oo & W) === W) null !== M && (M = M.next = { lane: 0, action: $.action, eagerReducer: $.eagerReducer, eagerState: $.eagerState, next: null }), (m = $.eagerReducer === i ? $.eagerState : i(m, $.action)); + else { + var X = { lane: W, action: $.action, eagerReducer: $.eagerReducer, eagerState: $.eagerState, next: null }; + null === M ? ((j = M = X), (_ = m)) : (M = M.next = X), (ao.lanes |= W), (Bo |= W); + } + $ = $.next; + } while (null !== $ && $ !== v); + null === M ? (_ = m) : (M.next = j), qr(m, s.memoizedState) || (go = !0), (s.memoizedState = m), (s.baseState = _), (s.baseQueue = M), (u.lastRenderedState = m); + } + return [s.memoizedState, u.dispatch]; + } + function Lh(i) { + var s = Ih(), + u = s.queue; + if (null === u) throw Error(y(311)); + u.lastRenderedReducer = i; + var m = u.dispatch, + v = u.pending, + _ = s.memoizedState; + if (null !== v) { + u.pending = null; + var j = (v = v.next); + do { + (_ = i(_, j.action)), (j = j.next); + } while (j !== v); + qr(_, s.memoizedState) || (go = !0), (s.memoizedState = _), null === s.baseQueue && (s.baseState = _), (u.lastRenderedState = _); + } + return [_, m]; + } + function Mh(i, s, u) { + var m = s._getVersion; + m = m(s._source); + var v = s._workInProgressVersionPrimary; + if ((null !== v ? (i = v === m) : ((i = i.mutableReadLanes), (i = (oo & i) === i) && ((s._workInProgressVersionPrimary = m), to.push(s))), i)) return u(s._source); + throw (to.push(s), Error(y(350))); + } + function Nh(i, s, u, m) { + var v = Co; + if (null === v) throw Error(y(349)); + var _ = s._getVersion, + j = _(s._source), + M = ro.current, + $ = M.useState(function () { + return Mh(v, s, u); + }), + W = $[1], + X = $[0]; + $ = so; + var Y = i.memoizedState, + Z = Y.refs, + ee = Z.getSnapshot, + ae = Y.source; + Y = Y.subscribe; + var ie = ao; + return ( + (i.memoizedState = { refs: Z, source: s, subscribe: m }), + M.useEffect( + function () { + (Z.getSnapshot = u), (Z.setSnapshot = W); + var i = _(s._source); + if (!qr(j, i)) { + (i = u(s._source)), qr(X, i) || (W(i), (i = Ig(ie)), (v.mutableReadLanes |= i & v.pendingLanes)), (i = v.mutableReadLanes), (v.entangledLanes |= i); + for (var m = v.entanglements, M = i; 0 < M; ) { + var $ = 31 - Ut(M), + Y = 1 << $; + (m[$] |= i), (M &= ~Y); + } + } + }, + [u, s, m] + ), + M.useEffect( + function () { + return m(s._source, function () { + var i = Z.getSnapshot, + u = Z.setSnapshot; + try { + u(i(s._source)); + var m = Ig(ie); + v.mutableReadLanes |= m & v.pendingLanes; + } catch (i) { + u(function () { + throw i; + }); + } + }); + }, + [s, m] + ), + (qr(ee, u) && qr(ae, s) && qr(Y, m)) || (((i = { pending: null, dispatch: null, lastRenderedReducer: Jh, lastRenderedState: X }).dispatch = W = Oh.bind(null, ao, i)), ($.queue = i), ($.baseQueue = null), (X = Mh(v, s, u)), ($.memoizedState = $.baseState = X)), + X + ); + } + function Ph(i, s, u) { + return Nh(Ih(), i, s, u); + } + function Qh(i) { + var s = Hh(); + return 'function' == typeof i && (i = i()), (s.memoizedState = s.baseState = i), (i = (i = s.queue = { pending: null, dispatch: null, lastRenderedReducer: Jh, lastRenderedState: i }).dispatch = Oh.bind(null, ao, i)), [s.memoizedState, i]; + } + function Rh(i, s, u, m) { + return ( + (i = { tag: i, create: s, destroy: u, deps: m, next: null }), + null === (s = ao.updateQueue) ? ((s = { lastEffect: null }), (ao.updateQueue = s), (s.lastEffect = i.next = i)) + : null === (u = s.lastEffect) ? (s.lastEffect = i.next = i) + : ((m = u.next), (u.next = i), (i.next = m), (s.lastEffect = i)), + i + ); + } + function Sh(i) { + return (i = { current: i }), (Hh().memoizedState = i); + } + function Th() { + return Ih().memoizedState; + } + function Uh(i, s, u, m) { + var v = Hh(); + (ao.flags |= i), (v.memoizedState = Rh(1 | s, u, void 0, void 0 === m ? null : m)); + } + function Vh(i, s, u, m) { + var v = Ih(); + m = void 0 === m ? null : m; + var _ = void 0; + if (null !== io) { + var j = io.memoizedState; + if (((_ = j.destroy), null !== m && Bh(m, j.deps))) return void Rh(s, u, _, m); + } + (ao.flags |= i), (v.memoizedState = Rh(1 | s, u, _, m)); + } + function Wh(i, s) { + return Uh(516, 4, i, s); + } + function Xh(i, s) { + return Vh(516, 4, i, s); + } + function Yh(i, s) { + return Vh(4, 2, i, s); + } + function Zh(i, s) { + return ( + 'function' == typeof s ? + ((i = i()), + s(i), + function () { + s(null); + }) + : null != s ? + ((i = i()), + (s.current = i), + function () { + s.current = null; + }) + : void 0 + ); + } + function $h(i, s, u) { + return (u = null != u ? u.concat([i]) : null), Vh(4, 2, Zh.bind(null, s, i), u); + } + function ai() {} + function bi(i, s) { + var u = Ih(); + s = void 0 === s ? null : s; + var m = u.memoizedState; + return null !== m && null !== s && Bh(s, m[1]) ? m[0] : ((u.memoizedState = [i, s]), i); + } + function ci(i, s) { + var u = Ih(); + s = void 0 === s ? null : s; + var m = u.memoizedState; + return null !== m && null !== s && Bh(s, m[1]) ? m[0] : ((i = i()), (u.memoizedState = [i, s]), i); + } + function di(i, s) { + var u = eg(); + gg(98 > u ? 98 : u, function () { + i(!0); + }), + gg(97 < u ? 97 : u, function () { + var u = no.transition; + no.transition = 1; + try { + i(!1), s(); + } finally { + no.transition = u; + } + }); + } + function Oh(i, s, u) { + var m = Hg(), + v = Ig(i), + _ = { lane: v, action: u, eagerReducer: null, eagerState: null, next: null }, + j = s.pending; + if ((null === j ? (_.next = _) : ((_.next = j.next), (j.next = _)), (s.pending = _), (j = i.alternate), i === ao || (null !== j && j === ao))) co = lo = !0; + else { + if (0 === i.lanes && (null === j || 0 === j.lanes) && null !== (j = s.lastRenderedReducer)) + try { + var M = s.lastRenderedState, + $ = j(M, u); + if (((_.eagerReducer = j), (_.eagerState = $), qr($, M))) return; + } catch (i) {} + Jg(i, v, m); + } + } + var uo = { readContext: vg, useCallback: Ah, useContext: Ah, useEffect: Ah, useImperativeHandle: Ah, useLayoutEffect: Ah, useMemo: Ah, useReducer: Ah, useRef: Ah, useState: Ah, useDebugValue: Ah, useDeferredValue: Ah, useTransition: Ah, useMutableSource: Ah, useOpaqueIdentifier: Ah, unstable_isNewReconciler: !1 }, + po = { + readContext: vg, + useCallback: function (i, s) { + return (Hh().memoizedState = [i, void 0 === s ? null : s]), i; + }, + useContext: vg, + useEffect: Wh, + useImperativeHandle: function (i, s, u) { + return (u = null != u ? u.concat([i]) : null), Uh(4, 2, Zh.bind(null, s, i), u); + }, + useLayoutEffect: function (i, s) { + return Uh(4, 2, i, s); + }, + useMemo: function (i, s) { + var u = Hh(); + return (s = void 0 === s ? null : s), (i = i()), (u.memoizedState = [i, s]), i; + }, + useReducer: function (i, s, u) { + var m = Hh(); + return (s = void 0 !== u ? u(s) : s), (m.memoizedState = m.baseState = s), (i = (i = m.queue = { pending: null, dispatch: null, lastRenderedReducer: i, lastRenderedState: s }).dispatch = Oh.bind(null, ao, i)), [m.memoizedState, i]; + }, + useRef: Sh, + useState: Qh, + useDebugValue: ai, + useDeferredValue: function (i) { + var s = Qh(i), + u = s[0], + m = s[1]; + return ( + Wh( + function () { + var s = no.transition; + no.transition = 1; + try { + m(i); + } finally { + no.transition = s; + } + }, + [i] + ), + u + ); + }, + useTransition: function () { + var i = Qh(!1), + s = i[0]; + return Sh((i = di.bind(null, i[1]))), [i, s]; + }, + useMutableSource: function (i, s, u) { + var m = Hh(); + return (m.memoizedState = { refs: { getSnapshot: s, setSnapshot: null }, source: i, subscribe: u }), Nh(m, i, s, u); + }, + useOpaqueIdentifier: function () { + if (eo) { + var i = !1, + s = (function uf(i) { + return { $$typeof: Te, toString: i, valueOf: i }; + })(function () { + throw (i || ((i = !0), u('r:' + (rn++).toString(36))), Error(y(355))); + }), + u = Qh(s)[1]; + return ( + 0 == (2 & ao.mode) && + ((ao.flags |= 516), + Rh( + 5, + function () { + u('r:' + (rn++).toString(36)); + }, + void 0, + null + )), + s + ); + } + return Qh((s = 'r:' + (rn++).toString(36))), s; + }, + unstable_isNewReconciler: !1 + }, + ho = { + readContext: vg, + useCallback: bi, + useContext: vg, + useEffect: Xh, + useImperativeHandle: $h, + useLayoutEffect: Yh, + useMemo: ci, + useReducer: Kh, + useRef: Th, + useState: function () { + return Kh(Jh); + }, + useDebugValue: ai, + useDeferredValue: function (i) { + var s = Kh(Jh), + u = s[0], + m = s[1]; + return ( + Xh( + function () { + var s = no.transition; + no.transition = 1; + try { + m(i); + } finally { + no.transition = s; + } + }, + [i] + ), + u + ); + }, + useTransition: function () { + var i = Kh(Jh)[0]; + return [Th().current, i]; + }, + useMutableSource: Ph, + useOpaqueIdentifier: function () { + return Kh(Jh)[0]; + }, + unstable_isNewReconciler: !1 + }, + fo = { + readContext: vg, + useCallback: bi, + useContext: vg, + useEffect: Xh, + useImperativeHandle: $h, + useLayoutEffect: Yh, + useMemo: ci, + useReducer: Lh, + useRef: Th, + useState: function () { + return Lh(Jh); + }, + useDebugValue: ai, + useDeferredValue: function (i) { + var s = Lh(Jh), + u = s[0], + m = s[1]; + return ( + Xh( + function () { + var s = no.transition; + no.transition = 1; + try { + m(i); + } finally { + no.transition = s; + } + }, + [i] + ), + u + ); + }, + useTransition: function () { + var i = Lh(Jh)[0]; + return [Th().current, i]; + }, + useMutableSource: Ph, + useOpaqueIdentifier: function () { + return Lh(Jh)[0]; + }, + unstable_isNewReconciler: !1 + }, + mo = ie.ReactCurrentOwner, + go = !1; + function fi(i, s, u, m) { + s.child = null === i ? Kn(s, null, u, m) : Wn(s, i.child, u, m); + } + function gi(i, s, u, m, v) { + u = u.render; + var _ = s.ref; + return tg(s, v), (m = Ch(i, s, u, m, _, v)), null === i || go ? ((s.flags |= 1), fi(i, s, m, v), s.child) : ((s.updateQueue = i.updateQueue), (s.flags &= -517), (i.lanes &= ~v), hi(i, s, v)); + } + function ii(i, s, u, m, v, _) { + if (null === i) { + var j = u.type; + return 'function' != typeof j || ji(j) || void 0 !== j.defaultProps || null !== u.compare || void 0 !== u.defaultProps ? (((i = Vg(u.type, null, m, s, s.mode, _)).ref = s.ref), (i.return = s), (s.child = i)) : ((s.tag = 15), (s.type = j), ki(i, s, j, m, v, _)); + } + return (j = i.child), 0 == (v & _) && ((v = j.memoizedProps), (u = null !== (u = u.compare) ? u : Je)(v, m) && i.ref === s.ref) ? hi(i, s, _) : ((s.flags |= 1), ((i = Tg(j, m)).ref = s.ref), (i.return = s), (s.child = i)); + } + function ki(i, s, u, m, v, _) { + if (null !== i && Je(i.memoizedProps, m) && i.ref === s.ref) { + if (((go = !1), 0 == (_ & v))) return (s.lanes = i.lanes), hi(i, s, _); + 0 != (16384 & i.flags) && (go = !0); + } + return li(i, s, u, m, _); + } + function mi(i, s, u) { + var m = s.pendingProps, + v = m.children, + _ = null !== i ? i.memoizedState : null; + if ('hidden' === m.mode || 'unstable-defer-without-hiding' === m.mode) + if (0 == (4 & s.mode)) (s.memoizedState = { baseLanes: 0 }), ni(s, u); + else { + if (0 == (1073741824 & u)) return (i = null !== _ ? _.baseLanes | u : u), (s.lanes = s.childLanes = 1073741824), (s.memoizedState = { baseLanes: i }), ni(s, i), null; + (s.memoizedState = { baseLanes: 0 }), ni(s, null !== _ ? _.baseLanes : u); + } + else null !== _ ? ((m = _.baseLanes | u), (s.memoizedState = null)) : (m = u), ni(s, m); + return fi(i, s, v, u), s.child; + } + function oi(i, s) { + var u = s.ref; + ((null === i && null !== u) || (null !== i && i.ref !== u)) && (s.flags |= 128); + } + function li(i, s, u, m, v) { + var _ = Ff(u) ? fn : hn.current; + return (_ = Ef(s, _)), tg(s, v), (u = Ch(i, s, u, m, _, v)), null === i || go ? ((s.flags |= 1), fi(i, s, u, v), s.child) : ((s.updateQueue = i.updateQueue), (s.flags &= -517), (i.lanes &= ~v), hi(i, s, v)); + } + function pi(i, s, u, m, v) { + if (Ff(u)) { + var _ = !0; + Jf(s); + } else _ = !1; + if ((tg(s, v), null === s.stateNode)) null !== i && ((i.alternate = null), (s.alternate = null), (s.flags |= 2)), Mg(s, u, m), Og(s, u, m, v), (m = !0); + else if (null === i) { + var j = s.stateNode, + M = s.memoizedProps; + j.props = M; + var $ = j.context, + W = u.contextType; + 'object' == typeof W && null !== W ? (W = vg(W)) : (W = Ef(s, (W = Ff(u) ? fn : hn.current))); + var X = u.getDerivedStateFromProps, + Y = 'function' == typeof X || 'function' == typeof j.getSnapshotBeforeUpdate; + Y || ('function' != typeof j.UNSAFE_componentWillReceiveProps && 'function' != typeof j.componentWillReceiveProps) || ((M !== m || $ !== W) && Ng(s, j, m, W)), ($n = !1); + var Z = s.memoizedState; + (j.state = Z), Cg(s, m, j, v), ($ = s.memoizedState), M !== m || Z !== $ || dn.current || $n ? ('function' == typeof X && (Gg(s, u, X, m), ($ = s.memoizedState)), (M = $n || Lg(s, u, M, m, Z, $, W)) ? (Y || ('function' != typeof j.UNSAFE_componentWillMount && 'function' != typeof j.componentWillMount) || ('function' == typeof j.componentWillMount && j.componentWillMount(), 'function' == typeof j.UNSAFE_componentWillMount && j.UNSAFE_componentWillMount()), 'function' == typeof j.componentDidMount && (s.flags |= 4)) : ('function' == typeof j.componentDidMount && (s.flags |= 4), (s.memoizedProps = m), (s.memoizedState = $)), (j.props = m), (j.state = $), (j.context = W), (m = M)) : ('function' == typeof j.componentDidMount && (s.flags |= 4), (m = !1)); + } else { + (j = s.stateNode), yg(i, s), (M = s.memoizedProps), (W = s.type === s.elementType ? M : lg(s.type, M)), (j.props = W), (Y = s.pendingProps), (Z = j.context), 'object' == typeof ($ = u.contextType) && null !== $ ? ($ = vg($)) : ($ = Ef(s, ($ = Ff(u) ? fn : hn.current))); + var ee = u.getDerivedStateFromProps; + (X = 'function' == typeof ee || 'function' == typeof j.getSnapshotBeforeUpdate) || ('function' != typeof j.UNSAFE_componentWillReceiveProps && 'function' != typeof j.componentWillReceiveProps) || ((M !== Y || Z !== $) && Ng(s, j, m, $)), ($n = !1), (Z = s.memoizedState), (j.state = Z), Cg(s, m, j, v); + var ae = s.memoizedState; + M !== Y || Z !== ae || dn.current || $n ? ('function' == typeof ee && (Gg(s, u, ee, m), (ae = s.memoizedState)), (W = $n || Lg(s, u, W, m, Z, ae, $)) ? (X || ('function' != typeof j.UNSAFE_componentWillUpdate && 'function' != typeof j.componentWillUpdate) || ('function' == typeof j.componentWillUpdate && j.componentWillUpdate(m, ae, $), 'function' == typeof j.UNSAFE_componentWillUpdate && j.UNSAFE_componentWillUpdate(m, ae, $)), 'function' == typeof j.componentDidUpdate && (s.flags |= 4), 'function' == typeof j.getSnapshotBeforeUpdate && (s.flags |= 256)) : ('function' != typeof j.componentDidUpdate || (M === i.memoizedProps && Z === i.memoizedState) || (s.flags |= 4), 'function' != typeof j.getSnapshotBeforeUpdate || (M === i.memoizedProps && Z === i.memoizedState) || (s.flags |= 256), (s.memoizedProps = m), (s.memoizedState = ae)), (j.props = m), (j.state = ae), (j.context = $), (m = W)) : ('function' != typeof j.componentDidUpdate || (M === i.memoizedProps && Z === i.memoizedState) || (s.flags |= 4), 'function' != typeof j.getSnapshotBeforeUpdate || (M === i.memoizedProps && Z === i.memoizedState) || (s.flags |= 256), (m = !1)); + } + return qi(i, s, u, m, _, v); + } + function qi(i, s, u, m, v, _) { + oi(i, s); + var j = 0 != (64 & s.flags); + if (!m && !j) return v && Kf(s, u, !1), hi(i, s, _); + (m = s.stateNode), (mo.current = s); + var M = j && 'function' != typeof u.getDerivedStateFromError ? null : m.render(); + return (s.flags |= 1), null !== i && j ? ((s.child = Wn(s, i.child, null, _)), (s.child = Wn(s, null, M, _))) : fi(i, s, M, _), (s.memoizedState = m.state), v && Kf(s, u, !0), s.child; + } + function ri(i) { + var s = i.stateNode; + s.pendingContext ? Hf(0, s.pendingContext, s.pendingContext !== s.context) : s.context && Hf(0, s.context, !1), eh(i, s.containerInfo); + } + var yo, + vo, + bo, + _o, + Eo = { dehydrated: null, retryLane: 0 }; + function ti(i, s, u) { + var m, + v = s.pendingProps, + _ = Yn.current, + j = !1; + return ( + (m = 0 != (64 & s.flags)) || (m = (null === i || null !== i.memoizedState) && 0 != (2 & _)), + m ? ((j = !0), (s.flags &= -65)) : (null !== i && null === i.memoizedState) || void 0 === v.fallback || !0 === v.unstable_avoidThisFallback || (_ |= 1), + I(Yn, 1 & _), + null === i ? + (void 0 !== v.fallback && ph(s), + (i = v.children), + (_ = v.fallback), + j ? ((i = ui(s, i, _, u)), (s.child.memoizedState = { baseLanes: u }), (s.memoizedState = Eo), i) + : 'number' == typeof v.unstable_expectedLoadTime ? ((i = ui(s, i, _, u)), (s.child.memoizedState = { baseLanes: u }), (s.memoizedState = Eo), (s.lanes = 33554432), i) + : (((u = vi({ mode: 'visible', children: i }, s.mode, u, null)).return = s), (s.child = u))) + : (i.memoizedState, j ? ((v = wi(i, s, v.children, v.fallback, u)), (j = s.child), (_ = i.child.memoizedState), (j.memoizedState = null === _ ? { baseLanes: u } : { baseLanes: _.baseLanes | u }), (j.childLanes = i.childLanes & ~u), (s.memoizedState = Eo), v) : ((u = xi(i, s, v.children, u)), (s.memoizedState = null), u)) + ); + } + function ui(i, s, u, m) { + var v = i.mode, + _ = i.child; + return (s = { mode: 'hidden', children: s }), 0 == (2 & v) && null !== _ ? ((_.childLanes = 0), (_.pendingProps = s)) : (_ = vi(s, v, 0, null)), (u = Xg(u, v, m, null)), (_.return = i), (u.return = i), (_.sibling = u), (i.child = _), u; + } + function xi(i, s, u, m) { + var v = i.child; + return (i = v.sibling), (u = Tg(v, { mode: 'visible', children: u })), 0 == (2 & s.mode) && (u.lanes = m), (u.return = s), (u.sibling = null), null !== i && ((i.nextEffect = null), (i.flags = 8), (s.firstEffect = s.lastEffect = i)), (s.child = u); + } + function wi(i, s, u, m, v) { + var _ = s.mode, + j = i.child; + i = j.sibling; + var M = { mode: 'hidden', children: u }; + return 0 == (2 & _) && s.child !== j ? (((u = s.child).childLanes = 0), (u.pendingProps = M), null !== (j = u.lastEffect) ? ((s.firstEffect = u.firstEffect), (s.lastEffect = j), (j.nextEffect = null)) : (s.firstEffect = s.lastEffect = null)) : (u = Tg(j, M)), null !== i ? (m = Tg(i, m)) : ((m = Xg(m, _, v, null)).flags |= 2), (m.return = s), (u.return = s), (u.sibling = m), (s.child = u), m; + } + function yi(i, s) { + i.lanes |= s; + var u = i.alternate; + null !== u && (u.lanes |= s), sg(i.return, s); + } + function zi(i, s, u, m, v, _) { + var j = i.memoizedState; + null === j ? (i.memoizedState = { isBackwards: s, rendering: null, renderingStartTime: 0, last: m, tail: u, tailMode: v, lastEffect: _ }) : ((j.isBackwards = s), (j.rendering = null), (j.renderingStartTime = 0), (j.last = m), (j.tail = u), (j.tailMode = v), (j.lastEffect = _)); + } + function Ai(i, s, u) { + var m = s.pendingProps, + v = m.revealOrder, + _ = m.tail; + if ((fi(i, s, m.children, u), 0 != (2 & (m = Yn.current)))) (m = (1 & m) | 2), (s.flags |= 64); + else { + if (null !== i && 0 != (64 & i.flags)) + e: for (i = s.child; null !== i; ) { + if (13 === i.tag) null !== i.memoizedState && yi(i, u); + else if (19 === i.tag) yi(i, u); + else if (null !== i.child) { + (i.child.return = i), (i = i.child); + continue; + } + if (i === s) break e; + for (; null === i.sibling; ) { + if (null === i.return || i.return === s) break e; + i = i.return; + } + (i.sibling.return = i.return), (i = i.sibling); + } + m &= 1; + } + if ((I(Yn, m), 0 == (2 & s.mode))) s.memoizedState = null; + else + switch (v) { + case 'forwards': + for (u = s.child, v = null; null !== u; ) null !== (i = u.alternate) && null === ih(i) && (v = u), (u = u.sibling); + null === (u = v) ? ((v = s.child), (s.child = null)) : ((v = u.sibling), (u.sibling = null)), zi(s, !1, v, u, _, s.lastEffect); + break; + case 'backwards': + for (u = null, v = s.child, s.child = null; null !== v; ) { + if (null !== (i = v.alternate) && null === ih(i)) { + s.child = v; + break; + } + (i = v.sibling), (v.sibling = u), (u = v), (v = i); + } + zi(s, !0, u, null, _, s.lastEffect); + break; + case 'together': + zi(s, !1, null, null, void 0, s.lastEffect); + break; + default: + s.memoizedState = null; + } + return s.child; + } + function hi(i, s, u) { + if ((null !== i && (s.dependencies = i.dependencies), (Bo |= s.lanes), 0 != (u & s.childLanes))) { + if (null !== i && s.child !== i.child) throw Error(y(153)); + if (null !== s.child) { + for (u = Tg((i = s.child), i.pendingProps), s.child = u, u.return = s; null !== i.sibling; ) (i = i.sibling), ((u = u.sibling = Tg(i, i.pendingProps)).return = s); + u.sibling = null; + } + return s.child; + } + return null; + } + function Fi(i, s) { + if (!eo) + switch (i.tailMode) { + case 'hidden': + s = i.tail; + for (var u = null; null !== s; ) null !== s.alternate && (u = s), (s = s.sibling); + null === u ? (i.tail = null) : (u.sibling = null); + break; + case 'collapsed': + u = i.tail; + for (var m = null; null !== u; ) null !== u.alternate && (m = u), (u = u.sibling); + null === m ? + s || null === i.tail ? + (i.tail = null) + : (i.tail.sibling = null) + : (m.sibling = null); + } + } + function Gi(i, s, u) { + var m = s.pendingProps; + switch (s.tag) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return null; + case 1: + case 17: + return Ff(s.type) && Gf(), null; + case 3: + return fh(), H(dn), H(hn), uh(), (m = s.stateNode).pendingContext && ((m.context = m.pendingContext), (m.pendingContext = null)), (null !== i && null !== i.child) || (rh(s) ? (s.flags |= 4) : m.hydrate || (s.flags |= 256)), vo(s), null; + case 5: + hh(s); + var _ = dh(Xn.current); + if (((u = s.type), null !== i && null != s.stateNode)) bo(i, s, u, m, _), i.ref !== s.ref && (s.flags |= 128); + else { + if (!m) { + if (null === s.stateNode) throw Error(y(166)); + return null; + } + if (((i = dh(Jn.current)), rh(s))) { + (m = s.stateNode), (u = s.type); + var j = s.memoizedProps; + switch (((m[on] = s), (m[an] = j), u)) { + case 'dialog': + G('cancel', m), G('close', m); + break; + case 'iframe': + case 'object': + case 'embed': + G('load', m); + break; + case 'video': + case 'audio': + for (i = 0; i < Gr.length; i++) G(Gr[i], m); + break; + case 'source': + G('error', m); + break; + case 'img': + case 'image': + case 'link': + G('error', m), G('load', m); + break; + case 'details': + G('toggle', m); + break; + case 'input': + Za(m, j), G('invalid', m); + break; + case 'select': + (m._wrapperState = { wasMultiple: !!j.multiple }), G('invalid', m); + break; + case 'textarea': + hb(m, j), G('invalid', m); + } + for (var $ in (vb(u, j), (i = null), j)) + j.hasOwnProperty($) && + ((_ = j[$]), + 'children' === $ ? + 'string' == typeof _ ? + m.textContent !== _ && (i = ['children', _]) + : 'number' == typeof _ && m.textContent !== '' + _ && (i = ['children', '' + _]) + : M.hasOwnProperty($) && null != _ && 'onScroll' === $ && G('scroll', m)); + switch (u) { + case 'input': + Va(m), cb(m, j, !0); + break; + case 'textarea': + Va(m), jb(m); + break; + case 'select': + case 'option': + break; + default: + 'function' == typeof j.onClick && (m.onclick = jf); + } + (m = i), (s.updateQueue = m), null !== m && (s.flags |= 4); + } else { + switch ( + (($ = 9 === _.nodeType ? _ : _.ownerDocument), + i === Ye.html && (i = lb(u)), + i === Ye.html ? + 'script' === u ? (((i = $.createElement('div')).innerHTML = '