fastapi>=0.115,<1.0 # Multipart form parsing — required by Starlette/FastAPI to accept file uploads (UploadFile/Form). # The download center's local-file Upload (E7) is the only multipart endpoint in the app. python-multipart>=0.0.9,<1.0 uvicorn[standard]>=0.30,<1.0 sqlalchemy>=2.0,<2.1 psycopg[binary]>=3.2,<4.0 alembic>=1.13,<2.0 pydantic>=2.7,<3.0 pydantic-settings>=2.3,<3.0 authlib>=1.3,<2.0 httpx>=0.27,<1.0 feedparser>=6.0,<7.0 apscheduler>=3.10,<4.0 py3langid>=0.3,<1.0 itsdangerous>=2.1,<3.0 cryptography>=50.0.0,<51 argon2-cffi>=23.1,<26 # Download center: yt-dlp does the extraction/download; ffmpeg (OS-level in the Dockerfile) # does the merge + postprocessing. The [default] extra pulls yt-dlp-ejs (the challenge-solver # scripts Deno runs for YouTube's n-signature). yt-dlp is release-often (YouTube changes), so # keep the floor loose and bump it when extraction breaks. yt-dlp[default]>=2025.5.22 # Browser impersonation (`impersonate`) for Facebook downloads made with the user's cookie: some # links answer a signed-in plain request with "Cannot parse data" and only parse as Chrome (E11.5, # measured). The range is YT-DLP's, not ours — yt-dlp 2026.07.04 imports curl_cffi only in # 0.10.x–0.15.x and silently reports every target "unavailable" outside it. Move it when bumping # yt-dlp; `tests/test_facebook_impersonation.py::test_the_locked_curl_cffi_can_impersonate_chrome` # fails the gate if the locked pair can no longer impersonate. curl_cffi>=0.10,<0.16 # PO Token provider plugin: talks to the bgutil sidecar (brainicism/bgutil-ytdlp-pot-provider) # to mint YouTube Proof-of-Origin tokens on demand, bypassing "confirm you're not a bot" and # unlocking high-quality formats. Pin to match the sidecar image tag (versions must align). bgutil-ytdlp-pot-provider==1.3.1