Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d85e2498fd | ||
|
|
507382b6d2 | ||
|
|
f343cf8549 | ||
|
|
832d5baf35 | ||
|
|
0253f32574 | ||
|
|
6173180272 | ||
|
|
2d21931fb1 | ||
|
|
bdaa7187fd | ||
|
|
e7ad6e06ec | ||
|
|
7c14483852 | ||
|
|
8b4b1f934e | ||
|
|
713eb3f169 | ||
|
|
48297c80d1 | ||
|
|
315ffdac92 | ||
|
|
7ddc17e6e5 | ||
|
|
e3b8073c82 | ||
|
|
80517e416c | ||
|
|
4b71aade9d | ||
|
|
1b52698c54 | ||
|
|
b8f372d83f | ||
|
|
7bc5f55fb2 | ||
|
|
7eeafd03b3 | ||
|
|
f88480d271 | ||
|
|
9b8cce85bd | ||
|
|
aa364b57e8 | ||
|
|
ea973d0de4 | ||
|
|
1a1b64cbb2 | ||
|
|
09c7e11dbc | ||
|
|
3450a56756 | ||
|
|
f37f4466ae | ||
|
|
451834b219 | ||
|
|
91924353e2 | ||
|
|
67cf94fc95 | ||
|
|
36a343c09f | ||
|
|
4a37aebbf1 | ||
|
|
d5fa9f8d72 | ||
|
|
08c244334b | ||
|
|
23dd1c2726 | ||
|
|
23a309d394 | ||
|
|
3c1bb4e145 | ||
|
|
87b320a3e3 | ||
|
|
e4fb9615c7 | ||
|
|
efad4de0af | ||
|
|
04f62700a2 | ||
|
|
08415f7931 | ||
|
|
8bc86af3c8 | ||
|
|
fa2c5e42dc | ||
|
|
e3d3952b81 | ||
|
|
a9171addde | ||
|
|
440ac087ad | ||
|
|
9dd5eb4eeb | ||
|
|
26c2c9abc9 | ||
|
|
663b07c07e | ||
|
|
5add6a0e73 | ||
|
|
5c4912feb4 | ||
|
|
75e115f390 | ||
|
|
8e443d23f4 | ||
|
|
c43c9c319b | ||
|
|
e32b128b0f | ||
|
|
5287421cea | ||
|
|
9bc95ef350 | ||
|
|
028de6addb | ||
|
|
a107605937 | ||
|
|
cec5d0147b | ||
|
|
e46b879fc4 | ||
|
|
b6764fbb29 | ||
|
|
e8899cc314 | ||
|
|
2b2054dd6b | ||
|
|
92705b0ae2 | ||
|
|
2ae8a36b7f | ||
|
|
899139dda1 | ||
|
|
b6b571e84b | ||
|
|
9e098fa997 | ||
|
|
13d00f954f | ||
|
|
fee75d0c8a | ||
|
|
abae3f14cd | ||
|
|
b8a98e2c6e | ||
|
|
d990572b5b | ||
|
|
2d37d392bc | ||
|
|
59015fc3bb | ||
|
|
c3be68f988 | ||
|
|
8610784958 | ||
|
|
f01d71c34a | ||
|
|
a06501e4b1 | ||
|
|
7c2c30fa1b | ||
|
|
903dc714f2 | ||
|
|
b1bd2c8805 | ||
|
|
0e4b4f6d8c | ||
|
|
d8d0eaf247 | ||
|
|
90096faef3 | ||
|
|
f794f75394 | ||
|
|
8de63e486c | ||
|
|
4308efca47 | ||
|
|
877fa292d6 | ||
|
|
df6ea6f497 | ||
|
|
5e9be391e1 | ||
|
|
49960b8234 | ||
|
|
d669dbe54b | ||
|
|
2d1859ac0c | ||
|
|
dc864055a3 | ||
|
|
bad9537aba | ||
|
|
303b1adc0a | ||
|
|
c582904d41 | ||
|
|
65eabf6153 | ||
|
|
cc9c9e2253 | ||
|
|
8747ae9564 | ||
|
|
9253e54958 | ||
|
|
fb774f2caa | ||
|
|
ba120024a6 | ||
|
|
1fe0e69914 | ||
|
|
0fe04e411c | ||
|
|
35074f959f | ||
|
|
0d698fbaf1 | ||
|
|
c9e2a52327 | ||
|
|
a58e06109b | ||
|
|
65375e4836 | ||
|
|
edc517d33f | ||
|
|
354c82dc34 | ||
|
|
fe2acd0665 | ||
|
|
19b5b1a90c | ||
|
|
e7281e2118 | ||
|
|
10f334cf15 | ||
|
|
a057fd6458 | ||
|
|
3bafabeb0a | ||
|
|
edefbe17da | ||
|
|
a65041ffcd | ||
|
|
0962c60844 | ||
|
|
3d72eceac0 | ||
|
|
57b5deff5b | ||
|
|
1163dee352 | ||
|
|
f7fe562bba | ||
|
|
3394f98a8a | ||
|
|
a575b35286 | ||
|
|
0f41e79e98 | ||
|
|
24bf22a31f | ||
|
|
05a1b8802e | ||
|
|
9c409d9507 | ||
|
|
4ee7161c36 | ||
|
|
4cd9ce0ff7 | ||
|
|
a2d0dfd8b2 | ||
|
|
d4164fe0ba | ||
|
|
6bbecdd7c0 | ||
|
|
0784c3ae05 | ||
|
|
679757ccfa | ||
|
|
63a4e693e3 | ||
|
|
b21041d9e0 | ||
|
|
f014bb4587 | ||
|
|
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 | ||
|
|
100d0be513 | ||
|
|
fc8db2d977 | ||
|
|
e5d98d7889 | ||
|
|
c7b1a05ed3 | ||
|
|
649a90bd5e | ||
|
|
0fc880cf21 | ||
|
|
0d82a4c2c6 | ||
|
|
fb3aa59683 | ||
|
|
b938792ca8 | ||
|
|
bb74946d54 | ||
|
|
3e78105509 | ||
|
|
c6adf0ac89 | ||
|
|
219b4dca94 | ||
|
|
acec292b0f | ||
|
|
7ba86cbd23 | ||
|
|
3002eaf479 | ||
|
|
15422ca504 | ||
|
|
7067f00bee | ||
|
|
a0616eb251 | ||
|
|
5d4da0e4c7 | ||
|
|
546e3475fb | ||
|
|
56c44ebb58 | ||
|
|
bd03bc730c | ||
|
|
e0e1e58104 | ||
|
|
940de662b6 | ||
|
|
d151c1192b | ||
|
|
15ae10579c | ||
|
|
359696408d | ||
|
|
d3766368f8 | ||
|
|
73af7451fc | ||
|
|
e27fcefe45 | ||
|
|
aa5ade5517 | ||
|
|
94b6a66ce4 | ||
|
|
a51e486fa6 | ||
|
|
2b608daea4 | ||
|
|
aa60c2afd1 | ||
|
|
cff22c74a9 | ||
|
|
b77b8ee0da | ||
|
|
610aef2f14 | ||
|
|
e15ca41d6e | ||
|
|
60e9e53af4 | ||
|
|
9812000724 | ||
|
|
d72401fc39 | ||
|
|
822eba7982 | ||
|
|
9327564e6e | ||
|
|
6e9fe42a83 | ||
|
|
a32cf28ccb | ||
|
|
55b101802a | ||
|
|
ecda8b4394 | ||
|
|
6d4f8d4c26 | ||
|
|
26aa53f3fa | ||
|
|
2f7a94ea3f | ||
|
|
2b622b4ee9 | ||
|
|
3e280f1e08 | ||
|
|
c54d52ad45 | ||
|
|
e54d3ea96b | ||
|
|
e07cb8257d | ||
|
|
74b6a8fdba |
No files matched your search
@@ -1,12 +1,20 @@
|
||||
*.heapsnapshot
|
||||
.yarn
|
||||
example.ts
|
||||
.*sessions
|
||||
.secrets
|
||||
.minio
|
||||
.media
|
||||
tokens
|
||||
files
|
||||
venv
|
||||
.wwebjs_auth
|
||||
src/test.ts
|
||||
src/test.js
|
||||
test.js
|
||||
.wwebjs_cache
|
||||
src/dashboard
|
||||
.eslintcache
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
|
||||
+27
-1
@@ -6,12 +6,21 @@ exclude: |
|
||||
)$
|
||||
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: commit-message-prefix
|
||||
name: Validate Commit Message for src/plus Changes
|
||||
entry: python ./.precommit/validate_commit_message.py
|
||||
language: python
|
||||
stages: [commit-msg]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: lint
|
||||
stages: [pre-commit]
|
||||
name: lint
|
||||
language: system
|
||||
entry: bash -c '$HOME/.nvm/nvm-exec npm run lint'
|
||||
entry: bash -c '$HOME/.nvm/nvm-exec npm run lint-cache'
|
||||
pass_filenames: false
|
||||
files: |
|
||||
(?x)^(
|
||||
@@ -22,6 +31,7 @@ repos:
|
||||
rev: 'v3.1.0'
|
||||
hooks:
|
||||
- id: prettier
|
||||
stages: [pre-commit]
|
||||
exclude: |
|
||||
(?x)^(
|
||||
docs/.*|
|
||||
@@ -31,11 +41,13 @@ repos:
|
||||
rev: v1.1.2
|
||||
hooks:
|
||||
- id: markdown-toc
|
||||
stages: [pre-commit]
|
||||
name: README.md
|
||||
files: ^README.md$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: no-plus-in-core
|
||||
stages: [pre-commit]
|
||||
name: No "plus" in core
|
||||
language: pygrep
|
||||
entry: 'plus'
|
||||
@@ -46,3 +58,17 @@ repos:
|
||||
src/structures/.*|
|
||||
src/config.service.ts|
|
||||
)$
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: no-console-log
|
||||
stages: [pre-commit]
|
||||
name: No console.log() calls
|
||||
language: pygrep
|
||||
entry: 'console\.log'
|
||||
exclude: |
|
||||
(?x)^(
|
||||
entrypoint.sh|
|
||||
.pre-commit-config.yaml|
|
||||
^src/core/engines/webjs/session.webjs.core.ts|
|
||||
)$
|
||||
@@ -0,0 +1,38 @@
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def get_staged_files():
|
||||
result = subprocess.run(["git", "diff", "--cached", "--name-only"], stdout=subprocess.PIPE, text=True)
|
||||
files = result.stdout.splitlines()
|
||||
return files
|
||||
|
||||
|
||||
def get_commit_message(commit_msg_filepath):
|
||||
with open(commit_msg_filepath, 'r') as f:
|
||||
return f.readline().strip()
|
||||
|
||||
|
||||
def main():
|
||||
commit_msg_filepath = sys.argv[1]
|
||||
commit_message = get_commit_message(commit_msg_filepath)
|
||||
staged_files = get_staged_files()
|
||||
|
||||
has_plus_changes = any(f.startswith('src/plus') for f in staged_files)
|
||||
print(commit_message)
|
||||
starts_with_plus = commit_message.startswith('[PLUS]')
|
||||
|
||||
if has_plus_changes and not starts_with_plus:
|
||||
print("'[PLUS]' not found in commit message, but there's changes are from 'src/plus'.")
|
||||
return 1
|
||||
|
||||
if starts_with_plus and not all(f.startswith('src/plus') for f in staged_files):
|
||||
print("'[PLUS]' found in commit message, but there's changes from other directories. \n"
|
||||
"Changes MUST be only from 'src/plus'.")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+34
-10
@@ -1,28 +1,40 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
ARG NODE_VERSION=20.12.2-bullseye
|
||||
ARG NODE_VERSION=22.8-bullseye
|
||||
FROM node:${NODE_VERSION} as build
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=True
|
||||
|
||||
# npm packages
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y openssh-client
|
||||
RUN apt install openssh-client
|
||||
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
|
||||
WORKDIR /src
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
ENV YARN_CHECKSUM_BEHAVIOR=update
|
||||
RUN npm install -g corepack && corepack enable
|
||||
RUN yarn set version 3.6.3
|
||||
RUN --mount=type=ssh yarn install
|
||||
RUN yarn install
|
||||
|
||||
# App
|
||||
WORKDIR /src
|
||||
ADD . /src
|
||||
RUN --mount=type=ssh yarn install
|
||||
RUN yarn install
|
||||
RUN yarn build && find ./dist -name "*.d.ts" -delete
|
||||
|
||||
#
|
||||
# Dashboard
|
||||
#
|
||||
FROM node:${NODE_VERSION} as dashboard
|
||||
|
||||
# Download WAHA Dashboard
|
||||
ENV WAHA_DASHBOARD_SHA 9afbd7b68618ea67be01bdefa978cf98a6336611
|
||||
RUN \
|
||||
wget https://github.com/devlikeapro/dashboard/archive/${WAHA_DASHBOARD_SHA}.zip \
|
||||
&& unzip ${WAHA_DASHBOARD_SHA}.zip -d /tmp/dashboard \
|
||||
&& mkdir -p /dashboard \
|
||||
&& mv /tmp/dashboard/dashboard-${WAHA_DASHBOARD_SHA}/* /dashboard/ \
|
||||
&& rm -rf ${WAHA_DASHBOARD_SHA}.zip \
|
||||
&& rm -rf /tmp/dashboard/dashboard-${WAHA_DASHBOARD_SHA}
|
||||
|
||||
#
|
||||
# Final
|
||||
#
|
||||
@@ -38,6 +50,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 \
|
||||
@@ -58,7 +73,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 \
|
||||
@@ -72,7 +87,16 @@ WORKDIR /app
|
||||
COPY package.json ./
|
||||
COPY --from=build /src/node_modules ./node_modules
|
||||
COPY --from=build /src/dist ./dist
|
||||
COPY --from=dashboard /dashboard ./dist/dashboard
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Chokidar options to monitor file changes
|
||||
ENV CHOKIDAR_USEPOLLING=1
|
||||
ENV CHOKIDAR_INTERVAL=5000
|
||||
|
||||
# WAHA variables
|
||||
ENV WAHA_ZIPPER=ZIPUNZIP
|
||||
|
||||
# Run command, etc
|
||||
EXPOSE 3000
|
||||
CMD yarn start:prod
|
||||
CMD ["/entrypoint.sh"]
|
||||
@@ -29,12 +29,13 @@ push:
|
||||
docker push devlikeapro/waha
|
||||
|
||||
for-swagger:
|
||||
WHATSAPP_SWAGGER_CONFIG_ADVANCED=true npm run start
|
||||
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@https://github.com/devlikeapro/whatsapp-web.js#main-fork
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:WhiskeySockets/Baileys
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up venom-bot
|
||||
up-noweb:
|
||||
. ${NVM_DIR}/nvm.sh && nvm exec yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-channels-2
|
||||
|
||||
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
|
||||
@@ -141,7 +141,7 @@ later:
|
||||
How to log in - the instruction on WhatsApp site
|
||||
</a>
|
||||
|
||||
When your ready - find `POST /api/session/start`, click on **Try it out**, then **Execute** a bit below.
|
||||
When your ready - find `POST /api/sessions`, click on **Try it out**, then **Execute** a bit below.
|
||||
|
||||
|
||||
The example payload:
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
services:
|
||||
waha:
|
||||
restart: always
|
||||
container_name: waha
|
||||
# image: devlikeapro/waha:latest
|
||||
image: devlikeapro/waha-plus:latest
|
||||
ports:
|
||||
- '3000:3000/tcp'
|
||||
volumes:
|
||||
- './.sessions:/app/.sessions'
|
||||
- './.media:/app/.media'
|
||||
environment:
|
||||
- WHATSAPP_API_KEY=321
|
||||
- WAHA_DASHBOARD_USERNAME=waha
|
||||
- WAHA_DASHBOARD_PASSWORD=waha
|
||||
- WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
- WHATSAPP_RESTART_ALL_SESSIONS=True
|
||||
- WAHA_PRINT_QR=False
|
||||
- WAHA_MEDIA_STORAGE=LOCAL
|
||||
- WHATSAPP_FILES_LIFETIME=0
|
||||
- WHATSAPP_FILES_FOLDER=/app/.media
|
||||
|
||||
n8n:
|
||||
image: docker.n8n.io/n8nio/n8n
|
||||
container_name: n8n
|
||||
restart: always
|
||||
environment:
|
||||
- WEBHOOK_URL=http://n8n:5678
|
||||
ports:
|
||||
- '5678:5678'
|
||||
volumes:
|
||||
- n8n_data:/home/node/.n8n
|
||||
|
||||
volumes:
|
||||
n8n_data: {}
|
||||
@@ -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: {}
|
||||
+216
-53
@@ -1,72 +1,215 @@
|
||||
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/
|
||||
- WHATSAPP_HOOK_URL=https://httpbin.org/post
|
||||
- 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://httpbin.org/post
|
||||
# - 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_SCHEMA=http
|
||||
#- 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://httpbin.org/post
|
||||
# - 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
|
||||
#
|
||||
# Set log format to JSON if you consume logs with log management systems
|
||||
- WAHA_LOG_FORMAT=JSON
|
||||
- WAHA_LOG_LEVEL=info
|
||||
# - WAHA_LOG_FORMAT=PRETTY
|
||||
# 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
|
||||
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
#- 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
|
||||
#- WHATSAPP_API_SCHEMA=https
|
||||
#- WHATSAPP_API_PORT=3000
|
||||
#- WHATSAPP_API_HOSTNAME=waha.example.pro
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# Media - Local Storage
|
||||
# https://waha.devlike.pro/docs/how-to/storages/#media---local
|
||||
#
|
||||
# Set to 0 to keep media files forever
|
||||
# https://waha.devlike.pro/docs/how-to/storages/#save-media-files-between-the-container-restarts
|
||||
- WAHA_MEDIA_STORAGE=LOCAL
|
||||
- WHATSAPP_FILES_LIFETIME=0
|
||||
- WHATSAPP_FILES_FOLDER=/app/.media
|
||||
# Keep media files for 180 seconds (3 minutes)
|
||||
#- WHATSAPP_FILES_LIFETIME=180
|
||||
#
|
||||
|
||||
# Media - S3 Storage
|
||||
# https://waha.devlike.pro/docs/how-to/storages/#media---s3
|
||||
#- WAHA_MEDIA_STORAGE=S3
|
||||
#- WAHA_S3_REGION=eu-west-2
|
||||
#- WAHA_S3_BUCKET=waha
|
||||
#- WAHA_S3_ACCESS_KEY_ID=minioadmin
|
||||
#- WAHA_S3_SECRET_ACCESS_KEY=minioadmin
|
||||
#- WAHA_S3_ENDPOINT=http://minio:9000 # Not required if you're using AWS S3
|
||||
#- WAHA_S3_FORCE_PATH_STYLE=True # Required for Minio
|
||||
#- WAHA_S3_PROXY_FILES=True # Required for docker-compose setup
|
||||
|
||||
#
|
||||
# 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: Only if you're using MongoDB
|
||||
# https://waha.devlike.pro/docs/how-to/storages/#sessions---mongodb
|
||||
# Comment this block if you're using MongoDB
|
||||
mongodb:
|
||||
image: mongo
|
||||
container_name: mongodb
|
||||
@@ -76,5 +219,25 @@ services:
|
||||
- mongodb_data:/data/db
|
||||
restart: always
|
||||
|
||||
# NOTE: Only if you're using S3 to save media files
|
||||
# https://waha.devlike.pro/docs/how-to/storages/#media---s3
|
||||
# Comment this block if you're using AWS S3
|
||||
minio:
|
||||
image: quay.io/minio/minio
|
||||
container_name: minio
|
||||
restart: always
|
||||
ports:
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
MINIO_REGION: 'eu-west-2'
|
||||
MINIO_ROOT_USER: 'minioadmin'
|
||||
MINIO_ROOT_PASSWORD: 'minioadmin'
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
|
||||
volumes:
|
||||
# NOTE: Only if you're using MongoDB
|
||||
mongodb_data: {}
|
||||
minio_data: {}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Calculate UV_THREADPOOL_SIZE based on number of CPUs
|
||||
cpus=$(node -e "const os = require('os'); console.log(os.cpus().length);")
|
||||
uv_threadpool_size=$(($cpus * 2))
|
||||
|
||||
# Set UV_THREADPOOL_SIZE as an environment variable
|
||||
export UV_THREADPOOL_SIZE="${UV_THREADPOOL_SIZE:-$uv_threadpool_size}"
|
||||
|
||||
# Start your application using yarn
|
||||
node dist/main
|
||||
Binary file not shown.
@@ -50,8 +50,8 @@ docker run -it --rm --network=host -e WHATSAPP_HOOK_URL=http://localhost:5000/bo
|
||||
|
||||
2. Open Swagger API in the browser http://localhost:3000/
|
||||
3. Start session and scan QR code in swagger
|
||||
1. Find `POST /api/session/start` request press **Try it out** and
|
||||
**Execute** it with `default` session name
|
||||
1. Find `POST /api/sessions/` request press **Try it out** and **Execute** it
|
||||
with `default` session name
|
||||
2. Find `GET /api/screenshot` and execute it - it must show QR code
|
||||
3. Scan QR code on your mobile WhatsApp application (that installed on your
|
||||
phone)
|
||||
|
||||
+20
-6
@@ -15,6 +15,7 @@
|
||||
"start:prod": "node dist/main",
|
||||
"start:prod-exit": "node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --max-warnings=0",
|
||||
"lint-cache": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --cache --max-warnings=0",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
@@ -22,36 +23,50 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@adiwajshing/baileys": "github:WhiskeySockets/Baileys",
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-channels-2",
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@aws-sdk/client-s3": "^3.633.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.633.0",
|
||||
"@nestjs/axios": "^3.0.2",
|
||||
"@nestjs/common": "^9.0.9",
|
||||
"@nestjs/config": "^0.5.0",
|
||||
"@nestjs/config": "^3.2.3",
|
||||
"@nestjs/core": "^9.0.9",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.9",
|
||||
"@nestjs/platform-ws": "^9.0.9",
|
||||
"@nestjs/serve-static": "^2.1.3",
|
||||
"@nestjs/swagger": "^7.1.11",
|
||||
"@nestjs/terminus": "^10.2.3",
|
||||
"@nestjs/websockets": "^9.0.9",
|
||||
"@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",
|
||||
"better-sqlite3": "11.3.0",
|
||||
"check-disk-space": "^3.4.0",
|
||||
"class-validator": "^0.12.2",
|
||||
"chokidar": "^3.6.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "0.14.0",
|
||||
"del": "^6.0.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"file-type": "16.5.4",
|
||||
"fs-extra": "^11.2.0",
|
||||
"https-proxy-agent": "^7.0.0",
|
||||
"joi": "^17.13.3",
|
||||
"knex": "^3.1.0",
|
||||
"libphonenumber-js": "^1.10.36",
|
||||
"link-preview-js": "^3.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.27",
|
||||
"mongodb": "^6.3.0",
|
||||
"nestjs-pino": "^4.1.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-headerapikey": "^1.2.2",
|
||||
"pino-http": "^10.2.0",
|
||||
"pino-pretty": "^11.2.1",
|
||||
"pretty-bytes": "5.6.0",
|
||||
"promise-retry": "^2.0.1",
|
||||
"puppeteer": "^21.0.0",
|
||||
"qrcode": "^1.5.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
@@ -62,8 +77,7 @@
|
||||
"rxjs": "^7.1.0",
|
||||
"sharp": "^0.33.4",
|
||||
"swagger-ui-express": "^4.1.4",
|
||||
"venom-bot": "5.0.1",
|
||||
"whatsapp-web.js": "https://github.com/devlikeapro/whatsapp-web.js#main-fork-update"
|
||||
"whatsapp-web.js": "github:devlikeapro/whatsapp-web.js#fork-webpack-exodus-channels"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.0.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=JSON \
|
||||
--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
|
||||
@@ -8,9 +8,15 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { ApiFileAcceptHeader } from '@waha/nestjs/ApiFileAcceptHeader';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { BufferResponseInterceptor } from '../nestjs/BufferResponseInterceptor';
|
||||
import {
|
||||
CaptchaBody,
|
||||
OTPRequest,
|
||||
@@ -21,18 +27,16 @@ import {
|
||||
} from '../structures/auth.dto';
|
||||
import { WAHASessionStatus } from '../structures/enums.dto';
|
||||
import { Base64File } from '../structures/files.dto';
|
||||
import { BufferResponseInterceptor } from './BufferResponseInterceptor';
|
||||
import { ApiFileAcceptHeader, SessionApiParam, SessionParam } from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/auth')
|
||||
@ApiTags('auth')
|
||||
@ApiTags('🔑 Auth')
|
||||
class AuthController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('qr')
|
||||
@ApiOperation({
|
||||
summary: 'Get QR code for pairing WhatsApp Web.',
|
||||
summary: 'Get QR code for pairing WhatsApp API.',
|
||||
})
|
||||
@SessionApiParam
|
||||
@ApiFileAcceptHeader(Base64File, QRCodeValue)
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
import {
|
||||
Channel,
|
||||
CreateChannelRequest,
|
||||
ListChannelsQuery,
|
||||
NewsletterIdApiParam,
|
||||
NewsletterIdOrInviteCodeApiParam,
|
||||
} from '@waha/structures/channels.dto';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { isNewsletter, WhatsappSession } from '../core/abc/session.abc';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/channels')
|
||||
@ApiTags('📢 Channels')
|
||||
export class ChannelsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get list of know channels' })
|
||||
async list(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Query() query: ListChannelsQuery,
|
||||
): Promise<Channel[]> {
|
||||
return session.channelsList(query);
|
||||
}
|
||||
|
||||
@Post('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Create a new channel.' })
|
||||
create(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() request: CreateChannelRequest,
|
||||
): Promise<Channel> {
|
||||
return session.channelsCreateChannel(request);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@SessionApiParam
|
||||
@NewsletterIdApiParam
|
||||
@ApiOperation({ summary: 'Delete the channel.' })
|
||||
delete(@SessionParam session: WhatsappSession, @Param('id') id: string) {
|
||||
return session.channelsDeleteChannel(id);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@SessionApiParam
|
||||
@NewsletterIdOrInviteCodeApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Get the channel info',
|
||||
description:
|
||||
'You can use either id (123@newsletter) ' +
|
||||
'OR invite code (https://www.whatsapp.com/channel/123)',
|
||||
})
|
||||
get(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<Channel> {
|
||||
if (isNewsletter(id)) {
|
||||
return session.channelsGetChannel(id);
|
||||
} else {
|
||||
// https://www.whatsapp.com/channel/123 => 123
|
||||
const inviteCode = id.split('/').pop();
|
||||
return session.channelsGetChannelByInviteCode(inviteCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('follow')
|
||||
@SessionApiParam
|
||||
@NewsletterIdApiParam
|
||||
@ApiOperation({ summary: 'Follow the channel.' })
|
||||
follow(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<void> {
|
||||
return session.channelsFollowChannel(id);
|
||||
}
|
||||
|
||||
@Post('unfollow')
|
||||
@SessionApiParam
|
||||
@NewsletterIdApiParam
|
||||
@ApiOperation({ summary: 'Unfollow the channel.' })
|
||||
unfollow(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<void> {
|
||||
return session.channelsUnfollowChannel(id);
|
||||
}
|
||||
|
||||
@Post('mute')
|
||||
@SessionApiParam
|
||||
@NewsletterIdApiParam
|
||||
@ApiOperation({ summary: 'Mute the channel.' })
|
||||
mute(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<void> {
|
||||
return session.channelsMuteChannel(id);
|
||||
}
|
||||
|
||||
@Post('unmute')
|
||||
@SessionApiParam
|
||||
@NewsletterIdApiParam
|
||||
@ApiOperation({ summary: 'Unmute the channel.' })
|
||||
unmute(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<void> {
|
||||
return session.channelsUnmuteChannel(id);
|
||||
}
|
||||
}
|
||||
+42
-11
@@ -7,37 +7,44 @@ import {
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
UsePipes,
|
||||
ValidationPipe,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { ChatIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
|
||||
import { MessageIdApiParam } from '@waha/nestjs/params/MessageIdApiParam';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { parseBool } from '../helpers';
|
||||
import { GetChatMessagesQuery } from '../structures/chats.dto';
|
||||
import { GetChatMessagesQuery, GetChatsQuery } from '../structures/chats.dto';
|
||||
import { EditMessageRequest } from '../structures/chatting.dto';
|
||||
import {
|
||||
ChatIdApiParam,
|
||||
MessageIdApiParam,
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/chats')
|
||||
@ApiTags('chats')
|
||||
@ApiTags('💬 Chats')
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
class ChatsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get all chats' })
|
||||
getAllChats(@SessionParam session: WhatsappSession) {
|
||||
return session.getChats();
|
||||
@ApiOperation({ summary: 'Get chats' })
|
||||
getChats(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Query() query: GetChatsQuery,
|
||||
) {
|
||||
return session.getChats(query);
|
||||
}
|
||||
|
||||
@Delete(':chatId')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Deletes the chat' })
|
||||
@ChatIdApiParam
|
||||
deleteChat(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
@@ -48,6 +55,7 @@ class ChatsController {
|
||||
@Get(':chatId/messages')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Gets messages in the chat' })
|
||||
@ChatIdApiParam
|
||||
getChatMessages(
|
||||
@Query() query: GetChatMessagesQuery,
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -60,6 +68,7 @@ class ChatsController {
|
||||
@Delete(':chatId/messages')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Clears all messages from the chat' })
|
||||
@ChatIdApiParam
|
||||
clearMessages(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('chatId') chatId: string,
|
||||
@@ -93,6 +102,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 };
|
||||
@@ -26,35 +26,10 @@ import { WAMessage } from '../structures/responses.dto';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api')
|
||||
@ApiTags('chatting')
|
||||
@ApiTags('📤 Chatting')
|
||||
export class ChattingController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('/checkNumberStatus')
|
||||
@ApiOperation({ summary: 'Check number status' })
|
||||
async checkNumberStatus(
|
||||
@Query() request: CheckNumberStatusQuery,
|
||||
): Promise<WANumberExistResult> {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.checkNumberStatus(request);
|
||||
}
|
||||
|
||||
@Post('/sendContactVcard')
|
||||
sendContactVcard(@Body() request: MessageContactVcardRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendContactVCard(request);
|
||||
}
|
||||
|
||||
@Get('/sendText')
|
||||
@ApiOperation({ summary: 'Send a text message' })
|
||||
sendTextGet(@Query() query: MessageTextQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
const msg = new MessageTextRequest();
|
||||
msg.chatId = query.phone;
|
||||
msg.text = query.text;
|
||||
return whatsapp.sendText(msg);
|
||||
}
|
||||
|
||||
@Post('/sendText')
|
||||
@ApiOperation({ summary: 'Send a text message' })
|
||||
sendText(@Body() request: MessageTextRequest): Promise<WAMessage> {
|
||||
@@ -62,31 +37,11 @@ export class ChattingController {
|
||||
return whatsapp.sendText(request);
|
||||
}
|
||||
|
||||
@Post('/sendPoll')
|
||||
@ApiOperation({
|
||||
summary: 'Send a poll with options. You can use it as buttons replace',
|
||||
})
|
||||
sendPoll(@Body() request: MessagePollRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendPoll(request);
|
||||
}
|
||||
|
||||
@Post('/sendLocation')
|
||||
sendLocation(@Body() request: MessageLocationRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendLocation(request);
|
||||
}
|
||||
|
||||
@Post('/sendLinkPreview')
|
||||
sendLinkPreview(@Body() request: MessageLinkPreviewRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendLinkPreview(request);
|
||||
}
|
||||
|
||||
@Post('/sendImage')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Send an image. Either from an URL or base64 data - look at the request schemas for details.',
|
||||
summary: 'Send an image',
|
||||
description:
|
||||
'Either from an URL or base64 data - look at the request schemas for details.',
|
||||
})
|
||||
sendImage(@Body() request: MessageImageRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
@@ -95,8 +50,9 @@ export class ChattingController {
|
||||
|
||||
@Post('/sendFile')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Send a file. Either from an URL or base64 data - look at the request schemas for details.',
|
||||
summary: 'Send a file',
|
||||
description:
|
||||
'Either from an URL or base64 data - look at the request schemas for details.',
|
||||
})
|
||||
sendFile(@Body() request: MessageFileRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
@@ -105,8 +61,9 @@ export class ChattingController {
|
||||
|
||||
@Post('/sendVoice')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Send an voice message. Either from an URL or base64 data - look at the request schemas for details.',
|
||||
summary: 'Send an voice message',
|
||||
description:
|
||||
'Either from an URL or base64 data - look at the request schemas for details.',
|
||||
})
|
||||
sendVoice(@Body() request: MessageVoiceRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
@@ -115,21 +72,15 @@ export class ChattingController {
|
||||
|
||||
@Post('/sendVideo')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Send a video. Either from an URL or base64 data - look at the request schemas for details.',
|
||||
summary: 'Send a video',
|
||||
description:
|
||||
'Either from an URL or base64 data - look at the request schemas for details.',
|
||||
})
|
||||
sendVideo(@Body() request: MessageVideoRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendVideo(request);
|
||||
}
|
||||
|
||||
@Post('/reply')
|
||||
@ApiOperation({ summary: 'Reply to a text message' })
|
||||
reply(@Body() request: MessageReplyRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.reply(request);
|
||||
}
|
||||
|
||||
@Post('/sendSeen')
|
||||
sendSeen(@Body() chat: SendSeenRequest) {
|
||||
const whatsapp = this.manager.getSession(chat.session);
|
||||
@@ -166,10 +117,72 @@ export class ChattingController {
|
||||
return;
|
||||
}
|
||||
|
||||
@Post('/sendPoll')
|
||||
@ApiOperation({
|
||||
summary: 'Send a poll with options',
|
||||
description: 'You can use it as buttons or list replacement',
|
||||
})
|
||||
sendPoll(@Body() request: MessagePollRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendPoll(request);
|
||||
}
|
||||
|
||||
@Post('/sendLocation')
|
||||
sendLocation(@Body() request: MessageLocationRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendLocation(request);
|
||||
}
|
||||
|
||||
@Post('/sendLinkPreview')
|
||||
sendLinkPreview(@Body() request: MessageLinkPreviewRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendLinkPreview(request);
|
||||
}
|
||||
|
||||
@Get('/messages')
|
||||
@ApiOperation({ summary: 'Get messages in a chat' })
|
||||
getMessages(@Query() query: GetMessageQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
return whatsapp.getMessages(query);
|
||||
}
|
||||
|
||||
@Get('/sendText')
|
||||
@ApiOperation({ summary: 'Send a text message', deprecated: true })
|
||||
sendTextGet(@Query() query: MessageTextQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
const msg = new MessageTextRequest();
|
||||
msg.chatId = query.phone;
|
||||
msg.text = query.text;
|
||||
return whatsapp.sendText(msg);
|
||||
}
|
||||
|
||||
@Post('/sendContactVcard')
|
||||
sendContactVcard(@Body() request: MessageContactVcardRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.sendContactVCard(request);
|
||||
}
|
||||
|
||||
@Get('/checkNumberStatus')
|
||||
@ApiOperation({
|
||||
summary: 'Check number status',
|
||||
description: 'DEPRECATED. Use "POST /contacts/check-exists" instead',
|
||||
deprecated: true,
|
||||
})
|
||||
async DEPRECATED_checkNumberStatus(
|
||||
@Query() request: CheckNumberStatusQuery,
|
||||
): Promise<WANumberExistResult> {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.checkNumberStatus(request);
|
||||
}
|
||||
|
||||
@Post('/reply')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'DEPRECATED - you can set "reply_to" field when sending text, image, etc',
|
||||
deprecated: true,
|
||||
})
|
||||
reply(@Body() request: MessageReplyRequest) {
|
||||
const whatsapp = this.manager.getSession(request.session);
|
||||
return whatsapp.reply(request);
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,15 @@ import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/contacts')
|
||||
@ApiTags('contacts')
|
||||
@ApiTags('👤 Contacts')
|
||||
export class ContactsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('/')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Get contact basic info. The method always return result, even if the phone number is not registered in WhatsApp. For that - use /check-exists endpoint below.',
|
||||
summary: 'Get contact basic info',
|
||||
description:
|
||||
'The method always return result, even if the phone number is not registered in WhatsApp. For that - use /contacts/check-exists endpoint below.',
|
||||
})
|
||||
get(@Query() query: ContactQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
@@ -43,8 +44,9 @@ export class ContactsController {
|
||||
|
||||
@Get('/about')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Gets the Contact\'s current "about" info. Returns null if you don\'t have permission to read their status.',
|
||||
summary: 'Gets the Contact\'s "about" info',
|
||||
description:
|
||||
'Returns null if you do not have permission to read their status.',
|
||||
})
|
||||
getAbout(@Query() query: ContactQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
@@ -53,8 +55,9 @@ export class ContactsController {
|
||||
|
||||
@Get('/profile-picture')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
"Returns the contact's profile picture URL, if privacy settings allow it.",
|
||||
summary: "Get contact's profile picture URL",
|
||||
description:
|
||||
'If privacy settings do not allow to get the picture, the method will return null.',
|
||||
})
|
||||
getProfilePicture(@Query() query: ContactQuery) {
|
||||
const whatsapp = this.manager.getSession(query.session);
|
||||
|
||||
@@ -8,6 +8,11 @@ import {
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { GroupIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
@@ -18,11 +23,10 @@ import {
|
||||
SettingsSecurityChangeInfo,
|
||||
SubjectRequest,
|
||||
} from '../structures/groups.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/groups')
|
||||
@ApiTags('groups')
|
||||
@ApiTags('👥 Groups')
|
||||
export class GroupsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@@ -44,6 +48,7 @@ export class GroupsController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@GroupIdApiParam
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get the group.' })
|
||||
getGroup(@SessionParam session: WhatsappSession, @Param('id') id: string) {
|
||||
@@ -52,9 +57,11 @@ export class GroupsController {
|
||||
|
||||
@Put(':id/settings/security/info-admin-only')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Updates the group settings to only allow admins to edit group info (title, description, photo).',
|
||||
summary: 'Updates the group "info admin only" settings.',
|
||||
description:
|
||||
'You can allow only admins to edit group info (title, description, photo).',
|
||||
})
|
||||
setInfoAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -66,9 +73,11 @@ export class GroupsController {
|
||||
|
||||
@Get(':id/settings/security/info-admin-only')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Gets the group settings to only allow admins to edit group info (title, description, photo).',
|
||||
summary: "Get the group's 'info admin only' settings.",
|
||||
description:
|
||||
'You can allow only admins to edit group info (title, description, photo).',
|
||||
})
|
||||
getInfoAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -79,8 +88,10 @@ export class GroupsController {
|
||||
|
||||
@Put(':id/settings/security/messages-admin-only')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
summary: 'Update settings - who can send messages',
|
||||
description:
|
||||
'Updates the group settings to only allow admins to send messages.',
|
||||
})
|
||||
setMessagesAdminOnly(
|
||||
@@ -93,8 +104,10 @@ export class GroupsController {
|
||||
|
||||
@Get(':id/settings/security/messages-admin-only')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Gets the group settings to only allow admins to send messages.',
|
||||
summary: 'Get settings - who can send messages',
|
||||
description: 'The group settings to only allow admins to send messages.',
|
||||
})
|
||||
getMessagesAdminOnly(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -105,6 +118,7 @@ export class GroupsController {
|
||||
|
||||
@Delete(':id')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Delete the group.' })
|
||||
deleteGroup(@SessionParam session: WhatsappSession, @Param('id') id: string) {
|
||||
return session.deleteGroup(id);
|
||||
@@ -112,6 +126,7 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/leave')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Leave the group.' })
|
||||
leaveGroup(@SessionParam session: WhatsappSession, @Param('id') id: string) {
|
||||
return session.leaveGroup(id);
|
||||
@@ -119,11 +134,12 @@ export class GroupsController {
|
||||
|
||||
@Put(':id/description')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Updates the group description.\n' +
|
||||
'Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.\n',
|
||||
summary: 'Updates the group description.',
|
||||
description:
|
||||
'Returns "true" if the subject was properly updated. This can return "false" if the user does not have the necessary permissions.',
|
||||
})
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
setDescription(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@@ -134,10 +150,11 @@ export class GroupsController {
|
||||
|
||||
@Put(':id/subject')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Updates the group subject.\n' +
|
||||
'Returns true if the subject was properly updated. This can return false if the user does not have the necessary permissions.\n',
|
||||
summary: 'Updates the group subject',
|
||||
description:
|
||||
'Returns "true" if the subject was properly updated. This can return "false" if the user does not have the necessary permissions.',
|
||||
})
|
||||
setSubject(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -149,7 +166,8 @@ export class GroupsController {
|
||||
|
||||
@Get(':id/invite-code')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Gets the invite code for a specific group.' })
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Gets the invite code for the group.' })
|
||||
getInviteCode(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@@ -159,6 +177,7 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/invite-code/revoke')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Invalidates the current group invite code and generates a new one.',
|
||||
@@ -172,7 +191,8 @@ export class GroupsController {
|
||||
|
||||
@Get(':id/participants/')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get a list of participants by in the group.' })
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Get participants' })
|
||||
getParticipants(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@@ -182,7 +202,8 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/participants/add')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Adds a list of participants by ID to the group.' })
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Add participants' })
|
||||
addParticipants(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@@ -193,8 +214,9 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/participants/remove')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Removes a list of participants by ID to the group.',
|
||||
summary: 'Remove participants',
|
||||
})
|
||||
removeParticipants(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -206,6 +228,7 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/admin/promote')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Promote participants to admin users.' })
|
||||
promoteToAdmin(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@@ -217,7 +240,8 @@ export class GroupsController {
|
||||
|
||||
@Post(':id/admin/demote')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Demotes participants by to regular users.' })
|
||||
@GroupIdApiParam
|
||||
@ApiOperation({ summary: 'Demotes participants to regular users.' })
|
||||
demoteToAdmin(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { HealthCheck } from '@nestjs/terminus';
|
||||
|
||||
import { WAHAHealthCheckService } from '../core/abc/WAHAHealthCheckService';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('health')
|
||||
@ApiTags('other')
|
||||
@ApiTags('🔍 Observability')
|
||||
export class HealthController {
|
||||
constructor(private wahaHealth: WAHAHealthCheckService) {}
|
||||
|
||||
@Get()
|
||||
@HealthCheck()
|
||||
@ApiOperation({
|
||||
summary: 'Check the health of the server',
|
||||
description:
|
||||
"Perform all health checks and return the server's health status.",
|
||||
})
|
||||
async check() {
|
||||
return this.wahaHealth.check();
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import {
|
||||
applyDecorators,
|
||||
Injectable,
|
||||
Param,
|
||||
PipeTransform,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiExtraModels,
|
||||
ApiParam,
|
||||
ApiResponse,
|
||||
getSchemaPath,
|
||||
} from '@nestjs/swagger';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { Base64File } from '../structures/files.dto';
|
||||
|
||||
/**
|
||||
* Get session name and return Whatsapp session back (if exists)
|
||||
* use it as
|
||||
@Param('session', SessionPipe) session: WhatsappSession,
|
||||
*/
|
||||
@Injectable()
|
||||
export class SessionPipe implements PipeTransform<WhatsappSession> {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
async transform(value: any) {
|
||||
return this.manager.getSession(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorator for a method that uses SessionPipe above
|
||||
*/
|
||||
export const SessionApiParam = ApiParam({
|
||||
name: 'session',
|
||||
required: true,
|
||||
type: 'string',
|
||||
schema: {
|
||||
default: 'default',
|
||||
},
|
||||
description: 'WhatsApp session name',
|
||||
});
|
||||
|
||||
/**
|
||||
* Session param
|
||||
@SessionParam session: WhatsappSession,
|
||||
*/
|
||||
export const SessionParam = Param('session', SessionPipe);
|
||||
|
||||
export const ChatIdApiParam = ApiParam({
|
||||
name: 'chatId',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Chat ID',
|
||||
example: '123456789@c.us',
|
||||
});
|
||||
|
||||
export const MessageIdApiParam = ApiParam({
|
||||
name: 'messageId',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Message ID',
|
||||
example: 'true_123456789@c.us_BAE6A33293978B16',
|
||||
});
|
||||
|
||||
function getRefSchemaPaths(models) {
|
||||
return models.map((model) => {
|
||||
return { $ref: getSchemaPath(model) };
|
||||
});
|
||||
}
|
||||
|
||||
export function ApiFileAcceptHeader(...models) {
|
||||
models = models.length ? models : [Base64File];
|
||||
return applyDecorators(
|
||||
// Add extra models, otherwise it'll give a error
|
||||
// $ref not found
|
||||
ApiExtraModels(...models),
|
||||
ApiResponse({
|
||||
status: 200,
|
||||
content: {
|
||||
'image/png': {
|
||||
schema: {
|
||||
type: 'string',
|
||||
format: 'binary',
|
||||
},
|
||||
},
|
||||
'application/json': {
|
||||
schema: {
|
||||
oneOf: getRefSchemaPaths(models),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { WhatsappSession } from '@waha/core/abc/session.abc';
|
||||
import { ChatIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
import { Label, 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
|
||||
@ChatIdApiParam
|
||||
@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
|
||||
@ChatIdApiParam
|
||||
@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,17 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { PingResponse } from '@waha/structures/ping.dto';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('ping')
|
||||
@ApiTags('🔍 Observability')
|
||||
export class PingController {
|
||||
@Get()
|
||||
@ApiOperation({
|
||||
summary: 'Ping the server',
|
||||
description: 'Check if the server is alive and responding to requests.',
|
||||
})
|
||||
ping(): PingResponse {
|
||||
return { message: 'pong' };
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,11 @@ import {
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { ChatIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
@@ -15,11 +20,10 @@ import {
|
||||
WAHAChatPresences,
|
||||
WAHASessionPresence,
|
||||
} from '../structures/presence.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/presence')
|
||||
@ApiTags('presence')
|
||||
@ApiTags('✅ Presence')
|
||||
export class PresenceController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@@ -64,6 +68,7 @@ export class PresenceController {
|
||||
|
||||
@Get(':chatId')
|
||||
@SessionApiParam
|
||||
@ChatIdApiParam
|
||||
@ApiOperation({
|
||||
summary:
|
||||
"Get the presence for the chat id. If it hasn't been subscribed - it also subscribes to it.",
|
||||
@@ -77,6 +82,7 @@ export class PresenceController {
|
||||
|
||||
@Post(':chatId/subscribe')
|
||||
@SessionApiParam
|
||||
@ChatIdApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Subscribe to presence events for the chat.',
|
||||
})
|
||||
|
||||
@@ -7,16 +7,16 @@ import {
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { ApiFileAcceptHeader } from '@waha/nestjs/ApiFileAcceptHeader';
|
||||
import { Response } from 'express';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { BufferResponseInterceptor } from '../nestjs/BufferResponseInterceptor';
|
||||
import { SessionQuery } from '../structures/base.dto';
|
||||
import { BufferResponseInterceptor } from './BufferResponseInterceptor';
|
||||
import { ApiFileAcceptHeader } from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api')
|
||||
@ApiTags('screenshot')
|
||||
@ApiTags('🖼️ Screenshot')
|
||||
export class ScreenshotController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
import * as process from 'node:process';
|
||||
import * as v8 from 'node:v8';
|
||||
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Logger,
|
||||
NotFoundException,
|
||||
Post,
|
||||
Query,
|
||||
Res,
|
||||
StreamableFile,
|
||||
UseInterceptors,
|
||||
UsePipes,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import { WhatsappConfigService } from '@waha/config.service';
|
||||
import { getApp } from '@waha/main';
|
||||
import { WAHAValidationPipe } from '@waha/nestjs/pipes/WAHAValidationPipe';
|
||||
import { WAHAEnvironment } from '@waha/structures/environment.dto';
|
||||
import {
|
||||
EnvironmentQuery,
|
||||
ServerStatusResponse,
|
||||
StopRequest,
|
||||
} from '@waha/structures/server.dto';
|
||||
import { VERSION } from '@waha/version';
|
||||
import * as lodash from 'lodash';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/server')
|
||||
@ApiTags('🔍 Observability')
|
||||
export class ServerController {
|
||||
private logger: Logger;
|
||||
|
||||
constructor() {
|
||||
this.logger = new Logger('ServerController');
|
||||
}
|
||||
|
||||
@Get('version')
|
||||
@ApiOperation({ summary: 'Get the version of the server' })
|
||||
get(): WAHAEnvironment {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@Get('environment')
|
||||
@ApiOperation({ summary: 'Get the server environment' })
|
||||
environment(
|
||||
@Query(new WAHAValidationPipe()) query: EnvironmentQuery,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
): object {
|
||||
let result = process.env;
|
||||
if (!query.all) {
|
||||
result = lodash.pickBy(result, (value, key) => {
|
||||
return (
|
||||
key.startsWith('WAHA_') ||
|
||||
key.startsWith('WHATSAPP_') ||
|
||||
key === 'DEBUG'
|
||||
);
|
||||
});
|
||||
}
|
||||
const map = new Map<string, string>();
|
||||
// sort and set
|
||||
Object.keys(result)
|
||||
.sort()
|
||||
.forEach((key) => {
|
||||
map.set(key, result[key]);
|
||||
});
|
||||
return Object.fromEntries(map);
|
||||
}
|
||||
|
||||
@Get('status')
|
||||
@ApiOperation({ summary: 'Get the server status' })
|
||||
async status(): Promise<ServerStatusResponse> {
|
||||
const now = Date.now();
|
||||
const uptime = Math.floor(process.uptime() * 1000);
|
||||
const startTimestamp = now - uptime;
|
||||
return {
|
||||
startTimestamp: startTimestamp,
|
||||
uptime: uptime,
|
||||
};
|
||||
}
|
||||
|
||||
@Post('stop')
|
||||
@ApiOperation({
|
||||
summary: 'Stop (and restart) the server',
|
||||
description:
|
||||
"If you're using docker, after calling this endpoint Docker will start a new container, " +
|
||||
'so you can use this endpoint to restart the server',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async stop(@Body() request: StopRequest) {
|
||||
const timeout = 1_000;
|
||||
if (request.force) {
|
||||
this.logger.log(`Force stopping the server in ${timeout}ms`);
|
||||
setTimeout(() => {
|
||||
this.logger.log('Force stopping the server');
|
||||
process.kill(process.pid, 'SIGKILL');
|
||||
}, timeout);
|
||||
} else {
|
||||
this.logger.log(`Gracefully stopping the server in ${timeout}ms`);
|
||||
setTimeout(async () => {
|
||||
this.logger.log('Gracefully closing the application...');
|
||||
const app = getApp();
|
||||
if (app) {
|
||||
await app.close();
|
||||
}
|
||||
this.logger.log('Application closed');
|
||||
process.exit(0);
|
||||
}, timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/server/debug')
|
||||
@ApiTags('🔍 Observability')
|
||||
export class ServerDebugController {
|
||||
private logger: Logger;
|
||||
private readonly enabled: boolean;
|
||||
|
||||
constructor(protected config: WhatsappConfigService) {
|
||||
this.logger = new Logger('ServerDebugController');
|
||||
this.enabled = this.config.debugModeEnabled;
|
||||
}
|
||||
|
||||
@Get('heapsnapshot')
|
||||
@ApiOperation({
|
||||
summary: 'Return a heapsnapshot',
|
||||
description: "Return a heapsnapshot of the server's memory",
|
||||
})
|
||||
async heapsnapshot() {
|
||||
if (!this.enabled) {
|
||||
throw new NotFoundException('WAHA_DEBUG_MODE is disabled');
|
||||
}
|
||||
this.logger.log('Creating a heap snapshot...');
|
||||
const heap = v8.getHeapSnapshot();
|
||||
const fileName = `${Date.now()}.heapsnapshot`;
|
||||
return new StreamableFile(heap, {
|
||||
type: 'application/octet-stream',
|
||||
disposition: `attachment; filename=${fileName}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
+254
-48
@@ -6,69 +6,66 @@ import {
|
||||
NotFoundException,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
UsePipes,
|
||||
} from '@nestjs/common';
|
||||
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
ApiExtraModels,
|
||||
ApiOperation,
|
||||
ApiSecurity,
|
||||
ApiTags,
|
||||
} from '@nestjs/swagger';
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
import { WAHAValidationPipe } from '@waha/nestjs/pipes/WAHAValidationPipe';
|
||||
import { WAHASessionStatus } from '@waha/structures/enums.dto';
|
||||
import {
|
||||
SessionLogoutDeprecatedRequest,
|
||||
SessionStartDeprecatedRequest,
|
||||
SessionStopDeprecatedRequest,
|
||||
} from '@waha/structures/sessions.deprecated.dto';
|
||||
import { generatePrefixedId } from '@waha/utils/ids';
|
||||
import { sleep } from '@waha/utils/promiseTimeout';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import { parseBool } from '../helpers';
|
||||
import {
|
||||
ListSessionsQuery,
|
||||
MeInfo,
|
||||
SessionCreateRequest,
|
||||
SessionDTO,
|
||||
SessionInfo,
|
||||
SessionLogoutRequest,
|
||||
SessionStartRequest,
|
||||
SessionStopRequest,
|
||||
SessionUpdateRequest,
|
||||
} from '../structures/sessions.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const AsyncLock = require('async-lock');
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/sessions')
|
||||
@ApiTags('sessions')
|
||||
@ApiTags('🖥️ Sessions')
|
||||
class SessionsController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
private lock: any;
|
||||
|
||||
@Post('/start/')
|
||||
async start(@Body() request: SessionStartRequest): Promise<SessionDTO> {
|
||||
const result = await this.manager.start(request);
|
||||
await this.manager.sessionConfigRepository.save(
|
||||
request.name,
|
||||
request.config || null,
|
||||
);
|
||||
return result;
|
||||
constructor(private manager: SessionManager) {
|
||||
this.lock = new AsyncLock({ maxPending: Infinity });
|
||||
}
|
||||
|
||||
@Post('/stop/')
|
||||
@ApiOperation({ summary: 'Stop session' })
|
||||
async stop(@Body() request: SessionStopRequest): Promise<void> {
|
||||
if (request.logout) {
|
||||
await this.manager.logout(request);
|
||||
} else {
|
||||
await this.manager.stop(request);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@Post('/logout/')
|
||||
@ApiOperation({ summary: 'Logout from session.' })
|
||||
clean(@Body() request: SessionLogoutRequest): Promise<void> {
|
||||
return this.manager.logout(request);
|
||||
private withLock(name: string, fn: () => any) {
|
||||
return this.lock.acquire(name, fn);
|
||||
}
|
||||
|
||||
@Get('/')
|
||||
async list(@Query() query: ListSessionsQuery): Promise<SessionInfo[]> {
|
||||
const all = parseBool(query.all);
|
||||
return this.manager.getSessions(all);
|
||||
@ApiOperation({ summary: 'List all sessions' })
|
||||
list(
|
||||
@Query(new WAHAValidationPipe()) query: ListSessionsQuery,
|
||||
): Promise<SessionInfo[]> {
|
||||
return this.manager.getSessions(query.all);
|
||||
}
|
||||
|
||||
@Get('/:session')
|
||||
@ApiOperation({ summary: 'Get session information' })
|
||||
@SessionApiParam
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async get(@Param('session') name: string): Promise<SessionInfo> {
|
||||
const session = this.manager.getSessionInfo(name);
|
||||
if (session === null) {
|
||||
@@ -76,20 +73,229 @@ class SessionsController {
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/sessions/:session')
|
||||
@ApiTags('sessions')
|
||||
class SessionController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Get('me')
|
||||
@Get(':session/me')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Get information about the authenticated account' })
|
||||
getMe(@SessionParam session: WhatsappSession): Promise<MeInfo | null> {
|
||||
getMe(@SessionParam session: WhatsappSession): MeInfo | null {
|
||||
return session.getSessionMeInfo();
|
||||
}
|
||||
|
||||
@Post('')
|
||||
@ApiOperation({
|
||||
summary: 'Create a session',
|
||||
description:
|
||||
'Create session a new session (and start it at the same time if required).',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async create(@Body() request: SessionCreateRequest): Promise<SessionDTO> {
|
||||
const name = request.name || generatePrefixedId('session');
|
||||
await this.withLock(name, async () => {
|
||||
if (await this.manager.exists(name)) {
|
||||
const msg = `Session '${name}' already exists. Use PUT to update it.`;
|
||||
throw new UnprocessableEntityException(msg);
|
||||
}
|
||||
|
||||
const config = request.config;
|
||||
const start = request.start || false;
|
||||
await this.manager.upsert(name, config);
|
||||
if (start) {
|
||||
await this.manager.start(name);
|
||||
}
|
||||
});
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Put(':session')
|
||||
@ApiOperation({
|
||||
summary: 'Update a session',
|
||||
description: '',
|
||||
})
|
||||
@SessionApiParam
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async update(
|
||||
@Param('session') name: string,
|
||||
@Body() request: SessionUpdateRequest,
|
||||
): Promise<SessionDTO> {
|
||||
await this.withLock(name, async () => {
|
||||
if (!(await this.manager.exists(name))) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
const config = request.config;
|
||||
const isRunning = this.manager.isRunning(name);
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.upsert(name, config);
|
||||
if (isRunning) {
|
||||
await this.manager.start(name);
|
||||
}
|
||||
});
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Delete(':session')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Delete the session',
|
||||
description:
|
||||
'Delete the session with the given name. Stop and logout as well. Idempotent operation.',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async delete(@Param('session') name: string): Promise<void> {
|
||||
await this.withLock(name, async () => {
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.logout(name);
|
||||
await this.manager.delete(name);
|
||||
});
|
||||
}
|
||||
|
||||
@Post(':session/start')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Start the session',
|
||||
description:
|
||||
'Start the session with the given name. The session must exist. Identity operation.',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async start(@Param('session') name: string): Promise<SessionDTO> {
|
||||
await this.withLock(name, async () => {
|
||||
const exists = await this.manager.exists(name);
|
||||
if (!exists) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
const isRunning = this.manager.isRunning(name);
|
||||
if (!isRunning) {
|
||||
await this.manager.start(name);
|
||||
}
|
||||
});
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Post(':session/stop')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Stop the session',
|
||||
description: 'Stop the session with the given name. Idempotent operation.',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async stop(@Param('session') name: string): Promise<SessionDTO> {
|
||||
await this.withLock(name, async () => {
|
||||
const exists = await this.manager.exists(name);
|
||||
if (!exists) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
await this.manager.stop(name, false);
|
||||
});
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Post(':session/logout')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Logout from the session',
|
||||
description: 'Logout the session, restart a session if it was not STOPPED',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async logout(@Param('session') name: string): Promise<SessionDTO> {
|
||||
await this.withLock(name, async () => {
|
||||
const exists = await this.manager.exists(name);
|
||||
if (!exists) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
const isRunning = this.manager.isRunning(name);
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.logout(name);
|
||||
if (isRunning) {
|
||||
await this.manager.start(name);
|
||||
}
|
||||
});
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Post(':session/restart')
|
||||
@SessionApiParam
|
||||
@ApiOperation({
|
||||
summary: 'Restart the session',
|
||||
description: 'Restart the session with the given name.',
|
||||
})
|
||||
@UsePipes(new WAHAValidationPipe())
|
||||
async restart(@Param('session') name: string): Promise<SessionDTO> {
|
||||
await this.withLock(name, async () => {
|
||||
const exists = await this.manager.exists(name);
|
||||
if (!exists) {
|
||||
throw new NotFoundException('Session not found');
|
||||
}
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.start(name);
|
||||
});
|
||||
|
||||
return await this.manager.getSessionInfo(name);
|
||||
}
|
||||
|
||||
@Post('/start/')
|
||||
@ApiOperation({
|
||||
summary: 'Upsert and Start session',
|
||||
description:
|
||||
'Create session (if not exists) or update a config (if exists) and start it.',
|
||||
deprecated: true,
|
||||
})
|
||||
async DEPRACATED_start(
|
||||
@Body() request: SessionStartDeprecatedRequest,
|
||||
): Promise<SessionDTO> {
|
||||
const name = request.name;
|
||||
if (this.manager.isRunning(name)) {
|
||||
const msg = `Session '${name}' is already started.`;
|
||||
throw new UnprocessableEntityException(msg);
|
||||
}
|
||||
|
||||
return await this.withLock(name, async () => {
|
||||
const config = request.config;
|
||||
await this.manager.upsert(name, config);
|
||||
return await this.manager.start(name);
|
||||
});
|
||||
}
|
||||
|
||||
@Post('/stop/')
|
||||
@ApiOperation({
|
||||
summary: 'Stop (and Logout if asked) session',
|
||||
description: 'Stop session and Logout by default.',
|
||||
deprecated: true,
|
||||
})
|
||||
async DEPRECATED_stop(
|
||||
@Body() request: SessionStopDeprecatedRequest,
|
||||
): Promise<void> {
|
||||
const name = request.name;
|
||||
if (request.logout) {
|
||||
// Old API did remove the session complete
|
||||
await this.withLock(name, async () => {
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.logout(name);
|
||||
await this.manager.delete(name);
|
||||
});
|
||||
} else {
|
||||
await this.withLock(name, async () => {
|
||||
await this.manager.stop(name, false);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@Post('/logout/')
|
||||
@ApiOperation({
|
||||
summary: 'Logout and Delete session.',
|
||||
description: 'Stop, Logout and Delete session.',
|
||||
deprecated: true,
|
||||
})
|
||||
async DEPRECATED_logout(
|
||||
@Body() request: SessionLogoutDeprecatedRequest,
|
||||
): Promise<void> {
|
||||
const name = request.name;
|
||||
await this.withLock(name, async () => {
|
||||
await this.manager.stop(name, true);
|
||||
await this.manager.logout(name);
|
||||
await this.manager.delete(name);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export { SessionController, SessionsController };
|
||||
export { SessionsController };
|
||||
@@ -1,33 +1,29 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { Body, Controller, Post } from '@nestjs/common';
|
||||
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
SessionApiParam,
|
||||
SessionParam,
|
||||
} from '@waha/nestjs/params/SessionApiParam';
|
||||
|
||||
import { SessionManager } from '../core/abc/manager.abc';
|
||||
import { WhatsappSession } from '../core/abc/session.abc';
|
||||
import {
|
||||
DeleteStatusRequest,
|
||||
ImageStatus,
|
||||
TextStatus,
|
||||
VideoStatus,
|
||||
VoiceStatus,
|
||||
} from '../structures/status.dto';
|
||||
import { SessionApiParam, SessionParam } from './helpers';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/:session/status')
|
||||
@ApiTags('status')
|
||||
@ApiTags('🟢 Status')
|
||||
class StatusController {
|
||||
constructor(private manager: SessionManager) {}
|
||||
|
||||
@Post('text')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Send text status.' })
|
||||
@ApiOperation({ summary: 'Send text status' })
|
||||
sendTextStatus(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() status: TextStatus,
|
||||
@@ -37,7 +33,7 @@ class StatusController {
|
||||
|
||||
@Post('image')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Send image status.' })
|
||||
@ApiOperation({ summary: 'Send image status' })
|
||||
sendImageStatus(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() status: ImageStatus,
|
||||
@@ -47,7 +43,7 @@ class StatusController {
|
||||
|
||||
@Post('voice')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Send voice status.' })
|
||||
@ApiOperation({ summary: 'Send voice status' })
|
||||
sendVoiceStatus(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() status: VoiceStatus,
|
||||
@@ -57,13 +53,23 @@ class StatusController {
|
||||
|
||||
@Post('video')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'Send video status.' })
|
||||
@ApiOperation({ summary: 'Send video status' })
|
||||
sendVideoStatus(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() status: VideoStatus,
|
||||
) {
|
||||
return session.sendVideoStatus(status);
|
||||
}
|
||||
|
||||
@Post('delete')
|
||||
@SessionApiParam
|
||||
@ApiOperation({ summary: 'DELETE sent status' })
|
||||
deleteStatus(
|
||||
@SessionParam session: WhatsappSession,
|
||||
@Body() status: DeleteStatusRequest,
|
||||
) {
|
||||
return session.deleteStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
export { StatusController };
|
||||
@@ -1,14 +1,24 @@
|
||||
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';
|
||||
|
||||
@ApiSecurity('api_key')
|
||||
@Controller('api/version')
|
||||
@ApiTags('other')
|
||||
@ApiTags('🔍 Observability')
|
||||
export class VersionController {
|
||||
@Get('')
|
||||
@ApiOperation({
|
||||
summary: 'Get the server version ',
|
||||
deprecated: true,
|
||||
description: "Use 'GET /api/server/version' instead ",
|
||||
})
|
||||
get(): WAHAEnvironment {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
+22
-21
@@ -1,20 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { WAHAEvents } from '@waha/structures/enums.dto';
|
||||
|
||||
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 {
|
||||
public filesUri = '/api/files';
|
||||
public schema = 'http';
|
||||
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
get filesURL(): string {
|
||||
return `${this.schema}://${this.hostname}:${this.port}${this.filesUri}/`;
|
||||
get schema() {
|
||||
return this.configService.get('WHATSAPP_API_SCHEMA', 'http');
|
||||
}
|
||||
|
||||
get hostname(): string {
|
||||
@@ -25,17 +21,6 @@ export class WhatsappConfigService {
|
||||
return this.configService.get('WHATSAPP_API_PORT', '3000');
|
||||
}
|
||||
|
||||
get filesFolder(): string {
|
||||
return this.configService.get(
|
||||
'WHATSAPP_FILES_FOLDER',
|
||||
'/tmp/whatsapp-files',
|
||||
);
|
||||
}
|
||||
|
||||
get filesLifetime(): number {
|
||||
return this.configService.get<number>('WHATSAPP_FILES_LIFETIME', 180);
|
||||
}
|
||||
|
||||
get mimetypes(): string[] {
|
||||
if (!this.shouldDownloadMedia) {
|
||||
return ['mimetype/ignore-all-media'];
|
||||
@@ -66,8 +51,11 @@ export class WhatsappConfigService {
|
||||
}
|
||||
|
||||
get proxyServer(): string[] | string | undefined {
|
||||
const single = this.configService.get('WHATSAPP_PROXY_SERVER', undefined);
|
||||
const multipleValues = this.configService.get(
|
||||
const single = this.configService.get<string>(
|
||||
'WHATSAPP_PROXY_SERVER',
|
||||
undefined,
|
||||
);
|
||||
const multipleValues = this.configService.get<string>(
|
||||
'WHATSAPP_PROXY_SERVER_LIST',
|
||||
undefined,
|
||||
);
|
||||
@@ -103,7 +91,7 @@ export class WhatsappConfigService {
|
||||
return this.get('WHATSAPP_HOOK_URL');
|
||||
}
|
||||
|
||||
private getWebhookEvents(): string[] {
|
||||
private getWebhookEvents(): WAHAEvents[] {
|
||||
const value = this.get('WHATSAPP_HOOK_EVENTS', '');
|
||||
return value ? value.split(',') : [];
|
||||
}
|
||||
@@ -120,6 +108,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',
|
||||
@@ -140,4 +136,9 @@ export class WhatsappConfigService {
|
||||
3000,
|
||||
);
|
||||
}
|
||||
|
||||
get debugModeEnabled(): boolean {
|
||||
const value = this.configService.get('WAHA_DEBUG_MODE', 'false');
|
||||
return parseBool(value);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { DocumentBuilder, OpenAPIObject, SwaggerModule } from '@nestjs/swagger';
|
||||
import { DECORATORS } from '@nestjs/swagger/dist/constants';
|
||||
import { Logger } from 'nestjs-pino';
|
||||
|
||||
import { WhatsappConfigService } from '../config.service';
|
||||
import { VERSION } from '../version';
|
||||
import { SwaggerConfigServiceCore } from './config/SwaggerConfigServiceCore';
|
||||
|
||||
export class SwaggerConfiguratorCore {
|
||||
constructor(protected app: INestApplication) {}
|
||||
protected logger: any;
|
||||
|
||||
constructor(protected app: INestApplication) {
|
||||
this.logger = app.get(Logger);
|
||||
}
|
||||
|
||||
get title() {
|
||||
return 'WAHA - WhatsApp HTTP API';
|
||||
@@ -24,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>' +
|
||||
@@ -51,24 +56,30 @@ export class SwaggerConfiguratorCore {
|
||||
.setDescription(this.description)
|
||||
.setExternalDoc(this.title, this.externalDocUrl)
|
||||
.setVersion(VERSION.version)
|
||||
.addTag('sessions', 'Control WhatsApp sessions')
|
||||
.addTag('auth', 'Authentication')
|
||||
.addTag('screenshot', 'Get screenshot of WhatsApp and show QR code')
|
||||
.addTag('chatting', 'Chatting methods')
|
||||
.addTag('🖥️ Sessions', 'Control WhatsApp sessions (accounts)')
|
||||
.addTag('🔑 Auth', 'Authentication')
|
||||
.addTag('🖼️ Screenshot', 'Get screenshot of WhatsApp and show QR code')
|
||||
.addTag('📤 Chatting', 'Chatting methods')
|
||||
.addTag('📢 Channels', 'Channels (newsletters) methods')
|
||||
.addTag(
|
||||
'status',
|
||||
'🟢 Status',
|
||||
'Status (aka stories) methods. <b>NOWEB</b> engine only!',
|
||||
)
|
||||
.addTag('chats', `Chats methods`)
|
||||
.addTag('💬 Chats', `Chats methods`)
|
||||
.addTag(
|
||||
'contacts',
|
||||
'👤 Contacts',
|
||||
`Contacts methods.<br>
|
||||
Use phone number (without +) or phone number and \`@c.us\` at the end as \`contactId\`.<br>
|
||||
'E.g: \`12312312310\` OR \`12312312310@c.us\`<br>`,
|
||||
)
|
||||
.addTag('groups', `Groups methods.<br>`)
|
||||
.addTag('presence', `Presence information`)
|
||||
.addTag('other', 'Other methods')
|
||||
.addTag('👥 Groups', `Groups methods.<br>`)
|
||||
.addTag('✅ Presence', `Presence information`)
|
||||
.addTag(
|
||||
'🏷️ Labels',
|
||||
'Labels - available only for WhatsApp Business accounts',
|
||||
)
|
||||
.addTag('🔍 Observability', 'Other methods')
|
||||
.addTag('🗄️ Storage', 'Storage methods')
|
||||
.addApiKey({
|
||||
type: 'apiKey',
|
||||
description: 'Your secret api key',
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export abstract class DataStore {}
|
||||
export abstract class DataStore {
|
||||
abstract init(sessionName?: string): Promise<void>;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ConsoleLogger, Injectable } from '@nestjs/common';
|
||||
import { DiskHealthIndicator, HealthCheckService } from '@nestjs/terminus';
|
||||
import { Injectable, Logger, LoggerService } from '@nestjs/common';
|
||||
import { HealthCheckService } from '@nestjs/terminus';
|
||||
import type { HealthCheckResult } from '@nestjs/terminus/dist/health-check/health-check-result.interface';
|
||||
|
||||
import { WhatsappConfigService } from '../../config.service';
|
||||
@@ -7,12 +7,14 @@ import { SessionManager } from './manager.abc';
|
||||
|
||||
@Injectable()
|
||||
export abstract class WAHAHealthCheckService {
|
||||
protected logger: LoggerService;
|
||||
constructor(
|
||||
protected sessionManager: SessionManager,
|
||||
protected health: HealthCheckService,
|
||||
protected log: ConsoleLogger,
|
||||
protected config: WhatsappConfigService,
|
||||
) {}
|
||||
) {
|
||||
this.logger = new Logger('WAHAHealthCheckService');
|
||||
}
|
||||
|
||||
abstract check(): Promise<HealthCheckResult>;
|
||||
}
|
||||
+39
-10
@@ -1,22 +1,24 @@
|
||||
import { OnApplicationShutdown } from '@nestjs/common';
|
||||
import { BeforeApplicationShutdown } from '@nestjs/common';
|
||||
import { WAHAWebhook } from '@waha/structures/webhooks.dto';
|
||||
import { VERSION } from '@waha/version';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { WAHAEngine } from '../../structures/enums.dto';
|
||||
import { WAHAEngine, WAHAEvents } from '../../structures/enums.dto';
|
||||
import {
|
||||
SessionConfig,
|
||||
SessionDTO,
|
||||
SessionInfo,
|
||||
SessionLogoutRequest,
|
||||
SessionStartRequest,
|
||||
SessionStopRequest,
|
||||
} from '../../structures/sessions.dto';
|
||||
import { ISessionAuthRepository } from '../storage/ISessionAuthRepository';
|
||||
import { ISessionConfigRepository } from '../storage/ISessionConfigRepository';
|
||||
import { WhatsappSession } from './session.abc';
|
||||
import { WebhookConductor } from './webhooks.abc';
|
||||
|
||||
export abstract class SessionManager implements OnApplicationShutdown {
|
||||
export abstract class SessionManager implements BeforeApplicationShutdown {
|
||||
public store: any;
|
||||
public sessionAuthRepository: ISessionAuthRepository;
|
||||
public sessionConfigRepository: ISessionConfigRepository;
|
||||
public events: EventEmitter;
|
||||
|
||||
protected abstract getEngine(engine: WAHAEngine): typeof WhatsappSession;
|
||||
|
||||
@@ -24,20 +26,47 @@ export abstract class SessionManager implements OnApplicationShutdown {
|
||||
|
||||
protected abstract get WebhookConductorClass(): typeof WebhookConductor;
|
||||
|
||||
abstract onApplicationShutdown(signal?: string);
|
||||
abstract beforeApplicationShutdown(signal?: string);
|
||||
|
||||
//
|
||||
// API Methods
|
||||
//
|
||||
abstract start(request: SessionStartRequest): Promise<SessionDTO>;
|
||||
/**
|
||||
* Either create or update
|
||||
*/
|
||||
abstract exists(name: string): Promise<boolean>;
|
||||
|
||||
abstract stop(request: SessionStopRequest): Promise<void>;
|
||||
abstract isRunning(name: string): boolean;
|
||||
|
||||
abstract logout(request: SessionLogoutRequest): Promise<void>;
|
||||
abstract upsert(name: string, config?: SessionConfig): Promise<void>;
|
||||
|
||||
abstract delete(name: string): Promise<void>;
|
||||
|
||||
abstract start(name: string): Promise<SessionDTO>;
|
||||
|
||||
abstract stop(name: string, silent: boolean): Promise<void>;
|
||||
|
||||
abstract logout(name: string): Promise<void>;
|
||||
|
||||
abstract getSession(name: string): WhatsappSession;
|
||||
|
||||
abstract getSessionInfo(name: string): Promise<SessionInfo | null>;
|
||||
|
||||
abstract getSessions(all: boolean): Promise<SessionInfo[]>;
|
||||
|
||||
handleSessionEvent(event: WAHAEvents, session: WhatsappSession) {
|
||||
return (payload: any) => {
|
||||
const me = session.getSessionMeInfo();
|
||||
const data: WAHAWebhook = {
|
||||
event: event,
|
||||
session: session.name,
|
||||
metadata: session.sessionConfig?.metadata,
|
||||
me: me,
|
||||
payload: payload,
|
||||
engine: session.engine,
|
||||
environment: VERSION,
|
||||
};
|
||||
this.events.emit(event, data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
abstract class MediaStorage {
|
||||
abstract save(
|
||||
messageId: string,
|
||||
mimetype: string,
|
||||
buffer: Buffer,
|
||||
): Promise<string>;
|
||||
}
|
||||
|
||||
interface IEngineMediaProcessor<Message> {
|
||||
hasMedia(message: Message): boolean;
|
||||
|
||||
getFilename(message: Message): string | null;
|
||||
|
||||
getMimetype(message: Message): string;
|
||||
|
||||
getMessageId(message: Message): string;
|
||||
|
||||
getMediaBuffer(message: Message): Promise<Buffer | null>;
|
||||
}
|
||||
|
||||
interface MediaManager {
|
||||
processMedia<Message>(
|
||||
processor: IEngineMediaProcessor<Message>,
|
||||
message: Message,
|
||||
): Promise<Message>;
|
||||
}
|
||||
|
||||
export { IEngineMediaProcessor, MediaManager, MediaStorage };
|
||||
+142
-36
@@ -1,6 +1,14 @@
|
||||
import { ConsoleLogger } from '@nestjs/common';
|
||||
import {
|
||||
Channel,
|
||||
CreateChannelRequest,
|
||||
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';
|
||||
import { Logger } from 'pino';
|
||||
import { MessageId } from 'whatsapp-web.js';
|
||||
|
||||
import {
|
||||
@@ -40,6 +48,7 @@ import {
|
||||
SessionConfig,
|
||||
} from '../../structures/sessions.dto';
|
||||
import {
|
||||
DeleteStatusRequest,
|
||||
ImageStatus,
|
||||
TextStatus,
|
||||
VideoStatus,
|
||||
@@ -47,9 +56,9 @@ import {
|
||||
} from '../../structures/status.dto';
|
||||
import { WASessionStatusBody } from '../../structures/webhooks.dto';
|
||||
import { NotImplementedByEngineError } from '../exceptions';
|
||||
import { IMediaManager } from '../media/IMediaManager';
|
||||
import { QR } from '../QR';
|
||||
import { DataStore } from './DataStore';
|
||||
import { MediaManager } from './media.abc';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const qrcode = require('qrcode-terminal');
|
||||
@@ -74,14 +83,13 @@ export function ensureSuffix(phone) {
|
||||
|
||||
export enum WAHAInternalEvent {
|
||||
ENGINE_START = 'engine.start',
|
||||
SESSION_STATUS_CHANGED = 'session.status.changed',
|
||||
}
|
||||
|
||||
export interface SessionParams {
|
||||
name: string;
|
||||
printQR: boolean;
|
||||
mediaManager: MediaManager;
|
||||
log: ConsoleLogger;
|
||||
mediaManager: IMediaManager;
|
||||
loggerBuilder: LoggerBuilder;
|
||||
sessionStore: DataStore;
|
||||
proxyConfig?: ProxyConfig;
|
||||
sessionConfig?: SessionConfig;
|
||||
@@ -93,8 +101,9 @@ export abstract class WhatsappSession {
|
||||
public engine: WAHAEngine;
|
||||
|
||||
public name: string;
|
||||
protected mediaManager: MediaManager;
|
||||
protected log: ConsoleLogger;
|
||||
protected mediaManager: IMediaManager;
|
||||
public loggerBuilder: LoggerBuilder;
|
||||
protected logger: Logger;
|
||||
protected sessionStore: DataStore;
|
||||
protected proxyConfig?: ProxyConfig;
|
||||
public sessionConfig?: SessionConfig;
|
||||
@@ -106,7 +115,7 @@ export abstract class WhatsappSession {
|
||||
public constructor({
|
||||
name,
|
||||
printQR,
|
||||
log,
|
||||
loggerBuilder,
|
||||
sessionStore,
|
||||
proxyConfig,
|
||||
mediaManager,
|
||||
@@ -116,7 +125,8 @@ export abstract class WhatsappSession {
|
||||
this.events = new EventEmitter();
|
||||
this.name = name;
|
||||
this.proxyConfig = proxyConfig;
|
||||
this.log = log;
|
||||
this.loggerBuilder = loggerBuilder;
|
||||
this.logger = loggerBuilder.child({ name: 'WhatsappSession' });
|
||||
this.sessionStore = sessionStore;
|
||||
this.mediaManager = mediaManager;
|
||||
this.sessionConfig = sessionConfig;
|
||||
@@ -126,7 +136,8 @@ export abstract class WhatsappSession {
|
||||
|
||||
protected set status(value: WAHASessionStatus) {
|
||||
this._status = value;
|
||||
this.events.emit(WAHAInternalEvent.SESSION_STATUS_CHANGED, value);
|
||||
const body: WASessionStatusBody = { name: this.name, status: value };
|
||||
this.events.emit(WAHAEvents.SESSION_STATUS, body);
|
||||
}
|
||||
|
||||
public get status() {
|
||||
@@ -141,34 +152,51 @@ export abstract class WhatsappSession {
|
||||
// Run optimized version of Chrome
|
||||
// References:
|
||||
// https://github.com/pedroslopez/whatsapp-web.js/issues/1420
|
||||
// https://github.com/wppconnect-team/wppconnect/issues/1326
|
||||
// https://www.bannerbear.com/blog/ways-to-speed-up-puppeteer-screenshots/
|
||||
return [
|
||||
'--no-sandbox',
|
||||
'--aggressive-cache-discard',
|
||||
'--disable-accelerated-2d-canvas',
|
||||
'--disable-application-cache',
|
||||
'--disable-background-networking',
|
||||
'--disable-cache',
|
||||
'--disable-client-side-phishing-detection',
|
||||
'--disable-setuid-sandbox',
|
||||
'--disable-component-update',
|
||||
'--disable-default-apps',
|
||||
'--disable-popup-blocking',
|
||||
'--disable-offer-store-unmasked-wallet-cards',
|
||||
'--disable-speech-api',
|
||||
'--hide-scrollbars',
|
||||
'--mute-audio',
|
||||
'--disable-extensions',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-accelerated-2d-canvas',
|
||||
'--no-first-run',
|
||||
'--no-default-browser-check',
|
||||
'--no-pings',
|
||||
'--password-store=basic',
|
||||
'--use-mock-keychain',
|
||||
'--no-zygote',
|
||||
'--single-process',
|
||||
'--disable-extensions',
|
||||
'--disable-gpu',
|
||||
'--disable-offer-store-unmasked-wallet-cards',
|
||||
'--disable-offline-load-stale-cache',
|
||||
'--disable-popup-blocking',
|
||||
'--disable-setuid-sandbox',
|
||||
'--disable-site-isolation-trials', // https://superuser.com/questions/654565/how-to-run-google-chrome-in-a-single-process
|
||||
'--disable-speech-api',
|
||||
'--disable-sync',
|
||||
'--disable-translate',
|
||||
'--disable-web-security',
|
||||
'--disk-cache-size=0',
|
||||
'--hide-scrollbars',
|
||||
'--ignore-certificate-errors',
|
||||
'--ignore-ssl-errors',
|
||||
'--in-process-gpu', // https://superuser.com/questions/654565/how-to-run-google-chrome-in-a-single-process
|
||||
'--metrics-recording-only',
|
||||
'--mute-audio',
|
||||
'--no-default-browser-check',
|
||||
'--no-first-run',
|
||||
'--no-pings',
|
||||
'--no-sandbox',
|
||||
'--no-zygote',
|
||||
'--password-store=basic',
|
||||
'--renderer-process-limit=2', // https://superuser.com/questions/654565/how-to-run-google-chrome-in-a-single-process
|
||||
'--safebrowsing-disable-auto-update',
|
||||
'--single-process',
|
||||
'--use-mock-keychain',
|
||||
];
|
||||
}
|
||||
|
||||
protected isDebugEnabled() {
|
||||
return this.log.isLevelEnabled('debug');
|
||||
return this.logger.isLevelEnabled('debug');
|
||||
}
|
||||
|
||||
/** Start the session */
|
||||
@@ -184,10 +212,7 @@ export abstract class WhatsappSession {
|
||||
): boolean {
|
||||
switch (hook) {
|
||||
case WAHAEvents.SESSION_STATUS:
|
||||
this.events.on(WAHAInternalEvent.SESSION_STATUS_CHANGED, (value) => {
|
||||
const body: WASessionStatusBody = { name: this.name, status: value };
|
||||
handler(body);
|
||||
});
|
||||
this.events.on(WAHAEvents.SESSION_STATUS, handler);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -221,8 +246,8 @@ export abstract class WhatsappSession {
|
||||
|
||||
abstract getScreenshot(): Promise<Buffer>;
|
||||
|
||||
public getSessionMeInfo(): Promise<MeInfo | null> {
|
||||
throw new NotImplementedByEngineError();
|
||||
public getSessionMeInfo(): MeInfo | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
public getCaptcha(): Promise<QR> {
|
||||
@@ -285,7 +310,7 @@ export abstract class WhatsappSession {
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
public getChats() {
|
||||
public getChats(query: GetChatsQuery) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
@@ -317,6 +342,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
|
||||
*/
|
||||
@@ -435,6 +488,47 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Channels methods
|
||||
*/
|
||||
public channelsList(query: ListChannelsQuery): Promise<Channel[]> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsCreateChannel(
|
||||
request: CreateChannelRequest,
|
||||
): Promise<Channel> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsGetChannel(id: string): Promise<Channel> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsGetChannelByInviteCode(inviteCode: string): Promise<Channel> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsDeleteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsFollowChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsUnfollowChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsMuteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsUnmuteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Status methods
|
||||
*/
|
||||
@@ -454,6 +548,10 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public deleteStatus(request: DeleteStatusRequest) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async getEngineInfo(): Promise<any> {
|
||||
return {};
|
||||
}
|
||||
@@ -485,14 +583,22 @@ export abstract class WhatsappSession {
|
||||
return;
|
||||
}
|
||||
if (!qr.raw) {
|
||||
this.log.error(
|
||||
this.logger.error(
|
||||
'QR.raw is not available, can not print it in the console',
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.log.log(
|
||||
this.logger.info(
|
||||
"You can disable QR in console by setting 'WAHA_PRINT_QR=false' in your environment variables.",
|
||||
);
|
||||
qrcode.generate(qr.raw, { small: true });
|
||||
}
|
||||
}
|
||||
|
||||
export function isNewsletter(jid: string) {
|
||||
return jid.endsWith('@newsletter');
|
||||
}
|
||||
|
||||
export function getChannelInviteLink(code: string) {
|
||||
return `https://whatsapp.com/channel/${code}`;
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
import { ConsoleLogger } from '@nestjs/common';
|
||||
import { LoggerBuilder } from '@waha/utils/logging';
|
||||
import { Logger } from 'pino';
|
||||
|
||||
import { WebhookConfig } from '../../structures/webhooks.config.dto';
|
||||
import { WhatsappSession } from './session.abc';
|
||||
|
||||
export abstract class WebhookSender {
|
||||
protected url: string;
|
||||
protected logger: Logger;
|
||||
|
||||
constructor(
|
||||
protected log: ConsoleLogger,
|
||||
loggerBuilder: LoggerBuilder,
|
||||
protected webhookConfig: WebhookConfig,
|
||||
) {
|
||||
this.url = webhookConfig.url;
|
||||
this.logger = loggerBuilder.child({ name: WebhookSender.name });
|
||||
}
|
||||
|
||||
abstract send(json);
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
import {
|
||||
BeforeApplicationShutdown,
|
||||
Logger,
|
||||
LoggerService,
|
||||
} from '@nestjs/common';
|
||||
import { sleep } from '@nestjs/terminus/dist/utils';
|
||||
import {
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
OnGatewayInit,
|
||||
WebSocketGateway,
|
||||
WebSocketServer,
|
||||
} from '@nestjs/websockets';
|
||||
import { SessionManager } from '@waha/core/abc/manager.abc';
|
||||
import { WebsocketHeartbeatJob } from '@waha/nestjs/ws/WebsocketHeartbeatJob';
|
||||
import { WebSocket } from '@waha/nestjs/ws/ws';
|
||||
import { WAHAEvents } from '@waha/structures/enums.dto';
|
||||
import { generatePrefixedId } from '@waha/utils/ids';
|
||||
import { IncomingMessage } from 'http';
|
||||
import * as lodash from 'lodash';
|
||||
import * as url from 'url';
|
||||
import { Server } from 'ws';
|
||||
|
||||
@WebSocketGateway({
|
||||
path: '/ws',
|
||||
cors: true,
|
||||
})
|
||||
export class WebsocketGatewayCore
|
||||
implements
|
||||
OnGatewayInit,
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
BeforeApplicationShutdown
|
||||
{
|
||||
HEARTBEAT_INTERVAL = 10_000;
|
||||
|
||||
@WebSocketServer()
|
||||
server: Server;
|
||||
|
||||
private listeners: Map<WebSocket, { session: string; events: string[] }> =
|
||||
new Map();
|
||||
|
||||
private readonly logger: LoggerService;
|
||||
private heartbeat: WebsocketHeartbeatJob;
|
||||
|
||||
constructor(private manager: SessionManager) {
|
||||
this.logger = new Logger('WebsocketGateway');
|
||||
this.heartbeat = new WebsocketHeartbeatJob(
|
||||
this.logger,
|
||||
this.HEARTBEAT_INTERVAL,
|
||||
);
|
||||
}
|
||||
|
||||
handleConnection(socket: WebSocket, request: IncomingMessage, ...args): any {
|
||||
// wsc - websocket client
|
||||
const id = generatePrefixedId('wsc');
|
||||
socket.id = id;
|
||||
this.logger.debug(`New client connected: ${request.url}`);
|
||||
const params = this.getParams(id, request, socket);
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
const { session, events } = params;
|
||||
this.logger.debug(
|
||||
`Client connected to session: '${session}', events: ${events}, ${id}`,
|
||||
);
|
||||
this.listeners.set(socket, { session, events });
|
||||
}
|
||||
|
||||
private getParams(id: string, request: IncomingMessage, socket: WebSocket) {
|
||||
const query = url.parse(request.url, true).query;
|
||||
const session = (query.session as string) || '*';
|
||||
if (session !== '*') {
|
||||
this.logger.warn(
|
||||
`Only connecting to all sessions is allowed for now, use session=*, ${id}`,
|
||||
);
|
||||
const error =
|
||||
'Only connecting to all sessions is allowed for now, use session=*';
|
||||
socket.close(4001, JSON.stringify({ error }));
|
||||
return null;
|
||||
}
|
||||
|
||||
const events = ((query.events as string) || '*').split(',');
|
||||
if (
|
||||
!lodash.isEqual(events, ['*']) &&
|
||||
!lodash.isEqual(events, [WAHAEvents.SESSION_STATUS])
|
||||
) {
|
||||
this.logger.warn(
|
||||
`Only \'session.status\' event is allowed for now, use events=session.status or events=*, ${id}`,
|
||||
);
|
||||
const error =
|
||||
"Only 'session.status' event is allowed for now, use events=session.status or events=*";
|
||||
socket.close(4001, JSON.stringify({ error }));
|
||||
return null;
|
||||
}
|
||||
return { session, events };
|
||||
}
|
||||
|
||||
handleDisconnect(socket: WebSocket): any {
|
||||
this.logger.debug(`Client disconnected - ${socket.id}`);
|
||||
this.listeners.delete(socket);
|
||||
}
|
||||
|
||||
async beforeApplicationShutdown(signal?: string) {
|
||||
this.logger.log('Shutting down websocket server');
|
||||
// Allow pending messages to be sent, it can be even 1ms, just to release the event loop
|
||||
await sleep(100);
|
||||
this.server?.clients.forEach((options, client) => {
|
||||
// @ts-ignore
|
||||
this.logger.debug(`Closing client connection - ${client.id}...`);
|
||||
client.close(1001, 'Server is shutting down');
|
||||
});
|
||||
// Do not turn off heartbeat service here,
|
||||
// it's responsible for terminating the connection that is not alive
|
||||
this.logger.log('Websocket server is down');
|
||||
}
|
||||
|
||||
afterInit(server: Server) {
|
||||
this.logger.debug('Websocket server initialized');
|
||||
this.manager.events.on(
|
||||
WAHAEvents.SESSION_STATUS,
|
||||
this.sendToAll.bind(this),
|
||||
);
|
||||
this.logger.debug('Subscribed to manager events');
|
||||
|
||||
this.logger.debug('Starting heartbeat service...');
|
||||
this.heartbeat.start(server);
|
||||
this.logger.debug('Heartbeat service started');
|
||||
}
|
||||
|
||||
sendToAll(data: any) {
|
||||
this.listeners.forEach((options, client) => {
|
||||
if (options.events.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.logger.debug('Sending data to client', data);
|
||||
client.send(JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
+83
-27
@@ -1,11 +1,26 @@
|
||||
import { ConsoleLogger, Module } from '@nestjs/common';
|
||||
import { INestApplication, Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { APP_INTERCEPTOR } from '@nestjs/core';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { BufferJsonReplacerInterceptor } from '@waha/api/BufferJsonReplacerInterceptor';
|
||||
import { ChannelsController } from '@waha/api/channels.controller';
|
||||
import {
|
||||
ServerController,
|
||||
ServerDebugController,
|
||||
} from '@waha/api/server.controller';
|
||||
import { WebsocketGatewayCore } from '@waha/core/api/websocket.gateway.core';
|
||||
import { MediaLocalStorageConfig } from '@waha/core/media/local/MediaLocalStorageConfig';
|
||||
import { BufferJsonReplacerInterceptor } from '@waha/nestjs/BufferJsonReplacerInterceptor';
|
||||
import {
|
||||
getPinoHttpUseLevel,
|
||||
getPinoLogLevel,
|
||||
getPinoTransport,
|
||||
} from '@waha/utils/logging';
|
||||
import * as Joi from 'joi';
|
||||
import { LoggerModule } from 'nestjs-pino';
|
||||
import { join } from 'path';
|
||||
import { Logger } from 'pino';
|
||||
|
||||
import { AuthController } from '../api/auth.controller';
|
||||
import { ChatsController } from '../api/chats.controller';
|
||||
@@ -13,12 +28,11 @@ 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 {
|
||||
SessionController,
|
||||
SessionsController,
|
||||
} from '../api/sessions.controller';
|
||||
import { SessionsController } from '../api/sessions.controller';
|
||||
import { StatusController } from '../api/status.controller';
|
||||
import { VersionController } from '../api/version.controller';
|
||||
import { WhatsappConfigService } from '../config.service';
|
||||
@@ -31,31 +45,56 @@ import { WAHAHealthCheckServiceCore } from './health/WAHAHealthCheckServiceCore'
|
||||
import { SessionManagerCore } from './manager.core';
|
||||
|
||||
export const IMPORTS = [
|
||||
LoggerModule.forRoot({
|
||||
renameContext: 'name',
|
||||
pinoHttp: {
|
||||
quietReqLogger: true,
|
||||
level: getPinoLogLevel(),
|
||||
useLevel: getPinoHttpUseLevel(),
|
||||
transport: getPinoTransport(),
|
||||
autoLogging: {
|
||||
ignore: (req) => {
|
||||
return (
|
||||
req.url.startsWith('/dashboard/') ||
|
||||
req.url.startsWith('/api/files/') ||
|
||||
req.url.startsWith('/api/s3/')
|
||||
);
|
||||
},
|
||||
},
|
||||
serializers: {
|
||||
req: (req) => ({
|
||||
id: req.id,
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
query: req.query,
|
||||
params: req.params,
|
||||
}),
|
||||
res: (res) => ({
|
||||
statusCode: res.statusCode,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
validationSchema: Joi.object({
|
||||
WHATSAPP_API_SCHEMA: Joi.string().valid('http', 'https').default('http'),
|
||||
}),
|
||||
}),
|
||||
ServeStaticModule.forRootAsync({
|
||||
imports: [],
|
||||
extraProviders: [WhatsappConfigService, DashboardConfigServiceCore],
|
||||
inject: [WhatsappConfigService, DashboardConfigServiceCore],
|
||||
useFactory: (
|
||||
config: WhatsappConfigService,
|
||||
dashboardConfig: DashboardConfigServiceCore,
|
||||
) => {
|
||||
const options = [
|
||||
// Serve files (media)
|
||||
extraProviders: [DashboardConfigServiceCore],
|
||||
inject: [DashboardConfigServiceCore],
|
||||
useFactory: (dashboardConfig: DashboardConfigServiceCore) => {
|
||||
if (!dashboardConfig.enabled) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
rootPath: config.filesFolder,
|
||||
serveRoot: config.filesUri,
|
||||
},
|
||||
];
|
||||
if (dashboardConfig.enabled) {
|
||||
options.push({
|
||||
rootPath: join(__dirname, '..', 'dashboard'),
|
||||
serveRoot: dashboardConfig.dashboardUri,
|
||||
});
|
||||
}
|
||||
return options;
|
||||
},
|
||||
];
|
||||
},
|
||||
}),
|
||||
PassportModule,
|
||||
@@ -64,16 +103,20 @@ export const IMPORTS = [
|
||||
export const CONTROLLERS = [
|
||||
AuthController,
|
||||
SessionsController,
|
||||
SessionController,
|
||||
ChattingController,
|
||||
ChatsController,
|
||||
ChannelsController,
|
||||
StatusController,
|
||||
LabelsController,
|
||||
ContactsController,
|
||||
GroupsController,
|
||||
PresenceController,
|
||||
ScreenshotController,
|
||||
VersionController,
|
||||
PingController,
|
||||
HealthController,
|
||||
ServerController,
|
||||
ServerDebugController,
|
||||
VersionController,
|
||||
];
|
||||
const PROVIDERS = [
|
||||
{
|
||||
@@ -92,7 +135,8 @@ const PROVIDERS = [
|
||||
SwaggerConfigServiceCore,
|
||||
WhatsappConfigService,
|
||||
EngineConfigService,
|
||||
ConsoleLogger,
|
||||
WebsocketGatewayCore,
|
||||
MediaLocalStorageConfig,
|
||||
];
|
||||
|
||||
@Module({
|
||||
@@ -101,5 +145,17 @@ const PROVIDERS = [
|
||||
providers: PROVIDERS,
|
||||
})
|
||||
export class AppModuleCore {
|
||||
constructor(protected config: WhatsappConfigService) {}
|
||||
public startTimestamp: number;
|
||||
|
||||
constructor(protected config: WhatsappConfigService) {
|
||||
this.startTimestamp = Date.now();
|
||||
}
|
||||
|
||||
static getHttpsOptions(logger: Logger) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static appReady(app: INestApplication, logger: Logger) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
|
||||
@@ -7,7 +8,11 @@ import { parseBool } from '../../helpers';
|
||||
export class DashboardConfigServiceCore {
|
||||
public dashboardUri = '/dashboard';
|
||||
|
||||
constructor(protected configService: ConfigService) {}
|
||||
constructor(
|
||||
protected configService: ConfigService,
|
||||
@InjectPinoLogger('DashboardConfigService')
|
||||
protected logger: PinoLogger,
|
||||
) {}
|
||||
|
||||
get enabled(): boolean {
|
||||
const value = this.configService.get('WAHA_DASHBOARD_ENABLED', 'true');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
@@ -7,14 +7,18 @@ import { getEngineName } from '../../version';
|
||||
|
||||
@Injectable()
|
||||
export class EngineConfigService {
|
||||
constructor(protected configService: ConfigService) {}
|
||||
private logger: Logger;
|
||||
|
||||
constructor(protected configService: ConfigService) {
|
||||
this.logger = new Logger('EngineConfigService');
|
||||
}
|
||||
|
||||
getDefaultEngineName(): WAHAEngine {
|
||||
const value = getEngineName();
|
||||
if (value in WAHAEngine) {
|
||||
return WAHAEngine[value];
|
||||
}
|
||||
console.log(
|
||||
this.logger.warn(
|
||||
`Unknown WhatsApp default engine WHATSAPP_DEFAULT_ENGINE=${value}. Using WEBJS`,
|
||||
);
|
||||
return WAHAEngine.WEBJS;
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
|
||||
@Injectable()
|
||||
export class SwaggerConfigServiceCore {
|
||||
constructor(protected configService: ConfigService) {}
|
||||
constructor(
|
||||
protected configService: ConfigService,
|
||||
@InjectPinoLogger('SwaggerConfigService')
|
||||
protected logger: PinoLogger,
|
||||
) {}
|
||||
|
||||
get advancedConfigEnabled(): boolean {
|
||||
const value = this.configService.get(
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -3,7 +3,9 @@ import { Chat } from '@adiwajshing/baileys';
|
||||
export interface IChatRepository {
|
||||
getAll(): Promise<Chat[]>;
|
||||
|
||||
getAllWithMessages(): 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;
|
||||
@@ -18,9 +19,17 @@ export interface INowebStore {
|
||||
|
||||
getMessagesByJid(chatId: string, limit: number): Promise<any>;
|
||||
|
||||
getChats(): Promise<Chat[]>;
|
||||
getChats(limit?: number, offset?: number): Promise<Chat[]>;
|
||||
|
||||
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,5 +1,6 @@
|
||||
import { Chat, Contact, makeInMemoryStore, proto } from '@adiwajshing/baileys';
|
||||
import { BadRequestException, ConsoleLogger } from '@nestjs/common';
|
||||
import { Label } from '@adiwajshing/baileys/lib/Types/Label';
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { INowebStore } from './INowebStore';
|
||||
|
||||
@@ -40,7 +41,7 @@ export class NowebInMemoryStore implements INowebStore {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
getChats(): Promise<Chat[]> {
|
||||
getChats(limit?: number, offset?: number): Promise<Chat[]> {
|
||||
throw new BadRequestException(this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -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,8 +9,15 @@ 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';
|
||||
|
||||
import { toJID } from '../session.noweb.core';
|
||||
import { IChatRepository } from './IChatRepository';
|
||||
@@ -27,17 +34,21 @@ 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;
|
||||
|
||||
constructor(
|
||||
private log: ConsoleLogger,
|
||||
private logger: Logger,
|
||||
public storage: INowebStorage,
|
||||
) {
|
||||
this.socket = null;
|
||||
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 });
|
||||
}
|
||||
@@ -82,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;
|
||||
@@ -89,7 +104,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
|
||||
async close(): Promise<void> {
|
||||
await this.storage?.close().catch((error) => {
|
||||
this.log.warn(`Failed to close storage: ${error}`);
|
||||
this.logger.warn(`Failed to close storage: ${error}`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +112,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
private async onMessagingHistorySet(history) {
|
||||
const { contacts, chats, messages, isLatest } = history;
|
||||
if (isLatest) {
|
||||
this.log.debug(
|
||||
this.logger.debug(
|
||||
'history sync - clearing all entities, got latest history',
|
||||
);
|
||||
await Promise.all([
|
||||
@@ -110,7 +125,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
await Promise.all([
|
||||
this.withLock('contacts', async () => {
|
||||
await this.onContactsUpsert(contacts);
|
||||
this.log.log(`history sync - '${contacts.length}' synced contacts`);
|
||||
this.logger.info(`history sync - '${contacts.length}' synced contacts`);
|
||||
}),
|
||||
this.withLock('chats', () => this.onChatUpsert(chats)),
|
||||
this.withLock('messages', () => this.syncMessagesHistory(messages)),
|
||||
@@ -120,7 +135,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
private async syncMessagesHistory(messages) {
|
||||
const realMessages = messages.filter(isRealMessage);
|
||||
await this.messagesRepo.upsert(realMessages);
|
||||
this.log.log(
|
||||
this.logger.info(
|
||||
`history sync - '${messages.length}' got messages, '${realMessages.length}' real messages`,
|
||||
);
|
||||
}
|
||||
@@ -128,12 +143,12 @@ export class NowebPersistentStore implements INowebStore {
|
||||
private async onMessagesUpsert(update) {
|
||||
const { messages, type } = update;
|
||||
if (type !== 'notify' && type !== 'append') {
|
||||
this.log.debug(`unexpected type for messages.upsert: '${type}'`);
|
||||
this.logger.debug(`unexpected type for messages.upsert: '${type}'`);
|
||||
return;
|
||||
}
|
||||
const realMessages = messages.filter(isRealMessage);
|
||||
await this.messagesRepo.upsert(realMessages);
|
||||
this.log.debug(
|
||||
this.logger.debug(
|
||||
`messages.upsert - ${messages.length} got messages, ${realMessages.length} real messages`,
|
||||
);
|
||||
}
|
||||
@@ -178,7 +193,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
chat.conversationTimestamp = toNumber(chat.conversationTimestamp);
|
||||
await this.chatRepo.save(chat);
|
||||
}
|
||||
this.log.log(`history sync - '${chats.length}' synced chats`);
|
||||
this.logger.info(`history sync - '${chats.length}' synced chats`);
|
||||
}
|
||||
|
||||
private async onChatUpdate(updates: ChatUpdate[]) {
|
||||
@@ -219,7 +234,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
const contact = await this.contactRepo.getById(update.id);
|
||||
|
||||
if (!contact) {
|
||||
this.log.warn(
|
||||
this.logger.warn(
|
||||
`got update for non-existent contact. update: '${JSON.stringify(
|
||||
update,
|
||||
)}'`,
|
||||
@@ -246,7 +261,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
for (const { key, reaction } of reactions) {
|
||||
const msg = await this.messagesRepo.getByJidById(key.remoteJid, key.id);
|
||||
if (!msg) {
|
||||
this.log.warn(
|
||||
this.logger.warn(
|
||||
`got reaction update for non-existent message. key: '${JSON.stringify(
|
||||
key,
|
||||
)}'`,
|
||||
@@ -262,7 +277,7 @@ export class NowebPersistentStore implements INowebStore {
|
||||
for (const { key, receipt } of updates) {
|
||||
const msg = await this.messagesRepo.getByJidById(key.remoteJid, key.id);
|
||||
if (!msg) {
|
||||
this.log.warn(
|
||||
this.logger.warn(
|
||||
`got receipt update for non-existent message. key: '${JSON.stringify(
|
||||
key,
|
||||
)}'`,
|
||||
@@ -274,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);
|
||||
@@ -291,8 +326,8 @@ export class NowebPersistentStore implements INowebStore {
|
||||
return this.messagesRepo.getAllByJid(toJID(chatId), toNumber(limit));
|
||||
}
|
||||
|
||||
getChats() {
|
||||
return this.chatRepo.getAllWithMessages();
|
||||
getChats(limit?: number, offset?: number): Promise<Chat[]> {
|
||||
return this.chatRepo.getAllWithMessages(limit, offset);
|
||||
}
|
||||
|
||||
getContactById(jid) {
|
||||
@@ -302,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']),
|
||||
],
|
||||
),
|
||||
];
|
||||
@@ -7,11 +7,17 @@ export class Sqlite3ChatRepository
|
||||
extends Sqlite3KVRepository<Chat>
|
||||
implements IChatRepository
|
||||
{
|
||||
getAllWithMessages(): Promise<Chat[]> {
|
||||
async getAllWithMessages(limit?: number, offset?: number): Promise<Chat[]> {
|
||||
// Get chats with conversationTimestamp is not Null
|
||||
const query = this.select()
|
||||
let query = this.select()
|
||||
.whereNotNull('conversationTimestamp')
|
||||
.orderBy('conversationTimestamp', 'desc');
|
||||
return this.all(query);
|
||||
if (limit != null) {
|
||||
query = query.limit(limit);
|
||||
}
|
||||
if (offset != null) {
|
||||
query = query.offset(offset);
|
||||
}
|
||||
return await this.all(query);
|
||||
}
|
||||
}
|
||||
@@ -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,306 +0,0 @@
|
||||
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
|
||||
import * as Buffer from 'buffer';
|
||||
import { create, CreateConfig, Message, Whatsapp } from 'venom-bot';
|
||||
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
GetMessageQuery,
|
||||
MessageFileRequest,
|
||||
MessageImageRequest,
|
||||
MessageLinkPreviewRequest,
|
||||
MessageLocationRequest,
|
||||
MessageReactionRequest,
|
||||
MessageReplyRequest,
|
||||
MessageTextRequest,
|
||||
WANumberExistResult,
|
||||
} from '../../../structures/chatting.dto';
|
||||
import {
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHASessionStatus,
|
||||
} from '../../../structures/enums.dto';
|
||||
import { WAMessage } from '../../../structures/responses.dto';
|
||||
import { IEngineMediaProcessor } from '../../abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
|
||||
import { NotImplementedByEngineError } from '../../exceptions';
|
||||
import { QR } from '../../QR';
|
||||
|
||||
export class WhatsappSessionVenomCore extends WhatsappSession {
|
||||
engine = WAHAEngine.VENOM;
|
||||
|
||||
whatsapp: Whatsapp;
|
||||
private qr: QR;
|
||||
|
||||
public constructor(config) {
|
||||
super(config);
|
||||
this.qr = new QR();
|
||||
}
|
||||
|
||||
protected buildClient() {
|
||||
const venomOptions: CreateConfig = {
|
||||
headless: true,
|
||||
devtools: false,
|
||||
debug: false,
|
||||
logQR: true,
|
||||
browserArgs: this.getBrowserArgsForPuppeteer(),
|
||||
autoClose: 60000,
|
||||
puppeteerOptions: {},
|
||||
};
|
||||
this.addProxyConfig(venomOptions);
|
||||
return create(this.name, this.getCatchQR(), undefined, venomOptions);
|
||||
}
|
||||
|
||||
protected addProxyConfig(venomOptions: CreateConfig) {
|
||||
if (this.proxyConfig?.server !== undefined) {
|
||||
venomOptions.addProxy = [this.proxyConfig?.server];
|
||||
}
|
||||
if (
|
||||
this.proxyConfig?.username !== undefined &&
|
||||
this.proxyConfig?.password !== undefined
|
||||
) {
|
||||
venomOptions.userProxy = this.proxyConfig?.username;
|
||||
venomOptions.userPass = this.proxyConfig?.password;
|
||||
}
|
||||
}
|
||||
|
||||
protected getCatchQR() {
|
||||
return (base64Qrimg, asciiQR, attempts, urlCode) => {
|
||||
this.qr.save(base64Qrimg, urlCode);
|
||||
this.printQR(this.qr);
|
||||
this.status = WAHASessionStatus.SCAN_QR_CODE;
|
||||
this.log.debug('Number of attempts to read the qrcode: ', attempts);
|
||||
};
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.status = WAHASessionStatus.STARTING;
|
||||
try {
|
||||
this.whatsapp = await this.buildClient();
|
||||
} catch (error) {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error(error);
|
||||
this.qr.save('');
|
||||
return;
|
||||
}
|
||||
|
||||
this.status = WAHASessionStatus.WORKING;
|
||||
this.events.emit(WAHAInternalEvent.ENGINE_START);
|
||||
return this;
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.whatsapp.close();
|
||||
this.status = WAHASessionStatus.STOPPED;
|
||||
}
|
||||
|
||||
subscribeEngineEvent(event: WAHAEvents | string, handler: (message) => void) {
|
||||
switch (event) {
|
||||
case WAHAEvents.MESSAGE:
|
||||
this.whatsapp.onMessage((message: Message) =>
|
||||
this.processIncomingMessage(message).then(handler),
|
||||
);
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_ANY:
|
||||
this.whatsapp.onAnyMessage((message: Message) =>
|
||||
this.processIncomingMessage(message).then(handler),
|
||||
);
|
||||
return true;
|
||||
case WAHAEvents.STATE_CHANGE:
|
||||
this.whatsapp.onStateChange(handler);
|
||||
return true;
|
||||
case WAHAEvents.MESSAGE_ACK:
|
||||
this.whatsapp.onAck(handler);
|
||||
return true;
|
||||
case WAHAEvents.GROUP_JOIN:
|
||||
this.whatsapp.onAddedToGroup(handler);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* START - Methods for API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auth methods
|
||||
*/
|
||||
public getQR(): QR {
|
||||
return this.qr;
|
||||
}
|
||||
|
||||
getScreenshot(): Promise<Buffer> {
|
||||
if (this.status === WAHASessionStatus.STARTING) {
|
||||
throw new UnprocessableEntityException(
|
||||
`The session is starting, please try again after few seconds`,
|
||||
);
|
||||
} else if (this.status === WAHASessionStatus.SCAN_QR_CODE) {
|
||||
return Promise.resolve(this.qr.get());
|
||||
} else if (this.status === WAHASessionStatus.WORKING) {
|
||||
return this.whatsapp.page.screenshot();
|
||||
} else {
|
||||
throw new UnprocessableEntityException(`Unknown status - ${this.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
async checkNumberStatus(
|
||||
request: CheckNumberStatusQuery,
|
||||
): Promise<WANumberExistResult> {
|
||||
try {
|
||||
return await this.whatsapp.checkNumberStatus(
|
||||
this.ensureSuffix(request.phone),
|
||||
);
|
||||
} catch (error) {
|
||||
// Catch number doesn't exist error and return it as is
|
||||
if (error.status === 404 && !error.numberExists) {
|
||||
return error;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
sendText(request: MessageTextRequest) {
|
||||
return this.whatsapp.sendText(
|
||||
this.ensureSuffix(request.chatId),
|
||||
request.text,
|
||||
);
|
||||
}
|
||||
|
||||
reply(request: MessageReplyRequest) {
|
||||
return this.whatsapp.reply(request.chatId, request.text, request.reply_to);
|
||||
}
|
||||
|
||||
sendFile(request: MessageFileRequest) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
sendImage(request: MessageImageRequest) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
async sendVoice(request) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
sendLinkPreview(request: MessageLinkPreviewRequest) {
|
||||
return this.whatsapp.sendLinkPreview(
|
||||
request.chatId,
|
||||
request.url,
|
||||
request.title,
|
||||
);
|
||||
}
|
||||
|
||||
sendLocation(request: MessageLocationRequest) {
|
||||
return this.whatsapp.sendLocation(
|
||||
request.chatId,
|
||||
String(request.latitude),
|
||||
String(request.longitude),
|
||||
request.title,
|
||||
);
|
||||
}
|
||||
|
||||
sendSeen(chat: ChatRequest) {
|
||||
return this.whatsapp.markMarkSeenMessage(chat.chatId);
|
||||
}
|
||||
|
||||
startTyping(chat: ChatRequest) {
|
||||
return this.whatsapp.startTyping(chat.chatId, false);
|
||||
}
|
||||
|
||||
stopTyping(chat: ChatRequest) {
|
||||
return;
|
||||
// The method is not available yet in new venom-bot
|
||||
// return this.whatsapp.stopTyping(chat.chatId);
|
||||
}
|
||||
|
||||
async getChatMessages(chatId: string, limit: number) {
|
||||
const messages = await this.whatsapp.getAllMessagesInChat(
|
||||
chatId,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
// Go over messages, download media, and convert to right format.
|
||||
const result = [];
|
||||
for (const [count, message] of messages.entries()) {
|
||||
if (count > limit) {
|
||||
// Have enough in the list, stop processing
|
||||
break;
|
||||
}
|
||||
result.push(await this.processIncomingMessage(message));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async getMessages(query: GetMessageQuery) {
|
||||
return this.getChatMessages(query.chatId, query.limit);
|
||||
}
|
||||
|
||||
setReaction(request: MessageReactionRequest) {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* END - Methods for API
|
||||
*/
|
||||
|
||||
protected downloadMedia(message: Message) {
|
||||
const processor = new EngineMediaProcessor(this);
|
||||
return this.mediaManager.processMedia(processor, message);
|
||||
}
|
||||
|
||||
private processIncomingMessage(message: Message) {
|
||||
return this.downloadMedia(message).then(this.toWAMessage);
|
||||
}
|
||||
|
||||
protected toWAMessage(message: Message): Promise<WAMessage> {
|
||||
// @ts-ignore
|
||||
return Promise.resolve({
|
||||
id: message.id,
|
||||
timestamp: message.timestamp,
|
||||
from: message.from,
|
||||
fromMe: message.fromMe,
|
||||
to: message.to,
|
||||
body: message.body,
|
||||
// Media
|
||||
// @ts-ignore
|
||||
hasMedia: Boolean(message.media),
|
||||
// @ts-ignore
|
||||
media: message.media,
|
||||
// @ts-ignore
|
||||
mediaUrl: message.media?.url,
|
||||
// @ts-ignore
|
||||
ack: message.ack,
|
||||
location: undefined,
|
||||
vCards: undefined,
|
||||
_data: message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class EngineMediaProcessor implements IEngineMediaProcessor<Message> {
|
||||
constructor(public session: WhatsappSessionVenomCore) {}
|
||||
|
||||
hasMedia(message: any): boolean {
|
||||
if (!message.isMMS || !message.isMedia) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
getMessageId(message: any): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
getMimetype(message: any): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
getMediaBuffer(message: any): Promise<Buffer | null> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
getFilename(message: Message): string | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,15 @@
|
||||
exports.LoadUtils = () => {
|
||||
window.WAHA = {};
|
||||
|
||||
window.WAHA.getChats = async (limit, offset) => {
|
||||
let chats = window.Store.Chat.getModelsArray();
|
||||
if (limit || offset) {
|
||||
offset = offset || 0;
|
||||
limit = limit || Infinity;
|
||||
chats = chats.slice(offset, offset + limit);
|
||||
}
|
||||
|
||||
const chatPromises = chats.map((chat) => window.WWebJS.getChatModel(chat));
|
||||
return await Promise.all(chatPromises);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Client } from 'whatsapp-web.js';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { LoadUtils } = require('./WahaInjected');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const ChatFactory = require('whatsapp-web.js/src/factories/ChatFactory');
|
||||
|
||||
export class WebjsClient extends Client {
|
||||
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);
|
||||
}
|
||||
|
||||
async getChats(limit?: number, offset?: number) {
|
||||
if (limit == null && offset == null) {
|
||||
return await super.getChats();
|
||||
}
|
||||
return await this.getChats2(limit, offset);
|
||||
}
|
||||
|
||||
private async getChats2(limit?: number, offset?: number) {
|
||||
const chats = await this.pupPage.evaluate(
|
||||
async (limit, offset) => {
|
||||
// @ts-ignore
|
||||
return await window.WAHA.getChats(limit, offset);
|
||||
},
|
||||
limit,
|
||||
offset,
|
||||
);
|
||||
|
||||
return chats.map((chat) => ChatFactory.create(this, chat));
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,25 @@
|
||||
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
|
||||
import {
|
||||
Chat,
|
||||
Client,
|
||||
ClientOptions,
|
||||
Contact,
|
||||
Events,
|
||||
GroupChat,
|
||||
Location,
|
||||
Message,
|
||||
Reaction,
|
||||
} from 'whatsapp-web.js';
|
||||
import { Message as MessageInstance } from 'whatsapp-web.js/src/structures';
|
||||
|
||||
import { parseBool } from '../../../helpers';
|
||||
getChannelInviteLink,
|
||||
WAHAInternalEvent,
|
||||
WhatsappSession,
|
||||
} from '@waha/core/abc/session.abc';
|
||||
import { WebjsClient } from '@waha/core/engines/webjs/WebjsClient';
|
||||
import {
|
||||
AvailableInPlusVersion,
|
||||
NotImplementedByEngineError,
|
||||
} from '@waha/core/exceptions';
|
||||
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
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 { ChatArchiveEvent, GetChatsQuery } from '@waha/structures/chats.dto';
|
||||
import {
|
||||
ChatRequest,
|
||||
CheckNumberStatusQuery,
|
||||
@@ -28,8 +35,8 @@ import {
|
||||
MessageVoiceRequest,
|
||||
SendSeenRequest,
|
||||
WANumberExistResult,
|
||||
} from '../../../structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '../../../structures/contacts.dto';
|
||||
} from '@waha/structures/chatting.dto';
|
||||
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
|
||||
import {
|
||||
ACK_UNKNOWN,
|
||||
SECOND,
|
||||
@@ -38,32 +45,37 @@ import {
|
||||
WAHAPresenceStatus,
|
||||
WAHASessionStatus,
|
||||
WAMessageAck,
|
||||
} from '../../../structures/enums.dto';
|
||||
} from '@waha/structures/enums.dto';
|
||||
import {
|
||||
CreateGroupRequest,
|
||||
ParticipantsRequest,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '../../../structures/groups.dto';
|
||||
} from '@waha/structures/groups.dto';
|
||||
import { Label, LabelID } from '@waha/structures/labels.dto';
|
||||
import { ReplyToMessage } from '@waha/structures/message.dto';
|
||||
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
|
||||
import { MeInfo } from '@waha/structures/sessions.dto';
|
||||
import { WAMessageRevokedBody } from '@waha/structures/webhooks.dto';
|
||||
import { waitUntil } from '@waha/utils/promiseTimeout';
|
||||
import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
|
||||
import {
|
||||
WAMessage,
|
||||
WAMessageReaction,
|
||||
} from '../../../structures/responses.dto';
|
||||
import { MeInfo } from '../../../structures/sessions.dto';
|
||||
import { WAMessageRevokedBody } from '../../../structures/webhooks.dto';
|
||||
import { IEngineMediaProcessor } from '../../abc/media.abc';
|
||||
import { WAHAInternalEvent, WhatsappSession } from '../../abc/session.abc';
|
||||
import {
|
||||
AvailableInPlusVersion,
|
||||
NotImplementedByEngineError,
|
||||
} from '../../exceptions';
|
||||
import { QR } from '../../QR';
|
||||
Call,
|
||||
Channel as WEBJSChannel,
|
||||
Chat,
|
||||
ClientOptions,
|
||||
Contact,
|
||||
Events,
|
||||
GroupChat,
|
||||
Label as WEBJSLabel,
|
||||
Location,
|
||||
Message,
|
||||
Reaction,
|
||||
} from 'whatsapp-web.js';
|
||||
import { Message as MessageInstance } from 'whatsapp-web.js/src/structures';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const QRCode = require('qrcode');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const qrcode = require('qrcode-terminal');
|
||||
|
||||
export interface WebJSConfig {
|
||||
webVersion?: string;
|
||||
}
|
||||
@@ -74,16 +86,23 @@ 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: Client;
|
||||
whatsapp: WebjsClient;
|
||||
protected qr: QR;
|
||||
|
||||
public constructor(config) {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,8 +114,9 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
|
||||
protected getClientOptions(): ClientOptions {
|
||||
const path = this.getClassDirName();
|
||||
const webVersion = this.engineConfig?.webVersion || '2.2412.54';
|
||||
this.log.debug(`Using web version: '${webVersion}'`);
|
||||
const webVersion =
|
||||
this.engineConfig?.webVersion || '2.3000.1014522270-alpha';
|
||||
// this.log.debug(`Using web version: '${webVersion}'`);
|
||||
return {
|
||||
puppeteer: {
|
||||
headless: true,
|
||||
@@ -106,9 +126,9 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
},
|
||||
webVersion: webVersion,
|
||||
webVersionCache: {
|
||||
type: 'local',
|
||||
path: path,
|
||||
strict: true,
|
||||
type: 'none',
|
||||
// path: path,
|
||||
// strict: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -116,28 +136,27 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
protected async buildClient() {
|
||||
const clientOptions = this.getClientOptions();
|
||||
this.addProxyConfig(clientOptions);
|
||||
return new Client(clientOptions);
|
||||
return new WebjsClient(clientOptions);
|
||||
}
|
||||
|
||||
private restartClient() {
|
||||
if (!this.shouldRestart) {
|
||||
this.log.debug("Shouldn't restart the client, ignoring restart request");
|
||||
this.logger.debug(
|
||||
'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.log.warn(msg);
|
||||
return;
|
||||
}
|
||||
this.log.log(
|
||||
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
|
||||
);
|
||||
this.startTimeoutId = setTimeout(() => {
|
||||
this.startTimeoutId = undefined;
|
||||
this.start();
|
||||
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
|
||||
this.startDelayedJob.schedule(async () => {
|
||||
if (!this.shouldRestart) {
|
||||
this.logger.warn(
|
||||
'Should not restart the client, ignoring restart request',
|
||||
);
|
||||
return;
|
||||
}
|
||||
await this.end();
|
||||
await this.start();
|
||||
});
|
||||
}
|
||||
|
||||
protected addProxyConfig(clientOptions: ClientOptions) {
|
||||
@@ -158,7 +177,6 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
await this.end();
|
||||
this.shouldRestart = true;
|
||||
this.whatsapp = await this.buildClient();
|
||||
this.whatsapp
|
||||
@@ -167,21 +185,21 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
// Listen for browser disconnected event
|
||||
this.whatsapp.pupBrowser.on('disconnected', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The browser has been disconnected');
|
||||
this.logger.error('The browser has been disconnected');
|
||||
this.restartClient();
|
||||
});
|
||||
// Listen for page close event
|
||||
this.whatsapp.pupPage.on('close', () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error('The WhatsApp Web page has been closed');
|
||||
this.logger.error('The WhatsApp Web page has been closed');
|
||||
this.restartClient();
|
||||
});
|
||||
|
||||
// Listen for page error event
|
||||
if (this.isDebugEnabled()) {
|
||||
this.log.debug("Logging 'console' event for web page");
|
||||
this.logger.debug("Logging 'console' event for web page");
|
||||
this.whatsapp.pupPage.on('console', (msg) =>
|
||||
this.log.debug(`WEBJS page log: ${msg.text()}`),
|
||||
this.logger.debug(`WEBJS page log: ${msg.text()}`),
|
||||
);
|
||||
this.whatsapp.pupPage.evaluate(() =>
|
||||
console.log(`url is ${location.href}`),
|
||||
@@ -190,7 +208,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
})
|
||||
.catch((error) => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.log.error(error);
|
||||
this.logger.error(error);
|
||||
this.restartClient();
|
||||
return;
|
||||
});
|
||||
@@ -210,32 +228,44 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
async stop() {
|
||||
this.shouldRestart = false;
|
||||
this.status = WAHASessionStatus.STOPPED;
|
||||
this.events.removeAllListeners();
|
||||
await this.end();
|
||||
}
|
||||
|
||||
private async end() {
|
||||
try {
|
||||
this.whatsapp?.removeAllListeners();
|
||||
clearInterval(this.startTimeoutId);
|
||||
this.whatsapp?.pupBrowser?.removeAllListeners();
|
||||
this.whatsapp?.pupPage?.removeAllListeners();
|
||||
this.startDelayedJob.cancel();
|
||||
// It's possible that browser yet starting
|
||||
await waitUntil(
|
||||
async () => {
|
||||
const result = !!this.whatsapp.pupBrowser;
|
||||
this.logger.debug(`Browser is ready to be closed: ${result}`);
|
||||
return result;
|
||||
},
|
||||
1_000,
|
||||
10_000,
|
||||
);
|
||||
this.whatsapp?.destroy().catch((error) => {
|
||||
this.log.debug('Failed to destroy the client', error);
|
||||
this.logger.warn(error, 'Failed to destroy the client');
|
||||
});
|
||||
} catch (error) {
|
||||
this.log.error(error);
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getSessionMeInfo(): Promise<MeInfo | null> {
|
||||
getSessionMeInfo(): MeInfo | null {
|
||||
const clientInfo = this.whatsapp?.info;
|
||||
if (!clientInfo) {
|
||||
return null;
|
||||
}
|
||||
const wid = clientInfo.wid;
|
||||
const meInfo: MeInfo = {
|
||||
id: wid._serialized,
|
||||
pushName: clientInfo.pushname,
|
||||
return {
|
||||
id: wid?._serialized,
|
||||
pushName: clientInfo?.pushname,
|
||||
};
|
||||
return meInfo;
|
||||
}
|
||||
|
||||
protected listenEngineEventsInDebugMode() {
|
||||
@@ -245,14 +275,14 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
const event = Events[key];
|
||||
this.whatsapp.on(event, (...data: any[]) => {
|
||||
const log = { event: event, data: data };
|
||||
this.log.debug(`WEBJS event: ${JSON.stringify(log)}`);
|
||||
this.logger.debug({ event: log }, `WEBJS event`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected listenConnectionEvents() {
|
||||
this.whatsapp.on(Events.QR_RECEIVED, async (qr) => {
|
||||
this.log.debug('QR received');
|
||||
this.logger.debug('QR received');
|
||||
// Convert to image and save
|
||||
const url = await QRCode.toDataURL(qr);
|
||||
this.qr.save(url, qr);
|
||||
@@ -263,13 +293,25 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
this.whatsapp.on(Events.READY, () => {
|
||||
this.status = WAHASessionStatus.WORKING;
|
||||
this.qr.save('');
|
||||
this.log.log(`Session '${this.name}' has been authenticated!`);
|
||||
this.logger.info(`Session '${this.name}' is ready!`);
|
||||
});
|
||||
|
||||
this.whatsapp.on(Events.AUTHENTICATED, () => {
|
||||
this.status = WAHASessionStatus.WORKING;
|
||||
this.qr.save('');
|
||||
this.logger.info(`Session '${this.name}' has been authenticated!`);
|
||||
});
|
||||
|
||||
this.whatsapp.on(Events.AUTHENTICATION_FAILURE, () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.qr.save('');
|
||||
this.logger.info(`Session '${this.name}' has been disconnected!`);
|
||||
});
|
||||
|
||||
this.whatsapp.on(Events.DISCONNECTED, () => {
|
||||
this.status = WAHASessionStatus.FAILED;
|
||||
this.qr.save('');
|
||||
this.log.log(`Session '${this.name}' has been disconnected!`);
|
||||
this.logger.info(`Session '${this.name}' has been disconnected!`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -313,10 +355,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
sendText(request: MessageTextRequest) {
|
||||
const options = {
|
||||
// It's fine to sent just ids instead of Contact object
|
||||
mentions: request.mentions as unknown as string[],
|
||||
};
|
||||
const options = this.getMessageOptions(request);
|
||||
return this.whatsapp.sendMessage(
|
||||
this.ensureSuffix(request.chatId),
|
||||
request.text,
|
||||
@@ -343,11 +382,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
reply(request: MessageReplyRequest) {
|
||||
const options = {
|
||||
quotedMessageId: request.reply_to,
|
||||
// It's fine to sent just ids instead of Contact object
|
||||
mentions: request.mentions as unknown as string[],
|
||||
};
|
||||
const options = this.getMessageOptions(request);
|
||||
return this.whatsapp.sendMessage(request.chatId, request.text, options);
|
||||
}
|
||||
|
||||
@@ -367,7 +402,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
const location = new Location(request.latitude, request.longitude, {
|
||||
name: request.title,
|
||||
});
|
||||
return this.whatsapp.sendMessage(request.chatId, location);
|
||||
const options = this.getMessageOptions(request);
|
||||
return this.whatsapp.sendMessage(request.chatId, location, options);
|
||||
}
|
||||
|
||||
async sendSeen(request: SendSeenRequest) {
|
||||
@@ -417,8 +453,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
/**
|
||||
* Chats methods
|
||||
*/
|
||||
getChats() {
|
||||
return this.whatsapp.getChats();
|
||||
getChats(query: GetChatsQuery) {
|
||||
return this.whatsapp.getChats(query.limit, query.offset);
|
||||
}
|
||||
|
||||
async getChatMessages(chatId: string, limit: number, downloadMedia: boolean) {
|
||||
@@ -429,12 +465,12 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
const messages = await chat.fetchMessages({
|
||||
limit: limit,
|
||||
});
|
||||
// Go over messages, download media, and convert to right format.
|
||||
const result = [];
|
||||
for (const message of messages) {
|
||||
const msg = await this.processIncomingMessage(message, downloadMedia);
|
||||
result.push(msg);
|
||||
const promises = [];
|
||||
for (const msg of messages) {
|
||||
promises.push(this.processIncomingMessage(msg, downloadMedia));
|
||||
}
|
||||
let result = await Promise.all(promises);
|
||||
result = result.filter(Boolean);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -448,6 +484,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
|
||||
*/
|
||||
@@ -608,6 +690,109 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return groupChat.demoteParticipants(participantIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channels methods
|
||||
*/
|
||||
protected ChatToChannel(chat: WEBJSChannel): Channel {
|
||||
// @ts-ignore
|
||||
const metadata = chat.channelMetadata;
|
||||
let role = metadata.membershipType.toUpperCase();
|
||||
if (role === 'VIEWER') {
|
||||
role = ChannelRole.GUEST;
|
||||
}
|
||||
return {
|
||||
id: chat.id._serialized,
|
||||
name: chat.name,
|
||||
description: chat.description,
|
||||
invite: getChannelInviteLink(metadata.inviteCode),
|
||||
preview: null,
|
||||
picture: null,
|
||||
verified: metadata.verified,
|
||||
role: role,
|
||||
};
|
||||
}
|
||||
|
||||
protected ChannelMetadataToChannel(metadata: any): Channel {
|
||||
let role = metadata.membershipType.toUpperCase();
|
||||
if (role === 'VIEWER') {
|
||||
role = ChannelRole.GUEST;
|
||||
}
|
||||
return {
|
||||
id: metadata.id,
|
||||
name: metadata.titleMetadata.title,
|
||||
description: metadata.descriptionMetadata.description,
|
||||
invite: metadata.inviteLink,
|
||||
preview: metadata.pictureUrl,
|
||||
picture: metadata.pictureUrl,
|
||||
verified: metadata.isVerified,
|
||||
role: role,
|
||||
};
|
||||
}
|
||||
|
||||
public async channelsList(query: ListChannelsQuery): Promise<Channel[]> {
|
||||
const data = await this.whatsapp.getChannels();
|
||||
let channels = data.map(this.ChatToChannel);
|
||||
if (query.role) {
|
||||
// @ts-ignore
|
||||
channels = channels.filter((channel) => channel.role === query.role);
|
||||
}
|
||||
|
||||
const promises = channels.map(async (channel) =>
|
||||
this.whatsapp.getProfilePicUrl(channel.id),
|
||||
);
|
||||
const pictures = await Promise.all(promises);
|
||||
channels = channels.map((channel, index) => {
|
||||
channel.picture = pictures[index] || null;
|
||||
channel.preview = channel.picture;
|
||||
return channel;
|
||||
});
|
||||
return channels;
|
||||
}
|
||||
|
||||
public channelsCreateChannel(
|
||||
request: CreateChannelRequest,
|
||||
): Promise<Channel> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public async channelsGetChannel(id: string): Promise<Channel> {
|
||||
return await this.channelsGetChannelByInviteCode(id);
|
||||
}
|
||||
|
||||
public async channelsGetChannelByInviteCode(
|
||||
inviteCode: string,
|
||||
): Promise<Channel> {
|
||||
const metadata = await this.whatsapp.getChannelByInviteCode(inviteCode);
|
||||
const channel = this.ChannelMetadataToChannel(metadata);
|
||||
channel.preview =
|
||||
(await this.whatsapp.getProfilePicUrl(channel.id)) || null;
|
||||
channel.picture = channel.preview;
|
||||
return channel;
|
||||
}
|
||||
|
||||
public channelsDeleteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsFollowChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsUnfollowChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsMuteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public channelsUnmuteChannel(id: string): Promise<void> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Presences methods
|
||||
*/
|
||||
public async setPresence(presence: WAHAPresenceStatus, chatId?: string) {
|
||||
let chat: Chat;
|
||||
switch (presence) {
|
||||
@@ -688,6 +873,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;
|
||||
}
|
||||
@@ -698,8 +905,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
try {
|
||||
message = await this.downloadMedia(message);
|
||||
} catch (e) {
|
||||
this.log.error('Failed when tried to download media for a message');
|
||||
this.log.error(e, e.stack);
|
||||
this.logger.error('Failed when tried to download media for a message');
|
||||
this.logger.error(e, e.stack);
|
||||
}
|
||||
}
|
||||
return await this.toWAMessage(message);
|
||||
@@ -721,6 +928,7 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
}
|
||||
|
||||
protected toWAMessage(message: Message): Promise<WAMessage> {
|
||||
const replyTo = this.extractReplyTo(message);
|
||||
// @ts-ignore
|
||||
return Promise.resolve({
|
||||
id: message.id._serialized,
|
||||
@@ -741,11 +949,26 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
ackName: WAMessageAck[message.ack] || ACK_UNKNOWN,
|
||||
location: message.location,
|
||||
vCards: message.vCards,
|
||||
replyTo: replyTo,
|
||||
_data: message.rawData,
|
||||
});
|
||||
}
|
||||
|
||||
protected extractReplyTo(message: Message): ReplyToMessage | null {
|
||||
// @ts-ignore
|
||||
const quotedMsg = message.rawData.quotedMsg;
|
||||
if (!quotedMsg) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
id: quotedMsg.id?.id,
|
||||
participant: quotedMsg.author || quotedMsg.from,
|
||||
body: quotedMsg.caption || quotedMsg.body,
|
||||
};
|
||||
}
|
||||
|
||||
public async getEngineInfo() {
|
||||
// Add 1 seconds timeout
|
||||
return {
|
||||
WWebVersion: await this.whatsapp?.getWWebVersion(),
|
||||
state: await this.whatsapp?.getState(),
|
||||
@@ -760,11 +983,23 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
|
||||
protected downloadMedia(message: Message) {
|
||||
const processor = new EngineMediaProcessor();
|
||||
return this.mediaManager.processMedia(processor, message);
|
||||
return this.mediaManager.processMedia(processor, message, this.name);
|
||||
}
|
||||
|
||||
protected getMessageOptions(request: any): any {
|
||||
let mentions = request.mentions;
|
||||
mentions = mentions ? mentions.map(this.ensureSuffix) : undefined;
|
||||
|
||||
const quotedMessageId = request.reply_to;
|
||||
|
||||
return {
|
||||
mentions: mentions,
|
||||
quotedMessageId: quotedMessageId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class EngineMediaProcessor implements IEngineMediaProcessor<Message> {
|
||||
export class EngineMediaProcessor implements IMediaEngineProcessor<Message> {
|
||||
hasMedia(message: Message): boolean {
|
||||
if (!message.hasMedia) {
|
||||
return false;
|
||||
|
||||
+135
-88
@@ -1,34 +1,37 @@
|
||||
import {
|
||||
ConsoleLogger,
|
||||
Injectable,
|
||||
LogLevel,
|
||||
NotFoundException,
|
||||
UnprocessableEntityException,
|
||||
} from '@nestjs/common';
|
||||
import { MediaNoopStorage } from '@waha/core/media/MediaNoopStorage';
|
||||
import { getPinoLogLevel, LoggerBuilder } from '@waha/utils/logging';
|
||||
import { promiseTimeout, sleep } from '@waha/utils/promiseTimeout';
|
||||
import { EventEmitter } from 'events';
|
||||
import { PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { WhatsappConfigService } from '../config.service';
|
||||
import { getLogLevels } from '../helpers';
|
||||
import { WAHAEngine, WAHASessionStatus } from '../structures/enums.dto';
|
||||
import {
|
||||
WAHAEngine,
|
||||
WAHAEvents,
|
||||
WAHASessionStatus,
|
||||
} from '../structures/enums.dto';
|
||||
import {
|
||||
ProxyConfig,
|
||||
SessionConfig,
|
||||
SessionDTO,
|
||||
SessionInfo,
|
||||
SessionLogoutRequest,
|
||||
SessionStartRequest,
|
||||
SessionStopRequest,
|
||||
} from '../structures/sessions.dto';
|
||||
import { WebhookConfig } from '../structures/webhooks.config.dto';
|
||||
import { SessionManager } from './abc/manager.abc';
|
||||
import { SessionParams, WhatsappSession } from './abc/session.abc';
|
||||
import { EngineConfigService } from './config/EngineConfigService';
|
||||
import { WhatsappSessionNoWebCore } from './engines/noweb/session.noweb.core';
|
||||
import { WhatsappSessionVenomCore } from './engines/venom/session.venom.core';
|
||||
import { WhatsappSessionWebJSCore } from './engines/webjs/session.webjs.core';
|
||||
import { DOCS_URL } from './exceptions';
|
||||
import { getProxyConfig } from './helpers.proxy';
|
||||
import { CoreMediaManager, MediaStorageCore } from './media.core';
|
||||
import { MediaManagerCore } from './media/MediaManagerCore';
|
||||
import { LocalSessionAuthRepository } from './storage/LocalSessionAuthRepository';
|
||||
import { LocalSessionConfigRepository } from './storage/LocalSessionConfigRepository';
|
||||
import { LocalStoreCore } from './storage/LocalStoreCore';
|
||||
import { WebhookConductorCore } from './webhooks.core';
|
||||
|
||||
@@ -39,14 +42,20 @@ export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function buildLogger(name: string, levels: LogLevel[]) {
|
||||
return new ConsoleLogger(name, { logLevels: levels });
|
||||
enum DefaultSessionStatus {
|
||||
REMOVED = undefined,
|
||||
STOPPED = null,
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SessionManagerCore extends SessionManager {
|
||||
private session?: WhatsappSession;
|
||||
SESSION_STOP_TIMEOUT = 3000;
|
||||
|
||||
// session - exists and running (or failed or smth)
|
||||
// null - stopped
|
||||
// undefined - removed
|
||||
private session: WhatsappSession | DefaultSessionStatus;
|
||||
private sessionConfig?: SessionConfig;
|
||||
DEFAULT = 'default';
|
||||
|
||||
// @ts-ignore
|
||||
@@ -55,33 +64,31 @@ export class SessionManagerCore extends SessionManager {
|
||||
|
||||
constructor(
|
||||
private config: WhatsappConfigService,
|
||||
private log: ConsoleLogger,
|
||||
private engineConfigService: EngineConfigService,
|
||||
private log: PinoLogger,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.log.setContext('SessionManager');
|
||||
this.session = undefined;
|
||||
this.events = new EventEmitter();
|
||||
this.session = DefaultSessionStatus.STOPPED;
|
||||
this.sessionConfig = null;
|
||||
this.log.setContext(SessionManagerCore.name);
|
||||
const engineName = this.engineConfigService.getDefaultEngineName();
|
||||
this.EngineClass = this.getEngine(engineName);
|
||||
this.store = new LocalStoreCore(engineName.toLowerCase());
|
||||
this.sessionAuthRepository = new LocalSessionAuthRepository(this.store);
|
||||
this.sessionConfigRepository = new LocalSessionConfigRepository(this.store);
|
||||
this.startPredefinedSessions();
|
||||
}
|
||||
|
||||
protected startPredefinedSessions() {
|
||||
const startSessions = this.config.startSessions;
|
||||
startSessions.forEach((sessionName) => {
|
||||
this.start({ name: sessionName });
|
||||
this.start(sessionName);
|
||||
});
|
||||
}
|
||||
|
||||
protected getEngine(engine: WAHAEngine): typeof WhatsappSession {
|
||||
if (engine === WAHAEngine.WEBJS) {
|
||||
return WhatsappSessionWebJSCore;
|
||||
} else if (engine === WAHAEngine.VENOM) {
|
||||
return WhatsappSessionVenomCore;
|
||||
} else if (engine === WAHAEngine.NOWEB) {
|
||||
return WhatsappSessionNoWebCore;
|
||||
} else {
|
||||
@@ -95,43 +102,57 @@ export class SessionManagerCore extends SessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
async onApplicationShutdown(signal?: string) {
|
||||
async beforeApplicationShutdown(signal?: string) {
|
||||
if (!this.session) {
|
||||
return;
|
||||
}
|
||||
await this.stop({ name: this.DEFAULT, logout: false });
|
||||
await this.stop(this.DEFAULT, true);
|
||||
}
|
||||
|
||||
//
|
||||
// API Methods
|
||||
//
|
||||
async start(request: SessionStartRequest): Promise<SessionDTO> {
|
||||
this.onlyDefault(request.name);
|
||||
async exists(name: string): Promise<boolean> {
|
||||
this.onlyDefault(name);
|
||||
return this.session !== DefaultSessionStatus.REMOVED;
|
||||
}
|
||||
|
||||
isRunning(name: string): boolean {
|
||||
this.onlyDefault(name);
|
||||
return !!this.session;
|
||||
}
|
||||
|
||||
async upsert(name: string, config?: SessionConfig): Promise<void> {
|
||||
this.onlyDefault(name);
|
||||
this.sessionConfig = config;
|
||||
}
|
||||
|
||||
async start(name: string): Promise<SessionDTO> {
|
||||
this.onlyDefault(name);
|
||||
if (this.session) {
|
||||
throw new UnprocessableEntityException(
|
||||
`Session '${this.DEFAULT}' is already started.`,
|
||||
);
|
||||
}
|
||||
|
||||
const name = request.name;
|
||||
this.log.log(`'${name}' - starting session...`);
|
||||
const levels = getLogLevels(request.config?.debug);
|
||||
const log = buildLogger(`WhatsappSession - ${name}`, levels);
|
||||
const mediaManager = new CoreMediaManager(
|
||||
new MediaStorageCore(),
|
||||
this.log.info(`'${name}' - starting session...`);
|
||||
const mediaManager = new MediaManagerCore(
|
||||
new MediaNoopStorage(),
|
||||
this.config.mimetypes,
|
||||
);
|
||||
const webhookLog = buildLogger(`Webhook - ${name}`, levels);
|
||||
const webhook = new this.WebhookConductorClass(webhookLog);
|
||||
const proxyConfig = this.getProxyConfig(request);
|
||||
const logger = this.log.logger.child({ session: name });
|
||||
logger.level = getPinoLogLevel(this.sessionConfig?.debug);
|
||||
const loggerBuilder: LoggerBuilder = logger;
|
||||
|
||||
const webhook = new this.WebhookConductorClass(loggerBuilder);
|
||||
const proxyConfig = this.getProxyConfig();
|
||||
const sessionConfig: SessionParams = {
|
||||
name,
|
||||
mediaManager,
|
||||
log,
|
||||
loggerBuilder,
|
||||
printQR: this.engineConfigService.shouldPrintQR,
|
||||
sessionStore: this.store,
|
||||
proxyConfig: proxyConfig,
|
||||
sessionConfig: request.config,
|
||||
sessionConfig: this.sessionConfig,
|
||||
};
|
||||
await this.sessionAuthRepository.init(name);
|
||||
// @ts-ignore
|
||||
@@ -139,11 +160,18 @@ export class SessionManagerCore extends SessionManager {
|
||||
this.session = session;
|
||||
|
||||
// configure webhooks
|
||||
const webhooks = this.getWebhooks(request);
|
||||
const webhooks = this.getWebhooks();
|
||||
webhook.configure(session, webhooks);
|
||||
|
||||
// configure events
|
||||
session.events.on(
|
||||
WAHAEvents.SESSION_STATUS,
|
||||
this.handleSessionEvent(WAHAEvents.SESSION_STATUS, session),
|
||||
);
|
||||
|
||||
// start session
|
||||
await session.start();
|
||||
logger.info('Session has been started.');
|
||||
return {
|
||||
name: session.name,
|
||||
status: session.status,
|
||||
@@ -151,13 +179,46 @@ export class SessionManagerCore extends SessionManager {
|
||||
};
|
||||
}
|
||||
|
||||
async stop(name: string, silent: boolean): Promise<void> {
|
||||
this.onlyDefault(name);
|
||||
if (!this.isRunning(name)) {
|
||||
this.log.debug(`Session is not running.`, { session: name });
|
||||
return;
|
||||
}
|
||||
|
||||
this.log.info(`Stopping session...`, { session: name });
|
||||
try {
|
||||
const session = this.getSession(name);
|
||||
await session.stop();
|
||||
} catch (err) {
|
||||
this.log.warn(`Error while stopping session '${name}'`);
|
||||
if (!silent) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
this.log.info(`Session has been stopped.`, { session: name });
|
||||
this.session = DefaultSessionStatus.STOPPED;
|
||||
await sleep(this.SESSION_STOP_TIMEOUT);
|
||||
}
|
||||
|
||||
async logout(name: string): Promise<void> {
|
||||
this.onlyDefault(name);
|
||||
await this.sessionAuthRepository.clean(name);
|
||||
}
|
||||
|
||||
async delete(name: string): Promise<void> {
|
||||
this.onlyDefault(name);
|
||||
this.session = DefaultSessionStatus.REMOVED;
|
||||
this.sessionConfig = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine per session and global webhooks
|
||||
*/
|
||||
private getWebhooks(request: SessionStartRequest) {
|
||||
private getWebhooks() {
|
||||
let webhooks: WebhookConfig[] = [];
|
||||
if (request.config?.webhooks) {
|
||||
webhooks = webhooks.concat(request.config.webhooks);
|
||||
if (this.sessionConfig?.webhooks) {
|
||||
webhooks = webhooks.concat(this.sessionConfig.webhooks);
|
||||
}
|
||||
const globalWebhookConfig = this.config.getWebhookConfig();
|
||||
if (globalWebhookConfig) {
|
||||
@@ -169,44 +230,15 @@ export class SessionManagerCore extends SessionManager {
|
||||
/**
|
||||
* Get either session's or global proxy if defined
|
||||
*/
|
||||
protected getProxyConfig(
|
||||
request: SessionStartRequest,
|
||||
): ProxyConfig | undefined {
|
||||
if (request.config?.proxy) {
|
||||
return request.config.proxy;
|
||||
protected getProxyConfig(): ProxyConfig | undefined {
|
||||
if (this.sessionConfig?.proxy) {
|
||||
return this.sessionConfig.proxy;
|
||||
}
|
||||
if (!this.session) {
|
||||
return undefined;
|
||||
}
|
||||
const sessions = { [request.name]: this.session };
|
||||
return getProxyConfig(this.config, sessions, request.name);
|
||||
}
|
||||
|
||||
async stop(request: SessionStopRequest): Promise<void> {
|
||||
this.onlyDefault(request.name);
|
||||
|
||||
const name = request.name;
|
||||
this.log.log(`Stopping ${name} session...`);
|
||||
const session = this.getSession(name);
|
||||
await session.stop();
|
||||
this.log.log(`"${name}" has been stopped.`);
|
||||
this.session = undefined;
|
||||
}
|
||||
|
||||
async logout(request: SessionLogoutRequest) {
|
||||
const name = request.name;
|
||||
this.onlyDefault(request.name);
|
||||
this.stop({ name: name, logout: false })
|
||||
.then(() => {
|
||||
this.log.log(`Session '${name}' has been stopped.`);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.log.error(
|
||||
`Error while stopping session '${name}' while logging out`,
|
||||
err,
|
||||
);
|
||||
});
|
||||
await this.sessionAuthRepository.clean(request.name);
|
||||
const sessions = { [this.DEFAULT]: this.session as WhatsappSession };
|
||||
return getProxyConfig(this.config, sessions, this.DEFAULT);
|
||||
}
|
||||
|
||||
getSession(name: string): WhatsappSession {
|
||||
@@ -214,36 +246,51 @@ export class SessionManagerCore extends SessionManager {
|
||||
const session = this.session;
|
||||
if (!session) {
|
||||
throw new NotFoundException(
|
||||
`We didn't find a session with name '${name}'. Please start it first by using POST /sessions/start request`,
|
||||
`We didn't find a session with name '${name}'.\n` +
|
||||
`Please start it first by using POST /sessions/${name}/start request`,
|
||||
);
|
||||
}
|
||||
return session;
|
||||
return session as WhatsappSession;
|
||||
}
|
||||
|
||||
async getSessions(all: boolean): Promise<SessionInfo[]> {
|
||||
if (!this.session) {
|
||||
if (!all) {
|
||||
return [];
|
||||
}
|
||||
if (this.session === null && all) {
|
||||
return [
|
||||
{
|
||||
name: this.DEFAULT,
|
||||
status: WAHASessionStatus.STOPPED,
|
||||
config: undefined,
|
||||
config: this.sessionConfig,
|
||||
me: null,
|
||||
},
|
||||
];
|
||||
}
|
||||
const me = await this.session.getSessionMeInfo().catch((err) => null);
|
||||
if (this.session === undefined && all) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const session = this.session as WhatsappSession;
|
||||
const me = session.getSessionMeInfo();
|
||||
// Get engine info
|
||||
let engineInfo = {};
|
||||
if (session) {
|
||||
try {
|
||||
engineInfo = await promiseTimeout(10, session.getEngineInfo());
|
||||
} catch (e) {
|
||||
this.log.warn(
|
||||
{ session: this.session },
|
||||
'Error while getting engine info',
|
||||
);
|
||||
}
|
||||
}
|
||||
const engine = {
|
||||
engine: this.session?.engine,
|
||||
...(await this.session?.getEngineInfo().catch((err) => ({}))),
|
||||
engine: session?.engine,
|
||||
...engineInfo,
|
||||
};
|
||||
return [
|
||||
{
|
||||
name: this.session.name,
|
||||
status: this.session.status,
|
||||
config: this.session.sessionConfig,
|
||||
name: session.name,
|
||||
status: session.status,
|
||||
config: session.sessionConfig,
|
||||
me: me,
|
||||
engine: engine,
|
||||
},
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import { WAMedia } from '../structures/responses.dto';
|
||||
import {
|
||||
IEngineMediaProcessor,
|
||||
MediaManager,
|
||||
MediaStorage,
|
||||
} from './abc/media.abc';
|
||||
import { DOCS_URL } from './exceptions';
|
||||
|
||||
export class MediaStorageCore implements MediaStorage {
|
||||
async save(
|
||||
messageId: string,
|
||||
mimetype: string,
|
||||
buffer: Buffer,
|
||||
): Promise<string> {
|
||||
return Promise.resolve(
|
||||
`Media attachment's available only in WAHA Plus version. ${DOCS_URL}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class CoreMediaManager implements MediaManager {
|
||||
constructor(
|
||||
private storage: MediaStorage,
|
||||
private mimetypes: string[],
|
||||
) {}
|
||||
|
||||
async processMedia<Message>(
|
||||
processor: IEngineMediaProcessor<Message>,
|
||||
message: Message,
|
||||
): Promise<Message> {
|
||||
if (!processor.hasMedia(message)) {
|
||||
return message;
|
||||
}
|
||||
const mimetype = '';
|
||||
const filename = processor.getFilename(message);
|
||||
const url = await this.storage.save('', mimetype, Buffer.from(''));
|
||||
const media: WAMedia = {
|
||||
mimetype: mimetype,
|
||||
filename: filename,
|
||||
url: url,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
message.media = media;
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Engine specific media processor
|
||||
* Knows how to extract necessary attributes and fetch the data from Message
|
||||
*/
|
||||
interface IMediaEngineProcessor<Message> {
|
||||
hasMedia(message: Message): boolean;
|
||||
|
||||
getFilename(message: Message): string | null;
|
||||
|
||||
getMimetype(message: Message): string;
|
||||
|
||||
getMessageId(message: Message): string;
|
||||
|
||||
getMediaBuffer(message: Message): Promise<Buffer | null>;
|
||||
}
|
||||
|
||||
export { IMediaEngineProcessor };
|
||||
@@ -0,0 +1,15 @@
|
||||
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
|
||||
/**
|
||||
* General interface for MediaManager - one that handles the logic
|
||||
* and manipulates MediaStorage and MediaEngineProcessor
|
||||
*/
|
||||
interface IMediaManager {
|
||||
processMedia<Message>(
|
||||
processor: IMediaEngineProcessor<Message>,
|
||||
message: Message,
|
||||
session: string,
|
||||
): Promise<Message>;
|
||||
}
|
||||
|
||||
export { IMediaManager };
|
||||
@@ -0,0 +1,42 @@
|
||||
import { S3MediaData } from '@waha/structures/media.s3.dto';
|
||||
|
||||
/**
|
||||
* Handles saving data to the physical storage
|
||||
*/
|
||||
interface Message {
|
||||
// false_111111111@c.us_AAAAAAAAAAAAAA
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface File {
|
||||
extension: string;
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
export interface MediaData {
|
||||
session: string;
|
||||
message: Message;
|
||||
file: File;
|
||||
}
|
||||
|
||||
/**
|
||||
* For stored media data
|
||||
*/
|
||||
export interface MediaStorageData {
|
||||
url: string;
|
||||
s3?: S3MediaData;
|
||||
}
|
||||
|
||||
abstract class IMediaStorage {
|
||||
abstract init(): Promise<void>;
|
||||
|
||||
abstract save(buffer: Buffer, data: MediaData): Promise<boolean>;
|
||||
|
||||
abstract exists(data: MediaData): Promise<boolean>;
|
||||
|
||||
abstract getStorageData(data: MediaData): Promise<MediaStorageData>;
|
||||
|
||||
abstract purge(): Promise<void>;
|
||||
}
|
||||
|
||||
export { IMediaStorage };
|
||||
@@ -0,0 +1,44 @@
|
||||
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
import { IMediaStorage, MediaData } from '@waha/core/media/IMediaStorage';
|
||||
import { WAMedia } from '@waha/structures/media.dto';
|
||||
|
||||
import { IMediaManager } from './IMediaManager';
|
||||
|
||||
export class MediaManagerCore implements IMediaManager {
|
||||
constructor(
|
||||
private storage: IMediaStorage,
|
||||
private mimetypes: string[],
|
||||
) {}
|
||||
|
||||
async processMedia<Message>(
|
||||
processor: IMediaEngineProcessor<Message>,
|
||||
message: Message,
|
||||
session: string,
|
||||
): Promise<Message> {
|
||||
if (!processor.hasMedia(message)) {
|
||||
return message;
|
||||
}
|
||||
const mimetype = '';
|
||||
const mediaData: MediaData = {
|
||||
session: session,
|
||||
message: {
|
||||
id: '',
|
||||
},
|
||||
file: {
|
||||
extension: '',
|
||||
},
|
||||
};
|
||||
const { url } = await this.storage.getStorageData(mediaData);
|
||||
|
||||
const filename = processor.getFilename(message);
|
||||
const media: WAMedia = {
|
||||
mimetype: mimetype,
|
||||
filename: filename,
|
||||
url: url,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
message.media = media;
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DOCS_URL } from '@waha/core/exceptions';
|
||||
import { IMediaStorage, MediaData } from '@waha/core/media/IMediaStorage';
|
||||
|
||||
export class MediaNoopStorage implements IMediaStorage {
|
||||
async init() {
|
||||
return;
|
||||
}
|
||||
|
||||
async save(buffer: Buffer, data: MediaData): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
async exists(data: MediaData): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async getStorageData(data: MediaData) {
|
||||
const url = `Media attachment's available only in WAHA Plus version. ${DOCS_URL}`;
|
||||
return { url };
|
||||
}
|
||||
|
||||
async purge() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { WhatsappConfigService } from '@waha/config.service';
|
||||
|
||||
@Injectable()
|
||||
export class MediaLocalStorageConfig {
|
||||
public filesUri = '/api/files';
|
||||
|
||||
constructor(private config: WhatsappConfigService) {}
|
||||
|
||||
get filesURL(): string {
|
||||
return `${this.config.schema}://${this.config.hostname}:${this.config.port}${this.filesUri}/`;
|
||||
}
|
||||
|
||||
get filesFolder(): string {
|
||||
return this.config.get('WHATSAPP_FILES_FOLDER', '/tmp/whatsapp-files');
|
||||
}
|
||||
|
||||
get filesLifetime(): number {
|
||||
return parseInt(this.config.get('WHATSAPP_FILES_LIFETIME', '180'));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,4 @@ export abstract class ISessionAuthRepository {
|
||||
abstract init(sessionName?: string): Promise<void>;
|
||||
|
||||
abstract clean(sessionName: string): Promise<void>;
|
||||
|
||||
abstract getAll(): Promise<string[]>;
|
||||
}
|
||||
@@ -8,5 +8,9 @@ export abstract class ISessionConfigRepository {
|
||||
|
||||
abstract get(sessionName: string): Promise<SessionConfig | null>;
|
||||
|
||||
abstract exists(sessionName: string): Promise<boolean>;
|
||||
|
||||
abstract delete(sessionName: string): Promise<void>;
|
||||
|
||||
abstract getAll(): Promise<string[]>;
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import * as fs from 'fs/promises';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const fs = require('fs-extra');
|
||||
|
||||
import { ISessionAuthRepository } from './ISessionAuthRepository';
|
||||
import { LocalStore } from './LocalStore';
|
||||
// Keep all waha related files, ".waha.session.*"
|
||||
const KEEP_FILES = /^\.waha\.session\..*$/;
|
||||
|
||||
export class LocalSessionAuthRepository extends ISessionAuthRepository {
|
||||
private store: LocalStore;
|
||||
@@ -16,17 +19,17 @@ export class LocalSessionAuthRepository extends ISessionAuthRepository {
|
||||
}
|
||||
|
||||
async clean(sessionName: string) {
|
||||
const folder = this.store.getSessionDirectory(sessionName);
|
||||
await fs.rm(folder, { recursive: true });
|
||||
}
|
||||
|
||||
async getAll(): Promise<string[]> {
|
||||
await this.init();
|
||||
const content = await fs.readdir(this.store.getEngineDirectory(), {
|
||||
withFileTypes: true,
|
||||
});
|
||||
return content
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
// Remove all files and directories recursively, but keep waha files
|
||||
const sessionDirectory = this.store.getSessionDirectory(sessionName);
|
||||
// Check it exists and it's directory
|
||||
const exists = await fs.pathExists(sessionDirectory);
|
||||
if (!exists) {
|
||||
return;
|
||||
}
|
||||
const files = await fs.readdir(sessionDirectory);
|
||||
const filesToRemove = files.filter((file) => !file.match(KEEP_FILES));
|
||||
for (const file of filesToRemove) {
|
||||
await fs.remove(`${sessionDirectory}/${file}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as fs from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const fs = require('fs-extra');
|
||||
|
||||
import { fileExists } from '@waha/utils/files';
|
||||
|
||||
import { SessionConfig } from '../../structures/sessions.dto';
|
||||
import { ISessionConfigRepository } from './ISessionConfigRepository';
|
||||
@@ -14,11 +16,13 @@ export class LocalSessionConfigRepository extends ISessionConfigRepository {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
private async fileExists(filepath: string) {
|
||||
try {
|
||||
await fs.access(filepath, fs.constants.F_OK);
|
||||
} catch (error) {
|
||||
return false;
|
||||
async exists(sessionName: string): Promise<boolean> {
|
||||
const filepath = this.getFilePath(sessionName);
|
||||
const exists = await fileExists(filepath);
|
||||
if (!exists) {
|
||||
// check directory exist for empty config sessions
|
||||
const folder = this.store.getSessionDirectory(sessionName);
|
||||
return await fileExists(folder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -26,7 +30,7 @@ export class LocalSessionConfigRepository extends ISessionConfigRepository {
|
||||
async get(sessionName: string): Promise<SessionConfig | null> {
|
||||
const filepath = this.getFilePath(sessionName);
|
||||
// Check file exists
|
||||
if (!(await this.fileExists(filepath))) {
|
||||
if (!(await fileExists(filepath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -56,10 +60,17 @@ export class LocalSessionConfigRepository extends ISessionConfigRepository {
|
||||
}
|
||||
|
||||
async delete(sessionName: string): Promise<void> {
|
||||
const filepath = this.getFilePath(sessionName);
|
||||
if (!(await this.fileExists(filepath))) {
|
||||
return;
|
||||
}
|
||||
await fs.unlink(filepath);
|
||||
const sessionDirectory = this.store.getSessionDirectory(sessionName);
|
||||
await fs.remove(sessionDirectory);
|
||||
}
|
||||
|
||||
async getAll(): Promise<string[]> {
|
||||
await this.store.init();
|
||||
const content = await fs.readdir(this.store.getEngineDirectory(), {
|
||||
withFileTypes: true,
|
||||
});
|
||||
return content
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
}
|
||||
}
|
||||
+21
-16
@@ -1,5 +1,3 @@
|
||||
import { ConsoleLogger } from '@nestjs/common';
|
||||
|
||||
import { WAHAEvents } from '../structures/enums.dto';
|
||||
import { WebhookConfig } from '../structures/webhooks.config.dto';
|
||||
import { WAHAWebhook } from '../structures/webhooks.dto';
|
||||
@@ -7,30 +5,36 @@ import { VERSION } from '../version';
|
||||
import { WAHAInternalEvent, WhatsappSession } from './abc/session.abc';
|
||||
import { WebhookConductor, WebhookSender } from './abc/webhooks.abc';
|
||||
import request = require('request');
|
||||
import { LoggerBuilder } from '@waha/utils/logging';
|
||||
import { Logger } from 'pino';
|
||||
|
||||
export class WebhookSenderCore extends WebhookSender {
|
||||
send(json) {
|
||||
this.log.log(`Sending POST to ${this.url}...`);
|
||||
this.log.verbose(`POST DATA: ${JSON.stringify(json)}`);
|
||||
this.logger.info({ url: this.url }, `Sending POST ...`);
|
||||
this.logger.debug({ data: json }, `POST DATA`);
|
||||
|
||||
request.post(this.url, { json: json }, (error, res, body) => {
|
||||
if (error) {
|
||||
this.log.error(error);
|
||||
this.logger.error(error);
|
||||
return;
|
||||
}
|
||||
this.log.log(`POST request was sent with status code: ${res.statusCode}`);
|
||||
this.log.debug(`Response: ${body}`);
|
||||
this.logger.info(
|
||||
`POST request was sent with status code: ${res.statusCode}`,
|
||||
);
|
||||
this.logger.debug({ body: body }, `Response`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class WebhookConductorCore implements WebhookConductor {
|
||||
constructor(protected log: ConsoleLogger) {
|
||||
this.log = log;
|
||||
private logger: Logger;
|
||||
|
||||
constructor(protected loggerBuilder: LoggerBuilder) {
|
||||
this.logger = loggerBuilder.child({ name: WebhookConductor.name });
|
||||
}
|
||||
|
||||
protected buildSender(webhookConfig: WebhookConfig): WebhookSender {
|
||||
return new WebhookSenderCore(this.log, webhookConfig);
|
||||
return new WebhookSenderCore(this.loggerBuilder, webhookConfig);
|
||||
}
|
||||
|
||||
private getSuitableEvents(events: WAHAEvents[] | string[]): WAHAEvents[] {
|
||||
@@ -47,7 +51,7 @@ export class WebhookConductorCore implements WebhookConductor {
|
||||
for (const event of events) {
|
||||
// @ts-ignore
|
||||
if (!allEvents.includes(event)) {
|
||||
this.log.error(`Unknown event for webhook: '${event}'`);
|
||||
this.logger.error(`Unknown event for webhook: '${event}'`);
|
||||
continue;
|
||||
}
|
||||
rightEvents.push(event);
|
||||
@@ -70,7 +74,7 @@ export class WebhookConductorCore implements WebhookConductor {
|
||||
}
|
||||
|
||||
const url = webhook.url;
|
||||
this.log.log(`Configuring webhooks for ${url}...`);
|
||||
this.logger.info(`Configuring webhooks for ${url}...`);
|
||||
const events = this.getSuitableEvents(webhook.events);
|
||||
const sender = this.buildSender(webhook);
|
||||
for (const event of events) {
|
||||
@@ -93,14 +97,14 @@ export class WebhookConductorCore implements WebhookConductor {
|
||||
url,
|
||||
);
|
||||
if (!found) {
|
||||
this.log.error(
|
||||
this.logger.error(
|
||||
`Engine does not support webhook event: '${event}' for url '${url}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.log.log(`Webhooks were configured for ${url}.`);
|
||||
this.logger.info(`Webhooks were configured for ${url}.`);
|
||||
}
|
||||
|
||||
private configureSingleEvent(
|
||||
@@ -117,7 +121,7 @@ export class WebhookConductorCore implements WebhookConductor {
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
this.log.log(`Event '${event}' is enabled for url: ${url}`);
|
||||
this.logger.info(`Event '${event}' is enabled for url: ${url}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -127,10 +131,11 @@ export class WebhookConductorCore implements WebhookConductor {
|
||||
data: any,
|
||||
sender: WebhookSender,
|
||||
) {
|
||||
const me = await session.getSessionMeInfo().catch((err) => null);
|
||||
const me = session.getSessionMeInfo();
|
||||
const json: WAHAWebhook = {
|
||||
event: event,
|
||||
session: session.name,
|
||||
metadata: session.sessionConfig?.metadata,
|
||||
me: me,
|
||||
payload: data,
|
||||
engine: session.engine,
|
||||
|
||||
Whitespace-only changes.
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html><html><head><style type="text/css" data-primevue-style-id="layer-order" >@layer tailwind-base, primevue, tailwind-utilities</style><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link id="theme-css" rel="stylesheet" type="text/css" href="/dashboard/themes/lara-dark-green/theme.css">
|
||||
<link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico">
|
||||
<link rel="stylesheet" href="/dashboard/_nuxt/entry.CdRyF6M1.css">
|
||||
<link rel="modulepreload" as="script" crossorigin href="/dashboard/_nuxt/CdAotn7S.js">
|
||||
<link rel="prefetch" as="image" type="image/svg+xml" href="/dashboard/_nuxt/primeicons.BubJZjaf.svg">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ccJKIdck.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dbq0hxqO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DxKOBqhC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/AdkLG1re.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BO3ltiFH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CYhL7ix_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BwlcA3rq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiBqmW71.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/eLdOjEri.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIoHdha8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIUw7GKS.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3XiIAJo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDd6n_m5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1Sip8Hx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DJsXWhIp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dh-ZHPbY.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CQay6pFc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B1YYYcwB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DtEiWfmc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0KS7mWPU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DfRs6WFy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/4TRLVPYt.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DUyMz6Kq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B3yzUv7e.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cs_e0Jyg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D12jMld0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DFD6ABtc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DpxAcOXA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BnZbcMaK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BbTUXNRy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtwAl4SI.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CzF1vgty.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/RtM6PxTR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DREobrkF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIpALR7x.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CXYhB39H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8DP3eJmh.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cfpwp2_y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DqnHOBMx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BsAQV9Bu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/gJ3REwVq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/APAbiAbl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/TBrkteSm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C_oNyt3I.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1XkA2bf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BJhSZnhn.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/By-HpsnP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CpdXuDKl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ml1zUTb3.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2QbcHjol.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ca08GESE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D9bLrmuX.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CUo_zosT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DLaX2Rc0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D07-QKFk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/92NHSphk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CIQNJf2Q.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BlMMx3ZO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BiToFvXy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBPkAxhp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BMxgtM-u.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DMn_A95H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CM_CX4UR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1z1il7n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DnVQIBe4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cz8bw1cb.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ct0vUmX9.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/v19YZAG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CCyJ2OIf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DlrEeELo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B_-yrHFp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/G6CMuSbq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CSwvDmSR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DGtckhjV.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CW7WdM7z.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BybkDDc2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/tvJRpBit.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cysexb6G.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CfQfmr4y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDsMXgj0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DQrDif0P.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2nNxFeOi.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ChuxxnpQ.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYme1kum.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBo9fE9b.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/vromkmgO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DR_5D5CK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DdA0oWG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBmLef7_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BhprPxR2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/KLlBvxGE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ot8uXRrF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/qf2Wnj4S.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiZTV4zm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/1mD_0Gmg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DaK9vsnd.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hZ0eYskP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYT2DC_F.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BC5yIRjL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNgtVCIx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0Qz0KUbT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DSb3mYm4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNQ0gqHD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BDkUdWus.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cdm8H2oy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bxn3h1eA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D7pGaQXu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BFoAkamz.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hRxDLgWo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/W_LTasvG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BXW9ULDT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/9hnJxdZr.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtAnjVGO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/rOp_cn8n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/O1ZEMdSv.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D5rPsEXk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D3ktpMNC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bg_obesD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DPrOADBq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3-WSoLU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BK_1YlQG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DrPPGdq8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8VT3ACce.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CqsZXHTj.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DiD3_pIL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BuAsgUvH.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/useServerStore.DWEvhDiM.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1Y5pYTB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B7MMdMyR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C0K2Sjq5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/fmRlOMwp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/uEiA7KRH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B4IxZQIs.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DyMztKbV.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-404.JekaaCis.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bub0TpVl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DISPJkjY.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-500.CNP9nqm1.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CMeAQMKa.js">
|
||||
<script type="module" src="/dashboard/_nuxt/CdAotn7S.js" crossorigin></script>
|
||||
<script id="unhead:payload" type="application/json">{"title":"Dashboard | WAHA"}</script><style type="text/css" data-primevue-style-id="base" >
|
||||
.p-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-hidden-accessible input,
|
||||
.p-hidden-accessible select {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-overflow-hidden {
|
||||
overflow: hidden;
|
||||
padding-right: var(--scrollbar-width);
|
||||
}
|
||||
</style><style type="text/css" data-primevue-style-id="virtualscroller" >
|
||||
@layer primevue {
|
||||
.p-virtualscroller {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
will-change: scroll-position;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.p-virtualscroller-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* contain: content; */
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-virtualscroller-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
transform-origin: 0 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-virtualscroller .p-virtualscroller-loader {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loader.p-component-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon.p-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-horizontal > .p-virtualscroller-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Inline */
|
||||
.p-virtualscroller-inline .p-virtualscroller-content {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
|
||||
<script>window.__NUXT__={};window.__NUXT__.config={public:{primevue:{usePrimeVue:true,resolvePath:"",cssLayerOrder:"tailwind-base, primevue, tailwind-utilities",importPT:"",options:{ripple:true},components:[{name:"AutoComplete",as:"AutoComplete",from:"primevue/autocomplete",export:"default",filePath:"primevue/autocomplete",global:true},{name:"Calendar",as:"Calendar",from:"primevue/calendar",export:"default",filePath:"primevue/calendar",global:true},{name:"CascadeSelect",as:"CascadeSelect",from:"primevue/cascadeselect",export:"default",filePath:"primevue/cascadeselect",global:true},{name:"Checkbox",as:"Checkbox",from:"primevue/checkbox",export:"default",filePath:"primevue/checkbox",global:true},{name:"Chips",as:"Chips",from:"primevue/chips",export:"default",filePath:"primevue/chips",global:true},{name:"ColorPicker",as:"ColorPicker",from:"primevue/colorpicker",export:"default",filePath:"primevue/colorpicker",global:true},{name:"Dropdown",as:"Dropdown",from:"primevue/dropdown",export:"default",filePath:"primevue/dropdown",global:true},{name:"FloatLabel",as:"FloatLabel",from:"primevue/floatlabel",export:"default",filePath:"primevue/floatlabel",global:true},{name:"IconField",as:"IconField",from:"primevue/iconfield",export:"default",filePath:"primevue/iconfield",global:true},{name:"InputGroup",as:"InputGroup",from:"primevue/inputgroup",export:"default",filePath:"primevue/inputgroup",global:true},{name:"InputGroupAddon",as:"InputGroupAddon",from:"primevue/inputgroupaddon",export:"default",filePath:"primevue/inputgroupaddon",global:true},{name:"InputIcon",as:"InputIcon",from:"primevue/inputicon",export:"default",filePath:"primevue/inputicon",global:true},{name:"InputMask",as:"InputMask",from:"primevue/inputmask",export:"default",filePath:"primevue/inputmask",global:true},{name:"InputNumber",as:"InputNumber",from:"primevue/inputnumber",export:"default",filePath:"primevue/inputnumber",global:true},{name:"InputOtp",as:"InputOtp",from:"primevue/inputotp",export:"default",filePath:"primevue/inputotp",global:true},{name:"InputSwitch",as:"InputSwitch",from:"primevue/inputswitch",export:"default",filePath:"primevue/inputswitch",global:true},{name:"InputText",as:"InputText",from:"primevue/inputtext",export:"default",filePath:"primevue/inputtext",global:true},{name:"Knob",as:"Knob",from:"primevue/knob",export:"default",filePath:"primevue/knob",global:true},{name:"Listbox",as:"Listbox",from:"primevue/listbox",export:"default",filePath:"primevue/listbox",global:true},{name:"MultiSelect",as:"MultiSelect",from:"primevue/multiselect",export:"default",filePath:"primevue/multiselect",global:true},{name:"Password",as:"Password",from:"primevue/password",export:"default",filePath:"primevue/password",global:true},{name:"RadioButton",as:"RadioButton",from:"primevue/radiobutton",export:"default",filePath:"primevue/radiobutton",global:true},{name:"Rating",as:"Rating",from:"primevue/rating",export:"default",filePath:"primevue/rating",global:true},{name:"SelectButton",as:"SelectButton",from:"primevue/selectbutton",export:"default",filePath:"primevue/selectbutton",global:true},{name:"Slider",as:"Slider",from:"primevue/slider",export:"default",filePath:"primevue/slider",global:true},{name:"Textarea",as:"Textarea",from:"primevue/textarea",export:"default",filePath:"primevue/textarea",global:true},{name:"ToggleButton",as:"ToggleButton",from:"primevue/togglebutton",export:"default",filePath:"primevue/togglebutton",global:true},{name:"TreeSelect",as:"TreeSelect",from:"primevue/treeselect",export:"default",filePath:"primevue/treeselect",global:true},{name:"TriStateCheckbox",as:"TriStateCheckbox",from:"primevue/tristatecheckbox",export:"default",filePath:"primevue/tristatecheckbox",global:true},{name:"Button",as:"Button",from:"primevue/button",export:"default",filePath:"primevue/button",global:true},{name:"ButtonGroup",as:"ButtonGroup",from:"primevue/buttongroup",export:"default",filePath:"primevue/buttongroup",global:true},{name:"SpeedDial",as:"SpeedDial",from:"primevue/speeddial",export:"default",filePath:"primevue/speeddial",global:true},{name:"SplitButton",as:"SplitButton",from:"primevue/splitbutton",export:"default",filePath:"primevue/splitbutton",global:true},{name:"Column",as:"Column",from:"primevue/column",export:"default",filePath:"primevue/column",global:true},{name:"Row",as:"Row",from:"primevue/row",export:"default",filePath:"primevue/row",global:true},{name:"ColumnGroup",as:"ColumnGroup",from:"primevue/columngroup",export:"default",filePath:"primevue/columngroup",global:true},{name:"DataTable",as:"DataTable",from:"primevue/datatable",export:"default",filePath:"primevue/datatable",global:true},{name:"DataView",as:"DataView",from:"primevue/dataview",export:"default",filePath:"primevue/dataview",global:true},{name:"DataViewLayoutOptions",as:"DataViewLayoutOptions",from:"primevue/dataviewlayoutoptions",export:"default",filePath:"primevue/dataviewlayoutoptions",global:true},{name:"OrderList",as:"OrderList",from:"primevue/orderlist",export:"Line truncated
|
||||
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html><html><head><style type="text/css" data-primevue-style-id="layer-order" >@layer tailwind-base, primevue, tailwind-utilities</style><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link id="theme-css" rel="stylesheet" type="text/css" href="/dashboard/themes/lara-dark-green/theme.css">
|
||||
<link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico">
|
||||
<link rel="stylesheet" href="/dashboard/_nuxt/entry.CdRyF6M1.css">
|
||||
<link rel="modulepreload" as="script" crossorigin href="/dashboard/_nuxt/CdAotn7S.js">
|
||||
<link rel="prefetch" as="image" type="image/svg+xml" href="/dashboard/_nuxt/primeicons.BubJZjaf.svg">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ccJKIdck.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dbq0hxqO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DxKOBqhC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/AdkLG1re.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BO3ltiFH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CYhL7ix_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BwlcA3rq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiBqmW71.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/eLdOjEri.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIoHdha8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIUw7GKS.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3XiIAJo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDd6n_m5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1Sip8Hx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DJsXWhIp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dh-ZHPbY.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CQay6pFc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B1YYYcwB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DtEiWfmc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0KS7mWPU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DfRs6WFy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/4TRLVPYt.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DUyMz6Kq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B3yzUv7e.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cs_e0Jyg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D12jMld0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DFD6ABtc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DpxAcOXA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BnZbcMaK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BbTUXNRy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtwAl4SI.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CzF1vgty.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/RtM6PxTR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DREobrkF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIpALR7x.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CXYhB39H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8DP3eJmh.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cfpwp2_y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DqnHOBMx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BsAQV9Bu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/gJ3REwVq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/APAbiAbl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/TBrkteSm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C_oNyt3I.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1XkA2bf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BJhSZnhn.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/By-HpsnP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CpdXuDKl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ml1zUTb3.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2QbcHjol.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ca08GESE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D9bLrmuX.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CUo_zosT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DLaX2Rc0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D07-QKFk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/92NHSphk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CIQNJf2Q.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BlMMx3ZO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BiToFvXy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBPkAxhp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BMxgtM-u.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DMn_A95H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CM_CX4UR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1z1il7n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DnVQIBe4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cz8bw1cb.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ct0vUmX9.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/v19YZAG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CCyJ2OIf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DlrEeELo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B_-yrHFp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/G6CMuSbq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CSwvDmSR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DGtckhjV.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CW7WdM7z.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BybkDDc2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/tvJRpBit.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cysexb6G.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CfQfmr4y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDsMXgj0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DQrDif0P.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2nNxFeOi.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ChuxxnpQ.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYme1kum.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBo9fE9b.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/vromkmgO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DR_5D5CK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DdA0oWG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBmLef7_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BhprPxR2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/KLlBvxGE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ot8uXRrF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/qf2Wnj4S.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiZTV4zm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/1mD_0Gmg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DaK9vsnd.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hZ0eYskP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYT2DC_F.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BC5yIRjL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNgtVCIx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0Qz0KUbT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DSb3mYm4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNQ0gqHD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BDkUdWus.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cdm8H2oy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bxn3h1eA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D7pGaQXu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BFoAkamz.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hRxDLgWo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/W_LTasvG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BXW9ULDT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/9hnJxdZr.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtAnjVGO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/rOp_cn8n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/O1ZEMdSv.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D5rPsEXk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D3ktpMNC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bg_obesD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DPrOADBq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3-WSoLU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BK_1YlQG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DrPPGdq8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8VT3ACce.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CqsZXHTj.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DiD3_pIL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BuAsgUvH.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/useServerStore.DWEvhDiM.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1Y5pYTB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B7MMdMyR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C0K2Sjq5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/fmRlOMwp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/uEiA7KRH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B4IxZQIs.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DyMztKbV.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-404.JekaaCis.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bub0TpVl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DISPJkjY.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-500.CNP9nqm1.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CMeAQMKa.js">
|
||||
<script type="module" src="/dashboard/_nuxt/CdAotn7S.js" crossorigin></script>
|
||||
<script id="unhead:payload" type="application/json">{"title":"Dashboard | WAHA"}</script><style type="text/css" data-primevue-style-id="base" >
|
||||
.p-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-hidden-accessible input,
|
||||
.p-hidden-accessible select {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-overflow-hidden {
|
||||
overflow: hidden;
|
||||
padding-right: var(--scrollbar-width);
|
||||
}
|
||||
</style><style type="text/css" data-primevue-style-id="virtualscroller" >
|
||||
@layer primevue {
|
||||
.p-virtualscroller {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
will-change: scroll-position;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.p-virtualscroller-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* contain: content; */
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-virtualscroller-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
transform-origin: 0 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-virtualscroller .p-virtualscroller-loader {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loader.p-component-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon.p-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-horizontal > .p-virtualscroller-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Inline */
|
||||
.p-virtualscroller-inline .p-virtualscroller-content {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
|
||||
<script>window.__NUXT__={};window.__NUXT__.config={public:{primevue:{usePrimeVue:true,resolvePath:"",cssLayerOrder:"tailwind-base, primevue, tailwind-utilities",importPT:"",options:{ripple:true},components:[{name:"AutoComplete",as:"AutoComplete",from:"primevue/autocomplete",export:"default",filePath:"primevue/autocomplete",global:true},{name:"Calendar",as:"Calendar",from:"primevue/calendar",export:"default",filePath:"primevue/calendar",global:true},{name:"CascadeSelect",as:"CascadeSelect",from:"primevue/cascadeselect",export:"default",filePath:"primevue/cascadeselect",global:true},{name:"Checkbox",as:"Checkbox",from:"primevue/checkbox",export:"default",filePath:"primevue/checkbox",global:true},{name:"Chips",as:"Chips",from:"primevue/chips",export:"default",filePath:"primevue/chips",global:true},{name:"ColorPicker",as:"ColorPicker",from:"primevue/colorpicker",export:"default",filePath:"primevue/colorpicker",global:true},{name:"Dropdown",as:"Dropdown",from:"primevue/dropdown",export:"default",filePath:"primevue/dropdown",global:true},{name:"FloatLabel",as:"FloatLabel",from:"primevue/floatlabel",export:"default",filePath:"primevue/floatlabel",global:true},{name:"IconField",as:"IconField",from:"primevue/iconfield",export:"default",filePath:"primevue/iconfield",global:true},{name:"InputGroup",as:"InputGroup",from:"primevue/inputgroup",export:"default",filePath:"primevue/inputgroup",global:true},{name:"InputGroupAddon",as:"InputGroupAddon",from:"primevue/inputgroupaddon",export:"default",filePath:"primevue/inputgroupaddon",global:true},{name:"InputIcon",as:"InputIcon",from:"primevue/inputicon",export:"default",filePath:"primevue/inputicon",global:true},{name:"InputMask",as:"InputMask",from:"primevue/inputmask",export:"default",filePath:"primevue/inputmask",global:true},{name:"InputNumber",as:"InputNumber",from:"primevue/inputnumber",export:"default",filePath:"primevue/inputnumber",global:true},{name:"InputOtp",as:"InputOtp",from:"primevue/inputotp",export:"default",filePath:"primevue/inputotp",global:true},{name:"InputSwitch",as:"InputSwitch",from:"primevue/inputswitch",export:"default",filePath:"primevue/inputswitch",global:true},{name:"InputText",as:"InputText",from:"primevue/inputtext",export:"default",filePath:"primevue/inputtext",global:true},{name:"Knob",as:"Knob",from:"primevue/knob",export:"default",filePath:"primevue/knob",global:true},{name:"Listbox",as:"Listbox",from:"primevue/listbox",export:"default",filePath:"primevue/listbox",global:true},{name:"MultiSelect",as:"MultiSelect",from:"primevue/multiselect",export:"default",filePath:"primevue/multiselect",global:true},{name:"Password",as:"Password",from:"primevue/password",export:"default",filePath:"primevue/password",global:true},{name:"RadioButton",as:"RadioButton",from:"primevue/radiobutton",export:"default",filePath:"primevue/radiobutton",global:true},{name:"Rating",as:"Rating",from:"primevue/rating",export:"default",filePath:"primevue/rating",global:true},{name:"SelectButton",as:"SelectButton",from:"primevue/selectbutton",export:"default",filePath:"primevue/selectbutton",global:true},{name:"Slider",as:"Slider",from:"primevue/slider",export:"default",filePath:"primevue/slider",global:true},{name:"Textarea",as:"Textarea",from:"primevue/textarea",export:"default",filePath:"primevue/textarea",global:true},{name:"ToggleButton",as:"ToggleButton",from:"primevue/togglebutton",export:"default",filePath:"primevue/togglebutton",global:true},{name:"TreeSelect",as:"TreeSelect",from:"primevue/treeselect",export:"default",filePath:"primevue/treeselect",global:true},{name:"TriStateCheckbox",as:"TriStateCheckbox",from:"primevue/tristatecheckbox",export:"default",filePath:"primevue/tristatecheckbox",global:true},{name:"Button",as:"Button",from:"primevue/button",export:"default",filePath:"primevue/button",global:true},{name:"ButtonGroup",as:"ButtonGroup",from:"primevue/buttongroup",export:"default",filePath:"primevue/buttongroup",global:true},{name:"SpeedDial",as:"SpeedDial",from:"primevue/speeddial",export:"default",filePath:"primevue/speeddial",global:true},{name:"SplitButton",as:"SplitButton",from:"primevue/splitbutton",export:"default",filePath:"primevue/splitbutton",global:true},{name:"Column",as:"Column",from:"primevue/column",export:"default",filePath:"primevue/column",global:true},{name:"Row",as:"Row",from:"primevue/row",export:"default",filePath:"primevue/row",global:true},{name:"ColumnGroup",as:"ColumnGroup",from:"primevue/columngroup",export:"default",filePath:"primevue/columngroup",global:true},{name:"DataTable",as:"DataTable",from:"primevue/datatable",export:"default",filePath:"primevue/datatable",global:true},{name:"DataView",as:"DataView",from:"primevue/dataview",export:"default",filePath:"primevue/dataview",global:true},{name:"DataViewLayoutOptions",as:"DataViewLayoutOptions",from:"primevue/dataviewlayoutoptions",export:"default",filePath:"primevue/dataviewlayoutoptions",global:true},{name:"OrderList",as:"OrderList",from:"primevue/orderlist",export:"Line truncated
|
||||
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html><html><head><style type="text/css" data-primevue-style-id="layer-order" >@layer tailwind-base, primevue, tailwind-utilities</style><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link id="theme-css" rel="stylesheet" type="text/css" href="/dashboard/themes/lara-dark-green/theme.css">
|
||||
<link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico">
|
||||
<link rel="stylesheet" href="/dashboard/_nuxt/entry.CdRyF6M1.css">
|
||||
<link rel="modulepreload" as="script" crossorigin href="/dashboard/_nuxt/CdAotn7S.js">
|
||||
<link rel="prefetch" as="image" type="image/svg+xml" href="/dashboard/_nuxt/primeicons.BubJZjaf.svg">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ccJKIdck.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dbq0hxqO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DxKOBqhC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/AdkLG1re.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BO3ltiFH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CYhL7ix_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BwlcA3rq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiBqmW71.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/eLdOjEri.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIoHdha8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIUw7GKS.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3XiIAJo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDd6n_m5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1Sip8Hx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DJsXWhIp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dh-ZHPbY.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CQay6pFc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B1YYYcwB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DtEiWfmc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0KS7mWPU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DfRs6WFy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/4TRLVPYt.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DUyMz6Kq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B3yzUv7e.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cs_e0Jyg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D12jMld0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DFD6ABtc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DpxAcOXA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BnZbcMaK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BbTUXNRy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtwAl4SI.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CzF1vgty.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/RtM6PxTR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DREobrkF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIpALR7x.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CXYhB39H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8DP3eJmh.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cfpwp2_y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DqnHOBMx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BsAQV9Bu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/gJ3REwVq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/APAbiAbl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/TBrkteSm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C_oNyt3I.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1XkA2bf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BJhSZnhn.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/By-HpsnP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CpdXuDKl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ml1zUTb3.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2QbcHjol.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ca08GESE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D9bLrmuX.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CUo_zosT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DLaX2Rc0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D07-QKFk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/92NHSphk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CIQNJf2Q.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BlMMx3ZO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BiToFvXy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBPkAxhp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BMxgtM-u.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DMn_A95H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CM_CX4UR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1z1il7n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DnVQIBe4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cz8bw1cb.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ct0vUmX9.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/v19YZAG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CCyJ2OIf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DlrEeELo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B_-yrHFp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/G6CMuSbq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CSwvDmSR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DGtckhjV.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CW7WdM7z.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BybkDDc2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/tvJRpBit.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cysexb6G.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CfQfmr4y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDsMXgj0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DQrDif0P.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2nNxFeOi.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ChuxxnpQ.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYme1kum.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBo9fE9b.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/vromkmgO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DR_5D5CK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DdA0oWG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBmLef7_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BhprPxR2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/KLlBvxGE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ot8uXRrF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/qf2Wnj4S.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiZTV4zm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/1mD_0Gmg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DaK9vsnd.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hZ0eYskP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYT2DC_F.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BC5yIRjL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNgtVCIx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0Qz0KUbT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DSb3mYm4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNQ0gqHD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BDkUdWus.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cdm8H2oy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bxn3h1eA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D7pGaQXu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BFoAkamz.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hRxDLgWo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/W_LTasvG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BXW9ULDT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/9hnJxdZr.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtAnjVGO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/rOp_cn8n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/O1ZEMdSv.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D5rPsEXk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D3ktpMNC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bg_obesD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DPrOADBq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3-WSoLU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BK_1YlQG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DrPPGdq8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8VT3ACce.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CqsZXHTj.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DiD3_pIL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BuAsgUvH.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/useServerStore.DWEvhDiM.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1Y5pYTB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B7MMdMyR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C0K2Sjq5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/fmRlOMwp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/uEiA7KRH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B4IxZQIs.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DyMztKbV.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-404.JekaaCis.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bub0TpVl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DISPJkjY.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-500.CNP9nqm1.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CMeAQMKa.js">
|
||||
<script type="module" src="/dashboard/_nuxt/CdAotn7S.js" crossorigin></script>
|
||||
<script id="unhead:payload" type="application/json">{"title":"Dashboard | WAHA"}</script><style type="text/css" data-primevue-style-id="base" >
|
||||
.p-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-hidden-accessible input,
|
||||
.p-hidden-accessible select {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-overflow-hidden {
|
||||
overflow: hidden;
|
||||
padding-right: var(--scrollbar-width);
|
||||
}
|
||||
</style><style type="text/css" data-primevue-style-id="virtualscroller" >
|
||||
@layer primevue {
|
||||
.p-virtualscroller {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
will-change: scroll-position;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.p-virtualscroller-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* contain: content; */
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-virtualscroller-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
transform-origin: 0 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-virtualscroller .p-virtualscroller-loader {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loader.p-component-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon.p-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-horizontal > .p-virtualscroller-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Inline */
|
||||
.p-virtualscroller-inline .p-virtualscroller-content {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
|
||||
<script>window.__NUXT__={};window.__NUXT__.config={public:{primevue:{usePrimeVue:true,resolvePath:"",cssLayerOrder:"tailwind-base, primevue, tailwind-utilities",importPT:"",options:{ripple:true},components:[{name:"AutoComplete",as:"AutoComplete",from:"primevue/autocomplete",export:"default",filePath:"primevue/autocomplete",global:true},{name:"Calendar",as:"Calendar",from:"primevue/calendar",export:"default",filePath:"primevue/calendar",global:true},{name:"CascadeSelect",as:"CascadeSelect",from:"primevue/cascadeselect",export:"default",filePath:"primevue/cascadeselect",global:true},{name:"Checkbox",as:"Checkbox",from:"primevue/checkbox",export:"default",filePath:"primevue/checkbox",global:true},{name:"Chips",as:"Chips",from:"primevue/chips",export:"default",filePath:"primevue/chips",global:true},{name:"ColorPicker",as:"ColorPicker",from:"primevue/colorpicker",export:"default",filePath:"primevue/colorpicker",global:true},{name:"Dropdown",as:"Dropdown",from:"primevue/dropdown",export:"default",filePath:"primevue/dropdown",global:true},{name:"FloatLabel",as:"FloatLabel",from:"primevue/floatlabel",export:"default",filePath:"primevue/floatlabel",global:true},{name:"IconField",as:"IconField",from:"primevue/iconfield",export:"default",filePath:"primevue/iconfield",global:true},{name:"InputGroup",as:"InputGroup",from:"primevue/inputgroup",export:"default",filePath:"primevue/inputgroup",global:true},{name:"InputGroupAddon",as:"InputGroupAddon",from:"primevue/inputgroupaddon",export:"default",filePath:"primevue/inputgroupaddon",global:true},{name:"InputIcon",as:"InputIcon",from:"primevue/inputicon",export:"default",filePath:"primevue/inputicon",global:true},{name:"InputMask",as:"InputMask",from:"primevue/inputmask",export:"default",filePath:"primevue/inputmask",global:true},{name:"InputNumber",as:"InputNumber",from:"primevue/inputnumber",export:"default",filePath:"primevue/inputnumber",global:true},{name:"InputOtp",as:"InputOtp",from:"primevue/inputotp",export:"default",filePath:"primevue/inputotp",global:true},{name:"InputSwitch",as:"InputSwitch",from:"primevue/inputswitch",export:"default",filePath:"primevue/inputswitch",global:true},{name:"InputText",as:"InputText",from:"primevue/inputtext",export:"default",filePath:"primevue/inputtext",global:true},{name:"Knob",as:"Knob",from:"primevue/knob",export:"default",filePath:"primevue/knob",global:true},{name:"Listbox",as:"Listbox",from:"primevue/listbox",export:"default",filePath:"primevue/listbox",global:true},{name:"MultiSelect",as:"MultiSelect",from:"primevue/multiselect",export:"default",filePath:"primevue/multiselect",global:true},{name:"Password",as:"Password",from:"primevue/password",export:"default",filePath:"primevue/password",global:true},{name:"RadioButton",as:"RadioButton",from:"primevue/radiobutton",export:"default",filePath:"primevue/radiobutton",global:true},{name:"Rating",as:"Rating",from:"primevue/rating",export:"default",filePath:"primevue/rating",global:true},{name:"SelectButton",as:"SelectButton",from:"primevue/selectbutton",export:"default",filePath:"primevue/selectbutton",global:true},{name:"Slider",as:"Slider",from:"primevue/slider",export:"default",filePath:"primevue/slider",global:true},{name:"Textarea",as:"Textarea",from:"primevue/textarea",export:"default",filePath:"primevue/textarea",global:true},{name:"ToggleButton",as:"ToggleButton",from:"primevue/togglebutton",export:"default",filePath:"primevue/togglebutton",global:true},{name:"TreeSelect",as:"TreeSelect",from:"primevue/treeselect",export:"default",filePath:"primevue/treeselect",global:true},{name:"TriStateCheckbox",as:"TriStateCheckbox",from:"primevue/tristatecheckbox",export:"default",filePath:"primevue/tristatecheckbox",global:true},{name:"Button",as:"Button",from:"primevue/button",export:"default",filePath:"primevue/button",global:true},{name:"ButtonGroup",as:"ButtonGroup",from:"primevue/buttongroup",export:"default",filePath:"primevue/buttongroup",global:true},{name:"SpeedDial",as:"SpeedDial",from:"primevue/speeddial",export:"default",filePath:"primevue/speeddial",global:true},{name:"SplitButton",as:"SplitButton",from:"primevue/splitbutton",export:"default",filePath:"primevue/splitbutton",global:true},{name:"Column",as:"Column",from:"primevue/column",export:"default",filePath:"primevue/column",global:true},{name:"Row",as:"Row",from:"primevue/row",export:"default",filePath:"primevue/row",global:true},{name:"ColumnGroup",as:"ColumnGroup",from:"primevue/columngroup",export:"default",filePath:"primevue/columngroup",global:true},{name:"DataTable",as:"DataTable",from:"primevue/datatable",export:"default",filePath:"primevue/datatable",global:true},{name:"DataView",as:"DataView",from:"primevue/dataview",export:"default",filePath:"primevue/dataview",global:true},{name:"DataViewLayoutOptions",as:"DataViewLayoutOptions",from:"primevue/dataviewlayoutoptions",export:"default",filePath:"primevue/dataviewlayoutoptions",global:true},{name:"OrderList",as:"OrderList",from:"primevue/orderlist",export:"Line truncated
|
||||
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html><html><head><style type="text/css" data-primevue-style-id="layer-order" >@layer tailwind-base, primevue, tailwind-utilities</style><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link id="theme-css" rel="stylesheet" type="text/css" href="/dashboard/themes/lara-dark-green/theme.css">
|
||||
<link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico">
|
||||
<link rel="stylesheet" href="/dashboard/_nuxt/entry.CdRyF6M1.css">
|
||||
<link rel="modulepreload" as="script" crossorigin href="/dashboard/_nuxt/CdAotn7S.js">
|
||||
<link rel="prefetch" as="image" type="image/svg+xml" href="/dashboard/_nuxt/primeicons.BubJZjaf.svg">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ccJKIdck.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dbq0hxqO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DxKOBqhC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/AdkLG1re.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BO3ltiFH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CYhL7ix_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BwlcA3rq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiBqmW71.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/eLdOjEri.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIoHdha8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIUw7GKS.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3XiIAJo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDd6n_m5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1Sip8Hx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DJsXWhIp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dh-ZHPbY.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CQay6pFc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B1YYYcwB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DtEiWfmc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0KS7mWPU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DfRs6WFy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/4TRLVPYt.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DUyMz6Kq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B3yzUv7e.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cs_e0Jyg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D12jMld0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DFD6ABtc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DpxAcOXA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BnZbcMaK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BbTUXNRy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtwAl4SI.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CzF1vgty.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/RtM6PxTR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DREobrkF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIpALR7x.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CXYhB39H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8DP3eJmh.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cfpwp2_y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DqnHOBMx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BsAQV9Bu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/gJ3REwVq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/APAbiAbl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/TBrkteSm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C_oNyt3I.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1XkA2bf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BJhSZnhn.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/By-HpsnP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CpdXuDKl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ml1zUTb3.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2QbcHjol.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ca08GESE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D9bLrmuX.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CUo_zosT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DLaX2Rc0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D07-QKFk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/92NHSphk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CIQNJf2Q.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BlMMx3ZO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BiToFvXy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBPkAxhp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BMxgtM-u.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DMn_A95H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CM_CX4UR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1z1il7n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DnVQIBe4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cz8bw1cb.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ct0vUmX9.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/v19YZAG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CCyJ2OIf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DlrEeELo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B_-yrHFp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/G6CMuSbq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CSwvDmSR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DGtckhjV.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CW7WdM7z.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BybkDDc2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/tvJRpBit.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cysexb6G.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CfQfmr4y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDsMXgj0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DQrDif0P.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2nNxFeOi.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ChuxxnpQ.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYme1kum.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBo9fE9b.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/vromkmgO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DR_5D5CK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DdA0oWG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBmLef7_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BhprPxR2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/KLlBvxGE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ot8uXRrF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/qf2Wnj4S.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiZTV4zm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/1mD_0Gmg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DaK9vsnd.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hZ0eYskP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYT2DC_F.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BC5yIRjL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNgtVCIx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0Qz0KUbT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DSb3mYm4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNQ0gqHD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BDkUdWus.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cdm8H2oy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bxn3h1eA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D7pGaQXu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BFoAkamz.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hRxDLgWo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/W_LTasvG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BXW9ULDT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/9hnJxdZr.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtAnjVGO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/rOp_cn8n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/O1ZEMdSv.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D5rPsEXk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D3ktpMNC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bg_obesD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DPrOADBq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3-WSoLU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BK_1YlQG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DrPPGdq8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8VT3ACce.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CqsZXHTj.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DiD3_pIL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BuAsgUvH.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/useServerStore.DWEvhDiM.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1Y5pYTB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B7MMdMyR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C0K2Sjq5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/fmRlOMwp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/uEiA7KRH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B4IxZQIs.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DyMztKbV.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-404.JekaaCis.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bub0TpVl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DISPJkjY.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-500.CNP9nqm1.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CMeAQMKa.js">
|
||||
<script type="module" src="/dashboard/_nuxt/CdAotn7S.js" crossorigin></script>
|
||||
<script id="unhead:payload" type="application/json">{"title":"Dashboard | WAHA"}</script><style type="text/css" data-primevue-style-id="base" >
|
||||
.p-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-hidden-accessible input,
|
||||
.p-hidden-accessible select {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-overflow-hidden {
|
||||
overflow: hidden;
|
||||
padding-right: var(--scrollbar-width);
|
||||
}
|
||||
</style><style type="text/css" data-primevue-style-id="virtualscroller" >
|
||||
@layer primevue {
|
||||
.p-virtualscroller {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
will-change: scroll-position;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.p-virtualscroller-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* contain: content; */
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-virtualscroller-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
transform-origin: 0 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-virtualscroller .p-virtualscroller-loader {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loader.p-component-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon.p-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-horizontal > .p-virtualscroller-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Inline */
|
||||
.p-virtualscroller-inline .p-virtualscroller-content {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
|
||||
<script>window.__NUXT__={};window.__NUXT__.config={public:{primevue:{usePrimeVue:true,resolvePath:"",cssLayerOrder:"tailwind-base, primevue, tailwind-utilities",importPT:"",options:{ripple:true},components:[{name:"AutoComplete",as:"AutoComplete",from:"primevue/autocomplete",export:"default",filePath:"primevue/autocomplete",global:true},{name:"Calendar",as:"Calendar",from:"primevue/calendar",export:"default",filePath:"primevue/calendar",global:true},{name:"CascadeSelect",as:"CascadeSelect",from:"primevue/cascadeselect",export:"default",filePath:"primevue/cascadeselect",global:true},{name:"Checkbox",as:"Checkbox",from:"primevue/checkbox",export:"default",filePath:"primevue/checkbox",global:true},{name:"Chips",as:"Chips",from:"primevue/chips",export:"default",filePath:"primevue/chips",global:true},{name:"ColorPicker",as:"ColorPicker",from:"primevue/colorpicker",export:"default",filePath:"primevue/colorpicker",global:true},{name:"Dropdown",as:"Dropdown",from:"primevue/dropdown",export:"default",filePath:"primevue/dropdown",global:true},{name:"FloatLabel",as:"FloatLabel",from:"primevue/floatlabel",export:"default",filePath:"primevue/floatlabel",global:true},{name:"IconField",as:"IconField",from:"primevue/iconfield",export:"default",filePath:"primevue/iconfield",global:true},{name:"InputGroup",as:"InputGroup",from:"primevue/inputgroup",export:"default",filePath:"primevue/inputgroup",global:true},{name:"InputGroupAddon",as:"InputGroupAddon",from:"primevue/inputgroupaddon",export:"default",filePath:"primevue/inputgroupaddon",global:true},{name:"InputIcon",as:"InputIcon",from:"primevue/inputicon",export:"default",filePath:"primevue/inputicon",global:true},{name:"InputMask",as:"InputMask",from:"primevue/inputmask",export:"default",filePath:"primevue/inputmask",global:true},{name:"InputNumber",as:"InputNumber",from:"primevue/inputnumber",export:"default",filePath:"primevue/inputnumber",global:true},{name:"InputOtp",as:"InputOtp",from:"primevue/inputotp",export:"default",filePath:"primevue/inputotp",global:true},{name:"InputSwitch",as:"InputSwitch",from:"primevue/inputswitch",export:"default",filePath:"primevue/inputswitch",global:true},{name:"InputText",as:"InputText",from:"primevue/inputtext",export:"default",filePath:"primevue/inputtext",global:true},{name:"Knob",as:"Knob",from:"primevue/knob",export:"default",filePath:"primevue/knob",global:true},{name:"Listbox",as:"Listbox",from:"primevue/listbox",export:"default",filePath:"primevue/listbox",global:true},{name:"MultiSelect",as:"MultiSelect",from:"primevue/multiselect",export:"default",filePath:"primevue/multiselect",global:true},{name:"Password",as:"Password",from:"primevue/password",export:"default",filePath:"primevue/password",global:true},{name:"RadioButton",as:"RadioButton",from:"primevue/radiobutton",export:"default",filePath:"primevue/radiobutton",global:true},{name:"Rating",as:"Rating",from:"primevue/rating",export:"default",filePath:"primevue/rating",global:true},{name:"SelectButton",as:"SelectButton",from:"primevue/selectbutton",export:"default",filePath:"primevue/selectbutton",global:true},{name:"Slider",as:"Slider",from:"primevue/slider",export:"default",filePath:"primevue/slider",global:true},{name:"Textarea",as:"Textarea",from:"primevue/textarea",export:"default",filePath:"primevue/textarea",global:true},{name:"ToggleButton",as:"ToggleButton",from:"primevue/togglebutton",export:"default",filePath:"primevue/togglebutton",global:true},{name:"TreeSelect",as:"TreeSelect",from:"primevue/treeselect",export:"default",filePath:"primevue/treeselect",global:true},{name:"TriStateCheckbox",as:"TriStateCheckbox",from:"primevue/tristatecheckbox",export:"default",filePath:"primevue/tristatecheckbox",global:true},{name:"Button",as:"Button",from:"primevue/button",export:"default",filePath:"primevue/button",global:true},{name:"ButtonGroup",as:"ButtonGroup",from:"primevue/buttongroup",export:"default",filePath:"primevue/buttongroup",global:true},{name:"SpeedDial",as:"SpeedDial",from:"primevue/speeddial",export:"default",filePath:"primevue/speeddial",global:true},{name:"SplitButton",as:"SplitButton",from:"primevue/splitbutton",export:"default",filePath:"primevue/splitbutton",global:true},{name:"Column",as:"Column",from:"primevue/column",export:"default",filePath:"primevue/column",global:true},{name:"Row",as:"Row",from:"primevue/row",export:"default",filePath:"primevue/row",global:true},{name:"ColumnGroup",as:"ColumnGroup",from:"primevue/columngroup",export:"default",filePath:"primevue/columngroup",global:true},{name:"DataTable",as:"DataTable",from:"primevue/datatable",export:"default",filePath:"primevue/datatable",global:true},{name:"DataView",as:"DataView",from:"primevue/dataview",export:"default",filePath:"primevue/dataview",global:true},{name:"DataViewLayoutOptions",as:"DataViewLayoutOptions",from:"primevue/dataviewlayoutoptions",export:"default",filePath:"primevue/dataviewlayoutoptions",global:true},{name:"OrderList",as:"OrderList",from:"primevue/orderlist",export:"Line truncated
|
||||
@@ -1,234 +0,0 @@
|
||||
<!DOCTYPE html><html><head><style type="text/css" data-primevue-style-id="layer-order" >@layer tailwind-base, primevue, tailwind-utilities</style><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard | WAHA</title>
|
||||
<link id="theme-css" rel="stylesheet" type="text/css" href="/dashboard/themes/lara-dark-green/theme.css">
|
||||
<link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico">
|
||||
<link rel="stylesheet" href="/dashboard/_nuxt/entry.CdRyF6M1.css">
|
||||
<link rel="modulepreload" as="script" crossorigin href="/dashboard/_nuxt/CdAotn7S.js">
|
||||
<link rel="prefetch" as="image" type="image/svg+xml" href="/dashboard/_nuxt/primeicons.BubJZjaf.svg">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ccJKIdck.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dbq0hxqO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DxKOBqhC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/AdkLG1re.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BO3ltiFH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CYhL7ix_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BwlcA3rq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiBqmW71.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/eLdOjEri.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIoHdha8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIUw7GKS.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3XiIAJo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDd6n_m5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1Sip8Hx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DJsXWhIp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Dh-ZHPbY.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CQay6pFc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B1YYYcwB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DtEiWfmc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0KS7mWPU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DfRs6WFy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/4TRLVPYt.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DUyMz6Kq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B3yzUv7e.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cs_e0Jyg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D12jMld0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DFD6ABtc.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DpxAcOXA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BnZbcMaK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BbTUXNRy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtwAl4SI.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CzF1vgty.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/RtM6PxTR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DREobrkF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BIpALR7x.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CXYhB39H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8DP3eJmh.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cfpwp2_y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DqnHOBMx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BsAQV9Bu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/gJ3REwVq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/APAbiAbl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/TBrkteSm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C_oNyt3I.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D1XkA2bf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BJhSZnhn.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/By-HpsnP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CpdXuDKl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ml1zUTb3.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2QbcHjol.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ca08GESE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D9bLrmuX.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CUo_zosT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DLaX2Rc0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D07-QKFk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/92NHSphk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CIQNJf2Q.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BlMMx3ZO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BiToFvXy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBPkAxhp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BMxgtM-u.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DMn_A95H.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CM_CX4UR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1z1il7n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DnVQIBe4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cz8bw1cb.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ct0vUmX9.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/v19YZAG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CCyJ2OIf.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DlrEeELo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B_-yrHFp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/G6CMuSbq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CSwvDmSR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DGtckhjV.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CW7WdM7z.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BybkDDc2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/tvJRpBit.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cysexb6G.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CfQfmr4y.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DDsMXgj0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DQrDif0P.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/2nNxFeOi.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/ChuxxnpQ.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYme1kum.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBo9fE9b.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/vromkmgO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DR_5D5CK.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DdA0oWG0.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CBmLef7_.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BhprPxR2.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/KLlBvxGE.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Ot8uXRrF.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/qf2Wnj4S.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CiZTV4zm.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/1mD_0Gmg.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DaK9vsnd.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hZ0eYskP.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DYT2DC_F.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BC5yIRjL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNgtVCIx.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/0Qz0KUbT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DSb3mYm4.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BNQ0gqHD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BDkUdWus.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Cdm8H2oy.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bxn3h1eA.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D7pGaQXu.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BFoAkamz.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/hRxDLgWo.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/W_LTasvG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BXW9ULDT.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/9hnJxdZr.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BtAnjVGO.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/rOp_cn8n.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/O1ZEMdSv.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D5rPsEXk.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/D3ktpMNC.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bg_obesD.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DPrOADBq.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C3-WSoLU.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BK_1YlQG.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DrPPGdq8.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/8VT3ACce.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CqsZXHTj.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DiD3_pIL.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/BuAsgUvH.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/useServerStore.DWEvhDiM.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C1Y5pYTB.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B7MMdMyR.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/C0K2Sjq5.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/fmRlOMwp.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/uEiA7KRH.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/B4IxZQIs.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DyMztKbV.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-404.JekaaCis.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/Bub0TpVl.js">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/DISPJkjY.js">
|
||||
<link rel="prefetch" as="style" href="/dashboard/_nuxt/error-500.CNP9nqm1.css">
|
||||
<link rel="prefetch" as="script" crossorigin href="/dashboard/_nuxt/CMeAQMKa.js">
|
||||
<script type="module" src="/dashboard/_nuxt/CdAotn7S.js" crossorigin></script>
|
||||
<script id="unhead:payload" type="application/json">{"title":"Dashboard | WAHA"}</script><style type="text/css" data-primevue-style-id="base" >
|
||||
.p-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.p-hidden-accessible input,
|
||||
.p-hidden-accessible select {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.p-overflow-hidden {
|
||||
overflow: hidden;
|
||||
padding-right: var(--scrollbar-width);
|
||||
}
|
||||
</style><style type="text/css" data-primevue-style-id="virtualscroller" >
|
||||
@layer primevue {
|
||||
.p-virtualscroller {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
transform: translateZ(0);
|
||||
will-change: scroll-position;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.p-virtualscroller-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* contain: content; */
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.p-virtualscroller-spacer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
transform-origin: 0 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-virtualscroller .p-virtualscroller-loader {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loader.p-component-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-loading-icon.p-icon {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.p-virtualscroller-horizontal > .p-virtualscroller-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Inline */
|
||||
.p-virtualscroller-inline .p-virtualscroller-content {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
|
||||
<script>window.__NUXT__={};window.__NUXT__.config={public:{primevue:{usePrimeVue:true,resolvePath:"",cssLayerOrder:"tailwind-base, primevue, tailwind-utilities",importPT:"",options:{ripple:true},components:[{name:"AutoComplete",as:"AutoComplete",from:"primevue/autocomplete",export:"default",filePath:"primevue/autocomplete",global:true},{name:"Calendar",as:"Calendar",from:"primevue/calendar",export:"default",filePath:"primevue/calendar",global:true},{name:"CascadeSelect",as:"CascadeSelect",from:"primevue/cascadeselect",export:"default",filePath:"primevue/cascadeselect",global:true},{name:"Checkbox",as:"Checkbox",from:"primevue/checkbox",export:"default",filePath:"primevue/checkbox",global:true},{name:"Chips",as:"Chips",from:"primevue/chips",export:"default",filePath:"primevue/chips",global:true},{name:"ColorPicker",as:"ColorPicker",from:"primevue/colorpicker",export:"default",filePath:"primevue/colorpicker",global:true},{name:"Dropdown",as:"Dropdown",from:"primevue/dropdown",export:"default",filePath:"primevue/dropdown",global:true},{name:"FloatLabel",as:"FloatLabel",from:"primevue/floatlabel",export:"default",filePath:"primevue/floatlabel",global:true},{name:"IconField",as:"IconField",from:"primevue/iconfield",export:"default",filePath:"primevue/iconfield",global:true},{name:"InputGroup",as:"InputGroup",from:"primevue/inputgroup",export:"default",filePath:"primevue/inputgroup",global:true},{name:"InputGroupAddon",as:"InputGroupAddon",from:"primevue/inputgroupaddon",export:"default",filePath:"primevue/inputgroupaddon",global:true},{name:"InputIcon",as:"InputIcon",from:"primevue/inputicon",export:"default",filePath:"primevue/inputicon",global:true},{name:"InputMask",as:"InputMask",from:"primevue/inputmask",export:"default",filePath:"primevue/inputmask",global:true},{name:"InputNumber",as:"InputNumber",from:"primevue/inputnumber",export:"default",filePath:"primevue/inputnumber",global:true},{name:"InputOtp",as:"InputOtp",from:"primevue/inputotp",export:"default",filePath:"primevue/inputotp",global:true},{name:"InputSwitch",as:"InputSwitch",from:"primevue/inputswitch",export:"default",filePath:"primevue/inputswitch",global:true},{name:"InputText",as:"InputText",from:"primevue/inputtext",export:"default",filePath:"primevue/inputtext",global:true},{name:"Knob",as:"Knob",from:"primevue/knob",export:"default",filePath:"primevue/knob",global:true},{name:"Listbox",as:"Listbox",from:"primevue/listbox",export:"default",filePath:"primevue/listbox",global:true},{name:"MultiSelect",as:"MultiSelect",from:"primevue/multiselect",export:"default",filePath:"primevue/multiselect",global:true},{name:"Password",as:"Password",from:"primevue/password",export:"default",filePath:"primevue/password",global:true},{name:"RadioButton",as:"RadioButton",from:"primevue/radiobutton",export:"default",filePath:"primevue/radiobutton",global:true},{name:"Rating",as:"Rating",from:"primevue/rating",export:"default",filePath:"primevue/rating",global:true},{name:"SelectButton",as:"SelectButton",from:"primevue/selectbutton",export:"default",filePath:"primevue/selectbutton",global:true},{name:"Slider",as:"Slider",from:"primevue/slider",export:"default",filePath:"primevue/slider",global:true},{name:"Textarea",as:"Textarea",from:"primevue/textarea",export:"default",filePath:"primevue/textarea",global:true},{name:"ToggleButton",as:"ToggleButton",from:"primevue/togglebutton",export:"default",filePath:"primevue/togglebutton",global:true},{name:"TreeSelect",as:"TreeSelect",from:"primevue/treeselect",export:"default",filePath:"primevue/treeselect",global:true},{name:"TriStateCheckbox",as:"TriStateCheckbox",from:"primevue/tristatecheckbox",export:"default",filePath:"primevue/tristatecheckbox",global:true},{name:"Button",as:"Button",from:"primevue/button",export:"default",filePath:"primevue/button",global:true},{name:"ButtonGroup",as:"ButtonGroup",from:"primevue/buttongroup",export:"default",filePath:"primevue/buttongroup",global:true},{name:"SpeedDial",as:"SpeedDial",from:"primevue/speeddial",export:"default",filePath:"primevue/speeddial",global:true},{name:"SplitButton",as:"SplitButton",from:"primevue/splitbutton",export:"default",filePath:"primevue/splitbutton",global:true},{name:"Column",as:"Column",from:"primevue/column",export:"default",filePath:"primevue/column",global:true},{name:"Row",as:"Row",from:"primevue/row",export:"default",filePath:"primevue/row",global:true},{name:"ColumnGroup",as:"ColumnGroup",from:"primevue/columngroup",export:"default",filePath:"primevue/columngroup",global:true},{name:"DataTable",as:"DataTable",from:"primevue/datatable",export:"default",filePath:"primevue/datatable",global:true},{name:"DataView",as:"DataView",from:"primevue/dataview",export:"default",filePath:"primevue/dataview",global:true},{name:"DataViewLayoutOptions",as:"DataViewLayoutOptions",from:"primevue/dataviewlayoutoptions",export:"default",filePath:"primevue/dataviewlayoutoptions",global:true},{name:"OrderList",as:"OrderList",from:"primevue/orderlist",export:"Line truncated
|
||||
@@ -1,3 +0,0 @@
|
||||
import{s as k}from"./CiBqmW71.js";import{a3 as O,a5 as w,t as c,v as m,x as p,N as C,Q as S,aa as u,Y as b,y as V,W as g,P as B,ab as x}from"./CdAotn7S.js";import{s as A}from"./AdkLG1re.js";import"./CYhL7ix_.js";var P={root:function(t){var n=t.instance,r=t.props;return["p-chips p-component p-inputwrapper",{"p-disabled":r.disabled,"p-invalid":r.invalid,"p-focus":n.focused,"p-inputwrapper-filled":r.modelValue&&r.modelValue.length||n.inputValue&&n.inputValue.length,"p-inputwrapper-focus":n.focused}]},container:function(t){var n=t.props,r=t.instance;return["p-inputtext p-chips-multiple-container",{"p-variant-filled":n.variant?n.variant==="filled":r.$primevue.config.inputStyle==="filled"}]},token:function(t){var n=t.state,r=t.index;return["p-chips-token",{"p-focus":n.focusedIndex===r}]},label:"p-chips-token-label",removeTokenIcon:"p-chips-token-icon",inputToken:"p-chips-input-token"},K=O.extend({name:"chips",classes:P}),D={name:"BaseChips",extends:A,props:{modelValue:{type:Array,default:null},max:{type:Number,default:null},separator:{type:[String,Object],default:null},addOnBlur:{type:Boolean,default:null},allowDuplicate:{type:Boolean,default:!0},placeholder:{type:String,default:null},variant:{type:String,default:null},invalid:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},inputId:{type:String,default:null},inputClass:{type:[String,Object],default:null},inputStyle:{type:Object,default:null},inputProps:{type:null,default:null},removeTokenIcon:{type:String,default:void 0},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:K,provide:function(){return{$parentInstance:this}}};function f(e){return L(e)||F(e)||j(e)||T()}function T(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function j(e,t){if(e){if(typeof e=="string")return h(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if(n==="Object"&&e.constructor&&(n=e.constructor.name),n==="Map"||n==="Set")return Array.from(e);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return h(e,t)}}function F(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}function L(e){if(Array.isArray(e))return h(e)}function h(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var E={name:"Chips",extends:D,inheritAttrs:!1,emits:["update:modelValue","add","remove","focus","blur"],data:function(){return{id:this.$attrs.id,inputValue:null,focused:!1,focusedIndex:null}},watch:{"$attrs.id":{immediate:!0,handler:function(t){this.id=t||w()}}},methods:{onWrapperClick:function(){this.$refs.input.focus()},onInput:function(t){this.inputValue=t.target.value,this.focusedIndex=null},onFocus:function(t){this.focused=!0,this.focusedIndex=null,this.$emit("focus",t)},onBlur:function(t){this.focused=!1,this.focusedIndex=null,this.addOnBlur&&this.addItem(t,t.target.value,!1),this.$emit("blur",t)},onKeyDown:function(t){var n=t.target.value;switch(t.code){case"Backspace":n.length===0&&this.modelValue&&this.modelValue.length>0&&(this.focusedIndex!==null?this.removeItem(t,this.focusedIndex):this.removeItem(t,this.modelValue.length-1));break;case"Enter":case"NumpadEnter":n&&n.trim().length&&!this.maxedOut&&this.addItem(t,n,!0);break;case"ArrowLeft":n.length===0&&this.modelValue&&this.modelValue.length>0&&this.$refs.container.focus();break;case"ArrowRight":t.stopPropagation();break;default:this.separator&&(this.separator===t.key||t.key.match(this.separator))&&this.addItem(t,n,!0);break}},onPaste:function(t){var n=this;if(this.separator){var r=this.separator.replace("\\n",`
|
||||
`).replace("\\r","\r").replace("\\t"," "),i=(t.clipboardData||window.clipboardData).getData("Text");if(i){var o=this.modelValue||[],a=i.split(r);a=a.filter(function(l){return n.allowDuplicate||o.indexOf(l)===-1}),o=[].concat(f(o),f(a)),this.updateModel(t,o,!0)}}},onContainerFocus:function(){this.focused=!0},onContainerBlur:function(){this.focusedIndex=-1,this.focused=!1},onContainerKeyDown:function(t){switch(t.code){case"ArrowLeft":this.onArrowLeftKeyOn(t);break;case"ArrowRight":this.onArrowRightKeyOn(t);break;case"Backspace":this.onBackspaceKeyOn(t);break}},onArrowLeftKeyOn:function(){this.inputValue.length===0&&this.modelValue&&this.modelValue.length>0&&(this.focusedIndex=this.focusedIndex===null?this.modelValue.length-1:this.focusedIndex-1,this.focusedIndex<0&&(this.focusedIndex=0))},onArrowRightKeyOn:function(){this.inputValue.length===0&&this.modelValue&&this.modelValue.length>0&&(this.focusedIndex===this.modelValue.length-1?(this.focusedIndex=null,this.$refs.input.focus()):this.focusedIndex++)},onBackspaceKeyOn:function(t){this.focusedIndex!==null&&this.removeItem(t,this.focusedIndex)},updateModel:function(t,n,r){var i=this;this.$emit("update:modelValue",n),this.$emit("add",{originalEvent:t,value:n}),this.$refs.input.value="",this.inputValue="",setTimeout(function(){i.maxedOut&&(i.focused=!1)},0),r&&t.preventDefault()},addItem:function(t,n,r){if(n&&n.trim().length){var i=this.modelValue?f(this.modelValue):[];(this.allowDuplicate||i.indexOf(n)===-1)&&(i.push(n),this.updateModel(t,i,r))}},removeItem:function(t,n){if(!this.disabled){var r=f(this.modelValue),i=r.splice(n,1);this.focusedIndex=null,this.$refs.input.focus(),this.$emit("update:modelValue",r),this.$emit("remove",{originalEvent:t,value:i})}}},computed:{maxedOut:function(){return this.max&&this.modelValue&&this.max===this.modelValue.length},focusedOptionId:function(){return this.focusedIndex!==null?"".concat(this.id,"_chips_item_").concat(this.focusedIndex):null}},components:{TimesCircleIcon:k}};function d(e){"@babel/helpers - typeof";return d=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},d(e)}function v(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(e,i).enumerable})),n.push.apply(n,r)}return n}function I(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?v(Object(n),!0).forEach(function(r){M(e,r,n[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):v(Object(n)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))})}return e}function M(e,t,n){return t=N(t),t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function N(e){var t=R(e,"string");return d(t)=="symbol"?t:String(t)}function R(e,t){if(d(e)!="object"||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||"default");if(d(r)!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}var W=["aria-labelledby","aria-label","aria-activedescendant"],z=["id","aria-label","aria-setsize","aria-posinset","data-p-focused"],U=["id","disabled","placeholder","aria-invalid"];function q(e,t,n,r,i,o){return c(),m("div",u({class:e.cx("root")},e.ptmi("root")),[p("ul",u({ref:"container",class:e.cx("container"),tabindex:"-1",role:"listbox","aria-orientation":"horizontal","aria-labelledby":e.ariaLabelledby,"aria-label":e.ariaLabel,"aria-activedescendant":i.focused?o.focusedOptionId:void 0,onClick:t[5]||(t[5]=function(a){return o.onWrapperClick()}),onFocus:t[6]||(t[6]=function(){return o.onContainerFocus&&o.onContainerFocus.apply(o,arguments)}),onBlur:t[7]||(t[7]=function(){return o.onContainerBlur&&o.onContainerBlur.apply(o,arguments)}),onKeydown:t[8]||(t[8]=function(){return o.onContainerKeyDown&&o.onContainerKeyDown.apply(o,arguments)})},e.ptm("container")),[(c(!0),m(C,null,S(e.modelValue,function(a,l){return c(),m("li",u({key:"".concat(l,"_").concat(a),id:i.id+"_chips_item_"+l,role:"option",class:e.cx("token",{index:l}),"aria-label":a,"aria-selected":!0,"aria-setsize":e.modelValue.length,"aria-posinset":l+1},e.ptm("token"),{"data-p-focused":i.focusedIndex===l}),[b(e.$slots,"chip",{class:g(e.cx("label")),value:a},function(){return[p("span",u({class:e.cx("label")},e.ptm("label")),V(a),17)]}),b(e.$slots,"removetokenicon",{class:g(e.cx("removeTokenIcon")),index:l,onClick:function(s){return o.removeItem(s,l)},removeCallback:function(s){return o.removeItem(s,l)}},function(){return[(c(),B(x(e.removeTokenIcon?"span":"TimesCircleIcon"),u({class:[e.cx("removeTokenIcon"),e.removeTokenIcon],onClick:function(s){return o.removeItem(s,l)},"aria-hidden":"true"},e.ptm("removeTokenIcon")),null,16,["class","onClick"]))]}
Line truncated
|
||||
@@ -1,2 +0,0 @@
|
||||
import{O as P}from"./eLdOjEri.js";import{s as K}from"./BIoHdha8.js";import{a3 as T,a5 as z,a6 as g,a7 as o,a8 as D,a4 as H,aa as l,a9 as V,Z as F,t as r,v as d,x as O,$ as B,P as b,W as R,ab as L,O as f,y as M,i as x,A as C,z as N,ac as U,Y as I,N as h,Q as w,B as Z}from"./CdAotn7S.js";import{s as A}from"./AdkLG1re.js";var W={root:function(e){var i=e.instance,s=e.props;return["p-menu p-component",{"p-menu-overlay":s.popup,"p-ripple-disabled":i.$primevue.config.ripple===!1}]},start:"p-menu-start",menu:"p-menu-list p-reset",submenuHeader:"p-submenu-header",separator:"p-menuitem-separator",end:"p-menu-end",menuitem:function(e){var i=e.instance;return["p-menuitem",{"p-focus":i.id===i.focusedOptionId,"p-disabled":i.disabled()}]},content:"p-menuitem-content",action:"p-menuitem-link",icon:"p-menuitem-icon",label:"p-menuitem-text"},j=T.extend({name:"menu",classes:W}),q={name:"BaseMenu",extends:A,props:{popup:{type:Boolean,default:!1},model:{type:Array,default:null},appendTo:{type:[String,Object],default:"body"},autoZIndex:{type:Boolean,default:!0},baseZIndex:{type:Number,default:0},tabindex:{type:Number,default:0},ariaLabel:{type:String,default:null},ariaLabelledby:{type:String,default:null}},style:j,provide:function(){return{$parentInstance:this}}},E={name:"Menuitem",hostName:"Menu",extends:A,inheritAttrs:!1,emits:["item-click","item-mousemove"],props:{item:null,templates:null,id:null,focusedOptionId:null,index:null},methods:{getItemProp:function(e,i){return e&&e.item?H.getItemValue(e.item[i]):void 0},getPTOptions:function(e){return this.ptm(e,{context:{item:this.item,index:this.index,focused:this.isItemFocused(),disabled:this.disabled()}})},isItemFocused:function(){return this.focusedOptionId===this.id},onItemClick:function(e){var i=this.getItemProp(this.item,"command");i&&i({originalEvent:e,item:this.item.item}),this.$emit("item-click",{originalEvent:e,item:this.item,id:this.id})},onItemMouseMove:function(e){this.$emit("item-mousemove",{originalEvent:e,item:this.item,id:this.id})},visible:function(){return typeof this.item.visible=="function"?this.item.visible():this.item.visible!==!1},disabled:function(){return typeof this.item.disabled=="function"?this.item.disabled():this.item.disabled},label:function(){return typeof this.item.label=="function"?this.item.label():this.item.label},getMenuItemProps:function(e){return{action:l({class:this.cx("action"),tabindex:"-1","aria-hidden":!0},this.getPTOptions("action")),icon:l({class:[this.cx("icon"),e.icon]},this.getPTOptions("icon")),label:l({class:this.cx("label")},this.getPTOptions("label"))}}},directives:{ripple:V}},Q=["id","aria-label","aria-disabled","data-p-focused","data-p-disabled"],Y=["href","target"];function G(t,e,i,s,u,n){var v=F("ripple");return n.visible()?(r(),d("li",l({key:0,id:i.id,class:[t.cx("menuitem"),i.item.class],role:"menuitem",style:i.item.style,"aria-label":n.label(),"aria-disabled":n.disabled()},n.getPTOptions("menuitem"),{"data-p-focused":n.isItemFocused(),"data-p-disabled":n.disabled()||!1}),[O("div",l({class:t.cx("content"),onClick:e[0]||(e[0]=function(p){return n.onItemClick(p)}),onMousemove:e[1]||(e[1]=function(p){return n.onItemMouseMove(p)})},n.getPTOptions("content")),[i.templates.item?i.templates.item?(r(),b(L(i.templates.item),{key:1,item:i.item,label:n.label(),props:n.getMenuItemProps(i.item)},null,8,["item","label","props"])):f("",!0):B((r(),d("a",l({key:0,href:i.item.url,class:t.cx("action"),target:i.item.target,tabindex:"-1","aria-hidden":"true"},n.getPTOptions("action")),[i.templates.itemicon?(r(),b(L(i.templates.itemicon),{key:0,item:i.item,class:R(t.cx("icon"))},null,8,["item","class"])):i.item.icon?(r(),d("span",l({key:1,class:[t.cx("icon"),i.item.icon]},n.getPTOptions("icon")),null,16)):f("",!0),O("span",l({class:t.cx("label")},n.getPTOptions("label")),M(n.label()),17)],16,Y)),[[v]])],16)],16,Q)):f("",!0)}E.render=G;function S(t){return $(t)||_(t)||X(t)||J()}function J(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function X(t,e){if(t){if(typeof t=="string")return k(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);if(i==="Object"&&t.constructor&&(i=t.constructor.name),i==="Map"||i==="Set")return Array.from(t);if(i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i))return k(t,e)}}function _(t){if(typeof Symbol<"u"&&t[Symbol.iterator]!=null||t["@@iterator"]!=null)return Array.from(t)}function $(t){if(Array.isArray(t))return k(t)}function k(t,e){(e==null||e>t.length)&&(e=t.length);for(var i=0,s=new Array(e);i<e;i++)s[i]=t[i];return s}var ee={name:"Menu",extends:q,inheritAttrs:!1,emits:["show","hide","focus","blur"],data:function(){return{id:this.$attrs.id,overlayVisible:!1,focused:!1,focusedOptionIndex:-1,selectedOptionIndex:-1}},watch:{"$attrs.id":{immediate:!0,handler:function(e){this.id=e||z()}}},target:null,outsideClickListener:null,scrollHandler:null,resizeListener:null,container:null,list:null,mounted:function(){this.popup||(this.bindResizeListener(),this.bindOutsideClickListener())},beforeUnmount:function(){this.unbindResizeListener(),this.unbindOutsideClickListener(),this.scrollHandler&&(this.scrollHandler.destroy(),this.scrollHandler=null),this.target=null,this.container&&this.autoZIndex&&g.clear(this.container),this.container=null},methods:{itemClick:function(e){var i=e.item;this.disabled(i)||(i.command&&i.command(e),this.overlayVisible&&this.hide(),!this.popup&&this.focusedOptionIndex!==e.id&&(this.focusedOptionIndex=e.id))},itemMouseMove:function(e){this.focused&&(this.focusedOptionIndex=e.id)},onListFocus:function(e){this.focused=!0,!this.popup&&this.changeFocusedOptionIndex(0),this.$emit("focus",e)},onListBlur:function(e){this.focused=!1,this.focusedOptionIndex=-1,this.$emit("blur",e)},onListKeyDown:function(e){switch(e.code){case"ArrowDown":this.onArrowDownKey(e);break;case"ArrowUp":this.onArrowUpKey(e);break;case"Home":this.onHomeKey(e);break;case"End":this.onEndKey(e);break;case"Enter":case"NumpadEnter":this.onEnterKey(e);break;case"Space":this.onSpaceKey(e);break;case"Escape":this.popup&&(o.focus(this.target),this.hide());case"Tab":this.overlayVisible&&this.hide();break}},onArrowDownKey:function(e){var i=this.findNextOptionIndex(this.focusedOptionIndex);this.changeFocusedOptionIndex(i),e.preventDefault()},onArrowUpKey:function(e){if(e.altKey&&this.popup)o.focus(this.target),this.hide(),e.preventDefault();else{var i=this.findPrevOptionIndex(this.focusedOptionIndex);this.changeFocusedOptionIndex(i),e.preventDefault()}},onHomeKey:function(e){this.changeFocusedOptionIndex(0),e.preventDefault()},onEndKey:function(e){this.changeFocusedOptionIndex(o.find(this.container,'li[data-pc-section="menuitem"][data-p-disabled="false"]').length-1),e.preventDefault()},onEnterKey:function(e){var i=o.findSingle(this.list,'li[id="'.concat("".concat(this.focusedOptionIndex),'"]')),s=i&&o.findSingle(i,'a[data-pc-section="action"]');this.popup&&o.focus(this.target),s?s.click():i&&i.click(),e.preventDefault()},onSpaceKey:function(e){this.onEnterKey(e)},findNextOptionIndex:function(e){var i=o.find(this.container,'li[data-pc-section="menuitem"][data-p-disabled="false"]'),s=S(i).findIndex(function(u){return u.id===e});return s>-1?s+1:0},findPrevOptionIndex:function(e){var i=o.find(this.container,'li[data-pc-section="menuitem"][data-p-disabled="false"]'),s=S(i).findIndex(function(u){return u.id===e});return s>-1?s-1:0},changeFocusedOptionIndex:function(e){var i=o.find(this.container,'li[data-pc-section="menuitem"][data-p-disabled="false"]'),s=e>=i.length?i.length-1:e<0?0:e;s>-1&&(this.focusedOptionIndex=i[s].getAttribute("id"))},toggle:function(e){this.overlayVisible?this.hide():this.show(e)},show:function(e){this.overlayVisible=!0,this.target=e.currentTarget},hide:function(){this.overlayVisible=!1,this.target=null},onEnter:function(e){o.addStyles(e,{position:"absolute",top:"0",left:"0"}),this.alignOverlay(),this.bindOutsideClickListener(),this.bindResizeListener(),this.bindScrollListener(),this.autoZIndex&&g.set("menu",e,this.baseZIndex+this.$primevue.config.zIndex.menu),this.popup&&o.focus(this.list),this.$emit("show")},onLeave:function(){this.unbindOutsideClickListener(),this.unbindResizeListener(),this.unbindScrollListener(),this.$emit("hide")},onAfterLeave:function(e){this.autoZIndex&&g.clear(e)},alignOverlay:function(){o.absolutePosition(this.container,this.target);var e=o.getOuterWidth(this.target);e>o.getOuterWidth(this.container)&&(this.container.style.minWidth=o.getOuterWidth(this.target)+"px")},bindOutsideClickListener:function(){var e=this;this.outsideClickListener||(this.outsideClickListener=function(i){var s=e.container&&!e.container.contains(i.target),u=!(e.target&&(e.target===i.target||e.target.contains(i.target)));e.overlayVisible&&s&&u?e.hide():!e.popup&&s&&u&&(e.focusedOptionIndex=-1)},document.addEventListener("click",this.outsideClickListener))},unbindOutsideClickListener:function(){this.outsideClickList
Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
import{s as f}from"./DtEiWfmc.js";import{s as y,a as b}from"./DaK9vsnd.js";import{s as P}from"./B3yzUv7e.js";import{s as d}from"./CiBqmW71.js";import{a3 as S,a9 as $,i as k,Z as B,t as i,P as u,A as C,$ as v,x as g,aa as s,Y as c,v as m,ab as j,O as D,ad as A,ac as T}from"./CdAotn7S.js";import{s as E}from"./AdkLG1re.js";import"./CYhL7ix_.js";var N={root:function(t){var o=t.props;return"p-message p-component p-message-"+o.severity},wrapper:"p-message-wrapper",icon:"p-message-icon",text:"p-message-text",closeButton:"p-message-close p-link",closeIcon:"p-message-close-icon"},L=S.extend({name:"message",classes:N}),M={name:"BaseMessage",extends:E,props:{severity:{type:String,default:"info"},closable:{type:Boolean,default:!0},sticky:{type:Boolean,default:!0},life:{type:Number,default:3e3},icon:{type:String,default:void 0},closeIcon:{type:String,default:void 0},closeButtonProps:{type:null,default:null}},style:L,provide:function(){return{$parentInstance:this}}},K={name:"Message",extends:M,inheritAttrs:!1,emits:["close","life-end"],timeout:null,data:function(){return{visible:!0}},watch:{sticky:function(t){t||this.closeAfterDelay()}},mounted:function(){this.sticky||this.closeAfterDelay()},methods:{close:function(t){this.visible=!1,this.$emit("close",t)},closeAfterDelay:function(){var t=this;setTimeout(function(){t.visible=!1,t.$emit("life-end")},this.life)}},computed:{iconComponent:function(){return{info:y,success:f,warn:b,error:d}[this.severity]},closeAriaLabel:function(){return this.$primevue.config.locale.aria?this.$primevue.config.locale.aria.close:void 0}},directives:{ripple:$},components:{TimesIcon:P,InfoCircleIcon:y,CheckIcon:f,ExclamationTriangleIcon:b,TimesCircleIcon:d}};function l(e){"@babel/helpers - typeof";return l=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},l(e)}function h(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(p){return Object.getOwnPropertyDescriptor(e,p).enumerable})),o.push.apply(o,r)}return o}function n(e){for(var t=1;t<arguments.length;t++){var o=arguments[t]!=null?arguments[t]:{};t%2?h(Object(o),!0).forEach(function(r){V(e,r,o[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):h(Object(o)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(o,r))})}return e}function V(e,t,o){return t=R(t),t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function R(e){var t=Y(e,"string");return l(t)=="symbol"?t:String(t)}function Y(e,t){if(l(e)!="object"||!e)return e;var o=e[Symbol.toPrimitive];if(o!==void 0){var r=o.call(e,t||"default");if(l(r)!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}var Z=["aria-label"];function q(e,t,o,r,p,a){var I=k("TimesIcon"),w=B("ripple");return i(),u(T,s({name:"p-message",appear:""},e.ptmi("transition")),{default:C(function(){return[v(g("div",s({class:e.cx("root"),role:"alert","aria-live":"assertive","aria-atomic":"true"},e.ptm("root")),[e.$slots.container?c(e.$slots,"container",{key:0,onClose:a.close,closeCallback:a.close}):(i(),m("div",s({key:1,class:e.cx("wrapper")},e.ptm("wrapper")),[c(e.$slots,"messageicon",{class:"p-message-icon"},function(){return[(i(),u(j(e.icon?"span":a.iconComponent),s({class:[e.cx("icon"),e.icon]},e.ptm("icon")),null,16,["class"]))]}),g("div",s({class:["p-message-text",e.cx("text")]},e.ptm("text")),[c(e.$slots,"default")],16),e.closable?v((i(),m("button",s({key:0,class:e.cx("closeButton"),"aria-label":a.closeAriaLabel,type:"button",onClick:t[0]||(t[0]=function(O){return a.close(O)})},n(n(n({},e.closeButtonProps),e.ptm("button")),e.ptm("closeButton"))),[c(e.$slots,"closeicon",{},function(){return[e.closeIcon?(i(),m("i",s({key:0,class:[e.cx("closeIcon"),e.closeIcon]},n(n({},e.ptm("buttonIcon")),e.ptm("closeIcon"))),null,16)):(i(),u(I,s({key:1,class:[e.cx("closeIcon"),e.closeIcon]},n(n({},e.ptm("buttonIcon")),e.ptm("closeIcon"))),null,16,["class"]))]})],16,Z)),[[w]]):D("",!0)],16))],16),[[A,p.visible]])]}),_:3},16)}K.render=q;export{K as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{s as r}from"./CYhL7ix_.js";import{t,v as o,aa as s,x as a}from"./CdAotn7S.js";var n={name:"MinusIcon",extends:r},i=a("path",{d:"M13.2222 7.77778H0.777778C0.571498 7.77778 0.373667 7.69584 0.227806 7.54998C0.0819442 7.40412 0 7.20629 0 7.00001C0 6.79373 0.0819442 6.5959 0.227806 6.45003C0.373667 6.30417 0.571498 6.22223 0.777778 6.22223H13.2222C13.4285 6.22223 13.6263 6.30417 13.7722 6.45003C13.9181 6.5959 14 6.79373 14 7.00001C14 7.20629 13.9181 7.40412 13.7722 7.54998C13.6263 7.69584 13.4285 7.77778 13.2222 7.77778Z",fill:"currentColor"},null,-1),p=[i];function c(e,l,d,C,h,m){return t(),o("svg",s({width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg"},e.pti()),p,16)}n.render=c;export{n as s};
|
||||
@@ -1 +0,0 @@
|
||||
import{s as r}from"./AdkLG1re.js";import{a3 as a,t as i,v as l,Y as o,aa as p}from"./CdAotn7S.js";var u={root:function(t){var n=t.instance;return["p-splitter-panel",{"p-splitter-panel-nested":n.isNested}]}},d=a.extend({name:"splitterpanel",classes:u}),c={name:"BaseSplitterPanel",extends:r,props:{size:{type:Number,default:null},minSize:{type:Number,default:null}},style:d,provide:function(){return{$parentInstance:this}}},f={name:"SplitterPanel",extends:c,inheritAttrs:!1,data:function(){return{nestedState:null}},computed:{isNested:function(){var t=this;return this.$slots.default().some(function(n){return t.nestedState=n.type.name==="Splitter"?!0:null,t.nestedState})},getPTOptions:function(){return{context:{nested:this.isNested}}}}};function m(e,t,n,S,v,s){return i(),l("div",p({ref:"container",class:e.cx("root")},e.ptmi("root",s.getPTOptions)),[o(e.$slots,"default")],16)}f.render=m;export{f as default};
|
||||
@@ -1,2 +0,0 @@
|
||||
import{t as o,v as p,aa as l,x as y,a3 as J,a5 as X,a6 as T,a4 as c,a7 as a,a8 as $,ah as _,a9 as ee,i as w,Z as te,Y as h,B as P,y as O,P as v,ab as A,W as x,O as I,z as B,A as K,ac as ie,a1 as ne,N as H,Q as re,$ as se}from"./CdAotn7S.js";import{s as le}from"./CYhL7ix_.js";import{s as oe}from"./DtEiWfmc.js";import{s as ae}from"./BwlcA3rq.js";import{s as ue}from"./DUyMz6Kq.js";import{s as de}from"./BO3ltiFH.js";import{s as ce}from"./B3yzUv7e.js";import{O as pe}from"./eLdOjEri.js";import{s as fe}from"./BIoHdha8.js";import he from"./BIUw7GKS.js";import{s as ye}from"./AdkLG1re.js";var z={name:"BlankIcon",extends:le},be=y("rect",{width:"1",height:"1",fill:"currentColor","fill-opacity":"0"},null,-1),me=[be];function ge(t,e,i,r,s,n){return o(),p("svg",l({width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg"},t.pti()),me,16)}z.render=ge;var Oe={root:function(e){var i=e.instance,r=e.props,s=e.state;return["p-dropdown p-component p-inputwrapper",{"p-disabled":r.disabled,"p-invalid":r.invalid,"p-variant-filled":r.variant?r.variant==="filled":i.$primevue.config.inputStyle==="filled","p-dropdown-clearable":r.showClear,"p-focus":s.focused,"p-inputwrapper-filled":i.hasSelectedOption,"p-inputwrapper-focus":s.focused||s.overlayVisible,"p-overlay-open":s.overlayVisible}]},input:function(e){var i,r=e.instance,s=e.props;return["p-dropdown-label p-inputtext",{"p-placeholder":!s.editable&&r.label===s.placeholder,"p-dropdown-label-empty":!s.editable&&!r.$slots.value&&(r.label==="p-emptylabel"||((i=r.label)===null||i===void 0?void 0:i.length)===0)}]},clearIcon:"p-dropdown-clear-icon",trigger:"p-dropdown-trigger",loadingicon:"p-dropdown-trigger-icon",dropdownIcon:"p-dropdown-trigger-icon",panel:function(e){e.props;var i=e.instance;return["p-dropdown-panel p-component",{"p-ripple-disabled":i.$primevue.config.ripple===!1}]},header:"p-dropdown-header",filterContainer:"p-dropdown-filter-container",filterInput:function(e){var i=e.props,r=e.instance;return["p-dropdown-filter p-inputtext p-component",{"p-variant-filled":i.variant?i.variant==="filled":r.$primevue.config.inputStyle==="filled"}]},filterIcon:"p-dropdown-filter-icon",wrapper:"p-dropdown-items-wrapper",list:"p-dropdown-items",itemGroup:"p-dropdown-item-group",itemGroupLabel:"p-dropdown-item-group-label",item:function(e){var i=e.instance,r=e.props,s=e.state,n=e.option,d=e.focusedOption;return["p-dropdown-item",{"p-highlight":i.isSelected(n)&&r.highlightOnSelect,"p-focus":s.focusedOptionIndex===d,"p-disabled":i.isOptionDisabled(n)}]},itemLabel:"p-dropdown-item-label",checkIcon:"p-dropdown-check-icon",blankIcon:"p-dropdown-blank-icon",emptyMessage:"p-dropdown-empty-message"},ve=J.extend({name:"dropdown",classes:Oe}),Ie={name:"BaseDropdown",extends:ye,props:{modelValue:null,options:Array,optionLabel:[String,Function],optionValue:[String,Function],optionDisabled:[String,Function],optionGroupLabel:[String,Function],optionGroupChildren:[String,Function],scrollHeight:{type:String,default:"200px"},filter:Boolean,filterPlaceholder:String,filterLocale:String,filterMatchMode:{type:String,default:"contains"},filterFields:{type:Array,default:null},editable:Boolean,placeholder:{type:String,default:null},variant:{type:String,default:null},invalid:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},dataKey:null,showClear:{type:Boolean,default:!1},inputId:{type:String,default:null},inputClass:{type:[String,Object],default:null},inputStyle:{type:Object,default:null},inputProps:{type:null,default:null},panelClass:{type:[String,Object],default:null},panelStyle:{type:Object,default:null},panelProps:{type:null,default:null},filterInputProps:{type:null,default:null},clearIconProps:{type:null,default:null},appendTo:{type:[String,Object],default:"body"},loading:{type:Boolean,default:!1},clearIcon:{type:String,default:void 0},dropdownIcon:{type:String,default:void 0},filterIcon:{type:String,default:void 0},loadingIcon:{type:String,default:void 0},resetFilterOnHide:{type:Boolean,default:!1},resetFilterOnClear:{type:Boolean,default:!1},virtualScrollerOptions:{type:Object,default:null},autoOptionFocus:{type:Boolean,default:!1},autoFilterFocus:{type:Boolean,default:!1},selectOnFocus:{type:Boolean,default:!1},focusOnHover:{type:Boolean,default:!0},highlightOnSelect:{type:Boolean,default:!0},checkmark:{type:Boolean,default:!1},filterMessage:{type:String,default:null},selectionMessage:{type:String,default:null},emptySelectionMessage:{type:String,default:null},emptyFilterMessage:{type:String,default:null},emptyMessage:{type:String,default:null},tabindex:{type:Number,default:0},ariaLabel:{type:String,default:null},ariaLabelledby:{type:String,default:null}},style:ve,provide:function(){return{$parentInstance:this}}};function L(t){"@babel/helpers - typeof";return L=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},L(t)}Line truncated
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Le(t,e){if(t){if(typeof t=="string")return j(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);if(i==="Object"&&t.constructor&&(i=t.constructor.name),i==="Map"||i==="Set")return Array.from(t);if(i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i))return j(t,e)}}function ke(t){if(typeof Symbol<"u"&&t[Symbol.iterator]!=null||t["@@iterator"]!=null)return Array.from(t)}function Fe(t){if(Array.isArray(t))return j(t)}function j(t,e){(e==null||e>t.length)&&(e=t.length);for(var i=0,r=new Array(e);i<e;i++)r[i]=t[i];return r}function G(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(s){return Object.getOwnPropertyDescriptor(t,s).enumerable})),i.push.apply(i,r)}return i}function R(t){for(var e=1;e<arguments.length;e++){var i=arguments[e]!=null?arguments[e]:{};e%2?G(Object(i),!0).forEach(function(r){N(t,r,i[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):G(Object(i)).forEach(function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(i,r))})}return t}function N(t,e,i){return e=Ce(e),e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function Ce(t){var e=Ve(t,"string");return L(e)=="symbol"?e:String(e)}function Ve(t,e){if(L(t)!="object"||!t)return t;var i=t[Symbol.toPrimitive];if(i!==void 0){var r=i.call(t,e||"default");if(L(r)!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(e==="string"?String:Number)(t)}var xe={name:"Dropdown",extends:Ie,inheritAttrs:!1,emits:["update:modelValue","change","focus","blur","before-show","before-hide","show","hide","filter"],outsideClickListener:null,scrollHandler:null,resizeListener:null,labelClickListener:null,overlay:null,list:null,virtualScroller:null,searchTimeout:null,searchValue:null,isModelValueChanged:!1,data:function(){return{id:this.$attrs.id,clicked:!1,focused:!1,focusedOptionIndex:-1,filterValue:null,overlayVisible:!1}},watch:{"$attrs.id":{immediate:!0,handler:function(e){this.id=e||X()}},modelValue:function(){this.isModelValueChanged=!0},options:function(){this.autoUpdateModel()}},mounted:function(){this.autoUpdateModel(),this.bindLabelClickListener()},updated:function(){this.overlayVisible&&this.isModelValueChanged&&this.scrollInView(this.findSelectedOptionIndex()),this.isModelValueChanged=!1},beforeUnmount:function(){this.unbindOutsideClickListener(),this.unbindResizeListener(),this.unbindLabelClickListener(),this.scrollHandler&&(this.scrollHandler.destroy(),this.scrollHandler=null),this.overlay&&(T.clear(this.overlay),this.overlay=null)},methods:{getOptionIndex:function(e,i){return this.virtualScrollerDisabled?e:i&&i(e).index},getOptionLabel:function(e){return this.optionLabel?c.resolveFieldData(e,this.optionLabel):e},getOptionValue:function(e){return this.optionValue?c.resolveFieldData(e,this.optionValue):e},getOptionRenderKey:function(e,i){return(this.dataKey?c.resolveFieldData(e,this.dataKey):this.getOptionLabel(e))+"_"+i},getPTItemOptions:function(e,i,r,s){return this.ptm(s,{context:{option:e,index:r,selected:this.isSelected(e),focused:this.focusedOptionIndex===this.getOptionIndex(r,i),disabled:this.isOptionDisabled(e)}})},isOptionDisabled:function(e){return this.optionDisabled?c.resolveFieldData(e,this.optionDisabled):!1},isOptionGroup:function(e){return this.optionGroupLabel&&e.optionGroup&&e.group},getOptionGroupLabel:function(e){return c.resolveFieldData(e,this.optionGroupLabel)},getOptionGroupChildren:function(e){return c.resolveFieldData(e,this.optionGroupChildren)},getAriaPosInset:function(e){var i=this;return(this.optionGroupLabel?e-this.visibleOptions.slice(0,e).filter(function(r){return i.isOptionGroup(r)}).length:e)+1},show:function(e){this.$emit("before-show"),this.overlayVisible=!0,this.focusedOptionIndex=this.focusedOptionIndex!==-1?this.focusedOptionIndex:this.autoOptionFocus?this.findFirstFocusedOptionIndex():this.editable?-1:this.findSelectedOptionIndex(),e&&a.focus(this.$refs.focusInput)},hide:function(e){var i=this,r=function(){i.$emit("before-hide"),i.overlayVisible=!1,i.clicked=!1,i.focusedOptionIndex=-1,i.searchValue="",i.resetFilterOnHide&&(i.filterValue=null),e&&a.focus(i.$refs.focusInput)};setTimeout(function(){r()},0)},onFocus:function(e){this.disabled||(this.focused=!0,this.overlayVisible&&(this.focusedOptionIndex=this.focusedOptionIndex!==-1?this.focusedOptionIndex:this.autoOptionFocus?this.findFirstFocusedOptionIndex():this.editable?-1:this.findSelectedOptionIndex(),this.scrollInView(this.focusedOptionIndex)),this.$emit("focus",e))},onBlur:function(e){this.focused=!1,this.focusedOptionIndex=-1,this.searchValue="",this.$emit("blur",e)},onKeyDown:function(e){if(this.disabled||a.isAndroid()){e.preventDefault();return}var i=e.metaKey||e.ctrlKey;switch(e.code){case"ArrowDown":this.onArrowDownKey(e);break;c
Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
import{s as m}from"./AdkLG1re.js";import{a3 as p,t as u,v as l,aa as r,x as d,y as f,O as c}from"./CdAotn7S.js";var v={root:function(a){var i=a.props;return["p-knob p-component",{"p-disabled":i.disabled}]},range:"p-knob-range",value:"p-knob-value",label:"p-knob-text"},y=p.extend({name:"knob",classes:v}),b={name:"BaseKnob",extends:m,props:{modelValue:{type:Number,default:null},size:{type:Number,default:100},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},step:{type:Number,default:1},min:{type:Number,default:0},max:{type:Number,default:100},valueColor:{type:String,default:"var(--primary-color, Black)"},rangeColor:{type:String,default:"var(--surface-border, LightGray)"},textColor:{type:String,default:"var(--text-color-secondary, Black)"},strokeWidth:{type:Number,default:14},showValue:{type:Boolean,default:!0},valueTemplate:{type:String,default:"{value}"},tabindex:{type:Number,default:0},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:y,provide:function(){return{$parentInstance:this}}},o=3.14159265358979,g={name:"Knob",extends:b,inheritAttrs:!1,emits:["update:modelValue","change"],data:function(){return{radius:40,midX:50,midY:50,minRadians:4*o/3,maxRadians:-o/3}},methods:{updateValue:function(a,i){var n=a-this.size/2,s=this.size/2-i,t=Math.atan2(s,n),h=-o/2-o/6;this.updateModel(t,h)},updateModel:function(a,i){var n;if(a>this.maxRadians)n=this.mapRange(a,this.minRadians,this.maxRadians,this.min,this.max);else if(a<i)n=this.mapRange(a+2*o,this.minRadians,this.maxRadians,this.min,this.max);else return;var s=Math.round((n-this.min)/this.step)*this.step+this.min;this.$emit("update:modelValue",s),this.$emit("change",s)},updateModelValue:function(a){a>this.max?this.$emit("update:modelValue",this.max):a<this.min?this.$emit("update:modelValue",this.min):this.$emit("update:modelValue",a)},mapRange:function(a,i,n,s,t){return(a-i)*(t-s)/(n-i)+s},onClick:function(a){!this.disabled&&!this.readonly&&this.updateValue(a.offsetX,a.offsetY)},onMouseDown:function(a){!this.disabled&&!this.readonly&&(window.addEventListener("mousemove",this.onMouseMove),window.addEventListener("mouseup",this.onMouseUp),a.preventDefault())},onMouseUp:function(a){!this.disabled&&!this.readonly&&(window.removeEventListener("mousemove",this.onMouseMove),window.removeEventListener("mouseup",this.onMouseUp),a.preventDefault())},onTouchStart:function(a){!this.disabled&&!this.readonly&&(window.addEventListener("touchmove",this.onTouchMove),window.addEventListener("touchend",this.onTouchEnd),a.preventDefault())},onTouchEnd:function(a){!this.disabled&&!this.readonly&&(window.removeEventListener("touchmove",this.onTouchMove),window.removeEventListener("touchend",this.onTouchEnd),a.preventDefault())},onMouseMove:function(a){!this.disabled&&!this.readonly&&(this.updateValue(a.offsetX,a.offsetY),a.preventDefault())},onTouchMove:function(a){if(!this.disabled&&!this.readonly&&a.touches.length==1){var i=this.$el.getBoundingClientRect(),n=a.targetTouches.item(0),s=n.clientX-i.left,t=n.clientY-i.top;this.updateValue(s,t)}},onKeyDown:function(a){if(!this.disabled&&!this.readonly)switch(a.code){case"ArrowRight":case"ArrowUp":{a.preventDefault(),this.updateModelValue(this.modelValue+this.step);break}case"ArrowLeft":case"ArrowDown":{a.preventDefault(),this.updateModelValue(this.modelValue-this.step);break}case"Home":{a.preventDefault(),this.$emit("update:modelValue",this.min);break}case"End":{a.preventDefault(),this.$emit("update:modelValue",this.max);break}case"PageUp":{a.preventDefault(),this.updateModelValue(this.modelValue+10);break}case"PageDown":{a.preventDefault(),this.updateModelValue(this.modelValue-10);break}}}},computed:{rangePath:function(){return"M ".concat(this.minX," ").concat(this.minY," A ").concat(this.radius," ").concat(this.radius," 0 1 1 ").concat(this.maxX," ").concat(this.maxY)},valuePath:function(){return"M ".concat(this.zeroX," ").concat(this.zeroY," A ").concat(this.radius," ").concat(this.radius," 0 ").concat(this.largeArc," ").concat(this.sweep," ").concat(this.valueX," ").concat(this.valueY)},zeroRadians:function(){return this.min>0&&this.max>0?this.mapRange(this.min,this.min,this.max,this.minRadians,this.maxRadians):this.mapRange(0,this.min,this.max,this.minRadians,this.maxRadians)},valueRadians:function(){return this.mapRange(this.modelValue,this.min,this.max,this.minRadians,this.maxRadians)},minX:function(){return this.midX+Math.cos(this.minRadians)*this.radius},minY:function(){return this.midY-Math.sin(this.minRadians)*this.radius},maxX:function(){return this.midX+Math.cos(this.maxRadians)*this.radius},maxY:function(){return this.midY-Math.sin(this.maxRadians)*this.radius},zeroX:function(){return this.midX+Math.cos(this.zeroRadians)*this.radius},zeroY:function(){return this.midY-Math.sin(this.zeroRadians)*this.radius},valueX:function(){return this.midX+Math.cos(this.valueRadians)*this.radius},valueY:function(){return this.midY-Math.sin(this.valueRadians)*this.radius},largeArc:funLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
import{ax as d,a3 as u,t as m,v as i,ae as f,aa as t,y as a,O as v,x as s,N as y,Q as T,$ as h,ai as g}from"./CdAotn7S.js";import{s as k}from"./AdkLG1re.js";var l=d(),w={root:"p-terminal p-component",content:"p-terminal-content",prompt:"p-terminal-prompt",command:"p-terminal-command",response:"p-terminal-response",container:"p-terminal-prompt-container",commandText:"p-terminal-input"},x=u.extend({name:"terminal",classes:w}),S={name:"BaseTerminal",extends:k,props:{welcomeMessage:{type:String,default:null},prompt:{type:String,default:null}},style:x,provide:function(){return{$parentInstance:this}}},C={name:"Terminal",extends:S,inheritAttrs:!1,data:function(){return{commandText:null,commands:[]}},mounted:function(){l.on("response",this.responseListener),this.$refs.input.focus()},updated:function(){this.$el.scrollTop=this.$el.scrollHeight},beforeUnmount:function(){l.off("response",this.responseListener)},methods:{onClick:function(){this.$refs.input.focus()},onKeydown:function(n){n.key==="Enter"&&this.commandText&&(this.commands.push({text:this.commandText}),l.emit("command",this.commandText),this.commandText="")},responseListener:function(n){this.commands[this.commands.length-1].response=n}}};function B(e,n,K,L,p,o){return m(),i("div",t({class:e.cx("root"),onClick:n[2]||(n[2]=function(){return o.onClick&&o.onClick.apply(o,arguments)})},e.ptmi("root")),[e.welcomeMessage?(m(),i("div",f(t({key:0},e.ptm("welcomeMessage"))),a(e.welcomeMessage),17)):v("",!0),s("div",t({class:e.cx("content")},e.ptm("content")),[(m(!0),i(y,null,T(p.commands,function(r,c){return m(),i("div",t({key:r.text+c.toString()},e.ptm("commands")),[s("span",t({class:e.cx("prompt")},e.ptm("prompt")),a(e.prompt),17),s("span",t({class:e.cx("command")},e.ptm("command")),a(r.text),17),s("div",t({class:e.cx("response"),"aria-live":"polite"},e.ptm("response")),a(r.response),17)],16)}),128))],16),s("div",t({class:e.cx("container")},e.ptm("container")),[s("span",t({class:e.cx("prompt")},e.ptm("prompt")),a(e.prompt),17),h(s("input",t({ref:"input","onUpdate:modelValue":n[0]||(n[0]=function(r){return p.commandText=r}),type:"text",class:e.cx("commandText"),autocomplete:"off",onKeydown:n[1]||(n[1]=function(){return o.onKeydown&&o.onKeydown.apply(o,arguments)})},e.ptm("commandText")),null,16),[[g,p.commandText]])],16)],16)}C.render=B;export{C as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{O as M}from"./eLdOjEri.js";import{s as T}from"./BIoHdha8.js";import{a3 as V,a5 as F,a4 as h,a6 as P,a7 as c,a8 as O,aa as d,a9 as D,i as y,Z as z,t as l,P as p,A as x,v as I,N as k,Q as R,x as K,$ as N,ab as L,W as B,O as g,y as G,aD as H,ac as w,z as E,Y as S}from"./CdAotn7S.js";import{s as C}from"./AdkLG1re.js";import{s as U}from"./CQay6pFc.js";import"./CYhL7ix_.js";var W={submenu:function(e){var i=e.instance,s=e.processedItem;return{display:i.isItemActive(s)?"block":"none"}}},Z={root:function(e){var i=e.instance,s=e.props;return["p-tieredmenu p-component",{"p-tieredmenu-overlay":s.popup,"p-ripple-disabled":i.$primevue.config.ripple===!1}]},start:"p-tieredmenu-start",menu:"p-tieredmenu-root-list",menuitem:function(e){var i=e.instance,s=e.processedItem;return["p-menuitem",{"p-menuitem-active p-highlight":i.isItemActive(s),"p-focus":i.isItemFocused(s),"p-disabled":i.isItemDisabled(s)}]},content:"p-menuitem-content",action:"p-menuitem-link",icon:"p-menuitem-icon",text:"p-menuitem-text",submenuIcon:"p-submenu-icon",submenu:"p-submenu-list",separator:"p-menuitem-separator",end:"p-tieredmenu-end"},j=V.extend({name:"tieredmenu",classes:Z,inlineStyles:W}),_={name:"BaseTieredMenu",extends:C,props:{popup:{type:Boolean,default:!1},model:{type:Array,default:null},appendTo:{type:[String,Object],default:"body"},autoZIndex:{type:Boolean,default:!0},baseZIndex:{type:Number,default:0},disabled:{type:Boolean,default:!1},tabindex:{type:Number,default:0},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:j,provide:function(){return{$parentInstance:this}}},A={name:"TieredMenuSub",hostName:"TieredMenu",extends:C,emits:["item-click","item-mouseenter","item-mousemove"],container:null,props:{menuId:{type:String,default:null},focusedItemId:{type:String,default:null},items:{type:Array,default:null},visible:{type:Boolean,default:!1},level:{type:Number,default:0},templates:{type:Object,default:null},activeItemPath:{type:Object,default:null},tabindex:{type:Number,default:0}},methods:{getItemId:function(e){return"".concat(this.menuId,"_").concat(e.key)},getItemKey:function(e){return this.getItemId(e)},getItemProp:function(e,i,s){return e&&e.item?h.getItemValue(e.item[i],s):void 0},getItemLabel:function(e){return this.getItemProp(e,"label")},getItemLabelId:function(e){return"".concat(this.menuId,"_").concat(e.key,"_label")},getPTOptions:function(e,i,s){return this.ptm(s,{context:{item:e,index:i,active:this.isItemActive(e),focused:this.isItemFocused(e),disabled:this.isItemDisabled(e)}})},isItemActive:function(e){return this.activeItemPath.some(function(i){return i.key===e.key})},isItemVisible:function(e){return this.getItemProp(e,"visible")!==!1},isItemDisabled:function(e){return this.getItemProp(e,"disabled")},isItemFocused:function(e){return this.focusedItemId===this.getItemId(e)},isItemGroup:function(e){return h.isNotEmpty(e.items)},onEnter:function(){c.nestedPosition(this.container,this.level)},onItemClick:function(e,i){this.getItemProp(i,"command",{originalEvent:e,item:i.item}),this.$emit("item-click",{originalEvent:e,processedItem:i,isFocus:!0})},onItemMouseEnter:function(e,i){this.$emit("item-mouseenter",{originalEvent:e,processedItem:i})},onItemMouseMove:function(e,i){this.$emit("item-mousemove",{originalEvent:e,processedItem:i})},getAriaSetSize:function(){var e=this;return this.items.filter(function(i){return e.isItemVisible(i)&&!e.getItemProp(i,"separator")}).length},getAriaPosInset:function(e){var i=this;return e-this.items.slice(0,e).filter(function(s){return i.isItemVisible(s)&&i.getItemProp(s,"separator")}).length+1},getMenuItemProps:function(e,i){return{action:d({class:this.cx("action"),tabindex:-1,"aria-hidden":!0},this.getPTOptions(e,i,"action")),icon:d({class:[this.cx("icon"),this.getItemProp(e,"icon")]},this.getPTOptions(e,i,"icon")),label:d({class:this.cx("label")},this.getPTOptions(e,i,"label")),submenuicon:d({class:this.cx("submenuIcon")},this.getPTOptions(e,i,"submenuIcon"))}},containerRef:function(e){this.container=e}},components:{AngleRightIcon:U},directives:{ripple:D}},q=["tabindex"],Q=["id","aria-label","aria-disabled","aria-expanded","aria-haspopup","aria-level","aria-setsize","aria-posinset","data-p-highlight","data-p-focused","data-p-disabled"],Y=["onClick","onMouseenter","onMousemove"],J=["href","target"],X=["id"],$=["id"];function ee(t,e,i,s,a,n){var u=y("AngleRightIcon"),f=y("TieredMenuSub",!0),v=z("ripple");return l(),p(w,d({name:"p-tieredmenu",onEnter:n.onEnter},t.ptm("menu.transition")),{default:x(function(){return[i.level===0||i.visible?(l(),I("ul",d({key:0,ref:n.containerRef,class:i.level===0?t.cx("menu"):t.cx("submenu"),tabindex:i.tabindex},i.level===0?t.ptm("menu"):t.ptm("submenu")),[(l(!0),I(k,null,R(i.items,function(r,o){return l(),I(k,{key:n.getItemKey(r)},[n.isItemVisible(r)&&!n.getItemProp(r,"separator")?(l(),I("li",d({key:0,id:n.getItemId(r),style:n.getItemProp(r,"style"),class:[t.cx("menuitem",{processedItem:r}),n.getItemProp(r,"class")],role:"menuiLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
import{t as s,v as c,aa as n,x as i,a3 as R,a6 as b,a7 as f,av as Z,i as p,Z as V,Y as u,P as $,ab as j,O as w,z as m,A as y,$ as H,ae as C,af as d,ac as T,W as U,aD as K}from"./CdAotn7S.js";import{s as N}from"./gJ3REwVq.js";import{s as h}from"./CYhL7ix_.js";import{s as q}from"./B3yzUv7e.js";import{s as F}from"./BIoHdha8.js";import{s as W}from"./AdkLG1re.js";var I={name:"RefreshIcon",extends:h},Y=i("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M6.77051 5.96336C6.84324 5.99355 6.92127 6.00891 7.00002 6.00854C7.07877 6.00891 7.1568 5.99355 7.22953 5.96336C7.30226 5.93317 7.36823 5.88876 7.42357 5.83273L9.82101 3.43529C9.93325 3.32291 9.99629 3.17058 9.99629 3.01175C9.99629 2.85292 9.93325 2.70058 9.82101 2.5882L7.42357 0.190763C7.3687 0.131876 7.30253 0.0846451 7.22901 0.0518865C7.15549 0.019128 7.07612 0.00151319 6.99564 9.32772e-05C6.91517 -0.00132663 6.83523 0.0134773 6.7606 0.0436218C6.68597 0.0737664 6.61817 0.118634 6.56126 0.175548C6.50435 0.232462 6.45948 0.300257 6.42933 0.374888C6.39919 0.449519 6.38439 0.529456 6.38581 0.609933C6.38722 0.690409 6.40484 0.769775 6.4376 0.843296C6.47036 0.916817 6.51759 0.982986 6.57647 1.03786L7.95103 2.41241H6.99998C5.46337 2.41241 3.98969 3.02283 2.90314 4.10938C1.81659 5.19593 1.20618 6.66961 1.20618 8.20622C1.20618 9.74283 1.81659 11.2165 2.90314 12.3031C3.98969 13.3896 5.46337 14 6.99998 14C8.53595 13.9979 10.0084 13.3868 11.0945 12.3007C12.1806 11.2146 12.7917 9.74218 12.7938 8.20622C12.7938 8.04726 12.7306 7.89481 12.6182 7.78241C12.5058 7.67001 12.3534 7.60686 12.1944 7.60686C12.0355 7.60686 11.883 7.67001 11.7706 7.78241C11.6582 7.89481 11.5951 8.04726 11.5951 8.20622C11.5951 9.11504 11.3256 10.0035 10.8207 10.7591C10.3157 11.5148 9.59809 12.1037 8.75845 12.4515C7.9188 12.7993 6.99489 12.8903 6.10353 12.713C5.21217 12.5357 4.3934 12.0981 3.75077 11.4554C3.10813 10.8128 2.67049 9.99404 2.49319 9.10268C2.31589 8.21132 2.40688 7.2874 2.75468 6.44776C3.10247 5.60811 3.69143 4.89046 4.44709 4.38554C5.20275 3.88063 6.09116 3.61113 6.99998 3.61113H7.95098L6.57647 4.98564C6.46423 5.09802 6.40119 5.25035 6.40119 5.40918C6.40119 5.56801 6.46423 5.72035 6.57647 5.83273C6.63181 5.88876 6.69778 5.93317 6.77051 5.96336Z",fill:"currentColor"},null,-1),G=[Y];function J(e,t,o,a,l,r){return s(),c("svg",n({width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg"},e.pti()),G,16)}I.render=J;var L={name:"SearchMinusIcon",extends:h},Q=i("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M6.0208 12.0411C4.83005 12.0411 3.66604 11.688 2.67596 11.0265C1.68589 10.3649 0.914216 9.42464 0.458534 8.32452C0.00285271 7.22441 -0.116374 6.01388 0.11593 4.84601C0.348235 3.67813 0.921637 2.60537 1.76363 1.76338C2.60562 0.921393 3.67838 0.34799 4.84625 0.115686C6.01412 -0.116618 7.22466 0.00260857 8.32477 0.45829C9.42488 0.913972 10.3652 1.68564 11.0267 2.67572C11.6883 3.66579 12.0414 4.8298 12.0414 6.02056C12.0395 7.41563 11.5542 8.76029 10.6783 9.8305L13.8244 12.9765C13.9367 13.089 13.9997 13.2414 13.9997 13.4003C13.9997 13.5592 13.9367 13.7116 13.8244 13.8241C13.769 13.8801 13.703 13.9245 13.6302 13.9548C13.5575 13.985 13.4794 14.0003 13.4006 14C13.3218 14.0003 13.2437 13.985 13.171 13.9548C13.0982 13.9245 13.0322 13.8801 12.9768 13.8241L9.83082 10.678C8.76059 11.5539 7.4159 12.0393 6.0208 12.0411ZM6.0208 1.20731C5.07199 1.20731 4.14449 1.48867 3.35559 2.0158C2.56669 2.54292 1.95181 3.29215 1.58872 4.16874C1.22562 5.04532 1.13062 6.00989 1.31572 6.94046C1.50083 7.87104 1.95772 8.72583 2.62863 9.39674C3.29954 10.0676 4.15433 10.5245 5.0849 10.7096C6.01548 10.8947 6.98005 10.7997 7.85663 10.4367C8.73322 10.0736 9.48244 9.45868 10.0096 8.66978C10.5367 7.88088 10.8181 6.95337 10.8181 6.00457C10.8181 4.73226 10.3126 3.51206 9.41297 2.6124C8.51331 1.71274 7.29311 1.20731 6.0208 1.20731ZM4.00591 6.60422H8.00362C8.16266 6.60422 8.31518 6.54104 8.42764 6.42859C8.5401 6.31613 8.60328 6.1636 8.60328 6.00456C8.60328 5.84553 8.5401 5.693 8.42764 5.58054C8.31518 5.46809 8.16266 5.40491 8.00362 5.40491H4.00591C3.84687 5.40491 3.69434 5.46809 3.58189 5.58054C3.46943 5.693 3.40625 5.84553 3.40625 6.00456C3.40625 6.1636 3.46943 6.31613 3.58189 6.42859C3.69434 6.54104 3.84687 6.60422 4.00591 6.60422Z",fill:"currentColor"},null,-1),X=[Q];function _(e,t,o,a,l,r){return s(),c("svg",n({width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg"},e.pti()),X,16)}L.render=_;var B={name:"SearchPlusIcon",extends:h},x=i("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M2.67596 11.0265C3.66604 11.688 4.83005 12.0411 6.0208 12.0411C6.81143 12.0411 7.59432 11.8854 8.32477 11.5828C8.86999 11.357 9.37802 11.0526 9.83311 10.6803L12.9768 13.8241C13.0322 13.8801 13.0982 13.9245 13.171 13.9548C13.2437 13.985 13.3218 14.0003 13.4006 14C13.4794 14.0003 13.5575 13.985 13.6302 13.9548C13.703 13.9245 13.769 13.8801 13.8244 13.8241C13.9367 13.7116 13.9997 13.5592 13.9997 13.4003C13.9997 13.2414 13.9367 13.089 13.8244 12.9765L10.6806 9.8328C11.0529 9.37Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
import{a3 as u,a4 as r,t as s,v as o,x as d,aa as i}from"./CdAotn7S.js";import{s as p}from"./AdkLG1re.js";var b={root:function(a){var n=a.instance,l=a.props;return["p-radiobutton p-component",{"p-highlight":n.checked,"p-disabled":l.disabled,"p-invalid":l.invalid,"p-variant-filled":l.variant?l.variant==="filled":n.$primevue.config.inputStyle==="filled"}]},box:"p-radiobutton-box",input:"p-radiobutton-input",icon:"p-radiobutton-icon"},c=u.extend({name:"radiobutton",classes:b}),h={name:"BaseRadioButton",extends:p,props:{value:null,modelValue:null,binary:Boolean,name:{type:String,default:null},variant:{type:String,default:null},invalid:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},tabindex:{type:Number,default:null},inputId:{type:String,default:null},inputClass:{type:[String,Object],default:null},inputStyle:{type:Object,default:null},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:c,provide:function(){return{$parentInstance:this}}},f={name:"RadioButton",extends:h,inheritAttrs:!1,emits:["update:modelValue","change","focus","blur"],methods:{getPTOptions:function(a){var n=a==="root"?this.ptmi:this.ptm;return n(a,{context:{checked:this.checked,disabled:this.disabled}})},onChange:function(a){if(!this.disabled&&!this.readonly){var n=this.binary?!this.checked:this.value;this.$emit("update:modelValue",n),this.$emit("change",a)}},onFocus:function(a){this.$emit("focus",a)},onBlur:function(a){this.$emit("blur",a)}},computed:{checked:function(){return this.modelValue!=null&&(this.binary?!!this.modelValue:r.equals(this.modelValue,this.value))}}},m=["data-p-highlight","data-p-disabled"],y=["id","value","name","checked","tabindex","disabled","readonly","aria-labelledby","aria-label","aria-invalid"];function v(e,a,n,l,g,t){return s(),o("div",i({class:e.cx("root")},t.getPTOptions("root"),{"data-p-highlight":t.checked,"data-p-disabled":e.disabled}),[d("input",i({id:e.inputId,type:"radio",class:[e.cx("input"),e.inputClass],style:e.inputStyle,value:e.value,name:e.name,checked:t.checked,tabindex:e.tabindex,disabled:e.disabled,readonly:e.readonly,"aria-labelledby":e.ariaLabelledby,"aria-label":e.ariaLabel,"aria-invalid":e.invalid||void 0,onFocus:a[0]||(a[0]=function(){return t.onFocus&&t.onFocus.apply(t,arguments)}),onBlur:a[1]||(a[1]=function(){return t.onBlur&&t.onBlur.apply(t,arguments)}),onChange:a[2]||(a[2]=function(){return t.onChange&&t.onChange.apply(t,arguments)})},t.getPTOptions("input")),null,16,y),d("div",i({class:e.cx("box")},t.getPTOptions("box")),[d("div",i({class:e.cx("icon")},t.getPTOptions("icon")),null,16)],16)],16,m)}f.render=v;export{f as default};
|
||||
@@ -1,2 +0,0 @@
|
||||
import{a3 as V,at as D,a4 as c,aa as $}from"./CdAotn7S.js";function h(n){"@babel/helpers - typeof";return h=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h(n)}function S(n,t){var e=Object.keys(n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(n);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(n,i).enumerable})),e.push.apply(e,r)}return e}function U(n){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?arguments[t]:{};t%2?S(Object(e),!0).forEach(function(r){B(n,r,e[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(e)):S(Object(e)).forEach(function(r){Object.defineProperty(n,r,Object.getOwnPropertyDescriptor(e,r))})}return n}function B(n,t,e){return t=x(t),t in n?Object.defineProperty(n,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):n[t]=e,n}function x(n){var t=E(n,"string");return h(t)=="symbol"?t:String(t)}function E(n,t){if(h(n)!="object"||!n)return n;var e=n[Symbol.toPrimitive];if(e!==void 0){var r=e.call(n,t||"default");if(h(r)!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(n)}var O=V.extend({name:"common",loadGlobalStyle:function(t){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return D(t,U({name:"global"},e))}});function y(n){"@babel/helpers - typeof";return y=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},y(n)}function G(n){return I(n)||N(n)||C(n)||w()}function N(n){if(typeof Symbol<"u"&&n[Symbol.iterator]!=null||n["@@iterator"]!=null)return Array.from(n)}function b(n,t){return I(n)||F(n,t)||C(n,t)||w()}function w(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function C(n,t){if(n){if(typeof n=="string")return T(n,t);var e=Object.prototype.toString.call(n).slice(8,-1);if(e==="Object"&&n.constructor&&(e=n.constructor.name),e==="Map"||e==="Set")return Array.from(n);if(e==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e))return T(n,t)}}function T(n,t){(t==null||t>n.length)&&(t=n.length);for(var e=0,r=new Array(t);e<t;e++)r[e]=n[e];return r}function F(n,t){var e=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(e!=null){var r,i,a,f,l=[],u=!0,d=!1;try{if(a=(e=e.call(n)).next,t===0){if(Object(e)!==e)return;u=!1}else for(;!(u=(r=a.call(e)).done)&&(l.push(r.value),l.length!==t);u=!0);}catch(o){d=!0,i=o}finally{try{if(!u&&e.return!=null&&(f=e.return(),Object(f)!==f))return}finally{if(d)throw i}}return l}}function I(n){if(Array.isArray(n))return n}function j(n,t){var e=Object.keys(n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(n);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(n,i).enumerable})),e.push.apply(e,r)}return e}function s(n){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?arguments[t]:{};t%2?j(Object(e),!0).forEach(function(r){P(n,r,e[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(e)):j(Object(e)).forEach(function(r){Object.defineProperty(n,r,Object.getOwnPropertyDescriptor(e,r))})}return n}function P(n,t,e){return t=K(t),t in n?Object.defineProperty(n,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):n[t]=e,n}function K(n){var t=M(n,"string");return y(t)=="symbol"?t:String(t)}function M(n,t){if(y(n)!="object"||!n)return n;var e=n[Symbol.toPrimitive];if(e!==void 0){var r=e.call(n,t||"default");if(y(r)!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(n)}var W={name:"BaseComponent",props:{pt:{type:Object,default:void 0},ptOptions:{type:Object,default:void 0},unstyled:{type:Boolean,default:void 0}},inject:{$parentInstance:{default:void 0}},watch:{isUnstyled:{immediate:!0,handler:function(t){if(!t){var e,r;O.loadStyle({nonce:(e=this.$config)===null||e===void 0||(e=e.csp)===null||e===void 0?void 0:e.nonce}),this.$options.style&&this.$style.loadStyle({nonce:(r=this.$config)===null||r===void 0||(r=r.csp)===null||r===void 0?void 0:r.nonce})}}}},beforeCreate:function(){var t,e,r,i,a,f,l,u,d,o,g,p=(t=this.pt)===null||t===void 0?void 0:t._usept,m=p?(e=this.pt)===null||e===void 0||(e=e.originalValue)===null||e===void 0?void 0:e[this.$.type.name]:void 0,v=p?(r=this.pt)===null||r===void 0||(r=r.value)===null||r===void 0?void 0:r[this.$.type.name]:this.pt;(i=v||m)===null||i===void 0||(i=i.hooks)===null||i===void 0||(a=i.onBeforeCreate)===null||a===void 0||a.call(i);var _=(f=this.$config)===null||f===void 0||(f=f.pt)===null||f===void 0?void 0:f._usept,k=_?(l=this.$primevue)===null||l===void 0||(l=l.config)===null||l===void 0||(l=l.pt)===null||l===void 0?void 0:l.originalValue:void 0,A=_?(u=this.$primevue)===null||u===void 0||(u=u.config)===null||u===void 0||(u=u.pt)===null||u===void 0?void 0:u.value:(d=this.$primevue)===null||d===void 0||(d=d.config)===null||d===void 0?void 0:d.pt;(o=A||k)===null||o===void 0||(o=o[this.$.type.name])===null||o===void 0||(o=o.hooks)===null||o===void 0||(g=o.onBeforeCreate)===null||g===void 0||g.call(o)},created:function(){this._hook("onCreated")},beforeMount:function(){var t;V.loadStyle({nonce:(t=this.$config)===null||t===void 0||(t=t.csp)===null||t===void 0?void 0:t.nonce}),this._loadGlobalStyles(),this._hook("onBeforeMount")},mounted:function(){this._hook("onMounted")},beforeUpdate:function(){this._hook("onBeforeUpdate")},updated:function(){this._hook("onUpdated")},beforeUnmount:function(){this._hook("onBeforeUnmount")},unmounted:function(){this._hook("onUnmounted")},methods:{_hook:function(t){if(!this.$options.hostName){var e=this._usePT(this._getPT(this.pt,this.$.type.name),this._getOptionValue,"hooks.".concat(t)),r=this._useDefaultPT(this._getOptionValue,"hooks.".concat(t));e==null||e(),r==null||r()}},_mergeProps:function(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;i<e;i++)r[i-1]=arguments[i];return c.isFunction(t)?t.apply(void 0,r):$.apply(void 0,r)},_loadGlobalStyles:function(){var t,e=this._useGlobalPT(this._getOptionValue,"global.css",this.$params);c.isNotEmpty(e)&&O.loadGlobalStyle(e,{nonce:(t=this.$config)===null||t===void 0||(t=t.csp)===null||t===void 0?void 0:t.nonce})},_getHostInstance:function(t){return t?this.$options.hostName?t.$.type.name===this.$options.hostName?t:this._getHostInstance(t.$parentInstance):t.$parentInstance:void 0},_getPropValue:function(t){var e;return this[t]||((e=this._getHostInstance(this))===null||e===void 0?void 0:e[t])},_getOptionValue:function(t){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"",r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},i=c.toFlatCase(e).split(
Line truncated
|
||||
@@ -1,2 +0,0 @@
|
||||
import{s as p}from"./DtEiWfmc.js";import{a3 as h,a4 as o,i as f,t as s,v as b,x as d,aa as r,Y as m,P as y,O as v,W as g}from"./CdAotn7S.js";import{s as k}from"./AdkLG1re.js";import"./CYhL7ix_.js";var C={root:function(a){var t=a.instance,l=a.props;return["p-checkbox p-component",{"p-highlight":t.checked,"p-disabled":l.disabled,"p-invalid":l.invalid,"p-variant-filled":l.variant?l.variant==="filled":t.$primevue.config.inputStyle==="filled"}]},box:"p-checkbox-box",input:"p-checkbox-input",icon:"p-checkbox-icon"},S=h.extend({name:"checkbox",classes:C}),B={name:"BaseCheckbox",extends:k,props:{value:null,modelValue:null,binary:Boolean,name:{type:String,default:null},trueValue:{type:null,default:!0},falseValue:{type:null,default:!1},variant:{type:String,default:null},invalid:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},required:{type:Boolean,default:!1},tabindex:{type:Number,default:null},inputId:{type:String,default:null},inputClass:{type:[String,Object],default:null},inputStyle:{type:Object,default:null},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:S,provide:function(){return{$parentInstance:this}}};function A(e){return x(e)||I(e)||V(e)||O()}function O(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function V(e,a){if(e){if(typeof e=="string")return i(e,a);var t=Object.prototype.toString.call(e).slice(8,-1);if(t==="Object"&&e.constructor&&(t=e.constructor.name),t==="Map"||t==="Set")return Array.from(e);if(t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return i(e,a)}}function I(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}function x(e){if(Array.isArray(e))return i(e)}function i(e,a){(a==null||a>e.length)&&(a=e.length);for(var t=0,l=new Array(a);t<a;t++)l[t]=e[t];return l}var T={name:"Checkbox",extends:B,inheritAttrs:!1,emits:["update:modelValue","change","focus","blur"],methods:{getPTOptions:function(a){var t=a==="root"?this.ptmi:this.ptm;return t(a,{context:{checked:this.checked,disabled:this.disabled}})},onChange:function(a){var t=this;if(!this.disabled&&!this.readonly){var l;this.binary?l=this.checked?this.falseValue:this.trueValue:this.checked?l=this.modelValue.filter(function(u){return!o.equals(u,t.value)}):l=this.modelValue?[].concat(A(this.modelValue),[this.value]):[this.value],this.$emit("update:modelValue",l),this.$emit("change",a)}},onFocus:function(a){this.$emit("focus",a)},onBlur:function(a){this.$emit("blur",a)}},computed:{checked:function(){return this.binary?this.modelValue===this.trueValue:o.contains(this.value,this.modelValue)}},components:{CheckIcon:p}},P=["data-p-highlight","data-p-disabled"],j=["id","value","name","checked","tabindex","disabled","readonly","required","aria-labelledby","aria-label","aria-invalid"];function q(e,a,t,l,u,n){var c=f("CheckIcon");return s(),b("div",r({class:e.cx("root")},n.getPTOptions("root"),{"data-p-highlight":n.checked,"data-p-disabled":e.disabled}),[d("input",r({id:e.inputId,type:"checkbox",class:[e.cx("input"),e.inputClass],style:e.inputStyle,value:e.value,name:e.name,checked:n.checked,tabindex:e.tabindex,disabled:e.disabled,readonly:e.readonly,required:e.required,"aria-labelledby":e.ariaLabelledby,"aria-label":e.ariaLabel,"aria-invalid":e.invalid||void 0,onFocus:a[0]||(a[0]=function(){return n.onFocus&&n.onFocus.apply(n,arguments)}),onBlur:a[1]||(a[1]=function(){return n.onBlur&&n.onBlur.apply(n,arguments)}),onChange:a[2]||(a[2]=function(){return n.onChange&&n.onChange.apply(n,arguments)})},n.getPTOptions("input")),null,16,j),d("div",r({class:e.cx("box")},n.getPTOptions("box")),[m(e.$slots,"icon",{checked:n.checked,class:g(e.cx("icon"))},function(){return[n.checked?(s(),y(c,r({key:0,class:e.cx("icon")},n.getPTOptions("icon")),null,16,["class"])):v("",!0)]})],16)],16,P)}T.render=q;export{T as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{s as r}from"./CYhL7ix_.js";import{t,v as o,aa as s,x as C}from"./CdAotn7S.js";var a={name:"TimesIcon",extends:r},n=C("path",{d:"M8.01186 7.00933L12.27 2.75116C12.341 2.68501 12.398 2.60524 12.4375 2.51661C12.4769 2.42798 12.4982 2.3323 12.4999 2.23529C12.5016 2.13827 12.4838 2.0419 12.4474 1.95194C12.4111 1.86197 12.357 1.78024 12.2884 1.71163C12.2198 1.64302 12.138 1.58893 12.0481 1.55259C11.9581 1.51625 11.8617 1.4984 11.7647 1.50011C11.6677 1.50182 11.572 1.52306 11.4834 1.56255C11.3948 1.60204 11.315 1.65898 11.2488 1.72997L6.99067 5.98814L2.7325 1.72997C2.59553 1.60234 2.41437 1.53286 2.22718 1.53616C2.03999 1.53946 1.8614 1.61529 1.72901 1.74767C1.59663 1.88006 1.5208 2.05865 1.5175 2.24584C1.5142 2.43303 1.58368 2.61419 1.71131 2.75116L5.96948 7.00933L1.71131 11.2675C1.576 11.403 1.5 11.5866 1.5 11.7781C1.5 11.9696 1.576 12.1532 1.71131 12.2887C1.84679 12.424 2.03043 12.5 2.2219 12.5C2.41338 12.5 2.59702 12.424 2.7325 12.2887L6.99067 8.03052L11.2488 12.2887C11.3843 12.424 11.568 12.5 11.7594 12.5C11.9509 12.5 12.1346 12.424 12.27 12.2887C12.4053 12.1532 12.4813 11.9696 12.4813 11.7781C12.4813 11.5866 12.4053 11.403 12.27 11.2675L8.01186 7.00933Z",fill:"currentColor"},null,-1),i=[n];function p(e,c,l,d,m,h){return t(),o("svg",s({width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg"},e.pti()),i,16)}a.render=p;export{a as s};
|
||||
@@ -1 +0,0 @@
|
||||
import{aI as B,r as k,L as S,G as N,v as u,y as d,O as s,W as c,x as r,P as f,A as x,ac as D,i as h,t as i,$ as L,ad as W,N as E,Q as O}from"./CdAotn7S.js";import{useLayout as R}from"./DiD3_pIL.js";const T={key:0,class:"layout-menuitem-root-text"},j=["href","target"],z={class:"layout-menuitem-text"},F={key:0,class:"pi pi-fw pi-angle-down layout-submenu-toggler"},G={class:"layout-menuitem-text"},P={key:0,class:"pi pi-fw pi-angle-down layout-submenu-toggler"},Q={class:"layout-submenu"},q={__name:"AppMenuItem",props:{item:{type:Object,default:()=>({})},index:{type:Number,default:0},root:{type:Boolean,default:!0},parentItemKey:{type:String,default:null}},setup(e){const I=B(),{layoutConfig:M,layoutState:b,setActiveMenuItem:C,onMenuToggle:K}=R(),m=e,o=k(!1),n=k(null);S(()=>{n.value=m.parentItemKey?m.parentItemKey+"-"+m.index:String(m.index);const t=b.activeMenuItem;o.value=t===n.value||t?t.startsWith(n.value+"-"):!1}),N(()=>M.activeMenuItem.value,t=>{o.value=t===n.value||t.startsWith(n.value+"-")});const g=(t,a)=>{if(a.disabled){t.preventDefault();return}const{overlayMenuActive:v,staticMenuMobileActive:y}=b;(a.to||a.url)&&(y.value||v.value)&&K(),a.command&&a.command({originalEvent:t,item:a});const l=a.items?o.value?m.parentItemKey:n:n.value;C(l)},w=t=>I.path===t.to;return(t,a)=>{const v=h("router-link"),y=h("app-menu-item",!0);return i(),u("li",{class:c({"layout-root-menuitem":e.root,"active-menuitem":o.value})},[e.root&&e.item.visible!==!1?(i(),u("div",T,d(e.item.label),1)):s("",!0),(!e.item.to||e.item.items)&&e.item.visible!==!1?(i(),u("a",{key:1,href:e.item.url,onClick:a[0]||(a[0]=l=>g(l,e.item,e.index)),class:c(e.item.class),target:e.item.target,tabindex:"0"},[r("i",{class:c([e.item.icon,"layout-menuitem-icon"])},null,2),r("span",z,d(e.item.label),1),e.item.items?(i(),u("i",F)):s("",!0)],10,j)):s("",!0),e.item.to&&!e.item.items&&e.item.visible!==!1?(i(),f(v,{key:2,onClick:a[1]||(a[1]=l=>g(l,e.item,e.index)),class:c([e.item.class,{"active-route":w(e.item)}]),tabindex:"0",to:e.item.to},{default:x(()=>[r("i",{class:c([e.item.icon,"layout-menuitem-icon"])},null,2),r("span",G,d(e.item.label),1),e.item.items?(i(),u("i",P)):s("",!0)]),_:1},8,["class","to"])):s("",!0),e.item.items&&e.item.visible!==!1?(i(),f(D,{key:3,name:"layout-submenu"},{default:x(()=>[L(r("ul",Q,[(i(!0),u(E,null,O(e.item.items,(l,A)=>(i(),f(y,{key:l,index:A,item:l,parentItemKey:n.value,root:!1},null,8,["index","item","parentItemKey"]))),128))],512),[[W,e.root?!0:o.value]])]),_:1})):s("",!0)],2)}}};export{q as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{u as S,a as A,_ as B}from"./C0K2Sjq5.js";import{r as i,T as L,o as M,e as T,c,U as x,v as E,x as t,M as l,z as d,A as N,W as R,i as w,t as O}from"./CdAotn7S.js";import{useLayout as U}from"./DiD3_pIL.js";import"./BK_1YlQG.js";import"./AdkLG1re.js";const $={class:"layout-topbar"},q=t("i",{class:"pi pi-bars"},null,-1),z=[q],D=["src"],V=t("span",null,"Dashboard | WAHA",-1),W=t("i",{class:"pi pi-ellipsis-v"},null,-1),H=[W],I={class:"m-auto"},j=["disabled"],F=t("i",{class:"pi pi-refresh"},null,-1),G=t("span",null,"Refresh",-1),J=[F,G],tt={__name:"AppTopbar",setup(K){const{layoutConfig:p,onMenuToggle:_}=U(),s=i(null),n=i(!1);L();const r=S();M(()=>{v()}),T(()=>{h()});const m=c(()=>`/dashboard/layout/images/${p.darkTheme.value?"logo-white":"logo-dark"}.svg`),b=()=>{n.value=!n.value},f=c(()=>({"layout-topbar-menu-mobile-active":n.value})),v=()=>{s.value||(s.value=o=>{g(o)&&(n.value=!1)},document.addEventListener("click",s.value))},h=()=>{s.value&&(document.removeEventListener("click",s),s.value=null)},g=o=>{if(!n.value)return;const e=document.querySelector(".layout-topbar-menu"),a=document.querySelector(".layout-topbar-menu-button");return!(e.isSameNode(o.target)||e.contains(o.target)||a.isSameNode(o.target)||a.contains(o.target))};function k(){A("store",async()=>await r.refresh())}const{refreshing:u}=x(r);return(o,e)=>{const a=w("router-link"),y=B;return O(),E("div",$,[t("button",{class:"p-link layout-menu-button layout-topbar-button",onClick:e[0]||(e[0]=C=>l(_)())},z),d(a,{to:"/",class:"layout-topbar-logo"},{default:N(()=>[t("img",{class:"mb-1",src:m.value,alt:"logo"},null,8,D),V]),_:1}),t("button",{class:"p-link layout-topbar-menu-button layout-topbar-button",onClick:e[1]||(e[1]=C=>b())},H),t("div",{class:R(["layout-topbar-menu",f.value])},[t("div",I,[d(y,{refreshing:l(u)},null,8,["refreshing"])]),t("button",{onClick:k,class:"p-link layout-topbar-button",disabled:l(u)},J,8,j)],2)])}}};export{tt as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{s as S}from"./BIoHdha8.js";import{a3 as F,a5 as V,a4 as d,a6 as x,a7 as m,aa as l,a9 as D,i as y,Z as T,t as u,P as v,A as k,v as I,N as L,Q as O,x as K,$ as z,ab as P,W as C,O as g,y as R,ac as E,z as M}from"./CdAotn7S.js";import{s as w}from"./AdkLG1re.js";import{s as N}from"./CQay6pFc.js";import"./CYhL7ix_.js";var B={root:function(e){var t=e.instance;return["p-contextmenu p-component",{"p-ripple-disabled":t.$primevue.config.ripple===!1}]},menu:"p-contextmenu-root-list",menuitem:function(e){var t=e.instance,a=e.processedItem;return["p-menuitem",{"p-menuitem-active p-highlight":t.isItemActive(a),"p-focus":t.isItemFocused(a),"p-disabled":t.isItemDisabled(a)}]},content:"p-menuitem-content",action:"p-menuitem-link",icon:"p-menuitem-icon",label:"p-menuitem-text",submenuIcon:"p-submenu-icon",submenu:"p-submenu-list",separator:"p-menuitem-separator"},_=F.extend({name:"contextmenu",classes:B}),G={name:"BaseContextMenu",extends:w,props:{model:{type:Array,default:null},appendTo:{type:[String,Object],default:"body"},autoZIndex:{type:Boolean,default:!0},baseZIndex:{type:Number,default:0},global:{type:Boolean,default:!1},tabindex:{type:Number,default:0},ariaLabelledby:{type:String,default:null},ariaLabel:{type:String,default:null}},style:_,provide:function(){return{$parentInstance:this}}},A={name:"ContextMenuSub",hostName:"ContextMenu",extends:w,emits:["item-click","item-mouseenter","item-mousemove"],props:{items:{type:Array,default:null},menuId:{type:String,default:null},focusedItemId:{type:String,default:null},root:{type:Boolean,default:!1},visible:{type:Boolean,default:!1},level:{type:Number,default:0},templates:{type:Object,default:null},activeItemPath:{type:Object,default:null},tabindex:{type:Number,default:0}},methods:{getItemId:function(e){return"".concat(this.menuId,"_").concat(e.key)},getItemKey:function(e){return this.getItemId(e)},getItemProp:function(e,t,a){return e&&e.item?d.getItemValue(e.item[t],a):void 0},getItemLabel:function(e){return this.getItemProp(e,"label")},getItemLabelId:function(e){return"".concat(this.menuId,"_").concat(e.key,"_label")},getPTOptions:function(e,t,a){return this.ptm(e,{context:{item:t,active:this.isItemActive(t),focused:this.isItemFocused(t),disabled:this.isItemDisabled(t),index:a}})},isItemActive:function(e){return this.activeItemPath.some(function(t){return t.key===e.key})},isItemVisible:function(e){return this.getItemProp(e,"visible")!==!1},isItemDisabled:function(e){return this.getItemProp(e,"disabled")},isItemFocused:function(e){return this.focusedItemId===this.getItemId(e)},isItemGroup:function(e){return d.isNotEmpty(e.items)},onItemClick:function(e,t){this.getItemProp(t,"command",{originalEvent:e,item:t.item}),this.$emit("item-click",{originalEvent:e,processedItem:t,isFocus:!0})},onItemMouseEnter:function(e,t){this.$emit("item-mouseenter",{originalEvent:e,processedItem:t})},onItemMouseMove:function(e,t){this.$emit("item-mousemove",{originalEvent:e,processedItem:t,isFocus:!0})},getAriaSetSize:function(){var e=this;return this.items.filter(function(t){return e.isItemVisible(t)&&!e.getItemProp(t,"separator")}).length},getAriaPosInset:function(e){var t=this;return e-this.items.slice(0,e).filter(function(a){return t.isItemVisible(a)&&t.getItemProp(a,"separator")}).length+1},onEnter:function(){m.nestedPosition(this.$refs.container,this.level)},getMenuItemProps:function(e,t){return{action:l({class:this.cx("action"),tabindex:-1,"aria-hidden":!0},this.getPTOptions("action",e,t)),icon:l({class:[this.cx("icon"),this.getItemProp(e,"icon")]},this.getPTOptions("icon",e,t)),label:l({class:this.cx("label")},this.getPTOptions("label",e,t)),submenuicon:l({class:this.cx("submenuIcon")},this.getPTOptions("submenuicon",e,t))}}},components:{AngleRightIcon:N},directives:{ripple:D}},U=["tabindex"],H=["id","aria-label","aria-disabled","aria-expanded","aria-haspopup","aria-level","aria-setsize","aria-posinset","data-p-highlight","data-p-focused","data-p-disabled"],Z=["onClick","onMouseenter","onMousemove"],W=["href","target"],j=["id"],X=["id"];function Y(i,e,t,a,r,n){var o=y("AngleRightIcon"),h=y("ContextMenuSub",!0),b=T("ripple");return u(),v(E,l({name:"p-contextmenusub",onEnter:n.onEnter},i.ptm("menu.transition")),{default:k(function(){return[t.root||t.visible?(u(),I("ul",l({key:0,ref:"container",tabindex:t.tabindex},i.ptm("menu")),[(u(!0),I(L,null,O(t.items,function(s,c){return u(),I(L,{key:n.getItemKey(s)},[n.isItemVisible(s)&&!n.getItemProp(s,"separator")?(u(),I("li",l({key:0,id:n.getItemId(s),style:n.getItemProp(s,"style"),class:[i.cx("menuitem",{processedItem:s}),n.getItemProp(s,"class")],role:"menuitem","aria-label":n.getItemLabel(s),"aria-disabled":n.isItemDisabled(s)||void 0,"aria-expanded":n.isItemGroup(s)?n.isItemActive(s):void 0,"aria-haspopup":n.isItemGroup(s)&&!n.getItemProp(s,"to")?"menu":void 0,"aria-level":t.level+1,"aria-setsize":n.getAriaSetSize(),"aria-posinset":n.getAriaPosInset(c)},n.getPTOptions("menuitem",s,c),{"data-p-highlight":n.isItemActive(s),"data-p-focused"Line truncated
|
||||
Loaded 100 of 686 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user