ytp-dl 0.6.3__py3-none-any.whl → 0.6.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
scripts/api.py CHANGED
@@ -5,9 +5,9 @@ import os
5
5
  import shutil
6
6
  import tempfile
7
7
  import time
8
+ from threading import BoundedSemaphore, Lock
8
9
 
9
10
  from flask import Flask, request, send_file, jsonify
10
- from gevent.lock import Semaphore
11
11
 
12
12
  from .downloader import validate_environment, download_video
13
13
 
@@ -17,10 +17,15 @@ BASE_DOWNLOAD_DIR = os.environ.get("YTPDL_JOB_BASE_DIR", "/root/ytpdl_jobs")
17
17
  os.makedirs(BASE_DOWNLOAD_DIR, exist_ok=True)
18
18
 
19
19
  MAX_CONCURRENT = int(os.environ.get("YTPDL_MAX_CONCURRENT", "1"))
20
- _sem = Semaphore(MAX_CONCURRENT)
20
+
21
+ # Thread-safe concurrency gate (caps actual download jobs).
22
+ _sem = BoundedSemaphore(MAX_CONCURRENT)
23
+
24
+ # Track in-flight jobs for /healthz reporting.
25
+ _in_use = 0
26
+ _in_use_lock = Lock()
21
27
 
22
28
  # Failsafe: delete abandoned job dirs older than this many seconds.
23
- # (keep 21600 if you prefer; 3600 is fine too)
24
29
  STALE_JOB_TTL_S = int(os.environ.get("YTPDL_STALE_JOB_TTL_S", "3600"))
25
30
 
26
31
  _ALLOWED_EXTENSIONS = {"mp3", "mp4", "best"}
@@ -43,11 +48,28 @@ def _cleanup_stale_jobs() -> None:
43
48
  pass
44
49
 
45
50
 
51
+ def _try_acquire_job_slot() -> bool:
52
+ global _in_use
53
+ if not _sem.acquire(blocking=False):
54
+ return False
55
+ with _in_use_lock:
56
+ _in_use += 1
57
+ return True
58
+
59
+
60
+ def _release_job_slot() -> None:
61
+ global _in_use
62
+ with _in_use_lock:
63
+ if _in_use > 0:
64
+ _in_use -= 1
65
+ _sem.release()
66
+
67
+
46
68
  @app.route("/api/download", methods=["POST"])
47
69
  def handle_download():
48
70
  _cleanup_stale_jobs()
49
71
 
50
- if not _sem.acquire(blocking=False):
72
+ if not _try_acquire_job_slot():
51
73
  return jsonify(error="Server busy, try again later"), 503
52
74
 
53
75
  job_dir: str | None = None
@@ -57,7 +79,7 @@ def handle_download():
57
79
  nonlocal released
58
80
  if not released:
59
81
  released = True
60
- _sem.release()
82
+ _release_job_slot()
61
83
 
62
84
  try:
63
85
  data = request.get_json(force=True)
@@ -90,8 +112,7 @@ def handle_download():
90
112
  if not (filename and os.path.exists(filename)):
91
113
  raise RuntimeError("Download failed")
92
114
 
93
- # Release semaphore as soon as yt-dlp is done.
94
- # Streaming the file should not block the next download job.
115
+ # Release slot as soon as yt-dlp is done.
95
116
  _release_once()
96
117
 
97
118
  response = send_file(filename, as_attachment=True)
@@ -126,7 +147,9 @@ def handle_download():
126
147
 
127
148
  @app.route("/healthz", methods=["GET"])
128
149
  def healthz():
129
- return jsonify(ok=True, in_use=(MAX_CONCURRENT - _sem.counter), capacity=MAX_CONCURRENT), 200
150
+ with _in_use_lock:
151
+ in_use = _in_use
152
+ return jsonify(ok=True, in_use=in_use, capacity=MAX_CONCURRENT), 200
130
153
 
