Compare commits

..
20 Commits
Author SHA1 Message Date
Aleksey Burov 983e8dbbd3 Update build.yaml
Release / deploy-docker (push) Waiting to run
2022-10-28 20:20:56 +07:00
Aleksey Burov b2150477d7 Add telegram dm link 2022-10-23 18:05:28 +07:00
Aleksey Burov f83eeac33a Delete docker-compose.yaml
Fix #19
2022-10-23 17:49:44 +07:00
allburov 37c4a85e76 Add httpbin in readme.md
Release / deploy-docker (push) Waiting to run
2022-10-13 10:31:39 +07:00
allburov 8732af0f43 Add onAnyMessage hook 2022-10-13 10:14:43 +07:00
allburov dfa7bc2ca8 Log errors
Release / deploy-docker (push) Waiting to run
2022-10-03 12:04:13 +07:00
allburov f857bab540 Change entrypoint to commands 2022-10-03 12:00:50 +07:00
allburov 59f2e1526d Ignore Dockerfile 2022-10-03 11:59:22 +07:00
allburov abe273166b Log QR code on a new line
Release / deploy-docker (push) Waiting to run
2022-10-03 11:53:38 +07:00
allburov 3e37e933b2 Add start:prod-exit to exit on any fails 2022-10-03 11:48:02 +07:00
allburov 6d2cae0784 Add how to build docker image locally 2022-09-30 11:47:31 +07:00
allburov 0bf44dae88 Add table of content pre-commit hook 2022-09-30 11:45:04 +07:00
FelipeVeiga 9c9d6fda10 adding message with buttons (#17) 2022-09-30 11:40:23 +07:00
allburov 8b82f76668 Start session at the launch time with WHATSAPP_START_SESSION
Release / deploy-docker (push) Waiting to run
2022-09-28 10:28:07 +07:00
allburov 5fb5eace6e Add GET /checkNumberStatus
Release / deploy-docker (push) Waiting to run
2022-09-27 17:01:36 +07:00
allburov ac865abe67 Send a message to group
Release / deploy-docker (push) Waiting to run
fix #16
2022-09-26 13:25:09 +07:00
allburov 0b4e8e31fb Add more screenshots 2022-09-17 15:27:36 +07:00
allburov 3695c5c25f Merge remote-tracking branch 'origin/main' into main 2022-09-17 15:21:48 +07:00
Aleksey Burov eaea661be2 Just 2 options 2022-08-22 19:23:09 +07:00
Aleksey Burov 2a5d5e9d13 Add direct support link to boosty 2022-08-22 18:42:05 +07:00
14 changed files with 112 additions and 32 deletions

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
Dockerfile
tokens
files
venv
+1 -1
View File
@@ -40,5 +40,5 @@ jobs:
push: ${{ github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
# cache-from: type=gha
cache-to: type=gha
+5
View File
@@ -0,0 +1,5 @@
repos:
- repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs
rev: v1.1.2
hooks:
- id: markdown-toc
+2 -1
View File
@@ -19,5 +19,6 @@ RUN npm install
WORKDIR /app
ADD . /app
RUN npm run build
ENTRYPOINT npm run start:prod
EXPOSE 3000
CMD npm run start:prod
+49 -10
View File
@@ -5,8 +5,28 @@ WhatsApp HTTP API that you can configure in a click! It's really Free! :)
The project provides you HTTP API for Whatsapp that you can use to send and receive messages. You can
go [through currently supported methods in Swagger](https://allburov.github.io/whatsapp-http-api/)
The project is an HTTP API wrapper around https://github.com/orkestral/venom
> The project is an HTTP API wrapper around https://github.com/orkestral/venom
# Tables of Contents
<!-- toc -->
- [Installation](#installation)
- [First Steps](#first-steps)
* [Run WhatsAPP HTTP API](#run-whatsapp-http-api)
* [Create a new session and login](#create-a-new-session-and-login)
* [Send a text message](#send-a-text-message)
- [Receive messages](#receive-messages)
+ [Python echo server](#python-echo-server)
- [Environment variables](#environment-variables)
* [Common](#common)
* [Webhooks](#webhooks)
* [File storage](#file-storage)
- [How to](#how-to)
* [How to build the newest Docker image locally](#how-to-build-the-newest-docker-image-locally)
- [Support](#support)
<!-- tocstop -->
# Installation
@@ -42,14 +62,16 @@ support ([yet](https://github.com/allburov/whatsapp-http-api/issues/4)) authoriz
1. To start a new session you should have your mobile phone with installed WhatsApp application close to you. Please go
and read how what we'll need to a bit
later: [How to log in - the instruction on WhatsApp site](https://faq.whatsapp.com/381777293328336/?helpref=hc_fnav)
2. Open API documentation at http://localhost:3000/
2. **Start a new session with a name** (you can use `default` for the start) - find `POST /api/session/start`, click
1. Open API documentation at http://localhost:3000/
1. **Start a new session with a name** (you can use `default` for the start) - find `POST /api/session/start`, click
on **Try it out**, then **Execute** a bit below.
3. **Scan QR Code** - find `GET /api/screenshot` and execute it, it'll show you QR code that you must scan with your
![](./docs/images/session-start.png)
1. **Scan QR Code** - find `GET /api/screenshot` and execute it, it'll show you QR code that you must scan with your
device.
4. **Get a screenshot** from Whatsapp again! It'll show you the screenshot of you Whatsapp instance.
5. If you can get the actual screenshot - then you're ready to start sending messages!
![](./docs/screenshot.png)
![](./docs/images/qr.png)
1. **Get a screenshot again** - it'll show you the screenshot of you Whatsapp instance. If you can get the actual
screenshot - then you're ready to start sending messages!
![](./docs/images/screenshot.png)
## Send a text message
@@ -114,6 +136,7 @@ If you try to send an image the "echo server" will send a path to the downloaded
- `DEBUG` - show debug and verbose logs, set in any value
- `WHATSAPP_API_PORT` - listen port for HTTP server (default: `3000`)
- `WHATSAPP_API_HOSTNAME` - Hostname for HTTP server (default: `localhost`)
- `WHATSAPP_START_SESSION` - start session with that name right after launching the app
## Webhooks
@@ -121,11 +144,18 @@ The description of [webhooks you can in Venom README.md, section Events](https:/
All webhooks are disabled by default:
- `WHATSAPP_HOOK_ONANYMESSAGE=http://localhost/uri`
- `WHATSAPP_HOOK_ONMESSAGE=http://localhost/uri`
- `WHATSAPP_HOOK_ONSTATECHANGE=http://localhost/uri`
- `WHATSAPP_HOOK_ONACK=http://localhost/uri`
- `WHATSAPP_HOOK_ONADDEDTOGROUP=http://localhost/uri`
If you want to look at the payload of the webhooks - use the url for that `https://httpbin.org/post`.
```bash
docker run -it -v `pwd`/tokens:/app/tokens --network=host -e WHATSAPP_HOOK_ONMESSAGE=https://httpbin.org/post allburov/whatsapp-http-api
```
## File storage
- `WHATSAPP_FILES_FOLDER` - folder where will be stored files from chats (images, voice messages) (
@@ -135,12 +165,21 @@ All webhooks are disabled by default:
like `audio,image`).
- `WHATSAPP_FILES_LIFETIME`- to keep free space files will be removed after this time (default: `180`, in seconds)
# How to
## How to build the newest Docker image locally
If the changes haven't been released yet from `main` branch - you can build your own version from the git repository
```bash
git clone https://github.com/allburov/whatsapp-http-api.git
cd whatsapp-http-api
docker build . -t allburov/whatsapp-http-api
```
# Support
If you want to support the project - you can either:
1. Create a Pull Request for desired functionality
2. Support [the project one time](https://boosty.to/allburov/single-payment/post/e7db2841-5b53-4e5e-bb37-e0fdcbab8d2b)
3. Support [the project every month](https://boosty.to/allburov/purchase/1015878)
4. Support [the project and get access to private telegram channel](https://boosty.to/allburov/purchase/1015879)
2. Support [the project one time, every month or get access to telegram channel on Boosty](https://boosty.to/allburov)
3. Looking for the personal support, have an important feature request for your business, need to develop a whatsapp bot? [Reach me out at Telegram](https://t.me/allburov)!
-15
View File
@@ -1,15 +0,0 @@
version: '3.4'
services:
whatsapp-http-api:
build: .
image: allburov/whatsapp-http-api
restart: always
ports:
- 3000:3000
shm_size: "1gb"
environment:
- WHATSAPP_DOWNLOADS_FOLDER=/app/files/downloads
volumes:
- ./tokens:/app/tokens
- ./files:/app/files
Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

+1
View File
@@ -13,6 +13,7 @@
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node --unhandled-rejections=none dist/main",
"start:prod-exit": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
+11
View File
@@ -11,6 +11,11 @@ export class SessionQuery {
sessionName: string = WHATSAPP_DEFAULT_SESSION_NAME;
}
export class CheckNumberStatusQuery extends SessionQuery {
@IsString()
phone: string
}
export class MessageTextQuery extends SessionQuery {
@IsString()
phone: string
@@ -48,6 +53,12 @@ export class MessageText extends ChatRequest {
text: string;
}
export class MessageTextButtons extends ChatRequest {
text: string;
title: string;
buttons: any[];
}
export class MessageReply extends ChatRequest {
text: string;
@ApiProperty({
+27
View File
@@ -2,6 +2,7 @@ import {Body, Controller, Get, NotImplementedException, Post, Query} from '@nest
import {ApiOperation, ApiTags} from "@nestjs/swagger";
import {
ChatRequest,
CheckNumberStatusQuery,
MessageContactVcard,
MessageFile,
MessageImage,
@@ -9,6 +10,7 @@ import {
MessageLocation,
MessageReply,
MessageText,
MessageTextButtons,
MessageTextQuery
} from "./all.dto";
import {ensureSuffix, WhatsappSessionManager} from "../whatsapp.service";
@@ -19,6 +21,24 @@ export class ChattingController {
constructor(private whatsappSessionManager: WhatsappSessionManager) {
}
@Get('/checkNumberStatus')
@ApiOperation({summary: 'Check number status'})
async checkNumberStatus(
@Query() request: CheckNumberStatusQuery,
) {
const whatsapp = this.whatsappSessionManager.getSession(request.sessionName)
try {
const result = await whatsapp.checkNumberStatus(ensureSuffix(request.phone))
return {numberExists: result['numberExists']}
} catch (error) {
// We need to "touch" the error in order to get unhandled rejections
// It logs out the session and stop the app
console.log(typeof error)
console.log(error)
return {numberExists: false}
}
}
@Post('/sendContactVcard')
sendContactVcard(@Body() message: MessageContactVcard) {
const whatsapp = this.whatsappSessionManager.getSession(message.sessionName)
@@ -41,6 +61,13 @@ export class ChattingController {
return whatsapp.sendText(ensureSuffix(message.chatId), message.text)
}
@Post('/sendTextButtons')
@ApiOperation({summary: 'Send a text message with buttons'})
sendTextButtons(@Body() message: MessageTextButtons) {
const whatsapp = this.whatsappSessionManager.getSession(message.sessionName)
return whatsapp.sendButtons(ensureSuffix(message.chatId), message.title, message.buttons, message.text)
}
@Post('/sendLocation')
sendLocation(@Body() message: MessageLocation) {
const whatsapp = this.whatsappSessionManager.getSession(message.sessionName)
+4
View File
@@ -46,6 +46,10 @@ export class WhatsappConfigService {
return types ? types.split(',') : null
}
get startSession(): string | undefined {
return this.configService.get('WHATSAPP_START_SESSION', undefined)
}
get(name: string): any {
return this.configService.get(name)
}
+11 -5
View File
@@ -15,9 +15,11 @@ const writeFileAsync = promisify(fs.writeFile)
const SECOND = 1000;
const ONMESSAGE_HOOK = "onMessage"
const ON_ANY_MESSAGE_HOOK = "onAnyMessage"
const ON_MESSAGE_HOOK = "onMessage"
const HOOKS = [
ONMESSAGE_HOOK,
ON_ANY_MESSAGE_HOOK,
ON_MESSAGE_HOOK,
"onStateChange",
"onAck",
// TODO: IMPLEMENTED THESE TOO
@@ -65,7 +67,8 @@ export class WhatsappService {
this.saveQRCode(base64Qrimg)
this.status = WhatsappStatus.SCAN_QR_CODE
console.log('Number of attempts to read the qrcode: ', attempts);
console.log('Terminal qrcode: ', asciiQR);
console.log('Terminal qrcode:');
console.log(asciiQR);
},
undefined,
{
@@ -190,7 +193,7 @@ export class WhatsappService {
continue
}
if (hook === ONMESSAGE_HOOK) {
if (hook === ON_MESSAGE_HOOK || hook == ON_ANY_MESSAGE_HOOK) {
this.whatsapp[hook](data => this.onMessageHook(data, url))
} else {
this.whatsapp[hook](data => this.callWebhook(data, url))
@@ -221,6 +224,9 @@ export class WhatsappSessionManager implements OnApplicationShutdown {
this.log.setContext('WhatsappSessionManager')
this.cleanDownloadsFolder(this.config.filesFolder)
this.sessions = {}
if (config.startSession) {
this.startSession(config.startSession)
}
}
async startSession(name: string) {
@@ -288,7 +294,7 @@ const SUFFIX_DIRECT_MESSAGE = "@c.us"
* @param phone
*/
export function ensureSuffix(phone) {
if (phone.endsWith(SUFFIX_DIRECT_MESSAGE)) {
if (phone.includes("@")) {
return phone
}
return phone + SUFFIX_DIRECT_MESSAGE