AkshitShubham commited on
Commit
47d04a3
·
verified ·
1 Parent(s): 6f47224

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +2 -35
  2. .gitignore +199 -0
  3. Dockerfile +67 -0
  4. README.md +181 -10
  5. beta/api/api.py +40 -0
  6. beta/api/api_dl.py +35 -0
  7. beta/api/blueprints/api_pref_manager.py +39 -0
  8. beta/api/blueprints/client_info_routes.py +103 -0
  9. beta/api/blueprints/leagacy_create_task.py +40 -0
  10. beta/api/blueprints/session_lodge.py +82 -0
  11. beta/api/blueprints/template_routes.py +25 -0
  12. beta/api/blueprints/while_dl_and_post_dl.py +35 -0
  13. beta/api/mr_manager/boss_manager.py +8 -0
  14. beta/api/mr_manager/client_manager.py +119 -0
  15. beta/api/mr_manager/task_manager.py +105 -0
  16. beta/api/static/css/main.45e125bd.css +2 -0
  17. beta/api/static/css/main.45e125bd.css.map +1 -0
  18. beta/api/static/js/453.4633cf1b.chunk.js +2 -0
  19. beta/api/static/js/453.4633cf1b.chunk.js.map +1 -0
  20. beta/api/static/js/main.00bb85dc.js +0 -0
  21. beta/api/static/js/main.00bb85dc.js.LICENSE.txt +95 -0
  22. beta/api/static/js/main.00bb85dc.js.map +0 -0
  23. beta/api/static/media/logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg +1 -0
  24. beta/api/static/media/roboto-cyrillic-300-normal.1431d1cef06ad04f5458.woff2 +0 -0
  25. beta/api/static/media/roboto-cyrillic-300-normal.5b5f2f31962967dfc22c.woff +0 -0
  26. beta/api/static/media/roboto-cyrillic-400-normal.71a33b6b50457b2c903a.woff2 +0 -0
  27. beta/api/static/media/roboto-cyrillic-400-normal.c1d66054fe23e181d92c.woff +0 -0
  28. beta/api/static/media/roboto-cyrillic-500-normal.965aebef74db72eaf236.woff +0 -0
  29. beta/api/static/media/roboto-cyrillic-500-normal.cad7d3d9cb265e334e58.woff2 +0 -0
  30. beta/api/static/media/roboto-cyrillic-700-normal.d010f1f324e111a22e53.woff2 +0 -0
  31. beta/api/static/media/roboto-cyrillic-700-normal.f8a034d72aa6828199d4.woff +0 -0
  32. beta/api/static/media/roboto-cyrillic-ext-300-normal.3503ec5cc6330e21f695.woff +0 -0
  33. beta/api/static/media/roboto-cyrillic-ext-300-normal.4777461b144e55145268.woff2 +0 -0
  34. beta/api/static/media/roboto-cyrillic-ext-400-normal.804378952da8a10faae2.woff2 +0 -0
  35. beta/api/static/media/roboto-cyrillic-ext-400-normal.af4d91666ea345601bea.woff +0 -0
  36. beta/api/static/media/roboto-cyrillic-ext-500-normal.268f264f58eba5c07c88.woff +0 -0
  37. beta/api/static/media/roboto-cyrillic-ext-500-normal.62ced72e5832f02c2796.woff2 +0 -0
  38. beta/api/static/media/roboto-cyrillic-ext-700-normal.198a421f279162d59143.woff +0 -0
  39. beta/api/static/media/roboto-cyrillic-ext-700-normal.be4d02458ce53887dc37.woff2 +0 -0
  40. beta/api/static/media/roboto-greek-300-normal.8ecd7085cfe9bc2c22ac.woff +0 -0
  41. beta/api/static/media/roboto-greek-300-normal.db2632771401f61463fe.woff2 +0 -0
  42. beta/api/static/media/roboto-greek-400-normal.c35e4c3958e209d17b31.woff2 +0 -0
  43. beta/api/static/media/roboto-greek-400-normal.dfdff8fa12eac629d29f.woff +0 -0
  44. beta/api/static/media/roboto-greek-500-normal.1a05a4887ccb810cb4dd.woff +0 -0
  45. beta/api/static/media/roboto-greek-500-normal.9ac81fefbe6c319ea40b.woff2 +0 -0
  46. beta/api/static/media/roboto-greek-700-normal.50e795c1345353b0e996.woff2 +0 -0
  47. beta/api/static/media/roboto-greek-700-normal.a84892c56152037b3552.woff +0 -0
  48. beta/api/static/media/roboto-greek-ext-300-normal.35b9d6be04b95f0f0530.woff2 +0 -0
  49. beta/api/static/media/roboto-greek-ext-300-normal.392a45a84c081c4b412d.woff +0 -0
  50. beta/api/static/media/roboto-greek-ext-400-normal.169619821ea93019d1bb.woff2 +0 -0
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Created by https://www.toptal.com/developers/gitignore/api/python
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python
3
+
4
+ ### Python ###
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # IDE
11
+ .idea/
12
+
13
+ # Download Files
14
+ webdl/
15
+
16
+ # CSV Files
17
+ *.csv
18
+
19
+ # C extensions
20
+ *.so
21
+
22
+ # Distribution / packaging
23
+ .Python
24
+ build/
25
+ develop-eggs/
26
+ dist/
27
+ downloads/
28
+ eggs/
29
+ .eggs/
30
+ lib/
31
+ lib64/
32
+ parts/
33
+ sdist/
34
+ var/
35
+ wheels/
36
+ share/python-wheels/
37
+ *.egg-info/
38
+ .installed.cfg
39
+ *.egg
40
+ MANIFEST
41
+
42
+ # PyInstaller
43
+ # Usually these files are written by a python script from a template
44
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
45
+ *.manifest
46
+ *.spec
47
+
48
+ # Installer logs
49
+ pip-log.txt
50
+ pip-delete-this-directory.txt
51
+
52
+ # Unit test / coverage reports
53
+ htmlcov/
54
+ .tox/
55
+ .nox/
56
+ .coverage
57
+ .coverage.*
58
+ .cache
59
+ nosetests.xml
60
+ coverage.xml
61
+ *.cover
62
+ *.py,cover
63
+ .hypothesis/
64
+ .pytest_cache/
65
+ cover/
66
+
67
+ # Translations
68
+ *.mo
69
+ *.pot
70
+
71
+ # Django stuff:
72
+ *.log
73
+ local_settings.py
74
+ db.sqlite3
75
+ db.sqlite3-journal
76
+
77
+ # Flask stuff:
78
+ instance/
79
+ .webassets-cache
80
+
81
+ # Scrapy stuff:
82
+ .scrapy
83
+
84
+ # Sphinx documentation
85
+ docs/_build/
86
+
87
+ # PyBuilder
88
+ .pybuilder/
89
+ target/
90
+
91
+ # Jupyter Notebook
92
+ .ipynb_checkpoints
93
+
94
+ # IPython
95
+ profile_default/
96
+ ipython_config.py
97
+
98
+ # pyenv
99
+ # For a library or package, you might want to ignore these files since the code is
100
+ # intended to run in multiple environments; otherwise, check them in:
101
+ # .python-version
102
+
103
+ # pipenv
104
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
105
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
106
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
107
+ # install all needed dependencies.
108
+ #Pipfile.lock
109
+
110
+ # poetry
111
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
112
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
113
+ # commonly ignored for libraries.
114
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
115
+ #poetry.lock
116
+
117
+ # pdm
118
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
119
+ #pdm.lock
120
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
121
+ # in version control.
122
+ # https://pdm.fming.dev/#use-with-ide
123
+ .pdm.toml
124
+
125
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
126
+ __pypackages__/
127
+
128
+ # Celery stuff
129
+ celerybeat-schedule
130
+ celerybeat.pid
131
+
132
+ # SageMath parsed files
133
+ *.sage.py
134
+
135
+ # Environments
136
+ .env
137
+ .venv
138
+ env/
139
+ venv/
140
+ ENV/
141
+ env.bak/
142
+ venv.bak/
143
+
144
+ # Spyder project settings
145
+ .spyderproject
146
+ .spyproject
147
+
148
+ # Rope project settings
149
+ .ropeproject
150
+
151
+ # mkdocs documentation
152
+ /site
153
+
154
+ # mypy
155
+ .mypy_cache/
156
+ .dmypy.json
157
+ dmypy.json
158
+
159
+ # Pyre type checker
160
+ .pyre/
161
+
162
+ # pytype static type analyzer
163
+ .pytype/
164
+
165
+ # Cython debug symbols
166
+ cython_debug/
167
+
168
+ # PyCharm
169
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
170
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
171
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
172
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
173
+ #.idea/
174
+
175
+ ### Python Patch ###
176
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
177
+ poetry.toml
178
+
179
+ # ruff
180
+ .ruff_cache/
181
+
182
+ # LSP config files
183
+ pyrightconfig.json
184
+
185
+ # End of https://www.toptal.com/developers/gitignore/api/python
186
+ pwdlv3.lnk
187
+ *.mp4
188
+ /bin/Logs/
189
+ *.m4s
190
+ /tmp
191
+ /bin
192
+ *.un~
193
+ *.py~
194
+
195
+ # ignore all *.test.py files
196
+ *.test.py
197
+ clients.json
198
+ clients.json
199
+ /csv_files/
Dockerfile ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.12-slim
3
+
4
+ # Set the working directory in the container to /app
5
+ WORKDIR /app
6
+
7
+ # Add the current directory contents into the container at /app
8
+ ADD . /app
9
+
10
+ # Install ffmpeg and curl
11
+ RUN apt-get update && apt-get install -y ffmpeg curl
12
+
13
+ # Create a virtual environment and activate it
14
+ RUN python -m venv /opt/venv
15
+
16
+ # Ensure the virtual environment is used
17
+ ENV PATH="/opt/venv/bin:$PATH"
18
+
19
+ # Install any needed packages specified in requirements.txt
20
+ RUN pip install --no-cache-dir -r requirements.txt
21
+
22
+ # Make port 7680 available to the world outside this container
23
+ EXPOSE 5000
24
+
25
+ # Copy defaults.json from the given URL
26
+ COPY ./defaults.linux.json ./defaults.json
27
+
28
+ # Run setup script commands
29
+ RUN curl -o defaults.json https://raw.githubusercontent.com/shubhamakshit/pwdlv3/main/defaults.linux.json && \
30
+ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \
31
+ if command -v python &> /dev/null; then \
32
+ echo "Python is installed" && \
33
+ if [[ $(uname -o) != "Android" ]]; then \
34
+ python get-pip.py; \
35
+ fi && \
36
+ python -m pip install -r requirements.txt; \
37
+ elif command -v python3 &> /dev/null; then \
38
+ echo "Python3 is installed" && \
39
+ if [[ $(uname -o) != "Android" ]]; then \
40
+ python3 get-pip.py; \
41
+ fi && \
42
+ python3 -m pip install -r requirements.txt; \
43
+ else \
44
+ echo "Python is not installed" && \
45
+ exit 1; \
46
+ fi && \
47
+ rm get-pip.py && \
48
+ mkdir -p /app/bin && \
49
+ curl -o /app/bin/mp4decrypt https://raw.githubusercontent.com/shubhamakshit/pwdlv3_assets/main/$(uname -o)/$(uname -m)/mp4decrypt && \
50
+ curl -o /app/bin/vsd https://raw.githubusercontent.com/shubhamakshit/pwdlv3_assets/main/$(uname -o)/$(uname -m)/vsd && \
51
+ chmod +x /app/bin/* && \
52
+ if ! grep -q "alias pwdl" ~/.bashrc; then \
53
+ echo "alias pwdl='python3 /app/pwdl.py'" >> ~/.bashrc; \
54
+ fi && \
55
+ echo "Please restart your terminal or run 'source ~/.bashrc' to apply the alias."
56
+
57
+ # Create webdl directory
58
+ RUN mkdir /app/webdl
59
+
60
+ #set flask app
61
+ ENV FLASK_DEBUG=1
62
+ ENV FLASK_ENV=development
63
+ ENV FLASK_APP=run:app
64
+
65
+ ENTRYPOINT ["flask", "run", "--host=0.0.0.0"]
66
+
67
+
README.md CHANGED
@@ -1,10 +1,181 @@
1
- ---
2
- title: Pwdl
3
- emoji: 📈
4
- colorFrom: green
5
- colorTo: red
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Table of Contents
2
+ 1. [Project Information](#project-information)
3
+ 2. [Tools Used](#tools-used)
4
+ 3. [Getting Started](#getting-started)
5
+ - [Windows](#windows)
6
+ - [Linux](#linux)
7
+ 4. [Usage](#usage)
8
+ 5. [API Reference](#api-reference)
9
+ 6. [Docker Usage](#docker-usage)
10
+ 7. [Shell Usage (Beta)](#shell-usage-beta)
11
+ 8. [Error Codes](#error-codes)
12
+ 9. [Contributing](#contributing)
13
+ 10. [License](#license)
14
+
15
+ # Project Information
16
+ `pwdlv3` is a project aimed at downloading videos from pw.live. It is written in Python and JavaScript, and uses pip for dependency management.
17
+
18
+ # Tools Used
19
+
20
+ - **Python**: Backend logic scripting.
21
+ - **JavaScript**: Frontend logic handling.
22
+ - **pip**: Dependency management.
23
+ - **Flask**: HTTP requests handling and web UI rendering.
24
+ - **Docker**: Containerization for consistent application deployment.
25
+ - **VSD**: Downloading MPD (MPEG-DASH) files. [More about VSD](https://github.com/clitic/vsd).
26
+ - **Bento4's mp4decrypt**: Decrypting encrypted MP4 files.
27
+ - **FFmpeg**: Merging audio and video files.
28
+
29
+ # Getting Started
30
+
31
+ ## Windows
32
+ 1. Clone the repository:
33
+ ```bash
34
+ git clone https://github.com/username/pwdlv3.git
35
+ ```
36
+ 2. Navigate to the project directory:
37
+ ```bash
38
+ cd pwdlv3
39
+ ```
40
+ 3. Install the required dependencies:
41
+ ```bash
42
+ pip install -r requirements.txt
43
+ ```
44
+ 4. Run the setup script:
45
+ ```bash
46
+ pwdl.bat
47
+ ```
48
+
49
+ ## Linux
50
+ 1. Clone the repository:
51
+ ```bash
52
+ git clone https://github.com/username/pwdlv3.git
53
+ ```
54
+ 2. Navigate to the project directory:
55
+ ```bash
56
+ cd pwdlv3
57
+ ```
58
+ 3. Install the required dependencies:
59
+ ```bash
60
+ pip install -r requirements.txt
61
+ ```
62
+ 4. Run the setup script:
63
+ ```bash
64
+ ./setup.sh
65
+ ```
66
+
67
+ # Usage
68
+
69
+ Run the project with the following command:
70
+
71
+ ```bash
72
+ python pwdl.py --options
73
+ ```
74
+
75
+ - Download a single video:
76
+ ```bash
77
+ python pwdl.py --id VIDEO_ID --name VIDEO_NAME
78
+ ```
79
+ - Download multiple videos from a CSV file:
80
+ ```bash
81
+ python pwdl.py --csv-file FILE_PATH
82
+ ```
83
+ - Start the shell:
84
+ ```bash
85
+ python pwdl.py --shell
86
+ ```
87
+ - Start the WebUI:
88
+ ```bash
89
+ python pwdl.py --webui
90
+ ```
91
+
92
+ # API Reference
93
+
94
+ The project provides several API endpoints for interacting with the video downloading service:
95
+
96
+ - **POST /api/create_task**: Create a new download task.
97
+ - **Request Body**: JSON with 'id' (video ID) and 'name' (output file name).
98
+ - **Response**: JSON with 'task_id'.
99
+
100
+ - **GET /api/progress/<task_id>**: Get the progress of a download task.
101
+ - **Response**: JSON with progress information.
102
+
103
+ - **GET /api/get-file/<task_id>/<name>**: Download the completed video file.
104
+ - **Response**: Video file download.
105
+
106
+ - **GET /key/vid_id**: Get the decryption key for a video.
107
+ - **Query Parameters**: 'vid_id' and 'token'.
108
+ - **Response**: JSON with 'key'.
109
+
110
+ These endpoints are also available without the '/api' prefix. For example, use `/create_task` instead of `/api/create_task`.
111
+
112
+ # Docker Usage
113
+
114
+ The Dockerfile is used to create a Docker image that encapsulates the entire application, including all dependencies.
115
+
116
+ ## Building the Docker Image
117
+
118
+ Navigate to the project directory and run:
119
+
120
+ ```bash
121
+ docker build -t shubhamakshit/pwdl .
122
+ ```
123
+
124
+ ## Running the Docker Image
125
+
126
+ Run the Docker image with:
127
+
128
+ ```bash
129
+ docker run -p 5000:5000 shubhamakshit/pwdl
130
+ ```
131
+
132
+ Access the application at `http://localhost:5000`.
133
+
134
+ # Shell Usage (Beta)
135
+
136
+ Start the interactive shell with:
137
+
138
+ ```bash
139
+ python pwdl.py --shell
140
+ ```
141
+
142
+ Available commands:
143
+
144
+ - `get_key <vid_id> <token>`: Get the decryption key for a video.
145
+ - `tkn-up <token>`: Update the token in the default settings.
146
+ - `exit`: Exit the shell.
147
+
148
+ Note: This feature is in beta and may change.
149
+
150
+ # Error Codes
151
+
152
+ | Code | Description |
153
+ | ---- | ----------- |
154
+ | 0 | No error |
155
+ | 1 | defaults.json not found |
156
+ | 2 | Dependency not found |
157
+ | 3 | Dependency not found in default settings |
158
+ | 4 | CSV file not found |
159
+ | 5 | Download failed |
160
+ | 6 | Could not make directory |
161
+ | 7 | Token not found in default settings |
162
+ | 8 | Overwrite aborted by user |
163
+ | 22 | Can't load file |
164
+ | 23 | Flare is not started |
165
+ | 24 | Request failed due to unknown reason |
166
+ | 25 | Key extraction failed |
167
+ | 26 | Key not provided |
168
+ | 27 | Could not download audio |
169
+ | 28 | Could not download video |
170
+ | 29 | Could not decrypt audio |
171
+ | 30 | Could not decrypt video |
172
+ | 31 | Method is patched |
173
+ | 32 | Could not extract key |
174
+
175
+ # Contributing
176
+
177
+ Instructions for how to contribute to the project will be provided here.
178
+
179
+ # License
180
+
181
+ Information about the project's license will be provided here.
beta/api/api.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from flask import Flask
3
+ from flask_cors import CORS
4
+ from mainLogic.utils.glv import Global
5
+ from beta.api.mr_manager.boss_manager import Boss
6
+
7
+ from beta.api.blueprints.api_pref_manager import api_prefs
8
+ from beta.api.blueprints.template_routes import template_blueprint
9
+ from beta.api.blueprints.session_lodge import session_lodge
10
+ from beta.api.blueprints.while_dl_and_post_dl import dl_and_post_dl
11
+ from beta.api.blueprints.leagacy_create_task import legacy_create_task
12
+ from beta.api.blueprints.client_info_routes import client_info
13
+
14
+ app = Flask(__name__)
15
+ CORS(app)
16
+
17
+ # Initialize ClientManager and TaskManager
18
+ client_manager = Boss.client_manager
19
+ task_manager = Boss.task_manager
20
+ OUT_DIR = Boss.OUT_DIR
21
+
22
+ try:
23
+ if not os.path.exists(OUT_DIR):
24
+ os.makedirs(OUT_DIR)
25
+ except Exception as e:
26
+ Global.errprint(f"Could not create output directory {OUT_DIR}")
27
+ Global.sprint(f"Defaulting to './' ")
28
+ Global.errprint(f"Error: {e}")
29
+ OUT_DIR = './'
30
+
31
+
32
+ app.register_blueprint(api_prefs)
33
+ app.register_blueprint(legacy_create_task)
34
+ app.register_blueprint(template_blueprint)
35
+ app.register_blueprint(session_lodge)
36
+ app.register_blueprint(dl_and_post_dl)
37
+ app.register_blueprint(client_info)
38
+
39
+ if __name__ == '__main__':
40
+ app.run(debug=True, port=7680)
beta/api/api_dl.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from mainLogic.utils.gen_utils import delete_old_files
3
+ from mainLogic.main import Main
4
+ from mainLogic.startup.checkup import CheckState
5
+ from mainLogic.utils.glv import Global
6
+ from mainLogic.utils import glv_var
7
+
8
+
9
+ def download_pw_video(task_id, name, id, out_dir, client_id, session_id, progress_callback):
10
+ # Create directories for client_id and session_id if they don't exist
11
+ client_session_dir = os.path.join(out_dir, client_id, session_id)
12
+ os.makedirs(client_session_dir, exist_ok=True)
13
+
14
+ print(f"Downloading {name} with id {id} to {client_session_dir}")
15
+
16
+ ch = CheckState()
17
+ state = ch.checkup(glv_var.EXECUTABLES, directory="./", verbose=False)
18
+ prefs = state['prefs']
19
+
20
+ if 'webui-del-time' in prefs:
21
+ del_time = int(prefs['webui-del-time'])
22
+ else:
23
+ del_time = 45
24
+
25
+ delete_old_files(glv_var.api_webdl_directory, del_time)
26
+
27
+ vsd = state['vsd']
28
+ ffmpeg = state['ffmpeg']
29
+ mp4d = state['mp4decrypt']
30
+ verbose = True
31
+ Main(id=id,
32
+ name=f"{name}-{task_id}",
33
+ token=prefs['token'],
34
+ directory=client_session_dir, tmpDir="/*auto*/", vsdPath=vsd, ffmpeg=ffmpeg, mp4d=mp4d, verbose=verbose,
35
+ progress_callback=progress_callback).process()
beta/api/blueprints/api_pref_manager.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from flask import Blueprint, request, jsonify
4
+
5
+ from mainLogic.utils.glv import Global
6
+ from mainLogic.utils.glv_var import PREFS_FILE
7
+
8
+ api_prefs = Blueprint('api_prefs', __name__)
9
+
10
+ @api_prefs.route('/api/prefs/defaults.json', methods=['GET'])
11
+ @api_prefs.route('/prefs/defaults.json', methods=['GET'])
12
+ def get_prefs():
13
+ import json as js
14
+ file_path = PREFS_FILE
15
+ if not os.path.exists(file_path):
16
+ return jsonify({'error': 'file not found'}), 404
17
+ with open(file_path, 'r') as file:
18
+ data = js.load(file)
19
+ return jsonify(data), 200
20
+
21
+
22
+ @api_prefs.route('/api/update/defaults.json', methods=['POST'])
23
+ @api_prefs.route('/update/defaults.json', methods=['POST'])
24
+ def update_prefs():
25
+ import json as js
26
+ file_path = PREFS_FILE
27
+ if not os.path.exists(file_path):
28
+ return jsonify({'error': 'file not found'}), 404
29
+ try:
30
+ data = request.json
31
+ except:
32
+ return jsonify({'error': 'Invalid JSON'}), 400
33
+ with open(file_path, 'r') as file:
34
+ data = js.load(file)
35
+ data.update(request.json)
36
+ with open(file_path, 'w') as file:
37
+ js.dump(data, file, indent=4)
38
+ return jsonify(data), 200
39
+
beta/api/blueprints/client_info_routes.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ from beta.api.mr_manager.boss_manager import Boss
3
+ from mainLogic.big4.decrypt.key import LicenseKeyFetcher
4
+
5
+ client_manager = Boss.client_manager
6
+ task_manager = Boss.task_manager
7
+ OUT_DIR = Boss.OUT_DIR
8
+
9
+ client_info = Blueprint('client_info', __name__)
10
+
11
+ @client_info.route('/api/session/<client_id>/<session_id>', methods=['GET'])
12
+ @client_info.route('/session/<client_id>/<session_id>', methods=['GET'])
13
+ def get_session(client_id, session_id):
14
+ # if client_id == 'anonymous' or session_id == 'anonymous':
15
+ # return jsonify({'error': 'Access to anonymous sessions is not allowed'}), 403
16
+
17
+ client_info = client_manager.get_client_info(client_id)
18
+ if client_info and session_id in client_info['sessions']:
19
+ session_info = client_info['sessions'][session_id]
20
+ return jsonify(session_info), 200
21
+ else:
22
+ return jsonify({'error': 'Session not found'}), 404
23
+
24
+
25
+ @client_info.route('/api/client/<client_id>', methods=['GET'])
26
+ @client_info.route('/client/<client_id>', methods=['GET'])
27
+ def get_client(client_id):
28
+
29
+ client_info = client_manager.get_client_info(client_id)
30
+ if client_info:
31
+ return jsonify(client_info), 200
32
+ else:
33
+ return jsonify({'error': 'Client not found'}), 404
34
+
35
+
36
+ @client_info.route('/api/session/<client_id>/<session_id>/active', methods=['GET'])
37
+ @client_info.route('/session/<client_id>/<session_id>/active', methods=['GET'])
38
+ def check_session_active(client_id, session_id):
39
+ if client_id == 'anonymous' or session_id == 'anonymous':
40
+ return jsonify({'error': 'Access to anonymous sessions is not allowed'}), 403
41
+
42
+ client_info = client_manager.get_client_info(client_id)
43
+ if client_info and session_id in client_info['sessions']:
44
+ session_info = client_info['sessions'][session_id]
45
+ tasks = session_info['tasks']
46
+ for task_id in tasks:
47
+ status = tasks[task_id]['status']
48
+ if status == 'running':
49
+ return jsonify({'active': True}), 200
50
+ return jsonify({'active': False}), 200
51
+ else:
52
+ return jsonify({'error': 'Session not found'}), 404
53
+
54
+
55
+ def is_session_active(client_id, session_id):
56
+ if client_id == 'anonymous' or session_id == 'anonymous':
57
+ return {'error': 'Access to anonymous sessions is not allowed'}, 403
58
+
59
+ client_info = client_manager.get_client_info(client_id)
60
+ if client_info and session_id in client_info['sessions']:
61
+ session_info = client_info['sessions'][session_id]
62
+ tasks = session_info['tasks']
63
+ for task_id, task in tasks.items():
64
+ if task['status'] == 'running':
65
+ return {'active': True}, 200
66
+ return {'active': False}, 200
67
+ else:
68
+ return {'error': 'Session not found'}, 404
69
+
70
+
71
+ @client_info.route('/api/client/<client_id>/active_sessions', methods=['GET'])
72
+ @client_info.route('/client/<client_id>/active_sessions', methods=['GET'])
73
+ def get_active_sessions(client_id):
74
+ if client_id == 'anonymous':
75
+ return jsonify({'error': 'Access to anonymous client is not allowed'}), 403
76
+
77
+ client_info = client_manager.get_client_info(client_id)
78
+
79
+ if client_info:
80
+ active_sessions = []
81
+ for session_id in client_info['sessions']:
82
+ session_data = is_session_active(client_id, session_id)
83
+ if session_data[1] != 200:
84
+ return jsonify(session_data[0]), session_data[1]
85
+ active = session_data[0].get('active', False)
86
+
87
+ if active:
88
+ active_sessions.append(session_id)
89
+ return jsonify({"active_sessions": active_sessions}), 200
90
+ return jsonify({'error': 'Client not found'}), 404
91
+
92
+
93
+
94
+ @client_info.route('/api/key/vid_id', methods=['GET'])
95
+ @client_info.route('/key/vid_id', methods=['GET'])
96
+ def get_key():
97
+ vid_id = request.args.get('vid_id')
98
+ token = request.args.get('token')
99
+ if not vid_id or not token:
100
+ return jsonify({'error': 'vid_id and token are required'}), 400
101
+ fetcher = LicenseKeyFetcher(token)
102
+ key = fetcher.get_key(vid_id)
103
+ return jsonify({'key': key}), 200
beta/api/blueprints/leagacy_create_task.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ from beta.api.api_dl import download_pw_video
3
+ from beta.api.mr_manager.boss_manager import Boss
4
+ from mainLogic.utils.gen_utils import generate_safe_folder_name
5
+
6
+ legacy_create_task = Blueprint('legacy_create_task', __name__)
7
+
8
+ client_manager = Boss.client_manager
9
+ task_manager = Boss.task_manager
10
+ OUT_DIR = Boss.OUT_DIR
11
+
12
+ @legacy_create_task.route('/api/create_task', methods=['POST'])
13
+ @legacy_create_task.route('/create_task', methods=['POST'])
14
+ def create_task():
15
+ data = request.json
16
+ client_id = data.get('client_id', 'anonymous')
17
+ session_id = data.get('session_id', 'anonymous')
18
+ id = data.get('id')
19
+ name = data.get('name')
20
+
21
+ # Generate safe names
22
+ name = generate_safe_folder_name(name)
23
+
24
+ if not id or not name:
25
+ return jsonify({'error': 'id and name are required'}), 400
26
+
27
+ args = {
28
+ 'name': name,
29
+ 'id': id,
30
+ 'out_dir': OUT_DIR,
31
+ 'client_id': client_id,
32
+ 'session_id': session_id
33
+ }
34
+
35
+ client_manager.add_client(client_id)
36
+ client_manager.add_session(client_id, session_id)
37
+
38
+ task_id = task_manager.create_task(client_id, session_id, download_pw_video, args)
39
+ return jsonify({'task_id': task_id}), 202
40
+
beta/api/blueprints/session_lodge.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ from beta.api.api_dl import download_pw_video
3
+ from mainLogic.utils.gen_utils import generate_random_word
4
+ from beta.api.mr_manager.boss_manager import Boss
5
+ from mainLogic.utils.gen_utils import generate_safe_folder_name
6
+
7
+
8
+ session_lodge = Blueprint('session_lodge', __name__)
9
+
10
+ client_manager = Boss.client_manager
11
+ task_manager = Boss.task_manager
12
+ OUT_DIR = Boss.OUT_DIR
13
+
14
+
15
+ @session_lodge.route('/api/client/<client_id>/<session_id>/create_session', methods=['POST'])
16
+ @session_lodge.route('/client/<client_id>/<session_id>/create_session', methods=['POST'])
17
+ def create_session(client_id, session_id):
18
+ clients = client_manager.get_client_info(client_id)
19
+ if not clients:
20
+ client_manager.add_client(client_id)
21
+
22
+ session = client_manager.get_client_info(client_id).get('sessions', {}).get(session_id)
23
+ if not session:
24
+ client_manager.add_session(client_id, session_id)
25
+ sess_name = generate_random_word()
26
+ print(f"Generated session name: {sess_name}")
27
+ client_manager.set_session_name(client_id, session_id, sess_name)
28
+ data = request.json
29
+ ids = data.get('ids', [])
30
+ names = data.get('names', [])
31
+
32
+
33
+ if not ids or not names:
34
+ return jsonify({'error': 'ids and names are required'}), 400
35
+
36
+ if len(ids) != len(names):
37
+ return jsonify({'error': 'ids and names must be of equal length'}), 400
38
+
39
+ names_safe = [generate_safe_folder_name(name) for name in names]
40
+ names = names_safe
41
+
42
+ task_ids = []
43
+
44
+ for i in range(len(ids)):
45
+ id = ids[i]
46
+ name = names[i]
47
+ print(f"Creating task for {name} with id {id}")
48
+ args = {
49
+ 'name': name,
50
+ 'id': id,
51
+ 'out_dir': OUT_DIR,
52
+ 'client_id': client_id,
53
+ 'session_id': session_id
54
+ }
55
+ task_id = task_manager.create_task(client_id, session_id, download_pw_video, args, inactive=True)
56
+ task_ids.append(task_id)
57
+
58
+ return jsonify({'task_ids': task_ids}), 202
59
+
60
+
61
+ @session_lodge.route('/api/start/<task_id>',methods=['GET','POST'])
62
+ @session_lodge.route('/start/<task_id>',methods=['GET','POST'])
63
+ def start_task(task_id):
64
+ try:
65
+ task_manager.start_task(task_id)
66
+ return jsonify({'success': True}), 200
67
+ except Exception as e:
68
+ print(e)
69
+ return jsonify({'error': str(e)}), 500
70
+
71
+ @session_lodge.route('/api/client/<client_id>/delete_client')
72
+ @session_lodge.route('/client/<client_id>/delete_client')
73
+ def delete_client_route(client_id):
74
+ client_manager.remove_client(client_id)
75
+ return jsonify({'message': f'Client with ID {client_id} deleted successfully'}), 200
76
+
77
+ @session_lodge.route('/api/client/<client_id>/<session_id>/delete_session')
78
+ @session_lodge.route('/client/<client_id>/<session_id>/delete_session')
79
+ def delete_session_route(client_id, session_id):
80
+ client_manager.remove_session(client_id, session_id)
81
+ return jsonify({'message': f'Session with ID {session_id} for client {client_id} deleted successfully'}), 200
82
+
beta/api/blueprints/template_routes.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify, render_template
2
+
3
+ from mainLogic.utils.glv import Global
4
+
5
+ template_blueprint = Blueprint('template_blueprint', __name__)
6
+
7
+ @template_blueprint.route('/')
8
+ def index():
9
+ return render_template('index.html')
10
+
11
+ @template_blueprint.route('/util')
12
+ def util():
13
+ return render_template('util.html')
14
+
15
+ @template_blueprint.route('/prefs')
16
+ def prefs():
17
+ return render_template('prefs.html')
18
+
19
+ @template_blueprint.route('/help')
20
+ def help():
21
+ return render_template('help.html')
22
+
23
+ @template_blueprint.route('/sessions')
24
+ def sessions():
25
+ return render_template('sessions.html')
beta/api/blueprints/while_dl_and_post_dl.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from flask import Blueprint, jsonify, send_file
4
+ from beta.api.mr_manager.boss_manager import Boss
5
+
6
+ client_manager = Boss.client_manager
7
+ task_manager = Boss.task_manager
8
+ OUT_DIR = Boss.OUT_DIR
9
+
10
+ dl_and_post_dl = Blueprint('dl_and_post_dl', __name__)
11
+
12
+
13
+
14
+ @dl_and_post_dl.route('/api/progress/<task_id>', methods=['GET'])
15
+ @dl_and_post_dl.route('/progress/<task_id>', methods=['GET'])
16
+ def get_progress(task_id):
17
+ progress = task_manager.get_progress(task_id)
18
+ return jsonify(progress), 200
19
+
20
+
21
+ @dl_and_post_dl.route('/api/get-file/<task_id>/<name>', methods=['GET'])
22
+ @dl_and_post_dl.route('/get-file/<task_id>/<name>', methods=['GET'])
23
+ def get_file(task_id, name):
24
+ task_info = task_manager.get_progress(task_id)
25
+
26
+ if task_info['status'] == 'not found':
27
+ return jsonify({'error': 'file not found'}), 404
28
+
29
+ client_session_dir = os.path.join(OUT_DIR, task_info['client_id'], task_info['session_id'])
30
+
31
+ file_path = os.path.join(client_session_dir, f"{name}-{task_id}.mp4")
32
+ if not os.path.exists(file_path):
33
+ return jsonify({'error': 'file not found'}), 404
34
+
35
+ return send_file(file_path, as_attachment=True,download_name=f"{name}.mp4")
beta/api/mr_manager/boss_manager.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from beta.api.mr_manager.client_manager import ClientManager
2
+ from beta.api.mr_manager.task_manager import TaskManager
3
+ from mainLogic.utils import glv_var
4
+
5
+ class Boss:
6
+ client_manager = ClientManager('clients.json')
7
+ task_manager = TaskManager(client_manager)
8
+ OUT_DIR = glv_var.api_webdl_directory
beta/api/mr_manager/client_manager.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+ class ClientManager:
5
+ def __init__(self, json_file_path):
6
+ self.json_file_path = json_file_path
7
+ self.clients = self.load_data()
8
+
9
+ def load_data(self):
10
+ if not os.path.exists(self.json_file_path):
11
+ return {}
12
+ try:
13
+ with open(self.json_file_path, 'r') as file:
14
+ return json.load(file)
15
+ except json.JSONDecodeError:
16
+ return {}
17
+
18
+ def save_data(self):
19
+ with open(self.json_file_path, 'w') as file:
20
+ json.dump(self.clients, file, indent=4)
21
+
22
+ def client_exists(self, client_id):
23
+ return client_id in self.clients
24
+
25
+ def session_exists(self, client_id, session_id):
26
+ return client_id in self.clients and session_id in self.clients[client_id]['sessions']
27
+
28
+ def add_client(self, client_id="anonymous"):
29
+ if client_id not in self.clients:
30
+ self.clients[client_id] = {
31
+ "name": "Anonymous" if client_id == "anonymous" else "",
32
+ "client_id": client_id,
33
+ "sessions": {}
34
+ }
35
+ self.save_data()
36
+ else:
37
+ print(f"Client with ID {client_id} already exists.")
38
+
39
+ def remove_client(self, client_id):
40
+ if client_id in self.clients:
41
+ del self.clients[client_id]
42
+ self.save_data()
43
+ else:
44
+ print(f"Client with ID {client_id} does not exist.")
45
+
46
+ def add_session(self, client_id="anonymous", session_id="anonymous"):
47
+ if client_id in self.clients:
48
+ if session_id not in self.clients[client_id]['sessions']:
49
+ self.clients[client_id]['sessions'][session_id] = {"tasks": {}, "name": ""}
50
+ self.save_data()
51
+ else:
52
+ print(f"Session with ID {session_id} already exists for client {client_id}.")
53
+ else:
54
+ print(f"Client with ID {client_id} does not exist.")
55
+
56
+ def remove_session(self, client_id, session_id):
57
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
58
+ del self.clients[client_id]['sessions'][session_id]
59
+ self.save_data()
60
+ else:
61
+ print(f"Session with ID {session_id} does not exist for client {client_id}.")
62
+
63
+ def add_task(self, client_id, session_id, task_id, task_info):
64
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
65
+ self.clients[client_id]['sessions'][session_id]['tasks'][task_id] = task_info
66
+ self.save_data()
67
+ else:
68
+ print(f"Either client with ID {client_id} or session with ID {session_id} does not exist.")
69
+
70
+ def update_task(self, task_info):
71
+ client_id = task_info['client_id']
72
+ session_id = task_info['session_id']
73
+ task_id = task_info['task_id']
74
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
75
+ if task_id in self.clients[client_id]['sessions'][session_id]['tasks']:
76
+ self.clients[client_id]['sessions'][session_id]['tasks'][task_id] = task_info
77
+ self.save_data()
78
+ else:
79
+ print(f"Task with ID {task_id} does not exist in session {session_id} for client {client_id}.")
80
+ else:
81
+ print(f"Either client with ID {client_id} or session with ID {session_id} does not exist.")
82
+
83
+ def remove_task(self, client_id, session_id, task_id):
84
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
85
+ if task_id in self.clients[client_id]['sessions'][session_id]['tasks']:
86
+ del self.clients[client_id]['sessions'][session_id]['tasks'][task_id]
87
+ self.save_data()
88
+ else:
89
+ print(f"Task with ID {task_id} does not exist in session {session_id} for client {client_id}.")
90
+ else:
91
+ print(f"Either client with ID {client_id} or session with ID {session_id} does not exist.")
92
+
93
+ def get_client_info(self, client_id):
94
+ if client_id in self.clients:
95
+ return self.clients[client_id]
96
+ else:
97
+ print(f"Client with ID {client_id} does not exist.")
98
+ return None
99
+
100
+ def set_session_name(self, client_id, session_id, name):
101
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
102
+ self.clients[client_id]['sessions'][session_id]['name'] = name
103
+ self.save_data()
104
+ else:
105
+ print(f"Either client with ID {client_id} or session with ID {session_id} does not exist.")
106
+
107
+ def delete_session(self, client_id, session_id):
108
+ if client_id in self.clients and session_id in self.clients[client_id]['sessions']:
109
+ del self.clients[client_id]['sessions'][session_id]
110
+ self.save_data()
111
+ else:
112
+ print(f"Session with ID {session_id} does not exist for client {client_id}.")
113
+
114
+ def delete_client(self, client_id):
115
+ if client_id in self.clients:
116
+ del self.clients[client_id]
117
+ self.save_data()
118
+ else:
119
+ print(f"Client with ID {client_id} does not exist.")
beta/api/mr_manager/task_manager.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+ import uuid
3
+
4
+ class TaskManager:
5
+ def __init__(self, client_manager):
6
+ self.tasks = {}
7
+ self.lock = threading.Lock()
8
+ self.client_manager = client_manager
9
+ self.inactive_tasks = {}
10
+
11
+ def handle_completion(self, task_id):
12
+ print(f"Task {task_id} completed")
13
+ with self.lock:
14
+ self.tasks[task_id]['status'] = 'completed'
15
+ self.client_manager.update_task(self.tasks[task_id])
16
+
17
+ on_task_complete = handle_completion
18
+
19
+ def create_task(self, client_id, session_id, target, *args, inactive=False):
20
+ task_id = str(uuid.uuid4())
21
+ print(f"Args: {args}")
22
+ args_dict = args[0]
23
+ try:
24
+ name = args_dict['name']
25
+ id = args_dict['id']
26
+ out_dir = args_dict['out_dir']
27
+ except KeyError:
28
+ raise ValueError('name, id, and out_dir are required in args')
29
+
30
+ client_id = args_dict.get('client_id', client_id)
31
+ session_id = args_dict.get('session_id', session_id)
32
+
33
+ task_info = {
34
+ 'task_id': task_id,
35
+ 'progress': {
36
+ 'progress': 0
37
+ },
38
+ 'status': 'created' if inactive else 'running', # Set status to 'created' if inactive
39
+ 'name': name,
40
+ 'out_dir': out_dir,
41
+ 'id': id,
42
+ 'client_id': client_id,
43
+ 'session_id': session_id
44
+ }
45
+
46
+ with self.lock:
47
+ self.tasks[task_id] = task_info
48
+ self.client_manager.add_task(client_id, session_id, task_id, task_info)
49
+
50
+ if not inactive:
51
+ thread = threading.Thread(target=self._run_task, args=(task_info, target, name, id, out_dir, client_id, session_id, *args[1:]))
52
+ thread.start()
53
+ else:
54
+ self.inactive_tasks[task_id] = {
55
+ 'target': target,
56
+ 'args': args,
57
+ 'task_info': task_info
58
+ }
59
+
60
+ return task_id
61
+
62
+ def start_task(self, task_id):
63
+ with self.lock:
64
+ if task_id in self.tasks:
65
+ if self.tasks[task_id]['status'] == 'created':
66
+ task_info = self.tasks[task_id]
67
+ target = self._get_target_function(task_id) # Replace with your actual logic to retrieve the target function
68
+ thread = threading.Thread(target=self._run_task, args=(task_info, target, task_info['name'], task_info['id'], task_info['out_dir'], task_info['client_id'], task_info['session_id']))
69
+ thread.start()
70
+ self.tasks[task_id]['status'] = 'running'
71
+ else:
72
+ raise ValueError(f"Task {task_id} is already running or completed.")
73
+
74
+ def _run_task(self, task_info, target, *args):
75
+ task_id = task_info['task_id']
76
+ try:
77
+ print(task_id, [*args], lambda progress: self._update_progress(task_id, progress))
78
+ target(task_id, *args, progress_callback=lambda progress: self._update_progress(task_id, progress))
79
+ with self.lock:
80
+ self.tasks[task_id]['url'] = f'/get-file/{task_id}/{self.tasks[task_id]["name"]}'
81
+ self.tasks[task_id]['status'] = 'completed'
82
+ self.client_manager.update_task(self.tasks[task_id])
83
+ except Exception as e:
84
+ with self.lock:
85
+ self.tasks[task_id]['status'] = 'failed'
86
+ self.tasks[task_id]['error'] = str(e)
87
+ self.client_manager.update_task(self.tasks[task_id])
88
+
89
+ def _update_progress(self, task_id, progress):
90
+ with self.lock:
91
+ if task_id in self.tasks:
92
+ self.tasks[task_id]['progress'] = progress
93
+ self.client_manager.update_task(self.tasks[task_id])
94
+
95
+ def get_progress(self, task_id):
96
+ with self.lock:
97
+ return self.tasks.get(task_id, {'status': 'not found'})
98
+
99
+ def _get_target_function(self, task_id):
100
+ if task_id in self.inactive_tasks:
101
+ return self.inactive_tasks[task_id]['target']
102
+ else:
103
+ raise ValueError(f"Task {task_id} is not inactive.")
104
+
105
+
beta/api/static/css/main.45e125bd.css ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ @font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-cyrillic-ext-300-normal.4777461b144e55145268.woff2) format("woff2"),url(/static/media/roboto-cyrillic-ext-300-normal.3503ec5cc6330e21f695.woff) format("woff");unicode-range:u+0460-052f,u+1c80-1c88,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-cyrillic-300-normal.1431d1cef06ad04f5458.woff2) format("woff2"),url(/static/media/roboto-cyrillic-300-normal.5b5f2f31962967dfc22c.woff) format("woff");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-greek-ext-300-normal.35b9d6be04b95f0f0530.woff2) format("woff2"),url(/static/media/roboto-greek-ext-300-normal.392a45a84c081c4b412d.woff) format("woff");unicode-range:u+1f??}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-greek-300-normal.db2632771401f61463fe.woff2) format("woff2"),url(/static/media/roboto-greek-300-normal.8ecd7085cfe9bc2c22ac.woff) format("woff");unicode-range:u+0370-0377,u+037a-037f,u+0384-038a,u+038c,u+038e-03a1,u+03a3-03ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-vietnamese-300-normal.32fc45a3d1e8ea11fabc.woff2) format("woff2"),url(/static/media/roboto-vietnamese-300-normal.8472d69545c7409091b4.woff) format("woff");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-latin-ext-300-normal.dc7dcec8e3f654e0ed63.woff2) format("woff2"),url(/static/media/roboto-latin-ext-300-normal.182712ab85f1472cdb2f.woff) format("woff");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(/static/media/roboto-latin-300-normal.c48fb6765a9fcb00b330.woff2) format("woff2"),url(/static/media/roboto-latin-300-normal.0515ab82dae6923cab85.woff) format("woff");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-cyrillic-ext-400-normal.804378952da8a10faae2.woff2) format("woff2"),url(/static/media/roboto-cyrillic-ext-400-normal.af4d91666ea345601bea.woff) format("woff");unicode-range:u+0460-052f,u+1c80-1c88,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-cyrillic-400-normal.71a33b6b50457b2c903a.woff2) format("woff2"),url(/static/media/roboto-cyrillic-400-normal.c1d66054fe23e181d92c.woff) format("woff");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-greek-ext-400-normal.169619821ea93019d1bb.woff2) format("woff2"),url(/static/media/roboto-greek-ext-400-normal.f708607d2a7290fb8bfa.woff) format("woff");unicode-range:u+1f??}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-greek-400-normal.c35e4c3958e209d17b31.woff2) format("woff2"),url(/static/media/roboto-greek-400-normal.dfdff8fa12eac629d29f.woff) format("woff");unicode-range:u+0370-0377,u+037a-037f,u+0384-038a,u+038c,u+038e-03a1,u+03a3-03ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-vietnamese-400-normal.3230f9b040f3c630e0c3.woff2) format("woff2"),url(/static/media/roboto-vietnamese-400-normal.e0e8ba725ebd107367a8.woff) format("woff");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-latin-ext-400-normal.861b791f9de857a6e7bc.woff2) format("woff2"),url(/static/media/roboto-latin-ext-400-normal.e757c42df6aaa3e11b62.woff) format("woff");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(/static/media/roboto-latin-400-normal.b009a76ad6afe4ebd301.woff2) format("woff2"),url(/static/media/roboto-latin-400-normal.3f2b9a42f643e62a49b7.woff) format("woff");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-cyrillic-ext-500-normal.62ced72e5832f02c2796.woff2) format("woff2"),url(/static/media/roboto-cyrillic-ext-500-normal.268f264f58eba5c07c88.woff) format("woff");unicode-range:u+0460-052f,u+1c80-1c88,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-cyrillic-500-normal.cad7d3d9cb265e334e58.woff2) format("woff2"),url(/static/media/roboto-cyrillic-500-normal.965aebef74db72eaf236.woff) format("woff");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-greek-ext-500-normal.6fb9cffb1d3e72bf9293.woff2) format("woff2"),url(/static/media/roboto-greek-ext-500-normal.eaa367bbd0b333a7f80b.woff) format("woff");unicode-range:u+1f??}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-greek-500-normal.9ac81fefbe6c319ea40b.woff2) format("woff2"),url(/static/media/roboto-greek-500-normal.1a05a4887ccb810cb4dd.woff) format("woff");unicode-range:u+0370-0377,u+037a-037f,u+0384-038a,u+038c,u+038e-03a1,u+03a3-03ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-vietnamese-500-normal.d8642a3d1d4ef6179644.woff2) format("woff2"),url(/static/media/roboto-vietnamese-500-normal.657896dad292ee9a0a0a.woff) format("woff");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-latin-ext-500-normal.9165081d10e1ba601384.woff2) format("woff2"),url(/static/media/roboto-latin-ext-500-normal.252057e589a0379208ed.woff) format("woff");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(/static/media/roboto-latin-500-normal.f25d774ecfe0996f8eb5.woff2) format("woff2"),url(/static/media/roboto-latin-500-normal.1f075502d0094a398e21.woff) format("woff");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-cyrillic-ext-700-normal.be4d02458ce53887dc37.woff2) format("woff2"),url(/static/media/roboto-cyrillic-ext-700-normal.198a421f279162d59143.woff) format("woff");unicode-range:u+0460-052f,u+1c80-1c88,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-cyrillic-700-normal.d010f1f324e111a22e53.woff2) format("woff2"),url(/static/media/roboto-cyrillic-700-normal.f8a034d72aa6828199d4.woff) format("woff");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-greek-ext-700-normal.bd9854c751441ccc1a70.woff2) format("woff2"),url(/static/media/roboto-greek-ext-700-normal.249853776d22a271b2b5.woff) format("woff");unicode-range:u+1f??}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-greek-700-normal.50e795c1345353b0e996.woff2) format("woff2"),url(/static/media/roboto-greek-700-normal.a84892c56152037b3552.woff) format("woff");unicode-range:u+0370-0377,u+037a-037f,u+0384-038a,u+038c,u+038e-03a1,u+03a3-03ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-vietnamese-700-normal.3425a701027d0699e369.woff2) format("woff2"),url(/static/media/roboto-vietnamese-700-normal.4df79f684fcbca8386bd.woff) format("woff");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-latin-ext-700-normal.ed67ad54b1a8f5d21150.woff2) format("woff2"),url(/static/media/roboto-latin-ext-700-normal.c1cc6d6fc851b3a2f79d.woff) format("woff");unicode-range:u+0100-02af,u+0304,u+0308,u+0329,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(/static/media/roboto-latin-700-normal.227c93190fe7f82de3f8.woff2) format("woff2"),url(/static/media/roboto-latin-700-normal.666d7a2f9db53cf52e2d.woff) format("woff");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+2074,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.App{text-align:center}.App-logo{height:40vmin;pointer-events:none}@media (prefers-reduced-motion:no-preference){.App-logo{animation:App-logo-spin 20s linear infinite}}.App-header{align-items:center;background-color:#282c34;color:#fff;display:flex;flex-direction:column;font-size:calc(10px + 2vmin);justify-content:center;min-height:100vh}.App-link{color:#61dafb}@keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
2
+ /*# sourceMappingURL=main.45e125bd.css.map*/
beta/api/static/css/main.45e125bd.css.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"static/css/main.45e125bd.css","mappings":"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","sources":["../node_modules/@fontsource/roboto/300.css","../node_modules/@fontsource/roboto/400.css","../node_modules/@fontsource/roboto/500.css","../node_modules/@fontsource/roboto/700.css","index.css","App.css"],"sourcesContent":["/* roboto-cyrillic-ext-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-cyrillic-ext-300-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-ext-300-normal.woff) format('woff');\n unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;\n}\n\n/* roboto-cyrillic-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-cyrillic-300-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-300-normal.woff) format('woff');\n unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;\n}\n\n/* roboto-greek-ext-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-greek-ext-300-normal.woff2) format('woff2'), url(./files/roboto-greek-ext-300-normal.woff) format('woff');\n unicode-range: U+1F00-1FFF;\n}\n\n/* roboto-greek-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-greek-300-normal.woff2) format('woff2'), url(./files/roboto-greek-300-normal.woff) format('woff');\n unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;\n}\n\n/* roboto-vietnamese-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-vietnamese-300-normal.woff2) format('woff2'), url(./files/roboto-vietnamese-300-normal.woff) format('woff');\n unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;\n}\n\n/* roboto-latin-ext-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-latin-ext-300-normal.woff2) format('woff2'), url(./files/roboto-latin-ext-300-normal.woff) format('woff');\n unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;\n}\n\n/* roboto-latin-300-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src: url(./files/roboto-latin-300-normal.woff2) format('woff2'), url(./files/roboto-latin-300-normal.woff) format('woff');\n unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;\n}","/* roboto-cyrillic-ext-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-cyrillic-ext-400-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-ext-400-normal.woff) format('woff');\n unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;\n}\n\n/* roboto-cyrillic-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-cyrillic-400-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-400-normal.woff) format('woff');\n unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;\n}\n\n/* roboto-greek-ext-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-greek-ext-400-normal.woff2) format('woff2'), url(./files/roboto-greek-ext-400-normal.woff) format('woff');\n unicode-range: U+1F00-1FFF;\n}\n\n/* roboto-greek-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-greek-400-normal.woff2) format('woff2'), url(./files/roboto-greek-400-normal.woff) format('woff');\n unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;\n}\n\n/* roboto-vietnamese-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-vietnamese-400-normal.woff2) format('woff2'), url(./files/roboto-vietnamese-400-normal.woff) format('woff');\n unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;\n}\n\n/* roboto-latin-ext-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-latin-ext-400-normal.woff2) format('woff2'), url(./files/roboto-latin-ext-400-normal.woff) format('woff');\n unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;\n}\n\n/* roboto-latin-400-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src: url(./files/roboto-latin-400-normal.woff2) format('woff2'), url(./files/roboto-latin-400-normal.woff) format('woff');\n unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;\n}","/* roboto-cyrillic-ext-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-cyrillic-ext-500-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-ext-500-normal.woff) format('woff');\n unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;\n}\n\n/* roboto-cyrillic-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-cyrillic-500-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-500-normal.woff) format('woff');\n unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;\n}\n\n/* roboto-greek-ext-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-greek-ext-500-normal.woff2) format('woff2'), url(./files/roboto-greek-ext-500-normal.woff) format('woff');\n unicode-range: U+1F00-1FFF;\n}\n\n/* roboto-greek-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-greek-500-normal.woff2) format('woff2'), url(./files/roboto-greek-500-normal.woff) format('woff');\n unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;\n}\n\n/* roboto-vietnamese-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-vietnamese-500-normal.woff2) format('woff2'), url(./files/roboto-vietnamese-500-normal.woff) format('woff');\n unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;\n}\n\n/* roboto-latin-ext-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-latin-ext-500-normal.woff2) format('woff2'), url(./files/roboto-latin-ext-500-normal.woff) format('woff');\n unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;\n}\n\n/* roboto-latin-500-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src: url(./files/roboto-latin-500-normal.woff2) format('woff2'), url(./files/roboto-latin-500-normal.woff) format('woff');\n unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;\n}","/* roboto-cyrillic-ext-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-cyrillic-ext-700-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-ext-700-normal.woff) format('woff');\n unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;\n}\n\n/* roboto-cyrillic-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-cyrillic-700-normal.woff2) format('woff2'), url(./files/roboto-cyrillic-700-normal.woff) format('woff');\n unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;\n}\n\n/* roboto-greek-ext-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-greek-ext-700-normal.woff2) format('woff2'), url(./files/roboto-greek-ext-700-normal.woff) format('woff');\n unicode-range: U+1F00-1FFF;\n}\n\n/* roboto-greek-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-greek-700-normal.woff2) format('woff2'), url(./files/roboto-greek-700-normal.woff) format('woff');\n unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;\n}\n\n/* roboto-vietnamese-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-vietnamese-700-normal.woff2) format('woff2'), url(./files/roboto-vietnamese-700-normal.woff) format('woff');\n unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;\n}\n\n/* roboto-latin-ext-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-latin-ext-700-normal.woff2) format('woff2'), url(./files/roboto-latin-ext-700-normal.woff) format('woff');\n unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;\n}\n\n/* roboto-latin-700-normal */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src: url(./files/roboto-latin-700-normal.woff2) format('woff2'), url(./files/roboto-latin-700-normal.woff) format('woff');\n unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;\n}","body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n monospace;\n}\n",".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"names":[],"sourceRoot":""}
beta/api/static/js/453.4633cf1b.chunk.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ "use strict";(self.webpackChunkuntitled1=self.webpackChunkuntitled1||[]).push([[453],{6453:(e,t,n)=>{n.r(t),n.d(t,{getCLS:()=>y,getFCP:()=>g,getFID:()=>C,getLCP:()=>P,getTTFB:()=>D});var i,r,a,o,u=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},c=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},f=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},s=function(e){addEventListener("pageshow",(function(t){t.persisted&&e(t)}),!0)},m=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},v=-1,d=function(){return"hidden"===document.visibilityState?0:1/0},p=function(){f((function(e){var t=e.timeStamp;v=t}),!0)},l=function(){return v<0&&(v=d(),p(),s((function(){setTimeout((function(){v=d(),p()}),0)}))),{get firstHiddenTime(){return v}}},g=function(e,t){var n,i=l(),r=u("FCP"),a=function(e){"first-contentful-paint"===e.name&&(f&&f.disconnect(),e.startTime<i.firstHiddenTime&&(r.value=e.startTime,r.entries.push(e),n(!0)))},o=window.performance&&performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],f=o?null:c("paint",a);(o||f)&&(n=m(e,r,t),o&&a(o),s((function(i){r=u("FCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,n(!0)}))}))})))},h=!1,T=-1,y=function(e,t){h||(g((function(e){T=e.value})),h=!0);var n,i=function(t){T>-1&&e(t)},r=u("CLS",0),a=0,o=[],v=function(e){if(!e.hadRecentInput){var t=o[0],i=o[o.length-1];a&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(a+=e.value,o.push(e)):(a=e.value,o=[e]),a>r.value&&(r.value=a,r.entries=o,n())}},d=c("layout-shift",v);d&&(n=m(i,r,t),f((function(){d.takeRecords().map(v),n(!0)})),s((function(){a=0,T=-1,r=u("CLS",0),n=m(i,r,t)})))},E={passive:!0,capture:!0},w=new Date,L=function(e,t){i||(i=t,r=e,a=new Date,F(removeEventListener),S())},S=function(){if(r>=0&&r<a-w){var e={entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+r};o.forEach((function(t){t(e)})),o=[]}},b=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){L(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,E),removeEventListener("pointercancel",i,E)};addEventListener("pointerup",n,E),addEventListener("pointercancel",i,E)}(t,e):L(t,e)}},F=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,b,E)}))},C=function(e,t){var n,a=l(),v=u("FID"),d=function(e){e.startTime<a.firstHiddenTime&&(v.value=e.processingStart-e.startTime,v.entries.push(e),n(!0))},p=c("first-input",d);n=m(e,v,t),p&&f((function(){p.takeRecords().map(d),p.disconnect()}),!0),p&&s((function(){var a;v=u("FID"),n=m(e,v,t),o=[],r=-1,i=null,F(addEventListener),a=d,o.push(a),S()}))},k={},P=function(e,t){var n,i=l(),r=u("LCP"),a=function(e){var t=e.startTime;t<i.firstHiddenTime&&(r.value=t,r.entries.push(e),n())},o=c("largest-contentful-paint",a);if(o){n=m(e,r,t);var v=function(){k[r.id]||(o.takeRecords().map(a),o.disconnect(),k[r.id]=!0,n(!0))};["keydown","click"].forEach((function(e){addEventListener(e,v,{once:!0,capture:!0})})),f(v,!0),s((function(i){r=u("LCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,k[r.id]=!0,n(!0)}))}))}))}},D=function(e){var t,n=u("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("load",(function(){return setTimeout(t,0)}))}}}]);
2
+ //# sourceMappingURL=453.4633cf1b.chunk.js.map
beta/api/static/js/453.4633cf1b.chunk.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"static/js/453.4633cf1b.chunk.js","mappings":"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","sources":["../node_modules/web-vitals/dist/web-vitals.js"],"sourcesContent":["var e,t,n,i,r=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:\"v2-\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12)}},a=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if(\"first-input\"===e&&!(\"PerformanceEventTiming\"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},o=function(e,t){var n=function n(i){\"pagehide\"!==i.type&&\"hidden\"!==document.visibilityState||(e(i),t&&(removeEventListener(\"visibilitychange\",n,!0),removeEventListener(\"pagehide\",n,!0)))};addEventListener(\"visibilitychange\",n,!0),addEventListener(\"pagehide\",n,!0)},u=function(e){addEventListener(\"pageshow\",(function(t){t.persisted&&e(t)}),!0)},c=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},f=-1,s=function(){return\"hidden\"===document.visibilityState?0:1/0},m=function(){o((function(e){var t=e.timeStamp;f=t}),!0)},v=function(){return f<0&&(f=s(),m(),u((function(){setTimeout((function(){f=s(),m()}),0)}))),{get firstHiddenTime(){return f}}},d=function(e,t){var n,i=v(),o=r(\"FCP\"),f=function(e){\"first-contentful-paint\"===e.name&&(m&&m.disconnect(),e.startTime<i.firstHiddenTime&&(o.value=e.startTime,o.entries.push(e),n(!0)))},s=window.performance&&performance.getEntriesByName&&performance.getEntriesByName(\"first-contentful-paint\")[0],m=s?null:a(\"paint\",f);(s||m)&&(n=c(e,o,t),s&&f(s),u((function(i){o=r(\"FCP\"),n=c(e,o,t),requestAnimationFrame((function(){requestAnimationFrame((function(){o.value=performance.now()-i.timeStamp,n(!0)}))}))})))},p=!1,l=-1,h=function(e,t){p||(d((function(e){l=e.value})),p=!0);var n,i=function(t){l>-1&&e(t)},f=r(\"CLS\",0),s=0,m=[],v=function(e){if(!e.hadRecentInput){var t=m[0],i=m[m.length-1];s&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(s+=e.value,m.push(e)):(s=e.value,m=[e]),s>f.value&&(f.value=s,f.entries=m,n())}},h=a(\"layout-shift\",v);h&&(n=c(i,f,t),o((function(){h.takeRecords().map(v),n(!0)})),u((function(){s=0,l=-1,f=r(\"CLS\",0),n=c(i,f,t)})))},T={passive:!0,capture:!0},y=new Date,g=function(i,r){e||(e=r,t=i,n=new Date,w(removeEventListener),E())},E=function(){if(t>=0&&t<n-y){var r={entryType:\"first-input\",name:e.type,target:e.target,cancelable:e.cancelable,startTime:e.timeStamp,processingStart:e.timeStamp+t};i.forEach((function(e){e(r)})),i=[]}},S=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;\"pointerdown\"==e.type?function(e,t){var n=function(){g(e,t),r()},i=function(){r()},r=function(){removeEventListener(\"pointerup\",n,T),removeEventListener(\"pointercancel\",i,T)};addEventListener(\"pointerup\",n,T),addEventListener(\"pointercancel\",i,T)}(t,e):g(t,e)}},w=function(e){[\"mousedown\",\"keydown\",\"touchstart\",\"pointerdown\"].forEach((function(t){return e(t,S,T)}))},L=function(n,f){var s,m=v(),d=r(\"FID\"),p=function(e){e.startTime<m.firstHiddenTime&&(d.value=e.processingStart-e.startTime,d.entries.push(e),s(!0))},l=a(\"first-input\",p);s=c(n,d,f),l&&o((function(){l.takeRecords().map(p),l.disconnect()}),!0),l&&u((function(){var a;d=r(\"FID\"),s=c(n,d,f),i=[],t=-1,e=null,w(addEventListener),a=p,i.push(a),E()}))},b={},F=function(e,t){var n,i=v(),f=r(\"LCP\"),s=function(e){var t=e.startTime;t<i.firstHiddenTime&&(f.value=t,f.entries.push(e),n())},m=a(\"largest-contentful-paint\",s);if(m){n=c(e,f,t);var d=function(){b[f.id]||(m.takeRecords().map(s),m.disconnect(),b[f.id]=!0,n(!0))};[\"keydown\",\"click\"].forEach((function(e){addEventListener(e,d,{once:!0,capture:!0})})),o(d,!0),u((function(i){f=r(\"LCP\"),n=c(e,f,t),requestAnimationFrame((function(){requestAnimationFrame((function(){f.value=performance.now()-i.timeStamp,b[f.id]=!0,n(!0)}))}))}))}},P=function(e){var t,n=r(\"TTFB\");t=function(){try{var t=performance.getEntriesByType(\"navigation\")[0]||function(){var e=performance.timing,t={entryType:\"navigation\",startTime:0};for(var n in e)\"navigationStart\"!==n&&\"toJSON\"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},\"complete\"===document.readyState?setTimeout(t,0):addEventListener(\"load\",(function(){return setTimeout(t,0)}))};export{h as getCLS,d as getFCP,L as getFID,F as getLCP,P as getTTFB};\n"],"names":["e","t","n","i","r","name","value","delta","entries","id","concat","Date","now","Math","floor","random","a","PerformanceObserver","supportedEntryTypes","includes","self","getEntries","map","observe","type","buffered","o","document","visibilityState","removeEventListener","addEventListener","u","persisted","c","f","s","m","timeStamp","v","setTimeout","firstHiddenTime","d","disconnect","startTime","push","window","performance","getEntriesByName","requestAnimationFrame","p","l","h","hadRecentInput","length","takeRecords","T","passive","capture","y","g","w","E","entryType","target","cancelable","processingStart","forEach","S","L","b","F","once","P","getEntriesByType","timing","max","navigationStart","responseStart","readyState"],"sourceRoot":""}
beta/api/static/js/main.00bb85dc.js ADDED
The diff for this file is too large to render. See raw diff
 
beta/api/static/js/main.00bb85dc.js.LICENSE.txt ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @license
2
+ Papa Parse
3
+ v5.4.1
4
+ https://github.com/mholt/PapaParse
5
+ License: MIT
6
+ */
7
+
8
+ /**
9
+ * @license React
10
+ * react-dom.production.min.js
11
+ *
12
+ * Copyright (c) Facebook, Inc. and its affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ */
17
+
18
+ /**
19
+ * @license React
20
+ * react-is.production.min.js
21
+ *
22
+ * Copyright (c) Facebook, Inc. and its affiliates.
23
+ *
24
+ * This source code is licensed under the MIT license found in the
25
+ * LICENSE file in the root directory of this source tree.
26
+ */
27
+
28
+ /**
29
+ * @license React
30
+ * react-jsx-runtime.production.min.js
31
+ *
32
+ * Copyright (c) Facebook, Inc. and its affiliates.
33
+ *
34
+ * This source code is licensed under the MIT license found in the
35
+ * LICENSE file in the root directory of this source tree.
36
+ */
37
+
38
+ /**
39
+ * @license React
40
+ * react.production.min.js
41
+ *
42
+ * Copyright (c) Facebook, Inc. and its affiliates.
43
+ *
44
+ * This source code is licensed under the MIT license found in the
45
+ * LICENSE file in the root directory of this source tree.
46
+ */
47
+
48
+ /**
49
+ * @license React
50
+ * scheduler.production.min.js
51
+ *
52
+ * Copyright (c) Facebook, Inc. and its affiliates.
53
+ *
54
+ * This source code is licensed under the MIT license found in the
55
+ * LICENSE file in the root directory of this source tree.
56
+ */
57
+
58
+ /**
59
+ * @mui/material v5.15.20
60
+ *
61
+ * @license MIT
62
+ * This source code is licensed under the MIT license found in the
63
+ * LICENSE file in the root directory of this source tree.
64
+ */
65
+
66
+ /**
67
+ * @remix-run/router v1.16.1
68
+ *
69
+ * Copyright (c) Remix Software Inc.
70
+ *
71
+ * This source code is licensed under the MIT license found in the
72
+ * LICENSE.md file in the root directory of this source tree.
73
+ *
74
+ * @license MIT
75
+ */
76
+
77
+ /**
78
+ * React Router v6.23.1
79
+ *
80
+ * Copyright (c) Remix Software Inc.
81
+ *
82
+ * This source code is licensed under the MIT license found in the
83
+ * LICENSE.md file in the root directory of this source tree.
84
+ *
85
+ * @license MIT
86
+ */
87
+
88
+ /** @license React v16.13.1
89
+ * react-is.production.min.js
90
+ *
91
+ * Copyright (c) Facebook, Inc. and its affiliates.
92
+ *
93
+ * This source code is licensed under the MIT license found in the
94
+ * LICENSE file in the root directory of this source tree.
95
+ */
beta/api/static/js/main.00bb85dc.js.map ADDED
The diff for this file is too large to render. See raw diff
 
beta/api/static/media/logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg ADDED
beta/api/static/media/roboto-cyrillic-300-normal.1431d1cef06ad04f5458.woff2 ADDED
Binary file (9.58 kB). View file
 
beta/api/static/media/roboto-cyrillic-300-normal.5b5f2f31962967dfc22c.woff ADDED
Binary file (8.43 kB). View file
 
beta/api/static/media/roboto-cyrillic-400-normal.71a33b6b50457b2c903a.woff2 ADDED
Binary file (9.63 kB). View file
 
beta/api/static/media/roboto-cyrillic-400-normal.c1d66054fe23e181d92c.woff ADDED
Binary file (8.39 kB). View file
 
beta/api/static/media/roboto-cyrillic-500-normal.965aebef74db72eaf236.woff ADDED
Binary file (8.7 kB). View file
 
beta/api/static/media/roboto-cyrillic-500-normal.cad7d3d9cb265e334e58.woff2 ADDED
Binary file (9.84 kB). View file
 
beta/api/static/media/roboto-cyrillic-700-normal.d010f1f324e111a22e53.woff2 ADDED
Binary file (9.64 kB). View file
 
beta/api/static/media/roboto-cyrillic-700-normal.f8a034d72aa6828199d4.woff ADDED
Binary file (8.66 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-300-normal.3503ec5cc6330e21f695.woff ADDED
Binary file (13.5 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-300-normal.4777461b144e55145268.woff2 ADDED
Binary file (15 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-400-normal.804378952da8a10faae2.woff2 ADDED
Binary file (15.3 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-400-normal.af4d91666ea345601bea.woff ADDED
Binary file (13.5 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-500-normal.268f264f58eba5c07c88.woff ADDED
Binary file (13.4 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-500-normal.62ced72e5832f02c2796.woff2 ADDED
Binary file (15 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-700-normal.198a421f279162d59143.woff ADDED
Binary file (13.4 kB). View file
 
beta/api/static/media/roboto-cyrillic-ext-700-normal.be4d02458ce53887dc37.woff2 ADDED
Binary file (14.7 kB). View file
 
beta/api/static/media/roboto-greek-300-normal.8ecd7085cfe9bc2c22ac.woff ADDED
Binary file (6.44 kB). View file
 
beta/api/static/media/roboto-greek-300-normal.db2632771401f61463fe.woff2 ADDED
Binary file (7.12 kB). View file
 
beta/api/static/media/roboto-greek-400-normal.c35e4c3958e209d17b31.woff2 ADDED
Binary file (7.11 kB). View file
 
beta/api/static/media/roboto-greek-400-normal.dfdff8fa12eac629d29f.woff ADDED
Binary file (6.35 kB). View file
 
beta/api/static/media/roboto-greek-500-normal.1a05a4887ccb810cb4dd.woff ADDED
Binary file (6.32 kB). View file
 
beta/api/static/media/roboto-greek-500-normal.9ac81fefbe6c319ea40b.woff2 ADDED
Binary file (7.02 kB). View file
 
beta/api/static/media/roboto-greek-700-normal.50e795c1345353b0e996.woff2 ADDED
Binary file (6.94 kB). View file
 
beta/api/static/media/roboto-greek-700-normal.a84892c56152037b3552.woff ADDED
Binary file (6.3 kB). View file
 
beta/api/static/media/roboto-greek-ext-300-normal.35b9d6be04b95f0f0530.woff2 ADDED
Binary file (1.48 kB). View file
 
beta/api/static/media/roboto-greek-ext-300-normal.392a45a84c081c4b412d.woff ADDED
Binary file (1.25 kB). View file
 
beta/api/static/media/roboto-greek-ext-400-normal.169619821ea93019d1bb.woff2 ADDED
Binary file (1.48 kB). View file