Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faf8d053dd | ||
|
|
5ece56f9b0 | ||
|
|
c4d9474f34 | ||
|
|
3b8481ccac | ||
|
|
a31d0215f5 | ||
|
|
f6cce68553 | ||
|
|
636b100b9f | ||
|
|
7a3574eaa0 | ||
|
|
9cd6176e60 | ||
|
|
f2641029cb | ||
|
|
6350e191f8 | ||
|
|
c570ba3488 | ||
|
|
b64abd24c8 | ||
|
|
13c9ab3962 | ||
|
|
b9f1c6ee79 | ||
|
|
938170a957 | ||
|
|
ca0a28c0cf | ||
|
|
c3967173a1 | ||
|
|
9ebbd9a1fd | ||
|
|
16e343ca19 | ||
|
|
1de9132f16 | ||
|
|
dad54a8e47 | ||
|
|
7d73b96b78 | ||
|
|
1260fe34aa | ||
|
|
3b4678e059 | ||
|
|
ff8294b5db | ||
|
|
7e94e19f5d | ||
|
|
ae18e2575a | ||
|
|
a5c493a29c | ||
|
|
8ee89fe51c | ||
|
|
b4909847bf | ||
|
|
568be88127 | ||
|
|
67144c1d08 | ||
|
|
285c78d41a | ||
|
|
7d15735444 | ||
|
|
4191749564 | ||
|
|
9e68dbbf09 | ||
|
|
f02ad5b051 | ||
|
|
08e20a25ed | ||
|
|
ee0468038d | ||
|
|
04afc297d9 | ||
|
|
ed06ca76e0 | ||
|
|
a68510a814 | ||
|
|
4040efab01 | ||
|
|
f08cc1061e | ||
|
|
3b5b11891e | ||
|
|
72427c9309 | ||
|
|
befe2068fd | ||
|
|
c7a3ef32fa | ||
|
|
51d394f4ef | ||
|
|
8db341dd70 | ||
|
|
5cd7fec3ab | ||
|
|
f672ecbb45 | ||
|
|
9a12b2c9b6 | ||
|
|
c31407fd87 | ||
|
|
646c81f136 | ||
|
|
aca6232d2a | ||
|
|
c61da10523 | ||
|
|
1f53d65ac2 | ||
|
|
844ab1287e | ||
|
|
d6d318b23b | ||
|
|
7504ffd934 | ||
|
|
e8078908c9 | ||
|
|
431848280f | ||
|
|
2e0c575512 | ||
|
|
ebf0d99417 | ||
|
|
423d893fee | ||
|
|
56fe0d3b04 | ||
|
|
7172d9d203 | ||
|
|
bd770a6902 | ||
|
|
628508faed | ||
|
|
826634f061 | ||
|
|
c7ed959a71 | ||
|
|
aea6befc1e | ||
|
|
7bb3484788 | ||
|
|
4eafc67a7e | ||
|
|
b5197b6f20 | ||
|
|
d306304195 | ||
|
|
35f47dae4f | ||
|
|
f1be4810d5 | ||
|
|
d4f9406869 | ||
|
|
a41b81d724 | ||
|
|
da56b86102 | ||
|
|
f12d2c9be0 | ||
|
|
322b9b4c25 | ||
|
|
fb7fe410f9 | ||
|
|
ee392a079c | ||
|
|
0502579d50 | ||
|
|
f10f3175d9 | ||
|
|
f155af99f1 | ||
|
|
0fbf3575a6 | ||
|
|
f6b9b5f54e | ||
|
|
2dadd9d8c9 | ||
|
|
5786b3cdfe | ||
|
|
769fc30c0c | ||
|
|
fb2dad9c6f | ||
|
|
c43d308a2d | ||
|
|
742a12ce6a | ||
|
|
d953f27865 | ||
|
|
4719cded95 | ||
|
|
9d489bdb69 | ||
|
|
537c307550 | ||
|
|
d5575e0323 | ||
|
|
592962bbc8 | ||
|
|
7a371c86dc | ||
|
|
0e295bebde | ||
|
|
8d98759be6 | ||
|
|
924317b01b | ||
|
|
a08a601dc3 | ||
|
|
e652c15d6c | ||
|
|
4534eb60de | ||
|
|
54c6c0c24c | ||
|
|
393694ae96 | ||
|
|
818bb730e4 | ||
|
|
61bd35a192 | ||
|
|
81f9df000a | ||
|
|
0dcb31c108 | ||
|
|
cd4140fda9 | ||
|
|
117cc25cdb | ||
|
|
832ad26151 | ||
|
|
5a344cd8ad | ||
|
|
0b0a67cdad | ||
|
|
a326a240f0 | ||
|
|
dfdb033769 | ||
|
|
a31af45d97 | ||
|
|
cae955c483 | ||
|
|
0bfff5259e | ||
|
|
0fa83e603b | ||
|
|
906b03804f | ||
|
|
1ed7a61bea | ||
|
|
ad6ae7ab05 | ||
|
|
5e2de1d47d | ||
|
|
591ca51104 | ||
|
|
b210841158 | ||
|
|
a223a3985b | ||
|
|
8baa6a73cd | ||
|
|
508efac2ea | ||
|
|
b6eed9e228 | ||
|
|
b62cad07f0 | ||
|
|
6d552d27ac | ||
|
|
39d0f2a060 | ||
|
|
0b03abee91 | ||
|
|
b4fb69d0ee | ||
|
|
5b9ed029b3 | ||
|
|
c29397371b | ||
|
|
fe47e27788 | ||
|
|
a14c702c79 | ||
|
|
fe4246036d | ||
|
|
074063b814 | ||
|
|
0271a8b721 | ||
|
|
08617383be | ||
|
|
3840459b0a | ||
|
|
aee7ac28bc |
No files matched your search
@@ -0,0 +1,14 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: wa_http_api
|
||||
open_collective: # doks Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom:
|
||||
- https://boosty.to/wa-http-api
|
||||
- https://portal.devlike.pro/
|
||||
@@ -1,8 +1,3 @@
|
||||
ignore:
|
||||
teams:
|
||||
- no-labels
|
||||
users:
|
||||
- allburov
|
||||
teamLabels:
|
||||
- team: waha-patrons-pro
|
||||
label: patron:PRO
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_IMAGE }}
|
||||
images: ${{ vars.DOCKER_IMAGE }}
|
||||
flavor: latest=false
|
||||
tags: |
|
||||
type=raw,value=${{ matrix.tag }}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
name: Manual push
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to push'
|
||||
required: true
|
||||
default: 'dev'
|
||||
push:
|
||||
description: 'Push to registry'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
docker-build:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
name: ${{ matrix.platform }} - ${{ matrix.browser }} - ${{ matrix.tag }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# Chromium
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204'
|
||||
tag: 'latest'
|
||||
platform: 'amd64'
|
||||
browser: 'chromium'
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204-arm'
|
||||
tag: 'arm'
|
||||
platform: 'linux/arm64'
|
||||
browser: 'chromium'
|
||||
# Chrome
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204'
|
||||
tag: 'chrome'
|
||||
platform: 'amd64'
|
||||
browser: 'chrome'
|
||||
# Chrome is not supported on arm64
|
||||
# - runner: "buildjet-4vcpu-ubuntu-2204-arm"
|
||||
# tag: "chrome-arm"
|
||||
# platform: "linux/arm64"
|
||||
# browser: "chrome"
|
||||
# No browser
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204'
|
||||
tag: 'noweb'
|
||||
platform: 'amd64'
|
||||
browser: 'none'
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204-arm'
|
||||
tag: 'noweb-arm'
|
||||
platform: 'linux/arm64'
|
||||
browser: 'none'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ vars.DOCKER_IMAGE }}
|
||||
flavor: latest=false
|
||||
tags: |
|
||||
type=raw,value=${{ inputs.tag }}-${{ matrix.tag }}
|
||||
|
||||
- name: Login to image repository
|
||||
if: github.ref_type == 'tag'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: ${{ matrix.platform }}
|
||||
build-args: |
|
||||
USE_BROWSER=${{ matrix.browser }}
|
||||
push: ${{ inputs.push }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -1,3 +1,4 @@
|
||||
exclude: '^src/dashboard'
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
|
||||
@@ -35,7 +35,7 @@ update-swagger:
|
||||
wget http://localhost:3000/-json -O ./docs/site/static/swagger/openapi.json
|
||||
|
||||
update-dependencies:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up whatsapp-web.js@https://github.com/pedroslopez/whatsapp-web.js
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js#main-fork
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:WhiskeySockets/Baileys
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up venom-bot
|
||||
|
||||
|
||||
@@ -21,12 +21,51 @@ services:
|
||||
- './.sessions:/app/.sessions'
|
||||
environment:
|
||||
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
|
||||
- WHATSAPP_RESTART_ALL_SESSIONS=True
|
||||
- WHATSAPP_HOOK_URL=https://httpbin.org/post
|
||||
- WHATSAPP_HOOK_EVENTS=message
|
||||
# - WHATSAPP_RESTART_ALL_SESSIONS=True
|
||||
# - WHATSAPP_HOOK_URL=https://httpbin.org/post
|
||||
# - WHATSAPP_HOOK_EVENTS=message
|
||||
# - WHATSAPP_API_HOSTNAME=localhost
|
||||
- WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
- WHATSAPP_API_KEY=321
|
||||
- WHATSAPP_SWAGGER_USERNAME=admin
|
||||
- WHATSAPP_SWAGGER_PASSWORD=123
|
||||
- WHATSAPP_API_HOSTNAME=localhost
|
||||
# Username and password for Swagger
|
||||
- WHATSAPP_SWAGGER_USERNAME=swagger
|
||||
- WHATSAPP_SWAGGER_PASSWORD=admin
|
||||
# Username and password for WAHA Dashboard
|
||||
# you can use the same username and password for both Swagger and Dashboard
|
||||
- WAHA_DASHBOARD_USERNAME=dashboard
|
||||
- WAHA_DASHBOARD_PASSWORD=admin
|
||||
restart: always
|
||||
|
||||
whatsapp-http-api-plus--mongodb:
|
||||
image: devlikeapro/whatsapp-http-api-plus
|
||||
container_name: whatsapp-http-api-plus--mongodb
|
||||
ports:
|
||||
- '3000:3000/tcp'
|
||||
volumes:
|
||||
- './.sessions:/app/.sessions'
|
||||
environment:
|
||||
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
|
||||
# - WHATSAPP_RESTART_ALL_SESSIONS=True
|
||||
# - WHATSAPP_HOOK_URL=https://httpbin.org/post
|
||||
# - WHATSAPP_HOOK_EVENTS=message
|
||||
# - WHATSAPP_API_KEY=321
|
||||
# - WHATSAPP_SWAGGER_USERNAME=admin
|
||||
# - WHATSAPP_SWAGGER_PASSWORD=123
|
||||
# - WAHA_DASHBOARD_USERNAME=admin
|
||||
# - WAHA_DASHBOARD_PASSWORD=123
|
||||
# - WHATSAPP_API_HOSTNAME=localhost
|
||||
- WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
|
||||
restart: always
|
||||
|
||||
mongodb:
|
||||
image: mongo
|
||||
container_name: mongodb
|
||||
ports:
|
||||
- '27017:27017/tcp'
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
mongodb_data: {}
|
||||
@@ -85,13 +85,13 @@
|
||||
|
||||
[[main]]
|
||||
name = "Get on Patreon ->"
|
||||
weight = 50
|
||||
weight = 60
|
||||
url = "https://patreon.com/wa_http_api"
|
||||
parent = "waha-plus"
|
||||
|
||||
[[main]]
|
||||
name = "Get on Boosty ->"
|
||||
weight = 60
|
||||
weight = 50
|
||||
url = "https://boosty.to/wa-http-api"
|
||||
parent = "waha-plus"
|
||||
|
||||
@@ -104,9 +104,14 @@
|
||||
[[main]]
|
||||
name = "Python ->"
|
||||
weight = 21
|
||||
url = "https://github.com/devlikeapro/whatsapp-http-api/tree/core/examples/python"
|
||||
url = "/docs/examples/python"
|
||||
parent = "examples"
|
||||
|
||||
[[main]]
|
||||
name = "Kotlin ->"
|
||||
weight = 22
|
||||
url = "/docs/examples/kotlin"
|
||||
parent = "examples"
|
||||
|
||||
[[social]]
|
||||
name = "GitHub"
|
||||
|
||||
@@ -110,4 +110,4 @@ lastMod = false
|
||||
[menu]
|
||||
[menu.section]
|
||||
auto = true
|
||||
collapsibleSidebar = true
|
||||
collapsibleSidebar = false
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title : "WAHA"
|
||||
description: "WAHA - WhatsApp HTTP API that you can run in a click!"
|
||||
lead: "WAHA - WhatsApp HTTP API that you can run in a click!"
|
||||
lead: "WAHA - <b>WhatsApp HTTP API</b> that you can run in a click!"
|
||||
date: 2020-10-06T08:47:36+00:00
|
||||
lastmod: 2020-10-06T08:47:36+00:00
|
||||
draft: false
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: "Kotlin"
|
||||
description: "WhatsApp HTTP API + Kotlin examples."
|
||||
lead: "WhatsApp HTTP API + Kotlin examples."
|
||||
date: 2020-10-06T08:49:31+00:00
|
||||
lastmod: 2020-10-06T08:49:31+00:00
|
||||
draft: false
|
||||
images: ["/images/kotlin-whatsapp.png"]
|
||||
menu:
|
||||
docs:
|
||||
parent: "help"
|
||||
weight: 630
|
||||
toc: true
|
||||
---
|
||||
|
||||

|
||||
|
||||
We've created a few examples on how to interact with WAHA WhatsApp HTTP 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 HTTP API locally (which under the hood it
|
||||
runs real WhatsApp Web instance and expose HTTP API for interaction).
|
||||
|
||||
Here are the steps from
|
||||
[Quick Start](https://waha.devlike.pro/docs/overview/quick-start/):
|
||||
|
||||
Download and start WhatsApp HTTP API docker container
|
||||
|
||||
```bash
|
||||
# Download the image
|
||||
docker pull devlikeapro/whatsapp-http-api
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP 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/whatsapp-http-api:arm
|
||||
# Rename it, so you can use devlikeapro/whatsapp-http-api image in other place
|
||||
docker tag devlikeapro/whatsapp-http-api:arm devlikeapro/whatsapp-http-api
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP 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/start` request press **Try it out** and
|
||||
**Execute** it with `default` session name
|
||||
2. Find `GET /api/screenshot` and execute it - it must show QR code
|
||||
3. Scan QR code on your mobile WhatsApp application (that installed on your
|
||||
phone)
|
||||
4. Execute `GET /api/screenshot` once again - it must show the screenshot
|
||||
from WhatsApp Web.
|
||||
4. Send test text message - find `POST /api/sendText` and execute it with
|
||||
payload (change `12132132130` in the `chatId` to phone number that is
|
||||
registered in WhatsApp).
|
||||
|
||||
```json
|
||||
{
|
||||
"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!
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
title: "Python"
|
||||
description: "WhatsApp HTTP API Python examples."
|
||||
lead: "WhatsApp HTTP API Python 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: 630
|
||||
toc: true
|
||||
---
|
||||
We've created a few examples on how to interact with WAHA WhatsApp HTTP API with Python.
|
||||
|
||||
You can find the examples in [examples folder on GitHub with detailed instructions in README.md](https://github.com/devlikeapro/whatsapp-http-api/tree/core/examples/python)
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
---
|
||||
title: "Python"
|
||||
description: "WhatsApp HTTP API + Python examples."
|
||||
lead: "WhatsApp HTTP API + Python examples."
|
||||
date: 2020-10-06T08:49:31+00:00
|
||||
lastmod: 2020-10-06T08:49:31+00:00
|
||||
draft: false
|
||||
images: ["/images/python-whatsapp.png"]
|
||||
menu:
|
||||
docs:
|
||||
parent: "help"
|
||||
weight: 630
|
||||
toc: true
|
||||
---
|
||||
|
||||

|
||||
|
||||
We've created a few examples on how to interact with WAHA WhatsApp HTTP API with Python.
|
||||
|
||||
You can find the examples in [examples folder on GitHub with detailed instructions in README.md ->](https://github.com/devlikeapro/whatsapp-http-api/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 HTTP API locally (which under the hood it
|
||||
runs real WhatsApp Web instance and expose HTTP API for interaction).
|
||||
|
||||
Here are the steps from
|
||||
[Quick Start](https://waha.devlike.pro/docs/overview/quick-start/):
|
||||
|
||||
Download and start WhatsApp HTTP API docker container
|
||||
|
||||
```bash
|
||||
# Download the image
|
||||
docker pull devlikeapro/whatsapp-http-api
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP 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/whatsapp-http-api:arm
|
||||
# Rename it, so you can use devlikeapro/whatsapp-http-api image in other place
|
||||
docker tag devlikeapro/whatsapp-http-api:arm devlikeapro/whatsapp-http-api
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP 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/start` request press **Try it out** and
|
||||
**Execute** it with `default` session name
|
||||
2. Find `GET /api/screenshot` and execute it - it must show QR code
|
||||
3. Scan QR code on your mobile WhatsApp application (that installed on your
|
||||
phone)
|
||||
4. Execute `GET /api/screenshot` once again - it must show the screenshot
|
||||
from WhatsApp Web.
|
||||
4. Send test text message - find `POST /api/sendText` and execute it with
|
||||
payload (change `12132132130` in the `chatId` to phone number that is
|
||||
registered in WhatsApp).
|
||||
|
||||
```json
|
||||
{
|
||||
"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/whatsapp-http-api.git
|
||||
# Open python example folder
|
||||
cd whatsapp-http-api/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/plus-version/).
|
||||
|
||||
Download **WAHA Plus** version:
|
||||
|
||||
```bash
|
||||
# Download the image
|
||||
docker pull devlikeapro/whatsapp-http-api-plus
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
Run the WhatsApp Download Files bot:
|
||||
|
||||
```bash
|
||||
# Clone the git repository with example
|
||||
git clone https://github.com/devlikeapro/whatsapp-http-api.git
|
||||
# Open python example folder
|
||||
cd whatsapp-http-api/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!
|
||||
|
||||
@@ -26,6 +26,7 @@ The following environment variables can be used to configure the WAHA.
|
||||
|
||||
### Common
|
||||
- `DEBUG=1`: Set this variable to any value to enable debug and verbose logs.
|
||||
- You can also do it for a **specific session** by setting `config.debug` field to `true` when starting a session.
|
||||
- `WHATSAPP_API_PORT=3000`: The port number that the HTTP server will listen on. The default value is `3000`.
|
||||
- `WHATSAPP_API_HOSTNAME=localhost`: The hostname for the HTTP server. The default value is `localhost`.
|
||||
|
||||
@@ -38,6 +39,8 @@ The following environment variables can be used to configure the WAHA.
|
||||
response.
|
||||
- `WHATSAPP_START_SESSION=session1,session2`: This variable can be used to start sessions with the specified names right
|
||||
after launching the API. Separate session names with a comma.
|
||||
- Also read more about [Sessions ->]({{< relref "/docs/how-to/sessions" >}})
|
||||
- Also read more about [Session Storages on the dedicated page ->]({{< relref "/docs/how-to/storages#sessions" >}})
|
||||
|
||||
### Swagger
|
||||
- `WHATSAPP_SWAGGER_CONFIG_ADVANCED=true` - enables advanced configuration options for Swagger documentation - you can customize host, port and base URL for the requests.
|
||||
@@ -66,14 +69,18 @@ Read more about it on [**Session page** ->]({{< relref "/docs/how-to/sessions#co
|
||||
Keep in mind that session's proxy configuration takes precedence over proxy configuration set by environment variables!
|
||||
|
||||
|
||||
### Security 
|
||||
### Security
|
||||
<b>Security is available in [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
|
||||
|
||||
- `WHATSAPP_API_KEY=mysecret`: If you set this variable, you must include the `X-Api-Key: mysecret` header in all
|
||||
requests to the API. This will protect the API with a secret code.
|
||||
- `WHATSAPP_SWAGGER_USERNAME=admin` and `WHATSAPP_SWAGGER_PASSWORD=admin`: These variables can be used to protect the
|
||||
Swagger panel with `admin / admin` credentials. This does not affect API access.
|
||||
|
||||
Read more about security settings for Swagger and API on [**Security page** ->]({{< relref "/docs/how-to/security" >}}).
|
||||
|
||||
### Files 
|
||||
### Files
|
||||
<b>Files configuration is available in [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
|
||||
|
||||
The following environment variables can be used to configure the file storage options for the WAHA:
|
||||
|
||||
@@ -85,8 +92,11 @@ The following environment variables can be used to configure the file storage op
|
||||
- Under the hood, it sets `WHATSAPP_FILES_MIMETYPES=mimetype/ignore-all-media` to ignore all media files.
|
||||
- `WHATSAPP_FILES_LIFETIME`: This variable can be used to set the time (in seconds) after which files will be removed to
|
||||
free up space. The default value is `180`.
|
||||
- Set this variable to `0` to disable the file lifetime.
|
||||
- `WHATSAPP_FILES_FOLDER`: This variable can be used to set the folder where files from chats (images, voice messages)
|
||||
will be stored. The default value is `/tmp/whatsapp-files`.
|
||||
- The folder must be mounted to the host machine to keep the files between container restarts. [ Read more about how to persist files ->]({{< relref "/docs/how-to/storages#media" >}})
|
||||
- Also read more about [Media Storages on the dedicated page ->]({{< relref "/docs/how-to/storages#media" >}})
|
||||
|
||||
💡 Even if WAHA doesn't process the message media because of `WHATSAPP_FILES_MIMETYPES` or `WHATSAPP_DOWNLOAD_MEDIA`
|
||||
you'll get a webhook event with `hasMedia: True` field, but with no `media.url`.
|
||||
@@ -105,6 +115,14 @@ you'll get a webhook event with `hasMedia: True` field, but with no `media.url`.
|
||||
}
|
||||
```
|
||||
|
||||
### Health Check
|
||||
<b>Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
|
||||
|
||||
The following environment variables can be used to configure the [Health Check ->]({{< relref "/docs/how-to/other" >}}):
|
||||
- `WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB` - the threshold in MB for the media files storage. The default value is `100`.
|
||||
- `WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB` - the threshold in MB for the sessions files storage. The default value is `100`.
|
||||
- `WHATSAPP_HEALTH_MONGODB_TIMEOUT` - the timeout in milliseconds for the MongoDB health check. The default value is `5000`.
|
||||
|
||||
## Examples
|
||||
|
||||
#### Debug Mode
|
||||
|
||||
@@ -6,7 +6,7 @@ date: 2020-10-06T08:48:45+00:00
|
||||
lastmod: 2020-10-06T08:48:45+00:00
|
||||
draft: false
|
||||
images: [ ]
|
||||
weight: 899
|
||||
weight: 898
|
||||
---
|
||||
|
||||
This page provides useful information to assist you in deploying the project.
|
||||
|
||||
@@ -47,18 +47,14 @@ Not running Chromium saves you CPU and Memory, so you can run more instances on
|
||||
️Working with the engine requires more attention, because it's easy to be blocked with it!
|
||||
|
||||
⚠ Read the article before using **NOWEB** engine
|
||||
|
||||
Quotes from the users:
|
||||
> The server has **2 CPU and 8GB** of memory. Today we have **85 sessions** in this instance.
|
||||
|
||||
> **400** sessions with **4CPU and 32RAM**. It's working fine.
|
||||
|
||||
[How to avoid blocking ->]({{< relref " /docs/overview/how-to-avoid-blocking" >}}).
|
||||
|
||||
### MOBILE (experimental)
|
||||
{{< alert icon="👉" text="<b>Experimental engine!</b><br/>Please contact us on <a href='https://www.patreon.com/wa_http_api' target='_blank'>Patreon -></a> or <a href='https://boosty.to/wa-http-api' target='_blank'>Boosty -></a> if you're interested in using it.<br>Available for <a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>PRO</a> subscribers only" />}}
|
||||
|
||||
- `WHATSAPP_DEFAULT_ENGINE=MOBILE`
|
||||
- [https://github.com/WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys)
|
||||
|
||||
**MOBILE** engine **does not require a browser and a mobile device** to work with WhatsApp, it does so directly using a WebSocket.
|
||||
You don't have to use a mobile device to run this engine.
|
||||
|
||||
|
||||
### VENOM
|
||||
|
||||
- `WHATSAPP_DEFAULT_ENGINE=VENOM`
|
||||
@@ -69,17 +65,30 @@ It uses Puppeteer to run a real instance of Whatsapp Web to avoid getting blocke
|
||||
|
||||
## Docker images
|
||||
WAHA provides few docker images with different setup.
|
||||
{{< alert icon="👉" text="Use `devlikeapro/whatsapp-http-api` instead of `devlikeapro/whatsapp-http-api-plus` to get **WAHA Plus** version." />}}
|
||||
|
||||
For **x86** processors use following images:
|
||||
- `devlikeapro/whatsapp-http-api:latest` - latest version of WAHA, using **Chromium** (does not support video receiving and receiving in Plus version)
|
||||
- `devlikeapro/whatsapp-http-api:chrome` - latest version of WAHA, using **Chrome** (supports video receiving and receiving in Plus version)
|
||||
- `devlikeapro/whatsapp-http-api:noweb`- latest version of WAHA, **no browser installed** - use it only for **NOWEB** engine
|
||||
| Image | CPU | Browser |
|
||||
|---------------------------------------------------------|-----|-------------------------|
|
||||
| [WAHA Plus]({{< relref "/docs/how-to/plus-version" >}}) | | |
|
||||
| `devlikeapro/whatsapp-http-api-plus:latest` | x86 | Chromium |
|
||||
| `devlikeapro/whatsapp-http-api-plus:chrome` | x86 | Chrome (supports video) |
|
||||
| `devlikeapro/whatsapp-http-api-plus:noweb` | x86 | None |
|
||||
| `devlikeapro/whatsapp-http-api-plus:arm` | ARM | Chromium |
|
||||
| `devlikeapro/whatsapp-http-api-plus:noweb-arm` | ARM | None |
|
||||
| **WAHA Core** | | |
|
||||
| `devlikeapro/whatsapp-http-api:latest` | x86 | Chromium |
|
||||
| `devlikeapro/whatsapp-http-api:chrome` | x86 | Chrome |
|
||||
| `devlikeapro/whatsapp-http-api:noweb` | x86 | None |
|
||||
| `devlikeapro/whatsapp-http-api:arm` | ARM | Chromium |
|
||||
| `devlikeapro/whatsapp-http-api:noweb-arm` | ARM | None |
|
||||
|
||||
For **ARM** processors use following images:
|
||||
- `devlikeapro/whatsapp-http-api:arm` - **Chromium**
|
||||
- `devlikeapro/whatsapp-http-api:arm-noweb`- **no browser installed**
|
||||
Browsers:
|
||||
- **Chromium** - is the default browser for **WAHA**. It's a good choice for most cases.
|
||||
- **Chrome** - is a good choice if you need to receive videos in Plus version.
|
||||
- **None** - is a good choice if you want to use **NOWEB** engine.
|
||||
|
||||
CPU:
|
||||
- **x86** - is a good choice for most cases.
|
||||
- **ARM** - is a good choice if you're using ARM processors (like Apple Silicon, Apple M1, etc.)
|
||||
{{< alert icon="💡" text="Chrome version is not available in ARM" />}}
|
||||
|
||||
## Features
|
||||
@@ -96,7 +105,7 @@ Here, you will find a list of supported endpoints and webhooks per engine.
|
||||
If you don't specify `WHATSAPP_DEFAULT_ENGINE` environment variable - look at **WEBJS** engine,
|
||||
it's the engine WAHA runs by default.
|
||||
|
||||
### Engine
|
||||
### Protocols
|
||||
|
||||
| | WEBJS | NOWEB | VENOM |
|
||||
|--------------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
@@ -120,30 +129,31 @@ please [create an issue](https://github.com/devlikeapro/whatsapp-http-api/issues
|
||||
| `POST /api/{session}/auth/qr` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/{session}/auth/request-code` | ➖ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/auth/authorize-code` | ➖ | ➖️<br>[#113](https://github.com/devlikeapro/whatsapp-http-api/issues/113) | ➖ |
|
||||
| `GET /api/{session}/auth/captcha` <br>Only in **MOBILE** engine | ➖ | ➖ | ➖ |
|
||||
| `POST /api/{session}/auth/captcha` <br>Only in **MOBILE** engine | ➖ | ➖ | ➖ |
|
||||
| **Screenshot** | | | |
|
||||
| `POST /api/screenshot` | ✔️ | ➖ | ✔️ |
|
||||
|
||||
| **Chatting** | WEBJS | NOWEB | VENOM |
|
||||
|------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| `GET /api/checkNumberStatus` | ✔️ | ✔️ | ✔️ |
|
||||
| `GET /api/sendContactVcard` | ➖ | ➖ | ✔️ |
|
||||
| `GET /api/sendText` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendText` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendPoll` | ➖ | ✔️ | ➖ |
|
||||
| `POST /api/sendLocation` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendLinkPreview` | ➖ | ✔️ | ✔️ |
|
||||
| `POST /api/sendImage`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendFile`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendVoice`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendVideo`  | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/reply` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendSeen` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/startTyping` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/stopTyping` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/reaction` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/messages` | ✔️ | ➖ | ✔️ |
|
||||
| **Chatting** | WEBJS | NOWEB | VENOM |
|
||||
|-------------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| `GET /api/checkNumberStatus` | ✔️ | ✔️ | ✔️ |
|
||||
| `GET /api/sendContactVcard` | ➖ | ✔️ | ➖ |
|
||||
| `GET /api/sendText` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendText` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/reply` | ✔️ | ✔️ | ✔️ |
|
||||
| `PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ➖ |
|
||||
| `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/sendPoll` | ➖ | ✔️ | ➖ |
|
||||
| `POST /api/sendLocation` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendLinkPreview` | ➖ | ✔️ | ✔️ |
|
||||
| `POST /api/sendImage`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendFile`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendVoice`  | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/sendVideo`  | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/sendSeen` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/startTyping` | ✔️ | ✔️ | ✔️ |
|
||||
| `POST /api/stopTyping` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/reaction` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/star` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/messages` | ✔️ | ➖ | ✔️ |
|
||||
|
||||
| | WEBJS | NOWEB | VENOM |
|
||||
|-------------------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
@@ -157,48 +167,56 @@ please [create an issue](https://github.com/devlikeapro/whatsapp-http-api/issues
|
||||
| `DELETE /api/{session}/chats/{chatId}` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/{session}/chats/{chatId}/messages` | ✔️ | ➖ | ✔️ |
|
||||
| `DELETE /api/{session}/chats/{chatId}/messages` | ✔️ | ➖ | ➖ |
|
||||
| `PUT /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ➖ |
|
||||
| `DELETE /api/{session}/chats/{chatId}/messages/{messageId}` | ✔️ | ✔️ | ➖ |
|
||||
| **Contacts** | | | |
|
||||
| `GET /api/contacts` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/contacts/all` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/contacts/check-exists` | ✔️ | ✔️ | ✔️ |
|
||||
| `GET /api/contacts/about` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/contacts/profile-picture` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/contacts/profile-picture` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/contacts/block` | ✔️ | ➖ | ➖ |
|
||||
| `POST /api/contacts/unblock` | ✔️ | ➖ | ➖ |
|
||||
|
||||
| **Groups** | WEBJS | NOWEB | VENOM |
|
||||
|--------------------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| `POST /api/{session}/groups` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}` | ✔️ | ✔️ | ➖ |
|
||||
| `DELETE /api/{session}/groups/{id}` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/leave` | ✔️ | ✔️ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/description` | ✔️ | ✔️ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/subject` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/invite-code` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/invite-code/revoke` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/participants` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/participants/add` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/participants/remove` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/admin/promote` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/admin/demote` | ✔️ | ✔️ | ➖ |
|
||||
| **Groups** | WEBJS | NOWEB | VENOM |
|
||||
|------------------------------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| `POST /api/{session}/groups` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}` | ✔️ | ✔️ | ➖ |
|
||||
| `DELETE /api/{session}/groups/{id}` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/settings/security/info-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/settings/security/messages-admin-only` | ✔️ | ➖ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/leave` | ✔️ | ✔️ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/description` | ✔️ | ✔️ | ➖ |
|
||||
| `PUT /api/{session}/groups/{id}/subject` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/invite-code` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/invite-code/revoke` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/groups/{id}/participants` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/participants/add` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/participants/remove` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/admin/promote` | ✔️ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/groups/{id}/admin/demote` | ✔️ | ✔️ | ➖ |
|
||||
|
||||
| | WEBJS | NOWEB | VENOM |
|
||||
|---------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| **Presence** | | | |
|
||||
| `POST /api/{session}/presence` | ➖ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/presence` | ✔️ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/presence` | ➖ | ✔️ | ➖ |
|
||||
| `GET /api/{session}/presence/{chatId}` | ➖ | ✔️ | ➖ |
|
||||
| `POST /api/{session}/presence/{chatId}/subscribe` | ➖ | ✔️ | ➖ |
|
||||
| **Other** | | | |
|
||||
| `POST /api/version` | ➖ | ✔️ | ➖ |
|
||||
| `GET /api/version` | ➖ | ✔️ | ➖ |
|
||||
| `GET /health`  | ✔️ | ✔️ | ✔️ |
|
||||
|
||||
### Webhooks
|
||||
|
||||
| **Webhooks** | WEBJS | NOWEB | VENOM |
|
||||
|-----------------------------------------------------|:-----:|:-----:|:-----:|
|
||||
| `message` | ✔️ | ✔️ | ✔️ |
|
||||
| `message` with files  | ✔️ | ✔️ | ✔️ |
|
||||
| `message.reaction` | ✔️ | ✔️ | ➖ |
|
||||
| `message.any` | ✔️ | ✔️ | ✔️ |
|
||||
| `message.ack` | ✔️ | ✔️ | ✔️ |
|
||||
| `message.revoked` | ✔️ | ➖ | ➖ |
|
||||
|
||||
@@ -87,22 +87,47 @@ Request:
|
||||
}
|
||||
```
|
||||
|
||||
### Settings
|
||||
#### Security for group info
|
||||
### Security - update group info
|
||||
Updates the group settings to only allow admins to edit group info (title, description, photo).
|
||||
`PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only`
|
||||
```json
|
||||
{
|
||||
"adminsOnly": true
|
||||
}
|
||||
```
|
||||
|
||||
Get the group settings to only allow admins to edit group info (title, description, photo).
|
||||
|
||||
`GET /api/{session}/groups/{groupId}/settings/security/info-admin-only`
|
||||
```json
|
||||
{
|
||||
"adminsOnly": true
|
||||
}
|
||||
```
|
||||
`PUT /api/{session}/groups/{groupId}/settings/security/info-admin-only`
|
||||
|
||||
The request doesn't require any request's body and
|
||||
**can't be used to disable the security setting (allow ANY to edit group info)**.
|
||||
If you wish to have that ability - please [create an issue](https://github.com/devlikeapro/whatsapp-http-api/issues)
|
||||
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.
|
||||
|
||||
`PUT /api/{session}/groups/{groupId}/settings/security/messages-admin-only`
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
`GET /api/{session}/groups/{groupId}/settings/security/messages-admin-only`
|
||||
```json
|
||||
{
|
||||
"adminsOnly": true
|
||||
}
|
||||
```
|
||||
|
||||
### Participants
|
||||
|
||||
#### Get participants
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
---
|
||||
title: "Other"
|
||||
description: "Other features and API"
|
||||
lead: ""
|
||||
date: 2020-10-06T08:48:45+00:00
|
||||
lastmod: 2020-10-06T08:48:45+00:00
|
||||
draft: false
|
||||
images: [ ]
|
||||
weight: 802
|
||||
---
|
||||
|
||||
This page provides useful information about other features and API that are not covered in the other sections.
|
||||
|
||||
## Health Check
|
||||
<b>Health check is available in [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
|
||||
|
||||
The health check endpoint is used to determine the health of the service.
|
||||
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
It returns a **200 OK** status code if the service is healthy.
|
||||
|
||||
The response format:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"info": {
|
||||
"metric1": {
|
||||
"field": "value"
|
||||
},
|
||||
"metric2": {
|
||||
"field": "value"
|
||||
}
|
||||
},
|
||||
"error": {},
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
Where:
|
||||
- `status`: `'error' | 'ok' | 'shutting_down'` - If any health indicator failed the status will be `'error'`. If the app is shutting down but still accepting HTTP requests, the health check will have the `'shutting_down'` status.
|
||||
- `info`: Object containing information of each health indicator which is of status `'up'`, or in other words "healthy".
|
||||
- `error`: Object containing information of each health indicator which is of status `'down'`, or in other words "unhealthy".
|
||||
- `details`: Object containing detailed information of each health indicator.
|
||||
|
||||
### Health Check Indicators
|
||||
Few things we check in the health check:
|
||||
- Media files storage space - `mediaFiles.space`
|
||||
- Sessions files storage space - `sessionsFiles.space`
|
||||
- MongoDB connection - `mongodb`
|
||||
|
||||
### Configuration
|
||||
The following environment variables can be used to configure the health check:
|
||||
- `WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB` - the threshold in MB for the media files storage. The default value is `100`.
|
||||
- `WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB` - the threshold in MB for the sessions files storage. The default value is `100`.
|
||||
- `WHATSAPP_HEALTH_MONGODB_TIMEOUT` - the timeout in milliseconds for the MongoDB health check. The default value is `5000`.
|
||||
|
||||
### Examples
|
||||
**Healthy response** when you use [Local Storage]({{< relref "/docs/how-to/storages#sessions" >}}) for session authentication:
|
||||
|
||||
**200 OK**
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"info": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132979355648,
|
||||
"threshold": 104857600
|
||||
},
|
||||
"sessionsFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/app/.sessions",
|
||||
"diskPath": "/",
|
||||
"free": 132979355648,
|
||||
"threshold": 104857600
|
||||
}
|
||||
},
|
||||
"error": {},
|
||||
"details": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132979355648,
|
||||
"threshold": 104857600
|
||||
},
|
||||
"sessionsFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/app/.sessions",
|
||||
"diskPath": "/",
|
||||
"free": 132979355648,
|
||||
"threshold": 104857600
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Healthy response** when you use [MongoDB Storage]({{< relref "/docs/how-to/storages#sessions" >}}) for session authentication:
|
||||
|
||||
**200 OK**
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"info": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132977496064,
|
||||
"threshold": 104857600
|
||||
},
|
||||
"mongodb": {
|
||||
"status": "up",
|
||||
"message": "Up and running"
|
||||
}
|
||||
},
|
||||
"error": {},
|
||||
"details": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132977496064,
|
||||
"threshold": 104857600
|
||||
},
|
||||
"mongodb": {
|
||||
"status": "up",
|
||||
"message": "Up and running"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Unhealthy response example**
|
||||
|
||||
**503 Service Unavailable**
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"info": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132976623616,
|
||||
"threshold": 104857600
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"mongodb": {
|
||||
"status": "down",
|
||||
"error": "Timeout"
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"mediaFiles.space": {
|
||||
"status": "up",
|
||||
"path": "/tmp/whatsapp-files",
|
||||
"diskPath": "/",
|
||||
"free": 132976623616,
|
||||
"threshold": 104857600
|
||||
},
|
||||
"mongodb": {
|
||||
"status": "down",
|
||||
"error": "Timeout"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Get version
|
||||
Returns the version of the installed docker image.
|
||||
```
|
||||
GET /api/version
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2024.2.3",
|
||||
"engine": "NOWEB",
|
||||
"tier": "PLUS",
|
||||
"browser": "/usr/bin/google-chrome-stable"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -49,48 +49,48 @@ Treat **WAHA Plus** it as an additional episode, behind-the-scenes videos, our n
|
||||
We donate most of the donations down to the stream to the underlying libraries and tools - JS-community, Node, other libraries authors, personal contributors.
|
||||
By donating to the **WAHA** you donate to the Open Source world!
|
||||
|
||||
### Features
|
||||
|
||||
The Plus additional features are:
|
||||
|
||||
1. [**Send images\files\voices** →]({{< relref "/docs/how-to/send-messages" >}})
|
||||
2. [**Receive images\files\voices** →]({{< relref "/docs/how-to/receive-messages" >}})
|
||||
3. [**Webhook retries** →]({{< relref "/docs/how-to/receive-messages#retries" >}})
|
||||
4. [**Security** →]({{< relref "/docs/how-to/security" >}})
|
||||
5. [**Saving sessions** →]({{< relref "/docs/how-to/sessions" >}})
|
||||
6. [**Support multiple sessions** →]({{< relref "/docs/how-to/sessions" >}})
|
||||
7. **Priority in support** - on both bugs and features
|
||||
|
||||
### Why WAHA?
|
||||
|
||||
What is the difference between **WAHA Plus** and **other SaaS solutions** for WhatsApp HTTP API?
|
||||
|
||||
| | WAHA Plus | Others |
|
||||
|--------------------|:-------------------------------------------------:|----------------------------------------------------------------------------------:|
|
||||
| **Sessions** | ✔️ No limits on **accounts** or **servers**! | ➖ One account for $50/month. |
|
||||
| **Infrastructure** | ✔️ On-Premise - your server, your infrastructure! | ➖ Insecure cloud solution. |
|
||||
| **Security** | ✔️ No data leaks! | ➖ You have to give access to customers' data - phone number, name, your messages. |
|
||||
| **License Term** | ✔️ No license checks! | ➖ One month |
|
||||
| **Message price** | ✔️ All messages are Free! | ➖ Some solutions have a price for messages - $1/100 messages. |
|
||||
| **Expenses** | ✔️ $19 **donation**! | ➖ Monthly payment starts from $50 |
|
||||
|
||||
|
||||
## Get Plus 
|
||||
## Tiers
|
||||
|
||||
The more you support the project - the more you get!
|
||||
|
||||
### Tiers
|
||||
### Core
|
||||
|
||||
Here's available tiers for our supporters:
|
||||
| Essential product for your needs! | |
|
||||
|----------------------------------------------------------------------------------|----------|
|
||||
| [Send and receive text messages ->]({{< relref "/docs/how-to/send-messages" >}}) | ✔️ |
|
||||
| [Webhooks ->]({{< relref "/docs/how-to/webhooks" >}}) | ✔️ |
|
||||
| No license checks on installed instances | ✔️ |
|
||||
| Messages limit | **∞** |
|
||||
| [Sessions limit ->]({{< relref "/docs/how-to/sessions" >}}) | **1** |
|
||||
| **Donation** | **FREE** |
|
||||
|
||||
### Plus
|
||||
| Optimize your experience with extra perks! | |
|
||||
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|
||||
| All in **Core** | ✔️ |
|
||||
| [Sessions limit ->]({{< relref "/docs/how-to/sessions" >}}) | **∞** |
|
||||
| [Send and receive files ->]({{< relref "/docs/how-to/send-messages" >}}) | ✔️ |
|
||||
| [Built-in Security ->]({{< relref "/docs/how-to/security" >}}) | ✔️ |
|
||||
| [Webhook retries →]({{< relref "/docs/how-to/receive-messages#retries" >}}) | ✔️ |
|
||||
| [MongoDB support ->]({{< relref "/docs/how-to/storages" >}}) | ✔️ |
|
||||
| Access to **WAHA Plus** docker image with a personal key. | ✔️ |
|
||||
| [](https://waha.devlike.pro/docs/how-to/plus-version/#tiers) badge and `patron:PLUS` label on [project's issues, PRs and Discussion](https://github.com/devlikeapro/whatsapp-http-api) to highlight your support to the project! | ✔️ |
|
||||
| Built-in [WAHA Dashboard]({{< relref "/docs/how-to/waha-dashboard" >}}) - UI to manage your sessions! | ✔️ |
|
||||
| Access to the **WAHA Plus** **source code** (in a private Github repository). | ➖ |
|
||||
| Membership to the **WAHA Discord server** for receiving personal support, and sharing your experiences with other professionals. | ➖ |
|
||||
| [WAHA Hub]({{< relref "/docs/waha-hub/introduction" >}}) - a single place to manage multiple servers! | ➖ |
|
||||
| **Donation** | **$19** |
|
||||
|
||||
### Pro
|
||||
| Exclusive perks for the PROfessionals! | |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|
||||
| All in **Plus** | ✔️ |
|
||||
| [](https://waha.devlike.pro/docs/how-to/plus-version/#tiers) badge and `patron:PRO` label on [project's issues, PRs and Discussion](https://github.com/devlikeapro/whatsapp-http-api) to highlight your support to the project! | ✔️ |
|
||||
| Access to the **WAHA Plus** **source code** (in a private Github repository). | ✔️ |
|
||||
| Membership to the **WAHA Discord server** for receiving personal support, and sharing your experiences with other professionals. | ✔️ |
|
||||
| [WAHA Hub]({{< relref "/docs/waha-hub/introduction" >}}) - a single place to manage multiple servers! | ✔️ |
|
||||
| **Donation** | **$99** |
|
||||
|
||||
| | Plus | Advanced | Pro |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|:--------:|:-------:|
|
||||
| Access to WAHA Plus  docker image with a personal key. | ✔️ | ✔️ | ✔️ |
|
||||
| Special badge ([](https://waha.devlike.pro/docs/how-to/plus-version/#tiers)) and labels (`patron:TIER`) on [project's issues, PRs and Discussion](https://github.com/devlikeapro/whatsapp-http-api) to highlight your support to the project! | ✔️ | ✔️ | ✔️ |
|
||||
| An invitation to a private Github repository so you have the WAHA Plus source code. | ➖️ | ✔️ | ✔️️ |
|
||||
| Access to a Telegram group where we provide support and assistance. | ➖️ | ➖ | ✔️ |
|
||||
| Access to an [experimental MOBILE engine]({{< relref "/docs/how-to/plus-version#tiers" >}})!. | ➖️ | ➖ | ✔️ |
|
||||
| **Donation** | **$19** | **$39** | **$99** |
|
||||
|
||||
For **$19** donation you get:
|
||||
1. **Secret password** for Docker Hub to download Plus image: `devlikeapro/whatsapp-http-api-plus`.
|
||||
@@ -100,23 +100,29 @@ For **$19** donation you get:
|
||||
|
||||
{{< alert icon="💡" text="If you stay subscribed - the donation amount will never change for you and always be $19 to get monthly updates!" />}}
|
||||
|
||||
### Patreon
|
||||
<p align="center">
|
||||
<img src="patreon.png" alt="Patreon" />
|
||||
</p>
|
||||
|
||||
Support the project and get WAHA Plus version on
|
||||
<a href="https://patreon.com/wa_http_api" target="_blank">
|
||||
<b>
|
||||
Patreon ->
|
||||
</b>
|
||||
</a>
|
||||
## Why WAHA?
|
||||
|
||||
Go ahead and get your own WhatsApp HTTP API!
|
||||
What is the difference between **WAHA Plus** and **other SaaS solutions** for WhatsApp HTTP API?
|
||||
|
||||
| WAHA Plus | Others |
|
||||
|:-------------------------------------------------:|----------------------------------------------------------------------------------:|
|
||||
| ✔️ No limits on **accounts** or **servers**! | ➖ One account for $50/month. |
|
||||
| ✔️ On-Premise - your server, your infrastructure! | ➖ Insecure cloud solution. |
|
||||
| ✔️ No data leaks! | ➖ You have to give access to customers' data - phone number, name, your messages. |
|
||||
| ✔️ No license checks! | ➖ One month |
|
||||
| ✔️ All messages are **Free**! | ➖ Some solutions have a price for messages - $1/100 messages. |
|
||||
| ✔️ $19 **donation**! | ➖ Monthly payment starts from $50 |
|
||||
|
||||
{{< alert icon="💡" text="If you stay subscribed - the donation amount will never change for you and always be $19 to get monthly updates!" />}}
|
||||
|
||||
## Get Plus 
|
||||
|
||||
{{< alert icon="💡" text="If you stay subscribed - the donation amount will never change for you and always be $19 to get monthly updates!" />}}
|
||||
|
||||
### Boosty
|
||||
<p align="center">
|
||||
<img src="boosty.svg" alt="Patreon" />
|
||||
<img src="boosty.svg" alt="Patreon" style='width: 40%'/>
|
||||
<br/>
|
||||
<br/>
|
||||
</p>
|
||||
@@ -130,7 +136,53 @@ Boosty ->
|
||||
|
||||
Go ahead and get your own WhatsApp HTTP API!
|
||||
|
||||
## Install Plus
|
||||
|
||||
### Patreon
|
||||
|
||||
<p align="center">
|
||||
<img src="patreon.png" alt="Patreon" style='width: 40%'/>
|
||||
</p>
|
||||
|
||||
{{< alert icon="🙏" text="Please consider using Boosty instead of Patreon due to its lower fees 🙏" />}}
|
||||
|
||||
Support the project and get WAHA Plus version on
|
||||
<a href="https://patreon.com/wa_http_api" target="_blank">
|
||||
<b>
|
||||
Patreon ->
|
||||
</b>
|
||||
</a>
|
||||
|
||||
Go ahead and get your own WhatsApp HTTP API!
|
||||
|
||||
|
||||
### Crypto
|
||||
<p align="center">
|
||||
<img src="tether-usdt-logo.svg" alt="Tether Logo" style='width: 40%'/>
|
||||
</p>
|
||||
|
||||
If you wish to donate in crypto - please contact us at [crypto@devlike.pro](mailto:crypto@devlike.pro)
|
||||
with the desired **amount**, **currency** and **network**.
|
||||
|
||||
> e.g. "I want to donate $99 in USDT using TRC20 network."
|
||||
|
||||
|
||||
## Patron Portal
|
||||
<p align="center">
|
||||
<img src="patron-portal.png" alt="Patron Portal" />
|
||||
<br/>
|
||||
<br/>
|
||||
</p>
|
||||
|
||||
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
|
||||
**<a href="https://www.patreon.com/posts/waha-patron-97637416" target="_blank">Patreon -> </a>**
|
||||
or
|
||||
**<a href="https://boosty.to/wa-http-api/posts/8319079f-dac1-4179-b954-fcc559097c76" target="_blank">Boosty -></a>**
|
||||
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
|
||||
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 339.43 295.27"><title>tether-usdt-logo</title><path d="M62.15,1.45l-61.89,130a2.52,2.52,0,0,0,.54,2.94L167.95,294.56a2.55,2.55,0,0,0,3.53,0L338.63,134.4a2.52,2.52,0,0,0,.54-2.94l-61.89-130A2.5,2.5,0,0,0,275,0H64.45a2.5,2.5,0,0,0-2.3,1.45h0Z" style="fill:#50af95;fill-rule:evenodd"/><path d="M191.19,144.8v0c-1.2.09-7.4,0.46-21.23,0.46-11,0-18.81-.33-21.55-0.46v0c-42.51-1.87-74.24-9.27-74.24-18.13s31.73-16.25,74.24-18.15v28.91c2.78,0.2,10.74.67,21.74,0.67,13.2,0,19.81-.55,21-0.66v-28.9c42.42,1.89,74.08,9.29,74.08,18.13s-31.65,16.24-74.08,18.12h0Zm0-39.25V79.68h59.2V40.23H89.21V79.68H148.4v25.86c-48.11,2.21-84.29,11.74-84.29,23.16s36.18,20.94,84.29,23.16v82.9h42.78V151.83c48-2.21,84.12-11.73,84.12-23.14s-36.09-20.93-84.12-23.15h0Zm0,0h0Z" style="fill:#fff;fill-rule:evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 874 B |
@@ -27,7 +27,8 @@ See the list of engines [**that support the feature ->**]({{< relref "/docs/how-
|
||||
You can set your global or chat-related presence with `POST /api/{session}/presence` endpoint
|
||||
|
||||
Start typing to a chat (you can use `POST /startTyping` instead)
|
||||
```json
|
||||
```
|
||||
POST /api/{session}/presence
|
||||
{
|
||||
"chatId": "111111111@c.us",
|
||||
"presence": "typing"
|
||||
@@ -35,7 +36,8 @@ Start typing to a chat (you can use `POST /startTyping` instead)
|
||||
```
|
||||
|
||||
Clear "typing" state (you can use `POST /stopTyping` instead)
|
||||
```json
|
||||
```
|
||||
POST /api/{session}/presence
|
||||
{
|
||||
"chatId": "111111111@c.us",
|
||||
"presence": "paused"
|
||||
@@ -43,7 +45,8 @@ Clear "typing" state (you can use `POST /stopTyping` instead)
|
||||
```
|
||||
|
||||
Set global "online", all contacts will see it
|
||||
```json
|
||||
```
|
||||
POST /api/{session}/presence
|
||||
{
|
||||
"presence": "online"
|
||||
}
|
||||
@@ -53,7 +56,8 @@ Set global "online", all contacts will see it
|
||||
to the device.
|
||||
If you would like to receive said notifications - you need to mark a session's presence as `offline`.
|
||||
|
||||
```json
|
||||
```
|
||||
POST /api/{session}/presence
|
||||
{
|
||||
"presence": "offline"
|
||||
}
|
||||
|
||||
@@ -115,6 +115,43 @@ Fired on all message creations, including your own. The payload is the same as f
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{< alert icon="👉" text="NOWEB engine note - reactions were sent in 'message' and 'message.any' events, not it's available only in 'message.reaction'!" />}}
|
||||
|
||||
### message.ack
|
||||
Receive events when server or recipient gets the message, read or played it.
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ We do not recommend exposing the API on any public networks!
|
||||
Either protect the API with [Api Key](https://www.fortinet.com/resources/cyberglossary/api-key) or deny access by using
|
||||
firewalls.
|
||||
|
||||
## Swagger Security 
|
||||
👉 Security options are available in [**WAHA Plus**]({{< relref "plus-version#plus" >}})  version only.
|
||||
|
||||
## Swagger Security
|
||||
### Username and password
|
||||
If you want to hide the project Swagger panel under the password - run the following command to hide under `admin/admin`
|
||||
login and password.
|
||||
@@ -35,8 +37,15 @@ You also can hide swagger completely by setting `WHATSAPP_SWAGGER_ENABLED=false`
|
||||
|
||||
{{< alert icon="👉" text="Disabling Swagger does not protect the API, please use API security as well" />}}
|
||||
|
||||
## Dashboard Security
|
||||
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 `waha`.
|
||||
- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `waha`.
|
||||
|
||||
## API security 
|
||||
Read more about [**Dashboard ->**]({{< relref "/docs/how-to/waha-dashboard" >}})
|
||||
|
||||
## API security
|
||||
|
||||
You can protect the API by requiring Api Key in a request's headers.
|
||||
|
||||
@@ -72,7 +81,7 @@ headers = {
|
||||
requests.get("http://localhost:3000/api/sessions", headers=headers)
|
||||
```
|
||||
|
||||
## Webhook security 
|
||||
## Webhook security
|
||||
To make sure that you get a webhook from your WAHA instance - you can use **HMAC authentication**.
|
||||
Read more about it on [Webhooks page ->]({{< relref "/docs/how-to/webhooks#hmac-authentication" >}})
|
||||
|
||||
@@ -57,6 +57,7 @@ To send text message - use `POST /api/sendText` with example payload.
|
||||
"text": "Hi there!"
|
||||
}
|
||||
```
|
||||
|
||||
#### 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.
|
||||
@@ -75,11 +76,6 @@ also mention it in `mentions` in format `2132132130@c.us`
|
||||
}
|
||||
```
|
||||
|
||||
### Send poll
|
||||
We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})!
|
||||
|
||||

|
||||
|
||||
### Reply on message
|
||||
To reply on a message - use `POST /api/reply` with example payload.
|
||||
```json
|
||||
@@ -94,6 +90,46 @@ To reply on a message - use `POST /api/reply` with example payload.
|
||||
#### Reply files 
|
||||
WAHA does not support reply with files (images, voice, etc.). If you're interested in it - please create an issue in GitHub.
|
||||
|
||||
|
||||
### Edit message
|
||||
You can edit **text** messages or **"caption"** in media messages.
|
||||
|
||||
```
|
||||
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:
|
||||
```
|
||||
PUT /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA
|
||||
```
|
||||
|
||||
**Payload:**
|
||||
```json
|
||||
{
|
||||
"text": "Hello, world!"
|
||||
}
|
||||
```
|
||||
|
||||
### Delete message
|
||||
You can delete messages from the chat.
|
||||
|
||||
```
|
||||
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:
|
||||
```
|
||||
DELETE /api/{session}/chats/123%40c.us/messages/true_123%40c.us_AAA
|
||||
```
|
||||
|
||||
### Send poll
|
||||
We have a dedicated page [how to send polls and receive votes]({{< relref "/docs/how-to/polls" >}})!
|
||||
|
||||

|
||||
|
||||
### Add a reaction
|
||||
Use `PUT /api/reaction` method to set reaction to a message.
|
||||
|
||||
@@ -116,6 +152,85 @@ To remove reaction from a message - send empty string in the reaction request.
|
||||
}
|
||||
```
|
||||
|
||||
### Star and unstar message
|
||||
Use `PUT /api/star` method to star or unstar a message.
|
||||
|
||||
{{< alert icon="👉" text="Star API uses PUT, not POST request! Please make sure you send right request." />}}
|
||||
|
||||
**Star:**
|
||||
```json
|
||||
{
|
||||
"messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
"chatId": "71111111111@c.us",
|
||||
"star": true,
|
||||
"session": "default"
|
||||
}
|
||||
```
|
||||
|
||||
**Unstar:**
|
||||
```json
|
||||
{
|
||||
"messageId": "false_71111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
"chatId": "71111111111@c.us",
|
||||
"star": false,
|
||||
"session": "default"
|
||||
}
|
||||
```
|
||||
|
||||
### Send contact (vcard)
|
||||
Use `POST /api/sendContactVcard` to send contact (vcard).
|
||||
|
||||
You can use fields this way:
|
||||
```json
|
||||
{
|
||||
"session": "default",
|
||||
"chatId": "79111111@c.us",
|
||||
"contacts": [
|
||||
{
|
||||
"fullName": "John Doe",
|
||||
"organization": "Company Name",
|
||||
"phoneNumber": "+91 11111 11111",
|
||||
"whatsappId": "911111111111"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Or provide a vCard file content:
|
||||
```json
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Or even combine it:
|
||||
```json
|
||||
{
|
||||
"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"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### Send image 
|
||||
Use `POST /api/sendImage` to send images.
|
||||
|
||||
@@ -158,6 +273,8 @@ 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.
|
||||
|
||||
Please make sure your file has **OPUS** encoding and packed in OGG container.
|
||||
|
||||
#### URL
|
||||
```json
|
||||
{
|
||||
@@ -165,8 +282,7 @@ You can send voice messages in two ways:
|
||||
"chatId": "11111111111@c.us",
|
||||
"file": {
|
||||
"mimetype": "audio/ogg; codecs=opus",
|
||||
"filename": "voice-message.mp3",
|
||||
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.mp3"
|
||||
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.opus"
|
||||
},
|
||||
"caption": "string"
|
||||
}
|
||||
@@ -204,7 +320,7 @@ You can send voice messages in two ways:
|
||||
"file": {
|
||||
"mimetype": "video/mp4",
|
||||
"filename": "video.mp4",
|
||||
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.mp3"
|
||||
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/video.mp4"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -233,13 +349,14 @@ You can send files in two ways:
|
||||
#### URL
|
||||
```json
|
||||
{
|
||||
"session": "default",
|
||||
"caption": "Check this out!",
|
||||
"chatId": "11111111111@c.us",
|
||||
"file": {
|
||||
"mimetype": "image/jpeg",
|
||||
"filename": "filename.jpeg",
|
||||
"url": "https://github.com/devlikeapro/whatsapp-http-api/raw/main/docs/dev.likeapro.jpg"
|
||||
},
|
||||
"session": "default"
|
||||
"url": "https://raw.githubusercontent.com/devlikeapro/whatsapp-http-api/core/examples/video.mp4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -84,6 +84,20 @@ Read more about it in [Autostart section](#autostart).
|
||||
You can configure proxy when for all sessions by set up environment variables.
|
||||
Read more about it on [**Configuration page** ->]({{< relref "/docs/how-to/config#proxy" >}}).
|
||||
|
||||
#### Enable 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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List
|
||||
|
||||
To get session list - call `GET /api/sessions`.
|
||||
@@ -94,7 +108,30 @@ The response:
|
||||
[
|
||||
{
|
||||
"name": "default",
|
||||
"status": "STARTING"
|
||||
"status": "WORKING",
|
||||
"config": {
|
||||
"proxy": null,
|
||||
"webhooks": [
|
||||
{
|
||||
"url": "https://httpbin.org/post",
|
||||
"events": [
|
||||
"message",
|
||||
"session.status"
|
||||
],
|
||||
"hmac": null,
|
||||
"retries": null,
|
||||
"customHeaders": null
|
||||
}
|
||||
],
|
||||
"debug": false
|
||||
},
|
||||
"me": {
|
||||
"id": "79111111@c.us",
|
||||
"pushName": "WAHA"
|
||||
},
|
||||
"engine": {
|
||||
"engine": "NOWEB"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -103,6 +140,38 @@ You can add `?all=true` parameter to the request `GET /api/session?all=True` it'
|
||||
including **STOPPED**,
|
||||
so you can know which one will be restarted if you set `WHATSAPP_RESTART_ALL_SESSIONS=True` environment variable.
|
||||
|
||||
### Get session
|
||||
To get information about a specific session - call `GET /api/sessions/{session}`.
|
||||
```json
|
||||
{
|
||||
"name": "default",
|
||||
"status": "WORKING",
|
||||
"config": {
|
||||
"proxy": null,
|
||||
"webhooks": [
|
||||
{
|
||||
"url": "https://httpbin.org/post",
|
||||
"events": [
|
||||
"message",
|
||||
"session.status"
|
||||
],
|
||||
"hmac": null,
|
||||
"retries": null,
|
||||
"customHeaders": null
|
||||
}
|
||||
],
|
||||
"debug": false
|
||||
},
|
||||
"me": {
|
||||
"id": "79111111@c.us",
|
||||
"pushName": "WAHA"
|
||||
},
|
||||
"engine": {
|
||||
"engine": "NOWEB"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Stop
|
||||
|
||||
In order to stop a new session - call `POST /api/sessions/stop`
|
||||
@@ -298,28 +367,8 @@ configure autostart options so when the docker container restarts - it restores
|
||||
|
||||
### Session persistent
|
||||
|
||||
#### File storage
|
||||
If you want to save your session and do not scan QR code everytime when you launch WAHA - connect a local file storage
|
||||
to the container. WAHA stores authentication information in the directory and reuses it after restart.
|
||||
|
||||
[Attach volume](https://docs.docker.com/storage/volumes/) part to the command:
|
||||
|
||||
```bash
|
||||
-v `pwd`/.sessions:/app/.sessions
|
||||
```
|
||||
|
||||
The full command would be:
|
||||
|
||||
```bash
|
||||
docker run -d -v `pwd`/.sessions:/app/.sessions -p 3000:3000/tcp --name whatsapp-http-api devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
#### Remote storage 
|
||||
|
||||
If you're interested in using some "remote" storage (like Redis or other Databases) to save sessions - please create an
|
||||
issue on GitHub.
|
||||
|
||||
For instances, it may be useful if you run WAHA in a cluster of servers and do not have shared file storage
|
||||
If you want to save your session and do not scan QR code everytime when you launch WAHA -
|
||||
[connect the session storage to the container ->]({{< relref "/docs/how-to/storages#sessions" >}})
|
||||
|
||||
### Autostart
|
||||
If you don't want to call `POST /api/sessions/start` for every session each time when the container restart -
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: "Storages"
|
||||
description: "Storages"
|
||||
lead: ""
|
||||
date: 2020-10-06T08:48:45+00:00
|
||||
lastmod: 2020-10-06T08:48:45+00:00
|
||||
draft: false
|
||||
images: [ ]
|
||||
weight: 700
|
||||
---
|
||||
There are several storages that are used by the WAHA, below you can find the list of them and the way to configure them.
|
||||
1. [Sessions](#sessions) - used to store the session data, such as authentication information, configuration, and other data that is required to keep the session alive and connected to WhatsApp.
|
||||
2. [Media](#media) - used to store the media files, such as images, videos, and other files that are received from the WhatsApp instance.
|
||||
|
||||
<b>Storages are available in [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) only.</b>
|
||||
|
||||
## Sessions
|
||||
The "Sessions" storage is used to store the session data, such as authentication information, configuration,
|
||||
and other data that is required to keep the session alive and connected to WhatsApp.
|
||||
|
||||
If you want to save your session and do not scan QR code everytime when you launch WAHA -
|
||||
connect the session storage to the container.
|
||||
|
||||
For the session storage, you can use the following options:
|
||||
1. [Local (files)](#local-files) - the default option, stores the session data in the local storage using files.
|
||||
2. [MongoDB](#mongodb) - stores the session data in the MongoDB database.
|
||||
|
||||
The following table shows the compatibility of the session storage with the engines:
|
||||
|
||||
| | WEBJS | NOWEB | VENOM |
|
||||
|---------------|:-----:|:-----:|:-----:|
|
||||
| Local (files) | ✔️ | ✔️ | ✔️ |
|
||||
| MongoDB | ✔️ | ✔️ | ➖ |
|
||||
|
||||
## Sessions - Local (files)
|
||||
By default, the WAHA uses the **local storage (files)** to store the session data.
|
||||
|
||||
{{< alert icon="💡" text="It's <b>well tested solution</b> even for production" />}}
|
||||
|
||||
In order to use the local storage and save the session data between the container restarts,
|
||||
you need to mount the volume to the `/app/.sessions` directory using the `-v` option in `docker run` command:
|
||||
|
||||
```bash
|
||||
-v /path/to/on/host/.sessions:/app/.sessions
|
||||
```
|
||||
|
||||
The full command to run the WAHA with the local storage and save the session data
|
||||
in the current directory and `.sessions` directory:
|
||||
```bash
|
||||
docker run -v `pwd`/.sessions:/app/.sessions -p 3000:3000/tcp devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
This is the only action you need to do to use the local storage - all session data will be available between the container restarts.
|
||||
|
||||
### How it works
|
||||
In the host machine, the session data will be stored in the current directory in the `.sessions` directory.
|
||||
|
||||
Under the hood, the WAHA stores the session data in the following directory structure:
|
||||
```
|
||||
.sessions/{engine}/{sessionName}/...
|
||||
```
|
||||
when you "logout" the session using [POST /api/sessions/logout]({{< relref "/docs/how-to/sessions#logout">}}) or providing `logout: True` in [POST /api/sessions/stop]({{< relref "/docs/how-to/sessions#stop">}})
|
||||
it removes the directory with the session data.
|
||||
|
||||
### Health Check
|
||||
The [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the local storage.
|
||||
|
||||
## Sessions - MongoDB
|
||||
If you want to use the MongoDB to store the session data, you need to:
|
||||
1. Start the MongoDB server (using docker or any other way). You can either start your own MongoDB server or use the one of cloud providers, like [MongoDB Atlas](https://www.mongodb.com/atlas/database).
|
||||
2. Set `WHATSAPP_SESSIONS_MONGO_URL=mongodb://user:password@host:port/` environment variable to connect to the MongoDB server.
|
||||
|
||||
|
||||
**We recommend using your own MongoDB server as close as possible to WAHA server** for the best performance and security reasons.
|
||||
|
||||
{{< alert icon="💡" text="For <b>WEBJS</b> engine it can take up to 1 minute to save credentials in Mongo Database" />}}
|
||||
|
||||
### Example
|
||||
First, you need to start MongoDB server:
|
||||
```bash
|
||||
docker run -d -p 27017:27017 --name mongodb mongo
|
||||
```
|
||||
|
||||
Then, you need to run the WAHA with the `WHATSAPP_SESSIONS_MONGO_URL` environment variable (please note using `--network host` option as well)
|
||||
```bash
|
||||
docker run -e WHATSAPP_SESSIONS_MONGO_URL=mongodb://localhost:27017/ --network host devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
This is the only action you need to do to use the MongoDB storage -
|
||||
all session authentication data will be stored in the MongoDB database.
|
||||
|
||||
### How it works
|
||||
When you start a session, it stores the session data in the MongoDB database in two databases:
|
||||
1. `waha_{engine}` - it saves the session configuration in `sessions` collection with `name: {sessionName}` field.
|
||||
2. `waha_{engine}_{sessionName}` - it saves the WhatsApp authentication data and other session data. Each engine saves different data in this database.
|
||||
|
||||
When you "logout" the session using [POST /api/sessions/logout]({{< relref "/docs/how-to/sessions#logout">}}) or providing `logout: True` in [POST /api/sessions/stop]({{< relref "/docs/how-to/sessions#stop">}}) it removes those databases or elements from them.
|
||||
|
||||
For dealing and troubleshooting with the MongoDB, we recommend using [MongoDB Compass](https://www.mongodb.com/products/tools/compass).
|
||||
|
||||

|
||||
|
||||
### MongoDB Atlas
|
||||
If you use the [MongoDB Atlas](https://www.mongodb.com/atlas/database) you must grant
|
||||
`Atlas Admin` role in **Security => Database Access** before you connect to the database.
|
||||
|
||||
For production please consider running the MongoDB server close to the WAHA server for the best performance and security reasons.
|
||||
|
||||
### Health Check
|
||||
The [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the MongoDB connection.
|
||||
|
||||
## Media
|
||||
When your WhatsApp instance receives media files, it stores them in the media storage.
|
||||
|
||||
You can use the following options to store the media files:
|
||||
1. [Local](#local) - the default option, stores the media files in the local storage using files.
|
||||
2. [S3](#s3) - stores the media files in the S3 storage.
|
||||
|
||||
Read more about [available configuration options ->]({{<relref "/docs/how-to/config#files">}}).
|
||||
|
||||
The following table shows the compatibility of the storage with the engines:
|
||||
|
||||
| | WEBJS | NOWEB | VENOM |
|
||||
|-------|:-----:|:-----:|:-----:|
|
||||
| Local | ✔️ | ✔️ | ✔️ |
|
||||
| S3 | 🕒 | 🕒 | ➖ |
|
||||
|
||||
## Media - Local
|
||||
By default, the WAHA uses the **local file storage** to store the media files and those files has a short lifetime (180 seconds).
|
||||
So it's your app responsibility to download and store them in a safe persistent place during this time.
|
||||
|
||||
### Save media files between the container restarts
|
||||
If you want to use the local storage and **save the media files between the container restarts for a long time** - you need to:
|
||||
1. Specify a dedicated folder to store the media files using `WHATSAPP_FILES_FOLDER=/app/.media` environment variable
|
||||
2. Disable automatic media files cleanup using `WHATSAPP_FILES_LIFETIME=0` environment variable
|
||||
3. Connect the volume to the specified folder using the `-v /path/to/files/on/host:/app/.media` option in `docker run` command to the folder specified in `WHATSAPP_FILES_FOLDER` environment variable.
|
||||
|
||||
Read more about [available configuration options ->]({{<relref "/docs/how-to/config#files">}}).
|
||||
|
||||
Here's all the steps in one command:
|
||||
```bash
|
||||
docker run -v /path/to/on/host/.media:/app/.media -e WHATSAPP_FILES_FOLDER=/app/.media -e WHATSAPP_FILES_LIFETIME=0 -p 3000:3000/tcp devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
### Health Check
|
||||
The [WAHA Plus ]({{< relref "/docs/how-to/plus-version" >}}) provides [the health check endpoint]({{< relref "/docs/how-to/other" >}}) that checks the local storage.
|
||||
|
||||
## Media - S3
|
||||
If you're interested in using the S3 storage or any other cloud storage (like [self-hosted S3 - Minio](https://min.io/)),
|
||||
please create an issue or vote for the S3 issue in [the GitHub repository](https://github.com/devlikeapro/whatsapp-http-api/issues?q=is%3Aissue+is%3Aopen+S3).
|
||||
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "Dashboard"
|
||||
description: "Dashboard"
|
||||
lead: ""
|
||||
date: 2020-10-06T08:48:45+00:00
|
||||
lastmod: 2020-10-06T08:48:45+00:00
|
||||
draft: false
|
||||
images: [ ]
|
||||
weight: 110
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**WAHA Dashboard** is a UI to manage your WhatsApp sessions!
|
||||
|
||||
|
||||

|
||||
<div class="text-center">
|
||||
<a href="./waha-dashboard.png" target="_blank">See full size image</a>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
👉 **WAHA Dashboard** is available in [**WAHA Plus**]({{< relref "plus-version#plus" >}})  version only.
|
||||
|
||||
You can access **WAHA Dashboard** by running the project and opening
|
||||
<a href="http://localhost:3000/dashboard" target="_blank">http://localhost:3000/dashboard</a>
|
||||
(or similar, but with <a href="/dashboard" target="_blank">/dashboard</a> at the end).
|
||||
|
||||
ℹ️ **Default username and password**: `waha/waha`
|
||||
|
||||
```bash
|
||||
docker run -it -p 3000:3000/tcp devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
If you're using [API Key]({{< relref "security" >}}), remember to set up the key in the dashboard.
|
||||
|
||||

|
||||
<div class="text-center">
|
||||
<a href="./waha-dashboard-key.png" target="_blank">See full size image</a>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
## 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 `waha`.
|
||||
- `WAHA_DASHBOARD_PASSWORD=waha` - password used to log in, by default `waha`.
|
||||
|
||||
```bash
|
||||
docker run -it -p 3000:3000/tcp -e WAHA_DASHBOARD_USERNAME=waha -e WAHA_DASHBOARD_PASSWORD=waha devlikeapro/whatsapp-http-api-plus
|
||||
```
|
||||
|
||||
## Multiple servers
|
||||
If you wish to connect, control and manage multiple servers in a single "dashboard", consider using
|
||||
[WAHA Hub]({{< relref "/docs/waha-hub/introduction" >}}) - central management server to help you build reliable infrastructure!
|
||||
|
||||
## Bug reports and feature requests
|
||||
If you're experiencing any issues or have a feature request, please create an issue in the
|
||||
[WAHA GitHub](https://github.com/devlikeapro/whatsapp-http-api/issues)
|
||||
|
||||
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 73 KiB |
@@ -226,6 +226,43 @@ Fired on all message creations, including your own. The payload is the same as f
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{< alert icon="👉" text="NOWEB engine note - reactions were sent in 'message' and 'message.any' events, not it's available only in 'message.reaction'!" />}}
|
||||
|
||||
### message.ack
|
||||
Receive events when server or recipient gets the message, read or played it.
|
||||
|
||||
@@ -263,7 +300,7 @@ revokes a previously sent message.
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "message.ack",
|
||||
"event": "message.revoked",
|
||||
"session": "default",
|
||||
"payload": {
|
||||
"before": {
|
||||
|
||||
@@ -19,6 +19,99 @@ If you wish to get and read Release Notes - read them on one of our platforms, *
|
||||
|
||||
You even can **subscribe to get new updates** there!
|
||||
|
||||
## 2024.4
|
||||
### 🎉 New
|
||||
----
|
||||
|
||||
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/whatsapp-http-api/issues/300)
|
||||
|
||||
----
|
||||
|
||||
Implement `GET /api/contacts/profile-picture` for **NOWEB** engine.
|
||||
- Issue: [#298](https://github.com/devlikeapro/whatsapp-http-api/issues/298)
|
||||
|
||||
----
|
||||
|
||||
## 2024.3
|
||||
### 🎉 New
|
||||
|
||||
----
|
||||
|
||||
Add `message.reaction` webhook in **WEBJS** and **NOWEB** engines
|
||||
- Read more about [message.reaction]({{< relref "/docs/how-to/webhooks#messagereaction" >}}) event
|
||||
- Issue: [#275](https://github.com/devlikeapro/whatsapp-http-api/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/whatsapp-http-api/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/whatsapp-http-api/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/whatsapp-http-api/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/whatsapp-http-api/issues/256)
|
||||
|
||||
----
|
||||
|
||||
Handles `caption` and `filename` right in `POST /api/sendFile`
|
||||
- Issue: [#94](https://github.com/devlikeapro/whatsapp-http-api/issues/94)
|
||||
- Issue: [#133](https://github.com/devlikeapro/whatsapp-http-api/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/whatsapp-http-api/issues/274)
|
||||
|
||||
----
|
||||
|
||||
Add `config.debug` field to `POST /api/session/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/other/)
|
||||
|
||||
## 2024.1
|
||||
- Implement [Patron Portal](https://portal.devlike.pro/) where you can get your personal API key and manage your perks.
|
||||
- Read more on [Patreon ->](https://www.patreon.com/posts/waha-patron-97637416)
|
||||
- Read more on [Boosty ->](https://boosty.to/wa-http-api/posts/8319079f-dac1-4179-b954-fcc559097c76)
|
||||
|
||||
## 2024.2
|
||||
- Listen for browser disconnected and page close events in **WEBJS** engine [#262](https://github.com/devlikeapro/whatsapp-http-api/issues/262)
|
||||
|
||||
## 2023.12
|
||||
December 2023
|
||||
- Add `chatId` field to `GET /api/contacts/check-exists` to help get the right `chatId` for Brazilian numbers.
|
||||
|
||||
@@ -14,6 +14,7 @@ toc: true
|
||||
---
|
||||
|
||||
## How much CPU and Memory does WhatsApp HTTP API consume?
|
||||
### WEBJS
|
||||
|
||||
The benchmark has been made on **Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz**.
|
||||
It may differ from case to case, it depends on usage pattern - how many messages you get, how many send, etc.
|
||||
@@ -26,4 +27,12 @@ It may differ from case to case, it depends on usage pattern - how many messages
|
||||
The nature of WhatsApp HTTP API and its underlying engines - is to run **real** WhatsApp Web version in Chrome and
|
||||
communicate with it to prevent blocking from WhatsApp. It's the reason why it's so demanding on resources.
|
||||
|
||||
### NOWEB
|
||||
If you're looking for less resource demanded engine - [have a look at **NOWEB** engine ->]({{< relref "/docs/how-to/engines" >}})
|
||||
|
||||
Quotes from the users:
|
||||
> The server has **2 CPU and 8GB** of memory. Today we have **85 sessions** in this instance.
|
||||
|
||||
> **400** sessions with **4CPU and 32RAM**. It's working fine.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ toc: true
|
||||
**WAHA** - **W**hats**A**pp **H**TTP **A**PI that you can install on your own server and run in less than 5 minutes!
|
||||
|
||||
<div class="d-flex justify-content-center my-4">
|
||||
<img src="/images/logo.png"/>
|
||||
<img src="/images/logo.svg" style='border-radius: 50%' width='150'/>
|
||||
</div>
|
||||
|
||||
## Get started
|
||||
|
||||
@@ -9,7 +9,7 @@ images: []
|
||||
menu:
|
||||
docs:
|
||||
parent: "overview"
|
||||
weight: 110
|
||||
weight: 101
|
||||
toc: true
|
||||
---
|
||||
|
||||
@@ -36,18 +36,21 @@ Also, Docker makes installation and update processes so simple, just one command
|
||||
|
||||
We will guide you through the necessary steps to successfully send your first text message using WhatsApp HTTP API.
|
||||
|
||||
**If you find it easier to follow a video** tutorial, we've got you covered!
|
||||
A 3-minute video tutorial is available to help you navigate WhatsApp HTTP API smoothly.
|
||||
<div class='article-card'>
|
||||
<b class='h4'>Are you a visual learner?</b>
|
||||
|
||||
<div class="d-flex justify-content-center my-4">
|
||||
<iframe
|
||||
width="560" height="315"
|
||||
src="https://www.youtube.com/embed/RFerMyAUPRg"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
We've got you covered! Watch the video below to see how to send your first message using <b>WAHA</b>.
|
||||
|
||||
<div class="d-flex justify-content-center my-4">
|
||||
<iframe
|
||||
width="560" height="315"
|
||||
src="https://www.youtube.com/embed/RFerMyAUPRg"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
### 1. Download image
|
||||
@@ -107,6 +110,9 @@ Open the link in your browser [http://localhost:3000/](http://localhost:3000/) a
|
||||
(Swagger).
|
||||
|
||||
{{< alert icon="👉" text="We don't recommend expose the API in the internet without authentication!" />}}
|
||||
[Read more about Security ->]({{< relref "/docs/how-to/security" >}})
|
||||
|
||||
<br/>
|
||||
|
||||

|
||||
|
||||
@@ -183,8 +189,9 @@ curl -d "{\"chatId\": \"${PHONE}@c.us\", \"text\": \"Hello from WhatsApp HTTP AP
|
||||
```
|
||||
|
||||
## What is next?
|
||||
- Right now you've sent simple text message, but you can send more! [Send messages →]({{< relref "/docs/how-to/send-messages" >}})
|
||||
- Read how to receive and response to messages [Receive messages →]({{< relref "/docs/how-to/receive-messages" >}})
|
||||
- Learn about the easiest way to manage your WhatsApp sessions - [WAHA Dashboard ->]({{< relref "/docs/how-to/waha-dashboard" >}})
|
||||
- Right now you've sent simple text message, but you can send more! [Send messages ->]({{< relref "/docs/how-to/send-messages" >}})
|
||||
- Read how to receive and response to messages [Receive messages ->]({{< relref "/docs/how-to/receive-messages" >}})
|
||||
- [Save session information, so you don't have to scan QR after container restart ->]({{< relref "/docs/how-to/sessions" >}})
|
||||
- Make sure your [API is properly protected ->]({{< relref "/docs/how-to/security" >}})
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title : "WAHA Hub"
|
||||
description: "WAHA Hub"
|
||||
lead: ""
|
||||
date: 2020-10-06T08:48:45+00:00
|
||||
lastmod: 2020-10-06T08:48:45+00:00
|
||||
draft: false
|
||||
images: []
|
||||
weight: 300
|
||||
---
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: "WAHA Hub"
|
||||
description: "WAHA Hub"
|
||||
lead: ""
|
||||
date: 2020-10-06T08:48:57+00:00
|
||||
lastmod: 2020-10-06T08:48:57+00:00
|
||||
draft: false
|
||||
images: [ ]
|
||||
menu:
|
||||
docs:
|
||||
parent: "overview"
|
||||
weight: 100
|
||||
toc: true
|
||||
---
|
||||
|
||||
⚠️ The project in **DEVELOPMENT** yet... Subscribe to [**WAHA PRO**]({{< relref "plus-version#pro" >}}) to speed up the
|
||||
development!
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**WAHA Hub** - central management solution to help your build reliable infrastructure with multiple WAHA servers!
|
||||
|
||||
While [WAHA Dashboard]({{< relref "/docs/how-to/waha-dashboard" >}}) is a UI to manage your WhatsApp sessions on
|
||||
**single server**, **WAHA Hub** is a central management server to control and manage **multiple servers** in a single
|
||||
place.
|
||||
|
||||
👉 **WAHA Hub** is available in [**WAHA PRO**]({{< relref "plus-version#pro" >}}) version only.
|
||||
|
||||

|
||||
<div class="text-center">
|
||||
<a href="waha-dashboard.png" target="_blank">See full size image</a>
|
||||
</div>
|
||||
|
||||
## Features
|
||||
|
||||
- Control and manage multiple servers in a single Hub.
|
||||
- Monitor the status of your servers
|
||||
- And more!
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 73 KiB |
@@ -1,93 +1,258 @@
|
||||
{{ define "main" }}
|
||||
<section class="section container-fluid mt-n3 pb-3">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h1 class="mt-0">{{ .Title }}</h1>
|
||||
<section class='section container-fluid mt-n3 pb-3'>
|
||||
<div class='row justify-content-center'>
|
||||
<div class='col-lg-12 text-center'>
|
||||
<h1 class='mt-0'>{{ .Title }}</h1>
|
||||
</div>
|
||||
<div class="col-lg-9 col-xl-9 text-center">
|
||||
<div class="mb-4">
|
||||
<img src="/images/logo.png" title="WhatsApp HTTP API" alt="logo" width="100"/>
|
||||
<div class='col-lg-9 col-xl-9 text-center'>
|
||||
<div class='mb-4'>
|
||||
<img src='/images/logo.svg' title='WhatsApp HTTP API' alt='logo' width='100' style='border-radius: 50%'/>
|
||||
</div>
|
||||
<p class="lead">{{ .Params.lead | safeHTML }}</p>
|
||||
<code>
|
||||
docker run -it -p 3000:3000/tcp devlikeapro/whatsapp-http-api
|
||||
</code>
|
||||
<br/>
|
||||
<br/>
|
||||
<a class="btn btn-primary btn-lg px-4 mb-2"
|
||||
href="/docs/{{ if .Site.Params.options.docsVersioning }}{{ .Site.Params.docsVersion }}/{{ end }}overview/introduction/"
|
||||
role="button">Get Started</a>
|
||||
<p class="meta"><a href="https://github.com/devlikeapro/whatsapp-http-api">Source code in GitHub.</a></p>
|
||||
<p class='lead'>{{ .Params.lead | safeHTML }}</p>
|
||||
<div class='code-block highlight'>
|
||||
<pre tabindex='0' class='chroma'><code class='language-bash' data-lang='bash' style='padding: 0'>docker run -it -p 3000:3000/tcp devlikeapro/whatsapp-http-api</code></pre>
|
||||
</div>
|
||||
<a class='btn btn-primary btn-lg px-4 mb-2'
|
||||
href='/docs/{{ if .Site.Params.options.docsVersioning }}{{ .Site.Params.docsVersion }}/{{ end }}overview/introduction/'
|
||||
role='button'>Get Started</a>
|
||||
<p class='meta'><a href='https://github.com/devlikeapro/whatsapp-http-api'>Source code in GitHub.</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{ define "sidebar-prefooter" }}
|
||||
<section class="section section-sm">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center text-center">
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">It's free!</h2>
|
||||
<section class='section section-sm'>
|
||||
<div class='container hr'>
|
||||
<div class='row justify-content-center text-center'>
|
||||
<div class='col-12'>
|
||||
<h2>
|
||||
WAHA Features
|
||||
</h2>
|
||||
</div>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/message-green.png' alt='Free' style='width: 5rem'>
|
||||
<h2 class='h4 color-accent'>Send and Receive<br />Messages</h2>
|
||||
<p>
|
||||
<b>WAHA Core</b> version is always free!
|
||||
You can
|
||||
<a href='https://waha.devlike.pro/docs/how-to/send-messages/'>send</a>
|
||||
and
|
||||
<a href='https://waha.devlike.pro/docs/how-to/receive-messages/'>receive</a>
|
||||
messages from WhatsApp using HTTP API.
|
||||
</p>
|
||||
|
||||
<div class='code-block highlight' style='text-align: left'>
|
||||
<pre tabindex='0' class='chroma m-0'>
|
||||
<code class='language-json' data-lang='json' style='padding: 1rem!important; border-radius: 0.5rem'>POST /api/sendText
|
||||
{
|
||||
"session": "default",
|
||||
"chatId": "12132132130@c.us",
|
||||
"text": "Hi there!"
|
||||
}
|
||||
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/file-check-green.svg' alt='Servers' style='width: 5rem'>
|
||||
<h2 class='h4'>Send and Receive<br />Files</h2>
|
||||
<p>
|
||||
You can
|
||||
<a href='https://waha.devlike.pro/docs/how-to/send-messages/'>send</a>
|
||||
and
|
||||
<a href='https://waha.devlike.pro/docs/how-to/receive-messages/'>receive</a>
|
||||
files from WhatsApp using HTTP API.
|
||||
</p>
|
||||
|
||||
<div class='code-block highlight' style='text-align: left'>
|
||||
<pre tabindex='0' class='chroma m-0'>
|
||||
<code class='language-json' data-lang='json' style='padding: 1rem!important; border-radius: 0.5rem'>POST /api/sendFile
|
||||
{
|
||||
"session": "default",
|
||||
"chatId": "12132132130@c.us",
|
||||
"file": {
|
||||
"url": "https://d.com/invoice.pdf"
|
||||
}
|
||||
}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/button-green.png' alt='API' style='width: 5rem'>
|
||||
<h2 class='h4'>
|
||||
WAHA can do<br />a lot more
|
||||
</h2>
|
||||
<p>
|
||||
Check out
|
||||
<a href='https://waha.devlike.pro/docs/overview/introduction/#features'>
|
||||
the documentation
|
||||
</a>
|
||||
to see all the features.
|
||||
</p>
|
||||
|
||||
<div class='code-block highlight' style='text-align: left'>
|
||||
<pre tabindex='0' class='chroma m-0'>
|
||||
<code class='language-json' data-lang='json' style='padding: 1rem!important; border-radius: 0.5rem'>POST /api/{session}/groups
|
||||
{
|
||||
"name": "Group name",
|
||||
"participants": [
|
||||
{"id": "123123123123@c.us"}
|
||||
]
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='col-12 pros-card' style='width: 80%'>
|
||||
<h2 class='h4 color-accent'>Swagger documentation and OpenApi schema!</h2>
|
||||
<p>
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#core' target='_blank'>
|
||||
<b>WAHA Core</b>
|
||||
</a>
|
||||
and
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#plus' target='_blank'>
|
||||
<b>WAHA Plus</b>
|
||||
</a>
|
||||
provide
|
||||
<a href='https://waha.devlike.pro/swagger' target='_blank'>
|
||||
Swagger documentation and OpenApi schema.
|
||||
</a>
|
||||
<br>
|
||||
Even <b>WAHA Plus</b> version have no licence expiration!
|
||||
</p>
|
||||
<img src='/images/swagger.png' alt='Swagger' style='max-width: 100%'>
|
||||
</div>
|
||||
|
||||
<div class='col-12 pros-card' style='width: 80%'>
|
||||
<h2 class='h4 color-accent'>WAHA Dashboard</h2>
|
||||
<p>
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#plus' target='_blank'>
|
||||
<b>WAHA Plus</b>
|
||||
</a>
|
||||
provides
|
||||
<a href='https://waha.devlike.pro/docs/how-to/waha-dashboard' target='_blank'>
|
||||
WAHA Dashboard
|
||||
</a> - a web interface to easily manage your WhatsApp sessions!
|
||||
<br>
|
||||
</p>
|
||||
<img src='/images/waha-dashboard.png' alt='WAHA Dashboard' style='max-width: 100%'>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class='section section-sm'>
|
||||
<div class='container hr'>
|
||||
<div class='row justify-content-center text-center'>
|
||||
<div class='col-12'>
|
||||
<h2>
|
||||
Why WAHA?
|
||||
</h2>
|
||||
</div>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/free-green.png' alt='Free' style='width: 5rem'>
|
||||
<h2 class='h4 color-accent'>It's free!</h2>
|
||||
<p>
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>
|
||||
<b>WAHA Core</b>
|
||||
</a>
|
||||
version is always free, <b>no limits in messages</b> or time!
|
||||
<br>
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#tiers' target='_blank'>
|
||||
<b>WAHA Plus</b>
|
||||
</a>
|
||||
version have no licence expiration!
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">Language agnostic</h2>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/servers-green.png' alt='Servers' style='width: 5rem'>
|
||||
<h2 class='h4'>Self-hosted solution</h2>
|
||||
<p>
|
||||
<a href='https://waha.devlike.pro/docs/how-to/plus-version/#why-waha' target='_blank'>
|
||||
No strings to suspicious SaaS WhatsApp HTTP API solutions.
|
||||
</a>
|
||||
Install it on your own server!
|
||||
</p>
|
||||
</div>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/api-green.png' alt='API' style='width: 5rem'>
|
||||
<h2 class='h4'>HTTP API</h2>
|
||||
<p>
|
||||
Use your own favorite language - Python, JavaScript, PHP, C#, Clojure, or PowerShell.
|
||||
<br/>
|
||||
<small class="text-muted">
|
||||
<br />
|
||||
<small class='text-muted'>
|
||||
PowerShell, really? Are you insane?! Choose another language, dude.
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">Well documented</h2>
|
||||
<p>Documentation has a lof examples and how-to guides.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center text-center">
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">Self hosted</h2>
|
||||
<div class='row justify-content-center text-center'>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/document-green.png' alt='Document' style='width: 5rem'>
|
||||
<h2 class='h4'>Well documented</h2>
|
||||
<p>
|
||||
No strings to suspicious SaaS WhatsApp HTTP API solutions. Install it on your own server!
|
||||
</p>
|
||||
<a href='https://waha.devlike.pro/docs/overview/introduction/' target='_blank'>
|
||||
Documentation
|
||||
</a>
|
||||
has a lof examples and how-to guides.</p>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">Easy installation</h2>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/easy-green.png' alt='Easy' style='width: 5rem'>
|
||||
<h2 class='h4'>Quick installation</h2>
|
||||
<p>
|
||||
You need to install <a href="https://docs.docker.com/engine/install/">Docker</a> and can run the API in a
|
||||
click!
|
||||
<br/>
|
||||
<small class="text-muted">
|
||||
You need to install Docker and
|
||||
<a href='https://waha.devlike.pro/docs/how-to/install/' target='_blank'>
|
||||
run the API in a click!
|
||||
</a>
|
||||
<br />
|
||||
<small class='text-muted'>
|
||||
It's actually "a command", not a click.
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<h2 class="h4">No blocking</h2>
|
||||
<div class='col-12 col-lg-4 pros-card'>
|
||||
<img src='/images/icons/checked-green.png' alt='Checked' style='width: 5rem'>
|
||||
<h2 class='h4'>No blocking</h2>
|
||||
<p>
|
||||
Under the hood it runs a real instance of Whatsapp Web to avoid getting blocked.
|
||||
<br/>
|
||||
<small class="text-muted">
|
||||
<a href='https://waha.devlike.pro/docs/how-to/engines/' target='_blank'>
|
||||
Under the hood
|
||||
</a>
|
||||
it runs a real instance of Whatsapp Web to avoid getting blocked.
|
||||
<br />
|
||||
<small class='text-muted'>
|
||||
WhatsApp does not allow bots or unofficial clients on their platform, so this shouldn't be considered
|
||||
totally safe.
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class='section section-sm'>
|
||||
<div class='container hr'>
|
||||
<div class='text-center mt-4'>
|
||||
<h2>
|
||||
Try it now!
|
||||
</h2>
|
||||
<div class='mb-4'>
|
||||
<img src='/images/logo.png' title='WhatsApp HTTP API' alt='logo' width='100' />
|
||||
</div>
|
||||
<a class='btn btn-primary btn-lg px-4 mb-2'
|
||||
href='/docs/{{ if .Site.Params.options.docsVersioning }}{{ .Site.Params.docsVersion }}/{{ end }}overview/introduction/'
|
||||
role='button'>Get Started</a>
|
||||
<p class='meta'><a href='https://github.com/devlikeapro/whatsapp-http-api'>Source code in GitHub.</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{ define "sidebar-footer" }}
|
||||
<section class="section section-sm container-fluid">
|
||||
<div class="row justify-content-center text-center">
|
||||
<div class="col-lg-9">
|
||||
<section class='section section-sm container-fluid'>
|
||||
<div class='row justify-content-center text-center'>
|
||||
<div class='col-lg-9'>
|
||||
{{- .Content -}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,63 @@
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript" >
|
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||||
<script type='text/javascript'>
|
||||
(function(m, e, t, r, i, k, a) {
|
||||
m[i] = m[i] || function() {
|
||||
(m[i].a = m[i].a || []).push(arguments);
|
||||
};
|
||||
m[i].l = 1 * new Date();
|
||||
for (var j = 0; j < document.scripts.length; j++) {
|
||||
if (document.scripts[j].src === r) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
k = e.createElement(t), a = e.getElementsByTagName(t)[0], k.async = 1, k.src = r, a.parentNode.insertBefore(k, a);
|
||||
})
|
||||
(window, document, 'script', 'https://mc.yandex.ru/metrika/tag.js', 'ym');
|
||||
|
||||
ym(91185978, "init", {
|
||||
clickmap:true,
|
||||
trackLinks:true,
|
||||
accurateTrackBounce:true,
|
||||
webvisor:true
|
||||
});
|
||||
ym(91185978, 'init', {
|
||||
clickmap: true,
|
||||
trackLinks: true,
|
||||
accurateTrackBounce: true,
|
||||
webvisor: true,
|
||||
});
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/91185978" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<noscript>
|
||||
<div><img src='https://mc.yandex.ru/watch/91185978' style='position:absolute; left:-9999px;' alt='' /></div>
|
||||
</noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-2XLLXRJ1KF"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-2XLLXRJ1KF');
|
||||
</script>
|
||||
<!-- /Google tag (gtag.js) -->
|
||||
|
||||
<!-- Main page cards -->
|
||||
<style>
|
||||
.pros-card {
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1.5rem;
|
||||
margin: 1rem;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.article-card {
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1.5rem;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 1rem 0 #4aae2050;
|
||||
}
|
||||
|
||||
.hr {
|
||||
border-top: 1px solid #e9ecef;
|
||||
}
|
||||
</style>
|
||||
<!-- /Main page cards -->
|
||||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,289 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link rel="icon" href="./favicon.ico" />
|
||||
<style>
|
||||
:root {
|
||||
--surface-card: #1f2937;
|
||||
--surface-border: #374151;
|
||||
--card-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bg-image {
|
||||
/* The image used */
|
||||
background-image: url('./waha-dashboard.png');
|
||||
|
||||
/* Add the blur effect */
|
||||
filter: blur(2px);
|
||||
-webkit-filter: blur(2px);
|
||||
|
||||
/* Full height */
|
||||
height: 100%;
|
||||
|
||||
/* Center and scale the image nicely */
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #111827;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 20px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(158, 158, 255);
|
||||
text-decoration-color: rgb(158, 158, 255);
|
||||
}
|
||||
|
||||
.upgrade-link {
|
||||
text-decoration: none;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
background-color: #4ade80;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
color: #052e16;
|
||||
text-decoration: none;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.card {
|
||||
min-width: 25rem;
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--surface-border);
|
||||
box-shadow: var(--card-shadow);
|
||||
padding: 2rem;
|
||||
border-radius: 12px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 2;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg-image"></div>
|
||||
<div class="card">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="1080"
|
||||
height="1080"
|
||||
viewBox="0 0 1080 1080"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<desc>Created with Fabric.js 5.2.4</desc>
|
||||
<defs></defs>
|
||||
<g
|
||||
transform="matrix(1 0 0 1 540 540)"
|
||||
id="c3cb5d1b-8350-492a-8567-8c1ee2307b9a"
|
||||
></g>
|
||||
<g
|
||||
transform="matrix(1 0 0 1 540 540)"
|
||||
id="054ae9ae-db12-4435-8648-8bfb02267690"
|
||||
>
|
||||
<rect
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(255, 255, 255);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
visibility: hidden;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
x="-540"
|
||||
y="-540"
|
||||
rx="0"
|
||||
ry="0"
|
||||
width="1080"
|
||||
height="1080"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 540 540)">
|
||||
<rect
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(255, 255, 255);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
visibility: hidden;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
x="-540"
|
||||
y="-540"
|
||||
rx="0"
|
||||
ry="0"
|
||||
width="1080"
|
||||
height="1080"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(2.02 0 0 2.02 540 540)">
|
||||
<rect
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(255, 255, 255);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
visibility: hidden;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
x="-540"
|
||||
y="-540"
|
||||
rx="0"
|
||||
ry="0"
|
||||
width="1080"
|
||||
height="1080"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(3.68 0 0 3.68 540.38 540.48)">
|
||||
<path
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(74, 173, 32);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
transform=" translate(-392.21, -570.16)"
|
||||
d="M 392.26 705.96 C 376.77 705.96 361.28999999999996 706.0400000000001 345.8 705.95 C 318.16 705.7900000000001 297.6 685.2700000000001 297.22 657.57 C 297.15000000000003 652.24 297.07000000000005 646.9100000000001 297.25 641.59 C 297.36 638.23 296.3 636.6 292.72 636.89 C 290.24 637.09 287.73 636.98 285.23 636.9 C 277.1 636.63 271.70000000000005 631.65 271.38 623.49 C 271.06 615.1800000000001 271.06 606.83 271.37 598.52 C 271.69 590.05 277.04 585.23 285.58 585.01 C 297.21 584.72 297.19 584.72 297.21999999999997 573.01 C 297.22999999999996 567.36 297.14 561.72 297.97999999999996 556.0699999999999 C 301.25999999999993 533.93 320.72999999999996 516.4599999999999 343.09 516.04 C 355.07 515.81 367.07 515.86 379.04999999999995 516.02 C 382.72999999999996 516.0699999999999 384.02 514.87 383.96 511.15 C 383.77 500.65999999999997 383.76 490.16999999999996 383.96999999999997 479.67999999999995 C 384.04999999999995 476.00999999999993 382.96 473.65999999999997 379.92999999999995 471.37999999999994 C 372.23999999999995 465.5799999999999 369.78 456.25999999999993 373.06999999999994 447.7199999999999 C 376.18999999999994 439.5999999999999 385.13999999999993 433.7399999999999 393.4599999999999 434.3599999999999 C 402.63999999999993 435.0399999999999 410.43999999999994 441.3499999999999 412.4599999999999 450.2199999999999 C 414.4799999999999 459.0299999999999 411.7099999999999 466.4299999999999 404.4699999999999 471.7899999999999 C 401.8699999999999 473.7199999999999 400.9199999999999 475.69999999999993 400.9699999999999 478.8299999999999 C 401.1199999999999 489.1499999999999 401.2499999999999 499.4799999999999 400.9299999999999 509.79999999999995 C 400.7899999999999 514.5 402.0299999999999 516.24 406.9999999999999 516.0799999999999 C 417.8099999999999 515.7299999999999 428.6399999999999 515.91 439.4699999999999 515.9899999999999 C 466.5199999999999 516.2099999999999 486.7199999999999 536.2299999999999 487.2399999999999 563.3 C 487.3399999999999 568.29 487.2599999999999 573.29 487.2799999999999 578.29 C 487.2999999999999 585 487.3099999999999 585 493.7899999999999 585.02 C 495.94999999999993 585.03 498.1199999999999 584.96 500.2799999999999 585.06 C 507.94999999999993 585.43 512.9999999999999 590.42 513.1499999999999 598.1199999999999 C 513.3199999999998 606.6099999999999 513.3099999999998 615.1099999999999 513.1599999999999 623.5999999999999 C 513.0299999999999 631.3599999999999 508.1999999999999 636.31 500.47999999999985 636.8699999999999 C 498.15999999999985 637.0399999999998 495.77999999999986 637.2199999999999 493.49999999999983 636.8899999999999 C 488.1999999999998 636.1299999999999 486.86999999999983 638.5399999999998 487.1999999999998 643.3999999999999 C 487.54999999999984 648.5399999999998 487.3499999999998 653.7199999999999 487.23999999999984 658.8799999999999 C 486.67999999999984 685.6599999999999 466.4599999999998 705.7399999999999 439.71999999999986 705.9599999999999 C 423.9 706.06 408.08 705.95 392.26 705.96 z"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(-3.68 0 0 -3.68 546.38 845.01)">
|
||||
<path
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(56, 134, 22);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
transform=" translate(-394.07, -654.42)"
|
||||
d="M 394.26 632.93 C 404.75 632.93 415.23 632.9 425.71999999999997 632.9399999999999 C 431.92999999999995 632.9599999999999 433.52 634.7399999999999 432.90999999999997 640.7099999999999 C 430.99999999999994 659.66 414.40999999999997 675.2199999999999 395.38 675.91 C 376.87 676.5799999999999 359.57 662.65 356 644.1899999999999 C 355.72 642.7199999999999 355.33 641.26 355.19 639.78 C 354.71 634.9 356.32 633.01 361.3 632.97 C 372.29 632.87 383.28 632.93 394.26 632.93 z"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(3.68 0 0 3.68 673.99 594.08)">
|
||||
<path
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(56, 135, 22);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
transform=" translate(-428.75, -584.99)"
|
||||
d="M 428.83 602 C 419.12 601.96 411.59999999999997 594.6 411.53 585.07 C 411.46999999999997 575.4100000000001 419.21 567.9100000000001 429.16999999999996 567.98 C 438.33 568.0500000000001 445.93999999999994 575.71 445.97999999999996 584.91 C 446.02 594.33 438.29 602.04 428.83 602 z"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</g>
|
||||
<g transform="matrix(3.68 0 0 3.68 406.92 594.18)">
|
||||
<path
|
||||
style="
|
||||
stroke: none;
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: butt;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
fill: rgb(56, 135, 22);
|
||||
fill-rule: nonzero;
|
||||
opacity: 1;
|
||||
"
|
||||
vector-effect="non-scaling-stroke"
|
||||
transform=" translate(-356.06, -584.99)"
|
||||
d="M 339.05 584.57 C 339.19 574.94 346.67 567.84 356.53000000000003 567.99 C 366.26000000000005 568.14 373.21000000000004 575.46 373.07000000000005 585.42 C 372.94000000000005 595.16 365.62000000000006 602.13 355.68000000000006 602 C 346.04 601.87 338.91 594.4 339.05 584.57 z"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<div class="message">
|
||||
Sorry,
|
||||
<a
|
||||
href="https://waha.devlike.pro/docs/how-to/waha-dashboard"
|
||||
target="_blank"
|
||||
>WAHA Dashboard</a
|
||||
>
|
||||
is not available in <strong>WAHA Core</strong> version.
|
||||
<br />
|
||||
Please consider upgrading to <strong>WAHA Plus</strong>.
|
||||
</div>
|
||||
<div style="margin-top: 2rem; margin-bottom: 1rem">
|
||||
<a
|
||||
class="upgrade-link link-button"
|
||||
href="https://waha.devlike.pro/docs/how-to/plus-version/"
|
||||
target="_blank"
|
||||
>Upgrade to WAHA Plus</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 646 B After Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M15 19L17 21L21 17M13 3H8.2C7.0799 3 6.51984 3 6.09202 3.21799C5.71569 3.40973 5.40973 3.71569 5.21799 4.09202C5 4.51984 5 5.0799 5 6.2V17.8C5 18.9201 5 19.4802 5.21799 19.908C5.40973 20.2843 5.71569 20.5903 6.09202 20.782C6.51984 21 7.0799 21 8.2 21H11.5M13 3L19 9M13 3V7.4C13 7.96005 13 8.24008 13.109 8.45399C13.2049 8.64215 13.3578 8.79513 13.546 8.89101C13.7599 9 14.0399 9 14.6 9H19M19 9V13.4M9 17H11.5M9 13H15M9 9H10" stroke="#388716" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 747 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 19L17 21L21 17M13 3H8.2C7.0799 3 6.51984 3 6.09202 3.21799C5.71569 3.40973 5.40973 3.71569 5.21799 4.09202C5 4.51984 5 5.0799 5 6.2V17.8C5 18.9201 5 19.4802 5.21799 19.908C5.40973 20.2843 5.71569 20.5903 6.09202 20.782C6.51984 21 7.0799 21 8.2 21H11.5M13 3L19 9M13 3V7.4C13 7.96005 13 8.24008 13.109 8.45399C13.2049 8.64215 13.3578 8.79513 13.546 8.89101C13.7599 9 14.0399 9 14.6 9H19M19 9V13.4M9 17H11.5M9 13H15M9 9H10" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 744 B |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1"
|
||||
width="1000"
|
||||
height="1000"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="230 260 500 550"
|
||||
style="background-color: #94DB77" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#94DB77;}
|
||||
.st1{fill:#4AAD20;}
|
||||
.st2{fill:#388616;}
|
||||
.st3{fill:#388716;}
|
||||
.st4{fill:#E9F3E4;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M191.12,540.08c0-91.78,0.03-183.55-0.1-275.33c0-3.5,0.49-4.75,5.66-4.75
|
||||
c187.59,0.13,375.17,0.13,562.76,0.02c4.6,0,5.54,0.74,5.54,4.34c-0.14,183.72-0.14,367.44,0.02,551.16c0,4-1.5,4.47-6.02,4.47
|
||||
c-187.38-0.09-374.75-0.1-562.13,0.01c-4.78,0-5.86-0.84-5.86-4.59C191.15,723.63,191.12,631.86,191.12,540.08z"/>
|
||||
<path class="st1" d="M392.26,705.96c-15.49,0-30.97,0.08-46.46-0.01c-27.64-0.16-48.2-20.68-48.58-48.38
|
||||
c-0.07-5.33-0.15-10.66,0.03-15.98c0.11-3.36-0.95-4.99-4.53-4.7c-2.48,0.2-4.99,0.09-7.49,0.01c-8.13-0.27-13.53-5.25-13.85-13.41
|
||||
c-0.32-8.31-0.32-16.66-0.01-24.97c0.32-8.47,5.67-13.29,14.21-13.51c11.63-0.29,11.61-0.29,11.64-12
|
||||
c0.01-5.65-0.08-11.29,0.76-16.94c3.28-22.14,22.75-39.61,45.11-40.03c11.98-0.23,23.98-0.18,35.96-0.02
|
||||
c3.68,0.05,4.97-1.15,4.91-4.87c-0.19-10.49-0.2-20.98,0.01-31.47c0.08-3.67-1.01-6.02-4.04-8.3c-7.69-5.8-10.15-15.12-6.86-23.66
|
||||
c3.12-8.12,12.07-13.98,20.39-13.36c9.18,0.68,16.98,6.99,19,15.86c2.02,8.81-0.75,16.21-7.99,21.57c-2.6,1.93-3.55,3.91-3.5,7.04
|
||||
c0.15,10.32,0.28,20.65-0.04,30.97c-0.14,4.7,1.1,6.44,6.07,6.28c10.81-0.35,21.64-0.17,32.47-0.09
|
||||
c27.05,0.22,47.25,20.24,47.77,47.31c0.1,4.99,0.02,9.99,0.04,14.99c0.02,6.71,0.03,6.71,6.51,6.73c2.16,0.01,4.33-0.06,6.49,0.04
|
||||
c7.67,0.37,12.72,5.36,12.87,13.06c0.17,8.49,0.16,16.99,0.01,25.48c-0.13,7.76-4.96,12.71-12.68,13.27
|
||||
c-2.32,0.17-4.7,0.35-6.98,0.02c-5.3-0.76-6.63,1.65-6.3,6.51c0.35,5.14,0.15,10.32,0.04,15.48
|
||||
c-0.56,26.78-20.78,46.86-47.52,47.08C423.9,706.06,408.08,705.95,392.26,705.96z"/>
|
||||
<path class="st1" d="M598.2,362.07c59.99,0.04,108.7,48.78,108.71,108.8c0.01,60.11-49.08,109.12-109.16,108.98
|
||||
C538.06,579.71,489,530.4,489.14,470.66C489.28,410.82,538.28,362.04,598.2,362.07z"/>
|
||||
<path class="st2" d="M394.26,632.93c10.49,0,20.97-0.03,31.46,0.01c6.21,0.02,7.8,1.8,7.19,7.77c-1.91,18.95-18.5,34.51-37.53,35.2
|
||||
c-18.51,0.67-35.81-13.26-39.38-31.72c-0.28-1.47-0.67-2.93-0.81-4.41c-0.48-4.88,1.13-6.77,6.11-6.81
|
||||
C372.29,632.87,383.28,632.93,394.26,632.93z"/>
|
||||
<path class="st3" d="M428.83,602c-9.71-0.04-17.23-7.4-17.3-16.93c-0.06-9.66,7.68-17.16,17.64-17.09
|
||||
c9.16,0.07,16.77,7.73,16.81,16.93C446.02,594.33,438.29,602.04,428.83,602z"/>
|
||||
<path class="st3" d="M339.05,584.57c0.14-9.63,7.62-16.73,17.48-16.58c9.73,0.15,16.68,7.47,16.54,17.43
|
||||
c-0.13,9.74-7.45,16.71-17.39,16.58C346.04,601.87,338.91,594.4,339.05,584.57z"/>
|
||||
<path class="st4" d="M598.39,405.96c35.8-0.01,64.91,29.38,64.43,65.03c-0.49,35.73-30.23,64.62-65.81,63.8
|
||||
c-8.91-0.21-17.55-2.04-25.56-6.01c-2.93-1.46-5.49-1.58-8.53-0.72c-8.48,2.4-17.03,4.53-25.54,6.84
|
||||
c-2.86,0.78-3.98,0.46-2.97-2.94c2.37-7.97,4.29-16.07,6.69-24.03c1.07-3.56,0.85-6.48-0.81-9.95
|
||||
C519.91,455.33,551.14,405.98,598.39,405.96z"/>
|
||||
<path class="st1" d="M548.99,520.52c1.54-5.81,2.66-10.77,4.2-15.6c0.89-2.79,0.54-4.93-0.91-7.47
|
||||
c-18.93-33.1,0.22-73.52,37.83-80.02c28.33-4.9,56.38,15.3,60.95,43.88c4.74,29.61-15.08,57.38-43.86,61.82
|
||||
c-12.32,1.9-23.85,0-34.68-6c-2.55-1.41-4.83-1.63-7.54-0.84C559.94,517.75,554.84,518.98,548.99,520.52z"/>
|
||||
<path class="st4" d="M615.43,501.21c-7.36-0.22-13.98-3.02-20.17-6.59c-11.52-6.64-20.22-16.22-26.57-27.83
|
||||
c-4.58-8.38-3.88-16.68,1.39-22.88c4.54-5.35,10.44-4.55,13.13,1.78c0.85,1.99,1.52,4.08,2.57,5.95c2.35,4.2,2.04,7.87-1.68,11.1
|
||||
c-2.2,1.92-1.79,3.85-0.29,6.12c4.63,6.96,10.62,12.24,18.05,16.08c3.6,1.86,6.4,1.78,8.35-1.92c2.73-5.2,6.35-5.45,10.9-2.5
|
||||
c1.38,0.9,2.97,1.49,4.46,2.22c6.33,3.1,7.13,9.14,1.71,13.92C623.96,499.62,620.04,501.38,615.43,501.21z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 73 KiB |
@@ -1 +1 @@
|
||||
{"openapi":"3.1.0","paths":{"/api/{session}/auth/qr":{"get":{"operationId":"AuthController_getQR","summary":"Get QR code for pairing WhatsApp Web.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"},{"name":"format","required":true,"in":"query","schema":{"default":"image","enum":["image","raw"],"type":"string"}}],"responses":{"200":{"content":{"image/png":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Base64File"},{"$ref":"#/components/schemas/QRCodeValue"}]}}},"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/request-code":{"post":{"operationId":"AuthController_requestCode","summary":"Request authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCodeRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/authorize-code":{"post":{"operationId":"AuthController_authorizeCode","summary":"Send OTP authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OTPRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/sessions/start":{"post":{"operationId":"SessionsController_start","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDTO"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/stop":{"post":{"operationId":"SessionsController_stop","summary":"Stop session","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStopRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/logout":{"post":{"operationId":"SessionsController_clean","summary":"Logout from session.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogoutRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions":{"get":{"operationId":"SessionsController_list","parameters":[{"name":"all","required":false,"in":"query","example":false,"description":"Return all sessions, including those that are in the STOPPED state.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionInfo"}}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/{session}/me":{"get":{"operationId":"SessionController_getMe","summary":"Get information about the authenticated account","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeInfo"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/checkNumberStatus":{"get":{"operationId":"ChattingController_checkNumberStatus","summary":"Check number status","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WANumberExistResult"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendContactVcard":{"post":{"operationId":"ChattingController_sendContactVcard","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageContactVcardRequest"}}}},"responses":{"201":{"description":""}},"tags":["chatting"],"security":[{"api_key":[]}]}},"/api/sendText":{"get":{"operationId":"ChattingController_sendTextGet","summary":"Send a text message","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"name":"text","required":true,"in":"query","schema":{"type":"string"}},{"name":"session","required":true,"in":"query","schema":{"default":"default","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["chatting"],"security":[{"api_key":[]}]},"post":{"operationId":"ChattingController_sendText","summary":"Send a text message","parameters":[],"requestBody":{"required":true,Line truncated
|
||||
{"openapi":"3.1.0","paths":{"/api/{session}/auth/qr":{"get":{"operationId":"AuthController_getQR","summary":"Get QR code for pairing WhatsApp Web.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"},{"name":"format","required":true,"in":"query","schema":{"default":"image","enum":["image","raw"],"type":"string"}}],"responses":{"200":{"content":{"image/png":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Base64File"},{"$ref":"#/components/schemas/QRCodeValue"}]}}},"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/request-code":{"post":{"operationId":"AuthController_requestCode","summary":"Request authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCodeRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/authorize-code":{"post":{"operationId":"AuthController_authorizeCode","summary":"Send OTP authentication code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OTPRequest"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/{session}/auth/captcha":{"get":{"operationId":"AuthController_getCaptcha","summary":"Get captcha image.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"responses":{"200":{"content":{"image/png":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Base64File"}]}}},"description":""}},"tags":["auth"],"security":[{"api_key":[]}]},"post":{"operationId":"AuthController_saveCaptcha","summary":"Enter captcha code.","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaBody"}}}},"responses":{"201":{"description":""}},"tags":["auth"],"security":[{"api_key":[]}]}},"/api/sessions/start":{"post":{"operationId":"SessionsController_start","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDTO"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/stop":{"post":{"operationId":"SessionsController_stop","summary":"Stop session","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStopRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/logout":{"post":{"operationId":"SessionsController_clean","summary":"Logout from session.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogoutRequest"}}}},"responses":{"201":{"description":""}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions":{"get":{"operationId":"SessionsController_list","parameters":[{"name":"all","required":false,"in":"query","example":false,"description":"Return all sessions, including those that are in the STOPPED state.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionInfo"}}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/{session}":{"get":{"operationId":"SessionsController_get","parameters":[{"name":"session","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionInfo"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/sessions/{session}/me":{"get":{"operationId":"SessionController_getMe","summary":"Get information about the authenticated account","parameters":[{"name":"session","required":true,"in":"path","schema":{"default":"default"},"description":"WhatsApp session name"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeInfo"}}}}},"tags":["sessions"],"security":[{"api_key":[]}]}},"/api/checkNumberStatus":{"get":{"operationId":"ChattingController_checkNumberStatus","summary":"Check number status","parameters":[{"name":"phone","required":true,"in":"query","schema":{"type":"string"}},{"nLine truncated
|
||||
@@ -2,6 +2,8 @@
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"plugins": ["@nestjs/swagger"]
|
||||
"plugins": ["@nestjs/swagger"],
|
||||
"assets": ["dashboard/**"],
|
||||
"watchAssets": true
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
"dependencies": {
|
||||
"@adiwajshing/baileys": "github:WhiskeySockets/Baileys",
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@nestjs/axios": "^3.0.2",
|
||||
"@nestjs/common": "^9.0.9",
|
||||
"@nestjs/config": "^0.5.0",
|
||||
"@nestjs/core": "^9.0.9",
|
||||
@@ -31,8 +32,10 @@
|
||||
"@nestjs/platform-express": "^9.0.9",
|
||||
"@nestjs/serve-static": "^2.1.3",
|
||||
"@nestjs/swagger": "^7.1.11",
|
||||
"@nestjs/terminus": "^10.2.3",
|
||||
"@types/lodash": "^4.14.194",
|
||||
"@types/ws": "^8.5.4",
|
||||
"check-disk-space": "^3.4.0",
|
||||
"class-validator": "^0.12.2",
|
||||
"del": "^6.0.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
@@ -42,8 +45,10 @@
|
||||
"link-preview-js": "^3.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.27",
|
||||
"mongodb": "^6.3.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-headerapikey": "^1.2.2",
|
||||
"puppeteer": "^21.0.0",
|
||||
"qrcode": "^1.5.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@@ -53,7 +58,7 @@
|
||||
"rxjs": "^7.1.0",
|
||||
"swagger-ui-express": "^4.1.4",
|
||||
"venom-bot": "5.0.1",
|
||||
"whatsapp-web.js": "https://github.com/pedroslopez/whatsapp-web.js"
|
||||
"whatsapp-web.js": "https://github.com/devlikeapro/whatsapp-web.js#main-fork-update"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.0.0",
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
import { Controller, Delete, Get, Param, Post, Query } from '@nestjs/common';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { parseBool } from '../helpers';
|
||||
import { GetChatMessagesQuery } from '../structures/chats.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
import { EditMessageRequest } from '../structures/chatting.dto';
|
||||
import {
|
||||
ChatIdApiParam,
|
||||
MessageIdApiParam,
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/chats')
|
||||
@@ -51,6 +66,33 @@ class ChatsController {
|
||||
) {
|
||||
return session.clearMessages(chatId);
|
||||
}
|
||||
|
||||
@Delete(':chatId/messages/:messageId')
|
||||
@SessionApiParam
|
||||
@ChatIdApiParam
|
||||
@MessageIdApiParam
|
||||
@ApiOperation({ summary: 'Deletes a message from the chat' })
|
||||
deleteMessage(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
@Param('messageId') messageId: string,
|
||||
) {
|
||||
return session.deleteMessage(chatId, messageId);
|
||||
}
|
||||
|
||||
@Put(':chatId/messages/:messageId')
|
||||
@SessionApiParam
|
||||
@ChatIdApiParam
|
||||
@MessageIdApiParam
|
||||
@ApiOperation({ summary: 'Edits a message in the chat' })
|
||||
editMessage(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
@Param('messageId') messageId: string,
|
||||
@Body() body: EditMessageRequest,
|
||||
) {
|
||||
return session.editMessage(chatId, messageId, body);
|
||||
}
|
||||
}
|
||||
|
||||
export { ChatsController };
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
MessagePollRequest,
|
||||
MessageReactionRequest,
|
||||
MessageReplyRequest,
|
||||
MessageStarRequest,
|
||||
MessageTextQuery,
|
||||
MessageTextRequest,
|
||||
MessageVideoRequest,
|
||||
@@ -157,6 +158,14 @@ export class ChattingController {
|
||||
return whatsapp.setReaction(request);
|
||||
}
|
||||
|
||||
@Put('/star')
|
||||
@ApiOperation({ summary: 'Star or unstar a message' })
|
||||
async setStar(@Body() request: MessageStarRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
await whatsapp.setStar(request);
|
||||
return;
|
||||
}
|
||||
|
||||
@Get('/messages')
|
||||
@ApiOperation({ summary: 'Get messages in a chat' })
|
||||
getMessages(@Query() query: GetMessageQuery) {
|
||||
|
||||
@@ -56,11 +56,12 @@ export class GroupsController {
|
||||
summary:
|
||||
'Updates the group settings to only allow admins to edit group info (title, description, photo).',
|
||||
})
|
||||
setGroupAdminOnly(
|
||||
setInfoAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@Body() request: SettingsSecurityChangeInfo,
|
||||
) {
|
||||
return session.setInfoAdminsOnly(id, true);
|
||||
return session.setInfoAdminsOnly(id, request.adminsOnly);
|
||||
}
|
||||
|
||||
@Get(':id/settings/security/info-admin-only')
|
||||
@@ -76,6 +77,32 @@ export class GroupsController {
|
||||
return session.getInfoAdminsOnly(id);
|
||||
}
|
||||
|
||||
@Put(':id/settings/security/messages-admin-only')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Updates the group settings to only allow admins to send messages.',
|
||||
})
|
||||
setMessagesAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@Body() request: SettingsSecurityChangeInfo,
|
||||
) {
|
||||
return session.setMessagesAdminsOnly(id, request.adminsOnly);
|
||||
}
|
||||
|
||||
@Get(':id/settings/security/messages-admin-only')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Gets the group settings to only allow admins to send messages.',
|
||||
})
|
||||
getMessagesAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<SettingsSecurityChangeInfo> {
|
||||
return session.getMessagesAdminsOnly(id);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Delete the group.' })
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { HealthCheck } from '@nestjs/terminus';
|
||||
|
||||
import { WAHAHealthCheckService } from '../core/abc/WAHAHealthCheckService';
|
||||
|
||||
@Controller('health')
|
||||
@ApiTags('other')
|
||||
export class HealthController {
|
||||
constructor(private wahaHealth: WAHAHealthCheckService) {}
|
||||
|
||||
@Get()
|
||||
@HealthCheck()
|
||||
async check() {
|
||||
return this.wahaHealth.check();
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,22 @@ export const SessionApiParam = ApiParam({
|
||||
*/
|
||||
export const SessionParam = Param('session', SessionPipe);
|
||||
|
||||
export const ChatIdApiParam = ApiParam({
|
||||
name: 'chatId',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Chat ID',
|
||||
example: '123456789@c.us',
|
||||
});
|
||||
|
||||
export const MessageIdApiParam = ApiParam({
|
||||
name: 'messageId',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Message ID',
|
||||
example: 'true_123456789@c.us_BAE6A33293978B16',
|
||||
});
|
||||
|
||||
function getRefSchemaPaths(models) {
|
||||
return models.map((model) => {
|
||||
return { $ref: getSchemaPath(model) };
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
NotFoundException,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiExtraModels,
|
||||
ApiOperation,
|
||||
@@ -29,7 +38,7 @@ class SessionsController {
|
||||
@Post('/start/')
|
||||
async start(@Body() request: SessionStartRequest): Promise<SessionDTO> {
|
||||
const result = await this.manager.start(request);
|
||||
await this.manager.sessionStorage.configRepository.save(
|
||||
await this.manager.sessionConfigRepository.save(
|
||||
request.name,
|
||||
request.config || null,
|
||||
);
|
||||
@@ -39,9 +48,10 @@ class SessionsController {
|
||||
@Post('/stop/')
|
||||
@ApiOperation({ summary: 'Stop session' })
|
||||
async stop(@Body() request: SessionStopRequest): Promise<void> {
|
||||
await this.manager.stop(request);
|
||||
if (request.logout) {
|
||||
await this.manager.logout(request);
|
||||
} else {
|
||||
await this.manager.stop(request);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -57,6 +67,15 @@ class SessionsController {
|
||||
const all = parseBool(query.all);
|
||||
return this.manager.getSessions(all);
|
||||
}
|
||||
|
||||
@Get('/:session')
|
||||
async get(@Param('session') name: string): Promise<SessionInfo> {
|
||||
const session = this.manager.getSessionInfo(name);
|
||||
if (session === null) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
|
||||
@@ -8,13 +8,24 @@ import { getEngineName } from './version';
|
||||
|
||||
@Injectable()
|
||||
export class WhatsappConfigService {
|
||||
public files_uri = '/api/files';
|
||||
public filesUri = '/api/files';
|
||||
public dashboardUri = '/dashboard';
|
||||
public schema = 'http';
|
||||
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
static noSlash(value: string): string {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (value.startsWith('/')) {
|
||||
return value.slice(1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
get filesURL(): string {
|
||||
return `${this.schema}://${this.hostname}:${this.port}${this.files_uri}/`;
|
||||
return `${this.schema}://${this.hostname}:${this.port}${this.filesUri}/`;
|
||||
}
|
||||
|
||||
get hostname(): string {
|
||||
@@ -108,6 +119,10 @@ export class WhatsappConfigService {
|
||||
return value ? value.split(',') : [];
|
||||
}
|
||||
|
||||
getSessionMongoUrl(): string | undefined {
|
||||
return this.configService.get('WHATSAPP_SESSIONS_MONGO_URL', undefined);
|
||||
}
|
||||
|
||||
getDefaultEngineName(): WAHAEngine {
|
||||
const value = getEngineName();
|
||||
if (value in WAHAEngine) {
|
||||
@@ -148,7 +163,49 @@ export class WhatsappConfigService {
|
||||
return [user, password];
|
||||
}
|
||||
|
||||
getDashboardEnabled(): boolean {
|
||||
const value = this.configService.get('WAHA_DASHBOARD_ENABLED', 'true');
|
||||
return parseBool(value);
|
||||
}
|
||||
|
||||
getDashboardUsernamePassword(): [string, string] | null {
|
||||
if (!this.getDashboardEnabled()) {
|
||||
return null;
|
||||
}
|
||||
const user = this.configService.get('WAHA_DASHBOARD_USERNAME', 'waha');
|
||||
const password = this.configService.get('WAHA_DASHBOARD_PASSWORD', 'waha');
|
||||
if (!user || !password) {
|
||||
console.log(
|
||||
'Please set up both WAHA_DASHBOARD_USERNAME and WAHA_DASHBOARD_PASSWORD ' +
|
||||
'to enable swagger authentication.',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
return [user, password];
|
||||
}
|
||||
|
||||
getSwaggerAdvancedConfigEnabled(): boolean {
|
||||
return this.configService.get('WHATSAPP_SWAGGER_CONFIG_ADVANCED', false);
|
||||
}
|
||||
|
||||
getHealthMediaFilesThreshold(): number {
|
||||
return this.configService.get<number>(
|
||||
'WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB',
|
||||
100,
|
||||
);
|
||||
}
|
||||
|
||||
getHealthSessionFilesThreshold(): number {
|
||||
return this.configService.get<number>(
|
||||
'WHATSAPP_HEALTH_SESSION_FILES_THRESHOLD_MB',
|
||||
100,
|
||||
);
|
||||
}
|
||||
|
||||
getHealthMongoTimeout(): number {
|
||||
return this.configService.get<number>(
|
||||
'WHATSAPP_HEALTH_MONGO_TIMEOUT_MS',
|
||||
3000,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export abstract class DataStore {}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { ConsoleLogger, Injectable } from '@nestjs/common';
|
||||
import { DiskHealthIndicator, HealthCheckService } from '@nestjs/terminus';
|
||||
import type { HealthCheckResult } from '@nestjs/terminus/dist/health-check/health-check-result.interface';
|
||||
|
||||
import { WhatsappConfigService } from '../../config.service';
|
||||
import { SessionManager } from './manager.abc';
|
||||
|
||||
@Injectable()
|
||||
export abstract class WAHAHealthCheckService {
|
||||
constructor(
|
||||
protected sessionManager: SessionManager,
|
||||
protected health: HealthCheckService,
|
||||
protected log: ConsoleLogger,
|
||||
protected config: WhatsappConfigService,
|
||||
) {}
|
||||
|
||||
abstract check(): Promise<HealthCheckResult>;
|
||||
}
|
||||
@@ -8,12 +8,15 @@ import {
|
||||
SessionStartRequest,
|
||||
SessionStopRequest,
|
||||
} from '../../structures/sessions.dto';
|
||||
import { ISessionAuthRepository } from '../storage/ISessionAuthRepository';
|
||||
import { ISessionConfigRepository } from '../storage/ISessionConfigRepository';
|
||||
import { WhatsappSession } from './session.abc';
|
||||
import { LocalSessionStorage } from './storage.abc';
|
||||
import { WebhookConductor } from './webhooks.abc';
|
||||
|
||||
export abstract class SessionManager implements OnApplicationShutdown {
|
||||
public sessionStorage: LocalSessionStorage;
|
||||
public store: any;
|
||||
public sessionAuthRepository: ISessionAuthRepository;
|
||||
public sessionConfigRepository: ISessionConfigRepository;
|
||||
|
||||
protected abstract getEngine(engine: WAHAEngine): typeof WhatsappSession;
|
||||
|
||||
@@ -34,5 +37,7 @@ export abstract class SessionManager implements OnApplicationShutdown {
|
||||
|
||||
abstract getSession(name: string): WhatsappSession;
|
||||
|
||||
abstract getSessionInfo(name: string): Promise<SessionInfo | null>;
|
||||
|
||||
abstract getSessions(all: boolean): Promise<SessionInfo[]>;
|
||||
}
|
||||
@@ -3,10 +3,10 @@ import { EventEmitter } from 'events';
|
||||
import * as fs from 'fs';
|
||||
import { MessageId } from 'whatsapp-web.js';
|
||||
|
||||
import { OTPRequest, RequestCodeRequest } from '../../structures/auth.dto';
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
EditMessageRequest,
|
||||
GetMessageQuery,
|
||||
MessageContactVcardRequest,
|
||||
MessageFileRequest,
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
MessagePollRequest,
|
||||
MessageReactionRequest,
|
||||
MessageReplyRequest,
|
||||
MessageStarRequest,
|
||||
MessageTextRequest,
|
||||
MessageVideoRequest,
|
||||
MessageVoiceRequest,
|
||||
@@ -47,8 +48,8 @@ import {
|
||||
import { WASessionStatusBody } from '../../structures/webhooks.dto';
|
||||
import { NotImplementedByEngineError } from '../exceptions';
|
||||
import { QR } from '../QR';
|
||||
import { DataStore } from './DataStore';
|
||||
import { MediaManager } from './media.abc';
|
||||
import { LocalSessionStorage } from './storage.abc';
|
||||
|
||||
const CHROME_PATH = '/usr/bin/google-chrome-stable';
|
||||
const CHROMIUM_PATH = '/usr/bin/chromium';
|
||||
@@ -77,7 +78,7 @@ export interface SessionParams {
|
||||
name: string;
|
||||
mediaManager: MediaManager;
|
||||
log: ConsoleLogger;
|
||||
sessionStorage: LocalSessionStorage;
|
||||
sessionStore: DataStore;
|
||||
proxyConfig?: ProxyConfig;
|
||||
sessionConfig?: SessionConfig;
|
||||
}
|
||||
@@ -89,7 +90,7 @@ export abstract class WhatsappSession {
|
||||
public name: string;
|
||||
protected mediaManager: MediaManager;
|
||||
protected log: ConsoleLogger;
|
||||
protected sessionStorage: LocalSessionStorage;
|
||||
protected sessionStore: DataStore;
|
||||
protected proxyConfig?: ProxyConfig;
|
||||
public sessionConfig?: SessionConfig;
|
||||
|
||||
@@ -98,7 +99,7 @@ export abstract class WhatsappSession {
|
||||
public constructor({
|
||||
name,
|
||||
log,
|
||||
sessionStorage,
|
||||
sessionStore,
|
||||
proxyConfig,
|
||||
mediaManager,
|
||||
sessionConfig,
|
||||
@@ -107,7 +108,7 @@ export abstract class WhatsappSession {
|
||||
this.name = name;
|
||||
this.proxyConfig = proxyConfig;
|
||||
this.log = log;
|
||||
this.sessionStorage = sessionStorage;
|
||||
this.sessionStore = sessionStore;
|
||||
this.mediaManager = mediaManager;
|
||||
this.sessionConfig = sessionConfig;
|
||||
}
|
||||
@@ -266,6 +267,10 @@ export abstract class WhatsappSession {
|
||||
|
||||
abstract setReaction(request: MessageReactionRequest);
|
||||
|
||||
setStar(request: MessageStarRequest): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
@@ -285,6 +290,18 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public deleteMessage(chatId: string, messageId: string) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public editMessage(
|
||||
chatId: string,
|
||||
messageId: string,
|
||||
request: EditMessageRequest,
|
||||
) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public clearMessages(chatId) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
@@ -339,6 +356,14 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public getMessagesAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public setMessagesAdminsOnly(id, value) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public deleteGroup(id) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
@@ -418,6 +443,10 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async getEngineInfo(): Promise<any> {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* END - Methods for API
|
||||
*/
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { SessionConfig } from '../../structures/sessions.dto';
|
||||
|
||||
abstract class SessionConfigRepository {
|
||||
abstract save(
|
||||
sessionName: string,
|
||||
config: SessionConfig | null,
|
||||
): Promise<void>;
|
||||
|
||||
abstract get(sessionName: string): Promise<SessionConfig | null>;
|
||||
}
|
||||
|
||||
abstract class SessionStorage {
|
||||
protected constructor(public engine: string) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
abstract init(sessionName?: string): Promise<void>;
|
||||
|
||||
abstract clean(sessionName: string): Promise<void>;
|
||||
|
||||
abstract getAll(): Promise<string[]>;
|
||||
|
||||
//
|
||||
// Repositories
|
||||
//
|
||||
abstract get configRepository(): SessionConfigRepository;
|
||||
}
|
||||
|
||||
abstract class LocalSessionStorage extends SessionStorage {
|
||||
public sessionsFolder: string;
|
||||
|
||||
abstract getFolderPath(sessionName: string): string;
|
||||
}
|
||||
|
||||
export { LocalSessionStorage, SessionConfigRepository };
|
||||
@@ -2,12 +2,15 @@ import { ConsoleLogger, Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { join } from 'path';
|
||||
|
||||
import { AuthController } from '../api/auth.controller';
|
||||
import { ChatsController } from '../api/chats.controller';
|
||||
import { ChattingController } from '../api/chatting.controller';
|
||||
import { ContactsController } from '../api/contacts.controller';
|
||||
import { GroupsController } from '../api/groups.controller';
|
||||
import { HealthController } from '../api/health.controller';
|
||||
import { PresenceController } from '../api/presence.controller';
|
||||
import { ScreenshotController } from '../api/screenshot.controller';
|
||||
import {
|
||||
@@ -18,6 +21,8 @@ import { StatusController } from '../api/status.controller';
|
||||
import { VersionController } from '../api/version.controller';
|
||||
import { WhatsappConfigService } from '../config.service';
|
||||
import { SessionManager } from './abc/manager.abc';
|
||||
import { WAHAHealthCheckService } from './abc/WAHAHealthCheckService';
|
||||
import { WAHAHealthCheckServiceCore } from './health/WAHAHealthCheckServiceCore';
|
||||
import { SessionManagerCore } from './manager.core';
|
||||
|
||||
export const IMPORTS = [
|
||||
@@ -29,15 +34,24 @@ export const IMPORTS = [
|
||||
extraProviders: [WhatsappConfigService],
|
||||
inject: [WhatsappConfigService],
|
||||
useFactory: (config: WhatsappConfigService) => {
|
||||
return [
|
||||
const options = [
|
||||
// Serve files (media)
|
||||
{
|
||||
rootPath: config.filesFolder,
|
||||
serveRoot: config.files_uri,
|
||||
serveRoot: config.filesUri,
|
||||
},
|
||||
];
|
||||
if (config.getDashboardEnabled()) {
|
||||
options.push({
|
||||
rootPath: join(__dirname, '..', 'dashboard'),
|
||||
serveRoot: config.dashboardUri,
|
||||
});
|
||||
}
|
||||
return options;
|
||||
},
|
||||
}),
|
||||
PassportModule,
|
||||
TerminusModule,
|
||||
];
|
||||
export const CONTROLLERS = [
|
||||
AuthController,
|
||||
@@ -51,12 +65,17 @@ export const CONTROLLERS = [
|
||||
PresenceController,
|
||||
ScreenshotController,
|
||||
VersionController,
|
||||
HealthController,
|
||||
];
|
||||
const PROVIDERS = [
|
||||
{
|
||||
provide: SessionManager,
|
||||
useClass: SessionManagerCore,
|
||||
},
|
||||
{
|
||||
provide: WAHAHealthCheckService,
|
||||
useClass: WAHAHealthCheckServiceCore,
|
||||
},
|
||||
WhatsappConfigService,
|
||||
ConsoleLogger,
|
||||
];
|
||||
@@ -66,4 +85,6 @@ const PROVIDERS = [
|
||||
controllers: CONTROLLERS,
|
||||
providers: PROVIDERS,
|
||||
})
|
||||
export class AppModuleCore {}
|
||||
export class AppModuleCore {
|
||||
constructor(protected config: WhatsappConfigService) {}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { useMultiFileAuthState } from '@adiwajshing/baileys';
|
||||
import { Store } from 'whatsapp-web.js';
|
||||
|
||||
import { DataStore } from '../../abc/DataStore';
|
||||
import { LocalStore } from '../../storage/LocalStore';
|
||||
|
||||
export class NowebAuthFactoryCore {
|
||||
buildAuth(store: DataStore, name: string) {
|
||||
if (store instanceof LocalStore) return this.buildLocalAuth(store, name);
|
||||
throw new Error(`Unsupported store type '${store.constructor.name}'`);
|
||||
}
|
||||
|
||||
protected async buildLocalAuth(store: LocalStore, name: string) {
|
||||
await store.init(name);
|
||||
const authFolder = store.getSessionDirectory(name);
|
||||
const { state, saveCreds } = await useMultiFileAuthState(authFolder);
|
||||
return { state, saveCreds };
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import makeWASocket, {
|
||||
getKeyAuthor,
|
||||
isJidGroup,
|
||||
jidNormalizedUser,
|
||||
makeCacheableSignalKeyStore,
|
||||
makeInMemoryStore,
|
||||
PresenceData,
|
||||
proto,
|
||||
@@ -14,15 +15,18 @@ import makeWASocket, {
|
||||
} from '@adiwajshing/baileys';
|
||||
import { UnprocessableEntityException } from '@nestjs/common';
|
||||
import * as Buffer from 'buffer';
|
||||
import { request } from 'express';
|
||||
import * as fs from 'fs/promises';
|
||||
import { Agent } from 'https';
|
||||
import * as lodash from 'lodash';
|
||||
import { PairingCodeResponse } from 'src/structures/auth.dto';
|
||||
|
||||
import { flipObject, splitAt } from '../helpers';
|
||||
import { flipObject, splitAt } from '../../../helpers';
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
EditMessageRequest,
|
||||
MessageContactVcardRequest,
|
||||
MessageDestination,
|
||||
MessageFileRequest,
|
||||
MessageImageRequest,
|
||||
@@ -31,12 +35,13 @@ import {
|
||||
MessagePollRequest,
|
||||
MessageReactionRequest,
|
||||
MessageReplyRequest,
|
||||
MessageStarRequest,
|
||||
MessageTextRequest,
|
||||
MessageVoiceRequest,
|
||||
SendSeenRequest,
|
||||
WANumberExistResult,
|
||||
} from '../structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
|
||||
} from '../../../structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
|
||||
import {
|
||||
ACK_UNKNOWN,
|
||||
SECOND,
|
||||
@@ -45,35 +50,40 @@ import {
|
||||
WAHAPresenceStatus,
|
||||
WAHASessionStatus,
|
||||
WAMessageAck,
|
||||
} from '../structures/enums.dto';
|
||||
} from '../../../structures/enums.dto';
|
||||
import {
|
||||
CreateGroupRequest,
|
||||
ParticipantsRequest,
|
||||
} from '../structures/groups.dto';
|
||||
} from '../../../structures/groups.dto';
|
||||
import {
|
||||
WAHAChatPresences,
|
||||
WAHAPresenceData,
|
||||
} from '../structures/presence.dto';
|
||||
import { WAMessage } from '../structures/responses.dto';
|
||||
import { MeInfo } from '../structures/sessions.dto';
|
||||
import { BROADCAST_ID, TextStatus } from '../structures/status.dto';
|
||||
} from '../../../structures/presence.dto';
|
||||
import {
|
||||
WAMessage,
|
||||
WAMessageReaction,
|
||||
} from '../../../structures/responses.dto';
|
||||
import { MeInfo } from '../../../structures/sessions.dto';
|
||||
import { BROADCAST_ID, TextStatus } from '../../../structures/status.dto';
|
||||
import {
|
||||
PollVote,
|
||||
PollVotePayload,
|
||||
WAMessageAckBody,
|
||||
} from '../structures/webhooks.dto';
|
||||
import { IEngineMediaProcessor } from './abc/media.abc';
|
||||
} from '../../../structures/webhooks.dto';
|
||||
import { IEngineMediaProcessor } from '../../abc/media.abc';
|
||||
import {
|
||||
ensureSuffix,
|
||||
WAHAInternalEvent,
|
||||
WhatsappSession,
|
||||
} from './abc/session.abc';
|
||||
} from '../../abc/session.abc';
|
||||
import {
|
||||
AvailableInPlusVersion,
|
||||
NotImplementedByEngineError,
|
||||
} from './exceptions';
|
||||
import { createAgentProxy } from './helpers.proxy';
|
||||
import { QR } from './QR';
|
||||
} from '../../exceptions';
|
||||
import { toVcard } from '../../helpers';
|
||||
import { createAgentProxy } from '../../helpers.proxy';
|
||||
import { QR } from '../../QR';
|
||||
import { NowebAuthFactoryCore } from './NowebAuthFactoryCore';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const QRCode = require('qrcode');
|
||||
@@ -101,6 +111,9 @@ const ToEnginePresenceStatus = flipObject(PresenceStatuses);
|
||||
|
||||
export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
engine = WAHAEngine.NOWEB;
|
||||
authFactory = new NowebAuthFactoryCore();
|
||||
private restartTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
|
||||
get listenConnectionEventsFromTheStart() {
|
||||
return true;
|
||||
}
|
||||
@@ -123,9 +136,13 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return {
|
||||
agent: agent,
|
||||
fetchAgent: agent,
|
||||
auth: state,
|
||||
auth: {
|
||||
creds: state.creds,
|
||||
/** caching makes the store faster to send/recv messages */
|
||||
keys: makeCacheableSignalKeyStore(state.keys, logger),
|
||||
},
|
||||
printQRInTerminal: true,
|
||||
browser: Browsers.macOS('Chrome'),
|
||||
browser: Browsers.ubuntu('Chrome'),
|
||||
logger: logger,
|
||||
mobile: false,
|
||||
defaultQueryTimeoutMs: undefined,
|
||||
@@ -134,9 +151,10 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
async makeSocket() {
|
||||
const authFolder = this.sessionStorage.getFolderPath(this.name);
|
||||
await fs.mkdir(authFolder, { recursive: true });
|
||||
const { state, saveCreds } = await useMultiFileAuthState(authFolder);
|
||||
const { state, saveCreds } = await this.authFactory.buildAuth(
|
||||
this.sessionStore,
|
||||
this.name,
|
||||
);
|
||||
const agent = this.makeAgent();
|
||||
const socketConfig = this.getSocketConfig(agent, state);
|
||||
const sock: any = makeWASocket(socketConfig);
|
||||
@@ -191,15 +209,31 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
|
||||
protected listenEngineEventsInDebugMode() {
|
||||
this.sock.ev.process((events) => {
|
||||
this.log.debug(`Received NOWEB events`, events);
|
||||
this.log.debug(`NOWEB events: ${JSON.stringify(events)}`);
|
||||
});
|
||||
}
|
||||
|
||||
private restartClient() {
|
||||
if (this.restartTimeoutId) {
|
||||
this.log.log(
|
||||
'Request to restart is already in progress, ignoring this request',
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.log.log('Setting up client restart in 2 seconds...');
|
||||
this.restartTimeoutId = setTimeout(() => {
|
||||
this.restartTimeoutId = undefined;
|
||||
this.buildClient();
|
||||
}, 2 * SECOND);
|
||||
}
|
||||
|
||||
protected listenConnectionEvents() {
|
||||
this.log.debug(`Start listening ${BaileysEvents.CONNECTION_UPDATE}...`);
|
||||
this.sock.ev.on(BaileysEvents.CONNECTION_UPDATE, async (update) => {
|
||||
const { connection, lastDisconnect, qr } = update;
|
||||
if (connection === 'open') {
|
||||
const { connection, lastDisconnect, qr, isNewLogin } = update;
|
||||
if (isNewLogin) {
|
||||
this.restartClient();
|
||||
} else if (connection === 'open') {
|
||||
this.qr.save('');
|
||||
this.status = WAHASessionStatus.WORKING;
|
||||
this.resubscribeToKnownPresences();
|
||||
@@ -217,7 +251,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.qr.save('');
|
||||
// reconnect if not logged out
|
||||
if (shouldReconnect) {
|
||||
setTimeout(() => this.buildClient(), 2 * SECOND);
|
||||
this.restartClient();
|
||||
} else {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
}
|
||||
@@ -234,9 +268,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
async stop() {
|
||||
this.sock.ev.removeAllListeners();
|
||||
this.sock.ws.removeAllListeners();
|
||||
this.sock.ws.close();
|
||||
this.sock?.ev?.removeAllListeners();
|
||||
this.sock?.ws?.removeAllListeners();
|
||||
this.sock?.ws?.close();
|
||||
this.status = WAHASessionStatus.STOPPED;
|
||||
return;
|
||||
}
|
||||
@@ -336,6 +370,37 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return this.sock.sendMessage(chatId, message);
|
||||
}
|
||||
|
||||
public deleteMessage(chatId: string, messageId: string) {
|
||||
const jid = toJID(this.ensureSuffix(chatId));
|
||||
const key = parseMessageId(messageId);
|
||||
return this.sock.sendMessage(jid, { delete: key });
|
||||
}
|
||||
|
||||
public editMessage(
|
||||
chatId: string,
|
||||
messageId: string,
|
||||
request: EditMessageRequest,
|
||||
) {
|
||||
const jid = toJID(this.ensureSuffix(chatId));
|
||||
const key = parseMessageId(messageId);
|
||||
const message = {
|
||||
text: request.text,
|
||||
mentions: request.mentions?.map(toJID),
|
||||
edit: key,
|
||||
};
|
||||
return this.sock.sendMessage(jid, message);
|
||||
}
|
||||
|
||||
async sendContactVCard(request: MessageContactVcardRequest) {
|
||||
const chatId = this.ensureSuffix(request.chatId);
|
||||
const contacts = request.contacts.map((el) => ({ vcard: toVcard(el) }));
|
||||
await this.sock.sendMessage(chatId, {
|
||||
contacts: {
|
||||
contacts: contacts,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async sendPoll(request: MessagePollRequest) {
|
||||
const requestPoll = request.poll;
|
||||
const poll = {
|
||||
@@ -422,6 +487,19 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return this.sock.sendMessage(key.remoteJid, reactionMessage);
|
||||
}
|
||||
|
||||
async setStar(request: MessageStarRequest) {
|
||||
const key = parseMessageId(request.messageId);
|
||||
await this.sock.chatModify(
|
||||
{
|
||||
star: {
|
||||
messages: [{ id: key.id, fromMe: key.fromMe }],
|
||||
star: request.star,
|
||||
},
|
||||
},
|
||||
toJID(request.chatId),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contacts methods
|
||||
*/
|
||||
@@ -438,7 +516,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
public async getContactProfilePicture(query: ContactQuery) {
|
||||
throw new NotImplementedByEngineError();
|
||||
const contact = this.ensureSuffix(query.contactId);
|
||||
const url = await this.sock.profilePictureUrl(contact, 'image');
|
||||
return { profilePictureURL: url };
|
||||
}
|
||||
|
||||
public async blockContact(request: ContactRequest) {
|
||||
@@ -576,6 +656,12 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.handleIncomingMessages(messages, handler, false);
|
||||
});
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_REACTION:
|
||||
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) => {
|
||||
const reactions = this.processMessageReaction(messages);
|
||||
reactions.map(handler);
|
||||
});
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_ANY:
|
||||
this.sock.ev.on(BaileysEvents.MESSAGES_UPSERT, ({ messages }) =>
|
||||
this.handleIncomingMessages(messages, handler, true),
|
||||
@@ -632,6 +718,8 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
// if there is no text or media message
|
||||
if (!message) return;
|
||||
if (!message.message) return;
|
||||
// Ignore reactions, we have dedicated handler for that
|
||||
if (message.message.reactionMessage) return;
|
||||
// Ignore poll votes, we have dedicated handler for that
|
||||
if (message.message.pollUpdateMessage) return;
|
||||
// Do not include my messages
|
||||
@@ -642,6 +730,34 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
}
|
||||
|
||||
private processMessageReaction(messages: any[]): WAMessageReaction[] {
|
||||
const reactions = [];
|
||||
for (const message of messages) {
|
||||
if (!message) return [];
|
||||
if (!message.message) return [];
|
||||
if (!message.message.reactionMessage) return [];
|
||||
|
||||
const id = buildMessageId(message.key);
|
||||
const fromToParticipant = getFromToParticipant(message);
|
||||
const reactionMessage = message.message.reactionMessage;
|
||||
const messageId = buildMessageId(reactionMessage.key);
|
||||
const reaction: WAMessageReaction = {
|
||||
id: id,
|
||||
timestamp: message.messageTimestamp,
|
||||
from: toCusFormat(fromToParticipant.from),
|
||||
fromMe: message.key.fromMe,
|
||||
to: toCusFormat(fromToParticipant.to),
|
||||
participant: toCusFormat(fromToParticipant.participant),
|
||||
reaction: {
|
||||
text: reactionMessage.text,
|
||||
messageId: messageId,
|
||||
},
|
||||
};
|
||||
reactions.push(reaction);
|
||||
}
|
||||
return reactions;
|
||||
}
|
||||
|
||||
private processIncomingMessage(message) {
|
||||
return this.downloadMedia(message)
|
||||
.then(this.toWAMessage)
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
GetMessageQuery,
|
||||
MessageContactVcardRequest,
|
||||
MessageFileRequest,
|
||||
MessageImageRequest,
|
||||
MessageLinkPreviewRequest,
|
||||
@@ -15,17 +14,17 @@ import {
|
||||
MessageReplyRequest,
|
||||
MessageTextRequest,
|
||||
WANumberExistResult,
|
||||
} from '../structures/chatting.dto';
|
||||
} from '../../../structures/chatting.dto';
|
||||
import {
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHASessionStatus,
|
||||
} from '../structures/enums.dto';
|
||||
import { WAMessage } from '../structures/responses.dto';
|
||||
import { IEngineMediaProcessor } from './abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from './abc/session.abc';
|
||||
import { NotImplementedByEngineError } from './exceptions';
|
||||
import { QR } from './QR';
|
||||
} from '../../../structures/enums.dto';
|
||||
import { WAMessage } from '../../../structures/responses.dto';
|
||||
import { IEngineMediaProcessor } from '../../abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
|
||||
import { NotImplementedByEngineError } from '../../exceptions';
|
||||
import { QR } from '../../QR';
|
||||
|
||||
export class WhatsappSessionVenomCore extends WhatsappSession {
|
||||
engine = WAHAEngine.VENOM;
|
||||
@@ -164,14 +163,6 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
|
||||
}
|
||||
}
|
||||
|
||||
sendContactVCard(request: MessageContactVcardRequest) {
|
||||
return this.whatsapp.sendContactVcard(
|
||||
request.chatId,
|
||||
request.contactsId,
|
||||
request.name,
|
||||
);
|
||||
}
|
||||
|
||||
sendText(request: MessageTextRequest) {
|
||||
return this.whatsapp.sendText(
|
||||
this.ensureSuffix(request.chatId),
|
||||
@@ -8,24 +8,27 @@ import {
|
||||
GroupChat,
|
||||
Location,
|
||||
Message,
|
||||
Reaction,
|
||||
} from 'whatsapp-web.js';
|
||||
import { Message as MessageInstance } from 'whatsapp-web.js/src/structures';
|
||||
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
EditMessageRequest,
|
||||
GetMessageQuery,
|
||||
MessageFileRequest,
|
||||
MessageImageRequest,
|
||||
MessageLocationRequest,
|
||||
MessageReactionRequest,
|
||||
MessageReplyRequest,
|
||||
MessageStarRequest,
|
||||
MessageTextRequest,
|
||||
MessageVoiceRequest,
|
||||
SendSeenRequest,
|
||||
WANumberExistResult,
|
||||
} from '../structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
|
||||
} from '../../../structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
|
||||
import {
|
||||
ACK_UNKNOWN,
|
||||
WAHAEngine,
|
||||
@@ -33,22 +36,25 @@ import {
|
||||
WAHAPresenceStatus,
|
||||
WAHASessionStatus,
|
||||
WAMessageAck,
|
||||
} from '../structures/enums.dto';
|
||||
} from '../../../structures/enums.dto';
|
||||
import {
|
||||
CreateGroupRequest,
|
||||
ParticipantsRequest,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '../structures/groups.dto';
|
||||
import { WAMessage } from '../structures/responses.dto';
|
||||
import { MeInfo } from '../structures/sessions.dto';
|
||||
import { WAMessageRevokedBody } from '../structures/webhooks.dto';
|
||||
import { IEngineMediaProcessor } from './abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from './abc/session.abc';
|
||||
} from '../../../structures/groups.dto';
|
||||
import {
|
||||
WAMessage,
|
||||
WAMessageReaction,
|
||||
} from '../../../structures/responses.dto';
|
||||
import { MeInfo } from '../../../structures/sessions.dto';
|
||||
import { WAMessageRevokedBody } from '../../../structures/webhooks.dto';
|
||||
import { IEngineMediaProcessor } from '../../abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
|
||||
import {
|
||||
AvailableInPlusVersion,
|
||||
NotImplementedByEngineError,
|
||||
} from './exceptions';
|
||||
import { QR } from './QR';
|
||||
} from '../../exceptions';
|
||||
import { QR } from '../../QR';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const QRCode = require('qrcode');
|
||||
@@ -67,14 +73,24 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
this.qr = new QR();
|
||||
}
|
||||
|
||||
protected buildClient() {
|
||||
const clientOptions: ClientOptions = {
|
||||
protected getClientOptions(): ClientOptions {
|
||||
return {
|
||||
puppeteer: {
|
||||
headless: true,
|
||||
executablePath: this.getBrowserExecutablePath(),
|
||||
args: this.getBrowserArgsForPuppeteer(),
|
||||
},
|
||||
webVersion: '2.2412.54',
|
||||
webVersionCache: {
|
||||
type: 'remote',
|
||||
remotePath:
|
||||
'https://raw.githubusercontent.com/wppconnect-team/wa-version/main/html/{version}.html',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected async buildClient() {
|
||||
const clientOptions = this.getClientOptions();
|
||||
this.addProxyConfig(clientOptions);
|
||||
return new Client(clientOptions);
|
||||
}
|
||||
@@ -98,12 +114,35 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
|
||||
async start() {
|
||||
this.status = WAHASessionStatus.STARTING;
|
||||
this.whatsapp = this.buildClient();
|
||||
this.whatsapp.initialize().catch((error) => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error(error);
|
||||
return;
|
||||
});
|
||||
this.whatsapp = await this.buildClient();
|
||||
this.whatsapp
|
||||
.initialize()
|
||||
.then(() => {
|
||||
// Listen for browser disconnected event
|
||||
this.whatsapp.pupBrowser.on('disconnected', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The browser has been disconnected');
|
||||
});
|
||||
// Listen for page close event
|
||||
this.whatsapp.pupPage.on('close', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The WhatsApp Web page has been closed');
|
||||
});
|
||||
if (this.isDebugEnabled()) {
|
||||
this.log.debug("Logging 'console' event for web page");
|
||||
this.whatsapp.pupPage.on('console', (msg) =>
|
||||
this.log.debug(`WEBJS page log: ${msg.text()}`),
|
||||
);
|
||||
this.whatsapp.pupPage.evaluate(() =>
|
||||
console.log(`url is ${location.href}`),
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error(error);
|
||||
return;
|
||||
});
|
||||
if (this.isDebugEnabled()) {
|
||||
this.listenEngineEventsInDebugMode();
|
||||
}
|
||||
@@ -136,7 +175,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
for (const key in Events) {
|
||||
const event = Events[key];
|
||||
this.whatsapp.on(event, (...data: any[]) => {
|
||||
this.log.debug(`Received WEBJS event`, { event: event, data: data });
|
||||
const log = { event: event, data: data };
|
||||
this.log.debug(`WEBJS event: ${JSON.stringify(log)}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -217,6 +257,24 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
);
|
||||
}
|
||||
|
||||
public deleteMessage(chatId: string, messageId: string) {
|
||||
const message = this.recreateMessage(messageId);
|
||||
return message.delete(true);
|
||||
}
|
||||
|
||||
public editMessage(
|
||||
chatId: string,
|
||||
messageId: string,
|
||||
request: EditMessageRequest,
|
||||
) {
|
||||
const message = this.recreateMessage(messageId);
|
||||
const options = {
|
||||
// It's fine to sent just ids instead of Contact object
|
||||
mentions: request.mentions as unknown as string[],
|
||||
};
|
||||
return message.edit(request.text, options);
|
||||
}
|
||||
|
||||
reply(request: MessageReplyRequest) {
|
||||
const options = {
|
||||
quotedMessageId: request.reply_to,
|
||||
@@ -265,15 +323,30 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
async setReaction(request: MessageReactionRequest) {
|
||||
const messageId = this.deserializeId(request.messageId);
|
||||
// Recreate instance to react on it
|
||||
const message = new MessageInstance(this.whatsapp);
|
||||
message.id = messageId;
|
||||
message._data = { id: messageId };
|
||||
|
||||
const message = this.recreateMessage(request.messageId);
|
||||
return message.react(request.reaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreate message instance from id
|
||||
*/
|
||||
private recreateMessage(msgId: string): MessageInstance {
|
||||
const messageId = this.deserializeId(msgId);
|
||||
const data = {
|
||||
id: messageId,
|
||||
};
|
||||
return new MessageInstance(this.whatsapp, data);
|
||||
}
|
||||
|
||||
async setStar(request: MessageStarRequest) {
|
||||
const message = this.recreateMessage(request.messageId);
|
||||
if (request.star) {
|
||||
await message.star();
|
||||
} else {
|
||||
await message.unstar();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
@@ -363,6 +436,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
public async getInfoAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
return {
|
||||
// Undocumented property, can be changed in the future
|
||||
// @ts-ignore
|
||||
adminsOnly: groupChat.groupMetadata.restrict,
|
||||
};
|
||||
@@ -373,6 +447,21 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return groupChat.setInfoAdminsOnly(value);
|
||||
}
|
||||
|
||||
public async getMessagesAdminsOnly(id): Promise<SettingsSecurityChangeInfo> {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
// @ts-ignore
|
||||
return {
|
||||
// Undocumented property, can be changed in the future
|
||||
// @ts-ignore
|
||||
adminsOnly: groupChat.groupMetadata.announce,
|
||||
};
|
||||
}
|
||||
|
||||
public async setMessagesAdminsOnly(id, value) {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
return groupChat.setMessagesAdminsOnly(value);
|
||||
}
|
||||
|
||||
public getGroups() {
|
||||
return this.whatsapp
|
||||
.getChats()
|
||||
@@ -506,6 +595,11 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
},
|
||||
);
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_REACTION:
|
||||
this.whatsapp.on('message_reaction', (message) =>
|
||||
handler(this.processMessageReaction(message)),
|
||||
);
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_ANY:
|
||||
this.whatsapp.on(Events.MESSAGE_CREATE, (message) =>
|
||||
this.processIncomingMessage(message).then(handler),
|
||||
@@ -543,6 +637,21 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return await this.toWAMessage(message);
|
||||
}
|
||||
|
||||
private processMessageReaction(reaction: Reaction): WAMessageReaction {
|
||||
return {
|
||||
id: reaction.id._serialized,
|
||||
from: reaction.senderId,
|
||||
fromMe: reaction.id.fromMe,
|
||||
participant: reaction.senderId,
|
||||
to: reaction.id.remote,
|
||||
timestamp: reaction.timestamp,
|
||||
reaction: {
|
||||
text: reaction.reaction,
|
||||
messageId: reaction.msgId._serialized,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected toWAMessage(message: Message): Promise<WAMessage> {
|
||||
// @ts-ignore
|
||||
return Promise.resolve({
|
||||
@@ -568,6 +677,13 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
});
|
||||
}
|
||||
|
||||
public async getEngineInfo() {
|
||||
return {
|
||||
WWebVersion: await this.whatsapp?.getWWebVersion(),
|
||||
state: await this.whatsapp?.getState(),
|
||||
};
|
||||
}
|
||||
|
||||
protected toWAContact(contact: Contact) {
|
||||
// @ts-ignore
|
||||
contact.id = contact.id._serialized;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { HealthCheckResult } from '@nestjs/terminus';
|
||||
|
||||
import { WAHAHealthCheckService } from '../abc/WAHAHealthCheckService';
|
||||
import { AvailableInPlusVersion } from '../exceptions';
|
||||
|
||||
@Injectable()
|
||||
export class WAHAHealthCheckServiceCore extends WAHAHealthCheckService {
|
||||
check(): Promise<HealthCheckResult> {
|
||||
throw new AvailableInPlusVersion();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export function toVcard(data): string {
|
||||
if (data.vcard) {
|
||||
return data.vcard;
|
||||
}
|
||||
const parts = [];
|
||||
parts.push('BEGIN:VCARD');
|
||||
parts.push('VERSION:3.0');
|
||||
parts.push(`FN:${data.fullName}`);
|
||||
if (data.organization) {
|
||||
parts.push(`ORG:${data.organization};`);
|
||||
}
|
||||
if (data.whatsappId) {
|
||||
parts.push(
|
||||
`TEL;type=CELL;type=VOICE;waid=${data.whatsappId}:${data.phoneNumber}`,
|
||||
);
|
||||
} else {
|
||||
parts.push(`TEL;type=CELL;type=VOICE:${data.phoneNumber}`);
|
||||
}
|
||||
parts.push('END:VCARD');
|
||||
return parts.join('\n');
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
ConsoleLogger,
|
||||
Injectable,
|
||||
LogLevel,
|
||||
NotFoundException,
|
||||
UnprocessableEntityException,
|
||||
} from '@nestjs/common';
|
||||
@@ -19,13 +20,15 @@ import {
|
||||
import { WebhookConfig } from '../structures/webhooks.config.dto';
|
||||
import { SessionManager } from './abc/manager.abc';
|
||||
import { SessionParams, WhatsappSession } from './abc/session.abc';
|
||||
import { WhatsappSessionNoWebCore } from './engines/noweb/session.noweb.core';
|
||||
import { WhatsappSessionVenomCore } from './engines/venom/session.venom.core';
|
||||
import { WhatsappSessionWebJSCore } from './engines/webjs/session.webjs.core';
|
||||
import { DOCS_URL } from './exceptions';
|
||||
import { getProxyConfig } from './helpers.proxy';
|
||||
import { CoreMediaManager, MediaStorageCore } from './media.core';
|
||||
import { WhatsappSessionNoWebCore } from './session.noweb.core';
|
||||
import { WhatsappSessionVenomCore } from './session.venom.core';
|
||||
import { WhatsappSessionWebJSCore } from './session.webjs.core';
|
||||
import { SessionStorageCore } from './storage.core';
|
||||
import { LocalSessionAuthRepository } from './storage/LocalSessionAuthRepository';
|
||||
import { LocalSessionConfigRepository } from './storage/LocalSessionConfigRepository';
|
||||
import { LocalStoreCore } from './storage/LocalStoreCore';
|
||||
import { WebhookConductorCore } from './webhooks.core';
|
||||
|
||||
export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
|
||||
@@ -36,8 +39,8 @@ export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
|
||||
}
|
||||
}
|
||||
|
||||
export function buildLogger(name) {
|
||||
return new ConsoleLogger(name, { logLevels: getLogLevels() });
|
||||
export function buildLogger(name: string, levels: LogLevel[]) {
|
||||
return new ConsoleLogger(name, { logLevels: levels });
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -59,8 +62,9 @@ export class SessionManagerCore extends SessionManager {
|
||||
this.session = undefined;
|
||||
const engineName = this.config.getDefaultEngineName();
|
||||
this.EngineClass = this.getEngine(engineName);
|
||||
this.sessionStorage = new SessionStorageCore(engineName.toLowerCase());
|
||||
|
||||
this.store = new LocalStoreCore(engineName.toLowerCase());
|
||||
this.sessionAuthRepository = new LocalSessionAuthRepository(this.store);
|
||||
this.sessionConfigRepository = new LocalSessionConfigRepository(this.store);
|
||||
this.startPredefinedSessions();
|
||||
}
|
||||
|
||||
@@ -104,23 +108,24 @@ export class SessionManagerCore extends SessionManager {
|
||||
|
||||
const name = request.name;
|
||||
this.log.log(`'${name}' - starting session...`);
|
||||
const log = buildLogger(`WhatsappSession - ${name}`);
|
||||
const levels = getLogLevels(request.config?.debug);
|
||||
const log = buildLogger(`WhatsappSession - ${name}`, levels);
|
||||
const mediaManager = new CoreMediaManager(
|
||||
new MediaStorageCore(),
|
||||
this.config.mimetypes,
|
||||
);
|
||||
const webhookLog = buildLogger(`Webhook - ${name}`);
|
||||
const webhookLog = buildLogger(`Webhook - ${name}`, levels);
|
||||
const webhook = new this.WebhookConductorClass(webhookLog);
|
||||
const proxyConfig = this.getProxyConfig(request);
|
||||
const sessionConfig: SessionParams = {
|
||||
name,
|
||||
mediaManager,
|
||||
log,
|
||||
sessionStorage: this.sessionStorage,
|
||||
sessionStore: this.store,
|
||||
proxyConfig: proxyConfig,
|
||||
sessionConfig: request.config,
|
||||
};
|
||||
await this.sessionStorage.init(name);
|
||||
await this.sessionAuthRepository.init(name);
|
||||
// @ts-ignore
|
||||
const session = new this.EngineClass(sessionConfig);
|
||||
this.session = session;
|
||||
@@ -181,7 +186,19 @@ export class SessionManagerCore extends SessionManager {
|
||||
}
|
||||
|
||||
async logout(request: SessionLogoutRequest) {
|
||||
await this.sessionStorage.clean(request.name);
|
||||
const name = request.name;
|
||||
this.onlyDefault(request.name);
|
||||
this.stop({ name: name, logout: false })
|
||||
.then(() => {
|
||||
this.log.log(`Session '${name}' has been stopped.`);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.log.error(
|
||||
`Error while stopping session '${name}' while logging out`,
|
||||
err,
|
||||
);
|
||||
});
|
||||
await this.sessionAuthRepository.clean(request.name);
|
||||
}
|
||||
|
||||
getSession(name: string): WhatsappSession {
|
||||
@@ -210,13 +227,25 @@ export class SessionManagerCore extends SessionManager {
|
||||
];
|
||||
}
|
||||
const me = await this.session.getSessionMeInfo().catch((err) => null);
|
||||
const engine = {
|
||||
engine: this.session?.engine,
|
||||
...(await this.session?.getEngineInfo().catch((err) => ({}))),
|
||||
};
|
||||
return [
|
||||
{
|
||||
name: this.session.name,
|
||||
status: this.session.status,
|
||||
config: this.session.sessionConfig,
|
||||
me: me,
|
||||
engine: engine,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async getSessionInfo(name: string): Promise<SessionInfo | null> {
|
||||
if (name !== this.DEFAULT) {
|
||||
return null;
|
||||
}
|
||||
return this.getSessions(true).then((sessions) => sessions[0]);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import { SessionConfig } from '../structures/sessions.dto';
|
||||
import {
|
||||
LocalSessionStorage,
|
||||
SessionConfigRepository,
|
||||
} from './abc/storage.abc';
|
||||
|
||||
class LocalSessionConfigRepository extends SessionConfigRepository {
|
||||
FILENAME = '.waha.session.config.json';
|
||||
|
||||
constructor(private storage: LocalSessionStorage) {
|
||||
super();
|
||||
}
|
||||
|
||||
async get(sessionName: string): Promise<SessionConfig | null> {
|
||||
const filepath = this.getFilePath(sessionName);
|
||||
// Check file exists
|
||||
try {
|
||||
await fs.access(filepath, fs.constants.F_OK);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to load config
|
||||
let content;
|
||||
try {
|
||||
content = await fs.readFile(filepath, 'utf-8');
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
async save(sessionName: string, config: SessionConfig | null) {
|
||||
// Create folder if not exist
|
||||
const folder = this.storage.getFolderPath(sessionName);
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
// Save config
|
||||
const filepath = this.getFilePath(sessionName);
|
||||
const content = JSON.stringify(config || null);
|
||||
await fs.writeFile(filepath, content);
|
||||
}
|
||||
|
||||
private getFilePath(sessionName): string {
|
||||
const folder = this.storage.getFolderPath(sessionName);
|
||||
return path.join(folder, this.FILENAME);
|
||||
}
|
||||
}
|
||||
|
||||
export class SessionStorageCore extends LocalSessionStorage {
|
||||
public sessionsFolder: string;
|
||||
|
||||
constructor(engine: string) {
|
||||
super(engine);
|
||||
this.sessionsFolder = path.join(os.tmpdir(), 'waha-sessions');
|
||||
}
|
||||
|
||||
get engineFolder() {
|
||||
return path.join(this.sessionsFolder, this.engine);
|
||||
}
|
||||
|
||||
async init(sessionName?: string) {
|
||||
const folder = sessionName
|
||||
? this.getFolderPath(sessionName)
|
||||
: this.engineFolder;
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
}
|
||||
|
||||
getFolderPath(name: string): string {
|
||||
const suffix = crypto.createHash('md5').update(name).digest('hex');
|
||||
return path.join(this.engineFolder, `${name}-${suffix}`);
|
||||
}
|
||||
|
||||
async clean(sessionName: string) {
|
||||
const folder = this.getFolderPath(sessionName);
|
||||
await fs.rm(folder, { recursive: true });
|
||||
}
|
||||
|
||||
async getAll(): Promise<string[]> {
|
||||
await this.init();
|
||||
const content = await fs.readdir(this.engineFolder, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
return content
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
}
|
||||
|
||||
get configRepository(): LocalSessionConfigRepository {
|
||||
return new LocalSessionConfigRepository(this);
|
||||
}
|
||||
}
|
||||