Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb8691ddc0 | ||
|
|
cf3041d07b | ||
|
|
313b3d5d6b | ||
|
|
122e7336be | ||
|
|
e954453f6b | ||
|
|
55ef3d09f3 | ||
|
|
88b9cc5ac9 | ||
|
|
f07cb7470d | ||
|
|
bd874a0232 | ||
|
|
7cc4cccb9c | ||
|
|
e85a3bacb7 | ||
|
|
530dfa758f | ||
|
|
8bc3489060 | ||
|
|
6914cb171a | ||
|
|
176c2bbd4c | ||
|
|
7771954455 | ||
|
|
a66743bb20 | ||
|
|
851c7b75f9 | ||
|
|
ed0b406027 | ||
|
|
71985972a2 | ||
|
|
2dbeef9290 | ||
|
|
a79453270d | ||
|
|
ae71808c61 | ||
|
|
5c195ba37b | ||
|
|
607ee17a86 | ||
|
|
a15aacc5b3 |
No files matched your search
@@ -1,5 +1,6 @@
|
||||
Dockerfile
|
||||
src/core/engines/gows/grpc
|
||||
src/core/engines/gows/proto
|
||||
.*sessions
|
||||
sessions
|
||||
files
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
src/core/engines/gows/grpc/*
|
||||
src/core/engines/gows/proto/*
|
||||
@@ -1,4 +1,5 @@
|
||||
src/core/engines/gows/grpc
|
||||
src/core/engines/gows/proto
|
||||
.env
|
||||
*.heapsnapshot
|
||||
.yarn
|
||||
|
||||
@@ -3,6 +3,7 @@ exclude: |
|
||||
^src/dashboard/.*|
|
||||
^src/core/engines/webjs/.*html|
|
||||
^src/core/engines/gows/grpc/.*|
|
||||
^src/core/engines/gows/proto/.*|
|
||||
^src/plus/engines/webjs/.*html|
|
||||
^.yarn/.*
|
||||
)$
|
||||
@@ -74,4 +75,6 @@ repos:
|
||||
.pre-commit-config.yaml|
|
||||
^src/core/engines/webjs/session.webjs.core.ts|
|
||||
^src/core/engines/webjs/_lodash.js|
|
||||
^tests/perf/.*|
|
||||
^scripts/.*|
|
||||
)$
|
||||
+27
-37
@@ -1,9 +1,3 @@
|
||||
# GOWS
|
||||
ARG GOWS_GITHUB_REPO=devlikeapro/gows
|
||||
ARG GOWS_SHA=39ba4dcceeeb6e6fab172ee71ad1c09deea4db16
|
||||
ARG WAHA_DASHBOARD_GITHUB_REPO=devlikeapro/dashboard
|
||||
ARG WAHA_DASHBOARD_SHA=a1c839d8da94d1cade182addffdfc42fc0cf7ed3
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
@@ -11,12 +5,8 @@ ARG NODE_VERSION=22.8-bullseye
|
||||
FROM node:${NODE_VERSION} AS build
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=True
|
||||
|
||||
# install protoc
|
||||
RUN apt-get update && \
|
||||
apt-get install protobuf-compiler -y
|
||||
|
||||
# npm packages
|
||||
WORKDIR /src
|
||||
WORKDIR /git
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
ENV YARN_CHECKSUM_BEHAVIOR=update
|
||||
@@ -25,19 +15,10 @@ RUN yarn set version 3.6.3
|
||||
RUN yarn install
|
||||
|
||||
# App
|
||||
WORKDIR /src
|
||||
ADD . /src
|
||||
WORKDIR /git
|
||||
ADD . /git
|
||||
RUN yarn install
|
||||
|
||||
# Build node grpc client for GOWS engine
|
||||
WORKDIR /gows/proto
|
||||
ARG GOWS_GITHUB_REPO
|
||||
ARG GOWS_SHA
|
||||
RUN wget https://raw.githubusercontent.com/${GOWS_GITHUB_REPO}/${GOWS_SHA}/proto/gows.proto
|
||||
WORKDIR /src
|
||||
|
||||
RUN make proto-gows
|
||||
|
||||
RUN yarn gows:proto
|
||||
RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
|
||||
#
|
||||
@@ -45,10 +26,13 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
#
|
||||
FROM node:${NODE_VERSION} AS dashboard
|
||||
|
||||
# Download WAHA Dashboard
|
||||
ARG WAHA_DASHBOARD_GITHUB_REPO
|
||||
ARG WAHA_DASHBOARD_SHA
|
||||
# jq to parse json
|
||||
RUN apt-get update && apt-get install -y jq && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY waha.config.json /tmp/waha.config.json
|
||||
RUN \
|
||||
WAHA_DASHBOARD_GITHUB_REPO=$(jq -r '.waha.dashboard.repo' /tmp/waha.config.json) && \
|
||||
WAHA_DASHBOARD_SHA=$(jq -r '.waha.dashboard.ref' /tmp/waha.config.json) && \
|
||||
wget https://github.com/${WAHA_DASHBOARD_GITHUB_REPO}/archive/${WAHA_DASHBOARD_SHA}.zip \
|
||||
&& unzip ${WAHA_DASHBOARD_SHA}.zip -d /tmp/dashboard \
|
||||
&& mkdir -p /dashboard \
|
||||
@@ -60,6 +44,10 @@ RUN \
|
||||
# GOWS
|
||||
#
|
||||
FROM golang:1.23-bullseye AS gows
|
||||
|
||||
# jq to parse json
|
||||
RUN apt-get update && apt-get install -y jq && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# install protoc
|
||||
RUN apt-get update && \
|
||||
apt-get install protobuf-compiler -y
|
||||
@@ -69,16 +57,18 @@ RUN apt-get update \
|
||||
&& apt-get install -y libvips-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG GOWS_GITHUB_REPO
|
||||
ARG GOWS_SHA
|
||||
RUN git clone https://github.com/${GOWS_GITHUB_REPO} gows && \
|
||||
cd gows && \
|
||||
git checkout ${GOWS_SHA}
|
||||
|
||||
COPY waha.config.json /tmp/waha.config.json
|
||||
WORKDIR /go/gows
|
||||
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
RUN make all
|
||||
RUN \
|
||||
GOWS_GITHUB_REPO=$(jq -r '.waha.gows.repo' /tmp/waha.config.json) && \
|
||||
GOWS_SHA=$(jq -r '.waha.gows.ref' /tmp/waha.config.json) && \
|
||||
ARCH=$(uname -m) && \
|
||||
if [ "$ARCH" = "x86_64" ]; then ARCH="amd64"; \
|
||||
elif [ "$ARCH" = "aarch64" ]; then ARCH="arm64"; \
|
||||
else echo "Unsupported architecture: $ARCH" && exit 1; fi && \
|
||||
mkdir -p /go/gows/bin && \
|
||||
wget -O /go/gows/bin/gows https://github.com/${GOWS_GITHUB_REPO}/releases/download/v.${GOWS_SHA}/gows-${ARCH} && \
|
||||
chmod +x /go/gows/bin/gows
|
||||
|
||||
|
||||
#
|
||||
@@ -163,8 +153,8 @@ ENV WHATSAPP_DEFAULT_ENGINE=$WHATSAPP_DEFAULT_ENGINE
|
||||
# Attach sources, install packages
|
||||
WORKDIR /app
|
||||
COPY package.json ./
|
||||
COPY --from=build /src/node_modules ./node_modules
|
||||
COPY --from=build /src/dist ./dist
|
||||
COPY --from=build /git/node_modules ./node_modules
|
||||
COPY --from=build /git/dist ./dist
|
||||
COPY --from=dashboard /dashboard ./dist/dashboard
|
||||
COPY --from=gows /go/gows/bin/gows /app/gows
|
||||
ENV WAHA_GOWS_PATH /app/gows
|
||||
|
||||
@@ -35,7 +35,7 @@ for-swagger:
|
||||
WHATSAPP_SWAGGER_CONFIG_ADVANCED=true . ${NVM_DIR}/nvm.sh && nvm exec yarn start
|
||||
|
||||
up-noweb:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-678
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-6712
|
||||
|
||||
up-noweb-libsignal:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up libsignal@github:devlikeapro/libsignal-node#fork-master
|
||||
@@ -47,15 +47,7 @@ start-proxy:
|
||||
docker run --rm -d --name squid-container -e TZ=UTC -p 3128:3128 ubuntu/squid:5.2-22.04_beta
|
||||
|
||||
proto-gows:
|
||||
rm -rf src/core/engines/gows/grpc
|
||||
mkdir -p src/core/engines/gows/grpc
|
||||
protoc \
|
||||
--plugin=protoc-gen-ts=node_modules/.bin/protoc-gen-ts \
|
||||
--plugin=protoc-gen-grpc=node_modules/.bin/grpc_tools_node_protoc_plugin \
|
||||
--js_out=import_style=commonjs,binary:src/core/engines/gows/grpc \
|
||||
--grpc_out=grpc_js:src/core/engines/gows/grpc \
|
||||
--ts_out=grpc_js:src/core/engines/gows/grpc \
|
||||
-I ../gows/proto ../gows/proto/gows.proto
|
||||
node scripts/gows-proto.js build --dir ../gows/proto
|
||||
|
||||
gows:
|
||||
cd ../gows && \
|
||||
|
||||
@@ -6,22 +6,16 @@
|
||||
|
||||
**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/waha)
|
||||
[](https://hub.docker.com/r/devlikeapro/waha)
|
||||
|
||||
- Documentation: [https://waha.devlike.pro/](https://waha.devlike.pro/)
|
||||
- Dashboard Example: [https://waha.devlike.pro/dashboard](https://waha.devlike.pro/dashboard)
|
||||
- Swagger Example: [https://waha.devlike.pro/swagger](https://waha.devlike.pro/swagger)
|
||||
|
||||
# Tables of Contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Features](#features)
|
||||
* [Messages](#messages)
|
||||
* [Sessions](#sessions)
|
||||
* [Security](#security)
|
||||
* [Updates](#updates)
|
||||
* [Groups](#groups)
|
||||
* [Contacts](#contacts)
|
||||
- [Quick start](#quick-start)
|
||||
* [Requirements](#requirements)
|
||||
* [Send your first message](#send-your-first-message)
|
||||
@@ -32,52 +26,11 @@
|
||||
+ [5. Get the screenshot](#5-get-the-screenshot)
|
||||
+ [6. Send a text message](#6-send-a-text-message)
|
||||
* [What is next?](#what-is-next)
|
||||
- [Development](#development)
|
||||
* [Start the project](#start-the-project)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
# Features
|
||||
|
||||
## Messages
|
||||
- Send messages
|
||||
- Receive messages
|
||||
- Message replies
|
||||
- Send location
|
||||
- Receive location
|
||||
- React to messages
|
||||
- Send media (images/documents/files)
|
||||
- Send voice messages
|
||||
- Receive media (images/audio/video/documents)
|
||||
- Receive messages - webhook retries
|
||||
|
||||
## Sessions
|
||||
- Multi Device
|
||||
- Get the screenshot
|
||||
- Session saving (don't have to scan QR on every restart)
|
||||
- Single WhatsApp account running inside one container
|
||||
- Multiple WhatsApp account running inside one container
|
||||
|
||||
## Security
|
||||
- Swagger panel authentication
|
||||
- API authentication
|
||||
|
||||
## Updates
|
||||
- Bug fixes and updates come as soon as they are implemented.
|
||||
|
||||
## Groups
|
||||
- Create a group
|
||||
- Get invite for group
|
||||
- Modify group info (subject, description)
|
||||
- Add group participants
|
||||
- Kick group participants
|
||||
- Promote/demote group participants
|
||||
|
||||
## Contacts
|
||||
- Mute/unmute chats
|
||||
- Block/unblock contacts
|
||||
- Get contact info
|
||||
- Get profile pictures
|
||||
- Get presence (online\offline\typing) status
|
||||
|
||||
# Quick start
|
||||
|
||||
## Requirements
|
||||
@@ -87,13 +40,6 @@ instruction <a href="https://docs.docker.com/get-docker/" target="_blank" rel="n
|
||||
|
||||
When you are ready - come back and follows the below steps to send the first text message to WhatsApp via HTTP API!
|
||||
|
||||
{{< details "Why Docker?" >}}
|
||||
Docker makes it easy to ship all-in-one solution with the runtime and dependencies. You don't have to worry about
|
||||
language-specific libraries or chrome installation.
|
||||
|
||||
Also Docker makes installation and update processes so simple, just one command!
|
||||
{{< /details >}}
|
||||
|
||||
## Send your first message
|
||||
|
||||
Let's go over steps that allow you to send your first text message via WhatsApp HTTP API!
|
||||
@@ -114,7 +60,7 @@ docker pull devlikeapro/waha-plus
|
||||
docker logout
|
||||
```
|
||||
|
||||
Read more about how to get `PASSWORD` for [Plus Version →]({{< relref "plus-version" >}})
|
||||
Read more about how to get `PASSWORD` for [**➕ WAHA Plus**](https://waha.devlike.pro/docs/how-to/waha-plus/)
|
||||
|
||||
### 2. Run WhatsApp HTTP API
|
||||
|
||||
@@ -195,3 +141,19 @@ curl -d "{\"chatId\": \"${PHONE}@c.us\", \"text\": \"Hello from WhatsApp HTTP AP
|
||||
|
||||
## What is next?
|
||||
[Go and read the full documentation!](https://waha.devlike.pro/docs/overview/introduction/)
|
||||
|
||||
# Development
|
||||
|
||||
## Start the project
|
||||
1. Clone the repository
|
||||
2. Make sure you're using node>=22
|
||||
3. Run the following commands:
|
||||
```bash
|
||||
# Install dependencies
|
||||
yarn install
|
||||
# Fetch and compile proto files
|
||||
yarn gows:proto
|
||||
# Run
|
||||
yarn start
|
||||
# open http://localhost:3000
|
||||
```
|
||||
+7
-3
@@ -20,10 +20,13 @@
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||
"gows:proto:fetch": "node scripts/gows-proto.js fetch",
|
||||
"gows:proto:build": "node scripts/gows-proto.js build",
|
||||
"gows:proto": "yarn gows:proto:fetch && yarn gows:proto:build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-channels-678",
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-channels-6712",
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@aws-sdk/client-s3": "^3.633.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.633.0",
|
||||
@@ -120,7 +123,8 @@
|
||||
"ts-loader": "^6.2.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.1.0",
|
||||
"typescript": "^4.8.4"
|
||||
"typescript": "^4.8.4",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const fs = require('fs');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const path = require('path');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const axios = require('axios');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { execSync } = require('child_process');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const yargs = require('yargs');
|
||||
|
||||
// Defaults
|
||||
const CONFIG_FILE = 'waha.config.json';
|
||||
// Load defaults from package.json
|
||||
gows = (() => {
|
||||
try {
|
||||
const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
||||
return config.waha.gows || {};
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
})();
|
||||
|
||||
const DEFAULT_REPO = gows.repo;
|
||||
if (!DEFAULT_REPO) {
|
||||
throw new Error(`Missing default repo in ${CONFIG_FILE}`);
|
||||
}
|
||||
const DEFAULT_REF = gows.ref;
|
||||
if (!DEFAULT_REF) {
|
||||
throw new Error('Missing default ref in ${CONFIG_FILE}');
|
||||
}
|
||||
const DEFAULT_DIR = './src/core/engines/gows/proto';
|
||||
|
||||
const PROTO_FILES = ['gows.proto'];
|
||||
const PROTO_OUTPUT = './src/core/engines/gows/grpc';
|
||||
|
||||
// Helper function to clean directory
|
||||
function cleanDirectory(directory, suffix) {
|
||||
if (!fs.existsSync(directory)) {
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
return;
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(directory);
|
||||
for (const file of files) {
|
||||
const filePath = path.join(directory, file);
|
||||
if (file.endsWith(suffix)) {
|
||||
fs.unlinkSync(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to download files
|
||||
async function downloadFiles(repo, ref, directory) {
|
||||
for (const file of PROTO_FILES) {
|
||||
const url = `https://github.com/${repo}/releases/download/v.${ref}/${file}`;
|
||||
const filePath = path.join(directory, file);
|
||||
try {
|
||||
const response = await axios.get(url, { responseType: 'arraybuffer' });
|
||||
fs.writeFileSync(filePath, response.data);
|
||||
console.log(`Downloaded: ${file}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to download ${file}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for fetch command
|
||||
async function handleFetch(repo, ref, dir) {
|
||||
console.log(`Fetching .proto files from ${repo}@${ref} to ${dir}...`);
|
||||
cleanDirectory(dir, '.proto');
|
||||
await downloadFiles(repo, ref, dir);
|
||||
}
|
||||
|
||||
// Handler for build command
|
||||
function handleBuild(dir) {
|
||||
console.log('Building gRPC files...');
|
||||
cleanDirectory(PROTO_OUTPUT);
|
||||
|
||||
const command = `grpc_tools_node_protoc \
|
||||
--plugin=protoc-gen-ts=node_modules/.bin/protoc-gen-ts \
|
||||
--plugin=protoc-gen-grpc=node_modules/.bin/grpc_tools_node_protoc_plugin \
|
||||
--js_out=import_style=commonjs,binary:${PROTO_OUTPUT} \
|
||||
--grpc_out=grpc_js:${PROTO_OUTPUT} \
|
||||
--ts_out=grpc_js:${PROTO_OUTPUT} \
|
||||
-I ${dir} ${dir}/gows.proto`;
|
||||
|
||||
try {
|
||||
execSync(command, { stdio: 'inherit' });
|
||||
console.log('gRPC files built successfully.');
|
||||
} catch (error) {
|
||||
console.error(`Failed to build gRPC files: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
// fetch
|
||||
yargs.command(
|
||||
'fetch',
|
||||
'Fetch .proto files from GitHub',
|
||||
(yargs) => {
|
||||
yargs
|
||||
.option('repo', {
|
||||
describe: 'GitHub repository (owner/repo)',
|
||||
type: 'string',
|
||||
default: DEFAULT_REPO,
|
||||
})
|
||||
.option('ref', {
|
||||
describe: 'Git reference (branch or commit SHA)',
|
||||
type: 'string',
|
||||
default: DEFAULT_REF,
|
||||
})
|
||||
.option('dir', {
|
||||
describe: 'Directory to output .proto files',
|
||||
type: 'string',
|
||||
default: DEFAULT_DIR,
|
||||
});
|
||||
},
|
||||
async (argv) => {
|
||||
await handleFetch(argv.repo, argv.ref, argv.dir);
|
||||
},
|
||||
);
|
||||
|
||||
// build
|
||||
yargs.command(
|
||||
'build',
|
||||
'Build gRPC files from .proto files',
|
||||
(yargs) => {
|
||||
yargs.option('dir', {
|
||||
describe: 'Directory containing .proto files',
|
||||
type: 'string',
|
||||
default: DEFAULT_DIR,
|
||||
});
|
||||
},
|
||||
(argv) => {
|
||||
handleBuild(argv.dir);
|
||||
},
|
||||
);
|
||||
|
||||
// Parse arguments
|
||||
yargs.parse();
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
echo "Starting WAHA..."
|
||||
|
||||
docker run -d \
|
||||
--restart=always \
|
||||
--name waha \
|
||||
-p 3000:3000/tcp \
|
||||
-v ./.sessions:/app/.sessions \
|
||||
-v ./.media:/app/.media \
|
||||
--env WHATSAPP_API_KEY=321 \
|
||||
--env WAHA_DASHBOARD_USERNAME=waha \
|
||||
--env WAHA_DASHBOARD_PASSWORD=waha \
|
||||
--env WAHA_LOG_FORMAT=JSON \
|
||||
--env WAHA_LOG_LEVEL=info \
|
||||
--env WHATSAPP_DEFAULT_ENGINE=WEBJS \
|
||||
--env WAHA_PRINT_QR=False \
|
||||
--env WHATSAPP_FILES_LIFETIME=0 \
|
||||
--env WHATSAPP_FILES_FOLDER=/app/.media \
|
||||
devlikeapro/waha-plus:latest
|
||||
|
||||
echo "WAHA started."
|
||||
@@ -1,21 +0,0 @@
|
||||
set -e
|
||||
echo "Updating WAHA..."
|
||||
echo "Logging in to Docker..."
|
||||
docker login -u devlikeapro # -p {KEY} - you can hard code key here https://portal.devlike.pro/
|
||||
|
||||
echo "Pulling the latest image..."
|
||||
docker pull devlikeapro/waha-plus
|
||||
|
||||
echo "Logging out of Docker..."
|
||||
docker logout
|
||||
|
||||
# Just pull if you're using WAHA Core
|
||||
# docker pull devlikeapro/waha
|
||||
|
||||
echo "Stopping the current container..."
|
||||
docker stop waha || true
|
||||
echo "Removing the current container..."
|
||||
docker rm waha || true
|
||||
|
||||
echo "Running WAHA..."
|
||||
sh ./waha-run.sh
|
||||
@@ -60,10 +60,7 @@ export class SwaggerConfiguratorCore {
|
||||
.addTag('🖼️ Screenshot', 'Get screenshot of WhatsApp and show QR code')
|
||||
.addTag('📤 Chatting', 'Chatting methods')
|
||||
.addTag('📢 Channels', 'Channels (newsletters) methods')
|
||||
.addTag(
|
||||
'🟢 Status',
|
||||
'Status (aka stories) methods. <b>NOWEB</b> engine only!',
|
||||
)
|
||||
.addTag('🟢 Status', 'Status (aka stories) methods')
|
||||
.addTag('💬 Chats', `Chats methods`)
|
||||
.addTag(
|
||||
'👤 Contacts',
|
||||
|
||||
@@ -32,7 +32,7 @@ export class WebsocketGatewayCore
|
||||
OnGatewayDisconnect,
|
||||
BeforeApplicationShutdown
|
||||
{
|
||||
HEARTBEAT_INTERVAL = 10_000;
|
||||
HEARTBEAT_INTERVAL = 60_000;
|
||||
|
||||
@WebSocketServer()
|
||||
server: Server;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export enum Jid {
|
||||
BROADCAST = 'status@broadcast',
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { messages } from '@waha/core/engines/gows/grpc/gows';
|
||||
import { MessageStatus } from '@waha/core/engines/gows/types';
|
||||
import { WAMessageAck } from '@waha/structures/enums.dto';
|
||||
|
||||
export function optional(value: any, type) {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
return new type({ value: value });
|
||||
}
|
||||
|
||||
export function parseJson(value: messages.Json | { data?: string }) {
|
||||
if (value instanceof messages.Json) {
|
||||
value = value.toObject();
|
||||
}
|
||||
if (value.data === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(value.data);
|
||||
}
|
||||
|
||||
export function parseJsonList(value: messages.JsonList) {
|
||||
return value.toObject().elements.map((value) => parseJson(value));
|
||||
}
|
||||
|
||||
export function statusToAck(status: MessageStatus): WAMessageAck | null {
|
||||
switch (status) {
|
||||
case MessageStatus.Error:
|
||||
return WAMessageAck.ERROR;
|
||||
case MessageStatus.Pending:
|
||||
return WAMessageAck.PENDING;
|
||||
case MessageStatus.ServerAck:
|
||||
return WAMessageAck.SERVER;
|
||||
case MessageStatus.DeliveryAck:
|
||||
return WAMessageAck.DEVICE;
|
||||
case MessageStatus.Read:
|
||||
return WAMessageAck.READ;
|
||||
case MessageStatus.Played:
|
||||
return WAMessageAck.PLAYED;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
import { isJidGroup, jidNormalizedUser } from '@adiwajshing/baileys';
|
||||
import {
|
||||
getUrlFromDirectPath,
|
||||
isJidGroup,
|
||||
isJidStatusBroadcast,
|
||||
jidNormalizedUser,
|
||||
} from '@adiwajshing/baileys';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import { connectivityState } from '@grpc/grpc-js';
|
||||
import { UnprocessableEntityException } from '@nestjs/common';
|
||||
import { WhatsappSession } from '@waha/core/abc/session.abc';
|
||||
import {
|
||||
getChannelInviteLink,
|
||||
WhatsappSession,
|
||||
} from '@waha/core/abc/session.abc';
|
||||
import { Jid } from '@waha/core/engines/const';
|
||||
import { EventsFromObservable } from '@waha/core/engines/gows/EventsFromObservable';
|
||||
import { GowsEventStreamObservable } from '@waha/core/engines/gows/GowsEventStreamObservable';
|
||||
import { messages } from '@waha/core/engines/gows/grpc/gows';
|
||||
@@ -12,9 +21,18 @@ import {
|
||||
toCusFormat,
|
||||
toJID,
|
||||
} from '@waha/core/engines/noweb/session.noweb.core';
|
||||
import { AvailableInPlusVersion } from '@waha/core/exceptions';
|
||||
import {
|
||||
AvailableInPlusVersion,
|
||||
NotImplementedByEngineError,
|
||||
} from '@waha/core/exceptions';
|
||||
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
import { QR } from '@waha/core/QR';
|
||||
import {
|
||||
Channel,
|
||||
ChannelRole,
|
||||
CreateChannelRequest,
|
||||
ListChannelsQuery,
|
||||
} from '@waha/structures/channels.dto';
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
@@ -27,6 +45,7 @@ import {
|
||||
MessageTextRequest,
|
||||
MessageVoiceRequest,
|
||||
SendSeenRequest,
|
||||
WANumberExistResult,
|
||||
} from '@waha/structures/chatting.dto';
|
||||
import {
|
||||
ACK_UNKNOWN,
|
||||
@@ -41,6 +60,7 @@ import {
|
||||
} from '@waha/structures/presence.dto';
|
||||
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
|
||||
import { MeInfo, ProxyConfig } from '@waha/structures/sessions.dto';
|
||||
import { StatusRequest, TextStatus } from '@waha/structures/status.dto';
|
||||
import { EnginePayload, WAMessageAckBody } from '@waha/structures/webhooks.dto';
|
||||
import { sleep, waitUntil } from '@waha/utils/promiseTimeout';
|
||||
import { onlyEvent } from '@waha/utils/reactive/ops/onlyEvent';
|
||||
@@ -61,11 +81,27 @@ import { promisify } from 'util';
|
||||
|
||||
import * as gows from './types';
|
||||
import MessageServiceClient = messages.MessageServiceClient;
|
||||
import {
|
||||
optional,
|
||||
parseJson,
|
||||
parseJsonList,
|
||||
statusToAck,
|
||||
} from '@waha/core/engines/gows/helpers';
|
||||
import {
|
||||
ChatSortField,
|
||||
ChatSummary,
|
||||
GetChatMessageQuery,
|
||||
GetChatMessagesFilter,
|
||||
GetChatMessagesQuery,
|
||||
} from '@waha/structures/chats.dto';
|
||||
import { ContactQuery } from '@waha/structures/contacts.dto';
|
||||
import { PaginationParams, SortOrder } from '@waha/structures/pagination.dto';
|
||||
|
||||
enum WhatsMeowEvent {
|
||||
CONNECTED = 'gows.ConnectedEventData',
|
||||
DISCONNECTED = 'events.Disconnected',
|
||||
KEEP_ALIVE_TIMEOUT = 'events.KeepAliveTimeout',
|
||||
KEEP_ALIVE_RESTORED = 'events.KeepAliveRestored',
|
||||
QR_CHANNEL_ITEM = 'whatsmeow.QRChannelItem',
|
||||
MESSAGE = 'events.Message',
|
||||
RECEIPT = 'events.Receipt',
|
||||
@@ -195,6 +231,11 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
this.status = WAHASessionStatus.STARTING;
|
||||
}
|
||||
});
|
||||
events.on(WhatsMeowEvent.KEEP_ALIVE_RESTORED, () => {
|
||||
if (this.status != WAHASessionStatus.WORKING) {
|
||||
this.status = WAHASessionStatus.WORKING;
|
||||
}
|
||||
});
|
||||
events.on(WhatsMeowEvent.QR_CHANNEL_ITEM, async (data) => {
|
||||
if (!data.Event) {
|
||||
return;
|
||||
@@ -402,11 +443,38 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
return this.messageResponse(jid, data);
|
||||
}
|
||||
|
||||
protected checkStatusRequest(request: StatusRequest) {
|
||||
if (request.contacts && request.contacts?.length > 0) {
|
||||
const msg =
|
||||
"GOWS doesn't accept 'contacts'. Remove the field to send status to all contacts.";
|
||||
throw new UnprocessableEntityException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public async sendTextStatus(status: TextStatus) {
|
||||
this.checkStatusRequest(status);
|
||||
|
||||
const message = new messages.MessageRequest({
|
||||
jid: Jid.BROADCAST,
|
||||
text: status.text,
|
||||
session: this.session,
|
||||
backgroundColor: new messages.OptionalString({
|
||||
value: status.backgroundColor,
|
||||
}),
|
||||
font: new messages.OptionalUInt32({
|
||||
value: status.font,
|
||||
}),
|
||||
});
|
||||
const response = await promisify(this.client.SendMessage)(message);
|
||||
const data = response.toObject();
|
||||
return this.messageResponse(Jid.BROADCAST, data);
|
||||
}
|
||||
|
||||
protected messageResponse(jid, data) {
|
||||
const id = buildMessageId({
|
||||
ID: data.id,
|
||||
IsFromMe: true,
|
||||
IsGroup: isJidGroup(jid),
|
||||
IsGroup: isJidGroup(jid) || isJidStatusBroadcast(jid),
|
||||
Chat: jid,
|
||||
Sender: this.me.id,
|
||||
});
|
||||
@@ -416,8 +484,20 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
};
|
||||
}
|
||||
|
||||
checkNumberStatus(request: CheckNumberStatusQuery) {
|
||||
throw new Error('Method not implemented.');
|
||||
async checkNumberStatus(
|
||||
request: CheckNumberStatusQuery,
|
||||
): Promise<WANumberExistResult> {
|
||||
const req = new messages.CheckPhonesRequest({
|
||||
session: this.session,
|
||||
phones: [request.phone],
|
||||
});
|
||||
const response = await promisify(this.client.CheckPhones)(req);
|
||||
const data = response.toObject();
|
||||
const info = data.infos[0];
|
||||
return {
|
||||
numberExists: info.registered,
|
||||
chatId: toCusFormat(info.jid),
|
||||
};
|
||||
}
|
||||
|
||||
sendLocation(request: MessageLocationRequest) {
|
||||
@@ -569,7 +649,7 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
return {
|
||||
participant: toCusFormat(data.From),
|
||||
lastKnownPresence: lastKnownPresence,
|
||||
lastSeen: parseTimestamp(data.LastSeen),
|
||||
lastSeen: parseTimestampToSeconds(data.LastSeen),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -606,6 +686,293 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Channels methods
|
||||
*/
|
||||
protected toChannel(newsletter: messages.Newsletter): Channel {
|
||||
const role: ChannelRole =
|
||||
(newsletter.role?.toUpperCase() as ChannelRole) || ChannelRole.GUEST;
|
||||
let picture = newsletter.picture;
|
||||
if (picture.startsWith('/')) {
|
||||
picture = getUrlFromDirectPath(picture);
|
||||
}
|
||||
let preview = newsletter.preview;
|
||||
if (preview.startsWith('/')) {
|
||||
preview = getUrlFromDirectPath(preview);
|
||||
}
|
||||
return {
|
||||
id: newsletter.id,
|
||||
name: newsletter.name,
|
||||
description: newsletter.description,
|
||||
invite: getChannelInviteLink(newsletter.invite),
|
||||
picture: picture,
|
||||
preview: preview,
|
||||
verified: newsletter.verified,
|
||||
role: role,
|
||||
};
|
||||
}
|
||||
|
||||
public async channelsList(query: ListChannelsQuery): Promise<Channel[]> {
|
||||
const request = new messages.NewsletterListRequest({
|
||||
session: this.session,
|
||||
});
|
||||
const response = await promisify(this.client.GetSubscribedNewsletters)(
|
||||
request,
|
||||
);
|
||||
const data = response.toObject();
|
||||
const newsletters = data.newsletters;
|
||||
let channels: Channel[] = newsletters.map(this.toChannel.bind(this));
|
||||
if (query.role) {
|
||||
// @ts-ignore
|
||||
channels = channels.filter((channel) => channel.role === query.role);
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
public async channelsCreateChannel(
|
||||
request: CreateChannelRequest,
|
||||
): Promise<Channel> {
|
||||
const req = new messages.CreateNewsletterRequest({
|
||||
session: this.session,
|
||||
name: request.name,
|
||||
description: request.description,
|
||||
});
|
||||
const response = await promisify(this.client.CreateNewsletter)(req);
|
||||
const newsletter = response.toObject() as messages.Newsletter;
|
||||
return this.toChannel(newsletter);
|
||||
}
|
||||
|
||||
public async channelsGetChannel(id: string): Promise<Channel> {
|
||||
return await this.channelsGetChannelByInviteCode(id);
|
||||
}
|
||||
|
||||
public async channelsGetChannelByInviteCode(
|
||||
inviteCode: string,
|
||||
): Promise<Channel> {
|
||||
const request = new messages.NewsletterInfoRequest({
|
||||
session: this.session,
|
||||
id: inviteCode,
|
||||
});
|
||||
const response = await promisify(this.client.GetNewsletterInfo)(request);
|
||||
const newsletter = response.toObject() as messages.Newsletter;
|
||||
return this.toChannel(newsletter);
|
||||
}
|
||||
|
||||
public channelsFollowChannel(id: string): Promise<any> {
|
||||
return this.channelsToggleFollow(id, true);
|
||||
}
|
||||
|
||||
public channelsUnfollowChannel(id: string): Promise<any> {
|
||||
return this.channelsToggleFollow(id, false);
|
||||
}
|
||||
|
||||
protected async channelsToggleFollow(id: string, follow: boolean) {
|
||||
const request = new messages.NewsletterToggleFollowRequest({
|
||||
session: this.session,
|
||||
jid: id,
|
||||
follow: follow,
|
||||
});
|
||||
const response = await promisify(this.client.NewsletterToggleFollow)(
|
||||
request,
|
||||
);
|
||||
return response.toObject();
|
||||
}
|
||||
|
||||
public channelsMuteChannel(id: string): Promise<void> {
|
||||
return this.channelsToggleMute(id, true);
|
||||
}
|
||||
|
||||
public channelsUnmuteChannel(id: string): Promise<void> {
|
||||
return this.channelsToggleMute(id, false);
|
||||
}
|
||||
|
||||
protected async channelsToggleMute(id: string, mute: boolean): Promise<any> {
|
||||
const request = new messages.NewsletterToggleMuteRequest({
|
||||
session: this.session,
|
||||
jid: id,
|
||||
mute: mute,
|
||||
});
|
||||
const response = await promisify(this.client.NewsletterToggleMute)(request);
|
||||
return response.toObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contacts methods
|
||||
*/
|
||||
|
||||
protected toWAContact(contact) {
|
||||
return {
|
||||
id: toCusFormat(contact.Jid),
|
||||
name: contact.Name,
|
||||
pushname: contact.PushName,
|
||||
};
|
||||
}
|
||||
|
||||
public async getContact(query: ContactQuery) {
|
||||
const jid = toJID(query.contactId);
|
||||
const request = new messages.EntityByIdRequest({
|
||||
session: this.session,
|
||||
id: jid,
|
||||
});
|
||||
const response = await promisify(this.client.GetContact)(request);
|
||||
const data = parseJson(response);
|
||||
return this.toWAContact(data);
|
||||
}
|
||||
|
||||
public async getContacts(pagination: PaginationParams) {
|
||||
const request = new messages.GetContactsRequest({
|
||||
session: this.session,
|
||||
pagination: new messages.Pagination({
|
||||
limit: pagination.limit,
|
||||
offset: pagination.offset,
|
||||
}),
|
||||
sortBy: new messages.SortBy({
|
||||
field: pagination.sortBy || 'id',
|
||||
order:
|
||||
pagination.sortOrder === SortOrder.DESC
|
||||
? messages.SortBy.Order.DESC
|
||||
: messages.SortBy.Order.ASC,
|
||||
}),
|
||||
});
|
||||
const response = await promisify(this.client.GetContacts)(request);
|
||||
const data = parseJsonList(response);
|
||||
return data.map(this.toWAContact.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
public async getChatsOverview(
|
||||
pagination: PaginationParams,
|
||||
): Promise<ChatSummary[]> {
|
||||
if (!pagination.sortBy) {
|
||||
pagination.sortBy = 'timestamp';
|
||||
}
|
||||
if (!pagination.sortOrder) {
|
||||
pagination.sortOrder = SortOrder.DESC;
|
||||
}
|
||||
const chats = await this.getChats(pagination);
|
||||
|
||||
const promises = [];
|
||||
for (const chat of chats) {
|
||||
promises.push(this.fetchChatSummary(chat));
|
||||
}
|
||||
const result = await Promise.all(promises);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async fetchChatSummary(chat): Promise<ChatSummary> {
|
||||
const id = toCusFormat(chat.id);
|
||||
const name = chat.name;
|
||||
const picture = await this.getContactProfilePicture(chat.id, false);
|
||||
const messages = await this.getChatMessages(
|
||||
chat.id,
|
||||
{ limit: 1, offset: 0, downloadMedia: false },
|
||||
{},
|
||||
);
|
||||
const message = messages.length > 0 ? messages[0] : null;
|
||||
return {
|
||||
id: id,
|
||||
name: name || null,
|
||||
picture: picture,
|
||||
lastMessage: message,
|
||||
_chat: chat,
|
||||
};
|
||||
}
|
||||
|
||||
protected toWAChat(chat) {
|
||||
return {
|
||||
id: toCusFormat(chat.Jid),
|
||||
name: chat.Name,
|
||||
conversationTimestamp: parseTimestampToSeconds(
|
||||
chat.ConversationTimestamp,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
public async getChats(pagination: PaginationParams) {
|
||||
if (pagination.sortBy === ChatSortField.CONVERSATION_TIMESTAMP) {
|
||||
pagination.sortBy = 'timestamp';
|
||||
}
|
||||
const request = new messages.GetChatsRequest({
|
||||
session: this.session,
|
||||
pagination: new messages.Pagination({
|
||||
limit: pagination.limit,
|
||||
offset: pagination.offset,
|
||||
}),
|
||||
sortBy: new messages.SortBy({
|
||||
field: pagination.sortBy || 'id',
|
||||
order:
|
||||
pagination.sortOrder === SortOrder.DESC
|
||||
? messages.SortBy.Order.DESC
|
||||
: messages.SortBy.Order.ASC,
|
||||
}),
|
||||
});
|
||||
const response = await promisify(this.client.GetChats)(request);
|
||||
const data = parseJsonList(response);
|
||||
return data.map(this.toWAChat.bind(this));
|
||||
}
|
||||
|
||||
public async getChatMessages(
|
||||
chatId: string,
|
||||
query: GetChatMessagesQuery,
|
||||
filter: GetChatMessagesFilter,
|
||||
) {
|
||||
const downloadMedia = query.downloadMedia;
|
||||
let jid: messages.OptionalString;
|
||||
if (chatId === 'all') {
|
||||
jid = null;
|
||||
} else {
|
||||
jid = new messages.OptionalString({
|
||||
value: toJID(this.ensureSuffix(chatId)),
|
||||
});
|
||||
}
|
||||
|
||||
const request = new messages.GetMessagesRequest({
|
||||
session: this.session,
|
||||
filters: new messages.MessageFilters({
|
||||
jid: jid,
|
||||
timestampGte: optional(
|
||||
filter['filter.timestamp.gte'],
|
||||
messages.OptionalUInt64,
|
||||
),
|
||||
timestampLte: optional(
|
||||
filter['filter.timestamp.lte'],
|
||||
messages.OptionalUInt64,
|
||||
),
|
||||
fromMe: optional(filter['filter.fromMe'], messages.OptionalBool),
|
||||
}),
|
||||
pagination: new messages.Pagination({
|
||||
limit: query.limit,
|
||||
offset: query.offset,
|
||||
}),
|
||||
});
|
||||
const response = await promisify(this.client.GetMessages)(request);
|
||||
const msgs = parseJsonList(response);
|
||||
const promises = [];
|
||||
for (const msg of msgs) {
|
||||
promises.push(this.processIncomingMessage(msg, downloadMedia));
|
||||
}
|
||||
let result = await Promise.all(promises);
|
||||
result = result.filter(Boolean);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async getChatMessage(
|
||||
chatId: string,
|
||||
messageId: string,
|
||||
query: GetChatMessageQuery,
|
||||
): Promise<null | WAMessage> {
|
||||
const key = parseMessageIdSerialized(messageId, true);
|
||||
const request = new messages.EntityByIdRequest({
|
||||
session: this.session,
|
||||
id: key.id,
|
||||
});
|
||||
const response = await promisify(this.client.GetMessageById)(request);
|
||||
const msg = parseJson(response);
|
||||
return this.processIncomingMessage(msg, query.downloadMedia);
|
||||
}
|
||||
|
||||
//
|
||||
// END - Methods for API
|
||||
//
|
||||
@@ -642,11 +1009,17 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
const id = buildMessageId(message);
|
||||
const body = this.extractBody(message.Message);
|
||||
const replyTo = null; // TODO: this.extractReplyTo(message.message);
|
||||
const ack = null; // TODO: Extract
|
||||
|
||||
let ack;
|
||||
if (message.Status) {
|
||||
ack = statusToAck(message.Status);
|
||||
} else {
|
||||
ack = message.Info.IsFromMe ? WAMessageAck.SERVER : WAMessageAck.DEVICE;
|
||||
}
|
||||
|
||||
return {
|
||||
id: id,
|
||||
timestamp: parseTimestamp(message.Info.Timestamp),
|
||||
timestamp: parseTimestampToSeconds(message.Info.Timestamp),
|
||||
from: toCusFormat(fromToParticipant.from),
|
||||
fromMe: message.Info.IsFromMe,
|
||||
body: body,
|
||||
@@ -773,7 +1146,7 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
const messageId = this.buildMessageIdFromKey(reactionMessage.key);
|
||||
const reaction: WAMessageReaction = {
|
||||
id: id,
|
||||
timestamp: parseTimestamp(message.Info.Timestamp),
|
||||
timestamp: parseTimestampToSeconds(message.Info.Timestamp),
|
||||
from: toCusFormat(fromToParticipant.from),
|
||||
fromMe: message.Info.IsFromMe,
|
||||
to: toCusFormat(fromToParticipant.to),
|
||||
@@ -894,3 +1267,11 @@ function parseTimestamp(timestamp: string): number {
|
||||
// "2024-12-25T14:28:42+03:00" => 1234567890
|
||||
return new Date(timestamp).getTime();
|
||||
}
|
||||
|
||||
function parseTimestampToSeconds(timestamp: string): number {
|
||||
const ms = parseTimestamp(timestamp);
|
||||
if (!ms) {
|
||||
return ms;
|
||||
}
|
||||
return Math.floor(ms / 1000);
|
||||
}
|
||||
@@ -22,3 +22,20 @@ export interface ChatPresence {
|
||||
State: ChatPresenceState;
|
||||
Media: ChatPresenceMedia;
|
||||
}
|
||||
|
||||
/**
|
||||
* StatusError Status = 0
|
||||
* StatusPending Status = 1
|
||||
* StatusServerAck Status = 2
|
||||
* StatusDeliveryAck Status = 3
|
||||
* StatusRead Status = 4
|
||||
* StatusPlayed Status = 5
|
||||
*/
|
||||
export enum MessageStatus {
|
||||
Error = 0,
|
||||
Pending = 1,
|
||||
ServerAck = 2,
|
||||
DeliveryAck = 3,
|
||||
Read = 4,
|
||||
Played = 5,
|
||||
}
|
||||
@@ -1054,7 +1054,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
* Status methods
|
||||
*/
|
||||
protected checkStatusRequest(request: StatusRequest) {
|
||||
if (request.contacts?.length > 0) {
|
||||
if (request.contacts && request.contacts?.length > 0) {
|
||||
const msg =
|
||||
"WEBJS doesn't accept 'contacts'. Remove the field to send status to all contacts.";
|
||||
throw new UnprocessableEntityException(msg);
|
||||
|
||||
@@ -22,7 +22,7 @@ export class WebsocketHeartbeatJob {
|
||||
this.logger.debug(
|
||||
`Terminating client connection due to heartbeat timeout, ${client.id}`,
|
||||
);
|
||||
return client.terminate();
|
||||
client.terminate();
|
||||
}
|
||||
|
||||
client.isAlive = false;
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface StatusRequest {
|
||||
export class TextStatus {
|
||||
text: string = 'Have a look! https://github.com/';
|
||||
backgroundColor: string = '#38b42f';
|
||||
font: number = 1;
|
||||
font: number = 0;
|
||||
|
||||
@ContactsProperty
|
||||
contacts?: string[];
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ export function getEngineName(): string {
|
||||
}
|
||||
|
||||
export const VERSION: WAHAEnvironment = {
|
||||
version: '2025.1.4',
|
||||
version: '2025.2.1',
|
||||
engine: getEngineName(),
|
||||
tier: getWAHAVersion(),
|
||||
browser: getBrowserExecutablePath(),
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const axios = require('axios');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const yargs = require('yargs/yargs');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
|
||||
// Parse CLI arguments
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.option('number', {
|
||||
alias: 'n',
|
||||
type: 'number',
|
||||
description: 'Number of messages to send',
|
||||
default: 10,
|
||||
})
|
||||
.option('chat-id', {
|
||||
alias: 'to',
|
||||
type: 'number',
|
||||
description: 'Chat ID to send messages to',
|
||||
demandOption: true,
|
||||
})
|
||||
.option('session', {
|
||||
type: 'string',
|
||||
description: 'Session ID to use',
|
||||
demandOption: true,
|
||||
})
|
||||
.option('api-key', {
|
||||
alias: 'k',
|
||||
type: 'string',
|
||||
description: 'API key for authentication',
|
||||
demandOption: true,
|
||||
})
|
||||
.help().argv;
|
||||
|
||||
const sendTextMessage = async (session, numMessages, chatId, apiKey) => {
|
||||
const url = 'http://localhost:3000/api/sendText/';
|
||||
for (let i = 1; i <= numMessages; i++) {
|
||||
console.log(`Sending message ${i}`);
|
||||
const response = await axios.post(
|
||||
url,
|
||||
{
|
||||
chatId: chatId.toString(),
|
||||
session: session,
|
||||
text: `Message - ${i}`,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'X-Api-Key': apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
console.log(`Message ${i} sent successfully:`, response.data);
|
||||
}
|
||||
};
|
||||
|
||||
// Run the script
|
||||
sendTextMessage(argv.session, argv.number, argv['chat-id'], argv['api-key']);
|
||||
@@ -0,0 +1,56 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const axios = require('axios');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const yargs = require('yargs/yargs');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
|
||||
// Parse CLI arguments
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.option('sessions', {
|
||||
alias: 'n',
|
||||
type: 'number',
|
||||
description: 'Number of sessions to create',
|
||||
default: 10,
|
||||
})
|
||||
.option('api-key', {
|
||||
alias: 'k',
|
||||
type: 'string',
|
||||
description: 'API key for authentication',
|
||||
demandOption: true,
|
||||
})
|
||||
.help().argv;
|
||||
|
||||
const createSessions = async (numSessions, apiKey) => {
|
||||
const url = 'http://localhost:3000/api/sessions/';
|
||||
|
||||
for (let i = 1; i <= numSessions; i++) {
|
||||
try {
|
||||
console.log(`Creating session ${i}`);
|
||||
const response = await axios.post(
|
||||
url,
|
||||
{
|
||||
name: '',
|
||||
config: {
|
||||
metadata: {},
|
||||
webhooks: [],
|
||||
},
|
||||
start: true,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'X-Api-Key': apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
console.log(`Session ${i} created successfully:`, response.data);
|
||||
} catch (error) {
|
||||
console.error(`Error creating session ${i}:`, error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Run the script
|
||||
createSessions(argv.sessions, argv['api-key']);
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts", "scripts/*.js"]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"waha": {
|
||||
"gows": {
|
||||
"repo": "devlikeapro/gows",
|
||||
"ref": "4b11c1d58018bc4b5028de51aa1bc7da9c2d9103"
|
||||
},
|
||||
"dashboard": {
|
||||
"repo": "devlikeapro/dashboard",
|
||||
"ref": "8c455ec6436398000a26df2a853a1d7dbe8567df"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,13 @@ __metadata:
|
||||
version: 6
|
||||
cacheKey: 8
|
||||
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-678":
|
||||
version: 6.7.8
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=04738f528321857efe837e3f93c73059878ecdcb"
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-6712":
|
||||
version: 6.7.12
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=18359f20a3c34166665ad8b62000347ce0c4592e"
|
||||
dependencies:
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@hapi/boom": ^9.1.3
|
||||
"@whiskeysockets/eslint-config": "github:whiskeysockets/eslint-config"
|
||||
async-lock: ^1.4.1
|
||||
audio-decode: ^2.1.3
|
||||
axios: ^1.6.0
|
||||
@@ -39,7 +40,7 @@ __metadata:
|
||||
optional: true
|
||||
sharp:
|
||||
optional: true
|
||||
checksum: 0f7b2031eeb25137c65aee3151028f7a8637cfed0763c7426817415ec818ca71f55267b9de88511905bd266f4006301a26206dac9bdb1821d13f1a0cbf075e32
|
||||
checksum: 53c939b9b2d47cb00db73e6cb04633fdd62c69dce6e5d830c3e18e09c90bceb0425c9c59ac58bfdeabce501091ca895132b035877243dfaf90f2297c99eb8fef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1242,6 +1243,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint-community/eslint-utils@npm:^4.4.0":
|
||||
version: 4.4.1
|
||||
resolution: "@eslint-community/eslint-utils@npm:4.4.1"
|
||||
dependencies:
|
||||
eslint-visitor-keys: ^3.4.3
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
checksum: a7ffc838eb6a9ef594cda348458ccf38f34439ac77dc090fa1c120024bcd4eb911dfd74d5ef44d42063e7949fa7c5123ce714a015c4abb917d4124be1bd32bfe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint-community/regexpp@npm:^4.10.0":
|
||||
version: 4.12.1
|
||||
resolution: "@eslint-community/regexpp@npm:4.12.1"
|
||||
checksum: 0d628680e204bc316d545b4993d3658427ca404ae646ce541fcc65306b8c712c340e5e573e30fb9f85f4855c0c5f6dca9868931f2fcced06417fbe1a0c6cd2d6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grpc/grpc-js@npm:^1.12.4":
|
||||
version: 1.12.4
|
||||
resolution: "@grpc/grpc-js@npm:1.12.4"
|
||||
@@ -3453,6 +3472,29 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:^7.15.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": ^4.10.0
|
||||
"@typescript-eslint/scope-manager": 7.18.0
|
||||
"@typescript-eslint/type-utils": 7.18.0
|
||||
"@typescript-eslint/utils": 7.18.0
|
||||
"@typescript-eslint/visitor-keys": 7.18.0
|
||||
graphemer: ^1.4.0
|
||||
ignore: ^5.3.1
|
||||
natural-compare: ^1.4.0
|
||||
ts-api-utils: ^1.3.0
|
||||
peerDependencies:
|
||||
"@typescript-eslint/parser": ^7.0.0
|
||||
eslint: ^8.56.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: dfcf150628ca2d4ccdfc20b46b0eae075c2f16ef5e70d9d2f0d746acf4c69a09f962b93befee01a529f14bbeb3e817b5aba287d7dd0edc23396bc5ed1f448c3d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/experimental-utils@npm:3.9.1":
|
||||
version: 3.9.1
|
||||
resolution: "@typescript-eslint/experimental-utils@npm:3.9.1"
|
||||
@@ -3486,6 +3528,51 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:^7.15.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/parser@npm:7.18.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": 7.18.0
|
||||
"@typescript-eslint/types": 7.18.0
|
||||
"@typescript-eslint/typescript-estree": 7.18.0
|
||||
"@typescript-eslint/visitor-keys": 7.18.0
|
||||
debug: ^4.3.4
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 132b56ac3b2d90b588d61d005a70f6af322860974225b60201cbf45abf7304d67b7d8a6f0ade1c188ac4e339884e78d6dcd450417f1481998f9ddd155bab0801
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/scope-manager@npm:7.18.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 7.18.0
|
||||
"@typescript-eslint/visitor-keys": 7.18.0
|
||||
checksum: b982c6ac13d8c86bb3b949c6b4e465f3f60557c2ccf4cc229799827d462df56b9e4d3eaed7711d79b875422fc3d71ec1ebcb5195db72134d07c619e3c5506b57
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/type-utils@npm:7.18.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": 7.18.0
|
||||
"@typescript-eslint/utils": 7.18.0
|
||||
debug: ^4.3.4
|
||||
ts-api-utils: ^1.3.0
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 68fd5df5146c1a08cde20d59b4b919acab06a1b06194fe4f7ba1b928674880249890785fbbc97394142f2ef5cff5a7fba9b8a940449e7d5605306505348e38bc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:3.9.1":
|
||||
version: 3.9.1
|
||||
resolution: "@typescript-eslint/types@npm:3.9.1"
|
||||
@@ -3493,6 +3580,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/types@npm:7.18.0"
|
||||
checksum: 7df2750cd146a0acd2d843208d69f153b458e024bbe12aab9e441ad2c56f47de3ddfeb329c4d1ea0079e2577fea4b8c1c1ce15315a8d49044586b04fedfe7a4d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:3.9.1":
|
||||
version: 3.9.1
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:3.9.1"
|
||||
@@ -3512,6 +3606,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:7.18.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 7.18.0
|
||||
"@typescript-eslint/visitor-keys": 7.18.0
|
||||
debug: ^4.3.4
|
||||
globby: ^11.1.0
|
||||
is-glob: ^4.0.3
|
||||
minimatch: ^9.0.4
|
||||
semver: ^7.6.0
|
||||
ts-api-utils: ^1.3.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: c82d22ec9654973944f779eb4eb94c52f4a6eafaccce2f0231ff7757313f3a0d0256c3252f6dfe6d43f57171d09656478acb49a629a9d0c193fb959bc3f36116
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/utils@npm:7.18.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": ^4.4.0
|
||||
"@typescript-eslint/scope-manager": 7.18.0
|
||||
"@typescript-eslint/types": 7.18.0
|
||||
"@typescript-eslint/typescript-estree": 7.18.0
|
||||
peerDependencies:
|
||||
eslint: ^8.56.0
|
||||
checksum: 751dbc816dab8454b7dc6b26a56671dbec08e3f4ef94c2661ce1c0fc48fa2d05a64e03efe24cba2c22d03ba943cd3c5c7a5e1b7b03bbb446728aec1c640bd767
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:3.9.1":
|
||||
version: 3.9.1
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:3.9.1"
|
||||
@@ -3521,6 +3648,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:7.18.0":
|
||||
version: 7.18.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:7.18.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 7.18.0
|
||||
eslint-visitor-keys: ^3.4.3
|
||||
checksum: 6e806a7cdb424c5498ea187a5a11d0fef7e4602a631be413e7d521e5aec1ab46ba00c76cfb18020adaa0a8c9802354a163bfa0deb74baa7d555526c7517bb158
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@wasm-audio-decoders/common@npm:9.0.4":
|
||||
version: 9.0.4
|
||||
resolution: "@wasm-audio-decoders/common@npm:9.0.4"
|
||||
@@ -3711,6 +3848,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@whiskeysockets/eslint-config@github:whiskeysockets/eslint-config":
|
||||
version: 1.0.0
|
||||
resolution: "@whiskeysockets/eslint-config@https://github.com/whiskeysockets/eslint-config.git#commit=326b55f2842668f4e11f471451c4e39819a0e1bf"
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin": ^7.15.0
|
||||
"@typescript-eslint/parser": ^7.15.0
|
||||
eslint-plugin-simple-import-sort: ^12.1.1
|
||||
peerDependencies:
|
||||
eslint: "*"
|
||||
typescript: ">=4"
|
||||
checksum: a1ae2c83b0b635cf4898b51a597cd9cabc0df3f5bd4f439a705a1f35877802e8f07836f3298d02b5543d41e07c266b348bd8c8458f83ed225d975e89618b0483
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@xtuc/ieee754@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@xtuc/ieee754@npm:1.2.0"
|
||||
@@ -6236,6 +6387,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-simple-import-sort@npm:^12.1.1":
|
||||
version: 12.1.1
|
||||
resolution: "eslint-plugin-simple-import-sort@npm:12.1.1"
|
||||
peerDependencies:
|
||||
eslint: ">=5.0.0"
|
||||
checksum: 6d73e43ecf6221c1952e0cc820e6867e3e1fe973575e23d438d1d3de52284ceb2a01d31e20a76de11feb158bbba98f113150a676cc5526a8b3a5844d63ca37f8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.0.0, eslint-scope@npm:^5.1.0":
|
||||
version: 5.1.1
|
||||
resolution: "eslint-scope@npm:5.1.1"
|
||||
@@ -6262,6 +6422,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-visitor-keys@npm:^3.4.3":
|
||||
version: 3.4.3
|
||||
resolution: "eslint-visitor-keys@npm:3.4.3"
|
||||
checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint@npm:7.7.0":
|
||||
version: 7.7.0
|
||||
resolution: "eslint@npm:7.7.0"
|
||||
@@ -7174,7 +7341,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"globby@npm:^11.0.1":
|
||||
"globby@npm:^11.0.1, globby@npm:^11.1.0":
|
||||
version: 11.1.0
|
||||
resolution: "globby@npm:11.1.0"
|
||||
dependencies:
|
||||
@@ -7211,6 +7378,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"graphemer@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "graphemer@npm:1.4.0"
|
||||
checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"grpc-tools@npm:^1.12.4":
|
||||
version: 1.12.4
|
||||
resolution: "grpc-tools@npm:1.12.4"
|
||||
@@ -7440,6 +7614,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ignore@npm:^5.3.1":
|
||||
version: 5.3.2
|
||||
resolution: "ignore@npm:5.3.2"
|
||||
checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0":
|
||||
version: 3.3.0
|
||||
resolution: "import-fresh@npm:3.3.0"
|
||||
@@ -12050,6 +12231,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-api-utils@npm:^1.3.0":
|
||||
version: 1.4.3
|
||||
resolution: "ts-api-utils@npm:1.4.3"
|
||||
peerDependencies:
|
||||
typescript: ">=4.2.0"
|
||||
checksum: ea00dee382d19066b2a3d8929f1089888b05fec797e32e7a7004938eda1dccf2e77274ee2afcd4166f53fab9b8d7ee90ebb225a3183f9ba8817d636f688a148d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-jest@npm:^29.1.3":
|
||||
version: 29.1.5
|
||||
resolution: "ts-jest@npm:29.1.5"
|
||||
@@ -12559,7 +12749,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "waha@workspace:."
|
||||
dependencies:
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-channels-678"
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-channels-6712"
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@aws-sdk/client-s3": ^3.633.0
|
||||
"@aws-sdk/s3-request-presigner": ^3.633.0
|
||||
@@ -12646,6 +12836,7 @@ __metadata:
|
||||
ulid: ^2.3.0
|
||||
whatsapp-web.js: "github:devlikeapro/whatsapp-web.js#fork-main-channels"
|
||||
write-file-atomic: ^6.0.0
|
||||
yargs: ^17.7.2
|
||||
dependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
@@ -12740,7 +12931,7 @@ __metadata:
|
||||
|
||||
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-channels":
|
||||
version: 1.26.0
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=a8683b0d1a5b8025ac1e7deb3476042ceadb4c07"
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=5b4dd6dec206905e3aaa7b0461d7c6d4cc3126a8"
|
||||
dependencies:
|
||||
"@pedroslopez/moduleraid": ^5.0.2
|
||||
archiver: ^5.3.1
|
||||
@@ -12758,7 +12949,7 @@ __metadata:
|
||||
optional: true
|
||||
unzipper:
|
||||
optional: true
|
||||
checksum: 637e53dffdaa80813a5cdd72e519f8f68978e00db17b39b471f39c8e2b98bc85643fe74168255a1dfdc655c71803e3d01b4ca6635bc6159c429dd59232ac07d4
|
||||
checksum: 441e54f450ed9ea5d5756c1ca4fd592e498ad79247d2c6508aee2a5c1b2608a9eb3f6360234f2f0ce563edb187a3d453d41773e745da9bebf657f575b9fa66b4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in new issue
Block a user