Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9030f7c4ce | ||
|
|
bde6c38bd4 | ||
|
|
0aefb6c6ec | ||
|
|
da650ccdef | ||
|
|
92d3e70c1f | ||
|
|
cb5dfaf066 | ||
|
|
cd75e5e4cc | ||
|
|
7bd6ab5ec0 | ||
|
|
92f9c89cf1 | ||
|
|
eb2632b23a | ||
|
|
8c90bc6808 | ||
|
|
66146532e1 | ||
|
|
dbf3a41c1d | ||
|
|
942bbf9c6c | ||
|
|
a9d7cc527c | ||
|
|
2d362722ed | ||
|
|
f81638e625 | ||
|
|
8ae77df0ff | ||
|
|
110bd0e5f7 | ||
|
|
1b3a366cb7 | ||
|
|
3b5d9a145f | ||
|
|
fc37fc067a | ||
|
|
bb18a28484 | ||
|
|
86ca08b9aa | ||
|
|
9522df7835 | ||
|
|
55e0fd0226 | ||
|
|
ff9a986a2e | ||
|
|
df31fe2a8b | ||
|
|
1aeaf996bc | ||
|
|
cb0e59e91a | ||
|
|
5f02f49e9d | ||
|
|
ce9f91fe2c | ||
|
|
ac37745721 | ||
|
|
e44aeefda8 | ||
|
|
dbff2b659a | ||
|
|
52ef8e8b76 | ||
|
|
b71567c754 | ||
|
|
d1670c743f | ||
|
|
009b38f471 | ||
|
|
0cf5f30c0d | ||
|
|
cd4e1f179d | ||
|
|
b89f9d6b35 | ||
|
|
c3ece96390 | ||
|
|
770739b44e | ||
|
|
84984c2cde | ||
|
|
86393c8674 | ||
|
|
d4aed3bc45 | ||
|
|
818cd77450 | ||
|
|
dc26c70400 | ||
|
|
6547d713ea | ||
|
|
e8dcb0c242 |
No files matched your search
@@ -6,6 +6,8 @@ tokens
|
||||
files
|
||||
venv
|
||||
.wwebjs_auth
|
||||
src/test.ts
|
||||
src/test.js
|
||||
test.js
|
||||
.wwebjs_cache
|
||||
src/dashboard
|
||||
|
||||
+8
-2
@@ -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 \
|
||||
@@ -48,6 +48,9 @@ RUN echo "USE_BROWSER=$USE_BROWSER"
|
||||
# Install ffmpeg to generate previews for videos
|
||||
RUN apt-get update && apt-get install -y ffmpeg --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install zip and unzip
|
||||
RUN apt-get update && apt-get install -y zip unzip --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install fonts if using either chromium or chrome
|
||||
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
|
||||
apt-get update \
|
||||
@@ -68,7 +71,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 \
|
||||
@@ -88,6 +91,9 @@ COPY --from=dashboard /dashboard ./dist/dashboard
|
||||
ENV CHOKIDAR_USEPOLLING=1
|
||||
ENV CHOKIDAR_INTERVAL=5000
|
||||
|
||||
# WAHA variables
|
||||
ENV WAHA_ZIPPER=ZIPUNZIP
|
||||
|
||||
# Run command, etc
|
||||
EXPOSE 3000
|
||||
CMD yarn start:prod
|
||||
@@ -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
|
||||
@@ -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
@@ -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.
@@ -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",
|
||||
@@ -59,6 +60,7 @@
|
||||
"passport-headerapikey": "^1.2.2",
|
||||
"pino-http": "^10.2.0",
|
||||
"pino-pretty": "^11.2.1",
|
||||
"pretty-bytes": "5.6.0",
|
||||
"puppeteer": "^21.0.0",
|
||||
"qrcode": "^1.5.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
|
||||
Executable
+23
@@ -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."
|
||||
Executable
+21
@@ -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
|
||||
@@ -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 };
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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' };
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -29,8 +29,8 @@ export class SwaggerConfiguratorCore {
|
||||
'<li><a href="https://github.com/devlikeapro/waha" target="_blank">GitHub - WAHA Core</a></li>' +
|
||||
'<li><a href="https://github.com/devlikeapro/waha-plu' + // Separate line to pass pre-commit check
|
||||
's" target="_blank">GitHub - WAHA Plus</a></li>' +
|
||||
'<li><b>NEW!</b> - <a href="/dashboard">WAHA Dashboard</a></li>' +
|
||||
'<li><b>NEW!</b> - <a href="https://waha.devlike.pro/docs/how-to/waha-dashboard">WAHA Dashboard Documentation</a></li>' +
|
||||
'<li><a href="/dashboard">WAHA Dashboard</a></li>' +
|
||||
'<li><a href="https://waha.devlike.pro/docs/how-to/waha-dashboard">WAHA Dashboard Documentation</a></li>' +
|
||||
'</ul>' +
|
||||
'<p>Support the project and get WAHA Plus version!</p>' +
|
||||
'<ul>' +
|
||||
@@ -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',
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export abstract class DataStore {}
|
||||
export abstract class DataStore {
|
||||
abstract init(sessionName?: string): Promise<void>;
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '@nestjs/websockets';
|
||||
import { SessionManager } from '@waha/core/abc/manager.abc';
|
||||
import { WAHAEvents } from '@waha/structures/enums.dto';
|
||||
import { HeartbeatJob } from '@waha/utils/HeartbeatJob';
|
||||
import { WebsocketHeartbeatJob } from '@waha/utils/WebsocketHeartbeatJob';
|
||||
import { WebSocket } from '@waha/utils/ws';
|
||||
import { IncomingMessage } from 'http';
|
||||
import * as lodash from 'lodash';
|
||||
@@ -41,11 +41,14 @@ export class WebsocketGatewayCore
|
||||
new Map();
|
||||
|
||||
private readonly logger: LoggerService;
|
||||
private heartbeat: HeartbeatJob;
|
||||
private heartbeat: WebsocketHeartbeatJob;
|
||||
|
||||
constructor(private manager: SessionManager) {
|
||||
this.logger = new Logger('WebsocketGateway');
|
||||
this.heartbeat = new HeartbeatJob(this.logger, this.HEARTBEAT_INTERVAL);
|
||||
this.heartbeat = new WebsocketHeartbeatJob(
|
||||
this.logger,
|
||||
this.HEARTBEAT_INTERVAL,
|
||||
);
|
||||
}
|
||||
|
||||
handleConnection(socket: WebSocket, request: IncomingMessage, ...args): any {
|
||||
|
||||
@@ -7,7 +7,11 @@ import { TerminusModule } from '@nestjs/terminus';
|
||||
import { BufferJsonReplacerInterceptor } from '@waha/api/BufferJsonReplacerInterceptor';
|
||||
import { ChannelsController } from '@waha/api/channels.controller';
|
||||
import { WebsocketGatewayCore } from '@waha/core/api/websocket.gateway.core';
|
||||
import { getPinoLogLevel, getPinoTransport } from '@waha/utils/logging';
|
||||
import {
|
||||
getPinoHttpUseLevel,
|
||||
getPinoLogLevel,
|
||||
getPinoTransport,
|
||||
} from '@waha/utils/logging';
|
||||
import { LoggerModule } from 'nestjs-pino';
|
||||
import { join } from 'path';
|
||||
import { Logger } from 'pino';
|
||||
@@ -18,6 +22,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 {
|
||||
@@ -41,6 +47,7 @@ export const IMPORTS = [
|
||||
pinoHttp: {
|
||||
quietReqLogger: true,
|
||||
level: getPinoLogLevel(),
|
||||
useLevel: getPinoHttpUseLevel(),
|
||||
transport: getPinoTransport(),
|
||||
autoLogging: {
|
||||
ignore: (req) => {
|
||||
@@ -99,12 +106,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,11 +36,18 @@ 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,
|
||||
WAMessageAckBody,
|
||||
} from '@waha/structures/webhooks.dto';
|
||||
import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
|
||||
import { SinglePeriodicJobRunner } from '@waha/utils/SinglePeriodicJobRunner';
|
||||
import * as Buffer from 'buffer';
|
||||
import { Agent } from 'https';
|
||||
import * as lodash from 'lodash';
|
||||
@@ -135,13 +146,13 @@ const ToEnginePresenceStatus = flipObject(PresenceStatuses);
|
||||
|
||||
export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
private START_ATTEMPT_DELAY_SECONDS = 2;
|
||||
private AUTO_RESTART_AFTER_SECONDS = 30 * 60;
|
||||
private AUTO_RESTART_AFTER_SECONDS = 28 * 60;
|
||||
|
||||
engine = WAHAEngine.NOWEB;
|
||||
authFactory = new NowebAuthFactoryCore();
|
||||
storageFactory = new NowebStorageFactoryCore();
|
||||
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private autoRestartTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private startDelayedJob: SingleDelayedJobRunner;
|
||||
private autoRestartJob: SinglePeriodicJobRunner;
|
||||
private msgRetryCounterCache: NodeCache;
|
||||
protected engineLogger: BaileysLogger;
|
||||
|
||||
@@ -166,6 +177,22 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.engineLogger = this.loggerBuilder.child({
|
||||
name: 'NOWEBEngine',
|
||||
}) as unknown as BaileysLogger;
|
||||
|
||||
// Restart job if session failed
|
||||
this.startDelayedJob = new SingleDelayedJobRunner(
|
||||
'start-engine',
|
||||
this.START_ATTEMPT_DELAY_SECONDS * SECOND,
|
||||
this.logger,
|
||||
);
|
||||
|
||||
// Enable auto-restart
|
||||
const shiftSeconds = Math.floor(Math.random() * 30);
|
||||
const delay = this.AUTO_RESTART_AFTER_SECONDS + shiftSeconds;
|
||||
this.autoRestartJob = new SinglePeriodicJobRunner(
|
||||
'auto-restart',
|
||||
delay * SECOND,
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -268,20 +295,15 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.enableAutoRestart();
|
||||
}
|
||||
|
||||
protected enableAutoRestart() {
|
||||
if (this.autoRestartTimeoutId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add random delay to avoid multiple restarts at the same time
|
||||
const shiftSeconds = Math.floor(Math.random() * 30);
|
||||
const delay = this.AUTO_RESTART_AFTER_SECONDS + shiftSeconds;
|
||||
this.logger.debug(`Auto-restart is enabled, after ${delay} seconds`);
|
||||
this.autoRestartTimeoutId = setTimeout(() => {
|
||||
this.autoRestartTimeoutId = null;
|
||||
private enableAutoRestart() {
|
||||
this.autoRestartJob.start(async () => {
|
||||
this.logger.info('Auto-restarting the client connection...');
|
||||
this.sock?.end(new Error('auto-restart'));
|
||||
}, delay * SECOND);
|
||||
if (this.sock?.ws?.isConnecting) {
|
||||
this.logger.warn('Auto-restart skipped, the client is connecting...');
|
||||
return;
|
||||
}
|
||||
this.sock?.end(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
protected async getMessage(
|
||||
@@ -301,19 +323,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
private restartClient() {
|
||||
if (this.startTimeoutId) {
|
||||
this.logger.info(
|
||||
'Request to restart is already in progress, ignoring this request',
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.logger.info(
|
||||
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
|
||||
);
|
||||
this.startTimeoutId = setTimeout(() => {
|
||||
this.startTimeoutId = undefined;
|
||||
this.buildClient();
|
||||
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
|
||||
this.startDelayedJob.schedule(async () => {
|
||||
await this.buildClient();
|
||||
});
|
||||
}
|
||||
|
||||
protected listenConnectionEvents() {
|
||||
@@ -335,9 +347,11 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.qr.save('');
|
||||
// reconnect if not logged out
|
||||
if (shouldReconnect) {
|
||||
this.logger.info(
|
||||
`Connection closed due to '${lastDisconnect.error}', reconnecting...`,
|
||||
);
|
||||
if (lastDisconnect.error) {
|
||||
this.logger.info(
|
||||
`Connection closed due to '${lastDisconnect.error}', reconnecting...`,
|
||||
);
|
||||
}
|
||||
this.restartClient();
|
||||
} else {
|
||||
this.logger.error(
|
||||
@@ -424,8 +438,8 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
private async end() {
|
||||
clearTimeout(this.autoRestartTimeoutId);
|
||||
clearTimeout(this.startTimeoutId);
|
||||
this.autoRestartJob.stop();
|
||||
this.startDelayedJob.cancel();
|
||||
// @ts-ignore
|
||||
this.sock?.ev?.removeAllListeners();
|
||||
this.sock?.ws?.removeAllListeners();
|
||||
@@ -700,6 +714,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 +1094,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 +1424,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>;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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'),
|
||||
|
||||
@@ -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
|
||||
> 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{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%}._apdl ._apdm{margin-top:-40px;color:var(--splashscreen-startup-icon)}._apdl ._apdm::after{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:'';position:relative;top:-100%;display:block;height:100%;left:calc(50% - 72px);opacity:1;width:calc(72px * 3)}@keyframes shimmer{from{left:calc(50% - 72px)}to{left:calc(50% + 72px)}}._apdl ._apdq{height:3px;margin-top:40px;position:relative;width:320px}._apdl ._apdq progress{vertical-align:top}._apdl ._apdr{margin-top:40px;font-size:17px;color:var(--splashscreen-primary-title)}._apdl ._apds{margin-top:12px;font-size:14px;color:var(--splashscreen-secondary-lighter)}._apdl ._apds span{display:inline-block;margin-bottom:2px;vertical-align:middle}._apdl ._apdq progress{-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%}._apdl ._apdq progress[value]::-webkit-progress-bar{background-color:var(--splashscreen-progress-background)}._apdl ._apdq progress[value]::-webkit-progress-value{background-color:var(--splashscreen-progress-primary);transition:width .45s ease}%23bootloader_z3kVBe5{height:42px;}.bootloader_z3kVBe5{display:block!important;}" 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>
|
||||
|
||||
@@ -7,8 +7,11 @@ const { LoadUtils } = require('./WahaInjected');
|
||||
const ChatFactory = require('whatsapp-web.js/src/factories/ChatFactory');
|
||||
|
||||
export class WebjsClient extends Client {
|
||||
async initialize() {
|
||||
await super.initialize();
|
||||
async inject() {
|
||||
// Even tho this.inject is not defined as interface in Client.ts
|
||||
// We can still call and override it
|
||||
// @ts-ignore
|
||||
await super.inject();
|
||||
//Load util functions (serializers, helper functions)
|
||||
await this.pupPage.evaluate(LoadUtils);
|
||||
}
|
||||
|
||||
@@ -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,20 @@ 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 { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
|
||||
import {
|
||||
Call,
|
||||
Channel as WEBJSChannel,
|
||||
Chat,
|
||||
ClientOptions,
|
||||
Contact,
|
||||
Events,
|
||||
GroupChat,
|
||||
Label as WEBJSLabel,
|
||||
Location,
|
||||
Message,
|
||||
Reaction,
|
||||
@@ -79,7 +84,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
engine = WAHAEngine.WEBJS;
|
||||
protected engineConfig?: WebJSConfig;
|
||||
|
||||
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
private startDelayedJob: SingleDelayedJobRunner;
|
||||
private shouldRestart: boolean;
|
||||
|
||||
whatsapp: WebjsClient;
|
||||
@@ -89,6 +94,13 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
super(config);
|
||||
this.qr = new QR();
|
||||
this.shouldRestart = true;
|
||||
|
||||
// Restart job if session failed
|
||||
this.startDelayedJob = new SingleDelayedJobRunner(
|
||||
'start-engine',
|
||||
this.START_ATTEMPT_DELAY_SECONDS * SECOND,
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,24 +140,20 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
private restartClient() {
|
||||
if (!this.shouldRestart) {
|
||||
this.logger.debug(
|
||||
"Shouldn't restart the client, ignoring restart request",
|
||||
'Should not restart the client, ignoring restart request',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.startTimeoutId) {
|
||||
const msg =
|
||||
'Request to restart is already in progress, ignoring restart request';
|
||||
this.logger.warn(msg);
|
||||
return;
|
||||
}
|
||||
this.logger.info(
|
||||
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
|
||||
);
|
||||
this.startTimeoutId = setTimeout(() => {
|
||||
this.startTimeoutId = undefined;
|
||||
this.start();
|
||||
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
|
||||
this.startDelayedJob.schedule(async () => {
|
||||
if (!this.shouldRestart) {
|
||||
this.logger.warn(
|
||||
'Should not restart the client, ignoring restart request',
|
||||
);
|
||||
return;
|
||||
}
|
||||
await this.start();
|
||||
});
|
||||
}
|
||||
|
||||
protected addProxyConfig(clientOptions: ClientOptions) {
|
||||
@@ -225,7 +233,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
private async end() {
|
||||
try {
|
||||
this.whatsapp?.removeAllListeners();
|
||||
clearInterval(this.startTimeoutId);
|
||||
this.startDelayedJob.cancel();
|
||||
this.whatsapp?.destroy().catch((error) => {
|
||||
this.logger.debug('Failed to destroy the client', error);
|
||||
});
|
||||
@@ -468,6 +476,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 +865,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;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,10 @@ export class SessionManagerCore extends SessionManager {
|
||||
try {
|
||||
engineInfo = await promiseTimeout(10, this.session.getEngineInfo());
|
||||
} catch (e) {
|
||||
this.log.warn('Error while getting engine info', e);
|
||||
this.log.warn(
|
||||
{ session: this.session },
|
||||
'Error while getting engine info',
|
||||
);
|
||||
}
|
||||
}
|
||||
const engine = {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class WAHAEnvironment {
|
||||
@ApiProperty({
|
||||
example: '2029.10.29',
|
||||
example: 'YYYY.MM.BUILD',
|
||||
})
|
||||
version: string;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export class PingResponse {
|
||||
message: string = 'pong';
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Logger } from 'pino';
|
||||
|
||||
type FunctionNoArgs = () => Promise<any>;
|
||||
|
||||
/**
|
||||
* Run a job (function) after a delay,
|
||||
* but make sure we run exactly ONE job at the same time
|
||||
*/
|
||||
export class SingleDelayedJobRunner {
|
||||
private timeout: NodeJS.Timeout;
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
private name: string,
|
||||
private timeoutMs: number,
|
||||
logger: Logger,
|
||||
private warningOverride: boolean = false,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
job: name,
|
||||
class: SingleDelayedJobRunner.name,
|
||||
});
|
||||
}
|
||||
|
||||
schedule(fn: FunctionNoArgs): boolean {
|
||||
if (this.timeout) {
|
||||
const msg = `Job has been started before, do not schedule it again`;
|
||||
this.log(this.warningOverride, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.timeout = setTimeout(() => {
|
||||
this.logger.debug(`Running job...`);
|
||||
fn().finally(() => {
|
||||
this.logger.debug(`Job finished`);
|
||||
this.timeout = null;
|
||||
});
|
||||
}, this.timeoutMs);
|
||||
this.logger.info(`Job scheduled with timeout ${this.timeoutMs} ms`);
|
||||
return true;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
clearTimeout(this.timeout);
|
||||
this.logger.info(`Job cancelled`);
|
||||
}
|
||||
|
||||
private log(warning: boolean, msg: string) {
|
||||
if (warning) {
|
||||
this.logger.warn(msg);
|
||||
} else {
|
||||
this.logger.info(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Logger } from 'pino';
|
||||
|
||||
type FunctionNoArgs = () => Promise<any>;
|
||||
|
||||
/**
|
||||
* Run a job (function) in some interval,
|
||||
* but make sure we run exactly ONE job at the same time
|
||||
*/
|
||||
export class SinglePeriodicJobRunner {
|
||||
private interval: NodeJS.Timeout;
|
||||
private isWorking: boolean = false;
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
private name: string,
|
||||
private intervalMs: number,
|
||||
logger: Logger,
|
||||
private warningOverlap: boolean = true,
|
||||
private warningOverride: boolean = false,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
job: name,
|
||||
class: SinglePeriodicJobRunner.name,
|
||||
});
|
||||
}
|
||||
|
||||
start(fn: FunctionNoArgs): boolean {
|
||||
if (this.interval) {
|
||||
const msg = `Job has been started before, do not schedule it again`;
|
||||
this.log(this.warningOverride, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.interval = setInterval(() => {
|
||||
if (this.isWorking) {
|
||||
const msg = `Job is already running, skipping this run`;
|
||||
this.log(this.warningOverlap, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isWorking = true;
|
||||
this.logger.debug('Running job...');
|
||||
fn().finally(() => {
|
||||
this.isWorking = false;
|
||||
this.logger.debug(`Job finished`);
|
||||
});
|
||||
}, this.intervalMs);
|
||||
this.logger.info(`Job started with interval ${this.intervalMs} ms`);
|
||||
return true;
|
||||
}
|
||||
|
||||
stop() {
|
||||
clearInterval(this.interval);
|
||||
this.logger.info(`Job stopped`);
|
||||
}
|
||||
|
||||
private log(warning: boolean, msg) {
|
||||
if (warning) {
|
||||
this.logger.warn(msg);
|
||||
} else {
|
||||
this.logger.info(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { LoggerService } from '@nestjs/common';
|
||||
import { WebSocket } from '@waha/utils/ws';
|
||||
import { WebSocketServer } from 'ws';
|
||||
|
||||
export class HeartbeatJob {
|
||||
export class WebsocketHeartbeatJob {
|
||||
private interval: ReturnType<typeof setInterval>;
|
||||
|
||||
constructor(
|
||||
+13
-1
@@ -1,5 +1,5 @@
|
||||
import { LogLevel } from '@nestjs/common';
|
||||
import { ChildLoggerOptions, Level, Logger } from 'pino';
|
||||
import { ChildLoggerOptions, Level, LevelWithSilent, Logger } from 'pino';
|
||||
|
||||
export interface LoggerBuilder {
|
||||
child(bindings: Record<string, any>, options?: ChildLoggerOptions): Logger;
|
||||
@@ -31,6 +31,18 @@ export function getPinoLogLevel(debug: boolean = false): Level {
|
||||
return getDefaultPinoLogLevel();
|
||||
}
|
||||
|
||||
export function getPinoHttpUseLevel(): LevelWithSilent {
|
||||
const levels = ['fatal', 'error', 'warn', 'info', 'debug', 'trace'];
|
||||
const level = (process.env.WAHA_HTTP_LOG_LEVEL || 'info').toLowerCase();
|
||||
if (!levels.includes(level)) {
|
||||
console.error(
|
||||
`Unknown ${process.env.WAHA_HTTP_LOG_LEVEL}' value for WAHA_HTTP_LOG_LEVEL`,
|
||||
);
|
||||
return 'info';
|
||||
}
|
||||
return level as LevelWithSilent;
|
||||
}
|
||||
|
||||
export function getDefaultPinoLogLevel(): Level {
|
||||
const logLevel = (process.env.WAHA_LOG_LEVEL || 'info').toLowerCase();
|
||||
const levels = ['fatal', 'error', 'warn', 'info', 'debug', 'trace'];
|
||||
|
||||
@@ -32,3 +32,7 @@ export const promiseTimeout = function (
|
||||
),
|
||||
]).finally(() => clearTimeout(timer));
|
||||
};
|
||||
|
||||
export async function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
+1
-1
@@ -33,7 +33,7 @@ export function getEngineName(): string {
|
||||
}
|
||||
|
||||
export const VERSION: WAHAEnvironment = {
|
||||
version: '2024.7.6',
|
||||
version: '2024.8.5',
|
||||
engine: getEngineName(),
|
||||
tier: getWAHAVersion(),
|
||||
browser: getBrowserExecutablePath(),
|
||||
|
||||
@@ -7,7 +7,7 @@ __metadata:
|
||||
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels":
|
||||
version: 6.7.5
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=66fde3f3e5df76b52c6a01b75c301d63e2b6a75f"
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=5a051ac5894dd8aa3b1ecf86e3db9843045f5dfc"
|
||||
dependencies:
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@hapi/boom": ^9.1.3
|
||||
@@ -39,7 +39,7 @@ __metadata:
|
||||
optional: true
|
||||
sharp:
|
||||
optional: true
|
||||
checksum: b4f3bc47c559641800e220bddfd06f86848c74dd0c5ea85aba4d1033606a3f90a2d2e488df33da191de75be7357b10df041b2b6d76ee5b7bda1bd37d2586b45c
|
||||
checksum: 0f4c218435b1e43b300e0b96cc48981bb79884a63e0c050847db5700e2864cd2a718847bc3cbb9afa91bdda9c2514e65d071b6cd78dab750bd123d55107aad86
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -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"
|
||||
@@ -10067,6 +10074,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pretty-bytes@npm:5.6.0":
|
||||
version: 5.6.0
|
||||
resolution: "pretty-bytes@npm:5.6.0"
|
||||
checksum: 9c082500d1e93434b5b291bd651662936b8bd6204ec9fa17d563116a192d6d86b98f6d328526b4e8d783c07d5499e2614a807520249692da9ec81564b2f439cd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pretty-format@npm:^25.2.1, pretty-format@npm:^25.5.0":
|
||||
version: 25.5.0
|
||||
resolution: "pretty-format@npm:25.5.0"
|
||||
@@ -12886,6 +12900,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
|
||||
@@ -12913,6 +12928,7 @@ __metadata:
|
||||
pino-http: ^10.2.0
|
||||
pino-pretty: ^11.2.1
|
||||
prettier: ^1.19.1
|
||||
pretty-bytes: 5.6.0
|
||||
puppeteer: ^21.0.0
|
||||
qrcode: ^1.5.1
|
||||
qrcode-terminal: ^0.12.0
|
||||
@@ -13029,7 +13045,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=f28dad2d12136192e9ee45370d768323196c10c0"
|
||||
dependencies:
|
||||
"@pedroslopez/moduleraid": ^5.0.2
|
||||
adm-zip: ^0.5.10
|
||||
@@ -13048,7 +13064,7 @@ __metadata:
|
||||
optional: true
|
||||
unzipper:
|
||||
optional: true
|
||||
checksum: 79e215af485616ed254c9da263532bb95ad1af25e5f2147424267758e7946c5c2d2c1b49459ee6ef65957cdec4da472917e5334c6d4120a2881c3177fcd5be5f
|
||||
checksum: 0bd28b1f332aafaa6f9d467de04c33da99c139208d03bef78c5323c0e3ada6762f31e156d63cc2f6a46bb90e298ad08ddd2db25e13fb045fc2d1a2e69595758b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in new issue
Block a user