Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +2 -35
- .gitignore +199 -0
- Dockerfile +67 -0
- README.md +181 -10
- beta/api/api.py +40 -0
- beta/api/api_dl.py +35 -0
- beta/api/blueprints/api_pref_manager.py +39 -0
- beta/api/blueprints/client_info_routes.py +103 -0
- beta/api/blueprints/leagacy_create_task.py +40 -0
- beta/api/blueprints/session_lodge.py +82 -0
- beta/api/blueprints/template_routes.py +25 -0
- beta/api/blueprints/while_dl_and_post_dl.py +35 -0
- beta/api/mr_manager/boss_manager.py +8 -0
- beta/api/mr_manager/client_manager.py +119 -0
- beta/api/mr_manager/task_manager.py +105 -0
- beta/api/static/css/main.45e125bd.css +2 -0
- beta/api/static/css/main.45e125bd.css.map +1 -0
- beta/api/static/js/453.4633cf1b.chunk.js +2 -0
- beta/api/static/js/453.4633cf1b.chunk.js.map +1 -0
- beta/api/static/js/main.00bb85dc.js +0 -0
- beta/api/static/js/main.00bb85dc.js.LICENSE.txt +95 -0
- beta/api/static/js/main.00bb85dc.js.map +0 -0
- beta/api/static/media/logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg +1 -0
- beta/api/static/media/roboto-cyrillic-300-normal.1431d1cef06ad04f5458.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-300-normal.5b5f2f31962967dfc22c.woff +0 -0
- beta/api/static/media/roboto-cyrillic-400-normal.71a33b6b50457b2c903a.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-400-normal.c1d66054fe23e181d92c.woff +0 -0
- beta/api/static/media/roboto-cyrillic-500-normal.965aebef74db72eaf236.woff +0 -0
- beta/api/static/media/roboto-cyrillic-500-normal.cad7d3d9cb265e334e58.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-700-normal.d010f1f324e111a22e53.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-700-normal.f8a034d72aa6828199d4.woff +0 -0
- beta/api/static/media/roboto-cyrillic-ext-300-normal.3503ec5cc6330e21f695.woff +0 -0
- beta/api/static/media/roboto-cyrillic-ext-300-normal.4777461b144e55145268.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-ext-400-normal.804378952da8a10faae2.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-ext-400-normal.af4d91666ea345601bea.woff +0 -0
- beta/api/static/media/roboto-cyrillic-ext-500-normal.268f264f58eba5c07c88.woff +0 -0
- beta/api/static/media/roboto-cyrillic-ext-500-normal.62ced72e5832f02c2796.woff2 +0 -0
- beta/api/static/media/roboto-cyrillic-ext-700-normal.198a421f279162d59143.woff +0 -0
- beta/api/static/media/roboto-cyrillic-ext-700-normal.be4d02458ce53887dc37.woff2 +0 -0
- beta/api/static/media/roboto-greek-300-normal.8ecd7085cfe9bc2c22ac.woff +0 -0
- beta/api/static/media/roboto-greek-300-normal.db2632771401f61463fe.woff2 +0 -0
- beta/api/static/media/roboto-greek-400-normal.c35e4c3958e209d17b31.woff2 +0 -0
- beta/api/static/media/roboto-greek-400-normal.dfdff8fa12eac629d29f.woff +0 -0
- beta/api/static/media/roboto-greek-500-normal.1a05a4887ccb810cb4dd.woff +0 -0
- beta/api/static/media/roboto-greek-500-normal.9ac81fefbe6c319ea40b.woff2 +0 -0
- beta/api/static/media/roboto-greek-700-normal.50e795c1345353b0e996.woff2 +0 -0
- beta/api/static/media/roboto-greek-700-normal.a84892c56152037b3552.woff +0 -0
- beta/api/static/media/roboto-greek-ext-300-normal.35b9d6be04b95f0f0530.woff2 +0 -0
- beta/api/static/media/roboto-greek-ext-300-normal.392a45a84c081c4b412d.woff +0 -0
- beta/api/static/media/roboto-greek-ext-400-normal.169619821ea93019d1bb.woff2 +0 -0
.gitattributes
CHANGED
@@ -1,35 +1,2 @@
|
|
1 |
-
|
2 |
-
|
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 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|