Compare commits

..
28 Commits
Author SHA1 Message Date
devlikepro 86ca08b9aa [core] 2024.8.1
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-04 10:22:16 +07:00
devlikepro 9522df7835 [core] Bump dashboard 2024-08-04 10:22:16 +07:00
devlikepro 55e0fd0226 [core] rename .removed to .deleted 2024-08-04 10:22:16 +07:00
devlikepro ff9a986a2e [core] Fix for chat id in labels events 2024-08-04 10:09:44 +07:00
devlikepro df31fe2a8b [core] NOWEB labels 2024-08-04 10:09:32 +07:00
devlikepro 1aeaf996bc [core] make up-engine commands 2024-08-04 10:09:32 +07:00
devlikepro cb0e59e91a [core] Print original error, not pino one 2024-08-04 10:09:32 +07:00
devlikepro 5f02f49e9d [core] Add other /labels endpoints 2024-08-04 10:09:32 +07:00
devlikepro ce9f91fe2c [core] Use /api/{session}/labels 2024-08-04 10:09:32 +07:00
devlikepro ac37745721 [core] Add type 2024-08-04 10:09:31 +07:00
aziz e44aeefda8 [core] chore: Add LabelsController to handle label-related API requests 2024-08-04 10:08:58 +07:00
devlikepro dbff2b659a [core] Fix swagger docs 2024-08-04 10:07:09 +07:00
devlikepro 52ef8e8b76 [core] Add /ping 2024-08-04 10:07:08 +07:00
devlikepro b71567c754 [core] exclude path from api-key
fixes #451
2024-08-04 10:07:08 +07:00
devlikepro d1670c743f [core] Add "sessions.name" index for MongoDB
closes #447
2024-08-04 10:06:43 +07:00
devlikepro 009b38f471 [core] Add call.* events
closes #307
2024-08-04 10:06:43 +07:00
devlikepro 0cf5f30c0d [core] Add timestamp to chat.archive 2024-08-04 10:06:42 +07:00
devlikepro cd4e1f179d [core] Add chat.archive event
closes #434
2024-08-04 10:06:42 +07:00
devlikepro b89f9d6b35 [core] Add chats /archive and /unarchive
fixes #434
2024-08-04 10:06:42 +07:00
devlikepro c3ece96390 [core] Remove html 2024-08-02 09:05:31 +07:00
devlikepro 770739b44e [core] Add pdf example 2024-08-01 13:44:37 +07:00
devlikepro 84984c2cde [core] Up chrome version 2024-07-31 17:10:19 +07:00
devlikepro 86393c8674 [core] 2024.7.7
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-24 19:02:03 +03:00
devlikepro d4aed3bc45 [core] pin adm-zip 0.5.10
trying to work on #457
2024-07-24 19:01:44 +03:00
devlikepro 818cd77450 [core] key 2024-07-23 10:37:37 +03:00
devlikepro dc26c70400 [core] waha-run 2024-07-23 10:28:52 +03:00
devlikepro 6547d713ea [core] remove version from docker 2024-07-23 10:03:41 +03:00
devlikepro e8dcb0c242 [core] Add full docker-compose.yaml 2024-07-23 09:46:47 +03:00
44 changed files with 1271 additions and 712 deletions

No files matched your search

