Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27a86f0dc1 | ||
|
|
767ea23173 | ||
|
|
85707508ed | ||
|
|
e8bc59ff9e | ||
|
|
7f9e622a64 | ||
|
|
b22e37596b | ||
|
|
642e90b1c8 | ||
|
|
8402ab896a | ||
|
|
d6dc7edf66 | ||
|
|
8f6dbf70f7 | ||
|
|
bd14d9a71e | ||
|
|
61a0a38dd2 | ||
|
|
102f438a99 | ||
|
|
586a2d1c79 | ||
|
|
5b04c39107 | ||
|
|
d96e91ea70 |
No files matched your search
@@ -23,8 +23,8 @@ assignees: ''
|
||||
```
|
||||
|
||||
> You can get the WAHA version by calling `GET /api/version` Try to update to
|
||||
> [the latest version](https://github.com/devlikeapro/whatsapp-http-api/releases)
|
||||
> before creating an issue!
|
||||
> [the latest version](https://github.com/devlikeapro/waha/releases) before
|
||||
> creating an issue!
|
||||
|
||||
**To Reproduce** Steps to reproduce the behavior:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
OWNER=devlikeapro
|
||||
REPO=whatsapp-http-api-plus
|
||||
REPO=waha-plus
|
||||
|
||||
# list workflows
|
||||
gh api -X GET /repos/$OWNER/$REPO/actions/workflows | jq '.workflows[] | .name,.id'
|
||||
|
||||
@@ -55,6 +55,7 @@ jobs:
|
||||
flavor: latest=false
|
||||
tags: |
|
||||
type=raw,value=${{ matrix.tag }}
|
||||
type=raw,value=${{ matrix.tag }}-{{tag}}
|
||||
|
||||
- name: Login to image repository
|
||||
if: github.ref_type == 'tag'
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
FROM node:${NODE_VERSION} as release
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=True
|
||||
# Quick fix for memory potential memory leaks
|
||||
# https://github.com/devlikeapro/whatsapp-http-api/issues/347
|
||||
# https://github.com/devlikeapro/waha/issues/347
|
||||
ENV NODE_OPTIONS="--max-old-space-size=16384"
|
||||
ARG USE_BROWSER=chromium
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
build:
|
||||
docker build . -t devlikeapro/whatsapp-http-api
|
||||
docker build . -t devlikeapro/waha
|
||||
|
||||
build-chrome:
|
||||
docker build . -t devlikeapro/whatsapp-http-api-plus:chrome --build-arg USE_BROWSER=chrome
|
||||
docker build . -t devlikeapro/waha-plus:chrome --build-arg USE_BROWSER=chrome
|
||||
|
||||
build-noweb:
|
||||
docker build . -t devlikeapro/whatsapp-http-api:noweb --build-arg USE_BROWSER=none
|
||||
docker build . -t devlikeapro/waha:noweb --build-arg USE_BROWSER=none
|
||||
|
||||
build-all: build build-chrome build-noweb
|
||||
|
||||
build-plus:
|
||||
docker build . -t devlikeapro/whatsapp-http-api-plus
|
||||
docker build . -t devlikeapro/waha-plus
|
||||
|
||||
build-ssh:
|
||||
# check IMAGE provided
|
||||
@[ "${IMAGE}" ] || ( echo "Add APP: make build-ssh image=devlikeapro/whatsapp-http-api"; exit 1 );
|
||||
@[ "${IMAGE}" ] || ( echo "Add APP: make build-ssh image=devlikeapro/waha"; exit 1 );
|
||||
eval $(ssh-agent) && \
|
||||
ssh-add ~/.ssh/id_rsa && \
|
||||
docker buildx build --ssh default=${SSH_AUTH_SOCK} . -t ${IMAGE} --build-arg USE_BROWSER=none
|
||||
|
||||
stop:
|
||||
docker stop whatsapp-http-api
|
||||
docker stop waha
|
||||
|
||||
clean: stop
|
||||
sudo rm -rf .sessions
|
||||
|
||||
push:
|
||||
docker push devlikeapro/whatsapp-http-api
|
||||
docker push devlikeapro/waha
|
||||
|
||||
for-swagger:
|
||||
WHATSAPP_SWAGGER_CONFIG_ADVANCED=true npm run start
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# WhatsApp HTTP API (WAHA)
|
||||
# WAHA
|
||||
|
||||
<p align="center">
|
||||
<img src="./logo.png" style='border-radius: 50%' width='150'/>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
**WAHA** - **W**hats**A**pp **H**TTP **A**PI (REST API) that you can install on your own server and run in less than 5 minutes!
|
||||
|
||||
[](https://hub.docker.com/r/devlikeapro/whatsapp-http-api)
|
||||
[](https://hub.docker.com/r/devlikeapro/waha)
|
||||
|
||||
- Documentation: [https://waha.devlike.pro/](https://waha.devlike.pro/)
|
||||
- Swagger Example: [https://waha.devlike.pro/swagger](https://waha.devlike.pro/swagger)
|
||||
@@ -104,13 +104,13 @@ Assuming you have installed [Docker](https://docs.docker.com/get-docker/), let's
|
||||
|
||||
|
||||
```bash
|
||||
docker pull devlikeapro/whatsapp-http-api
|
||||
docker pull devlikeapro/waha
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
docker login -u devlikeapro -p {KEY}
|
||||
docker pull devlikeapro/whatsapp-http-api-plus
|
||||
docker pull devlikeapro/waha-plus
|
||||
docker logout
|
||||
```
|
||||
|
||||
@@ -121,7 +121,7 @@ Read more about how to get `PASSWORD` for [Plus Version →]({{< relref "plus-ve
|
||||
Run WhatsApp HTTP API:
|
||||
|
||||
```bash
|
||||
docker run -it --rm -p 3000:3000/tcp --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
docker run -it --rm -p 3000:3000/tcp --name waha devlikeapro/waha
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP API is running on: http://[::1]:3000
|
||||
|
||||
+9
-9
@@ -1,10 +1,10 @@
|
||||
version: '3'
|
||||
services:
|
||||
whatsapp-http-api:
|
||||
waha:
|
||||
# Check available Docker images:
|
||||
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
|
||||
image: devlikeapro/whatsapp-http-api
|
||||
container_name: whatsapp-http-api
|
||||
image: devlikeapro/waha
|
||||
container_name: waha
|
||||
ports:
|
||||
- '3000:3000/tcp'
|
||||
environment:
|
||||
@@ -14,11 +14,11 @@ services:
|
||||
- WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
restart: always
|
||||
|
||||
whatsapp-http-api-plus:
|
||||
waha-plus:
|
||||
# Check available Docker images:
|
||||
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
|
||||
image: devlikeapro/whatsapp-http-api-plus:chrome
|
||||
container_name: whatsapp-http-api-plus
|
||||
image: devlikeapro/waha-plus:chrome
|
||||
container_name: waha-plus
|
||||
ports:
|
||||
- '3000:3000/tcp'
|
||||
volumes:
|
||||
@@ -43,11 +43,11 @@ services:
|
||||
# - WAHA_WEBJS_WEB_VERSION=2.2412.54-videofix
|
||||
restart: always
|
||||
|
||||
whatsapp-http-api-plus--mongodb:
|
||||
waha-plus--mongodb:
|
||||
# Check available Docker images:
|
||||
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
|
||||
image: devlikeapro/whatsapp-http-api-plus:chrome
|
||||
container_name: whatsapp-http-api-plus--mongodb
|
||||
image: devlikeapro/waha-plus:chrome
|
||||
container_name: waha-plus--mongodb
|
||||
ports:
|
||||
- '3000:3000/tcp'
|
||||
volumes:
|
||||
|
||||
+12
-12
@@ -19,9 +19,9 @@ Download and start WhatsApp HTTP API docker container
|
||||
|
||||
```bash
|
||||
# Download the image
|
||||
docker pull devlikeapro/whatsapp-http-api
|
||||
docker pull devlikeapro/waha
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP API is running on: http://[::1]:3000
|
||||
@@ -36,11 +36,11 @@ commands to download the image
|
||||
|
||||
```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
|
||||
docker pull devlikeapro/waha:arm
|
||||
# Rename it, so you can use devlikeapro/waha image in other place
|
||||
docker tag devlikeapro/waha:arm devlikeapro/waha
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha
|
||||
|
||||
# It prints logs and the last line must be
|
||||
# WhatsApp HTTP API is running on: http://[::1]:3000
|
||||
@@ -79,9 +79,9 @@ 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
|
||||
git clone https://github.com/devlikeapro/waha.git
|
||||
# Open python example folder
|
||||
cd whatsapp-http-api/examples/python
|
||||
cd waha/examples/python
|
||||
# Install requirements
|
||||
python -mpip install -r requirements.txt
|
||||
# Run the bot
|
||||
@@ -106,18 +106,18 @@ Download **WAHA Plus** version:
|
||||
|
||||
```bash
|
||||
# Download the image
|
||||
docker pull devlikeapro/whatsapp-http-api-plus
|
||||
docker pull devlikeapro/waha-plus
|
||||
# Run the docker container
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name whatsapp-http-api devlikeapro/whatsapp-http-api-plus
|
||||
docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bot -e "WHATSAPP_HOOK_EVENTS=*" --name waha devlikeapro/waha-plus
|
||||
```
|
||||
|
||||
Run the WhatsApp Download Files bot:
|
||||
|
||||
```bash
|
||||
# Clone the git repository with example
|
||||
git clone https://github.com/devlikeapro/whatsapp-http-api.git
|
||||
git clone https://github.com/devlikeapro/waha.git
|
||||
# Open python example folder
|
||||
cd whatsapp-http-api/examples/python
|
||||
cd waha/examples/python
|
||||
# Install requirements
|
||||
python -mpip install -r requirements.txt
|
||||
# Run the bot
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "whatsapp-http-api",
|
||||
"name": "waha",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
@@ -35,6 +35,7 @@
|
||||
"@nestjs/terminus": "^10.2.3",
|
||||
"@types/lodash": "^4.14.194",
|
||||
"@types/ws": "^8.5.4",
|
||||
"async-lock": "^1.4.1",
|
||||
"check-disk-space": "^3.4.0",
|
||||
"class-validator": "^0.12.2",
|
||||
"del": "^6.0.0",
|
||||
|
||||
@@ -31,7 +31,7 @@ export class AllExceptionsFilter implements ExceptionFilter {
|
||||
/**
|
||||
* If file not found - we get weird 500 error
|
||||
* So we convert that exception manually to 404 and send appropriate JSON response
|
||||
* @issue https://github.com/devlikeapro/whatsapp-http-api/issues/134
|
||||
* @issue https://github.com/devlikeapro/waha/issues/134
|
||||
* @solution https://github.com/nestjs/serve-static/issues/139#issuecomment-612429557
|
||||
*/
|
||||
if (exception.code === 'ENOENT') {
|
||||
|
||||
@@ -112,17 +112,6 @@ export class WhatsappConfigService {
|
||||
return this.configService.get('WHATSAPP_SESSIONS_MONGO_URL', undefined);
|
||||
}
|
||||
|
||||
getDefaultEngineName(): WAHAEngine {
|
||||
const value = getEngineName();
|
||||
if (value in WAHAEngine) {
|
||||
return WAHAEngine[value];
|
||||
}
|
||||
console.log(
|
||||
`Unknown WhatsApp default engine WHATSAPP_DEFAULT_ENGINE=${value}. Using WEBJS`,
|
||||
);
|
||||
return WAHAEngine.WEBJS;
|
||||
}
|
||||
|
||||
get(name: string, defaultValue: any = undefined): any {
|
||||
return this.configService.get(name, defaultValue);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ export class SwaggerConfiguratorCore {
|
||||
'<ul>' +
|
||||
'<li><a href="https://waha.devlike.pro/" target="_blank">Documentation</a></li>' +
|
||||
'<li><a href="https://waha.devlike.pro/docs/how-to/engines/#features" target="_blank">Supported features in engines</a></li>' +
|
||||
'<li><a href="https://github.com/devlikeapro/whatsapp-http-api" target="_blank">GitHub - WAHA Core</a></li>' +
|
||||
'<li><a href="https://github.com/devlikeapro/whatsapp-http-api-plu' + // Separate line to pass pre-commit check
|
||||
'<li><a href="https://github.com/devlikeapro/waha" target="_blank">GitHub - WAHA Core</a></li>' +
|
||||
'<li><a href="https://github.com/devlikeapro/waha-plu' + // Separate line to pass pre-commit check
|
||||
's" target="_blank">GitHub - WAHA Plus</a></li>' +
|
||||
'<li><b>NEW!</b> - <a href="/dashboard">WAHA Dashboard</a></li>' +
|
||||
'<li><b>NEW!</b> - <a href="https://waha.devlike.pro/docs/how-to/waha-dashboard">WAHA Dashboard Documentation</a></li>' +
|
||||
|
||||
@@ -2,11 +2,24 @@ import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
import { WAHAEngine } from '../../structures/enums.dto';
|
||||
import { getEngineName } from '../../version';
|
||||
|
||||
@Injectable()
|
||||
export class EngineConfigService {
|
||||
constructor(protected configService: ConfigService) {}
|
||||
|
||||
getDefaultEngineName(): WAHAEngine {
|
||||
const value = getEngineName();
|
||||
if (value in WAHAEngine) {
|
||||
return WAHAEngine[value];
|
||||
}
|
||||
console.log(
|
||||
`Unknown WhatsApp default engine WHATSAPP_DEFAULT_ENGINE=${value}. Using WEBJS`,
|
||||
);
|
||||
return WAHAEngine.WEBJS;
|
||||
}
|
||||
|
||||
get shouldPrintQR(): boolean {
|
||||
const value = this.configService.get('WAHA_PRINT_QR', true);
|
||||
return parseBool(value);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useMultiFileAuthState } from '@adiwajshing/baileys';
|
||||
import { Store } from 'whatsapp-web.js';
|
||||
|
||||
import { DataStore } from '../../abc/DataStore';
|
||||
import { LocalStore } from '../../storage/LocalStore';
|
||||
import { useMultiFileAuthState } from './useMultiFileAuthState';
|
||||
|
||||
export class NowebAuthFactoryCore {
|
||||
buildAuth(store: DataStore, name: string) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import makeWASocket, {
|
||||
getAggregateVotesInPollMessage,
|
||||
getKeyAuthor,
|
||||
isJidGroup,
|
||||
isJidStatusBroadcast,
|
||||
jidNormalizedUser,
|
||||
makeCacheableSignalKeyStore,
|
||||
makeInMemoryStore,
|
||||
@@ -109,9 +110,13 @@ const PresenceStatuses = {
|
||||
const ToEnginePresenceStatus = flipObject(PresenceStatuses);
|
||||
|
||||
export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
private START_ATTEMPT_DELAY_SECONDS = 2;
|
||||
private AUTO_RESTART_AFTER_SECONDS = 30 * 60;
|
||||
|
||||
engine = WAHAEngine.NOWEB;
|
||||
authFactory = new NowebAuthFactoryCore();
|
||||
private restartTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private autoRestartTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
|
||||
get listenConnectionEventsFromTheStart() {
|
||||
return true;
|
||||
@@ -194,6 +199,23 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.listenConnectionEvents();
|
||||
this.events.emit(WAHAInternalEvent.ENGINE_START);
|
||||
}
|
||||
this.enableAutoRestart();
|
||||
}
|
||||
|
||||
protected enableAutoRestart() {
|
||||
if (this.autoRestartTimeoutId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add random delay to avoid multiple restarts at the same time
|
||||
const shiftSeconds = Math.floor(Math.random() * 30);
|
||||
const delay = this.AUTO_RESTART_AFTER_SECONDS + shiftSeconds;
|
||||
this.log.debug(`Auto-restart is enabled, after ${delay} seconds`);
|
||||
this.autoRestartTimeoutId = setTimeout(() => {
|
||||
this.autoRestartTimeoutId = null;
|
||||
this.log.log('Auto-restarting the client connection...');
|
||||
this.sock?.end('auto-restart');
|
||||
}, delay * SECOND);
|
||||
}
|
||||
|
||||
protected async getMessage(
|
||||
@@ -213,17 +235,19 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
private restartClient() {
|
||||
if (this.restartTimeoutId) {
|
||||
if (this.startTimeoutId) {
|
||||
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.log.log(
|
||||
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
|
||||
);
|
||||
this.startTimeoutId = setTimeout(() => {
|
||||
this.startTimeoutId = undefined;
|
||||
this.buildClient();
|
||||
}, 2 * SECOND);
|
||||
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
|
||||
}
|
||||
|
||||
protected listenConnectionEvents() {
|
||||
@@ -241,17 +265,18 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
const shouldReconnect =
|
||||
lastDisconnect.error?.output?.statusCode !==
|
||||
DisconnectReason.loggedOut;
|
||||
this.log.error(
|
||||
'connection closed due to ',
|
||||
lastDisconnect.error,
|
||||
', reconnecting ',
|
||||
shouldReconnect,
|
||||
);
|
||||
this.qr.save('');
|
||||
// reconnect if not logged out
|
||||
if (shouldReconnect) {
|
||||
this.log.log(
|
||||
`Connection closed due to '${lastDisconnect.error}', reconnecting...`,
|
||||
);
|
||||
this.restartClient();
|
||||
} else {
|
||||
this.log.error(
|
||||
`Connection closed due to '${lastDisconnect.error}', do not reconnect the session.`,
|
||||
);
|
||||
await this.end();
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
}
|
||||
}
|
||||
@@ -267,13 +292,19 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
async stop() {
|
||||
this.sock?.ev?.removeAllListeners();
|
||||
this.sock?.ws?.removeAllListeners();
|
||||
this.sock?.ws?.close();
|
||||
await this.end();
|
||||
this.status = WAHASessionStatus.STOPPED;
|
||||
return;
|
||||
}
|
||||
|
||||
private async end() {
|
||||
clearTimeout(this.autoRestartTimeoutId);
|
||||
clearTimeout(this.startTimeoutId);
|
||||
this.sock?.ev?.removeAllListeners();
|
||||
this.sock?.ws?.removeAllListeners();
|
||||
this.sock?.end();
|
||||
}
|
||||
|
||||
async getSessionMeInfo(): Promise<MeInfo | null> {
|
||||
const me = this.sock.authState?.creds?.me;
|
||||
if (!me) {
|
||||
@@ -773,14 +804,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
let body = message.message.conversation;
|
||||
if (!body) {
|
||||
// Some of the messages have no conversation, but instead have text in extendedTextMessage
|
||||
// https://github.com/devlikeapro/whatsapp-http-api/issues/90
|
||||
// https://github.com/devlikeapro/waha/issues/90
|
||||
body = message.message.extendedTextMessage?.text;
|
||||
}
|
||||
if (!body) {
|
||||
// Populate from caption
|
||||
const mediaContent = extractMediaContent(message.message);
|
||||
// @ts-ignore - AudioMessage doesn't have caption field
|
||||
body = mediaContent.caption;
|
||||
body = mediaContent?.caption;
|
||||
}
|
||||
return Promise.resolve({
|
||||
id: id,
|
||||
@@ -980,6 +1011,9 @@ function toCusFormat(remoteJid) {
|
||||
if (isJidGroup(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isJidStatusBroadcast(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (!remoteJid) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import {
|
||||
AuthenticationCreds,
|
||||
AuthenticationState,
|
||||
proto,
|
||||
} from '@adiwajshing/baileys';
|
||||
import { BufferJSON, initAuthCreds } from '@adiwajshing/baileys/lib/Utils';
|
||||
import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const AsyncLock = require('async-lock');
|
||||
|
||||
// We need to lock files due to the fact that we are using async functions to read and write files
|
||||
// https://github.com/WhiskeySockets/Baileys/issues/794
|
||||
// https://github.com/nodejs/node/issues/26338
|
||||
// Default pending is 1000, set it to infinity
|
||||
// https://github.com/rogierschouten/async-lock/issues/63
|
||||
const fileLock = new AsyncLock({ maxPending: Infinity });
|
||||
|
||||
/**
|
||||
* stores the full authentication state in a single folder.
|
||||
* Far more efficient than singlefileauthstate
|
||||
*
|
||||
* Again, I wouldn't endorse this for any production level use other than perhaps a bot.
|
||||
* Would recommend writing an auth state for use with a proper SQL or No-SQL DB
|
||||
* */
|
||||
export const useMultiFileAuthState = async (
|
||||
folder: string,
|
||||
): Promise<{
|
||||
state: AuthenticationState;
|
||||
saveCreds: () => Promise<void>;
|
||||
}> => {
|
||||
const writeData = (data: any, file: string) => {
|
||||
const filePath = join(folder, fixFileName(file));
|
||||
return fileLock.acquire(filePath, () =>
|
||||
writeFile(join(filePath), JSON.stringify(data, BufferJSON.replacer)),
|
||||
);
|
||||
};
|
||||
|
||||
const readData = async (file: string) => {
|
||||
try {
|
||||
const filePath = join(folder, fixFileName(file));
|
||||
const data = await fileLock.acquire(filePath, () =>
|
||||
readFile(filePath, { encoding: 'utf-8' }),
|
||||
);
|
||||
return JSON.parse(data, BufferJSON.reviver);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const removeData = async (file: string) => {
|
||||
try {
|
||||
const filePath = join(folder, fixFileName(file));
|
||||
await fileLock.acquire(filePath, () => unlink(filePath));
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const folderInfo = await stat(folder).catch(() => {
|
||||
return null;
|
||||
});
|
||||
if (folderInfo) {
|
||||
if (!folderInfo.isDirectory()) {
|
||||
throw new Error(
|
||||
`found something that is not a directory at ${folder}, either delete it or specify a different location`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await mkdir(folder, { recursive: true });
|
||||
}
|
||||
|
||||
const fixFileName = (file?: string) =>
|
||||
file?.replace(/\//g, '__')?.replace(/:/g, '-') || '';
|
||||
|
||||
const creds: AuthenticationCreds =
|
||||
(await readData('creds.json')) || initAuthCreds();
|
||||
|
||||
return {
|
||||
state: {
|
||||
creds,
|
||||
keys: {
|
||||
get: async (type, ids) => {
|
||||
const data = {};
|
||||
await Promise.all(
|
||||
ids.map(async (id) => {
|
||||
let value = await readData(`${type}-${id}.json`);
|
||||
if (type === 'app-state-sync-key' && value) {
|
||||
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
||||
}
|
||||
|
||||
data[id] = value;
|
||||
}),
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
set: async (data) => {
|
||||
const tasks: Promise<void>[] = [];
|
||||
for (const category in data) {
|
||||
for (const id in data[category]) {
|
||||
const value = data[category][id];
|
||||
const file = `${category}-${id}.json`;
|
||||
tasks.push(value ? writeData(value, file) : removeData(file));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(tasks);
|
||||
},
|
||||
},
|
||||
},
|
||||
saveCreds: () => {
|
||||
return writeData(creds, 'creds.json');
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
|
||||
import {
|
||||
ACK_UNKNOWN,
|
||||
SECOND,
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHAPresenceStatus,
|
||||
@@ -67,15 +68,21 @@ export interface WebJSConfig {
|
||||
}
|
||||
|
||||
export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
private START_ATTEMPT_DELAY_SECONDS = 2;
|
||||
|
||||
engine = WAHAEngine.WEBJS;
|
||||
protected engineConfig?: WebJSConfig;
|
||||
|
||||
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private shouldRestart: boolean;
|
||||
|
||||
whatsapp: Client;
|
||||
protected qr: QR;
|
||||
|
||||
public constructor(config) {
|
||||
super(config);
|
||||
this.qr = new QR();
|
||||
this.shouldRestart = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,6 +101,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
headless: true,
|
||||
executablePath: this.getBrowserExecutablePath(),
|
||||
args: this.getBrowserArgsForPuppeteer(),
|
||||
dumpio: this.isDebugEnabled(),
|
||||
},
|
||||
webVersion: webVersion,
|
||||
webVersionCache: {
|
||||
@@ -110,6 +118,27 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return new Client(clientOptions);
|
||||
}
|
||||
|
||||
private restartClient() {
|
||||
if (!this.shouldRestart) {
|
||||
this.log.debug("Shouldn't restart the client, ignoring restart request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.startTimeoutId) {
|
||||
const msg =
|
||||
'Request to restart is already in progress, ignoring restart request';
|
||||
this.log.warn(msg);
|
||||
return;
|
||||
}
|
||||
this.log.log(
|
||||
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
|
||||
);
|
||||
this.startTimeoutId = setTimeout(() => {
|
||||
this.startTimeoutId = undefined;
|
||||
this.start();
|
||||
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
|
||||
}
|
||||
|
||||
protected addProxyConfig(clientOptions: ClientOptions) {
|
||||
if (this.proxyConfig?.server !== undefined) {
|
||||
// push the proxy server to the args
|
||||
@@ -127,8 +156,9 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.status = WAHASessionStatus.STARTING;
|
||||
protected async init() {
|
||||
await this.end();
|
||||
this.shouldRestart = true;
|
||||
this.whatsapp = await this.buildClient();
|
||||
this.whatsapp
|
||||
.initialize()
|
||||
@@ -137,12 +167,16 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
this.whatsapp.pupBrowser.on('disconnected', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The browser has been disconnected');
|
||||
this.restartClient();
|
||||
});
|
||||
// Listen for page close event
|
||||
this.whatsapp.pupPage.on('close', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The WhatsApp Web page has been closed');
|
||||
this.restartClient();
|
||||
});
|
||||
|
||||
// Listen for page error event
|
||||
if (this.isDebugEnabled()) {
|
||||
this.log.debug("Logging 'console' event for web page");
|
||||
this.whatsapp.pupPage.on('console', (msg) =>
|
||||
@@ -156,6 +190,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
.catch((error) => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error(error);
|
||||
this.restartClient();
|
||||
return;
|
||||
});
|
||||
if (this.isDebugEnabled()) {
|
||||
@@ -163,12 +198,30 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
this.listenConnectionEvents();
|
||||
this.events.emit(WAHAInternalEvent.ENGINE_START);
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.status = WAHASessionStatus.STARTING;
|
||||
await this.init();
|
||||
return this;
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.whatsapp.destroy();
|
||||
this.shouldRestart = false;
|
||||
this.status = WAHASessionStatus.STOPPED;
|
||||
await this.end();
|
||||
}
|
||||
|
||||
private async end() {
|
||||
try {
|
||||
this.whatsapp?.removeAllListeners();
|
||||
clearInterval(this.startTimeoutId);
|
||||
this.whatsapp?.destroy().catch((error) => {
|
||||
this.log.debug('Failed to destroy the client', error);
|
||||
});
|
||||
} catch (error) {
|
||||
this.log.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getSessionMeInfo(): Promise<MeInfo | null> {
|
||||
|
||||
@@ -62,7 +62,7 @@ export class SessionManagerCore extends SessionManager {
|
||||
|
||||
this.log.setContext('SessionManager');
|
||||
this.session = undefined;
|
||||
const engineName = this.config.getDefaultEngineName();
|
||||
const engineName = this.engineConfigService.getDefaultEngineName();
|
||||
this.EngineClass = this.getEngine(engineName);
|
||||
this.store = new LocalStoreCore(engineName.toLowerCase());
|
||||
this.sessionAuthRepository = new LocalSessionAuthRepository(this.store);
|
||||
|
||||
@@ -20,7 +20,7 @@ export class RemoteFile {
|
||||
|
||||
@ApiProperty({
|
||||
example:
|
||||
'https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.jpg',
|
||||
'https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.jpg',
|
||||
})
|
||||
url: string;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export class VoiceRemoteFile {
|
||||
|
||||
@ApiProperty({
|
||||
example:
|
||||
'https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/dev.likeapro.opus',
|
||||
'https://github.com/devlikeapro/waha/raw/core/examples/dev.likeapro.opus',
|
||||
})
|
||||
url: string;
|
||||
}
|
||||
@@ -109,8 +109,7 @@ export class VideoRemoteFile {
|
||||
filename = 'video.mp4';
|
||||
|
||||
@ApiProperty({
|
||||
example:
|
||||
'https://github.com/devlikeapro/whatsapp-http-api/raw/core/examples/video.mp4',
|
||||
example: 'https://github.com/devlikeapro/waha/raw/core/examples/video.mp4',
|
||||
})
|
||||
url: string;
|
||||
}
|
||||
+1
-1
@@ -33,7 +33,7 @@ export function getEngineName(): string {
|
||||
}
|
||||
|
||||
export const VERSION: WAHAEnvironment = {
|
||||
version: '2024.5.13',
|
||||
version: '2024.6.2',
|
||||
engine: getEngineName(),
|
||||
tier: getWAHAVersion(),
|
||||
browser: getBrowserExecutablePath(),
|
||||
|
||||
@@ -14,10 +14,11 @@ __metadata:
|
||||
|
||||
"@adiwajshing/baileys@github:WhiskeySockets/Baileys":
|
||||
version: 6.7.2
|
||||
resolution: "@adiwajshing/baileys@https://github.com/WhiskeySockets/Baileys.git#commit=79c33e53b4124735f019c48e8075c9cde807b7e7"
|
||||
resolution: "@adiwajshing/baileys@https://github.com/WhiskeySockets/Baileys.git#commit=9065ab690fde0641e3eac458c1521e1d151c5050"
|
||||
dependencies:
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@hapi/boom": ^9.1.3
|
||||
async-lock: ^1.4.1
|
||||
audio-decode: ^2.1.3
|
||||
axios: ^1.3.3
|
||||
cache-manager: 4.0.1
|
||||
@@ -44,7 +45,7 @@ __metadata:
|
||||
optional: true
|
||||
sharp:
|
||||
optional: true
|
||||
checksum: dacfec2d2c4767370f2ee9a846e119cedf22d792ae920c5682e66aa67e788ec409d5ee364e6879c7c9e76d00acfb2c26c197d377893aaccc2100f3ae22940d72
|
||||
checksum: 255c9aa3107a56055b33adbfba5cce41bad16d1b2453a19f3896438a85e191786c144ea73ebdb896f58c7436044aca8e740d5d9e7271c8df12f9e89318abf90f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3169,6 +3170,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"async-lock@npm:^1.4.1":
|
||||
version: 1.4.1
|
||||
resolution: "async-lock@npm:1.4.1"
|
||||
checksum: 29e70cd892932b7c202437786cedc39ff62123cb6941014739bd3cabd6106326416e9e7c21285a5d1dc042cad239a0f7ec9c44658491ee4a615fd36a21c1d10a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"async@npm:3.2.3":
|
||||
version: 3.2.3
|
||||
resolution: "async@npm:3.2.3"
|
||||
@@ -12425,6 +12433,72 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"waha@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "waha@workspace:."
|
||||
dependencies:
|
||||
"@adiwajshing/baileys": "github:WhiskeySockets/Baileys"
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@nestjs/axios": ^3.0.2
|
||||
"@nestjs/cli": ^9.0.0
|
||||
"@nestjs/common": ^9.0.9
|
||||
"@nestjs/config": ^0.5.0
|
||||
"@nestjs/core": ^9.0.9
|
||||
"@nestjs/passport": ^9.0.0
|
||||
"@nestjs/platform-express": ^9.0.9
|
||||
"@nestjs/schematics": ^9.0.1
|
||||
"@nestjs/serve-static": ^2.1.3
|
||||
"@nestjs/swagger": ^7.1.11
|
||||
"@nestjs/terminus": ^10.2.3
|
||||
"@nestjs/testing": ^9.0.9
|
||||
"@types/express": ^4.17.3
|
||||
"@types/jest": 26.0.10
|
||||
"@types/lodash": ^4.14.194
|
||||
"@types/node": ^18.14.2
|
||||
"@types/supertest": ^2.0.8
|
||||
"@types/ws": ^8.5.4
|
||||
"@typescript-eslint/eslint-plugin": 3.9.1
|
||||
"@typescript-eslint/parser": 3.9.1
|
||||
async-lock: ^1.4.1
|
||||
check-disk-space: ^3.4.0
|
||||
class-validator: ^0.12.2
|
||||
del: ^6.0.0
|
||||
eslint: 7.7.0
|
||||
eslint-config-prettier: ^6.10.0
|
||||
eslint-plugin-import: ^2.20.1
|
||||
eslint-plugin-simple-import-sort: ^10.0.0
|
||||
express-basic-auth: ^1.2.1
|
||||
file-type: 16.5.4
|
||||
https-proxy-agent: ^7.0.0
|
||||
jest: ^29.7.0
|
||||
libphonenumber-js: ^1.10.36
|
||||
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
|
||||
prettier: ^1.19.1
|
||||
puppeteer: ^21.0.0
|
||||
qrcode: ^1.5.1
|
||||
qrcode-terminal: ^0.12.0
|
||||
reflect-metadata: ^0.1.13
|
||||
request: ^2.88.2
|
||||
requestretry: ^4.1.1
|
||||
rimraf: ^3.0.2
|
||||
rxjs: ^7.1.0
|
||||
supertest: ^4.0.2
|
||||
swagger-ui-express: ^4.1.4
|
||||
ts-jest: ^29.1.3
|
||||
ts-loader: ^6.2.1
|
||||
ts-node: ^10.9.1
|
||||
tsconfig-paths: ^4.1.0
|
||||
typescript: ^4.8.4
|
||||
venom-bot: 5.0.1
|
||||
whatsapp-web.js: "https://github.com/devlikeapro/whatsapp-web.js#main-fork-update"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"walker@npm:^1.0.8":
|
||||
version: 1.0.8
|
||||
resolution: "walker@npm:1.0.8"
|
||||
@@ -12518,71 +12592,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"whatsapp-http-api@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "whatsapp-http-api@workspace:."
|
||||
dependencies:
|
||||
"@adiwajshing/baileys": "github:WhiskeySockets/Baileys"
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@nestjs/axios": ^3.0.2
|
||||
"@nestjs/cli": ^9.0.0
|
||||
"@nestjs/common": ^9.0.9
|
||||
"@nestjs/config": ^0.5.0
|
||||
"@nestjs/core": ^9.0.9
|
||||
"@nestjs/passport": ^9.0.0
|
||||
"@nestjs/platform-express": ^9.0.9
|
||||
"@nestjs/schematics": ^9.0.1
|
||||
"@nestjs/serve-static": ^2.1.3
|
||||
"@nestjs/swagger": ^7.1.11
|
||||
"@nestjs/terminus": ^10.2.3
|
||||
"@nestjs/testing": ^9.0.9
|
||||
"@types/express": ^4.17.3
|
||||
"@types/jest": 26.0.10
|
||||
"@types/lodash": ^4.14.194
|
||||
"@types/node": ^18.14.2
|
||||
"@types/supertest": ^2.0.8
|
||||
"@types/ws": ^8.5.4
|
||||
"@typescript-eslint/eslint-plugin": 3.9.1
|
||||
"@typescript-eslint/parser": 3.9.1
|
||||
check-disk-space: ^3.4.0
|
||||
class-validator: ^0.12.2
|
||||
del: ^6.0.0
|
||||
eslint: 7.7.0
|
||||
eslint-config-prettier: ^6.10.0
|
||||
eslint-plugin-import: ^2.20.1
|
||||
eslint-plugin-simple-import-sort: ^10.0.0
|
||||
express-basic-auth: ^1.2.1
|
||||
file-type: 16.5.4
|
||||
https-proxy-agent: ^7.0.0
|
||||
jest: ^29.7.0
|
||||
libphonenumber-js: ^1.10.36
|
||||
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
|
||||
prettier: ^1.19.1
|
||||
puppeteer: ^21.0.0
|
||||
qrcode: ^1.5.1
|
||||
qrcode-terminal: ^0.12.0
|
||||
reflect-metadata: ^0.1.13
|
||||
request: ^2.88.2
|
||||
requestretry: ^4.1.1
|
||||
rimraf: ^3.0.2
|
||||
rxjs: ^7.1.0
|
||||
supertest: ^4.0.2
|
||||
swagger-ui-express: ^4.1.4
|
||||
ts-jest: ^29.1.3
|
||||
ts-loader: ^6.2.1
|
||||
ts-node: ^10.9.1
|
||||
tsconfig-paths: ^4.1.0
|
||||
typescript: ^4.8.4
|
||||
venom-bot: 5.0.1
|
||||
whatsapp-web.js: "https://github.com/devlikeapro/whatsapp-web.js#main-fork-update"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js#main-fork-update":
|
||||
version: 1.23.1-alpha.6
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=d6eff450edf3e8d292cf70eb4243fd32ace61182"
|
||||
|
||||
Reference in new issue
Block a user