diff --git a/Dockerfile b/Dockerfile index 8f4d36e..17d7944 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,13 +18,16 @@ ENV PYTHONUNBUFFERED=1 \ # System deps: ffmpeg (transcode + thumbnails, FC-2), unar (archives, FC-2), # libpq for psycopg, postgresql-client + zstd for FC-5 backup/restore -# (pg_dump + tar --zstd), image libs. +# (pg_dump + tar --zstd), image libs, megatools (mega.nz public-link downloads +# for off-platform file-host links, #830 — `megatools dl`; Debian-native, no +# external MEGA apt repo needed). RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ unar \ libpq5 \ postgresql-client \ zstd \ + megatools \ libjpeg62-turbo \ libwebp7 \ libpng16-16 \ diff --git a/backend/app/services/external_fetch.py b/backend/app/services/external_fetch.py index 0ab6855..265092b 100644 --- a/backend/app/services/external_fetch.py +++ b/backend/app/services/external_fetch.py @@ -16,8 +16,8 @@ Backends: - pixeldrain : GET the /api/file/{id} endpoint. - mediafire : scrape the download page for the direct link + stream GET. - gdrive : gdown (handles the confirm-token + virus-scan interstitial). - - mega : MEGAcmd `mega-get` subprocess (public link incl. #key); needs - the binary in the runtime image. + - mega : `megatools dl` subprocess (public link incl. #key); needs the + `megatools` binary in the runtime image (Debian apt package). Public links work credential-free (rule 26); per-host creds are a later Settings concern. Plain-HTTP homelab — no secure-context API. The HTTP / gdown / @@ -89,16 +89,17 @@ def _gdown_download(url: str, out_dir: str) -> str | None: def _run_mega_get(url: str, out_dir: str, *, timeout: float) -> None: """Download a mega.nz public link (key in the #fragment) into out_dir via - MEGAcmd's `mega-get`. Raises ExternalFetchError on non-zero exit.""" - # Fixed argv (not shell): only `url` is external input, and it's a positional - # arg to mega-get, so there's no shell-injection surface. + `megatools dl` (the Debian `megatools` package). Raises ExternalFetchError + on non-zero exit.""" + # Fixed argv (not shell): only `url` is external input, passed positionally, + # so there's no shell-injection surface. proc = subprocess.run( - ["mega-get", url, out_dir], + ["megatools", "dl", "--path", out_dir, url], capture_output=True, text=True, timeout=timeout, check=False, ) if proc.returncode != 0: raise ExternalFetchError( - f"mega-get exit {proc.returncode}: {(proc.stderr or '').strip()[:300]}" + f"megatools dl exit {proc.returncode}: {(proc.stderr or '').strip()[:300]}" ) diff --git a/requirements.txt b/requirements.txt index c57f5d2..05f7231 100644 --- a/requirements.txt +++ b/requirements.txt @@ -41,5 +41,5 @@ py7zr>=1,<2 # Google Drive fetcher for off-platform file-host links (external downloads, # #830). Handles Drive's confirm-token + virus-scan interstitial. mega.nz uses -# the MEGAcmd `mega-get` binary instead (added to the runtime image, not pip). +# the `megatools` binary instead (Debian apt pkg in the runtime image, not pip). gdown>=5,<6