131
154
 
132
155
  def main():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ytp-dl
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: YouTube video downloader with Mullvad VPN integration and Flask API
5
5
  Home-page: https://github.com/yourusername/ytp-dl
6
6
  Author: dumgum82
@@ -20,7 +20,6 @@ Description-Content-Type: text/markdown
20
20
  Requires-Dist: yt-dlp[default]
21
21
  Requires-Dist: flask
22
22
  Requires-Dist: requests
23
- Requires-Dist: gevent
24
23
  Requires-Dist: gunicorn
25
24
  Dynamic: author
26
25
  Dynamic: author-email
@@ -34,39 +33,39 @@ Dynamic: summary
34
33
 
35
34
  # ytp-dl
36
35
 
37
- > A lightweight YouTube downloader with Mullvad VPN integration and HTTP API
36
+ A lightweight YouTube downloader with Mullvad VPN integration and an HTTP API.
38
37
 
39
38
  [![PyPI version](https://img.shields.io/pypi/v/ytp-dl.svg)](https://pypi.org/project/ytp-dl/)
40
39
  [![Python Support](https://img.shields.io/pypi/pyversions/ytp-dl.svg)](https://pypi.org/project/ytp-dl/)
41
40
  [![License](https://img.shields.io/pypi/l/ytp-dl.svg)](https://pypi.org/project/ytp-dl/)
42
41
  [![Downloads](https://img.shields.io/pypi/dm/ytp-dl.svg)](https://pypi.org/project/ytp-dl/)
43
42
 
44
- **ytp-dl** is a privacy-focused YouTube downloader that automatically routes downloads through Mullvad VPN via an HTTP API.
43
+ **ytp-dl** is a privacy-focused YouTube downloader that routes downloads through Mullvad VPN via an HTTP API.
45
44
 
46
45
  ---
47
46
 
48
- ## Features
47
+ ## Features
49
48
 
50
- * 🔒 **Privacy First** — Automatically connects/disconnects Mullvad VPN per download
51
- * 🎥 **Smart Quality Selection** Prefers 1080p H.264 + AAC (no transcoding needed)
52
- * 🎵 **Audio Downloads** Extract audio as MP3
53
- * 🚀 **HTTP API** Simple Flask-based API with concurrency controls
54
- * ⚡ **VPS Ready** — Includes automated installer script for Ubuntu
49
+ * Privacy-first: connect/disconnect Mullvad per download
50
+ * Smart quality selection: prefers 1080p H.264 + AAC (no transcoding)
51
+ * Audio downloads: extract audio as MP3
52
+ * HTTP API: simple Flask API with concurrency controls
53
+ * VPS-ready: automated installer script for Ubuntu
55
54
 
56
55
  ---
57
56
 
58
- ## 📦 Installation
57
+ ## Installation
59
58
 
60
59
  ```bash
61
- pip install ytp-dl==0.6.3 yt-dlp[default]
60
+ pip install ytp-dl==0.6.5 yt-dlp[default]
62
61
  ```
63
62
 
64
- **Requirements:**
63
+ Requirements:
65
64
 
66
- * Linux operating system (tested on Ubuntu 24.04/25.04)
67
- * [Mullvad CLI](https://mullvad.net/en/download/vpn/linux) installed and configured
68
- * FFmpeg (for handling audio + video)
69
- * Deno (system-wide, required by yt-dlp for modern YouTube extraction)
65
+ * Linux (tested on Ubuntu 24.04/25.04)
66
+ * Mullvad CLI installed and configured
67
+ * FFmpeg (audio/video handling)
68
+ * Deno (system-wide; required by yt-dlp for modern YouTube extraction)
70
69
  * Python 3.8+
71
70
 
72
71
  Notes:
@@ -75,29 +74,38 @@ Notes:
75
74
 
76
75
  ---
77
76
 
78
- ## 🎯 Using Your VPS
77
+ ## Using your VPS
79
78
 
80
- Once your VPS is running, you can download videos using simple HTTP requests:
79
+ Once your VPS is running, you can download videos using simple HTTP requests.
81
80
 
82
- ### Download a Video (1080p MP4)
81
+ ### Download a video (1080p MP4)
83
82
 
84
83
  ```bash
85
- curl -X POST http://YOUR_VPS_IP:5000/api/download -H "Content-Type: application/json" -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}' --output video.mp4
84
+ curl -X POST http://YOUR_VPS_IP:5000/api/download \
85
+ -H "Content-Type: application/json" \
86
+ -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}' \
87
+ --output video.mp4
86
88
  ```
87
89
 
88
- ### Download Audio Only (MP3)
90
+ ### Download audio only (MP3)
89
91
 
90
92
  ```bash
91
- curl -X POST http://YOUR_VPS_IP:5000/api/download -H "Content-Type: application/json" -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "extension": "mp3"}' --output audio.mp3
93
+ curl -X POST http://YOUR_VPS_IP:5000/api/download \
94
+ -H "Content-Type: application/json" \
95
+ -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "extension": "mp3"}' \
96
+ --output audio.mp3
92
97
  ```
93
98
 
94
- ### Download at Specific Resolution
99
+ ### Download at a specific resolution
95
100
 
96
101
  ```bash
97
- curl -X POST http://YOUR_VPS_IP:5000/api/download -H "Content-Type: application/json" -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "resolution": 720}' --output video.mp4
102
+ curl -X POST http://YOUR_VPS_IP:5000/api/download \
103
+ -H "Content-Type: application/json" \
104
+ -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "resolution": 720}' \
105
+ --output video.mp4
98
106
  ```
99
107
 
100
- ### Check Server Health
108
+ ### Check server health
101
109
 
102
110
  ```bash
103
111
  curl http://YOUR_VPS_IP:5000/healthz
@@ -125,7 +133,7 @@ response = requests.post(
125
133
  "resolution": 1080,
126
134
  "extension": "mp4"
127
135
  },
128
- stream=True
136
+ stream=True,
129
137
  )
130
138
 
131
139
  if response.status_code == 200:
@@ -140,28 +148,29 @@ else:
140
148
 
141
149
  ---
142
150
 
143
- ## ⚙️ Configuration
151
+ ## Configuration
144
152
 
145
- ### Installation Script Variables
153
+ ### Installation script variables
146
154
 
147
- These environment variables configure the VPS installation (they can be overridden when running the script):
155
+ These environment variables configure the VPS installation (you can override them when running the script).
148
156
 
149
157
  | Variable | Description | Default |
150
158
  | ------------------------ | --------------------------------------- | --------------------- |
151
159
  | `PORT` | API server port | `5000` |
152
160
  | `APP_DIR` | Installation directory | `/opt/yt-dlp-mullvad` |
153
- | `MV_ACCOUNT` | Mullvad account number | your mullvad id |
161
+ | `MV_ACCOUNT` | Mullvad account number | (empty) |
154
162
  | `YTPDL_MAX_CONCURRENT` | Max simultaneous downloads (API cap) | `1` |
155
163
  | `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code (e.g. `us`) | `us` |
164
+ | `GUNICORN_THREADS` | Threads per Gunicorn worker | `4` |
156
165
 
157
166
  Notes:
158
167
 
159
168
  * If `MV_ACCOUNT` is set, the installer attempts `mullvad account login <MV_ACCOUNT>` once.
160
169
  * If `MV_ACCOUNT` is left empty, the script skips login and assumes Mullvad is already configured.
161
170
 
162
- ### Runtime Environment Variables
171
+ ### Runtime environment variables
163
172
 
164
- After installation, these variables control the API behavior. They are set in `/etc/default/ytp-dl-api` and can be edited manually:
173
+ After installation, these are set in `/etc/default/ytp-dl-api` and can be edited manually.
165
174
 
166
175
  | Variable | Description | Default |
167
176
  | ------------------------ | ----------------------------- | -------------------------- |
@@ -178,50 +187,33 @@ sudo systemctl restart ytp-dl-api
178
187
 
179
188
  ---
180
189
 
181
- ## 🔧 Managing Your VPS Service
182
-
183
- ### View Service Status
190
+ ## Managing your VPS service
184
191
 
185
192
  ```bash
186
193
  sudo systemctl status ytp-dl-api
187
- ```
188
-
189
- ### View Logs
190
-
191
- ```bash
192
194
  sudo journalctl -u ytp-dl-api -f
193
- ```
194
-
195
- ### Restart Service
196
-
197
- ```bash
198
195
  sudo systemctl restart ytp-dl-api
199
- ```
200
-
201
- ### Stop/Start Service
202
-
203
- ```bash
204
196
  sudo systemctl stop ytp-dl-api
205
197
  sudo systemctl start ytp-dl-api
206
198
  ```
207
199
 
208
200
  ---
209
201
 
210
- ## 📋 API Reference
202
+ ## API reference
211
203
 
212
204
  ### POST `/api/download`
213
205
 
214
- **Request Body:**
206
+ Request body:
215
207
 
216
208
  ```json
217
209
  {
218
210
  "url": "string (required)",
219
211
  "resolution": "integer (optional, default: 1080)",
220
- "extension": "string (optional, 'mp4' or 'mp3')"
212
+ "extension": "string (optional, 'mp4', 'mp3', or 'best')"
221
213
  }
222
214
  ```
223
215
 
224
- **Response:**
216
+ Response:
225
217
 
226
218
  * `200 OK` - File download stream
227
219
  * `400 Bad Request` - Missing or invalid URL
@@ -230,8 +222,6 @@ sudo systemctl start ytp-dl-api
230
222
 
231
223
  ### GET `/healthz`
232
224
 
233
- **Response:**
234
-
235
225
  ```json
236
226
  {
237
227
  "ok": true,
@@ -242,16 +232,22 @@ sudo systemctl start ytp-dl-api
242
232
 
243
233
  ---
244
234
 
245
- ## 🖥️ VPS Deployment
235
+ ## VPS deployment
236
+
237
+ ### Why policy routing is included
238
+
239
+ When Mullvad connects/disconnects, Linux routing can change in a way that breaks inbound TCP handshakes (clients see intermittent connection timeouts). The installer sets up a small policy-routing rule that forces replies sourced from your public VPS IP to use the public interface, keeping the API reachable even while Mullvad is cycling.
246
240
 
247
- **What it does:**
241
+ ### What the installer does
248
242
 
249
- * Installs Python, FFmpeg, and Mullvad CLI
250
- * Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
251
- * Creates virtualenv at `/opt/yt-dlp-mullvad/venv`
252
- * Installs `ytp-dl==0.6.3` + `yt-dlp[default]` into the virtualenv
253
- * Sets up systemd service on port 5000
254
- * Configures Gunicorn with gevent workers
243
+ * Installs Python, FFmpeg, Mullvad CLI, and Deno
244
+ * Creates a virtualenv at `/opt/yt-dlp-mullvad/venv`
245
+ * Installs `ytp-dl==0.6.5` + `yt-dlp[default]` + `gunicorn`
246
+ * Installs a policy-routing oneshot service to keep the public API reachable
247
+ * Sets up a systemd service on port 5000
248
+ * Runs Gunicorn with `gthread` (threaded) workers
249
+
250
+ Note: `gthread` is a built-in Gunicorn worker class (no extra Python dependency).
255
251
 
256
252
  ```bash
257
253
  #!/usr/bin/env bash
@@ -260,9 +256,10 @@ sudo systemctl start ytp-dl-api
260
256
  # What this does:
261
257
  # - Installs Python, ffmpeg, Mullvad CLI
262
258
  # - Installs Deno system-wide (JS runtime required for modern YouTube extraction via yt-dlp)
259
+ # - Configures policy routing so the public API stays reachable while Mullvad toggles
263
260
  # - Creates a virtualenv at /opt/yt-dlp-mullvad/venv
264
- # - Installs ytp-dl==0.6.3 + yt-dlp[default] + gunicorn + gevent in that venv
265
- # - Creates a simple systemd service ytp-dl-api.service on port 5000
261
+ # - Installs ytp-dl==0.6.5 + yt-dlp[default] + gunicorn in that venv
262
+ # - Creates a systemd service ytp-dl-api.service on port 5000
266
263
  #
267
264
  # Mullvad connect/disconnect is handled per-job by downloader.py.
268
265
 
@@ -273,17 +270,33 @@ PORT="${PORT:-5000}" # API listen port
273
270
  APP_DIR="${APP_DIR:-/opt/yt-dlp-mullvad}" # app/venv root
274
271
  VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}" # python venv
275
272
 
276
- MV_ACCOUNT="${MV_ACCOUNT:-}" # Mullvad account (put number after -)
273
+ MV_ACCOUNT="${MV_ACCOUNT:-}" # Mullvad account (optional)
277
274
  YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
278
275
  YTPDL_MULLVAD_LOCATION="${YTPDL_MULLVAD_LOCATION:-us}" # default Mullvad relay hint
276
+ GUNICORN_THREADS="${GUNICORN_THREADS:-4}" # keep API responsive on small VPS
279
277
  ### -------------------------------------------------------------------------
280
278
 
281
279
  [[ "${EUID}" -eq 0 ]] || { echo "Please run as root"; exit 1; }
282
280
  export DEBIAN_FRONTEND=noninteractive
283
281
 
282
+ echo "==> 0) Capture public routing (pre-VPN)"
283
+ PUB_DEV="$(ip route show default | awk '/default/ {print $5; exit}')"
284
+ PUB_GW="$(ip route show default | awk '/default/ {print $3; exit}')"
285
+ PUB_IP="$(ip -4 addr show dev "${PUB_DEV}" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)"
286
+
287
+ if [[ -z "${PUB_DEV}" || -z "${PUB_GW}" || -z "${PUB_IP}" ]]; then
288
+ echo "Failed to detect public routing (PUB_DEV/PUB_GW/PUB_IP)."
289
+ echo "PUB_DEV=${PUB_DEV} PUB_GW=${PUB_GW} PUB_IP=${PUB_IP}"
290
+ exit 1
291
+ fi
292
+
293
+ echo "Public dev: ${PUB_DEV} | gw: ${PUB_GW} | ip: ${PUB_IP}"
294
+
284
295
  echo "==> 1) Base packages & Mullvad CLI"
285
296
  apt-get update
286
- apt-get install -yq --no-install-recommends python3-venv python3-pip curl ffmpeg ca-certificates unzip
297
+ apt-get install -yq --no-install-recommends \
298
+ python3-venv python3-pip curl ffmpeg ca-certificates unzip \
299
+ iproute2 iptables
287
300
 
288
301
  if ! command -v mullvad >/dev/null 2>&1; then
289
302
  curl -fsSLo /tmp/mullvad.deb https://mullvad.net/download/app/deb/latest/
@@ -297,6 +310,77 @@ fi
297
310
 
298
311
  mullvad status || true
299
312
 
313
+ # Keep the public API reachable even if Mullvad disconnects between jobs.
314
+ # (Lockdown mode can block all traffic while disconnected.)
315
+ mullvad lockdown-mode set off || true
316
+ mullvad lan set allow || true
317
+
318
+ echo "==> 1.1) Policy routing: keep replies from ${PUB_IP} on ${PUB_DEV}"
319
+ # Loose reverse-path filtering avoids drops when the default route changes under VPN.
320
+ tee /etc/sysctl.d/99-ytpdl-policy-routing.conf >/dev/null <<EOF
321
+ net.ipv4.conf.all.rp_filter=2
322
+ net.ipv4.conf.default.rp_filter=2
323
+ net.ipv4.conf.${PUB_DEV}.rp_filter=2
324
+ EOF
325
+ sysctl --system >/dev/null
326
+
327
+ # Persist the detected public route info for re-apply at boot.
328
+ tee /etc/default/ytpdl-policy-routing >/dev/null <<EOF
329
+ PUB_DEV=${PUB_DEV}
330
+ PUB_GW=${PUB_GW}
331
+ PUB_IP=${PUB_IP}
332
+ EOF
333
+
334
+ # Add a routing table id if it doesn't already exist.
335
+ grep -qE '^100\s+ytpdl-public$' /etc/iproute2/rt_tables || echo '100 ytpdl-public' >> /etc/iproute2/rt_tables
336
+
337
+ # Idempotent apply script.
338
+ tee /usr/local/sbin/ytpdl-policy-routing.sh >/dev/null <<'EOF'
339
+ #!/usr/bin/env bash
340
+ set -euo pipefail
341
+
342
+ source /etc/default/ytpdl-policy-routing
343
+
344
+ TABLE_ID="100"
345
+ TABLE_NAME="ytpdl-public"
346
+ PRIO="11000"
347
+
348
+ # Ensure table has the public default route.
349
+ ip route replace default via "${PUB_GW}" dev "${PUB_DEV}" table "${TABLE_NAME}"
350
+
351
+ # Ensure rule exists (replace is not supported for rules).
352
+ if ip rule show | grep -qE "^${PRIO}:.*from ${PUB_IP}/32 lookup ${TABLE_NAME}\b"; then
353
+ :
354
+ else
355
+ # remove any stale rule at this priority
356
+ while ip rule show | grep -qE "^${PRIO}:"; do
357
+ ip rule del priority "${PRIO}" || true
358
+ done
359
+ ip rule add priority "${PRIO}" from "${PUB_IP}/32" table "${TABLE_NAME}"
360
+ fi
361
+
362
+ ip route flush cache || true
363
+ EOF
364
+ chmod +x /usr/local/sbin/ytpdl-policy-routing.sh
365
+
366
+ tee /etc/systemd/system/ytpdl-policy-routing.service >/dev/null <<EOF
367
+ [Unit]
368
+ Description=ytp-dl policy routing (keep public API reachable)
369
+ After=network-online.target
370
+ Wants=network-online.target
371
+
372
+ [Service]
373
+ Type=oneshot
374
+ ExecStart=/usr/local/sbin/ytpdl-policy-routing.sh
375
+ RemainAfterExit=yes
376
+
377
+ [Install]
378
+ WantedBy=multi-user.target
379
+ EOF
380
+
381
+ systemctl daemon-reload
382
+ systemctl enable --now ytpdl-policy-routing.service
383
+
300
384
  echo "==> 1.5) Install Deno (system-wide, for yt-dlp YouTube extraction)"
301
385
  # Install into /usr/local/bin/deno so systemd PATH can see it.
302
386
  # Official installer supports system-wide install via DENO_INSTALL=/usr/local.
@@ -310,7 +394,7 @@ mkdir -p "${APP_DIR}"
310
394
  python3 -m venv "${VENV_DIR}"
311
395
  source "${VENV_DIR}/bin/activate"
312
396
  pip install --upgrade pip
313
- pip install "ytp-dl==0.6.3" "yt-dlp[default]" gunicorn gevent
397
+ pip install "ytp-dl==0.6.5" "yt-dlp[default]" gunicorn
314
398
  deactivate
315
399
 
316
400
  echo "==> 3) API environment file (/etc/default/ytp-dl-api)"
@@ -324,8 +408,9 @@ echo "==> 4) Gunicorn systemd service (ytp-dl-api.service on :${PORT})"
324
408
  tee /etc/systemd/system/ytp-dl-api.service >/dev/null <<EOF
325
409
  [Unit]
326
410
  Description=Gunicorn for ytp-dl Mullvad API (minimal)
327
- After=network-online.target
411
+ After=network-online.target ytpdl-policy-routing.service
328
412
  Wants=network-online.target
413
+ Requires=ytpdl-policy-routing.service
329
414
 
330
415
  [Service]
331
416
  User=root
@@ -334,7 +419,9 @@ EnvironmentFile=/etc/default/ytp-dl-api
334
419
  Environment=VIRTUAL_ENV=${VENV_DIR}
335
420
  Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
336
421
 
337
- ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1 --worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 --bind 0.0.0.0:${PORT} scripts.api:app
422
+ ExecStart=${VENV_DIR}/bin/gunicorn -k gthread -w 1 --threads ${GUNICORN_THREADS} \
423
+ --timeout 0 --graceful-timeout 15 --keep-alive 20 \
424
+ --bind 0.0.0.0:${PORT} scripts.api:app
338
425
 
339
426
  Restart=always
340
427
  RestartSec=3
@@ -363,5 +450,6 @@ echo "========================================="
363
450
  echo "Installation complete!"
364
451
  echo "API running on port ${PORT}"
365
452
  echo "Test from outside: curl http://YOUR_VPS_IP:${PORT}/healthz"
453
+ echo "If you use UFW: sudo ufw allow ${PORT}/tcp"
366
454
  echo "========================================="
367
455
  ```
@@ -0,0 +1,8 @@
1
+ scripts/__init__.py,sha256=EbAplfCcyLD3Q_9sxemm6owCc5_UJv53vmlxy810p2s,152
2
+ scripts/api.py,sha256=cyLjHmelLwzh8-GOjqXsQdhm6wLX8bOkADZ_qU1naRQ,4331
3
+ scripts/downloader.py,sha256=vvHasu-41DGPDUzOTA4kz52tijTkaii1NnuU4cHQxg8,10825
4
+ ytp_dl-0.6.5.dist-info/METADATA,sha256=XVL2522dMVIjIPh8cHZXSkkJM-7GRb-KyS_lfAwcOBI,14547
5
+ ytp_dl-0.6.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
6
+ ytp_dl-0.6.5.dist-info/entry_points.txt,sha256=QqjqZZAEt3Y7RGrleqZ312sjjboUpbMLdo7qFxuCH30,48
7
+ ytp_dl-0.6.5.dist-info/top_level.txt,sha256=rmzd5mewlrJy4sT608KPib7sM7edoY75AeqJeY3SPB4,8
8
+ ytp_dl-0.6.5.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- scripts/__init__.py,sha256=EbAplfCcyLD3Q_9sxemm6owCc5_UJv53vmlxy810p2s,152
2
- scripts/api.py,sha256=EmTmzhpElx5QaJJ5z8GiimJTVZOHRoKhcReIRUCShBg,3943
3
- scripts/downloader.py,sha256=vvHasu-41DGPDUzOTA4kz52tijTkaii1NnuU4cHQxg8,10825
4
- ytp_dl-0.6.3.dist-info/METADATA,sha256=Rloz8LictcjPy_qXwkUtYWjAKyefSAGbxQ3GvmSyBv8,11342
5
- ytp_dl-0.6.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
6
- ytp_dl-0.6.3.dist-info/entry_points.txt,sha256=QqjqZZAEt3Y7RGrleqZ312sjjboUpbMLdo7qFxuCH30,48
7
- ytp_dl-0.6.3.dist-info/top_level.txt,sha256=rmzd5mewlrJy4sT608KPib7sM7edoY75AeqJeY3SPB4,8
8
- ytp_dl-0.6.3.dist-info/RECORD,,
File without changes