+2 -2
View File
@@ -24,7 +24,7 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
FROM node:${NODE_VERSION} as dashboard
# Download WAHA Dashboard
ENV WAHA_DASHBOARD_SHA 7bfa9269fd385af687a464882637881dfd34cfb6
ENV WAHA_DASHBOARD_SHA 63fd6e9e23e90f90e8aa0de04feb3f1909f63021
RUN \
wget https://github.com/devlikeapro/dashboard/archive/${WAHA_DASHBOARD_SHA}.zip \
&& unzip ${WAHA_DASHBOARD_SHA}.zip -d /tmp/dashboard \
@@ -68,7 +68,7 @@ RUN if [ "$USE_BROWSER" = "chromium" ]; then \
# Install Chrome
# Available versions:
# https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable
ARG CHROME_VERSION="122.0.6261.128-1"
ARG CHROME_VERSION="126.0.6478.182-1"
RUN if [ "$USE_BROWSER" = "chrome" ]; then \
wget --no-verbose -O /tmp/chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
&& apt-get update \
+4 -3
View File
@@ -31,10 +31,11 @@ push:
for-swagger:
WHATSAPP_SWAGGER_CONFIG_ADVANCED=true . ${NVM_DIR}/nvm.sh && nvm exec yarn start
update-dependencies:
. ${NVM_DIR}/nvm.sh && nvm exec yarn up whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-webpack-exodus-channels
up-noweb:
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels
. ${NVM_DIR}/nvm.sh && nvm exec yarn up venom-bot
up-webjs:
. ${NVM_DIR}/nvm.sh && nvm exec yarn up whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-webpack-exodus-channels
start-proxy:
docker run --rm -d --name squid-container -e TZ=UTC -p 3128:3128 ubuntu/squid:5.2-22.04_beta
+114
View File
@@ -0,0 +1,114 @@
services:
waha:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha
container_name: waha
ports:
- '3000:3000/tcp'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# https://docs.webhook.site/
- WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
- WHATSAPP_HOOK_EVENTS=message
- WHATSAPP_DEFAULT_ENGINE=WEBJS
restart: always
waha-plus:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus
ports:
- '3000:3000/tcp'
volumes:
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_HOSTNAME=localhost
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_API_KEY=321
# Username and password for Swagger
- WHATSAPP_SWAGGER_USERNAME=swagger
- WHATSAPP_SWAGGER_PASSWORD=admin
# Username and password for WAHA Dashboard
# you can use the same username and password for both Swagger and Dashboard
# Default - waha / waha
- WAHA_DASHBOARD_USERNAME=waha
- WAHA_DASHBOARD_PASSWORD=waha
# Engine specific environment variables
# - WAHA_WEBJS_WEB_VERSION=2.2412.54-videofix
restart: always
waha-plus--mongodb:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus--mongodb
ports:
- '3000:3000/tcp'
volumes:
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_KEY=321
# - WHATSAPP_SWAGGER_USERNAME=admin
# - WHATSAPP_SWAGGER_PASSWORD=123
# - WAHA_DASHBOARD_USERNAME=admin
# - WAHA_DASHBOARD_PASSWORD=123
# - WHATSAPP_API_HOSTNAME=localhost
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
restart: always
# Let's Encrypt + Certbot
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--certbot:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- '/etc/letsencrypt:/etc/letsencrypt'
environment:
- DOMAIN=waha.example.pro
- WHATSAPP_API_HOSTNAME=${DOMAIN}
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem
- WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/${DOMAIN}/cert.pem
- WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/${DOMAIN}/chain.pem
# Self-signed certificates example
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--self-signed:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- './.secrets:/app/.secrets'
environment:
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=.secrets/privkey.pem
- WAHA_HTTPS_PATH_CERT=.secrets/cert.pem
- WAHA_HTTPS_PATH_CA=.secrets/chain.pem
mongodb:
image: mongo
container_name: mongodb
ports:
- '27017:27017/tcp'
volumes:
- mongodb_data:/data/db
restart: always
volumes:
mongodb_data: {}
+184 -96
View File
@@ -1,115 +1,203 @@
version: '3'
#
# https://waha.devlike.pro/docs/how-to/install/
# Here's we provide a simple example of how to install WAHA using Docker Compose.
#
# We're assuming you have Docker and Docker Compose installed.
# If you don't have Docker Compose installed, you can follow the official guide:
# https://docs.docker.com/compose/install/
#
services:
waha:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha
container_name: waha
ports:
- '3000:3000/tcp'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# https://docs.webhook.site/
- WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
- WHATSAPP_HOOK_EVENTS=message
- WHATSAPP_DEFAULT_ENGINE=WEBJS
# Always restart the container on failure
restart: always
waha-plus:
# Check available Docker images:
#
# Image
#
image: devlikeapro/waha-plus:latest # or devlikeapro/waha:latest if you're using WAHA Core
#
# We strongly recommend using the pinned version of WAHA
# https://waha.devlike.pro/docs/how-to/engines/#versions
# image: devlikeapro/waha-plus:latest-2024.7.6 # 'latest' is not mistaken here
#
# Multiple images are available
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus
# image: devlikeapro/waha-plus:chrome
#
# The first port can be any free port you want
# The second port must be the same as WHATSAPP_API_PORT or 3000 by default
# Consider using the same port for simplicity
ports:
- '3000:3000/tcp'
# NOTE: if you're using HTTP, you can use the following port mapping
#- '80:3000/tcp'
# NOTE: if you're using HTTPS, you can use the following port mapping
#- '443:3000/tcp'
volumes:
# Store sessions in the .sessions folder (comment it if you're using MongoDB)
# Doesn't work with WAHA Core
- './.sessions:/app/.sessions'
# https://waha.devlike.pro/docs/how-to/storages/#save-media-files-between-the-container-restarts
- './.media:/app/.media'
# If you're using certbot for HTTPS, you can use the following volume mapping
# https://waha.devlike.pro/blog/setting-up-https-for-waha/#lets-encrypt-certbot--waha
# - '/etc/letsencrypt:/etc/letsencrypt'
# WAHA Configuration
# https://waha.devlike.pro/docs/how-to/config/
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_HOSTNAME=localhost
- WHATSAPP_DEFAULT_ENGINE=WEBJS
#
# Common
#
# If you know the right URL, you can use it here.
# Use any port in WHATSAPP_API_PORT and domain in WHATSAPP_API_HOSTNAME
# https://waha.devlike.pro/docs/how-to/config/#common
#- WHATSAPP_API_PORT=3000
#- WHATSAPP_API_HOSTNAME=localhost
#
# Security
#
# https://waha.devlike.pro/docs/how-to/security/
#
- WHATSAPP_API_KEY=321
# Username and password for Swagger
- WHATSAPP_SWAGGER_USERNAME=swagger
- WHATSAPP_SWAGGER_PASSWORD=admin
# Username and password for WAHA Dashboard
# you can use the same username and password for both Swagger and Dashboard
# Default - waha / waha
- WAHA_DASHBOARD_USERNAME=waha
- WAHA_DASHBOARD_PASSWORD=waha
# Engine specific environment variables
# - WAHA_WEBJS_WEB_VERSION=2.2412.54-videofix
restart: always
#- WHATSAPP_SWAGGER_USERNAME=admin
#- WHATSAPP_SWAGGER_PASSWORD=admin
waha-plus--mongodb:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus--mongodb
ports:
- '3000:3000/tcp'
volumes:
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_KEY=321
# - WHATSAPP_SWAGGER_USERNAME=admin
# - WHATSAPP_SWAGGER_PASSWORD=123
# - WAHA_DASHBOARD_USERNAME=admin
# - WAHA_DASHBOARD_PASSWORD=123
# - WHATSAPP_API_HOSTNAME=localhost
#
# Dashboard
#
# https://waha.devlike.pro/docs/how-to/waha-dashboard/#configuration
# Enabled by default
#- WAHA_DASHBOARD_ENABLED=true
#- WAHA_DASHBOARD_USERNAME=waha
#- WAHA_DASHBOARD_PASSWORD=waha
#
# Logging
# https://waha.devlike.pro/docs/how-to/observability/#logging
#
- WAHA_LOG_FORMAT=PRETTY
# Set log format to JSON if you consume logs with log management systems
#- WAHA_LOG_FORMAT=JSON
- WAHA_LOG_LEVEL=info
# If you want to see more logs, you can set the log level to debug
#- WAHA_LOG_LEVEL=debug
# DEBUG=1 # shortcut for setting log level to debug
#
# Engine
#
# Choose the right engine for your needs (WEBJS by default)
# https://waha.devlike.pro/docs/how-to/engines/
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
restart: always
# Use NOWEB engine for the fastest performance
#- WHATSAPP_DEFAULT_ENGINE=NOWEB
# Let's Encrypt + Certbot
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--certbot:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- '/etc/letsencrypt:/etc/letsencrypt'
environment:
- DOMAIN=waha.example.pro
- WHATSAPP_API_HOSTNAME=${DOMAIN}
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem
- WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/${DOMAIN}/cert.pem
- WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/${DOMAIN}/chain.pem
#
# Sessions
#
# https://waha.devlike.pro/docs/how-to/config/#sessions
# Restart all sessions when container starts
- WHATSAPP_RESTART_ALL_SESSIONS=True
# Do not print QR codes in logs
- WAHA_PRINT_QR=False
#
# OR you can specify sessions by name, if you have handful amount of sessions
#- WHATSAPP_START_SESSION=session1,session2
# Do not use both WHATSAPP_RESTART_ALL_SESSIONS and WHATSAPP_START_SESSION parameters
#
# Self-signed certificates example
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--self-signed:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- './.secrets:/app/.secrets'
environment:
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=.secrets/privkey.pem
- WAHA_HTTPS_PATH_CERT=.secrets/cert.pem
- WAHA_HTTPS_PATH_CA=.secrets/chain.pem
#
# Swagger
#
# https://waha.devlike.pro/docs/how-to/swagger/
#- WHATSAPP_SWAGGER_USERNAME=admin
#- WHATSAPP_SWAGGER_PASSWORD=admin
# Disable Swagger
#- WHATSAPP_SWAGGER_ENABLED=false
# Enable advanced Swagger configuration
#- WHATSAPP_SWAGGER_CONFIG_ADVANCED=true
#
# Swagger White Label customization
# https://waha.devlike.pro/docs/how-to/swagger/#white-label
#- WHATSAPP_SWAGGER_TITLE=WAHA API
#
mongodb:
image: mongo
container_name: mongodb
ports:
- '27017:27017/tcp'
volumes:
- mongodb_data:/data/db
restart: always
#
# Global Proxy Settings
# https://waha.devlike.pro/docs/how-to/config/#global-proxy-configuration
# You can also set proxy settings for each session later when starting it
# https://waha.devlike.pro/docs/how-to/sessions/#configure-proxy
#- WHATSAPP_PROXY_SERVER=proxy.example.com:3128
#-WHATSAPP_PROXY_SERVER_USERNAME=user
#-WHATSAPP_PROXY_SERVER_PASSWORD=pass
#
volumes:
mongodb_data: {}
#
# HTTPS Configuration
#
# https://waha.devlike.pro/docs/how-to/config/#https
# Consider using certbot for HTTPS
# https://waha.devlike.pro/blog/setting-up-https-for-waha/#lets-encrypt-certbot--waha
#- WHATSAPP_API_HOSTNAME=waha.example.pro
#- WAHA_HTTPS_ENABLED=true
#- WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/waha.example.pro/privkey.pem
#- WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/waha.example.pro/cert.pem \
#- WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/waha.example.pro/chain.pem
#
#
# Media Configuration
#
# https://waha.devlike.pro/docs/how-to/config/#files
#
# Disable media (images, videos, files) download for incoming messages
#- WHATSAPP_DOWNLOAD_MEDIA=false
#
# Download only specific media types
#- WHATSAPP_FILES_MIMETYPES=image/jpeg,image/png
#
# Set to 0 to keep media files forever
# https://waha.devlike.pro/docs/how-to/storages/#save-media-files-between-the-container-restarts
- WHATSAPP_FILES_LIFETIME=0
- WHATSAPP_FILES_FOLDER=/app/.media
#
# Keep media files for 180 seconds (3 minutes)
#- WHATSAPP_FILES_LIFETIME=180
#
#
# Global Webhooks
#
# https://waha.devlike.pro/docs/how-to/config/#webhooks
# https://waha.devlike.pro/docs/how-to/webhooks/
#- WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
#- WHATSAPP_HOOK_EVENTS=session.status,message,message.reaction
#
#
# MongoDB Configuration
# https://waha.devlike.pro/docs/how-to/storages/#sessions---mongodb
#- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
#
# NOTE: Uncomment this block to run WAHA+ with MongoDB
# mongodb:
# image: mongo
# container_name: mongodb
# ports:
# - '27017:27017/tcp'
# volumes:
# - mongodb_data:/data/db
# restart: always
# NOTE: Uncomment this block to run WAHA+ with MongoDB
#volumes:
# mongodb_data: {}
Binary file not shown.
+1
View File
@@ -38,6 +38,7 @@
"@types/better-sqlite3": "^7.6.10",
"@types/lodash": "^4.14.194",
"@types/ws": "^8.5.4",
"adm-zip": "0.5.10",
"async-lock": "^1.4.1",
"better-sqlite3": "9.6.0",
"check-disk-space": "^3.4.0",
+23
View File
@@ -0,0 +1,23 @@
#!/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=PRETTY \
--env WAHA_LOG_LEVEL=info \
--env WHATSAPP_DEFAULT_ENGINE=WEBJS \
--env WHATSAPP_RESTART_ALL_SESSIONS=True \
--env WAHA_PRINT_QR=False \
--env WHATSAPP_FILES_LIFETIME=0 \
--env WHATSAPP_FILES_FOLDER=/app/.media \
devlikeapro/waha-plus:latest
echo "WAHA started."
+21
View File
@@ -0,0 +1,21 @@
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
+23
View File
@@ -4,6 +4,7 @@ import {
Delete,
Get,
Param,
Post,
Put,
Query,
UsePipes,
@@ -98,6 +99,28 @@ class ChatsController {
) {
return session.editMessage(chatId, messageId, body);
}
@Post(':chatId/archive')
@SessionApiParam
@ChatIdApiParam
@ApiOperation({ summary: 'Archive the chat' })
archiveChat(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
) {
return session.chatsArchiveChat(chatId);
}
@Post(':chatId/unarchive')
@SessionApiParam
@ChatIdApiParam
@ApiOperation({ summary: 'Unarchive the chat' })
unarchiveChat(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
) {
return session.chatsUnarchiveChat(chatId);
}
}
export { ChatsController };
+4 -1
View File
@@ -1,5 +1,5 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { HealthCheck } from '@nestjs/terminus';
import { WAHAHealthCheckService } from '../core/abc/WAHAHealthCheckService';
@@ -11,6 +11,9 @@ export class HealthController {
@Get()
@HealthCheck()
@ApiOperation({
summary: 'Check the health of the server, performing all health checks.',
})
async check() {
return this.wahaHealth.check();
}
+52
View File
@@ -0,0 +1,52 @@
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { SessionApiParam, SessionParam } from '@waha/api/helpers';
import { WhatsappSession } from '@waha/core/abc/session.abc';
import { Label, LabelID, SetLabelsRequest } from '@waha/structures/labels.dto';
import { SessionManager } from '../core/abc/manager.abc';
@ApiSecurity('api_key')
@Controller('api/:session/labels')
@ApiTags('labels')
export class LabelsController {
constructor(private manager: SessionManager) {}
@Get('/')
@SessionApiParam
@ApiOperation({ summary: 'Get all labels' })
getAll(@SessionParam session: WhatsappSession): Promise<Label[]> {
return session.getLabels();
}
@Get('/chats/:chatId')
@SessionApiParam
@ApiOperation({ summary: 'Get labels for the chat' })
getChatLabels(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
): Promise<Label[]> {
return session.getChatLabels(chatId);
}
@Put('/chats/:chatId')
@SessionApiParam
@ApiOperation({ summary: 'Save labels for the chat' })
putChatLabels(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
@Body() request: SetLabelsRequest,
) {
return session.putLabelsToChat(chatId, request.labels);
}
@Get('/:labelId/chats')
@SessionApiParam
@ApiOperation({ summary: 'Get chats by label' })
getChatsByLabel(
@SessionParam session: WhatsappSession,
@Param('labelId') labelId: string,
) {
return session.getChatsByLabelId(labelId);
}
}
+13
View File
@@ -0,0 +1,13 @@
import { Controller, Get } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { PingResponse } from '@waha/structures/ping.dto';
@Controller('ping')
@ApiTags('other')
export class PingController {
@Get()
@ApiOperation({ summary: 'Ping the server, perform no operations.' })
ping(): PingResponse {
return { message: 'pong' };
}
}
+7 -1
View File
@@ -1,5 +1,10 @@
import { Controller, Get } from '@nestjs/common';
import { ApiExtraModels, ApiSecurity, ApiTags } from '@nestjs/swagger';
import {
ApiExtraModels,
ApiOperation,
ApiSecurity,
ApiTags,
} from '@nestjs/swagger';
import { WAHAEnvironment } from '../structures/environment.dto';
import { VERSION } from '../version';
@@ -9,6 +14,7 @@ import { VERSION } from '../version';
@ApiTags('other')
export class VersionController {
@Get('')
@ApiOperation({ summary: 'Get the version of the server' })
get(): WAHAEnvironment {
return VERSION;
}
+8 -2
View File
@@ -2,9 +2,7 @@ import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { parseBool } from './helpers';
import { WAHAEngine } from './structures/enums.dto';
import { WebhookConfig } from './structures/webhooks.config.dto';
import { getEngineName } from './version';
@Injectable()
export class WhatsappConfigService {
@@ -120,6 +118,14 @@ export class WhatsappConfigService {
return this.configService.get('WHATSAPP_API_KEY', '');
}
getExcludedPaths(): string[] {
const value = this.configService.get('WHATSAPP_API_KEY_EXCLUDE_PATH', '');
if (!value) {
return [];
}
return value.split(',');
}
getHealthMediaFilesThreshold(): number {
return this.configService.get<number>(
'WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB',
+4
View File
@@ -74,6 +74,10 @@ export class SwaggerConfiguratorCore {
)
.addTag('groups', `Groups methods.<br>`)
.addTag('presence', `Presence information`)
.addTag(
'labels',
'Labels - available only for WhatsApp Business accounts',
)
.addTag('other', 'Other methods')
.addApiKey({
type: 'apiKey',
+3 -1
View File
@@ -1 +1,3 @@
export abstract class DataStore {}
export abstract class DataStore {
abstract init(sessionName?: string): Promise<void>;
}
+29
View File
@@ -4,6 +4,7 @@ import {
ListChannelsQuery,
} from '@waha/structures/channels.dto';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { Label, LabelID } from '@waha/structures/labels.dto';
import { LoggerBuilder } from '@waha/utils/logging';
import { EventEmitter } from 'events';
import * as fs from 'fs';
@@ -324,6 +325,34 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError();
}
public chatsArchiveChat(chatId: string): Promise<any> {
throw new NotImplementedByEngineError();
}
public chatsUnarchiveChat(chatId: string): Promise<any> {
throw new NotImplementedByEngineError();
}
/**
* Labels methods
*/
public getLabels(): Promise<Label[]> {
throw new NotImplementedByEngineError();
}
public getChatsByLabelId(labelId: string) {
throw new NotImplementedByEngineError();
}
public getChatLabels(chatId: string): Promise<Label[]> {
throw new NotImplementedByEngineError();
}
public putLabelsToChat(chatId: string, labels: LabelID[]) {
throw new NotImplementedByEngineError();
}
/**
* Contacts methods
*/
+4
View File
@@ -18,6 +18,8 @@ import { ChattingController } from '../api/chatting.controller';
import { ContactsController } from '../api/contacts.controller';
import { GroupsController } from '../api/groups.controller';
import { HealthController } from '../api/health.controller';
import { LabelsController } from '../api/labels.controller';
import { PingController } from '../api/ping.controller';
import { PresenceController } from '../api/presence.controller';
import { ScreenshotController } from '../api/screenshot.controller';
import {
@@ -99,12 +101,14 @@ export const CONTROLLERS = [
ChatsController,
ChannelsController,
StatusController,
LabelsController,
ContactsController,
GroupsController,
PresenceController,
ScreenshotController,
VersionController,
HealthController,
PingController,
];
const PROVIDERS = [
{
@@ -18,12 +18,16 @@ import makeWASocket, {
WAMessageContent,
WAMessageKey,
} from '@adiwajshing/baileys';
import { WACallEvent } from '@adiwajshing/baileys/lib/Types/Call';
import { Label as NOWEBLabel } from '@adiwajshing/baileys/lib/Types/Label';
import { LabelAssociationType } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
import { Logger as BaileysLogger } from '@adiwajshing/baileys/node_modules/pino';
import { UnprocessableEntityException } from '@nestjs/common';
import { NowebInMemoryStore } from '@waha/core/engines/noweb/store/NowebInMemoryStore';
import { flipObject, parseBool, splitAt } from '@waha/helpers';
import { PairingCodeResponse } from '@waha/structures/auth.dto';
import { CallData } from '@waha/structures/calls.dto';
import {
Channel,
ChannelRole,
@@ -32,6 +36,11 @@ import {
} from '@waha/structures/channels.dto';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
Label,
LabelChatAssociation,
LabelID,
} from '@waha/structures/labels.dto';
import {
PollVote,
PollVotePayload,
@@ -700,6 +709,73 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
return chats;
}
protected async chatsPutArchive(
chatId: string,
archive: boolean,
): Promise<any> {
const jid = toJID(chatId);
const messages = await this.store.getMessagesByJid(jid, 1);
return await this.sock.chatModify(
{ archive: archive, lastMessages: messages },
jid,
);
}
public chatsArchiveChat(chatId: string): Promise<any> {
return this.chatsPutArchive(chatId, true);
}
public chatsUnarchiveChat(chatId: string): Promise<any> {
return this.chatsPutArchive(chatId, false);
}
/**
* Labels methods
*/
public async getLabels(): Promise<Label[]> {
const labels = await this.store.getLabels();
return labels.map(this.toLabel);
}
public async getChatsByLabelId(labelId: string) {
const chats = await this.store.getChatsByLabelId(labelId);
// Remove unreadCount, it's not ready yet
chats.forEach((chat) => delete chat.unreadCount);
return chats;
}
public async getChatLabels(chatId: string): Promise<Label[]> {
const jid = toJID(chatId);
const labels = await this.store.getChatLabels(jid);
return labels.map(this.toLabel);
}
public async putLabelsToChat(chatId: string, labels: LabelID[]) {
const jid = toJID(chatId);
const labelsIds = labels.map((label) => label.id);
const currentLabels = await this.store.getChatLabels(jid);
const currentLabelsIds = currentLabels.map((label) => label.id);
const addLabelsIds = lodash.difference(labelsIds, currentLabelsIds);
const removeLabelsIds = lodash.difference(currentLabelsIds, labelsIds);
for (const labelId of addLabelsIds) {
await this.sock.addChatLabel(jid, labelId);
}
for (const labelId of removeLabelsIds) {
await this.sock.removeChatLabel(jid, labelId);
}
}
protected toLabel(label: NOWEBLabel): Label {
const color = label.color;
return {
id: label.id,
name: label.name,
color: color,
colorHex: Label.toHex(color),
};
}
/**
* Contacts methods
*/
@@ -1013,6 +1089,99 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
);
});
return true;
case WAHAEvents.CALL_RECEIVED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
calls = lodash.filter(calls, { status: 'offer' });
for (const call of calls) {
const body = this.toCallData(call);
handler(body);
}
});
return true;
case WAHAEvents.CALL_ACCEPTED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
calls = lodash.filter(calls, { status: 'accept' });
for (const call of calls) {
const body = this.toCallData(call);
handler(body);
}
});
return true;
case WAHAEvents.CALL_REJECTED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
const acceptCalls = lodash.filter(calls, { status: 'accept' });
if (acceptCalls.length > 0) {
// We got two events when accepting calls - reject and accept
// Like for each device
// So if we see accepted call - ignore rejected
return;
}
calls = lodash.filter(calls, { status: 'reject' });
for (const call of calls) {
const body = this.toCallData(call);
if (body.isGroup == null) {
// We get two "reject" events, one with null property, ignore it
return;
}
handler(body);
}
});
return true;
case WAHAEvents.LABEL_UPSERT:
this.sock.ev.on('labels.edit', (data: NOWEBLabel) => {
if (data.deleted) {
return;
}
const body = this.toLabel(data);
handler(body);
});
return true;
case WAHAEvents.LABEL_DELETED:
this.sock.ev.on('labels.edit', (data: NOWEBLabel) => {
if (!data.deleted) {
return;
}
const body = this.toLabel(data);
handler(body);
});
return true;
case WAHAEvents.LABEL_CHAT_ADDED:
this.sock.ev.on('labels.association', async ({ association, type }) => {
if (type !== 'add') {
return;
}
if (association.type !== LabelAssociationType.Chat) {
return;
}
const labelData = await this.store.getLabelById(association.labelId);
const label = labelData ? this.toLabel(labelData) : null;
const body: LabelChatAssociation = {
labelId: association.labelId,
chatId: toCusFormat(association.chatId),
label: label,
};
handler(body);
});
return true;
case WAHAEvents.LABEL_CHAT_DELETED:
this.sock.ev.on('labels.association', async ({ association, type }) => {
if (type !== 'remove') {
return;
}
if (association.type !== LabelAssociationType.Chat) {
return;
}
const labelData = await this.store.getLabelById(association.labelId);
const label = labelData ? this.toLabel(labelData) : null;
const body: LabelChatAssociation = {
labelId: association.labelId,
chatId: toCusFormat(association.chatId),
label: label,
};
handler(body);
});
return true;
default:
return false;
}
@@ -1250,6 +1419,20 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
handler(payload);
}
private toCallData(call: WACallEvent): CallData {
// call.date can be either string 2024-07-18T09:45:55.000Z or Date
const date = new Date(call.date);
// convert to timestamp in seconds
const timestamp: number = date.getTime() / 1000;
return {
id: call.id,
from: toCusFormat(call.from),
timestamp: timestamp,
isVideo: call.isVideo,
isGroup: call.isGroup,
};
}
private toWahaPresences(
remoteJid: string,
storedPresences: { [participant: string]: PresenceData },
@@ -3,6 +3,8 @@ import { Chat } from '@adiwajshing/baileys';
export interface IChatRepository {
getAll(): Promise<Chat[]>;
getAllByIds(ids: string[]): Promise<Chat[]>;
getAllWithMessages(limit?: number, offset?: number): Promise<Chat[]>;
getById(id: string): Promise<Chat | null>;
@@ -0,0 +1,19 @@
import {
LabelAssociation,
LabelAssociationType,
} from '@adiwajshing/baileys/lib/Types/LabelAssociation';
export interface ILabelAssociationRepository {
deleteOne(association: LabelAssociation): Promise<void>;
save(association: LabelAssociation): Promise<void>;
deleteByLabelId(labelId: string): Promise<void>;
getAssociationsByLabelId(
labelId: string,
type: LabelAssociationType,
): Promise<LabelAssociation[]>;
getAssociationsByChatId(chatId: string): Promise<LabelAssociation[]>;
}
@@ -0,0 +1,14 @@
import { Contact } from '@adiwajshing/baileys';
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
export interface ILabelsRepository {
getById(id: string): Promise<Label | null>;
getAll(): Promise<Label[]>;
getAllByIds(ids: string[]): Promise<Label[]>;
deleteById(id: string): Promise<void>;
save(label: Label): Promise<void>;
}
+31 -6
View File
@@ -1,15 +1,40 @@
import { WAMessage } from '@adiwajshing/baileys';
import { LabelAssociation } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
import { IChatRepository } from './IChatRepository';
import { IContactRepository } from './IContactRepository';
import { IMessagesRepository } from './IMessagesRepository';
export interface INowebStorage {
init(): Promise<void>;
export abstract class INowebStorage {
abstract init(): Promise<void>;
close(): Promise<void>;
abstract close(): Promise<void>;
getContactsRepository(): IContactRepository;
abstract getContactsRepository(): IContactRepository;
getChatRepository(): IChatRepository;
abstract getChatRepository(): IChatRepository;
getMessagesRepository(): IMessagesRepository;
abstract getMessagesRepository(): IMessagesRepository;
abstract getLabelsRepository(): ILabelsRepository;
abstract getLabelAssociationRepository(): ILabelAssociationRepository;
protected getMessagesMetadata(): Map<string, any> {
return new Map()
.set('jid', (msg: WAMessage) => msg.key.remoteJid)
.set('id', (msg: WAMessage) => msg.key.id)
.set('messageTimestamp', (msg: WAMessage) => msg.messageTimestamp);
}
protected getLabelAssociationMetadata() {
return new Map().set(
'id',
(a: LabelAssociation) =>
// @ts-ignore
`${a.type}_${a.labelId}_${a.chatId}_${a.messageId}`,
);
}
}
@@ -4,6 +4,7 @@ import {
Contact,
proto,
} from '@adiwajshing/baileys';
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
export interface INowebStore {
presences: any;
@@ -23,4 +24,12 @@ export interface INowebStore {
getContacts(): Promise<Contact[]>;
getContactById(jid: string): Promise<Contact>;
getLabels(): Promise<Label[]>;
getLabelById(labelId: string): Promise<Label | null>;
getChatsByLabelId(labelId: string): Promise<Chat[]>;
getChatLabels(chatId: string): Promise<Label[]>;
}
@@ -1,4 +1,5 @@
import { Chat, Contact, makeInMemoryStore, proto } from '@adiwajshing/baileys';
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
import { BadRequestException, ConsoleLogger } from '@nestjs/common';
import { INowebStore } from './INowebStore';
@@ -51,4 +52,20 @@ export class NowebInMemoryStore implements INowebStore {
getContactById(jid: string): Promise<Contact> {
throw new BadRequestException(this.errorMessage);
}
getLabels(): Promise<Label[]> {
throw new BadRequestException(this.errorMessage);
}
getLabelById(labelId: string): Promise<Label | null> {
throw new BadRequestException(this.errorMessage);
}
getChatsByLabelId(labelId: string): Promise<Chat[]> {
throw new BadRequestException(this.errorMessage);
}
getChatLabels(chatId: string): Promise<Label[]> {
throw new BadRequestException(this.errorMessage);
}
}
@@ -9,7 +9,13 @@ import {
updateMessageWithReaction,
updateMessageWithReceipt,
} from '@adiwajshing/baileys';
import { ConsoleLogger } from '@nestjs/common';
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
import {
LabelAssociation,
LabelAssociationType,
} from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
import { toNumber } from 'lodash';
import { Logger } from 'pino';
@@ -28,6 +34,8 @@ export class NowebPersistentStore implements INowebStore {
private chatRepo: IChatRepository;
private contactRepo: IContactRepository;
private messagesRepo: IMessagesRepository;
private labelsRepo: ILabelsRepository;
private labelAssociationsRepo: ILabelAssociationRepository;
public presences: any;
private lock: any;
@@ -39,6 +47,8 @@ export class NowebPersistentStore implements INowebStore {
this.chatRepo = storage.getChatRepository();
this.contactRepo = storage.getContactsRepository();
this.messagesRepo = storage.getMessagesRepository();
this.labelsRepo = storage.getLabelsRepository();
this.labelAssociationsRepo = storage.getLabelAssociationRepository();
this.presences = {};
this.lock = new AsyncLock({ maxPending: Infinity });
}
@@ -83,6 +93,10 @@ export class NowebPersistentStore implements INowebStore {
ev.on('contacts.update', (data) =>
this.withLock('contacts', () => this.onContactUpdate(data)),
);
ev.on('labels.edit', (data) => this.onLabelsEdit(data));
ev.on('labels.association', ({ association, type }) =>
this.onLabelsAssociation(association, type),
);
// Presence
ev.on('presence.update', (data) => this.onPresenceUpdate(data));
this.socket = socket;
@@ -275,6 +289,26 @@ export class NowebPersistentStore implements INowebStore {
}
}
private async onLabelsEdit(label: Label) {
if (label.deleted) {
await this.labelsRepo.deleteById(label.id);
await this.labelAssociationsRepo.deleteByLabelId(label.id);
} else {
await this.labelsRepo.save(label);
}
}
private async onLabelsAssociation(
association: LabelAssociation,
type: 'add' | 'remove',
) {
if (type === 'remove') {
await this.labelAssociationsRepo.deleteOne(association);
} else {
await this.labelAssociationsRepo.save(association);
}
}
private async onPresenceUpdate({ id, presences: update }) {
this.presences[id] = this.presences[id] || {};
Object.assign(this.presences[id], update);
@@ -303,4 +337,29 @@ export class NowebPersistentStore implements INowebStore {
getContacts() {
return this.contactRepo.getAll();
}
getLabels(): Promise<Label[]> {
return this.labelsRepo.getAll();
}
getLabelById(labelId: string): Promise<Label | null> {
return this.labelsRepo.getById(labelId);
}
async getChatsByLabelId(labelId: string): Promise<Chat[]> {
const associations =
await this.labelAssociationsRepo.getAssociationsByLabelId(
labelId,
LabelAssociationType.Chat,
);
const ids = associations.map((association) => association.chatId);
return await this.chatRepo.getAllByIds(ids);
}
async getChatLabels(chatId: string): Promise<Label[]> {
const associations =
await this.labelAssociationsRepo.getAssociationsByChatId(chatId);
const ids = associations.map((association) => association.labelId);
return await this.labelsRepo.getAllByIds(ids);
}
}
+22
View File
@@ -53,4 +53,26 @@ export const NOWEB_STORE_SCHEMA = [
new Index('timestamp_index', ['messageTimestamp']),
],
),
new Schema(
'labels',
[new Field('id', 'TEXT'), new Field('data', 'TEXT')],
[new Index('labels_id_index', ['id'])],
),
new Schema(
'labelAssociations',
[
new Field('id', 'TEXT'),
new Field('type', 'TEXT'),
new Field('labelId', 'TEXT'),
new Field('chatId', 'TEXT'),
new Field('messageId', 'TEXT'),
new Field('data', 'TEXT'),
],
[
new Index('label_assoc_id_index', ['id']),
new Index('label_assoc_type_label_index', ['type', 'labelId']),
new Index('label_assoc_type_chat_index', ['type', 'chatId']),
new Index('label_assoc_type_message_index', ['type', 'messageId']),
],
),
];
@@ -38,6 +38,15 @@ export class Sqlite3KVRepository<Entity> {
return this.all(this.select());
}
getAllByIds(ids: string[]) {
return this.all(this.select().whereIn('id', ids));
}
protected getAllBy(filters: any) {
const query = this.select().where(filters);
return this.all(query);
}
protected async getBy(filters: any) {
const query = this.select().where(filters).limit(1);
return this.get(query);
@@ -0,0 +1,40 @@
import {
LabelAssociation,
LabelAssociationType,
} from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
import { Sqlite3KVRepository } from './Sqlite3KVRepository';
export class Sqlite3LabelAssociationsRepository
extends Sqlite3KVRepository<LabelAssociation>
implements ILabelAssociationRepository
{
async deleteOne(association: LabelAssociation): Promise<void> {
await this.deleteBy({
type: association.type,
chatId: association.chatId,
labelId: association.labelId,
// @ts-ignore: messageId doesn't existing in ChatLabelAssociation
messageId: association.messageId || null,
});
}
async deleteByLabelId(labelId: string): Promise<void> {
await this.deleteBy({ labelId: labelId });
}
getAssociationsByLabelId(
labelId: string,
type: LabelAssociationType,
): Promise<LabelAssociation[]> {
return this.getAllBy({
type: type,
labelId: labelId,
});
}
getAssociationsByChatId(chatId: string): Promise<LabelAssociation[]> {
return this.getAllBy({ chatId: chatId, type: LabelAssociationType.Chat });
}
}
@@ -0,0 +1,8 @@
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
import { Sqlite3KVRepository } from './Sqlite3KVRepository';
export class Sqlite3LabelsRepository
extends Sqlite3KVRepository<Label>
implements ILabelsRepository {}
@@ -1,4 +1,9 @@
import { WAMessage } from '@adiwajshing/baileys';
import { LabelAssociation } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
import { Sqlite3LabelAssociationsRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LabelAssociationsRepository';
import { Sqlite3LabelsRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LabelsRepository';
import { INowebStorage } from '../INowebStorage';
import { Field, Index, NOWEB_STORE_SCHEMA, Schema } from '../Schema';
@@ -10,11 +15,12 @@ import { Sqlite3SchemaValidation } from './Sqlite3SchemaValidation';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Database = require('better-sqlite3');
export class Sqlite3Storage implements INowebStorage {
export class Sqlite3Storage extends INowebStorage {
private readonly db: any;
private readonly tables: Schema[];
constructor(filePath: string) {
super();
this.db = new Database(filePath);
this.tables = NOWEB_STORE_SCHEMA;
}
@@ -71,6 +77,33 @@ export class Sqlite3Storage implements INowebStorage {
this.db.exec(
'CREATE INDEX IF NOT EXISTS timestamp_index ON messages (messageTimestamp)',
);
//
// Labels
//
this.db.exec(
'CREATE TABLE IF NOT EXISTS labels (id TEXT PRIMARY KEY, data TEXT)',
);
this.db.exec(
'CREATE UNIQUE INDEX IF NOT EXISTS labels_id_index ON labels (id)',
);
// Label associations
this.db.exec(
'CREATE TABLE IF NOT EXISTS labelAssociations (id TEXT PRIMARY KEY, type TEXT, labelId TEXT, chatId TEXT, messageId TEXT, data TEXT)',
);
this.db.exec(
'CREATE UNIQUE INDEX IF NOT EXISTS label_assoc_id_index ON labelAssociations (id)',
);
this.db.exec(
'CREATE INDEX IF NOT EXISTS label_assoc_type_label_index ON labelAssociations (type, labelId)',
);
this.db.exec(
'CREATE INDEX IF NOT EXISTS label_assoc_type_chat_index ON labelAssociations (type, chatId)',
);
this.db.exec(
'CREATE INDEX IF NOT EXISTS label_assoc_type_message_index ON labelAssociations (type, messageId)',
);
}
async close() {
@@ -85,11 +118,21 @@ export class Sqlite3Storage implements INowebStorage {
return new Sqlite3ChatRepository(this.db, this.getSchema('chats'));
}
getLabelsRepository(): ILabelsRepository {
return new Sqlite3LabelsRepository(this.db, this.getSchema('labels'));
}
getLabelAssociationRepository(): ILabelAssociationRepository {
const metadata = this.getLabelAssociationMetadata();
return new Sqlite3LabelAssociationsRepository(
this.db,
this.getSchema('labelAssociations'),
metadata,
);
}
getMessagesRepository() {
const metadata = new Map()
.set('jid', (msg: WAMessage) => msg.key.remoteJid)
.set('id', (msg: WAMessage) => msg.key.id)
.set('messageTimestamp', (msg: WAMessage) => msg.messageTimestamp);
const metadata = this.getMessagesMetadata();
return new Sqlite3MessagesRepository(
this.db,
this.getSchema('messages'),
-535
View File
@@ -1,535 +0,0 @@
<!doctype html>
<html class="no-js" dir="ltr" loc="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>WhatsApp Web</title>
<meta name="viewport" content="width=device-width" />
<meta name="google" content="notranslate" />
<meta name="format-detection" content="telephone=no" />
<meta
name="description"
content="Quickly send and receive WhatsApp messages right from your computer."
/>
<meta
name="og:description"
content="Quickly send and receive WhatsApp messages right from your computer."
/>
<meta name="og:url" content="https://web.whatsapp.com/" />
<meta name="og:title" content="WhatsApp Web" />
<meta
name="og:image"
content="https://static.facebook.com/images/whatsapp/www/whatsapp-promo.png"
/>
<link
id="favicon"
rel="shortcut icon"
href="/img/favicon/1x/favicon.png"
type="image/png"
/>
<link
rel="apple-touch-icon"
sizes="192x192"
href="/apple-touch-icon.png"
type="image/png"
/>
<meta
name="theme-color"
content="#111b21"
media="(prefers-color-scheme: dark)"
/>
<meta name="theme-color" content="#f0f2f5" />
<link
id="whatsapp-pwa-manifest-link"
rel="manifest"
href="/manifest.json"
crossorigin="use-credentials"
/>
<style>
#initial_startup {
--startup-background: #f0f2f5;
--startup-background-rgb: 240, 242, 245;
--startup-icon: #bbc5cb;
--secondary-lighter: #8696a0;
--primary-title: #41525d;
--progress-primary: #00c298;
--progress-background: #e9edef;
}
.dark #initial_startup {
--startup-background: #111b21;
--startup-background-rgb: 17, 27, 33;
--startup-icon: #676f73;
--primary-title: rgba(233, 237, 239, 0.88);
--secondary-lighter: #667781;
--progress-primary: #0b846d;
--progress-background: #233138;
}
#app,
body,
html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
#app {
position: absolute;
top: 0;
left: 0;
}
#initial_startup {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
user-select: none;
background-color: var(--startup-background);
}
#initial_startup .graphic {
margin-top: -40px;
color: var(--startup-icon);
}
#initial_startup .graphic .resume-logo {
transform: translateX(calc(50% - 52px / 2));
}
#initial_startup .graphic::after {
position: relative;
top: -100%;
left: calc(50% - 72px * 2 - 72px / 2);
display: block;
width: calc(72px * 3);
height: 100%;
content: '';
background: linear-gradient(
to right,
rgba(var(--startup-background-rgb), 0.5) 0,
rgba(var(--startup-background-rgb), 0.5) 33.33%,
rgba(var(--startup-background-rgb), 0) 44.1%,
rgba(var(--startup-background-rgb), 0) 55.8%,
rgba(var(--startup-background-rgb), 0.5) 66.66%,
rgba(var(--startup-background-rgb), 0.5) 100%
);
opacity: 1;
animation: shimmer 1.5s linear 0.6s infinite;
}
html[dir='rtl'] #initial_startup .graphic::after {
animation-direction: reverse;
}
@keyframes shimmer {
from {
left: calc(50% - 72px * 2 - 72px / 2);
}
to {
left: calc(50% - 72px / 2);
}
}
#initial_startup .progress {
position: relative;
width: 420px;
height: 3px;
margin-top: 40px;
}
#initial_startup .progress progress {
vertical-align: top;
}
#initial_startup .main {
margin-top: 40px;
font-size: 17px;
color: var(--primary-title);
}
#initial_startup .secondary {
margin-top: 12px;
font-size: 14px;
color: var(--secondary-lighter);
}
#initial_startup .secondary span {
display: inline-block;
margin-bottom: 2px;
vertical-align: middle;
}
progress {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 3px;
margin: 0;
color: var(--progress-primary);
background-color: var(--progress-background);
border: none;
}
progress[value]::-webkit-progress-bar {
background-color: var(--progress-background);
}
progress[value]::-moz-progress-bar,
progress[value]::-webkit-progress-value {
background-color: var(--progress-primary);
transition: width 0.45s ease;
}
</style>
<link
href="/stylex-f0601c57714fe972a8c4d2c2562f8082.css"
rel="stylesheet"
/>
<link href="/app-6113f1562d101247269b.css" rel="stylesheet" />
</head>
<body class="web">
<script
data-binary-transparency-hash-key="inline-js-d11c72a06542fc3b43af600028cf0f996e4b9b178dfa047e18730efaf74aab0b"
>
try {
var systemThemeDark,
theme = window.localStorage.getItem('theme'),
systemThemeMode = window.localStorage.getItem('system-theme-mode');
if (('true' === systemThemeMode || !theme) && window.matchMedia) {
var systemTheme = window.matchMedia('(prefers-color-scheme: dark)');
systemThemeDark = systemTheme && systemTheme.matches;
}
var darkTheme = '"dark"' === theme || Boolean(systemThemeDark);
darkTheme && document.body.classList.add('dark');
} catch (e) {}
</script>
<div id="app"></div>
<div id="hard_expire_time" data-time="1719543128.405"></div>
<div id="initial_startup">
<div class="graphic">
<span
><svg width="250" height="52" xmlns="http://www.w3.org/2000/svg">
<path
class="resume-logo"
d="M37.7 31.2c-.6-.4-3.8-2-4.4-2.1-.6-.2-1-.4-1.4.3l-2 2.5c-.4.4-.8.5-1.5.2-.6-.3-2.7-1-5.1-3.2-2-1.7-3.2-3.8-3.6-4.5-.4-.6 0-1 .3-1.3l1-1.1.6-1.1c.2-.4 0-.8 0-1.1l-2-4.8c-.6-1.3-1.1-1-1.5-1.1h-1.2c-.5 0-1.2.1-1.8.8-.5.6-2.2 2.2-2.2 5.3 0 3.2 2.3 6.3 2.6 6.7.3.4 4.6 7 11 9.7l3.7 1.4c1.5.5 3 .4 4 .2 1.3-.1 3.9-1.5 4.4-3 .5-1.5.5-2.8.4-3-.2-.4-.6-.5-1.3-.8M26 47.2c-3.9 0-7.6-1-11-3l-.7-.4-8.1 2L8.4 38l-.6-.8A21.4 21.4 0 0126 4.4a21.3 21.3 0 0121.4 21.4c0 11.8-9.6 21.4-21.4 21.4M44.2 7.6a25.8 25.8 0 00-40.6 31L0 52l13.7-3.6A25.8 25.8 0 0044.3 7.5"
fill="currentColor"
></path></svg
></span>
</div>
<div class="progress">
<progress value="0" max="100" dir="ltr"></progress>
</div>
<div class="main">WhatsApp</div>
<div class="secondary">
<span
><svg width="10" height="12" xmlns="http://www.w3.org/2000/svg">
<path
d="M5 1.6c1.4 0 2.5 1 2.6 2.4v1.5h.2c.5 0 1 .4 1 1V10c0 .6-.5 1-1 1H2.3a1 1 0 01-1.1-1V6.5c0-.6.5-1 1-1h.2V4.2c0-1.4 1-2.5 2.4-2.6H5zm0 1.2c-.7 0-1.3.6-1.3 1.3v1.4h2.6V4.2c0-.7-.4-1.2-1-1.3H5z"
fill="currentColor"
></path>
</svg> </span
>&nbsp;End-to-end encrypted
</div>
</div>
<link
rel="preload"
crossorigin="anonymous"
as="fetch"
href="/binary-transparency-manifest-2.2412.54.json"
id="binary-transparency-manifest-preload"
/>
<script src="/libsignal-protocol-ee5b8ba.min.js"></script>
<script defer="defer" src="/runtime.295f0230b6dbd8983513.js"></script>
<script
data-binary-transparency-hash-key="inline-js-cdf06293c99d00ee0c1bc0fcfdbd76a7ae9aef6290926dbff0cba3a7994b7fca"
>
/*! Copyright (c) 2024 WhatsApp Inc. All Rights Reserved. */
(self.webpackChunkwhatsapp_web_client =
self.webpackChunkwhatsapp_web_client || []).push([
[5617],
{
307914: (e) => {
e.exports = function (e) {
return e && e.__esModule ? e : { default: e };
};
},
595318: (e) => {
(e.exports = function (e) {
return e && e.__esModule ? e : { default: e };
}),
(e.exports.default = e.exports),
(e.exports.__esModule = !0);
},
415227: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
const t = new Error(e);
if (void 0 === t.stack)
try {
throw t;
} catch (e) {}
return t;
});
},
670983: (e, t, r) => {
'use strict';
var n = r(307914);
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
let t =
arguments.length > 1 && void 0 !== arguments[1]
? arguments[1]
: '?';
if (null == e)
throw (0, o.default)('Unexpected null or undefined: ' + t);
return e;
});
var o = n(r(415227));
},
250473: (e, t, r) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.UNIQUE_UPLOADS_ALLOWED_BEFORE_THROTTLE =
t.TICKET_URL =
t.CLB_URL =
t.CLB_TOKEN =
t.CLB_CHECK_URL =
void 0);
var n = r(508247);
(t.CLB_CHECK_URL =
'https://crashlogs.whatsapp.net/wa_fls_upload_check'),
(t.CLB_TOKEN =
'1063127757113399|745146ffa34413f9dbb5469f5370b7af'),
(t.CLB_URL = 'https://crashlogs.whatsapp.net/wa_clb_data');
const o = n.DYN_ORIGIN + 'web-contact-us';
(t.TICKET_URL = o), (t.UNIQUE_UPLOADS_ALLOWED_BEFORE_THROTTLE = 0);
},
207024: (e, t, r) => {
'use strict';
var n = r(595318);
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.getDistribution = function () {
let e = 'unknown';
return (e = 'prod'), 'web_prod';
}),
(t.getLogUserAgent = function (e) {
let t,
{ appVersion: r, browser: n, device: o } = e;
return (t = 'Web/' + n), `WhatsApp/${r} ${t} Device/${o}`;
}),
n(r(472514)),
n(r(556869));
},
794858: (e, t, r) => {
'use strict';
var n = r(595318),
o = n(r(670983)),
a = r(508247),
s = r(250473),
c = r(207024),
_ = n(r(174285)),
u = r(425017);
function i(e) {
!(function (e, t) {
const r = window.navigator.userAgent;
if (r === p && e.includes('getElementsByTagName')) return;
const n = new FormData(),
i = new Blob([e], { type: 'text/plain' });
n.append(
'from_jid',
(function () {
if (f) return f;
try {
(f = JSON.parse(
(0, o.default)(_.default, 'localStorage').getItem(
d.UNKNOWN_ID,
),
)),
f && (f = f.replace('-', ''));
} catch (e) {}
if (!f) {
f = 'unknown' + Math.floor(1e10 * Math.random());
const e = f;
try {
(0, o.default)(_.default, 'localStorage').setItem(
d.UNKNOWN_ID,
JSON.stringify(e),
);
} catch (e) {}
}
return (0, o.default)(f, 'id');
})(),
),
n.append(
'agent',
(0, c.getLogUserAgent)(
(0, u.parseUASimple)(r, a.VERSION_BASE),
),
),
n.append('file', i, 'logs.txt'),
n.append('tags', 'load');
const l = new XMLHttpRequest(),
I =
s.CLB_URL +
'?access_token=' +
encodeURIComponent(s.CLB_TOKEN);
l.open('POST', I, !0), l.send(n);
})(e);
}
function l(e) {
let { error: t, reason: r, stack: n } = e;
const o = new Date().toISOString();
return `${o}: error: ${t}\n${o}: reason for logs: ${r}\n${o}: userAgent: ${window.navigator.userAgent}\n${n}`;
}
null == window.onerror &&
(window.onerror = function (e, t, r) {
const n = t.split('?')[0];
return "Uncaught SyntaxError: Unexpected token '<'" === e
? ((function (e) {
i(
l({
error: 'failed to load a js or css bundle',
reason: `failed to load [${e
.split('/')[3]
.replace(/^\//, '')}]`,
stack: '',
}),
);
})(n),
!0)
: (i(
l({
error: e,
reason: `Error at [${n}:${r}]`,
stack: '',
}),
),
!1);
});
const d = { UNKNOWN_ID: a.UNKNOWN_ID },
p =
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36';
let f;
},
425017: (e, t) => {
'use strict';
function r(e) {
return e.includes('windows')
? 'Windows'
: e.includes('mac')
? 'Mac OS'
: e.includes('linux')
? 'Linux'
: 'Unparsed';
}
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.parseUASimple = function (e, t) {
const n = e.toLowerCase();
return { browser: s(n), device: r(n), appVersion: t };
});
const n = /(chrome|firefox)\/([\w\.]+)/i,
o = /(edge|opr)\/([\w\.]+)/i,
a = {
chrome: 'Chrome',
edge: 'Edge',
opr: 'Opera',
firefox: 'Firefox',
};
function s(e) {
const t = e.match(o) || e.match(n);
return null == t ? 'Unparsed' : `${a[t[1]]} ${t[2]}`;
}
},
174285: (e, t) => {
'use strict';
let r;
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = void 0);
try {
r = window.localStorage;
} catch (e) {}
var n = r;
t.default = n;
},
508247: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.WS_ORIGIN =
t.WEB_PUBLIC_PATH =
t.VERSION_TERTIARY =
t.VERSION_STR =
t.VERSION_SECONDARY =
t.VERSION_PRIMARY =
t.VERSION_BASE =
t.USER_TIMINGS =
t.UNKNOWN_ID =
t.LOCALHOST_ENV_CONFIG =
t.HASH_PLACEHOLDER =
t.FLB_PLATFORM =
t.FB_APP_ID =
t.DYN_ORIGIN =
t.DIFF_VERSION =
t.DIFF_ID =
t.BUILD_URL =
t.BUILD_TIMESTAMP =
t.BUILD_ID =
void 0);
t.DIFF_ID = '';
(t.DIFF_VERSION = ''),
(t.LOCALHOST_ENV_CONFIG = !1),
(t.HASH_PLACEHOLDER = '507042ed75b89fb00e8ef35da3541122cbc261e6'),
(t.VERSION_PRIMARY = '2'),
(t.VERSION_SECONDARY = '2412'),
(t.VERSION_TERTIARY = '54'),
(t.VERSION_BASE = '2.2412.54'),
(t.VERSION_STR = '2.2412.54'),
(t.DYN_ORIGIN = 'https://web.whatsapp.com/'),
(t.WS_ORIGIN = ''),
(t.FLB_PLATFORM = 'web'),
(t.FB_APP_ID = ''),
(t.UNKNOWN_ID = 'WAUnknownID'),
(t.BUILD_ID = '583059957'),
(t.BUILD_TIMESTAMP = 'March 29, 2024'),
(t.WEB_PUBLIC_PATH = '/'),
(t.BUILD_URL = 'https://web.whatsapp.com/'),
(t.USER_TIMINGS = !1);
},
472514: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
return e.default;
});
},
556869: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function e(t) {
const r = new Error(t);
if (void 0 === r.stack)
try {
throw e;
} catch (e) {}
return r;
});
},
},
(e) => {
'use strict';
e((e.s = 794858));
},
]);
</script>
<script defer="defer" src="/vendor1~app.264a01b6133c4a120327.js"></script>
<script defer="defer" src="/app.2c7f8dd150ae88037cde.js"></script>
<script
data-binary-transparency-hash-key="inline-js-9c8cd3d0f4d5af8c7f5cd1c45208edd308bfe472e353a50e4cbacbf6cb58627c"
>
((i) => {
const l = document.getElementById(i);
l &&
fetch(l.href)
.then((b) => b.text())
.then((code) => {
const script = document.createElement('script');
script.id = 'binary-transparency-manifest';
script.type = 'application/json';
script.innerHTML = code;
document.body.append(script);
});
})('binary-transparency-manifest-preload');
</script>
</body>
</html>
@@ -1,53 +0,0 @@
<!DOCTYPE html><html id="whatsapp-web" class="" lang="en" dir="ltr"><head><link data-default-icon="https://static.whatsapp.net/rsrc.php/v3/yP/r/rYZqPCBaG70.png" rel="shortcut icon" href="https://static.whatsapp.net/rsrc.php/v3/yP/r/rYZqPCBaG70.png" /><meta name="bingbot" content="noarchive" /><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2,shrink-to-fit=no" /><link rel="manifest" href="/data/manifest.json" crossorigin="use-credentials" /><meta name="google" content="notranslate" /><meta name="format-detection" content="telephone=no" /><meta name="description" content="Quickly send and receive WhatsApp messages right from your computer." /><meta name="og:description" content="Quickly send and receive WhatsApp messages right from your computer." /><meta name="og:url" content="https://web.whatsapp.com/" /><meta name="og:title" content="WhatsApp Web" /><meta name="og:image" content="https://static.whatsapp.net/rsrc.php/v3/yR/r/y8-PTBaP90a.png" /><meta name="theme-color" content="#111b21" media="(prefers-color-scheme: dark)" /><meta name="theme-color" content="#f0f2f5" /><link rel="apple-touch-icon" sizes="192x192" href="https://static.whatsapp.net/rsrc.php/v3/yc/r/hUUuVTz6ZVi.png" /><style nonce="6GV2UyzI">:root{--splashscreen-startup-background:#f0f2f5;--splashscreen-startup-background-rgb:240, 242, 245;--splashscreen-startup-icon:#bbc5cb;--splashscreen-secondary-lighter:#8696a0;--splashscreen-primary-title:#4125d;--splashscreen-progress-primary:#00c298;--splashscreen-progress-background:#e9edef;}@media (prefers-color-scheme: dark){:root{--splashscreen-startup-background:#111b21;--splashscreen-startup-background-rgb:17,27, 33;--splashscreen-startup-icon:#676f73;--splashscreen-primary-title:rgba(233, 237, 239, 0.88);--splashscreen-secondary-lighter:#667781;--splashscreen-progress-primary:#0b846d;--splashscreen-progress-background:#233138;}}.__fb-light-mode{--splashscreen-startup-background:#f0f2f5;--splashscreen-startup-background-rgb:240, 242, 245;--splashscreen-startup-icon:#bbc5cb;--splashscreen-secondary-lighter:#8696a0;--splashscreen-primary-title:#4125d;--splashscreen-progress-primary:#00c298;--splashscreen-progress-background:#e9edef;}.__fb-dark-mode{--splashscreen-startup-background:#111b21;--splashscreen-startup-background-rgb:17,27, 33;--splashscreen-startup-icon:#676f73;--splashscreen-primary-title:rgba(233, 237, 239, 0.88);--splashscreen-secondary-lighter:#667781;--splashscreen-progress-primary:#0b846d;--splashscreen-progress-background:#233138;}</style><style nonce="6GV2UyzI"></style><script id="envjson" type="application/json" nonce="6GV2UyzI">{"useTrustedTypes":false,"isTrustedTypesReportOnly":false,"use_fbt_virtual_modules":true,"compat_iframe_token":null}</script><script src="data:application/x-javascript; charset=utf-8;base64,Oy8qRkJfUEtHX0RFTElNKi8KCnZhciBkYXRhRWxlbWVudD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZW52anNvbiIpO2lmKGRhdGFFbGVtZW50IT1udWxsKXt2YXIgY29weVZhcmlhYmxlcz1mdW5jdGlvbihhKXtmb3IodmFyIGIgaW4gdmFyaWFibGVzKWFbYl09dmFyaWFibGVzW2JdfSx2YXJpYWJsZXM9SlNPTi5wYXJzZShkYXRhRWxlbWVudC50ZXh0Q29udGVudCk7d2luZG93LnJlcXVpcmVMYXp5P3dpbmRvdy5yZXF1aXJlTGF6eShbIkVudiJdLGNvcHlWYXJpYWJsZXMpOih3aW5kb3cuRW52PXdpbmRvdy5FbnZ8fHt9LGNvcHlWYXJpYWJsZXMod2luZG93LkVudikpfQovLyMgc291cmNlVVJMPWh0dHBzOi8vc3RhdGljLndoYXRzYXBwLm5ldC9yc3JjLnBocC92My95TC9yL2RiZ3JNc25EMThwLmpzP19uY194PUlqM1dwOGxnNUt6Cg==" data-bootloader-hash="nxRKQO6" data-p=":0" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><script src="data:application/x-javascript; charset=utf-8;base64,Oy8qRkJfUEtHX0RFTElNKi8KCl9fYW5ub3RhdG9yPWZ1bmN0aW9uKGEpe3JldHVybiBhfSxfX2Rfc3R1Yj1bXSxfX2Q9ZnVuY3Rpb24oYSxiLGMsZCl7X19kX3N0dWIucHVzaChbYSxiLGMsZF0pfSxfX3JsX3N0dWI9W10scmVxdWlyZUxhenk9ZnVuY3Rpb24oKXtfX3JsX3N0dWIucHVzaChhcmd1bWVudHMpfTsKLy8jIHNvdXJjZVVSTD1odHRwczovL3N0YXRpYy53aGF0c2FwcC5uZXQvcnNyYy5waHAvdjMveTIvci9jTWRfU1pvdjlFaS5qcz9fbmNfeD1JajNXcDhsZzVLego=" data-bootloader-hash="W7CcKyc" data-p=":0" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><script src="data:application/x-javascript; charset=utf-8;base64,Oy8qRkJfUEtHX0RFTElNKi8KCl9idGxkcj17fTsKLy8jIHNvdXJjZVVSTD1odHRwczovL3N0YXRpYy53aGF0c2FwcC5uZXQvcnNyYy5waHAvdjMveUgvci9aTGNLT2JOdU8xYi5qcz9fbmNfeD1JajNXcDhsZzVLego=" data-bootloader-hash="678jA6i" data-p=":0" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><script src="data:application/x-javascript; charset=utf-8;base64,Oy8qRkJfUEtHX0RFTElNKi8KCihmdW5jdGlvbihhKXtmdW5jdGlvbiBiKGIpe2lmKCF3aW5kb3cub3BlbkRhdGFiYXNlKXJldHVybjtiLklfQU1fSU5DT0dOSVRPX0FORF9JX1JFQUxMWV9ORUVEX1dFQlNRTD1mdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gd2luZG93Lm9wZW5EYXRhYmFzZShhLGIsYyxkKX07d2luZG93Lm9wZW5EYXRhYmFzZT1mdW5jdGlvbigpe3Rocm93IG5ldyBFcnJvcigpfX1iKGEpfSkodGhpcyk7Ci8vIyBzb3VyY2VVUkw9aHR0cHM6Ly9zdGF0aWMud2hhdHNhcHAubmV0L3JzcmMucGhwL3YzL3lSL3IvLXBWQzBQRjQ0ZFkuanM/X25jX3g9SWozV3A4bGc1S3oK" data-bootloader-hash="k6/EjOG" data-p=":0" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"><Line truncated
<script type="application/json" data-content-len="92" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264-server","htmlStart",10]]]}</script>
<link type="text/css" rel="stylesheet" href="https://static.whatsapp.net/rsrc.php/v3/yv/l/0,cross/C-WCp2i_C8v1k_iwjHwlnlCsHvfmgKJ5t.css?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="yyAsU+g" crossorigin="anonymous" data-p=":19,14,8" data-c="1" />
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/yH/r/ht8oIC_2H5Y.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/yH/r/ht8oIC_2H5Y.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="VwZQdEs" async="1" crossorigin="anonymous" data-p=":1" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/yV/r/yJJyU7535wL.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/yV/r/yJJyU7535wL.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="Ji4B5gK" async="1" crossorigin="anonymous" data-p=":10" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/y3/r/GpR8XYkiC6brtOgQ7kvhNmryQSgyNOW8X.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/y3/r/GpR8XYkiC6brtOgQ7kvhNmryQSgyNOW8X.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="JoAZh6h" async="1" crossorigin="anonymous" data-p=":5,20,4" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/y3/r/y6YE2mWjTXs.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/y3/r/y6YE2mWjTXs.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="DbA7bqQ" async="1" crossorigin="anonymous" data-p=":3" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3iPAE4/yj/l/rt/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3iPAE4/yj/l/rt/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="EMb+P2t" async="1" crossorigin="anonymous" data-tsrc="https://static.whatsapp.net/rsrc-translations.php/v6iPAE4/y5/l/en_US/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz" data-p=":12" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><link rel="preload" href="https://static.whatsapp.net/rsrc-translations.php/v6iPAE4/y5/l/en_US/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz" as="fetch" crossorigin="anonymous" />
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3iL1C4/yq/l/rt/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3iL1C4/yq/l/rt/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="7mVyh6g" async="1" crossorigin="anonymous" data-tsrc="https://static.whatsapp.net/rsrc-translations.php/v6iL1C4/y1/l/en_US/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz" data-p=":7" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><link rel="preload" href="https://static.whatsapp.net/rsrc-translations.php/v6iL1C4/y1/l/en_US/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz" as="fetch" crossorigin="anonymous" />
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3iD_74/yY/l/rt/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3iD_74/yY/l/rt/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="l5bRwHF" async="1" crossorigin="anonymous" data-tsrc="https://static.whatsapp.net/rsrc-translations.php/v6iD_74/y0/l/en_US/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz" data-p=":18,2,11" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script><link rel="preload" href="https://static.whatsapp.net/rsrc-translations.php/v6iD_74/y0/l/en_US/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz" as="fetch" crossorigin="anonymous" />
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/yD/r/mY5slrRbdpI.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/yD/r/mY5slrRbdpI.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="l3EfnwR" async="1" crossorigin="anonymous" data-p=":6" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/yt/r/fyeayg1M_Ow.js?_nc_x=Ij3Wp8lg5Kz" as="script" crossorigin="anonymous" nonce="6GV2UyzI" /><script src="https://static.whatsapp.net/rsrc.php/v3/yt/r/fyeayg1M_Ow.js?_nc_x=Ij3Wp8lg5Kz" data-bootloader-hash="lkjhq5M" async="1" crossorigin="anonymous" data-p=":13" data-btmanifest="1014522270_main" data-c="1" nonce="6GV2UyzI"></script>
<script type="application/json" data-content-len="469" data-sjs>{"require":[["MakeHasteTranslations","fetchTranslationsForEarlyFlush",null,[{"EMb+P2t":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iPAE4\/y5\/l\/en_US\/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz","7mVyh6g":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iL1C4\/y1\/l\/en_US\/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz","l5bRwHF":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iD_74\/y0\/l\/en_US\/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz"}]]]}</script>
<!--EF-->
<title>WhatsApp Web</title>
<script type="application/json" data-content-len="921" data-sjs>{"require":[["HasteSupportData","handle",null,[{"gkxData":{"2199":{"result":false,"hash":null},"7742":{"result":false,"hash":null},"20935":{"result":true,"hash":null},"20936":{"result":false,"hash":null},"209":{"result":false,"hash":null},"4377":{"result":true,"hash":null},"21075":{"result":false,"hash":null},"21076":{"result":true,"hash":null},"22792":{"result":false,"hash":null},"3867":{"result":false,"hash":null},"4341":{"result":false,"hash":null},"9861":{"result":false,"hash":null},"21062":{"result":false,"hash":null},"21063":{"result":false,"hash":null},"21069":{"result":false,"hash":null},"21071":{"result":false,"hash":null},"21072":{"result":false,"hash":null},"33056":{"result":false,"hash":null}},"qexData":{"526":{"r":null},"538":{"r":null},"543":{"r":null},"104":{"r":null},"128":{"r":null},"344":{"r":null},"372":{"r":null},"388":{"r":null},"1604":{"r":null}},"justknobxData":{"1806":{"r":true}}}]]]}</script>
<link type="text/css" rel="stylesheet" href="data:text/css; charset=utf-8,._apdl&#123;align-items:center;background-color:var(--splashscreen-startup-background);display:flex;flex-direction:column;height:100%;justify-content:center;left:0;position:fixed;top:0;-webkit-user-select:none;width:100%&#125;._apdl ._apdm&#123;margin-top:-40px;color:var(--splashscreen-startup-icon)&#125;._apdl ._apdm::after&#123;animation:shimmer 1.5s linear .6s infinite;background:linear-gradient( to right, rgba(var(--splashscreen-startup-background-rgb), .5) 0%, rgba(var(--splashscreen-startup-background-rgb), .5) 33.33%, rgba(var(--splashscreen-startup-background-rgb), 0) 44.1%, rgba(var(--splashscreen-startup-background-rgb), 0) 55.8%, rgba(var(--splashscreen-startup-background-rgb), .5) 66.66%, rgba(var(--splashscreen-startup-background-rgb), .5) 100% );content:&#039;&#039;;position:relative;top:-100%;display:block;height:100%;left:calc(50% - 72px);opacity:1;width:calc(72px * 3)&#125;&#064;keyframes shimmer&#123;from&#123;left:calc(50% - 72px)&#125;to&#123;left:calc(50% + 72px)&#125;&#125;._apdl ._apdq&#123;height:3px;margin-top:40px;position:relative;width:320px&#125;._apdl ._apdq progress&#123;vertical-align:top&#125;._apdl ._apdr&#123;margin-top:40px;font-size:17px;color:var(--splashscreen-primary-title)&#125;._apdl ._apds&#123;margin-top:12px;font-size:14px;color:var(--splashscreen-secondary-lighter)&#125;._apdl ._apds span&#123;display:inline-block;margin-bottom:2px;vertical-align:middle&#125;._apdl ._apdq progress&#123;-webkit-appearance:none;background-color:var(--splashscreen-progress-background);border:none;color:var(--splashscreen-progress-primary);height:3px;margin:0;vertical-align:-0.2em;width:100%&#125;._apdl ._apdq progress[value]::-webkit-progress-bar&#123;background-color:var(--splashscreen-progress-background)&#125;._apdl ._apdq progress[value]::-webkit-progress-value&#123;background-color:var(--splashscreen-progress-primary);transition:width .45s ease&#125;%23bootloader_z3kVBe5&#123;height:42px;&#125;.bootloader_z3kVBe5&#123;display:block!important;&#125;" data-bootloader-hash="z3kVBe5" data-p=":0" data-c="1" />
</head><body class=""><div id="wa_web_initial_startup" class="_apdl"><div style="transform: translate(calc(50% - 52px / 2))" class="_apdm"><span><svg width="250" height="52" xmlns="http://www.w3.org/2000/svg"><path d="M37.7 31.2c-.6-.4-3.8-2-4.4-2.1-.6-.2-1-.4-1.4.3l-2 2.5c-.4.4-.8.5-1.5.2-.6-.3-2.7-1-5.1-3.2-2-1.7-3.2-3.8-3.6-4.5-.4-.6 0-1 .3-1.3l1-1.1.6-1.1c.2-.4 0-.8 0-1.1l-2-4.8c-.6-1.3-1.1-1-1.5-1.1h-1.2c-.5 0-1.2.1-1.8.8-.5.6-2.2 2.2-2.2 5.3 0 3.2 2.3 6.3 2.6 6.7.3.4 4.6 7 11 9.7l3.7 1.4c1.5.5 3 .4 4 .2 1.3-.1 3.9-1.5 4.4-3 .5-1.5.5-2.8.4-3-.2-.4-.6-.5-1.3-.8M26 47.2c-3.9 0-7.6-1-11-3l-.7-.4-8.1 2L8.4 38l-.6-.8A21.4 21.4 0 0126 4.4a21.3 21.3 0 0121.4 21.4c0 11.8-9.6 21.4-21.4 21.4M44.2 7.6a25.8 25.8 0 00-40.6 31L0 52l13.7-3.6A25.8 25.8 0 0044.3 7.5" fill="currentColor"></path></svg></span></div><div class="_apdq"><progress value="0" max="100" dir="ltr"></progress></div><div class="_apdr">WhatsApp</div><div class="_apds"><span><svg width="10" height="12" xmlns="http://www.w3.org/2000/svg"><path d="M5 1.6c1.4 0 2.5 1 2.6 2.4v1.5h.2c.5 0 1 .4 1 1V10c0 .6-.5 1-1 1H2.3a1 1 0 01-1.1-1V6.5c0-.6.5-1 1-1h.2V4.2c0-1.4 1-2.5 2.4-2.6H5zm0 1.2c-.7 0-1.3.6-1.3 1.3v1.4h2.6V4.2c0-.7-.4-1.2-1-1.3H5z" fill="currentColor"></path></svg></span><span> </span>End-to-end encrypted</div></div><script type="application/json" data-content-len="91" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","splash_screen_show"]]]}</script>
<div id="mount_0_0_Zy"></div>
<script type="application/json" data-content-len="53" data-sjs>{"require":[["maybeDisableAnimations",null,null,[]]]}</script>
<script type="application/json" data-content-len="49" data-sjs>{"require":[["replaceNativeTimer",null,null,[]]]}</script>
<script type="application/json" data-content-len="60" data-sjs>{"require":[["bootstrapWebSession",null,null,[1719469077]]]}</script>
<script type="application/json" data-content-len="108" data-sjs>{"require":[["qplTagServerJS",null,null,[["comet_aa_coinflip:true","should_use_bt_safe_js","logged_out"]]]]}</script>
<script type="application/json" data-content-len="157" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierOne"]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierOne",15]]]}</script>
<script type="application/json" data-content-len="76" data-sjs>{"require":[["JSScheduler","makeSchedulerGlobalEntry",null,["null",false]]]}</script>
<script type="application/json" data-content-len="1883" data-sjs>{"require":[["ScheduledServerJS","handle",null,[{"__bbox":{"define":[["cr:734",[],{"__rc":[null,null]},-1],["cr:1293",["ReactDOM.classic"],{"__rc":["ReactDOM.classic",null]},-1],["cr:4874",[],{"__rc":[null,null]},-1],["cr:6640",[],{"__rc":[null,null]},-1],["cr:7162",["ReactDOMCompatibilityLayer"],{"__rc":["ReactDOMCompatibilityLayer",null]},-1],["cr:7451",[],{"__rc":[null,null]},-1],["cr:1064332",[],{"__rc":[null,null]},-1],["cr:1106516",[],{"__rc":[null,null]},-1],["cr:1108857",[],{"__rc":[null,null]},-1],["cr:1294158",["React.classic"],{"__rc":["React.classic",null]},-1],["cr:1294159",["ReactDOM.classic"],{"__rc":["ReactDOM.classic",null]},-1],["UriNeedRawQuerySVConfig",[],{"uris":["dms.netmng.com","doubleclick.net","r.msn.com","watchit.sky.com","graphite.instagram.com","www.kfc.co.th","learn.pantheon.io","www.landmarkshops.in","www.ncl.com","s0.wp.com","www.tatacliq.com","bs.serving-sys.com","kohls.com","lazada.co.th","xg4ken.com","technopark.ru","officedepot.com.mx","bestbuy.com.mx","booking.com","nibio.no","myworkdayjobs.com","united-united.com","gcc.gnu.org"]},3871],["cr:5277",["ReactDOM.classic.prod-or-profiling"],{"__rc":["ReactDOM.classic.prod-or-profiling",null]},-1],["cr:1292365",["React-prod.classic"],{"__rc":["React-prod.classic",null]},-1],["cr:5278",["ReactDOM-prod.classic"],{"__rc":["ReactDOM-prod.classic",null]},-1],["cr:5695",["EventListenerWWW"],{"__rc":["EventListenerWWW",null]},-1],["cr:8909",["ReactFiberErrorDialogWWW"],{"__rc":["ReactFiberErrorDialogWWW",null]},-1],["cr:1353359",["CometEventListener"],{"__rc":["CometEventListener",null]},-1]],"require":[["WAWebCometRoot","init",[],[{"elementId":"mount_0_0_Zy"}]]]}},{"__bbox":{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierOneBeforeScheduler"]]]}},{"__bbox":{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierOneInsideScheduler"]]]}}]]]}</script>
<script type="application/json" data-content-len="83" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierOneEnd"]]]}</script>
<script type="application/json" data-content-len="157" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierTwo"]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierTwo",33]]]}</script>
<script type="application/json" data-content-len="2275" data-sjs>{"require":[["HasteSupportData","handle",null,[{"bxData":{"9547":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yl\/r\/gi_DckOUM5a.png"},"9548":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y_\/r\/TPtFe9SpDSX.png"},"9555":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y4\/r\/XEPQuYy90FJ.png"},"9556":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/ye\/r\/fWOSgX_xpHG.png"},"9561":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yW\/r\/BS_BUUXbKq5.mp3"},"9562":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yu\/r\/lsK0FC6wi8C.m4a"},"10639":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y3\/r\/AZwgE-H9Ubq.png"},"11319":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yX\/r\/JYPizEwERE4.png"},"11370":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y-\/r\/_8J_xqERSbv.png"}},"clpData":{"6476":{"r":1000,"s":1},"1744178":{"r":1,"s":1},"1838142":{"r":1,"s":1}},"gkxData":{"1624":{"result":false,"hash":null},"2160":{"result":false,"hash":null},"20836":{"result":false,"hash":null},"20940":{"result":false,"hash":null},"21043":{"result":false,"hash":null},"21050":{"result":false,"hash":null},"21051":{"result":false,"hash":null},"21052":{"result":false,"hash":null},"21053":{"result":false,"hash":null},"21054":{"result":false,"hash":null},"21055":{"result":false,"hash":null},"21056":{"result":false,"hash":null},"21057":{"result":false,"hash":null},"21058":{"result":true,"hash":null},"21106":{"result":true,"hash":null},"21107":{"result":false,"hash":null},"21112":{"result":true,"hash":null},"26256":{"result":false,"hash":null},"26258":{"result":true,"hash":null},"26259":{"result":false,"hash":null},"26260":{"result":false,"hash":null},"26261":{"result":false,"hash":null},"26262":{"result":true,"hash":null},"26264":{"result":true,"hash":null},"26265":{"result":false,"hash":null}},"qplData":{"106":{}},"justknobxData":{"371":{"r":true},"819":{"r":true},"860":{"r":100},"1617":{"r":155},"1618":{"r":8},"1619":{"r":1},"1620":{"r":2},"1621":{"r":4},"1622":{"r":0},"1623":{"r":6},"1624":{"r":1},"1662":{"r":2},"1663":{"r":14},"1664":{"r":2},"1784":{"r":false},"1854":{"r":false},"2086":{"r":3},"2148":{"r":false},"2157":{"r":true},"2237":{"r":false},"2268":{"r":true},"2269":{"r":true},"2434":{"r":true},"2552":{"r":false}}}]]]}</script>
<script type="application/json" data-content-len="30862" data-sjs>{"require":[["Bootloader","handlePayload",null,[{"consistency":{"rev":1014522270},"rsrcMap":{"4miG4t2":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yV\/r\/0gGYzfda2Tu.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":22","m":"1014522270_main"},"xFqg8AH":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yL\/r\/BlIuoNYtWPV.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":130","m":"1014522270_main"},"N4JDUAh":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/ye\/r\/bgg-9nYiLie.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":129","m":"1014522270_main"},"KBlGRAN":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yJ\/r\/nZUOmP0lYjZ.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":38","m":"1014522270_main"},"Kyj0DuM":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yE\/r\/CtlyoX5avh8.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":39","m":"1014522270_main"},"SWdcOen":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yk\/r\/tbbvhRiHhRw.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":71","m":"1014522270_main"},"1qIb1yr":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3ihVQ4\/ye\/l\/rt\/0FlCLfP5vYk.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6ihVQ4\/yS\/l\/en_US\/0FlCLfP5vYk.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":139","m":"1014522270_main"},"\/t7V6uL":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yI\/r\/Btaw39H8ma_.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":137","m":"1014522270_main"},"oStldiG":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yQ\/r\/Q4Zwg9r5_k1.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":68","m":"1014522270_main"},"jqmgzqL":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yG\/r\/ujDtbDfS_gy.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":69","m":"1014522270_main"},"BYy6KKX":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yO\/r\/_WxPYKNWneH.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":33","m":"1014522270_main"},"aoCs1Zg":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yH\/r\/XAD9_Dadb7D.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":88","m":"1014522270_main"},"aOYtth2":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/ye\/r\/iTqPNvdt0YL.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":42","m":"1014522270_main"},"NFGWH2r":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yw\/r\/bfsDWnduEyW.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":103","m":"1014522270_main"},"4QR59xK":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yP\/r\/6naoD9b2OZ5.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":67","m":"1014522270_main"},"06faHSS":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yh\/r\/uvxX-bsXSXt.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":155","m":"1014522270_main"},"onUpzfh":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yF\/r\/K6cSPvkmzMT.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":124","m":"1014522270_main"},"RHKXYV8":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yq\/r\/oucl0iRauKC.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":107","m":"1014522270_main"},"oVqtAlG":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yf\/r\/E8FehGQkWo7.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":106","m":"1014522270_main"},"P+W1C4N":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yY\/r\/hu7wNvLGe08.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":98","m":"1014522270_main"},"tw8mmSb":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yR\/r\/FZvPKCUdiMg.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":164","m":"1014522270_main"},"TmxCppI":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yT\/r\/vIKHDl0uM89.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":49","m":"1014522270_main"},"MkjpUky":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yx\/r\/daSMG4f170B.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":92","m":"1014522270_main"},"IDB3BEc":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y-\/r\/zoLfZ0IIEoQ.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":222","m":"1014522270_main"},"S25OcLy":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y9\/r\/ehQ6J4BH-Y5.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":146","m":"1014522270_main"},"7yT1nwq":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/ya\/r\/eeqAy7Pc9tB.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":30493","m":"1014522270_longtail"},"hxw7aRX":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yW\/r\/o0te43Nno_1.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":125","m":"1014522270_main"},"dax04J6":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yp\/r\/UuEvisQ2dNi.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":236","m":"1014522270_main"},"bhIV+ni":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yR\/r\/_57wqNSBfQp.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":244","m":"1014522270_main"},"9XxF5Q5":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y-\/r\/tU8GWxL8l8P.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":192","m":"1014522270_main"},"AT3ZkSW":{"type":"js","src":"https:\Line truncated
<script type="application/json" data-content-len="20293" data-sjs>{"require":[["ScheduledServerJS","handle",null,[{"__bbox":{"define":[["cr:310",["RunWWW"],{"__rc":["RunWWW",null]},-1],["cr:686",[],{"__rc":[null,null]},-1],["cr:1078",[],{"__rc":[null,null]},-1],["cr:1080",["unexpectedUseInComet"],{"__rc":["unexpectedUseInComet",null]},-1],["cr:1126",["TimeSliceSham"],{"__rc":["TimeSliceSham",null]},-1],["cr:3128",[],{"__rc":[null,null]},-1],["cr:3979",[],{"__rc":[null,null]},-1],["cr:4066",[],{"__rc":[null,null]},-1],["cr:4122",[],{"__rc":[null,null]},-1],["cr:4324",[],{"__rc":[null,null]},-1],["cr:4330",[],{"__rc":[null,null]},-1],["cr:4533",[],{"__rc":[null,null]},-1],["cr:4722",[],{"__rc":[null,null]},-1],["cr:4857",[],{"__rc":[null,null]},-1],["cr:4940",[],{"__rc":[null,null]},-1],["cr:4941",[],{"__rc":[null,null]},-1],["cr:4943",[],{"__rc":[null,null]},-1],["cr:5151",[],{"__rc":[null,null]},-1],["cr:5291",[],{"__rc":[null,null]},-1],["cr:5292",[],{"__rc":[null,null]},-1],["cr:5411",[],{"__rc":[null,null]},-1],["cr:5624",["WAWebCleanAssets"],{"__rc":["WAWebCleanAssets",null]},-1],["cr:5664",[],{"__rc":[null,null]},-1],["cr:5981",[],{"__rc":[null,null]},-1],["cr:6000",[],{"__rc":[null,null]},-1],["cr:6007",[],{"__rc":[null,null]},-1],["cr:6009",[],{"__rc":[null,null]},-1],["cr:6013",[],{"__rc":[null,null]},-1],["cr:6022",["WAWebFeatureDetectionSwSupport"],{"__rc":["WAWebFeatureDetectionSwSupport",null]},-1],["cr:7385",["clearIntervalWWW"],{"__rc":["clearIntervalWWW",null]},-1],["cr:7386",["clearTimeoutWWW"],{"__rc":["clearTimeoutWWW",null]},-1],["cr:7389",["setIntervalAcrossTransitionsWWW"],{"__rc":["setIntervalAcrossTransitionsWWW",null]},-1],["cr:7390",["setTimeoutWWW"],{"__rc":["setTimeoutWWW",null]},-1],["cr:7391",["setTimeoutAcrossTransitionsWWW"],{"__rc":["setTimeoutAcrossTransitionsWWW",null]},-1],["cr:7730",["getFbtResult"],{"__rc":["getFbtResult",null]},-1],["cr:7907",[],{"__rc":[null,null]},-1],["cr:8958",["FBJSON"],{"__rc":["FBJSON",null]},-1],["cr:8959",["DTSG"],{"__rc":["DTSG",null]},-1],["cr:8960",["DTSG_ASYNC"],{"__rc":["DTSG_ASYNC",null]},-1],["cr:9713",[],{"__rc":[null,null]},-1],["cr:696703",["JSScheduler"],{"__rc":["JSScheduler",null]},-1],["cr:951783",[],{"__rc":[null,null]},-1],["cr:1984081",[],{"__rc":[null,null]},-1],["IntlCurrentLocale",[],{"code":"en_US"},5954],["WAMediaWasmWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yz\/r\/iqQa0jgcX_h.js?_nc_x=Ij3Wp8lg5Kz","name":"WAMediaWasmWorkerBundle","dynamicModules":{"cr:6640":{"__bbox":{"__rc":[null,null]}}},"hsdp":{"bxData":{"236":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/y_\/r\/IbbOXFaNJTy.wasm"},"6945":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yO\/r\/tL59TT3QfUA.wasm"},"6946":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yf\/r\/rogm88TRRiw.wasm"}},"qplData":{"106":{}}}},7438],["CookiePrivacySandboxConfig",[],{"is_affected_by_samesite_lax":false},7723],["WAWebMediaWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yK\/r\/PzZ2siM8S-2.js?_nc_x=Ij3Wp8lg5Kz","name":"WAMediaWorkerBundle","useInitScript":true},7034],["CometPersistQueryParams",[],{"relative":{},"domain":{}},6231],["CookieDomain",[],{"domain":"whatsapp.com"},6421],["IntlVariationHoldout",[],{"disable_variation":false},6533],["IntlNumberTypeProps",["IntlCLDRNumberType05"],{"module":{"__m":"IntlCLDRNumberType05"}},7027],["WAWebRgbaToWebpWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y-\/r\/numw29EV6UR.js?_nc_x=Ij3Wp8lg5Kz","name":"WAWebRgbaToWebpWorkerBundle","dynamicModules":{"cr:6640":{"__bbox":{"__rc":[null,null]}}},"hsdp":{}},7480],["WAWebFtsWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yc\/r\/lRajA4A_zrm.js?_nc_x=Ij3Wp8lg5Kz","name":"WAWebFtsWorkerBundle","dynamicModules":{"cr:6640":{"__bbox":{"__rc":[null,null]}}},"hsdp":{"gkxData":{"26258":{"result":true,"hash":null},"26259":{"result":false,"hash":null}},"justknobxData":{"1617":{"r":155},"1618":{"r":8},"1619":{"r":1},"1620":{"r":2},"1621":{"r":4},"1622":{"r":0},"1623":{"r":6},"1624":{"r":1},"1662":{"r":2},"1663":{"r":14},"1664":{"r":2},"1854":{"r":false}}}},7301],["WAWebOpusRecorderWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yw\/r\/_OjcNvgJb7R.js?_nc_x=Ij3Wp8lg5Kz","name":"WAWebOpusRecorderWorkerBundle","hsdp":{}},7347],["WAWebWebpToRgbaWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yi\/r\/e0-X3rIGNEC.js?_nc_x=Ij3Wp8lg5Kz","name":"WAWebWebpToRgbaWorkerBundle","dynamicModules":{"cr:6640":{"__bbox":{"__rc":[null,null]}}},"hsdp":{}},7481],["GetAsyncParamsExtraData",[],{"extra_data":{}},7511],["BootloaderConfig",[],{"deferBootloads":false,"jsRetries":[200,500],"jsRetryAbortNum":2,"jsRetryAbortTime":5,"silentDups":true,"timeout":60000,"tieredLoadingFromTier":100,"hypStep4":true,"phdOn":false,"btCutoffIndex":259,"fastPathForAlreadyRequired":true,"earlyRequireLazy":false,"enableTimeoutLoggingForNonComet":false,"deferLongTailManifest":true,"lazySoT":false,"transLine truncated
<script type="application/json" data-content-len="83" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierTwoEnd"]]]}</script>
<script type="application/json" data-content-len="161" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierThree"]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierThree",51]]]}</script>
<link rel="preload" href="https://static.whatsapp.net/rsrc.php/v3/yw/l/0,cross/J-dbIEvJjBeMKI_FluK_QX.css?_nc_x=Ij3Wp8lg5Kz" as="style" crossorigin="anonymous" />
<script type="application/json" data-content-len="2043" data-sjs>{"require":[["HasteSupportData","handle",null,[{"bxData":{"482":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yS\/r\/aGcVD59xVTb.png"},"484":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y6\/r\/wa669aeJeom.png"},"9544":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yv\/r\/6Ib-MkrweJ6.ttf"},"9545":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yk\/r\/ln-uwGsChQW.ttf"},"9546":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yf\/r\/4l5Jzvrg84p.png"},"9551":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yq\/r\/xCHrap4ZvgY.png"},"9552":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y6\/r\/R6k6NrF2Cbl.png"},"9553":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yd\/r\/jLlIEwASpgj.png"},"9554":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y5\/r\/_U7GO8EnPFR.png"},"9559":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yy\/r\/noBSk9ItwJJ.png"},"9563":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yQ\/r\/WElxnwAGYY2.mp3"},"9564":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yv\/r\/ze2kHBOq8T0.mp3"},"9583":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yP\/r\/re6de1QF8pQ.png"},"10047":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v1\/y6\/r\/kNeGAbVVWRf.jpg"},"10591":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yp\/r\/ReKDgNfJEFB.png"},"14943":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/ye\/r\/W2MDyeo0zkf.png"},"9557":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y5\/r\/cJXjAoffU5Q.png"},"9558":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yB\/r\/7Y1jh45L_8V.png"},"9565":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yn\/r\/6swO8kJM8z2.mp4"},"9566":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/yk\/r\/GoZyw2bTK6s.mp4"},"9560":{"uri":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yo\/r\/Oh4t5oP-H5G.png"}},"clpData":{"1837559":{"r":1},"1848815":{"r":10000,"s":1},"1828945":{"r":100,"s":1},"5779":{"r":100,"s":1}},"justknobxData":{"2454":{"r":false},"2450":{"r":true},"2451":{"r":true},"2452":{"r":false},"2453":{"r":false}}}]]]}</script>
<script type="application/json" data-content-len="53047" data-sjs>{"require":[["Bootloader","handlePayload",null,[{"consistency":{"rev":1014522270},"rsrcMap":{"XGxTRzz":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iMK54\/yW\/l\/rt\/bMaImlcHRUG.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iMK54\/y2\/l\/en_US\/bMaImlcHRUG.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":32","m":"1014522270_main"},"mRZc\/dz":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yx\/r\/m96dxlCrt6Y.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":26","m":"1014522270_main"},"eGE9FvR":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3i0ta4\/yi\/l\/rt\/Ad_ijr7_dvd.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6i0ta4\/ym\/l\/en_US\/Ad_ijr7_dvd.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":23","m":"1014522270_main"},"ssxIBpF":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yZ\/r\/FPlNguXyB9e0gGYzfda2TufH5Ma2uwGKhY6Mk0m90rCLDQVEH-g-FDC.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":30,22,15,16,9","m":"1014522270_main"},"GkupZaS":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iCqe4\/yL\/l\/rt\/2gPPVV2aJv5.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iCqe4\/yu\/l\/en_US\/2gPPVV2aJv5.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":25","m":"1014522270_main"},"EKhm2GG":{"type":"css","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yw\/l\/0,cross\/J-dbIEvJjBeMKI_FluK_QX.css?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":27,31"},"IYqO5iZ":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yt\/r\/ZqmYe3zRs7G.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":17","m":"1014522270_main"},"tslua06":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3i9SF4\/yS\/l\/rt\/Z3qyCROs6-7.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6i9SF4\/yp\/l\/en_US\/Z3qyCROs6-7.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":24","m":"1014522270_main"},"aQxqT5q":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3ifY44\/yE\/l\/rt\/YaSkaFGEr-I.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6ifY44\/y6\/l\/en_US\/YaSkaFGEr-I.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":35","m":"1014522270_main"},"DrHIMI8":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iteW4\/yc\/l\/rt\/3apowRxtrqR.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iteW4\/yE\/l\/en_US\/3apowRxtrqR.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":131","m":"1014522270_main"},"sevwJOE":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iOwq4\/y0\/l\/rt\/k5EhubSdxpm.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iOwq4\/y6\/l\/en_US\/k5EhubSdxpm.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":21","m":"1014522270_main"},"DcG2ejT":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3ipMd4\/y0\/l\/rt\/GquHjbFn54u.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6ipMd4\/yL\/l\/en_US\/GquHjbFn54u.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":153","m":"1014522270_main"},"YS\/UrnR":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iXDa4\/yV\/l\/rt\/Zz-Ouubt7zy.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iXDa4\/yS\/l\/en_US\/Zz-Ouubt7zy.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":34","m":"1014522270_main"},"zG5Hlng":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yy\/r\/OkuaRXwmGgU.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":28","m":"1014522270_main"},"0SXrVmz":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iuDY4\/y0\/l\/rt\/vA2-0lRViF_.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iuDY4\/yM\/l\/en_US\/vA2-0lRViF_.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":29","m":"1014522270_main"},"kLGrgwC":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3inji4\/yG\/l\/rt\/vWzRuWZmn1W.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6inji4\/yj\/l\/en_US\/vWzRuWZmn1W.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":174","m":"1014522270_main"},"hikr3RH":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iYv84\/yJ\/l\/rt\/N41CKm1lGBa.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iYv84\/yj\/l\/en_US\/N41CKm1lGBa.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":57","m":"1014522270_main"},"fY+RSol":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iNj84\/y9\/l\/rt\/6rn8EUgGGpB.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/rsrc-translations.php\/v6iNj84\/yI\/l\/en_US\/6rn8EUgGGpB.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":122","m":"1014522270_main"},"\/9QLqMI":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yb\/r\/qXYvgBWQS1q.js?_nc_x=Ij3Wp8lg5Kz","c":1,"p":":113","m":"1014522270_main"},"rfKxJtC":{"type":"js","src":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iJyQ4\/yM\/l\/rt\/Ul0GyaekHhI.js?_nc_x=Ij3Wp8lg5Kz","tsrc":"https:\/\/static.whatsapp.net\/Line truncated
<script type="application/json" data-content-len="130" data-sjs>{"require":[["DeferredJSResourceScheduler",null,null,[["XGxTRzz","mRZc\/dz","eGE9FvR","ssxIBpF","GkupZaS","IYqO5iZ","tslua06"]]]]}</script>
<script type="application/json" data-content-len="7789" data-sjs>{"require":[["ScheduledServerJSWithCSS","handle",null,[{"__bbox":{"define":[["cr:104",[],{"__rc":[null,null]},-1],["cr:291",["ReactDOMServer-prod.modern"],{"__rc":["ReactDOMServer-prod.modern",null]},-1],["cr:293",["LexicalHistoryPlugin.prod"],{"__rc":["LexicalHistoryPlugin.prod",null]},-1],["cr:370",["Lexical.prod"],{"__rc":["Lexical.prod",null]},-1],["cr:427",["LexicalComposer.prod"],{"__rc":["LexicalComposer.prod",null]},-1],["cr:509",["LexicalComposerContext.prod"],{"__rc":["LexicalComposerContext.prod",null]},-1],["cr:629",[],{"__rc":[null,null]},-1],["cr:739",["LexicalPlainTextPlugin.prod"],{"__rc":["LexicalPlainTextPlugin.prod",null]},-1],["cr:988",["LexicalTreeView.prod"],{"__rc":["LexicalTreeView.prod",null]},-1],["cr:1066",[],{"__rc":[null,null]},-1],["cr:2015",[],{"__rc":[null,null]},-1],["cr:2120",["LexicalClearEditorPlugin.prod"],{"__rc":["LexicalClearEditorPlugin.prod",null]},-1],["cr:2180",["LexicalSelection.prod"],{"__rc":["LexicalSelection.prod",null]},-1],["cr:2260",["LexicalErrorBoundary.prod"],{"__rc":["LexicalErrorBoundary.prod",null]},-1],["cr:2774",["LexicalUtils.prod"],{"__rc":["LexicalUtils.prod",null]},-1],["cr:3107",[],{"__rc":[null,null]},-1],["cr:5037",[],{"__rc":[null,null]},-1],["cr:5685",[],{"__rc":[null,null]},-1],["cr:5735",[],{"__rc":[null,null]},-1],["cr:5736",[],{"__rc":[null,null]},-1],["cr:5923",[],{"__rc":[null,null]},-1],["cr:5932",[],{"__rc":[null,null]},-1],["cr:5959",[],{"__rc":[null,null]},-1],["cr:5990",[],{"__rc":[null,null]},-1],["cr:5993",[],{"__rc":[null,null]},-1],["cr:5994",[],{"__rc":[null,null]},-1],["cr:5997",[],{"__rc":[null,null]},-1],["cr:6003",[],{"__rc":[null,null]},-1],["cr:6004",[],{"__rc":[null,null]},-1],["cr:6005",[],{"__rc":[null,null]},-1],["cr:6006",[],{"__rc":[null,null]},-1],["cr:6010",[],{"__rc":[null,null]},-1],["cr:6018",[],{"__rc":[null,null]},-1],["cr:6019",[],{"__rc":[null,null]},-1],["cr:6842",[],{"__rc":[null,null]},-1],["cr:6862",[],{"__rc":[null,null]},-1],["cr:7456",[],{"__rc":[null,null]},-1],["cr:8723",[],{"__rc":[null,null]},-1],["cr:8750",[],{"__rc":[null,null]},-1],["cr:8751",[],{"__rc":[null,null]},-1],["cr:8752",[],{"__rc":[null,null]},-1],["cr:8753",[],{"__rc":[null,null]},-1],["cr:9051",[],{"__rc":[null,null]},-1],["cr:30",[],{"__rc":[null,null]},-1],["cr:8828",[],{"__rc":[null,null]},-1],["cr:1094907",[],{"__rc":[null,null]},-1],["WAWebWebpToAnimationFramesWorkerResource",[],{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yj\/r\/keURb6s4gBJ.js?_nc_x=Ij3Wp8lg5Kz","name":"WAWebWebpToAnimationFramesWorkerBundle","dynamicModules":{"cr:6640":{"__bbox":{"__rc":[null,null]}}},"hsdp":{}},7485],["cr:4986",[],{"__rc":[null,null]},-1],["cr:7004",["ReactReconcilerConstants.classic"],{"__rc":["ReactReconcilerConstants.classic",null]},-1],["cr:7007",["ReactReconciler.classic"],{"__rc":["ReactReconciler.classic",null]},-1],["cr:2695",[],{"__rc":[null,null]},-1],["cr:6008",[],{"__rc":[null,null]},-1],["cr:2904",["LexicalHistory.prod"],{"__rc":["LexicalHistory.prod",null]},-1],["cr:2181",["LexicalText.prod"],{"__rc":["LexicalText.prod",null]},-1],["cr:2903",["LexicalDragon.prod"],{"__rc":["LexicalDragon.prod",null]},-1],["cr:2909",["LexicalPlainText.prod"],{"__rc":["LexicalPlainText.prod",null]},-1],["cr:4793",["useLexicalEditable.prod"],{"__rc":["useLexicalEditable.prod",null]},-1],["cr:9917",["LexicalDevtoolsCore.prod"],{"__rc":["LexicalDevtoolsCore.prod",null]},-1],["cr:7002",["ReactReconcilerConstants-prod.classic"],{"__rc":["ReactReconcilerConstants-prod.classic",null]},-1],["cr:6994",["ReactReconciler-prod.classic"],{"__rc":["ReactReconciler-prod.classic",null]},-1],["cr:862",["LexicalClipboard.prod"],{"__rc":["LexicalClipboard.prod",null]},-1],["cr:1497",["LexicalHtml.prod"],{"__rc":["LexicalHtml.prod",null]},-1],["cr:1950",["LexicalTable.prod"],{"__rc":["LexicalTable.prod",null]},-1],["cr:2905",["LexicalLink.prod"],{"__rc":["LexicalLink.prod",null]},-1],["cr:3295",["LexicalMark.prod"],{"__rc":["LexicalMark.prod",null]},-1]],"require":[["CometSuspenseFalcoEvent"],["WAWebMainWrapper"],["WAFtsMultiLangTokenizer"],["WAWebEmojiAssetLoaderConfig"],["asn1js-2.1.1"],["WAWebEmojiAssetLoader"],["WAWebSetWorkerSafeHandlerApi"],["WAWebSetFrontendHandlerApi"],["WAWebPipVideoStreaming"],["WAWebLinkDevice.react"],["WAWebClearAppStates"],["FbtLogging"],["IntlQtEventFalcoEvent"],["emptyFunction","thatReturns",["RequireDeferredReference"],[[{"__dr":"CometSuspenseFalcoEvent"},{"__dr":"WAWebMainWrapper"},{"__dr":"WAFtsMultiLangTokenizer"},{"__dr":"WAWebEmojiAssetLoaderConfig"},{"__dr":"asn1js-2.1.1"},{"__dr":"WAWebEmojiAssetLoader"},{"__dr":"WAWebSetWorkerSafeHandlerApi"},{"__dr":"WAWebSetFrontendHandlerApi"},{"__dr":"WAWebPipVideoStreaming"},{"__dr":"WAWebLinkDevice.react"},{"__dr":"WAWebClearAppStates"},{"__dr":"FbtLogging"},{"__dr":"IntlQtEventFalcoEvent"}]]],["CometBTManifestLoader","init",[],[]],["ServiceWorkerCacheManagement","manageCache",[],[]],["WAWebEmojiSetup"],["BLine truncated
<script type="application/json" data-content-len="85" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264","tierThreeEnd"]]]}</script>
<script type="application/json" data-content-len="3705" data-sjs>{"require":[["CometQPLPayloadStore","storePayloadMap",null,[{"7385063454178867264":{"css\/7f2fjyjrk0cocg0s.pkg,css\/dkp7c20r8cg08o40.pkg,css\/a2k3bgidd4gsc8g0.pkg.__composite__.css":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yv\/l\/0,cross\/C-WCp2i_C8v1k_iwjHwlnlCsHvfmgKJ5t.css?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierOne","tierTwo","tierThree"]},"js\/1uuwsb5hks5c8c8s.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yH\/r\/ht8oIC_2H5Y.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierOne","tierTwo","tierThree"]},"js\/cuwb8pci4r48scww.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yV\/r\/yJJyU7535wL.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierOne","tierTwo"]},"js\/74ff0y83uq044k80.pkg,js\/7l01ghsx2tc04kcc.pkg,js\/boe4n1nexrwc0ws8.pkg.__composite__.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y3\/r\/GpR8XYkiC6brtOgQ7kvhNmryQSgyNOW8X.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierOne","tierTwo","tierThree"]},"js\/bjjs1pmj96gwss4w.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/y3\/r\/y6YE2mWjTXs.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierOne","tierTwo","tierThree"]},"js\/ckuz7ky8y9cssc8s.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iPAE4\/yj\/l\/rt\/3A4_-xOlNcy.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierTwo","tierThree"]},"js\/45xcw3rbngqo884k.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iL1C4\/yq\/l\/rt\/D6yUOPmld1J.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierTwo","tierThree"]},"js\/93xi0q6qcx0ksosc.pkg,js\/ajfm1uik02woo48s.pkg,js\/csa9qir353c4goc0.pkg.__composite__.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iD_74\/yY\/l\/rt\/OC6RHC1oEdtsQ3d6kRL04kvsWqehdEtWw.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierTwo","tierThree"]},"js\/cq8i5dizka0oow8o.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yD\/r\/mY5slrRbdpI.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierTwo","tierThree"]},"js\/bm1z2ax0ttkwg8w8.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yt\/r\/fyeayg1M_Ow.js?_nc_x=Ij3Wp8lg5Kz","refs":["htmlStart","tierTwo","tierThree"]},"css\/whatsapp\/web\/WhatsAppWebSplashScreen.css":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yt\/l\/0,cross\/ZrtiQW1FOc2.css?_nc_x=Ij3Wp8lg5Kz","refs":["tierOne"]},"js\/3iilb6qol88wkw0k.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iMK54\/yW\/l\/rt\/bMaImlcHRUG.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/38kxevuv39q8kgkc.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yx\/r\/m96dxlCrt6Y.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/dy1urilp36ogkcc8.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3i0ta4\/yi\/l\/rt\/Ad_ijr7_dvd.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/cdkr9wbfnr40ssg0.pkg,js\/7mvpi199fpwc44ss.pkg,js\/3121sq3e8pmo44k0.pkg,js\/7y8xjqkbm0w0kks8.pkg,js\/529myxqorq4gkcgw.pkg.__composite__.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yZ\/r\/FPlNguXyB9e0gGYzfda2TufH5Ma2uwGKhY6Mk0m90rCLDQVEH-g-FDC.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/bc0aut869zk84448.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3iCqe4\/yL\/l\/rt\/2gPPVV2aJv5.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"css\/ezxomokk1nw4w04k.pkg,css\/7bsaf1zhofk8c440.pkg.__composite__.css":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yw\/l\/0,cross\/J-dbIEvJjBeMKI_FluK_QX.css?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/dt5kj0sja4o4kwos.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3\/yt\/r\/ZqmYe3zRs7G.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]},"js\/8v1j52evupkwsc0o.pkg.js":{"url":"https:\/\/static.whatsapp.net\/rsrc.php\/v3i9SF4\/yS\/l\/rt\/Z3qyCROs6-7.js?_nc_x=Ij3Wp8lg5Kz","refs":["tierThree"]}}}]]]}</script>
<script type="application/json" data-content-len="69" data-sjs>{"require":[["qplTagServerJS",null,null,[["lastServerTagFlushed"]]]]}</script>
<script type="application/json" data-content-len="1381" data-sjs>{"require":[["qplTimingsServerJS",null,null,["7385063454178867264-server","earlyFlushStart",6]],["qplTimingsServerJS",null,null,["7385063454178867264-server","earlyFlushEnd",12]],["qplTimingsServerJS",null,null,["7385063454178867264-server","earlyFlush",12]],["qplTimingsServerJS",null,null,["7385063454178867264-server","cometPageRender",13]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierOneHasteResponseStart",14]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierOneHasteResponseEnd",15]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierOnePreloadersFinished",16]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierTwoHasteResponseStart",26]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierTwoHasteResponseEnd",32]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierTwoPreloadersFinished",34]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierThreeHasteResponseStart",39]],["qplTimingsServerJS",null,null,["7385063454178867264-server","genTierThreeHasteResponseEnd",50]],["qplTimingsServerJS",null,null,["7385063454178867264-server","tierThreePreloadersFinished",52]],["qplTimingsServerJS",null,null,["7385063454178867264-server","responseStart",1]],["qplTimingsServerJS",null,null,["7385063454178867264-server","responseEnd",53]]]}</script>
<script type="application/json" data-content-len="2" data-sjs>{}</script>
<script type="application/json" data-content-len="167" data-sjs>{"require":[["CometQPLPayloadStore","storePayloadBytesSent",null,[{"htmlStart":[15482,4730],"tierOne":[7727,2381],"tierTwo":[54050,14562],"tierThree":[63872,9826]}]]]}</script>
<div id='has-finished-comet-page' hidden style='display: none;'></div></body></html>
+73 -1
View File
@@ -12,13 +12,14 @@ import {
} from '@waha/core/exceptions';
import { QR } from '@waha/core/QR';
import { parseBool } from '@waha/helpers';
import { CallData } from '@waha/structures/calls.dto';
import {
Channel,
ChannelRole,
CreateChannelRequest,
ListChannelsQuery,
} from '@waha/structures/channels.dto';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { ChatArchiveEvent, GetChatsQuery } from '@waha/structures/chats.dto';
import {
ChatRequest,
CheckNumberStatusQuery,
@@ -50,16 +51,19 @@ import {
ParticipantsRequest,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
import { Label, LabelID } from '@waha/structures/labels.dto';
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
import { MeInfo } from '@waha/structures/sessions.dto';
import { WAMessageRevokedBody } from '@waha/structures/webhooks.dto';
import {
Call,
Channel as WEBJSChannel,
Chat,
ClientOptions,
Contact,
Events,
GroupChat,
Label as WEBJSLabel,
Location,
Message,
Reaction,
@@ -468,6 +472,52 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return chat.clearMessages();
}
public chatsArchiveChat(chatId: string): Promise<any> {
const id = this.ensureSuffix(chatId);
return this.whatsapp.archiveChat(id);
}
public chatsUnarchiveChat(chatId: string): Promise<any> {
const id = this.ensureSuffix(chatId);
return this.whatsapp.unarchiveChat(id);
}
/**
*
* Label methods
*/
public async getLabels(): Promise<Label[]> {
const labels = await this.whatsapp.getLabels();
return labels.map(this.toLabel);
}
public getChatsByLabelId(labelId: string) {
return this.whatsapp.getChatsByLabelId(labelId);
}
public async getChatLabels(chatId: string): Promise<Label[]> {
const id = this.ensureSuffix(chatId);
const labels = await this.whatsapp.getChatLabels(id);
return labels.map(this.toLabel);
}
public async putLabelsToChat(chatId: string, labels: LabelID[]) {
const labelIds = labels.map((label) => label.id);
const chatIds = [this.ensureSuffix(chatId)];
await this.whatsapp.addOrRemoveLabels(labelIds, chatIds);
}
protected toLabel(label: WEBJSLabel): Label {
const color = label.colorIndex;
return {
id: label.id,
name: label.name,
color: color,
colorHex: Label.toHex(color),
};
}
/**
* Contacts methods
*/
@@ -811,6 +861,28 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
case WAHAEvents.GROUP_LEAVE:
this.whatsapp.on(Events.GROUP_LEAVE, handler);
return true;
case WAHAEvents.CHAT_ARCHIVE:
this.whatsapp.on('chat_archived', (chat, archived, _) => {
const body: ChatArchiveEvent = {
id: chat.id._serialized,
archived: archived,
timestamp: chat.timestamp,
};
handler(body);
});
return true;
case WAHAEvents.CALL_RECEIVED:
this.whatsapp.on('call', (call: Call) => {
const body: CallData = {
id: call.id,
from: call.from,
timestamp: call.timestamp,
isVideo: call.isVideo,
isGroup: call.isGroup,
};
handler(body);
});
return true;
default:
return false;
}
+6
View File
@@ -7,6 +7,7 @@ import {
} from '@waha/utils/logging';
import { json, urlencoded } from 'express';
import { Logger as NestJSPinoLogger } from 'nestjs-pino';
import { LoggerErrorInterceptor } from 'nestjs-pino';
import { Logger } from 'pino';
import pino from 'pino';
@@ -60,6 +61,11 @@ async function bootstrap() {
bufferLogs: true,
});
app.useLogger(app.get(NestJSPinoLogger));
// Print original stack, not pino one
// https://github.com/iamolegga/nestjs-pino?tab=readme-ov-file#expose-stack-trace-and-error-class-in-err-property
app.useGlobalInterceptors(new LoggerErrorInterceptor());
app.enableShutdownHooks();
app.useGlobalFilters(new AllExceptionsFilter());
app.enableCors();
+26
View File
@@ -0,0 +1,26 @@
/**
* Events
*/
import { ApiProperty } from '@nestjs/swagger';
import { ChatIdProperty } from '@waha/structures/properties.dto';
function CallIdProperty() {
return ApiProperty({
description: 'Call ID',
example: 'ABCDEFGABCDEFGABCDEFGABCDEFG',
});
}
export class CallData {
@CallIdProperty()
id: string;
@ChatIdProperty()
from?: string;
timestamp: number;
isVideo: boolean;
isGroup: boolean;
}
+11 -1
View File
@@ -1,4 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { ChatIdProperty } from '@waha/structures/properties.dto';
import { Type } from 'class-transformer';
import { IsNumber, IsOptional } from 'class-validator';
@@ -32,5 +33,14 @@ export class GetChatsQuery {
}
/**
* Requests
* Events
*/
export class ChatArchiveEvent {
@ChatIdProperty()
id: string;
archived: boolean;
timestamp: number;
}
+8
View File
@@ -13,6 +13,14 @@ export enum WAHAEvents {
PRESENCE_UPDATE = 'presence.update',
POLL_VOTE = 'poll.vote',
POLL_VOTE_FAILED = 'poll.vote.failed',
CHAT_ARCHIVE = 'chat.archive',
CALL_RECEIVED = 'call.received',
CALL_ACCEPTED = 'call.accepted',
CALL_REJECTED = 'call.rejected',
LABEL_UPSERT = 'label.upsert',
LABEL_DELETED = 'label.deleted',
LABEL_CHAT_ADDED = 'label.chat.added',
LABEL_CHAT_DELETED = 'label.chat.deleted',
}
export enum WAHASessionStatus {
+1 -1
View File
@@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger';
export class WAHAEnvironment {
@ApiProperty({
example: '2029.10.29',
example: 'YYYY.MM.BUILD',
})
version: string;
+85
View File
@@ -0,0 +1,85 @@
import { ApiProperty } from '@nestjs/swagger';
import { ChatIdProperty } from '@waha/structures/properties.dto';
const Colors = [
'#ff9485',
'#64c4ff',
'#ffd429',
'#dfaef0',
'#99b6c1',
'#55ccb3',
'#ff9dff',
'#d3a91d',
'#6d7cce',
'#d7e752',
'#00d0e2',
'#ffc5c7',
'#93ceac',
'#f74848',
'#00a0f2',
'#83e422',
'#ffaf04',
'#b5ebff',
'#9ba6ff',
'#9368cf',
];
export class Label {
@ApiProperty({
example: '1',
description: 'Label ID',
})
id: string;
@ApiProperty({
example: 'Lead',
description: 'Label name',
})
name: string;
@ApiProperty({
example: 0,
description: 'Internal color number, not hex',
})
color: number;
@ApiProperty({
example: '#ff9485',
description: 'Color in hex',
})
colorHex: string;
static toHex(color: number) {
if (color >= Colors.length) {
return '#000000';
}
return Colors[color];
}
}
export class LabelID {
@ApiProperty({
example: '1',
description: 'Label ID',
})
id: string;
}
export class SetLabelsRequest {
labels: LabelID[];
}
export class LabelChatAssociation {
@ApiProperty({
example: '1',
description: 'Label ID',
})
labelId: string;
label: Label | null;
@ChatIdProperty({
description: 'Chat ID',
})
chatId: string;
}
+3
View File
@@ -0,0 +1,3 @@
export class PingResponse {
message: string = 'pong';
}
+89
View File
@@ -1,5 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { CallData } from '@waha/structures/calls.dto';
import { Label, LabelChatAssociation } from '@waha/structures/labels.dto';
import { ChatArchiveEvent } from './chats.dto';
import { MessageDestination } from './chatting.dto';
import {
WAHAEngine,
@@ -87,6 +90,7 @@ export class WAMessageRevokedBody {
after?: WAMessage;
before?: WAMessage;
}
export class WASessionStatusBody {
@ApiProperty({
example: 'default',
@@ -118,6 +122,7 @@ export class WAHAWebhook {
// eslint-disable-next-line @typescript-eslint/ban-types
| object;
}
class WAHAWebhookSessionStatus extends WAHAWebhook {
@ApiProperty({
description: 'The event is triggered when the session status changes.',
@@ -230,6 +235,82 @@ class WAHAWebhookPollVoteFailed extends WAHAWebhook {
payload: PollVotePayload;
}
class WAHAWebhookChatArchive extends WAHAWebhook {
@ApiProperty({
description:
'The event is triggered when the chat is archived or unarchived',
})
event = WAHAEvents.CHAT_ARCHIVE;
payload: ChatArchiveEvent;
}
class WAHAWebhookCallReceived extends WAHAWebhook {
@ApiProperty({
description:
'The event is triggered when the call is received by the user.',
})
event = WAHAEvents.CALL_RECEIVED;
payload: CallData;
}
class WAHAWebhookCallAccepted extends WAHAWebhook {
@ApiProperty({
description:
'The event is triggered when the call is accepted by the user.',
})
event = WAHAEvents.CALL_ACCEPTED;
payload: CallData;
}
class WAHAWebhookCallRejected extends WAHAWebhook {
@ApiProperty({
description:
'The event is triggered when the call is rejected by the user.',
})
event = WAHAEvents.CALL_REJECTED;
payload: CallData;
}
class WAHAWebhookLabelUpsert extends WAHAWebhook {
@ApiProperty({
description: 'The event is triggered when a label is created or updated',
})
event = WAHAEvents.LABEL_UPSERT;
payload: Label;
}
class WAHAWebhookLabelDeleted extends WAHAWebhook {
@ApiProperty({
description: 'The event is triggered when a label is deleted',
})
event = WAHAEvents.LABEL_DELETED;
payload: Label;
}
class WAHAWebhookLabelChatAdded extends WAHAWebhook {
@ApiProperty({
description: 'The event is triggered when a label is added to a chat',
})
event = WAHAEvents.LABEL_CHAT_ADDED;
payload: LabelChatAssociation;
}
class WAHAWebhookLabelChatDeleted extends WAHAWebhook {
@ApiProperty({
description: 'The event is triggered when a label is deleted from a chat',
})
event = WAHAEvents.LABEL_CHAT_DELETED;
payload: LabelChatAssociation;
}
const WAHA_WEBHOOKS = [
WAHAWebhookSessionStatus,
WAHAWebhookMessage,
@@ -243,5 +324,13 @@ const WAHA_WEBHOOKS = [
WAHAWebhookPresenceUpdate,
WAHAWebhookPollVote,
WAHAWebhookPollVoteFailed,
WAHAWebhookChatArchive,
WAHAWebhookCallReceived,
WAHAWebhookCallAccepted,
WAHAWebhookCallRejected,
WAHAWebhookLabelUpsert,
WAHAWebhookLabelDeleted,
WAHAWebhookLabelChatAdded,
WAHAWebhookLabelChatDeleted,
];
export { WAHA_WEBHOOKS };
+1 -1
View File
@@ -33,7 +33,7 @@ export function getEngineName(): string {
}
export const VERSION: WAHAEnvironment = {
version: '2024.7.6',
version: '2024.8.1',
engine: getEngineName(),
tier: getWAHAVersion(),
browser: getBrowserExecutablePath(),
+10 -2
View File
@@ -2732,6 +2732,13 @@ __metadata:
languageName: node
linkType: hard
"adm-zip@npm:0.5.10":
version: 0.5.10
resolution: "adm-zip@npm:0.5.10"
checksum: 07ed91cf6423bf5dca4ee63977bc7635e91b8d21829c00829d48dce4c6932e1b19e6cfcbe44f1931c956e68795ae97183fc775913883fa48ce88a1ac11fb2034
languageName: node
linkType: hard
"adm-zip@npm:^0.5.10":
version: 0.5.14
resolution: "adm-zip@npm:0.5.14"
@@ -12886,6 +12893,7 @@ __metadata:
"@types/ws": ^8.5.4
"@typescript-eslint/eslint-plugin": 3.9.1
"@typescript-eslint/parser": 3.9.1
adm-zip: 0.5.10
async-lock: ^1.4.1
better-sqlite3: 9.6.0
check-disk-space: ^3.4.0
@@ -13029,7 +13037,7 @@ __metadata:
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-webpack-exodus-channels":
version: 1.24.0
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=ed4e24ce1af3bd8196fc64b1c192e9350a4de863"
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=ec31dbb7207599b602169c70923f114dbc7c526e"
dependencies:
"@pedroslopez/moduleraid": ^5.0.2
adm-zip: ^0.5.10
@@ -13048,7 +13056,7 @@ __metadata:
optional: true
unzipper:
optional: true
checksum: 79e215af485616ed254c9da263532bb95ad1af25e5f2147424267758e7946c5c2d2c1b49459ee6ef65957cdec4da472917e5334c6d4120a2881c3177fcd5be5f
checksum: 65dc78c2e057ef5c366f7e4d2d9940017e5a37eb740c70aaabb1bcf2fc54b8886d41a925cfad87757922c7966bcca328c483438934725958a92e4519e11b6197
languageName: node
linkType: hard