catacomb/Cargo.toml
Luna 8d1c274075 Tackle remaining unscoped items: cookies chmod, log redact, Bandcamp, ETag+gzip
Four items knocked off the unscoped list:

Auto-chmod 0600 cookies.txt
- web::write_cookies now sets mode 0600 on the file after writing, on Unix.
  Mirrors the same guard we put on yt-offline.db. cookies.txt carries
  live session credentials; no reason for it to stay umask-default.

Redact cookies path from job log
- Downloader::spawn_job now runs each stdout/stderr line through a small
  redactor that replaces the absolute cookies.txt path with the bare
  filename before forwarding to the Job log. yt-dlp can echo the path
  in error strings, which leaks $HOME into the UI and /api/progress
  responses.
- 2 new tests cover the strip + pass-through cases.

Bandcamp full-discography mode
- Bandcamp at the bare artist URL is already a Channel in our classifier
  and yt-dlp's BandcampUserIE returns the full discography. The output
  template for Bandcamp's channel case now organizes tracks into
  per-album subfolders via `%(album|Unknown)s` so a discography pull
  stays coherent instead of one flat directory.
- New `Downloader::apply_platform_extras` adds `--embed-thumbnail` for
  audio-first platforms (Bandcamp, SoundCloud) so music players see the
  cover art via embedded tags rather than scanning for a sidecar JPEG.

Library ETag + gzip
- WebState gains `library_version: AtomicU64`. `bump_library_version()`
  is called from post_rescan, post_watched, post_maintenance_remove, and
  post_resume (only when crossing the "Continue watching" >3.0 boundary
  so playback-time updates don't constantly invalidate the cache).
- get_library is now Response-returning; it consults `If-None-Match` and
  short-circuits with 304 Not Modified when the client's ETag matches.
  Otherwise it sends `ETag: "<n>"` alongside the JSON.
- JS `loadLibrary()` caches the ETag and sends it on subsequent calls.
  Returns early on 304 keeping the existing in-memory library array.
- Adds `tower_http::compression::CompressionLayer` (gzip). Already-
  compressed media served from ServeDir is auto-skipped by the layer;
  JSON responses get ~10× smaller. New `compression-gzip` feature on
  the tower-http dep.

46 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 00:26:47 -07:00

27 lines
1.2 KiB
TOML

[package]
name = "yt-offline"
version = "0.1.0"
edition = "2021"
description = "Self-hosted archive for YouTube, TikTok, Twitch, Vimeo, Bandcamp, SoundCloud, Odysee and more. Desktop GUI + web UI, bundled yt-dlp with curl_cffi impersonation, Plex export, SQLite-backed resume tracking. AGPL-3.0."
[dependencies]
eframe = "0.29"
image = { version = "0.25", default-features = false, features = ["webp", "jpeg", "png"] }
toml = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rusqlite = { version = "0.31", features = ["bundled"] }
notify-rust = { version = "4", default-features = false, features = ["z"] }
axum = { version = "0.7", features = ["macros"] }
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", features = ["io"] }
tokio-stream = "0.1"
tower-http = { version = "0.5", features = ["cors", "fs", "compression-gzip"] }
argon2 = "0.5"
rand = "0.8"
# File-picker dialog for the desktop GUI. xdg-portal backend keeps it pure-Rust
# (zbus, no GTK/libdbus build dep), consistent with notify-rust above.
rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "tokio"] }
[profile.release]
opt-level = 2