Compare commits

..
208 Commits
Author SHA1 Message Date
devlikepro a9171addde [core] 2024.9.2
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-29 09:14:16 +07:00
devlikepro 440ac087ad [core] Cannot read properties of null (reading 'conversation')
fix #521
2024-08-29 09:14:16 +07:00
devlikepro 9dd5eb4eeb [core] dashboard
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-27 17:20:57 +07:00
devlikepro 26c2c9abc9 [core] Fix default session 2024-08-27 16:54:25 +07:00
devlikepro 663b07c07e [core] 2024.9.1 2024-08-27 16:44:36 +07:00
devlikepro 5add6a0e73 [core] up dashboard 2024-08-27 16:44:36 +07:00
devlikepro 5c4912feb4 [core] accept localhost url 2024-08-27 16:44:25 +07:00
devlikepro 75e115f390 [core] NOWEB - Handle both format for reply_to - full and only message id 2024-08-27 16:44:24 +07:00
devlikepro 8e443d23f4 [core] Add reply_to for incoming messages
Fixes #506
2024-08-27 16:44:24 +07:00
devlikepro c43c9c319b [core] Comment this 2024-08-27 16:44:24 +07:00
devlikepro e32b128b0f [core] Add reply to for all messages
fixes #503
2024-08-27 16:44:23 +07:00
devlikepro 5287421cea [core] Add location example 2024-08-27 16:43:39 +07:00
devlikepro 9bc95ef350 [core] fix delete message 2024-08-27 16:43:38 +07:00
devlikepro 028de6addb [core] cached eslint 2024-08-27 16:43:36 +07:00
devlikepro a107605937 [core] media error 2024-08-27 16:43:36 +07:00
devlikepro cec5d0147b [core] Move media dto 2024-08-27 16:43:35 +07:00
devlikepro e46b879fc4 [core] Add WHATSAPP_API_SCHEMA 2024-08-27 16:43:34 +07:00
devlikepro b6764fbb29 [core] Add WHATSAPP_API_SCHEMA 2024-08-27 16:43:33 +07:00
devlikepro e8899cc314 [core] Do not validate body on deprecated endpoints 2024-08-27 16:43:32 +07:00
devlikepro 2b2054dd6b [core] WEJBS add more optimization 2024-08-27 16:43:32 +07:00
devlikepro 92705b0ae2 [core] sort args 2024-08-27 16:43:32 +07:00
devlikepro 2ae8a36b7f [core] Up NOWEB 2024-08-27 16:43:32 +07:00
devlikepro 899139dda1 [core] ignore all files requests in http access logs 2024-08-27 16:43:32 +07:00
devlikepro b6b571e84b [core] proxy s3 files 2024-08-27 16:43:29 +07:00
devlikepro 9e098fa997 [core] move "schema" to main config.service.ts 2024-08-27 16:43:28 +07:00
devlikepro 13d00f954f [core] add Storage tag 2024-08-27 16:43:27 +07:00
devlikepro fee75d0c8a [core] WEBJS - optimize media 2024-08-27 16:43:26 +07:00
devlikepro abae3f14cd [core] NOWEB - optimize media 2024-08-27 16:43:25 +07:00
devlikepro b8a98e2c6e [core] WAHA_S3_FORCE_PATH_STYLE to docker-compose.yaml 2024-08-27 16:43:25 +07:00
devlikepro d990572b5b [core] Move files config 2024-08-27 16:43:24 +07:00
devlikepro 2d37d392bc [core] add pre-commit 2024-08-27 16:43:22 +07:00
devlikepro 59015fc3bb [core] Remove ConsoleLogger 2024-08-27 16:43:21 +07:00
devlikepro c3be68f988 [core] init for MediaStorage 2024-08-27 16:43:21 +07:00
devlikepro 8610784958 [core] add minio to docker-compose.yaml 2024-08-27 16:43:19 +07:00
devlikepro f01d71c34a [core] fix mongo service 2024-08-27 16:43:18 +07:00
devlikepro a06501e4b1 [core] Add filename 2024-08-27 16:43:16 +07:00
devlikepro 7c2c30fa1b [core] Add session to media 2024-08-27 16:43:16 +07:00
devlikepro 903dc714f2 [core] add s3 data to media 2024-08-27 16:43:16 +07:00
devlikepro b1bd2c8805 [core] Move GET /sendText down 2024-08-27 16:43:16 +07:00
devlikepro 0e4b4f6d8c [core] Stop process if bootstrap failed 2024-08-27 16:43:13 +07:00
devlikepro d8d0eaf247 [core] use modules for media storages 2024-08-27 16:43:13 +07:00
devlikepro 90096faef3 [core] Refactoring media manager 2024-08-27 16:43:13 +07:00
devlikepro f794f75394 [core] Move media files, rename classes 2024-08-27 16:43:09 +07:00
devlikepro 8de63e486c [core] install s3 2024-08-27 16:43:09 +07:00
devlikepro 4308efca47 [core] ignore .media 2024-08-27 16:43:08 +07:00
devlikepro 877fa292d6 [core] ignore .minio 2024-08-27 16:43:07 +07:00
devlikepro df6ea6f497 [core] add types for withLock 2024-08-27 16:43:06 +07:00
devlikepro 5e9be391e1 [core] Add UV_THREADPOOL_SIZE in docker 2024-08-27 16:43:04 +07:00
devlikepro 49960b8234 [core] update NOWEB 2024-08-27 16:43:03 +07:00
devlikepro d669dbe54b [core] Use new API to create a session 2024-08-27 16:43:03 +07:00
devlikepro 2d1859ac0c [core] Check session "name" length 2024-08-27 16:43:01 +07:00
devlikepro dc864055a3 [core] NOWEB - new newsletter actions 2024-08-27 16:43:00 +07:00
devlikepro bad9537aba [core] NOWEB - use fork-master-channels-2 branch 2024-08-27 16:43:00 +07:00
devlikepro 303b1adc0a [core] add emojies to tags 2024-08-27 16:42:58 +07:00
devlikepro c582904d41 [core] Add doc for /api/server/stop 2024-08-27 16:42:58 +07:00
devlikepro 65eabf6153 [core] Simplify /api/server/status 2024-08-27 16:42:58 +07:00
devlikepro cc9c9e2253 [core] /api/server swagger fix 2024-08-27 16:42:57 +07:00
devlikepro 8747ae9564 [core] logging for websocket 2024-08-27 16:42:56 +07:00
devlikepro 9253e54958 [core] API to restart server (actually it's /stop, but docker will handle restart) 2024-08-27 16:42:55 +07:00
devlikepro fb774f2caa [core] Adjust swagger for sendSeen
fixed #485
2024-08-27 16:42:55 +07:00
devlikepro ba120024a6 [core] Add metadata 2024-08-27 16:42:54 +07:00
devlikepro 1fe0e69914 [core] Make /start idempotent 2024-08-27 16:42:54 +07:00
devlikepro 0fe04e411c [core] 3s 2024-08-27 16:42:54 +07:00
devlikepro 35074f959f [core] check directory exists 2024-08-27 16:42:53 +07:00
devlikepro 0d698fbaf1 [core] fix log for unhandled rejection 2024-08-27 16:42:52 +07:00
devlikepro c9e2a52327 [core] check is running 2024-08-27 16:42:51 +07:00
devlikepro a58e06109b [core] PUT /api/sessions/{session} 2024-08-27 16:42:50 +07:00
devlikepro 65375e4836 [core] wait until, so we don't close a websocket on connecting 2024-08-27 16:42:49 +07:00
devlikepro edc517d33f [core] Add deprecated API to lock as well 2024-08-27 16:42:49 +07:00
devlikepro 354c82dc34 [core] timeout after stop a session 2024-08-27 16:42:48 +07:00
devlikepro fe2acd0665 [core] wait for a browser 2024-08-27 16:42:48 +07:00
devlikepro 19b5b1a90c [core] await for a client 2024-08-27 16:42:47 +07:00
devlikepro e7281e2118 [core] Add /api/sessions/{session}/restart 2024-08-27 16:42:45 +07:00
devlikepro 10f334cf15 [core] Log when session started 2024-08-27 16:42:45 +07:00
devlikepro a057fd6458 [core] Add timestamp run 2024-08-27 16:42:43 +07:00
devlikepro 3bafabeb0a [core] Add withLock for dangerous session operations 2024-08-27 16:42:43 +07:00
devlikepro edefbe17da [core] webjs log error 2024-08-27 16:42:42 +07:00
devlikepro a65041ffcd [core] DELETE /api/sessions/{session}/ 2024-08-27 16:42:42 +07:00
devlikepro 0962c60844 [core] DELETE /api/sessions/{session}/ 2024-08-27 16:42:42 +07:00
devlikepro 3d72eceac0 [core] Add /api/sessions/{session}/stop 2024-08-27 16:42:41 +07:00
devlikepro 57b5deff5b [core] Add /api/sessions/{session}/start 2024-08-27 16:42:40 +07:00
devlikepro 1163dee352 [core] uuid4 2024-08-27 16:42:39 +07:00
devlikepro f7fe562bba [core] Add POST /api/sessions
fixes #435
2024-08-27 16:42:39 +07:00
devlikepro 3394f98a8a [core] rm aka 2024-08-27 16:42:38 +07:00
devlikepro a575b35286 [core] Adjust session param 2024-08-27 16:42:36 +07:00
devlikepro 0f41e79e98 [core] Add sessions.deprecated.dto 2024-08-27 16:42:36 +07:00
devlikepro 24bf22a31f [core] Adjust sessions Swagger 2024-08-27 16:42:35 +07:00
devlikepro 05a1b8802e [core] Add swagger api key (forgot about it) 2024-08-27 16:42:34 +07:00
devlikepro 9c409d9507 [core] Simplify actions for manager 2024-08-27 16:42:34 +07:00
devlikepro 4ee7161c36 [core] Warning if client is not destroyed 2024-08-27 16:42:34 +07:00
devlikepro 4cd9ce0ff7 [core] Wait till the store is closed 2024-08-27 16:42:30 +07:00
devlikepro a2d0dfd8b2 [core] Add Old prefix for old methods 2024-08-27 16:42:30 +07:00
devlikepro d4164fe0ba [core] Add fs-extra 2024-08-27 16:42:29 +07:00
devlikepro 6bbecdd7c0 [core] Keep .waha.session. files in directory and remove it in LocalSessionConfigRepository.ts 2024-08-27 16:42:26 +07:00
devlikepro 0784c3ae05 [core] move getAll sessions to session config repo 2024-08-27 16:42:26 +07:00
devlikepro 679757ccfa [core] check is array object
fixes #470
2024-08-27 16:42:25 +07:00
devlikepro 63a4e693e3 [core] Move helpers to nestjs 2024-08-27 16:42:24 +07:00
devlikepro b21041d9e0 [core] Validate session config
fix #470
2024-08-27 16:42:24 +07:00
devlikepro f014bb4587 [core] Add /api/server/environment
fixes #319
2024-08-27 16:42:24 +07:00
devlikepro 9030f7c4ce [core] 2024.8.5
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-23 08:20:27 +07:00
devlikepro bde6c38bd4 [core] up NOWEB 2024-08-23 08:20:03 +07:00
devlikepro 0aefb6c6ec [core] 2024.8.4
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-18 16:45:05 +07:00
devlikepro da650ccdef [core] Fix get chats with limit offset properties
fixes #486
2024-08-18 14:21:33 +07:00
devlikepro 92d3e70c1f [core] 2024.8.3
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-14 15:49:36 +07:00
devlikepro cb5dfaf066 [core] Remove NEW from dashboard 2024-08-14 15:49:36 +07:00
devlikepro cd75e5e4cc [core] auto reconnection fix - reduce to 28 minutes and check if websocket is not connecting
fixes #483
2024-08-14 15:49:36 +07:00
devlikepro 7bd6ab5ec0 [core] 2024.8.2
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-07 17:29:11 +07:00
devlikepro 92f9c89cf1 [core] add WAHA_HTTP_LOG_LEVEL
fixed #466
2024-08-07 17:29:11 +07:00
devlikepro eb2632b23a [core] Fix noweb autorestart timing 2024-08-07 17:29:10 +07:00
devlikepro 8c90bc6808 [core] logger warning 2024-08-07 17:29:10 +07:00
devlikepro 66146532e1 [core] fix WEBJS constant restart 2024-08-07 17:29:10 +07:00
devlikepro dbf3a41c1d [core] Bump WEBJS 2024-08-07 17:29:10 +07:00
devlikepro 942bbf9c6c [core] Add sleep 2024-08-07 17:29:09 +07:00
devlikepro a9d7cc527c [core] Use SingleDelayedJobRunner in WEBJS 2024-08-07 17:29:09 +07:00
devlikepro 2d362722ed [core] Use SingleDelayedJobRunner 2024-08-07 17:29:09 +07:00
devlikepro f81638e625 [core] Use SinglePeriodicJobRunner to rerun session 2024-08-07 17:29:08 +07:00
devlikepro 8ae77df0ff [core] Add SingleDelayedJobRunner 2024-08-07 17:29:08 +07:00
devlikepro 110bd0e5f7 [core] Add SinglePeriodicJobRunner 2024-08-07 17:29:08 +07:00
devlikepro 1b3a366cb7 [core] Add test.* to ignore 2024-08-07 17:29:07 +07:00
devlikepro 3b5d9a145f [core] Rename WebsocketHeartbeatJob.ts 2024-08-07 17:29:07 +07:00
devlikepro fc37fc067a [core] Install zip and unzip in docker image 2024-08-07 17:29:07 +07:00
devlikepro bb18a28484 [core] Add pretty-bytes 2024-08-07 17:29:06 +07:00
devlikepro 86ca08b9aa [core] 2024.8.1
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-08-04 10:22:16 +07:00
devlikepro 9522df7835 [core] Bump dashboard 2024-08-04 10:22:16 +07:00
devlikepro 55e0fd0226 [core] rename .removed to .deleted 2024-08-04 10:22:16 +07:00
devlikepro ff9a986a2e [core] Fix for chat id in labels events 2024-08-04 10:09:44 +07:00
devlikepro df31fe2a8b [core] NOWEB labels 2024-08-04 10:09:32 +07:00
devlikepro 1aeaf996bc [core] make up-engine commands 2024-08-04 10:09:32 +07:00
devlikepro cb0e59e91a [core] Print original error, not pino one 2024-08-04 10:09:32 +07:00
devlikepro 5f02f49e9d [core] Add other /labels endpoints 2024-08-04 10:09:32 +07:00
devlikepro ce9f91fe2c [core] Use /api/{session}/labels 2024-08-04 10:09:32 +07:00
devlikepro ac37745721 [core] Add type 2024-08-04 10:09:31 +07:00
aziz e44aeefda8 [core] chore: Add LabelsController to handle label-related API requests 2024-08-04 10:08:58 +07:00
devlikepro dbff2b659a [core] Fix swagger docs 2024-08-04 10:07:09 +07:00
devlikepro 52ef8e8b76 [core] Add /ping 2024-08-04 10:07:08 +07:00
devlikepro b71567c754 [core] exclude path from api-key
fixes #451
2024-08-04 10:07:08 +07:00
devlikepro d1670c743f [core] Add "sessions.name" index for MongoDB
closes #447
2024-08-04 10:06:43 +07:00
devlikepro 009b38f471 [core] Add call.* events
closes #307
2024-08-04 10:06:43 +07:00
devlikepro 0cf5f30c0d [core] Add timestamp to chat.archive 2024-08-04 10:06:42 +07:00
devlikepro cd4e1f179d [core] Add chat.archive event
closes #434
2024-08-04 10:06:42 +07:00
devlikepro b89f9d6b35 [core] Add chats /archive and /unarchive
fixes #434
2024-08-04 10:06:42 +07:00
devlikepro c3ece96390 [core] Remove html 2024-08-02 09:05:31 +07:00
devlikepro 770739b44e [core] Add pdf example 2024-08-01 13:44:37 +07:00
devlikepro 84984c2cde [core] Up chrome version 2024-07-31 17:10:19 +07:00
devlikepro 86393c8674 [core] 2024.7.7
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-24 19:02:03 +03:00
devlikepro d4aed3bc45 [core] pin adm-zip 0.5.10
trying to work on #457
2024-07-24 19:01:44 +03:00
devlikepro 818cd77450 [core] key 2024-07-23 10:37:37 +03:00
devlikepro dc26c70400 [core] waha-run 2024-07-23 10:28:52 +03:00
devlikepro 6547d713ea [core] remove version from docker 2024-07-23 10:03:41 +03:00
devlikepro e8dcb0c242 [core] Add full docker-compose.yaml 2024-07-23 09:46:47 +03:00
devlikepro 100d0be513 [core] 2024.7.6
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-18 17:41:38 +03:00
devlikepro fc8db2d977 [core] WEBJS update 2024-07-18 17:41:31 +03:00
devlikepro e5d98d7889 [core] ignore /dashboard logs 2024-07-18 17:40:47 +03:00
devlikepro c7b1a05ed3 [core] Download dashboard 2024-07-15 18:46:43 +03:00
devlikepro 649a90bd5e [core] Keep dashboard 2024-07-15 17:56:04 +03:00
devlikepro 0fc880cf21 [core] Keep dashboard 2024-07-15 17:55:54 +03:00
devlikepro 0d82a4c2c6 [core] Remove dashboard 2024-07-15 17:54:38 +03:00
devlikepro fb3aa59683 [core] 2024.7.5
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-15 16:03:08 +03:00
devlikepro b938792ca8 [core] channels 2024-07-15 16:02:51 +03:00
devlikepro bb74946d54 [core] bump 2024.7.4
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-08 15:02:36 +03:00
devlikepro 3e78105509 [core] fix profile picture
closes #422
2024-07-08 15:02:36 +03:00
devlikepro c6adf0ac89 [core] console.log for webjs 2024-07-05 14:04:03 +03:00
devlikepro 219b4dca94 [core] pretty logs by default 2024-07-05 13:40:13 +03:00
devlikepro acec292b0f [core] 2024.7.3 2024-07-05 13:30:47 +03:00
devlikepro 7ba86cbd23 [core] logging 2024-07-05 13:30:08 +03:00
devlikepro 3002eaf479 [core] Init Logger in manager explicitly 2024-07-05 13:30:05 +03:00
devlikepro 15422ca504 [core] 2024.7.2
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-04 12:11:43 +03:00
devlikepro 7067f00bee [core] Up WEBJS engine 2024-07-04 12:11:43 +03:00
devlikepro a0616eb251 [core] 2024.7.1
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-07-03 10:58:33 +03:00
devlikepro 5d4da0e4c7 [core] No cache while waiting 2.3xx release 2024-07-03 10:56:33 +03:00
devlikepro 546e3475fb [core] mark GET sendText as deprecated
closes #406
2024-07-03 09:15:38 +03:00
devlikepro 56c44ebb58 [core] 2.3000
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-06-27 15:25:33 +07:00
devlikepro bd03bc730c [core] Remove 2.3000 2024-06-27 15:25:00 +07:00
devlikepro e0e1e58104 [core] 2024.6.8 2024-06-27 15:19:41 +07:00
devlikepro 940de662b6 [core] WEBJS 2.3000 2024-06-27 15:19:41 +07:00
devlikepro d151c1192b [core] update webjs 2024-06-27 15:19:41 +07:00
devlikepro 15ae10579c [core] use fork 2024-06-27 15:19:41 +07:00
devlikepro 359696408d [core] 2024.6.7
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-06-25 13:36:40 +07:00
devlikepro d3766368f8 [core] delete status endpoint 2024-06-25 13:36:40 +07:00
devlikepro 73af7451fc [core] Use NOWEB fork with fixes
fixes #390
2024-06-25 11:58:24 +07:00
devlikepro e27fcefe45 [core] fix #373 2024-06-24 19:50:22 +07:00
devlikepro aa5ade5517 [core] Remove link to project
Fix #373
2024-06-24 19:43:20 +07:00
devlikepro 94b6a66ce4 [core] dashboard 2024-06-24 19:16:28 +07:00
devlikepro a51e486fa6 [core] timeout 10ms 2024-06-24 19:10:07 +07:00
devlikepro 2b608daea4 update dashboard 2024-06-24 18:50:38 +07:00
devlikepro aa60c2afd1 [core] warning 2024-06-24 18:49:26 +07:00
devlikepro cff22c74a9 [core] Fix sock auth 2024-06-24 18:43:23 +07:00
devlikepro b77b8ee0da [core] timeout for getEngineInfo, logs 2024-06-24 18:41:42 +07:00
devlikepro 610aef2f14 [core] Make getSessionMeInfo sync 2024-06-24 18:41:42 +07:00
devlikepro e15ca41d6e [core] websockets 2024-06-24 17:38:44 +07:00
devlikepro 60e9e53af4 [core] issue session.status, not session.status.changed 2024-06-24 17:36:20 +07:00
devlikepro 9812000724 [core] debug by default in NOWEB 2024-06-21 12:17:12 +07:00
devlikepro d72401fc39 [core] Add msgRetryCounterCache 2024-06-20 14:21:00 +07:00
devlikepro 822eba7982 [core] keepAliveIntervalMs back to 30s 2024-06-19 16:20:01 +07:00
devlikepro 9327564e6e [core] set defaultQueryTimeoutMs to 120s 2024-06-19 16:20:01 +07:00
devlikepro 6e9fe42a83 [core] bump version 2024-06-19 12:55:14 +07:00
devlikepro a32cf28ccb [core] fix forever "typing" status
fix #379
2024-06-19 12:54:43 +07:00
devlikepro 55b101802a [core] no more ssh 2024-06-19 12:04:11 +07:00
devlikepro ecda8b4394 [core] set "trace" by default for noweb 2024-06-19 12:04:09 +07:00
devlikepro 6d4f8d4c26 [core] Add logger to NOWEB engine 2024-06-19 11:30:41 +07:00
devlikepro 26aa53f3fa Use webhook.site 2024-06-18 11:18:39 +07:00
devlikepro 2f7a94ea3f [core] dashboard update
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-06-18 11:02:16 +07:00
devlikepro 2b622b4ee9 [core] dashboard 2024-06-18 10:55:41 +07:00
devlikepro 3e280f1e08 [core] Bump version to 2024.6.5 2024-06-18 10:51:02 +07:00
devlikepro c54d52ad45 [core] built in ssl 2024-06-18 10:50:44 +07:00
devlikepro e54d3ea96b [core] fix for-swagger 2024-06-17 10:56:04 +07:00
devlikepro e07cb8257d [core] Bump to 2024.6.4
Release / amd64 - chrome - chrome (push) Waiting to run
Release / amd64 - chromium - latest (push) Waiting to run
Release / linux/arm64 - chromium - arm (push) Waiting to run
Release / amd64 - none - noweb (push) Waiting to run
Release / linux/arm64 - none - noweb-arm (push) Waiting to run
2024-06-17 10:37:11 +07:00
devlikepro 74b6a8fdba [core] add chats limit and offset 2024-06-17 10:36:51 +07:00
680 changed files with 7024 additions and 850235 deletions

No files matched your search

+7
View File
@@ -1,12 +1,19 @@
.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
View File
@@ -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|
)$
+38
View File
@@ -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())
+31 -9
View File
@@ -6,23 +6,33 @@ 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 .
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 c1a91f879a35f0ae32d46ddb2e061ac1819a3d4f
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 +48,9 @@ RUN echo "USE_BROWSER=$USE_BROWSER"
# Install ffmpeg to generate previews for videos
RUN apt-get update && apt-get install -y ffmpeg --no-install-recommends && rm -rf /var/lib/apt/lists/*
# Install zip and unzip
RUN apt-get update && apt-get install -y zip unzip --no-install-recommends && rm -rf /var/lib/apt/lists/*
# Install fonts if using either chromium or chrome
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
apt-get update \
@@ -58,7 +71,7 @@ RUN if [ "$USE_BROWSER" = "chromium" ]; then \
# Install Chrome
# Available versions:
# https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable
ARG CHROME_VERSION="122.0.6261.128-1"
ARG CHROME_VERSION="126.0.6478.182-1"
RUN if [ "$USE_BROWSER" = "chrome" ]; then \
wget --no-verbose -O /tmp/chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
&& apt-get update \
@@ -72,7 +85,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"]
+6 -5
View File
@@ -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
+1 -1
View File
@@ -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:
+114
View File
@@ -0,0 +1,114 @@
services:
waha:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha
container_name: waha
ports:
- '3000:3000/tcp'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# https://docs.webhook.site/
- WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
- WHATSAPP_HOOK_EVENTS=message
- WHATSAPP_DEFAULT_ENGINE=WEBJS
restart: always
waha-plus:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus
ports:
- '3000:3000/tcp'
volumes:
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_HOSTNAME=localhost
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_API_KEY=321
# Username and password for Swagger
- WHATSAPP_SWAGGER_USERNAME=swagger
- WHATSAPP_SWAGGER_PASSWORD=admin
# Username and password for WAHA Dashboard
# you can use the same username and password for both Swagger and Dashboard
# Default - waha / waha
- WAHA_DASHBOARD_USERNAME=waha
- WAHA_DASHBOARD_PASSWORD=waha
# Engine specific environment variables
# - WAHA_WEBJS_WEB_VERSION=2.2412.54-videofix
restart: always
waha-plus--mongodb:
# Check available Docker images:
# https://waha.devlike.pro/docs/how-to/engines/#docker-images
image: devlikeapro/waha-plus:chrome
container_name: waha-plus--mongodb
ports:
- '3000:3000/tcp'
volumes:
- './.sessions:/app/.sessions'
environment:
# Environment variables from https://waha.devlike.pro/docs/how-to/config/
# - WHATSAPP_RESTART_ALL_SESSIONS=True
# - WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# - WHATSAPP_HOOK_EVENTS=message
# - WHATSAPP_API_KEY=321
# - WHATSAPP_SWAGGER_USERNAME=admin
# - WHATSAPP_SWAGGER_PASSWORD=123
# - WAHA_DASHBOARD_USERNAME=admin
# - WAHA_DASHBOARD_PASSWORD=123
# - WHATSAPP_API_HOSTNAME=localhost
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
restart: always
# Let's Encrypt + Certbot
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--certbot:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- '/etc/letsencrypt:/etc/letsencrypt'
environment:
- DOMAIN=waha.example.pro
- WHATSAPP_API_HOSTNAME=${DOMAIN}
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem
- WAHA_HTTPS_PATH_CERT=/etc/letsencrypt/live/${DOMAIN}/cert.pem
- WAHA_HTTPS_PATH_CA=/etc/letsencrypt/live/${DOMAIN}/chain.pem
# Self-signed certificates example
# https://waha.devlike.pro/docs/how-to/security/#https
waha-https--self-signed:
image: devlikeapro/waha-plus
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './.sessions:/app/.sessions'
- './.secrets:/app/.secrets'
environment:
- WAHA_HTTPS_ENABLED=true
- WAHA_HTTPS_PATH_KEY=.secrets/privkey.pem
- WAHA_HTTPS_PATH_CERT=.secrets/cert.pem
- WAHA_HTTPS_PATH_CA=.secrets/chain.pem
mongodb:
image: mongo
container_name: mongodb
ports:
- '27017:27017/tcp'
volumes:
- mongodb_data:/data/db
restart: always
volumes:
mongodb_data: {}
+216 -53
View File
@@ -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
#
- WAHA_LOG_FORMAT=PRETTY
# Set log format to JSON if you consume logs with log management systems
#- WAHA_LOG_FORMAT=JSON
- WAHA_LOG_LEVEL=info
# If you want to see more logs, you can set the log level to debug
#- WAHA_LOG_LEVEL=debug
# DEBUG=1 # shortcut for setting log level to debug
#
# Engine
#
# Choose the right engine for your needs (WEBJS by default)
# https://waha.devlike.pro/docs/how-to/engines/
- WHATSAPP_DEFAULT_ENGINE=WEBJS
- WHATSAPP_SESSIONS_MONGO_URL=mongodb://mongodb:27017
restart: always
# Use NOWEB engine for the fastest performance
#- WHATSAPP_DEFAULT_ENGINE=NOWEB
#
# 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
View File
@@ -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
yarn start:prod
Binary file not shown.
+2 -2
View File
@@ -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)
+19 -4
View File
@@ -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",
"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",
@@ -63,7 +78,7 @@
"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",
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
set -e
echo "Starting WAHA..."
docker run -d \
--restart=always \
--name waha \
-p 3000:3000/tcp \
-v ./.sessions:/app/.sessions \
-v ./.media:/app/.media \
--env WHATSAPP_API_KEY=321 \
--env WAHA_DASHBOARD_USERNAME=waha \
--env WAHA_DASHBOARD_PASSWORD=waha \
--env WAHA_LOG_FORMAT=PRETTY \
--env WAHA_LOG_LEVEL=info \
--env WHATSAPP_DEFAULT_ENGINE=WEBJS \
--env WHATSAPP_RESTART_ALL_SESSIONS=True \
--env WAHA_PRINT_QR=False \
--env WHATSAPP_FILES_LIFETIME=0 \
--env WHATSAPP_FILES_FOLDER=/app/.media \
devlikeapro/waha-plus:latest
echo "WAHA started."
+21
View File
@@ -0,0 +1,21 @@
set -e
echo "Updating WAHA..."
echo "Logging in to Docker..."
docker login -u devlikeapro # -p {KEY} - you can hard code key here https://portal.devlike.pro/
echo "Pulling the latest image..."
docker pull devlikeapro/waha-plus
echo "Logging out of Docker..."
docker logout
# Just pull if you're using WAHA Core
# docker pull devlikeapro/waha
echo "Stopping the current container..."
docker stop waha || true
echo "Removing the current container..."
docker rm waha || true
echo "Running WAHA..."
sh ./waha-run.sh
+7 -3
View File
@@ -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,12 +27,10 @@ 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) {}
+122
View File
@@ -0,0 +1,122 @@
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 - either by id @newsletter OR invite code.',
})
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);
}
}
+39 -11
View File
@@ -7,32 +7,38 @@ 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')
@@ -93,6 +99,28 @@ class ChatsController {
) {
return session.editMessage(chatId, messageId, body);
}
@Post(':chatId/archive')
@SessionApiParam
@ChatIdApiParam
@ApiOperation({ summary: 'Archive the chat' })
archiveChat(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
) {
return session.chatsArchiveChat(chatId);
}
@Post(':chatId/unarchive')
@SessionApiParam
@ChatIdApiParam
@ApiOperation({ summary: 'Unarchive the chat' })
unarchiveChat(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
) {
return session.chatsUnarchiveChat(chatId);
}
}
export { ChatsController };
+22 -18
View File
@@ -26,7 +26,7 @@ import { WAMessage } from '../structures/responses.dto';
@ApiSecurity('api_key')
@Controller('api')
@ApiTags('chatting')
@ApiTags('📤 Chatting')
export class ChattingController {
constructor(private manager: SessionManager) {}
@@ -45,16 +45,6 @@ export class ChattingController {
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> {
@@ -123,13 +113,6 @@ export class ChattingController {
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);
@@ -172,4 +155,25 @@ export class ChattingController {
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('/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);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ import { ContactQuery, ContactRequest } from '../structures/contacts.dto';
@ApiSecurity('api_key')
@Controller('api/contacts')
@ApiTags('contacts')
@ApiTags('👤 Contacts')
export class ContactsController {
constructor(private manager: SessionManager) {}
+5 -2
View File
@@ -8,6 +8,10 @@ import {
Put,
} 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';
@@ -18,11 +22,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) {}
+6 -2
View File
@@ -1,16 +1,20 @@
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, performing all health checks.',
})
async check() {
return this.wahaHealth.check();
}
-96
View File
@@ -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),
},
},
},
}),
);
}
+55
View File
@@ -0,0 +1,55 @@
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 {
SessionApiParam,
SessionParam,
} from '@waha/nestjs/params/SessionApiParam';
import { Label, LabelID, SetLabelsRequest } from '@waha/structures/labels.dto';
import { SessionManager } from '../core/abc/manager.abc';
@ApiSecurity('api_key')
@Controller('api/:session/labels')
@ApiTags('🏷️ Labels')
export class LabelsController {
constructor(private manager: SessionManager) {}
@Get('/')
@SessionApiParam
@ApiOperation({ summary: 'Get all labels' })
getAll(@SessionParam session: WhatsappSession): Promise<Label[]> {
return session.getLabels();
}
@Get('/chats/:chatId')
@SessionApiParam
@ApiOperation({ summary: 'Get labels for the chat' })
getChatLabels(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
): Promise<Label[]> {
return session.getChatLabels(chatId);
}
@Put('/chats/:chatId')
@SessionApiParam
@ApiOperation({ summary: 'Save labels for the chat' })
putChatLabels(
@SessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
@Body() request: SetLabelsRequest,
) {
return session.putLabelsToChat(chatId, request.labels);
}
@Get('/:labelId/chats')
@SessionApiParam
@ApiOperation({ summary: 'Get chats by label' })
getChatsByLabel(
@SessionParam session: WhatsappSession,
@Param('labelId') labelId: string,
) {
return session.getChatsByLabelId(labelId);
}
}
+14
View File
@@ -0,0 +1,14 @@
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, perform no operations.' })
ping(): PingResponse {
return { message: 'pong' };
}
}
+5 -2
View File
@@ -7,6 +7,10 @@ import {
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';
@@ -15,11 +19,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) {}
+3 -3
View File
@@ -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) {}
+107
View File
@@ -0,0 +1,107 @@
import * as process from 'node:process';
import {
Body,
Controller,
Get,
Logger,
Post,
Query,
UsePipes,
} from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
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: 'Return 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: '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);
}
}
}
+256 -48
View File
@@ -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,231 @@ 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;
if (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 };
+16 -2
View File
@@ -8,20 +8,24 @@ import {
Query,
} 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) {}
@@ -64,6 +68,16 @@ class StatusController {
) {
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 };
+8 -2
View File
@@ -1,14 +1,20 @@
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 version of the server', deprecated: true })
get(): WAHAEnvironment {
return VERSION;
}
+17 -21
View File
@@ -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',
+24 -13
View File
@@ -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',
+3 -1
View File
@@ -1 +1,3 @@
export abstract class DataStore {}
export abstract class DataStore {
abstract init(sessionName?: string): Promise<void>;
}
+6 -4
View File
@@ -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
View File
@@ -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);
};
}
}
-28
View File
@@ -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 };
+139 -36
View File
@@ -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,48 @@ 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-speech-api',
'--disable-sync',
'--disable-translate',
'--disable-web-security',
'--disk-cache-size=0',
'--hide-scrollbars',
'--ignore-certificate-errors',
'--ignore-ssl-errors',
'--metrics-recording-only',
'--mute-audio',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--no-sandbox',
'--no-zygote',
'--password-store=basic',
'--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 +209,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 +243,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 +307,7 @@ export abstract class WhatsappSession {
/**
* Chats methods
*/
public getChats() {
public getChats(query: GetChatsQuery) {
throw new NotImplementedByEngineError();
}
@@ -317,6 +339,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 +485,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 +545,10 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError();
}
public deleteStatus(request: DeleteStatusRequest) {
throw new NotImplementedByEngineError();
}
public async getEngineInfo(): Promise<any> {
return {};
}
@@ -485,14 +580,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}`;
}
+6 -2
View File
@@ -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);
+140
View File
@@ -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));
});
}
}
+79 -27
View File
@@ -1,11 +1,23 @@
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 } 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 +25,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 +42,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 +100,19 @@ export const IMPORTS = [
export const CONTROLLERS = [
AuthController,
SessionsController,
SessionController,
ChattingController,
ChatsController,
ChannelsController,
StatusController,
LabelsController,
ContactsController,
GroupsController,
PresenceController,
ScreenshotController,
VersionController,
PingController,
HealthController,
ServerController,
VersionController,
];
const PROVIDERS = [
{
@@ -92,7 +131,8 @@ const PROVIDERS = [
SwaggerConfigServiceCore,
WhatsappConfigService,
EngineConfigService,
ConsoleLogger,
WebsocketGatewayCore,
MediaLocalStorageConfig,
];
@Module({
@@ -101,5 +141,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');
+7 -3
View File
@@ -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;
+6 -1
View File
@@ -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(
+511 -125
View File
@@ -4,32 +4,59 @@ import makeWASocket, {
DisconnectReason,
extractMessageContent,
getAggregateVotesInPollMessage,
getContentType,
getKeyAuthor,
getUrlFromDirectPath,
isJidGroup,
isJidStatusBroadcast,
isRealMessage,
jidNormalizedUser,
makeCacheableSignalKeyStore,
NewsletterMetadata,
normalizeMessageContent,
PresenceData,
proto,
WAMessageContent,
WAMessageKey,
} from '@adiwajshing/baileys';
import { WACallEvent } from '@adiwajshing/baileys/lib/Types/Call';
import { Label as NOWEBLabel } from '@adiwajshing/baileys/lib/Types/Label';
import { LabelAssociationType } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
import { Logger as BaileysLogger } from '@adiwajshing/baileys/node_modules/pino';
import { UnprocessableEntityException } from '@nestjs/common';
import { NowebInMemoryStore } from '@waha/core/engines/noweb/store/NowebInMemoryStore';
import { flipObject, getLogLevels, parseBool, splitAt } from '@waha/helpers';
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
import { flipObject, parseBool, splitAt } from '@waha/helpers';
import { PairingCodeResponse } from '@waha/structures/auth.dto';
import { CallData } from '@waha/structures/calls.dto';
import {
Channel,
ChannelRole,
CreateChannelRequest,
ListChannelsQuery,
} from '@waha/structures/channels.dto';
import { GetChatsQuery } from '@waha/structures/chats.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
Label,
LabelChatAssociation,
LabelID,
} from '@waha/structures/labels.dto';
import { ReplyToMessage } from '@waha/structures/message.dto';
import {
PollVote,
PollVotePayload,
WAMessageAckBody,
} from '@waha/structures/webhooks.dto';
import { waitUntil } from '@waha/utils/promiseTimeout';
import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
import { SinglePeriodicJobRunner } from '@waha/utils/SinglePeriodicJobRunner';
import * as Buffer from 'buffer';
import { Agent } from 'https';
import * as lodash from 'lodash';
import { toNumber } from 'lodash';
import * as NodeCache from 'node-cache';
import {
ChatRequest,
@@ -73,10 +100,15 @@ import {
WAMessageReaction,
} from '../../../structures/responses.dto';
import { MeInfo } from '../../../structures/sessions.dto';
import { BROADCAST_ID, TextStatus } from '../../../structures/status.dto';
import { IEngineMediaProcessor } from '../../abc/media.abc';
import {
BROADCAST_ID,
DeleteStatusRequest,
TextStatus,
} from '../../../structures/status.dto';
import {
ensureSuffix,
getChannelInviteLink,
isNewsletter,
WAHAInternalEvent,
WhatsappSession,
} from '../../abc/session.abc';
@@ -86,7 +118,6 @@ import {
} from '../../exceptions';
import { toVcard } from '../../helpers';
import { createAgentProxy } from '../../helpers.proxy';
import { buildLogger } from '../../manager.core';
import { QR } from '../../QR';
import { NowebAuthFactoryCore } from './NowebAuthFactoryCore';
import { INowebStore } from './store/INowebStore';
@@ -96,8 +127,6 @@ import { extractMediaContent } from './utils';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const QRCode = require('qrcode');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const logger = require('pino')();
export const BaileysEvents = {
CONNECTION_UPDATE: 'connection.update',
@@ -120,13 +149,15 @@ const ToEnginePresenceStatus = flipObject(PresenceStatuses);
export class WhatsappSessionNoWebCore extends WhatsappSession {
private START_ATTEMPT_DELAY_SECONDS = 2;
private AUTO_RESTART_AFTER_SECONDS = 30 * 60;
private AUTO_RESTART_AFTER_SECONDS = 28 * 60;
engine = WAHAEngine.NOWEB;
authFactory = new NowebAuthFactoryCore();
storageFactory = new NowebStorageFactoryCore();
private startTimeoutId: null | ReturnType<typeof setTimeout> = null;
private autoRestartTimeoutId: null | ReturnType<typeof setTimeout> = null;
private startDelayedJob: SingleDelayedJobRunner;
private autoRestartJob: SinglePeriodicJobRunner;
private msgRetryCounterCache: NodeCache;
protected engineLogger: BaileysLogger;
get listenConnectionEventsFromTheStart() {
return true;
@@ -139,14 +170,40 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
public constructor(config) {
super(config);
this.qr = new QR();
// external map to store retry counts of messages when decryption/encryption fails
// keep this out of the socket itself, to prevent a message decryption/encryption loop across socket restarts
this.msgRetryCounterCache = new NodeCache({
stdTTL: 60 * 60, // 1 hour
useClones: false,
});
this.engineLogger = this.loggerBuilder.child({
name: 'NOWEBEngine',
}) as unknown as BaileysLogger;
// Restart job if session failed
this.startDelayedJob = new SingleDelayedJobRunner(
'start-engine',
this.START_ATTEMPT_DELAY_SECONDS * SECOND,
this.logger,
);
// Enable auto-restart
const shiftSeconds = Math.floor(Math.random() * 30);
const delay = this.AUTO_RESTART_AFTER_SECONDS + shiftSeconds;
this.autoRestartJob = new SinglePeriodicJobRunner(
'auto-restart',
delay * SECOND,
this.logger,
);
}
start() {
async start() {
this.status = WAHASessionStatus.STARTING;
this.buildClient();
await this.buildClient();
}
getSocketConfig(agent, state) {
getSocketConfig(agent, state): any {
const fullSyncEnabled = this.sessionConfig?.noweb?.store?.fullSync || false;
const browser = fullSyncEnabled
? Browsers.ubuntu('Desktop')
@@ -157,19 +214,21 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
auth: {
creds: state.creds,
/** caching makes the store faster to send/recv messages */
keys: makeCacheableSignalKeyStore(state.keys, logger),
keys: makeCacheableSignalKeyStore(state.keys, this.engineLogger),
},
printQRInTerminal: false,
browser: browser,
logger: logger,
logger: this.engineLogger,
mobile: false,
defaultQueryTimeoutMs: undefined,
defaultQueryTimeoutMs: 120_000,
keepAliveIntervalMs: 30_000,
getMessage: (key) => this.getMessage(key),
syncFullHistory: fullSyncEnabled,
msgRetryCounterCache: this.msgRetryCounterCache,
};
}
async makeSocket() {
async makeSocket(): Promise<any> {
const { state, saveCreds } = await this.authFactory.buildAuth(
this.sessionStore,
this.name,
@@ -189,31 +248,32 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
async connectStore() {
this.log.debug(`Connecting store...`);
this.logger.debug(`Connecting store...`);
if (!this.store) {
this.log.debug(`Making a new store...`);
const levels = getLogLevels(false);
const log = buildLogger(`NowebStore - ${this.name}`, levels);
this.logger.debug(`Making a new store...`);
const storeEnabled = this.sessionConfig?.noweb?.store?.enabled || false;
if (storeEnabled) {
this.log.debug('Using NowebPersistentStore');
this.logger.debug('Using NowebPersistentStore');
const storage = this.storageFactory.createStorage(
this.sessionStore,
this.name,
);
this.store = new NowebPersistentStore(log, storage);
this.store = new NowebPersistentStore(
this.loggerBuilder.child({ name: NowebPersistentStore.name }),
storage,
);
await this.store.init().catch((err) => {
this.log.error(`Failed to initialize storage or store: ${err}`);
this.logger.error(`Failed to initialize storage or store: ${err}`);
this.status = WAHASessionStatus.FAILED;
this.end();
throw err;
});
} else {
this.log.debug('Using NowebInMemoryStore');
this.logger.debug('Using NowebInMemoryStore');
this.store = new NowebInMemoryStore();
}
}
this.log.debug(`Binding store to socket...`);
this.logger.debug(`Binding store to socket...`);
this.store.bind(this.sock.ev, this.sock);
}
@@ -226,6 +286,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
async buildClient() {
this.sock = await this.makeSocket();
this.issueMessageUpdateOnEdits();
this.issuePresenceUpdateOnMessageUpsert();
if (this.isDebugEnabled()) {
this.listenEngineEventsInDebugMode();
}
@@ -237,20 +298,15 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
this.enableAutoRestart();
}
protected enableAutoRestart() {
if (this.autoRestartTimeoutId) {
return;
}
// add random delay to avoid multiple restarts at the same time
const shiftSeconds = Math.floor(Math.random() * 30);
const delay = this.AUTO_RESTART_AFTER_SECONDS + shiftSeconds;
this.log.debug(`Auto-restart is enabled, after ${delay} seconds`);
this.autoRestartTimeoutId = setTimeout(() => {
this.autoRestartTimeoutId = null;
this.log.log('Auto-restarting the client connection...');
this.sock?.end(new Error('auto-restart'));
}, delay * SECOND);
private enableAutoRestart() {
this.autoRestartJob.start(async () => {
this.logger.info('Auto-restarting the client connection...');
if (this.sock?.ws?.isConnecting) {
this.logger.warn('Auto-restart skipped, the client is connecting...');
return;
}
this.sock?.end(undefined);
});
}
protected async getMessage(
@@ -265,28 +321,18 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
protected listenEngineEventsInDebugMode() {
this.sock.ev.process((events) => {
this.log.debug(`NOWEB events: ${JSON.stringify(events)}`);
this.logger.debug({ events: events }, `NOWEB events`);
});
}
private restartClient() {
if (this.startTimeoutId) {
this.log.log(
'Request to restart is already in progress, ignoring this request',
);
return;
}
this.log.log(
`Setting up client start in ${this.START_ATTEMPT_DELAY_SECONDS} seconds...`,
);
this.startTimeoutId = setTimeout(() => {
this.startTimeoutId = undefined;
this.buildClient();
}, this.START_ATTEMPT_DELAY_SECONDS * SECOND);
this.startDelayedJob.schedule(async () => {
await this.buildClient();
});
}
protected listenConnectionEvents() {
this.log.debug(`Start listening ${BaileysEvents.CONNECTION_UPDATE}...`);
this.logger.debug(`Start listening ${BaileysEvents.CONNECTION_UPDATE}...`);
this.sock.ev.on('connection.update', async (update) => {
const { connection, lastDisconnect, qr, isNewLogin } = update;
if (isNewLogin) {
@@ -304,12 +350,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
this.qr.save('');
// reconnect if not logged out
if (shouldReconnect) {
this.log.log(
`Connection closed due to '${lastDisconnect.error}', reconnecting...`,
);
if (lastDisconnect.error) {
this.logger.info(
`Connection closed due to '${lastDisconnect.error}', reconnecting...`,
);
}
this.restartClient();
} else {
this.log.error(
this.logger.error(
`Connection closed due to '${lastDisconnect.error}', do not reconnect the session.`,
);
await this.end();
@@ -328,8 +376,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
async stop() {
await this.end();
this.status = WAHASessionStatus.STOPPED;
this.events.removeAllListeners();
await this.end();
return;
}
@@ -359,27 +408,61 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
});
}
private issuePresenceUpdateOnMessageUpsert() {
//
// Fix for "typing" after sending a message
// https://github.com/devlikeapro/waha/issues/379
//
this.sock.ev.on('messages.upsert', ({ messages }) => {
const meId = this.sock?.authState?.creds?.me?.id;
for (const message of messages) {
if (!isRealMessage(message, meId)) {
continue;
}
if (message.key.fromMe) {
continue;
}
const jid = message.key.remoteJid;
const participant = message.key.participant || jid;
const jidPresences = this.store?.presences?.[jid];
const participantPresence = jidPresences?.[participant];
if (participantPresence?.lastKnownPresence === 'composing') {
this.logger.debug(
`Fixing presence for '${participant}' in '${jid} since it's typing`,
);
const presence: PresenceData = { lastKnownPresence: 'available' };
this.sock?.ev?.emit('presence.update', {
id: jid,
presences: { [participant]: presence },
});
}
}
});
}
private async end() {
clearTimeout(this.autoRestartTimeoutId);
clearTimeout(this.startTimeoutId);
this.autoRestartJob.stop();
this.startDelayedJob.cancel();
// @ts-ignore
this.sock?.ev?.removeAllListeners();
this.sock?.ws?.removeAllListeners();
await this.store?.close();
// wait until connection is not connecting to avoid error:
// "WebSocket was closed before the connection was established"
await waitUntil(async () => !this.sock?.ws?.isConnecting, 1_000, 10_000);
this.sock?.end(undefined);
this.store?.close();
}
async getSessionMeInfo(): Promise<MeInfo | null> {
const me = this.sock.authState?.creds?.me;
getSessionMeInfo(): MeInfo | null {
const me = this.sock?.authState?.creds?.me;
if (!me) {
return null;
}
const meId = jidNormalizedUser(me.id);
const meInfo: MeInfo = {
return {
id: toCusFormat(meId),
pushName: me.name,
};
return meInfo;
}
/**
@@ -404,7 +487,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
if (this.status == WAHASessionStatus.STARTING) {
this.log.debug('Waiting for connection update...');
this.logger.debug('Waiting for connection update...');
await this.sock.waitForConnectionUpdate((update) => !!update.qr);
}
@@ -413,12 +496,12 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
throw new UnprocessableEntityException(err);
}
this.log.log(`Requesting pairing code for '${phoneNumber}'...`);
this.logger.info(`Requesting pairing code for '${phoneNumber}'...`);
const code: string = await this.sock.requestPairingCode(phoneNumber);
// show it as ABCD-ABCD
const parts = splitAt(code, 4);
const codeRepr = parts.join('-');
this.log.log(`Your code: ${codeRepr}`);
this.logger.info(`Your code: ${codeRepr}`);
return { code: codeRepr };
}
@@ -455,18 +538,19 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
};
}
sendText(request: MessageTextRequest) {
async sendText(request: MessageTextRequest) {
const chatId = toJID(this.ensureSuffix(request.chatId));
const message = {
text: request.text,
mentions: request.mentions?.map(toJID),
};
return this.sock.sendMessage(chatId, message);
const options = await this.getMessageOptions(request);
return this.sock.sendMessage(chatId, message, options);
}
public deleteMessage(chatId: string, messageId: string) {
const jid = toJID(this.ensureSuffix(chatId));
const key = parseMessageId(messageId);
const key = parseMessageIdSerialized(messageId);
return this.sock.sendMessage(jid, { delete: key });
}
@@ -476,7 +560,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
request: EditMessageRequest,
) {
const jid = toJID(this.ensureSuffix(chatId));
const key = parseMessageId(messageId);
const key = parseMessageIdSerialized(messageId);
const message = {
text: request.text,
mentions: request.mentions?.map(toJID),
@@ -506,23 +590,18 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
};
const message = { poll: poll };
const remoteJid = toJID(request.chatId);
const result = await this.sock.sendMessage(remoteJid, message);
const options = await this.getMessageOptions(request);
const result = await this.sock.sendMessage(remoteJid, message, options);
return this.toWAMessage(result);
}
async reply(request: MessageReplyRequest) {
const { id } = parseMessageId(request.reply_to);
const quotedMessage = await this.store.loadMessage(
toJID(request.chatId),
id,
);
const options = await this.getMessageOptions(request);
const message = {
text: request.text,
mentions: request.mentions?.map(toJID),
};
return await this.sock.sendMessage(request.chatId, message, {
quoted: quotedMessage,
});
return await this.sock.sendMessage(request.chatId, message, options);
}
sendImage(request: MessageImageRequest) {
@@ -553,11 +632,14 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
async sendSeen(request: SendSeenRequest) {
const key = parseMessageId(request.messageId);
const key = parseMessageIdSerialized(request.messageId);
const participant = request.participant
? toJID(this.ensureSuffix(request.participant))
: undefined;
const data = {
remoteJid: key.remoteJid,
id: key.id,
participant: request.participant,
participant: participant,
};
return this.sock.readMessages([data]);
}
@@ -584,19 +666,18 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
toJID(chatId),
toNumber(limit),
);
const result = [];
const promises = [];
for (const msg of messages) {
const wamsg = await this.processIncomingMessage(msg, downloadMedia);
if (!wamsg) {
continue;
}
result.push(wamsg);
promises.push(this.processIncomingMessage(msg, downloadMedia));
}
let result = await Promise.all(promises);
result = result.filter(Boolean);
return result;
}
async setReaction(request: MessageReactionRequest) {
const key = parseMessageId(request.messageId);
const key = parseMessageIdSerialized(request.messageId);
const reactionMessage = {
react: {
text: request.reaction,
@@ -607,7 +688,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
async setStar(request: MessageStarRequest) {
const key = parseMessageId(request.messageId);
const key = parseMessageIdSerialized(request.messageId);
await this.sock.chatModify(
{
star: {
@@ -623,13 +704,80 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
* Chats methods
*/
async getChats() {
const chats = await this.store.getChats();
async getChats(query: GetChatsQuery) {
const chats = await this.store.getChats(query.limit, query.offset);
// Remove unreadCount, it's not ready yet
chats.forEach((chat) => delete chat.unreadCount);
return chats;
}
protected async chatsPutArchive(
chatId: string,
archive: boolean,
): Promise<any> {
const jid = toJID(chatId);
const messages = await this.store.getMessagesByJid(jid, 1);
return await this.sock.chatModify(
{ archive: archive, lastMessages: messages },
jid,
);
}
public chatsArchiveChat(chatId: string): Promise<any> {
return this.chatsPutArchive(chatId, true);
}
public chatsUnarchiveChat(chatId: string): Promise<any> {
return this.chatsPutArchive(chatId, false);
}
/**
* Labels methods
*/
public async getLabels(): Promise<Label[]> {
const labels = await this.store.getLabels();
return labels.map(this.toLabel);
}
public async getChatsByLabelId(labelId: string) {
const chats = await this.store.getChatsByLabelId(labelId);
// Remove unreadCount, it's not ready yet
chats.forEach((chat) => delete chat.unreadCount);
return chats;
}
public async getChatLabels(chatId: string): Promise<Label[]> {
const jid = toJID(chatId);
const labels = await this.store.getChatLabels(jid);
return labels.map(this.toLabel);
}
public async putLabelsToChat(chatId: string, labels: LabelID[]) {
const jid = toJID(chatId);
const labelsIds = labels.map((label) => label.id);
const currentLabels = await this.store.getChatLabels(jid);
const currentLabelsIds = currentLabels.map((label) => label.id);
const addLabelsIds = lodash.difference(labelsIds, currentLabelsIds);
const removeLabelsIds = lodash.difference(currentLabelsIds, labelsIds);
for (const labelId of addLabelsIds) {
await this.sock.addChatLabel(jid, labelId);
}
for (const labelId of removeLabelsIds) {
await this.sock.removeChatLabel(jid, labelId);
}
}
protected toLabel(label: NOWEBLabel): Label {
const color = label.color;
return {
id: label.id,
name: label.name,
color: color,
colorHex: Label.toHex(color),
};
}
/**
* Contacts methods
*/
@@ -752,20 +900,13 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
public async getPresence(chatId: string): Promise<WAHAChatPresences> {
await this.subscribePresence(chatId);
const remoteJid = toJID(chatId);
const storedPresences = this.store.presences[remoteJid];
return this.toWahaPresences(remoteJid, storedPresences || []);
}
public async subscribePresence(chatId: string): Promise<void> {
const remoteJid = toJID(chatId);
if (this.store.presences[remoteJid]) {
return;
if (!(remoteJid in this.store.presences)) {
this.store.presences[remoteJid] = [];
await this.sock.presenceSubscribe(remoteJid);
}
// Have no info - subscribe to listen for events
await this.sock.presenceSubscribe(remoteJid);
return;
const result = this.store.presences[remoteJid];
return this.toWahaPresences(remoteJid, result);
}
/**
@@ -780,9 +921,22 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
font: status.font,
statusJidList: JIDs,
};
return this.sock.sendMessage(BROADCAST_ID, message, options);
}
public deleteStatus(request: DeleteStatusRequest) {
const messageId = request.id;
const key = parseMessageIdSerialized(messageId, true);
key.fromMe = true;
key.remoteJid = BROADCAST_ID;
const JIDs = request.contacts.map(toJID);
const options = {
statusJidList: JIDs,
};
return this.sock.sendMessage(BROADCAST_ID, { delete: key }, options);
}
protected upsertMeInJIDs(JIDs: string[]) {
if (!this.sock?.authState?.creds?.me) {
return;
@@ -793,6 +947,81 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
}
}
/**
* Channels methods
*/
protected toChannel(newsletter: NewsletterMetadata): Channel {
const role =
// @ts-ignore
newsletter.viewer_metadata?.role ||
(newsletter.viewer_metadata?.view_role as ChannelRole) ||
ChannelRole.GUEST;
const preview = newsletter.preview
? getUrlFromDirectPath(newsletter.preview)
: null;
const picture = newsletter.picture
? getUrlFromDirectPath(newsletter.picture)
: null;
return {
id: newsletter.id,
name: newsletter.name,
description: newsletter.description,
invite: getChannelInviteLink(newsletter.invite),
preview: preview,
picture: picture,
verified: newsletter.verification === 'VERIFIED',
role: role,
};
}
public async channelsList(query: ListChannelsQuery): Promise<Channel[]> {
const newsletters = await this.sock.newsletterSubscribed();
let channels = newsletters.map(this.toChannel);
if (query.role) {
// @ts-ignore
channels = channels.filter((channel) => channel.role === query.role);
}
return channels;
}
public async channelsCreateChannel(request: CreateChannelRequest) {
const newsletter = await this.sock.newsletterCreate(
request.name,
request.description,
);
return this.toChannel(newsletter);
}
public async channelsGetChannel(id: string) {
const newsletter = await this.sock.newsletterMetadata('jid', id);
return this.toChannel(newsletter);
}
public async channelsGetChannelByInviteCode(inviteCode: string) {
const newsletter = await this.sock.newsletterMetadata('invite', inviteCode);
return this.toChannel(newsletter);
}
public async channelsDeleteChannel(id: string) {
return await this.sock.newsletterDelete(id);
}
public async channelsFollowChannel(id: string): Promise<void> {
return await this.sock.newsletterAction(id, 'follow');
}
public async channelsUnfollowChannel(id: string): Promise<void> {
return await this.sock.newsletterAction(id, 'unfollow');
}
public async channelsMuteChannel(id: string): Promise<void> {
return await this.sock.newsletterAction(id, 'mute');
}
public async channelsUnmuteChannel(id: string): Promise<void> {
return await this.sock.newsletterAction(id, 'unmute');
}
/**
* END - Methods for API
*/
@@ -856,6 +1085,99 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
);
});
return true;
case WAHAEvents.CALL_RECEIVED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
calls = lodash.filter(calls, { status: 'offer' });
for (const call of calls) {
const body = this.toCallData(call);
handler(body);
}
});
return true;
case WAHAEvents.CALL_ACCEPTED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
calls = lodash.filter(calls, { status: 'accept' });
for (const call of calls) {
const body = this.toCallData(call);
handler(body);
}
});
return true;
case WAHAEvents.CALL_REJECTED:
this.sock.ev.on('call', (calls: WACallEvent[]) => {
const acceptCalls = lodash.filter(calls, { status: 'accept' });
if (acceptCalls.length > 0) {
// We got two events when accepting calls - reject and accept
// Like for each device
// So if we see accepted call - ignore rejected
return;
}
calls = lodash.filter(calls, { status: 'reject' });
for (const call of calls) {
const body = this.toCallData(call);
if (body.isGroup == null) {
// We get two "reject" events, one with null property, ignore it
return;
}
handler(body);
}
});
return true;
case WAHAEvents.LABEL_UPSERT:
this.sock.ev.on('labels.edit', (data: NOWEBLabel) => {
if (data.deleted) {
return;
}
const body = this.toLabel(data);
handler(body);
});
return true;
case WAHAEvents.LABEL_DELETED:
this.sock.ev.on('labels.edit', (data: NOWEBLabel) => {
if (!data.deleted) {
return;
}
const body = this.toLabel(data);
handler(body);
});
return true;
case WAHAEvents.LABEL_CHAT_ADDED:
this.sock.ev.on('labels.association', async ({ association, type }) => {
if (type !== 'add') {
return;
}
if (association.type !== LabelAssociationType.Chat) {
return;
}
const labelData = await this.store.getLabelById(association.labelId);
const label = labelData ? this.toLabel(labelData) : null;
const body: LabelChatAssociation = {
labelId: association.labelId,
chatId: toCusFormat(association.chatId),
label: label,
};
handler(body);
});
return true;
case WAHAEvents.LABEL_CHAT_DELETED:
this.sock.ev.on('labels.association', async ({ association, type }) => {
if (type !== 'remove') {
return;
}
if (association.type !== LabelAssociationType.Chat) {
return;
}
const labelData = await this.store.getLabelById(association.labelId);
const label = labelData ? this.toLabel(labelData) : null;
const body: LabelChatAssociation = {
labelId: association.labelId,
chatId: toCusFormat(association.chatId),
label: label,
};
handler(body);
});
return true;
default:
return false;
}
@@ -917,16 +1239,16 @@ export class WhatsappSessionNoWebCore 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);
}
}
try {
return await this.toWAMessage(message);
} catch (error) {
this.log.error('Failed to process incoming message');
this.log.error(error);
this.logger.error('Failed to process incoming message');
this.logger.error(error);
console.trace(error);
return null;
}
@@ -935,18 +1257,8 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
protected toWAMessage(message): Promise<WAMessage> {
const fromToParticipant = getFromToParticipant(message);
const id = buildMessageId(message.key);
let body = message.message.conversation;
if (!body) {
// Some of the messages have no conversation, but instead have text in extendedTextMessage
// https://github.com/devlikeapro/waha/issues/90
body = message.message.extendedTextMessage?.text;
}
if (!body) {
// Populate from caption
const mediaContent = extractMediaContent(message.message);
// @ts-ignore - AudioMessage doesn't have caption field
body = mediaContent?.caption;
}
const body = this.extractBody(message.message);
const replyTo = this.extractReplyTo(message.message);
const ack = message.ack || message.status - 1;
return Promise.resolve({
id: id,
@@ -966,10 +1278,45 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
ackName: WAMessageAck[ack] || ACK_UNKNOWN,
location: message.location,
vCards: message.vCards,
replyTo: replyTo,
_data: message,
});
}
protected extractBody(message): string | null {
if (!message) {
return null;
}
let body = message.conversation;
if (!body) {
// Some of the messages have no conversation, but instead have text in extendedTextMessage
// https://github.com/devlikeapro/waha/issues/90
body = message.extendedTextMessage?.text;
}
if (!body) {
// Populate from caption
const mediaContent = extractMediaContent(message);
// @ts-ignore - AudioMessage doesn't have caption field
body = mediaContent?.caption;
}
return body;
}
protected extractReplyTo(message): ReplyToMessage | null {
const msgType = getContentType(message);
const contextInfo = message[msgType]?.contextInfo;
if (!contextInfo) {
return null;
}
const quotedMessage = contextInfo.quotedMessage;
const body = this.extractBody(quotedMessage);
return {
id: contextInfo.stanzaId,
participant: contextInfo.participant,
body: body,
};
}
protected toWAContact(contact: Contact) {
contact.id = toCusFormat(contact.id);
// @ts-ignore
@@ -1093,6 +1440,20 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
handler(payload);
}
private toCallData(call: WACallEvent): CallData {
// call.date can be either string 2024-07-18T09:45:55.000Z or Date
const date = new Date(call.date);
// convert to timestamp in seconds
const timestamp: number = date.getTime() / 1000;
return {
id: call.id,
from: toCusFormat(call.from),
timestamp: timestamp,
isVideo: call.isVideo,
isGroup: call.isGroup,
};
}
private toWahaPresences(
remoteJid: string,
storedPresences: { [participant: string]: PresenceData },
@@ -1119,11 +1480,23 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
protected downloadMedia(message) {
const processor = new EngineMediaProcessor(this);
return this.mediaManager.processMedia(processor, message);
return this.mediaManager.processMedia(processor, message, this.name);
}
protected async getMessageOptions(request: any): Promise<any> {
let quoted;
if (request.reply_to) {
const key = parseMessageIdSerialized(request.reply_to, true);
quoted = await this.store.loadMessage(toJID(request.chatId), key.id);
}
return {
quoted: quoted,
};
}
}
export class EngineMediaProcessor implements IEngineMediaProcessor<any> {
export class EngineMediaProcessor implements IMediaEngineProcessor<any> {
constructor(public session: WhatsappSessionNoWebCore) {}
hasMedia(message: any): boolean {
@@ -1152,6 +1525,9 @@ export class EngineMediaProcessor implements IEngineMediaProcessor<any> {
* Convert from 11111111111@s.whatsapp.net to 11111111111@c.us
*/
function toCusFormat(remoteJid) {
if (!remoteJid) {
return remoteJid;
}
if (isJidGroup(remoteJid)) {
return remoteJid;
}
@@ -1161,6 +1537,9 @@ function toCusFormat(remoteJid) {
if (isLidUser(remoteJid)) {
return remoteJid;
}
if (isNewsletter(remoteJid)) {
return remoteJid;
}
if (!remoteJid) {
return;
}
@@ -1182,6 +1561,9 @@ export function toJID(chatId) {
if (isJidStatusBroadcast(chatId)) {
return chatId;
}
if (isNewsletter(chatId)) {
return chatId;
}
const number = chatId.split('@')[0];
return number + '@s.whatsapp.net';
}
@@ -1201,7 +1583,11 @@ function buildMessageId({ id, remoteJid, fromMe }) {
* false_11111111111@c.us_AAA
* {id: "AAA", remoteJid: "11111111111@s.whatsapp.net", "fromMe": false}
*/
function parseMessageId(messageId) {
function parseMessageIdSerialized(messageId: string, soft: boolean = false) {
if (!messageId.includes('_') && soft) {
return { id: messageId };
}
const parts = messageId.split('_');
if (parts.length != 3) {
throw new Error(
@@ -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>;
}
+31 -6
View File
@@ -1,15 +1,40 @@
import { WAMessage } from '@adiwajshing/baileys';
import { LabelAssociation } from '@adiwajshing/baileys/lib/Types/LabelAssociation';
import { ILabelAssociationRepository } from '@waha/core/engines/noweb/store/ILabelAssociationsRepository';
import { ILabelsRepository } from '@waha/core/engines/noweb/store/ILabelsRepository';
import { IChatRepository } from './IChatRepository';
import { IContactRepository } from './IContactRepository';
import { IMessagesRepository } from './IMessagesRepository';
export interface INowebStorage {
init(): Promise<void>;
export abstract class INowebStorage {
abstract init(): Promise<void>;
close(): Promise<void>;
abstract close(): Promise<void>;
getContactsRepository(): IContactRepository;
abstract getContactsRepository(): IContactRepository;
getChatRepository(): IChatRepository;
abstract getChatRepository(): IChatRepository;
getMessagesRepository(): IMessagesRepository;
abstract getMessagesRepository(): IMessagesRepository;
abstract getLabelsRepository(): ILabelsRepository;
abstract getLabelAssociationRepository(): ILabelAssociationRepository;
protected getMessagesMetadata(): Map<string, any> {
return new Map()
.set('jid', (msg: WAMessage) => msg.key.remoteJid)
.set('id', (msg: WAMessage) => msg.key.id)
.set('messageTimestamp', (msg: WAMessage) => msg.messageTimestamp);
}
protected getLabelAssociationMetadata() {
return new Map().set(
'id',
(a: LabelAssociation) =>
// @ts-ignore
`${a.type}_${a.labelId}_${a.chatId}_${a.messageId}`,
);
}
}
+10 -1
View File
@@ -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);
}
}
+22
View File
@@ -53,4 +53,26 @@ export const NOWEB_STORE_SCHEMA = [
new Index('timestamp_index', ['messageTimestamp']),
],
),
new Schema(
'labels',
[new Field('id', 'TEXT'), new Field('data', 'TEXT')],
[new Index('labels_id_index', ['id'])],
),
new Schema(
'labelAssociations',
[
new Field('id', 'TEXT'),
new Field('type', 'TEXT'),
new Field('labelId', 'TEXT'),
new Field('chatId', 'TEXT'),
new Field('messageId', 'TEXT'),
new Field('data', 'TEXT'),
],
[
new Index('label_assoc_id_index', ['id']),
new Index('label_assoc_type_label_index', ['type', 'labelId']),
new Index('label_assoc_type_chat_index', ['type', 'chatId']),
new Index('label_assoc_type_message_index', ['type', 'messageId']),
],
),
];
@@ -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'),
+7 -6
View File
@@ -1,4 +1,5 @@
import { UnprocessableEntityException } from '@nestjs/common/exceptions/unprocessable-entity.exception';
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
import * as Buffer from 'buffer';
import { create, CreateConfig, Message, Whatsapp } from 'venom-bot';
@@ -21,7 +22,6 @@ import {
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';
@@ -69,7 +69,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
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);
this.logger.debug('Number of attempts to read the qrcode: ', attempts);
};
}
@@ -79,7 +79,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
this.whatsapp = await this.buildClient();
} catch (error) {
this.status = WAHASessionStatus.FAILED;
this.log.error(error);
this.logger.error(error);
this.qr.save('');
return;
}
@@ -90,8 +90,9 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
}
async stop() {
await this.whatsapp.close();
this.status = WAHASessionStatus.STOPPED;
this.events.removeAllListeners();
await this.whatsapp.close();
}
subscribeEngineEvent(event: WAHAEvents | string, handler: (message) => void) {
@@ -247,7 +248,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
protected downloadMedia(message: Message) {
const processor = new EngineMediaProcessor(this);
return this.mediaManager.processMedia(processor, message);
return this.mediaManager.processMedia(processor, message, this.name);
}
private processIncomingMessage(message: Message) {
@@ -279,7 +280,7 @@ export class WhatsappSessionVenomCore extends WhatsappSession {
}
}
export class EngineMediaProcessor implements IEngineMediaProcessor<Message> {
export class EngineMediaProcessor implements IMediaEngineProcessor<Message> {
constructor(public session: WhatsappSessionVenomCore) {}
hasMedia(message: any): boolean {
-535
View File
@@ -1,535 +0,0 @@
<!doctype html>
<html class="no-js" dir="ltr" loc="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>WhatsApp Web</title>
<meta name="viewport" content="width=device-width" />
<meta name="google" content="notranslate" />
<meta name="format-detection" content="telephone=no" />
<meta
name="description"
content="Quickly send and receive WhatsApp messages right from your computer."
/>
<meta
name="og:description"
content="Quickly send and receive WhatsApp messages right from your computer."
/>
<meta name="og:url" content="https://web.whatsapp.com/" />
<meta name="og:title" content="WhatsApp Web" />
<meta
name="og:image"
content="https://static.facebook.com/images/whatsapp/www/whatsapp-promo.png"
/>
<link
id="favicon"
rel="shortcut icon"
href="/img/favicon/1x/favicon.png"
type="image/png"
/>
<link
rel="apple-touch-icon"
sizes="192x192"
href="/apple-touch-icon.png"
type="image/png"
/>
<meta
name="theme-color"
content="#111b21"
media="(prefers-color-scheme: dark)"
/>
<meta name="theme-color" content="#f0f2f5" />
<link
id="whatsapp-pwa-manifest-link"
rel="manifest"
href="/manifest.json"
crossorigin="use-credentials"
/>
<style>
#initial_startup {
--startup-background: #f0f2f5;
--startup-background-rgb: 240, 242, 245;
--startup-icon: #bbc5cb;
--secondary-lighter: #8696a0;
--primary-title: #41525d;
--progress-primary: #00c298;
--progress-background: #e9edef;
}
.dark #initial_startup {
--startup-background: #111b21;
--startup-background-rgb: 17, 27, 33;
--startup-icon: #676f73;
--primary-title: rgba(233, 237, 239, 0.88);
--secondary-lighter: #667781;
--progress-primary: #0b846d;
--progress-background: #233138;
}
#app,
body,
html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
#app {
position: absolute;
top: 0;
left: 0;
}
#initial_startup {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
user-select: none;
background-color: var(--startup-background);
}
#initial_startup .graphic {
margin-top: -40px;
color: var(--startup-icon);
}
#initial_startup .graphic .resume-logo {
transform: translateX(calc(50% - 52px / 2));
}
#initial_startup .graphic::after {
position: relative;
top: -100%;
left: calc(50% - 72px * 2 - 72px / 2);
display: block;
width: calc(72px * 3);
height: 100%;
content: '';
background: linear-gradient(
to right,
rgba(var(--startup-background-rgb), 0.5) 0,
rgba(var(--startup-background-rgb), 0.5) 33.33%,
rgba(var(--startup-background-rgb), 0) 44.1%,
rgba(var(--startup-background-rgb), 0) 55.8%,
rgba(var(--startup-background-rgb), 0.5) 66.66%,
rgba(var(--startup-background-rgb), 0.5) 100%
);
opacity: 1;
animation: shimmer 1.5s linear 0.6s infinite;
}
html[dir='rtl'] #initial_startup .graphic::after {
animation-direction: reverse;
}
@keyframes shimmer {
from {
left: calc(50% - 72px * 2 - 72px / 2);
}
to {
left: calc(50% - 72px / 2);
}
}
#initial_startup .progress {
position: relative;
width: 420px;
height: 3px;
margin-top: 40px;
}
#initial_startup .progress progress {
vertical-align: top;
}
#initial_startup .main {
margin-top: 40px;
font-size: 17px;
color: var(--primary-title);
}
#initial_startup .secondary {
margin-top: 12px;
font-size: 14px;
color: var(--secondary-lighter);
}
#initial_startup .secondary span {
display: inline-block;
margin-bottom: 2px;
vertical-align: middle;
}
progress {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 3px;
margin: 0;
color: var(--progress-primary);
background-color: var(--progress-background);
border: none;
}
progress[value]::-webkit-progress-bar {
background-color: var(--progress-background);
}
progress[value]::-moz-progress-bar,
progress[value]::-webkit-progress-value {
background-color: var(--progress-primary);
transition: width 0.45s ease;
}
</style>
<link
href="/stylex-f0601c57714fe972a8c4d2c2562f8082.css"
rel="stylesheet"
/>
<link href="/app-6113f1562d101247269b.css" rel="stylesheet" />
</head>
<body class="web">
<script
data-binary-transparency-hash-key="inline-js-d11c72a06542fc3b43af600028cf0f996e4b9b178dfa047e18730efaf74aab0b"
>
try {
var systemThemeDark,
theme = window.localStorage.getItem('theme'),
systemThemeMode = window.localStorage.getItem('system-theme-mode');
if (('true' === systemThemeMode || !theme) && window.matchMedia) {
var systemTheme = window.matchMedia('(prefers-color-scheme: dark)');
systemThemeDark = systemTheme && systemTheme.matches;
}
var darkTheme = '"dark"' === theme || Boolean(systemThemeDark);
darkTheme && document.body.classList.add('dark');
} catch (e) {}
</script>
<div id="app"></div>
<div id="hard_expire_time" data-time="1719543128.405"></div>
<div id="initial_startup">
<div class="graphic">
<span
><svg width="250" height="52" xmlns="http://www.w3.org/2000/svg">
<path
class="resume-logo"
d="M37.7 31.2c-.6-.4-3.8-2-4.4-2.1-.6-.2-1-.4-1.4.3l-2 2.5c-.4.4-.8.5-1.5.2-.6-.3-2.7-1-5.1-3.2-2-1.7-3.2-3.8-3.6-4.5-.4-.6 0-1 .3-1.3l1-1.1.6-1.1c.2-.4 0-.8 0-1.1l-2-4.8c-.6-1.3-1.1-1-1.5-1.1h-1.2c-.5 0-1.2.1-1.8.8-.5.6-2.2 2.2-2.2 5.3 0 3.2 2.3 6.3 2.6 6.7.3.4 4.6 7 11 9.7l3.7 1.4c1.5.5 3 .4 4 .2 1.3-.1 3.9-1.5 4.4-3 .5-1.5.5-2.8.4-3-.2-.4-.6-.5-1.3-.8M26 47.2c-3.9 0-7.6-1-11-3l-.7-.4-8.1 2L8.4 38l-.6-.8A21.4 21.4 0 0126 4.4a21.3 21.3 0 0121.4 21.4c0 11.8-9.6 21.4-21.4 21.4M44.2 7.6a25.8 25.8 0 00-40.6 31L0 52l13.7-3.6A25.8 25.8 0 0044.3 7.5"
fill="currentColor"
></path></svg
></span>
</div>
<div class="progress">
<progress value="0" max="100" dir="ltr"></progress>
</div>
<div class="main">WhatsApp</div>
<div class="secondary">
<span
><svg width="10" height="12" xmlns="http://www.w3.org/2000/svg">
<path
d="M5 1.6c1.4 0 2.5 1 2.6 2.4v1.5h.2c.5 0 1 .4 1 1V10c0 .6-.5 1-1 1H2.3a1 1 0 01-1.1-1V6.5c0-.6.5-1 1-1h.2V4.2c0-1.4 1-2.5 2.4-2.6H5zm0 1.2c-.7 0-1.3.6-1.3 1.3v1.4h2.6V4.2c0-.7-.4-1.2-1-1.3H5z"
fill="currentColor"
></path>
</svg> </span
>&nbsp;End-to-end encrypted
</div>
</div>
<link
rel="preload"
crossorigin="anonymous"
as="fetch"
href="/binary-transparency-manifest-2.2412.54.json"
id="binary-transparency-manifest-preload"
/>
<script src="/libsignal-protocol-ee5b8ba.min.js"></script>
<script defer="defer" src="/runtime.295f0230b6dbd8983513.js"></script>
<script
data-binary-transparency-hash-key="inline-js-cdf06293c99d00ee0c1bc0fcfdbd76a7ae9aef6290926dbff0cba3a7994b7fca"
>
/*! Copyright (c) 2024 WhatsApp Inc. All Rights Reserved. */
(self.webpackChunkwhatsapp_web_client =
self.webpackChunkwhatsapp_web_client || []).push([
[5617],
{
307914: (e) => {
e.exports = function (e) {
return e && e.__esModule ? e : { default: e };
};
},
595318: (e) => {
(e.exports = function (e) {
return e && e.__esModule ? e : { default: e };
}),
(e.exports.default = e.exports),
(e.exports.__esModule = !0);
},
415227: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
const t = new Error(e);
if (void 0 === t.stack)
try {
throw t;
} catch (e) {}
return t;
});
},
670983: (e, t, r) => {
'use strict';
var n = r(307914);
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
let t =
arguments.length > 1 && void 0 !== arguments[1]
? arguments[1]
: '?';
if (null == e)
throw (0, o.default)('Unexpected null or undefined: ' + t);
return e;
});
var o = n(r(415227));
},
250473: (e, t, r) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.UNIQUE_UPLOADS_ALLOWED_BEFORE_THROTTLE =
t.TICKET_URL =
t.CLB_URL =
t.CLB_TOKEN =
t.CLB_CHECK_URL =
void 0);
var n = r(508247);
(t.CLB_CHECK_URL =
'https://crashlogs.whatsapp.net/wa_fls_upload_check'),
(t.CLB_TOKEN =
'1063127757113399|745146ffa34413f9dbb5469f5370b7af'),
(t.CLB_URL = 'https://crashlogs.whatsapp.net/wa_clb_data');
const o = n.DYN_ORIGIN + 'web-contact-us';
(t.TICKET_URL = o), (t.UNIQUE_UPLOADS_ALLOWED_BEFORE_THROTTLE = 0);
},
207024: (e, t, r) => {
'use strict';
var n = r(595318);
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.getDistribution = function () {
let e = 'unknown';
return (e = 'prod'), 'web_prod';
}),
(t.getLogUserAgent = function (e) {
let t,
{ appVersion: r, browser: n, device: o } = e;
return (t = 'Web/' + n), `WhatsApp/${r} ${t} Device/${o}`;
}),
n(r(472514)),
n(r(556869));
},
794858: (e, t, r) => {
'use strict';
var n = r(595318),
o = n(r(670983)),
a = r(508247),
s = r(250473),
c = r(207024),
_ = n(r(174285)),
u = r(425017);
function i(e) {
!(function (e, t) {
const r = window.navigator.userAgent;
if (r === p && e.includes('getElementsByTagName')) return;
const n = new FormData(),
i = new Blob([e], { type: 'text/plain' });
n.append(
'from_jid',
(function () {
if (f) return f;
try {
(f = JSON.parse(
(0, o.default)(_.default, 'localStorage').getItem(
d.UNKNOWN_ID,
),
)),
f && (f = f.replace('-', ''));
} catch (e) {}
if (!f) {
f = 'unknown' + Math.floor(1e10 * Math.random());
const e = f;
try {
(0, o.default)(_.default, 'localStorage').setItem(
d.UNKNOWN_ID,
JSON.stringify(e),
);
} catch (e) {}
}
return (0, o.default)(f, 'id');
})(),
),
n.append(
'agent',
(0, c.getLogUserAgent)(
(0, u.parseUASimple)(r, a.VERSION_BASE),
),
),
n.append('file', i, 'logs.txt'),
n.append('tags', 'load');
const l = new XMLHttpRequest(),
I =
s.CLB_URL +
'?access_token=' +
encodeURIComponent(s.CLB_TOKEN);
l.open('POST', I, !0), l.send(n);
})(e);
}
function l(e) {
let { error: t, reason: r, stack: n } = e;
const o = new Date().toISOString();
return `${o}: error: ${t}\n${o}: reason for logs: ${r}\n${o}: userAgent: ${window.navigator.userAgent}\n${n}`;
}
null == window.onerror &&
(window.onerror = function (e, t, r) {
const n = t.split('?')[0];
return "Uncaught SyntaxError: Unexpected token '<'" === e
? ((function (e) {
i(
l({
error: 'failed to load a js or css bundle',
reason: `failed to load [${e
.split('/')[3]
.replace(/^\//, '')}]`,
stack: '',
}),
);
})(n),
!0)
: (i(
l({
error: e,
reason: `Error at [${n}:${r}]`,
stack: '',
}),
),
!1);
});
const d = { UNKNOWN_ID: a.UNKNOWN_ID },
p =
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36';
let f;
},
425017: (e, t) => {
'use strict';
function r(e) {
return e.includes('windows')
? 'Windows'
: e.includes('mac')
? 'Mac OS'
: e.includes('linux')
? 'Linux'
: 'Unparsed';
}
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.parseUASimple = function (e, t) {
const n = e.toLowerCase();
return { browser: s(n), device: r(n), appVersion: t };
});
const n = /(chrome|firefox)\/([\w\.]+)/i,
o = /(edge|opr)\/([\w\.]+)/i,
a = {
chrome: 'Chrome',
edge: 'Edge',
opr: 'Opera',
firefox: 'Firefox',
};
function s(e) {
const t = e.match(o) || e.match(n);
return null == t ? 'Unparsed' : `${a[t[1]]} ${t[2]}`;
}
},
174285: (e, t) => {
'use strict';
let r;
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = void 0);
try {
r = window.localStorage;
} catch (e) {}
var n = r;
t.default = n;
},
508247: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.WS_ORIGIN =
t.WEB_PUBLIC_PATH =
t.VERSION_TERTIARY =
t.VERSION_STR =
t.VERSION_SECONDARY =
t.VERSION_PRIMARY =
t.VERSION_BASE =
t.USER_TIMINGS =
t.UNKNOWN_ID =
t.LOCALHOST_ENV_CONFIG =
t.HASH_PLACEHOLDER =
t.FLB_PLATFORM =
t.FB_APP_ID =
t.DYN_ORIGIN =
t.DIFF_VERSION =
t.DIFF_ID =
t.BUILD_URL =
t.BUILD_TIMESTAMP =
t.BUILD_ID =
void 0);
t.DIFF_ID = '';
(t.DIFF_VERSION = ''),
(t.LOCALHOST_ENV_CONFIG = !1),
(t.HASH_PLACEHOLDER = '507042ed75b89fb00e8ef35da3541122cbc261e6'),
(t.VERSION_PRIMARY = '2'),
(t.VERSION_SECONDARY = '2412'),
(t.VERSION_TERTIARY = '54'),
(t.VERSION_BASE = '2.2412.54'),
(t.VERSION_STR = '2.2412.54'),
(t.DYN_ORIGIN = 'https://web.whatsapp.com/'),
(t.WS_ORIGIN = ''),
(t.FLB_PLATFORM = 'web'),
(t.FB_APP_ID = ''),
(t.UNKNOWN_ID = 'WAUnknownID'),
(t.BUILD_ID = '583059957'),
(t.BUILD_TIMESTAMP = 'March 29, 2024'),
(t.WEB_PUBLIC_PATH = '/'),
(t.BUILD_URL = 'https://web.whatsapp.com/'),
(t.USER_TIMINGS = !1);
},
472514: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function (e) {
return e.default;
});
},
556869: (e, t) => {
'use strict';
Object.defineProperty(t, '__esModule', { value: !0 }),
(t.default = function e(t) {
const r = new Error(t);
if (void 0 === r.stack)
try {
throw e;
} catch (e) {}
return r;
});
},
},
(e) => {
'use strict';
e((e.s = 794858));
},
]);
</script>
<script defer="defer" src="/vendor1~app.264a01b6133c4a120327.js"></script>
<script defer="defer" src="/app.2c7f8dd150ae88037cde.js"></script>
<script
data-binary-transparency-hash-key="inline-js-9c8cd3d0f4d5af8c7f5cd1c45208edd308bfe472e353a50e4cbacbf6cb58627c"
>
((i) => {
const l = document.getElementById(i);
l &&
fetch(l.href)
.then((b) => b.text())
.then((code) => {
const script = document.createElement('script');
script.id = 'binary-transparency-manifest';
script.type = 'application/json';
script.innerHTML = code;
document.body.append(script);
});
})('binary-transparency-manifest-preload');
</script>
</body>
</html>
+15
View File
@@ -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);
};
};
+38
View File
@@ -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));
}
}
+326 -93
View File
@@ -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,42 @@ 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.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 +273,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 +291,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 +353,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 +380,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 +400,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 +451,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 +463,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 +482,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 +688,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 +871,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 +903,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 +926,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 +947,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 +981,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;
+130 -82
View File
@@ -1,21 +1,26 @@
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';
@@ -26,9 +31,8 @@ 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';
@@ -40,13 +44,15 @@ export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException {
}
}
export function buildLogger(name: string, levels: LogLevel[]) {
return new ConsoleLogger(name, { logLevels: levels });
}
@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 | undefined | null;
private sessionConfig?: SessionConfig;
DEFAULT = 'default';
// @ts-ignore
@@ -55,25 +61,25 @@ 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 = null;
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);
});
}
@@ -95,43 +101,60 @@ 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 !== undefined;
}
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,
sessionRunTimestamp: Date.now(),
});
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 +162,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 +181,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 = null;
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 = undefined;
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,75 +232,60 @@ 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 };
return getProxyConfig(this.config, sessions, this.DEFAULT);
}
getSession(name: string): WhatsappSession {
this.onlyDefault(name);
const session = this.session;
if (!session) {
if (session === undefined) {
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}'.
Please start it first by using POST /sessions/${name}/start request`,
);
}
return session;
}
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 me = this.session.getSessionMeInfo();
// Get engine info
let engineInfo = {};
if (this.session) {
try {
engineInfo = await promiseTimeout(10, this.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) => ({}))),
...engineInfo,
};
return [
{
-47
View File
@@ -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;
}
}
+17
View File
@@ -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 };
+15
View File
@@ -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 };
+42
View File
@@ -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 };
+44
View File
@@ -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;
}
}
+25
View File
@@ -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[]>;
}
+16 -13
View File
@@ -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,19 +16,15 @@ 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;
}
return true;
async exists(sessionName: string): Promise<boolean> {
const filepath = this.getFilePath(sessionName);
return await fileExists(filepath);
}
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 +54,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
View File
@@ -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,
View File
Whitespace-only changes.
-234
View File
@@ -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
-234
View File
@@ -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
-234
View File
@@ -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
-234
View File
@@ -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
-234
View File
@@ -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
-3
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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};
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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};
-2
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-2
View File
@@ -1,2 +0,0 @@
import{s as D}from"./BwlcA3rq.js";import{s as T}from"./D1Sip8Hx.js";import{a3 as j,a5 as B,a4 as c,a7 as m,aa as o,a9 as U,i as E,Z as R,t as d,v as f,N as b,Q as C,x as v,$ as k,P as g,ab as y,O as p,W as w,y as F,z as A,A as L,ad as M,ac as N,Y as _}from"./CdAotn7S.js";import{s as H}from"./AdkLG1re.js";import"./CYhL7ix_.js";var G={root:"p-panelmenu p-component",panel:"p-panelmenu-panel",header:function(e){var t=e.instance,a=e.item;return["p-panelmenu-header",{"p-highlight":t.isItemActive(a)&&!!a.items,"p-disabled":t.isItemDisabled(a)}]},headerContent:"p-panelmenu-header-content",headerAction:"p-panelmenu-header-action",headerIcon:"p-menuitem-icon",headerLabel:"p-menuitem-text",toggleableContent:"p-toggleable-content",menuContent:"p-panelmenu-content",menu:"p-panelmenu-root-list",menuitem:function(e){var t=e.instance,a=e.processedItem;return["p-menuitem",{"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"},q=j.extend({name:"panelmenu",classes:G}),z={name:"BasePanelMenu",extends:H,props:{model:{type:Array,default:null},expandedKeys:{type:Object,default:null},multiple:{type:Boolean,default:!1},tabindex:{type:Number,default:0}},style:q,provide:function(){return{$parentInstance:this}}},x={name:"PanelMenuSub",hostName:"PanelMenu",extends:H,emits:["item-toggle","item-mousemove"],props:{panelId:{type:String,default:null},focusedItemId:{type:String,default:null},items:{type:Array,default:null},level:{type:Number,default:0},templates:{type:Object,default:null},activeItemPath:{type:Object,default:null},tabindex:{type:Number,default:-1}},methods:{getItemId:function(e){return"".concat(this.panelId,"_").concat(e.key)},getItemKey:function(e){return this.getItemId(e)},getItemProp:function(e,t,a){return e&&e.item?c.getItemValue(e.item[t],a):void 0},getItemLabel:function(e){return this.getItemProp(e,"label")},getPTOptions:function(e,t,a){return this.ptm(e,{context:{item:t,index:a,active:this.isItemActive(t),focused:this.isItemFocused(t),disabled:this.isItemDisabled(t)}})},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 c.isNotEmpty(e.items)},onItemClick:function(e,t){this.getItemProp(t,"command",{originalEvent:e,item:t.item}),this.$emit("item-toggle",{processedItem:t,expanded:!this.isItemActive(t)})},onItemToggle:function(e){this.$emit("item-toggle",e)},onItemMouseMove:function(e,t){this.$emit("item-mousemove",{originalEvent:e,processedItem:t})},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},getMenuItemProps:function(e,t){return{action:o({class:this.cx("action"),tabindex:-1,"aria-hidden":!0},this.getPTOptions("action",e,t)),icon:o({class:[this.cx("icon"),this.getItemProp(e,"icon")]},this.getPTOptions("icon",e,t)),label:o({class:this.cx("label")},this.getPTOptions("label",e,t)),submenuicon:o({class:this.cx("submenuIcon")},this.getPTOptions("submenuicon",e,t))}}},components:{ChevronRightIcon:T,ChevronDownIcon:D},directives:{ripple:U}},W=["tabindex"],Q=["id","aria-label","aria-expanded","aria-level","aria-setsize","aria-posinset","data-p-focused","data-p-disabled"],Y=["onClick","onMousemove"],Z=["href","target"];function J(n,e,t,a,s,i){var l=E("PanelMenuSub",!0),u=R("ripple");return d(),f("ul",{class:w(n.cx("submenu")),tabindex:t.tabindex},[(d(!0),f(b,null,C(t.items,function(r,h){return d(),f(b,{key:i.getItemKey(r)},[i.isItemVisible(r)&&!i.getItemProp(r,"separator")?(d(),f("li",o({key:0,id:i.getItemId(r),class:[n.cx("menuitem",{processedItem:r}),i.getItemProp(r,"class")],style:i.getItemProp(r,"style"),role:"treeitem","aria-label":i.getItemLabel(r),"aria-expanded":i.isItemGroup(r)?i.isItemActive(r):void 0,"aria-level":t.level+1,"aria-setsize":i.getAriaSetSize(),"aria-posinset":i.getAriaPosInset(h)},i.getPTOptions("menuitem",r,h),{"data-p-focused":i.isItemFocused(r),"data-p-disabled":i.isItemDisabled(r)}),[v("div",o({class:n.cx("content"),onClick:function(K){return i.onItemClick(K,r)},onMousemove:function(K){return i.onItemMouseMove(K,r)}},i.getPTOptions("content",r,h)),[t.templates.item?(d(),g(y(t.templates.item),{key:1,item:r.item,root:!1,active:i.isItemActive(r),hasSubmenu:i.isItemGroup(r),label:i.getItemLabel(r),props:i.getMenuItemProps(r,h)},null,8,["item","active","hasSubmenu","label","props"])):k((d(),f("a",o({key:0,href:i.getItemProp(r,"url"),class:n.cx("action"),target:i.getItemProp(r,"target"),Line truncated
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ee(n,e){if(n){if(typeof n=="string")return O(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);if(t==="Object"&&n.constructor&&(t=n.constructor.name),t==="Map"||t==="Set")return Array.from(n);if(t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return O(n,e)}}function O(n,e){(e==null||e>n.length)&&(e=n.length);for(var t=0,a=new Array(e);t<e;t++)a[t]=n[t];return a}function te(n,e){var t=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(t!=null){var a,s,i,l,u=[],r=!0,h=!1;try{if(i=(t=t.call(n)).next,e===0){if(Object(t)!==t)return;r=!1}else for(;!(r=(a=i.call(t)).done)&&(u.push(a.value),u.length!==e);r=!0);}catch(I){h=!0,s=I}finally{try{if(!r&&t.return!=null&&(l=t.return(),Object(l)!==l))return}finally{if(h)throw s}}return u}}function ne(n){if(Array.isArray(n))return n}var V={name:"PanelMenuList",hostName:"PanelMenu",extends:H,emits:["item-toggle","header-focus"],props:{panelId:{type:String,default:null},items:{type:Array,default:null},templates:{type:Object,default:null},expandedKeys:{type:Object,default:null}},searchTimeout:null,searchValue:null,data:function(){return{focused:!1,focusedItem:null,activeItemPath:[]}},watch:{expandedKeys:function(e){this.autoUpdateActiveItemPath(e)}},mounted:function(){this.autoUpdateActiveItemPath(this.expandedKeys)},methods:{getItemProp:function(e,t){return e&&e.item?c.getItemValue(e.item[t]):void 0},getItemLabel:function(e){return this.getItemProp(e,"label")},isItemVisible:function(e){return this.getItemProp(e,"visible")!==!1},isItemDisabled:function(e){return this.getItemProp(e,"disabled")},isItemActive:function(e){return this.activeItemPath.some(function(t){return t.key===e.parentKey})},isItemGroup:function(e){return c.isNotEmpty(e.items)},onFocus:function(e){this.focused=!0,this.focusedItem=this.focusedItem||(this.isElementInPanel(e,e.relatedTarget)?this.findFirstItem():this.findLastItem())},onBlur:function(){this.focused=!1,this.focusedItem=null,this.searchValue=""},onKeyDown:function(e){var t=e.metaKey||e.ctrlKey;switch(e.code){case"ArrowDown":this.onArrowDownKey(e);break;case"ArrowUp":this.onArrowUpKey(e);break;case"ArrowLeft":this.onArrowLeftKey(e);break;case"ArrowRight":this.onArrowRightKey(e);break;case"Home":this.onHomeKey(e);break;case"End":this.onEndKey(e);break;case"Space":this.onSpaceKey(e);break;case"Enter":case"NumpadEnter":this.onEnterKey(e);break;case"Escape":case"Tab":case"PageDown":case"PageUp":case"Backspace":case"ShiftLeft":case"ShiftRight":break;default:!t&&c.isPrintableCharacter(e.key)&&this.searchItems(e,e.key);break}},onArrowDownKey:function(e){var t=c.isNotEmpty(this.focusedItem)?this.findNextItem(this.focusedItem):this.findFirstItem();this.changeFocusedItem({originalEvent:e,processedItem:t,focusOnNext:!0}),e.preventDefault()},onArrowUpKey:function(e){var t=c.isNotEmpty(this.focusedItem)?this.findPrevItem(this.focusedItem):this.findLastItem();this.changeFocusedItem({originalEvent:e,processedItem:t,selfCheck:!0}),e.preventDefault()},onArrowLeftKey:function(e){var t=this;if(c.isNotEmpty(this.focusedItem)){var a=this.activeItemPath.some(function(s){return s.key===t.focusedItem.key});a?this.activeItemPath=this.activeItemPath.filter(function(s){return s.key!==t.focusedItem.key}):this.focusedItem=c.isNotEmpty(this.focusedItem.parent)?this.focusedItem.parent:this.focusedItem,e.preventDefault()}},onArrowRightKey:function(e){var t=this;if(c.isNotEmpty(this.focusedItem)){var a=this.isItemGroup(this.focusedItem);if(a){var s=this.activeItemPath.some(function(i){return i.key===t.focusedItem.key});s?this.onArrowDownKey(e):(this.activeItemPath=this.activeItemPath.filter(function(i){return i.parentKey!==t.focusedItem.parentKey}),this.activeItemPath.push(this.focusedItem))}e.preventDefault()}},onHomeKey:function(e){this.changeFocusedItem({originalEvent:e,processedItem:this.findFirstItem(),allowHeaderFocus:!1}),e.preventDefault()},onEndKey:function(e){this.changeFocusedItem({originalEvent:e,processedItem:this.findLastItem(),focusOnNext:!0,allowHeaderFocus:!1}),e.preventDefault()},onEnterKey:function(e){if(c.isNotEmpty(this.focusedItem)){var t=m.findSingle(this.$el,'li[id="'.concat("".concat(this.focusedItemId),'"]')),a=t&&(m.findSingle(t,'[data-pc-section="action"]')||m.findSingle(t,"a,button"));a?a.click():t&&t.click()}e.preventDefault()},onSpaceKey:function(e){this.onEnterKey(e)},onItemToggle:function(e){var t=e.processedItem,a=e.expanded;this.expandedKeys?this.$emit("item-toggle",{item:t.item,expanded:a}):(this.activeItemPath=this.activeItemPath.filter(function(s){return s.parentKey!==t.parentKey}),a&&this.activeItemPath.push(t)),this.focusedItem=t,m.focus(this.$el)},onItemMouseMove:function(e){this.focused&&(this.focusedItem=e.processedItem)},isElementInPanel:function(e,t){var a=e.currentTarget.closest('[data-pc-section="panel"]');return a&&a.contains(t)},isItemMatched:function(e){var t;return this.isValidItem(e)&&((t=this. Line truncated
-1
View File
@@ -1 +0,0 @@
import{s as p}from"./DtEiWfmc.js";import{s as c,a as l}from"./DaK9vsnd.js";import{s as m}from"./CiBqmW71.js";import{s as u}from"./AdkLG1re.js";import{a3 as f,t as i,v as d,Y as o,P as v,aa as n,ab as $,x as g,B as y}from"./CdAotn7S.js";import"./CYhL7ix_.js";var h={root:function(s){var t=s.props,r=s.instance;return["p-inline-message p-component p-inline-message-"+t.severity,{"p-inline-message-icon-only":!r.$slots.default}]},icon:function(s){var t=s.props;return["p-inline-message-icon",t.icon]},text:"p-inline-message-text"},B=f.extend({name:"inlinemessage",classes:h}),x={name:"BaseInlineMessage",extends:u,props:{severity:{type:String,default:"error"},icon:{type:String,default:void 0}},style:B,provide:function(){return{$parentInstance:this}}},S={name:"InlineMessage",extends:x,inheritAttrs:!1,timeout:null,data:function(){return{visible:!0}},mounted:function(){var s=this;this.sticky||setTimeout(function(){s.visible=!1},this.life)},computed:{iconComponent:function(){return{info:c,success:p,warn:l,error:m}[this.severity]}}};function k(e,s,t,r,C,a){return i(),d("div",n({role:"alert","aria-live":"assertive","aria-atomic":"true",class:e.cx("root")},e.ptmi("root")),[o(e.$slots,"icon",{},function(){return[(i(),v($(e.icon?"span":a.iconComponent),n({class:e.cx("icon")},e.ptm("icon")),null,16,["class"]))]}),g("span",n({class:e.cx("text")},e.ptm("text")),[o(e.$slots,"default",{},function(){return[y(" ")]})],16)],16)}S.render=k;export{S as default};
Loaded 100 of 680 files, more files were not shown because too many files have changed in this diff. Show more