Commit Graph
145 Commits
Author SHA1 Message Date
imSp4rky d860eb9e01 fix(proxy): check the proxy exit IP before any service request
A dead proxy, or one that exits from this machine's IP, now fails with INVALID_PROXY instead of retrying every request; remote session create also builds the service off the event loop so a stuck check cannot block the server.
2026-09-10 17:08:04 -06:00
imSp4rky 0b055e43ba fix(api): stop serve leaking server credentials, paths, and cross-tenant data 2026-09-08 16:43:39 -06:00
imSp4rky 84b0a92c41 feat(api): report the live title and the client's command line to the dashboard 2026-09-07 17:03:36 -06:00
imSp4rky 627f1fa81c fix(dl): cache server-CDM keys to the local vaults
Batch and per-track remote licences read the vaults but never wrote back, so a --remote or import run kept nothing. Vault hits now replicate to the other vaults, and the server branch resolves keys under drm_lock like the local path.
2026-09-06 23:10:04 -06:00
imSp4rky d36797641d feat(dl): add --no-postscript to skip post-scripts for one run 2026-09-06 21:02:58 -06:00
imSp4rky fe7b3bb651 test(downloader): cover session state carried into download children
Assert that verify, params, cert and auth reach a spawned child, and that a mounted adapter the child cannot reproduce falls back to the single-process path. Documents --download-processes in the CLI reference.
2026-09-06 20:04:25 -06:00
imSp4rky 85503fd87c test(downloader): cover probe judging and the submission window
Assert that a probe is judged on the trailing tick, that a backoff is temporary and climbs back to the cap, and that a worker always finds its next segment staged. Documents adaptive-workers behaviour in the downloading guide.
2026-09-06 20:03:46 -06:00
imSp4rky adea7583f0 test(services): use placeholder tags instead of real service names 2026-09-05 22:16:22 -06:00
imSp4rky b0efa6c8d8 fix(dl): reject local proxies when --remote targets another machine
Gluetun and loopback proxy URIs only listen on this machine. Stop with an error instead of forwarding them, unless the server is on this machine too.
2026-09-05 10:50:35 -06:00
imSp4rky dffb72e41d fix(audio): accept immersive channel layouts like 5.1.4
parse_channels rejected a three-figure layout, so a remote download crashed rebuilding the track from JSON. Add channel_total so --channels can compare either form.
2026-09-04 19:27:39 -06:00
imSp4rky 235839abc8 feat(audio): support DTS:X Profile 2 with MP4 muxing
Route titles with a dtsx/dtsy sample entry to MP4 via MP4Box, since Matroska has no CodecID for DTS-UHD. Add per-rendition HLS audio codec selection, fix merge_segments progress and its cleanup path.
2026-09-04 14:19:29 -06:00
imSp4rky b391ffc80a perf(kv): push keys to vaults concurrently, log one summary per title
Vaults.add_key and add_keys now push to every vault at the same time, so one unreachable vault costs its own timeout instead of the sum. MySQL defaults connect_timeout to vault_timeout.
2026-09-04 09:13:31 -06:00
imSp4rky 3eaf4431e2 fix(dl): repair damaged cookie files without rewriting them
Space separators, a BOM, a missing header and #HttpOnly_ rows now load; repairs happen in memory and an unparseable file raises instead of loading as empty.
2026-09-03 10:53:00 -06:00
imSp4rky 8354235d56 feat(serve): add operator dashboard endpoints and per-key rate limits 2026-09-02 23:52:55 -06:00
imSp4rky ac8f71b969 fix(remote): send per-track MPD fragments for service-built AdaptationSets
A service can build an AdaptationSet the served manifest does not contain, so the client's re-parse could never find it and the track downloaded with no manifest data. Those tracks now get a one-AdaptationSet MPD of their own.
2026-09-02 15:13:06 -06:00
imSp4rky 7310273594 fix(ism): signal Dolby Vision and Atmos from Smooth manifests
Init segments now carry dvcC/dvvC with a profile-keyed sample entry and the dby1 brand; track ids cover the manifest URL so per-range ladders stop colliding, and the remote path carries the Atmos flag without inventing a JOC count.
2026-09-01 12:50:59 -06:00
imSp4rky a01ff594da fix(remote): send only the active profile's cache files to the server
The client withheld nothing before: every profile's tokens went to any remote server. Filter by active-credential digests and profile names, keeping service-global files; worst case for a withheld file is a server-side re-auth.
2026-08-30 21:17:20 -06:00
imSp4rky f7b1446427 feat(serve): forward per-session service logs to remote-dl clients
Mirror each remote session's self.log into a bounded buffer, drained by the client via GET /api/session/{id}/logs and re-emitted locally. Server-account sessions get no relay. Also namespace service CLI options under service_params so a transport key (profile) no longer collides with a service's own option, on both the session and download-job paths.
2026-08-30 20:52:18 -06:00
imSp4rky d9b21229c3 feat(serve)!: add server-held accounts for remote sessions
serve.server_accounts lends region-tagged server credentials to remote sessions (round-robin per region, per-key opt-in, per-account cache). Remote sessions no longer fall back to the server's local credentials when the client sends none.
2026-08-28 16:36:39 -06:00
imSp4rky e3f4e52444 feat(serve): add --quiet mode and developer dashboard API
Headless serve with plain stderr logging; /api/dashboard/* (status, sessions, jobs, logs, SSE/poll events) behind a separate serve.dashboard.key.
2026-08-28 13:18:41 -06:00
imSp4rky c49fccf3b5 fix(remote): resolve service names against the remote server
Remote mode resolved names with the local alias table and built an empty stub for any unknown tag, so an unentitled service showed a blank help page. Resolve against the server's tags and aliases, and reject unknown names with the list the server does offer.
2026-08-28 10:54:21 -06:00
imSp4rky 3cb3613565 feat(remote): forward HLS segment filters to remote clients
Add POST /api/session/{id}/segment_filter: the server runs the service's OnSegmentFilter and returns only the unwanted segment URIs, so ads and bumpers are dropped over --remote-only without exposing service code.
2026-08-27 23:56:16 -06:00
imSp4rky e9ed05d4b2 feat(vaults): batch HTTP json vault writes with InsertKeys 2026-08-27 18:21:45 -06:00
imSp4rky 160ca063a6 feat(vaults): batch HTTP json vault writes with InsertKeys
Try one InsertKeys call per 500 content keys, falling back to per-key InsertKey only when the server answers 404; kv copy/sync chunk 500 for json mode.
2026-08-27 18:10:09 -06:00
imSp4rky 4ef577c1d1 fix(tracks): match resolutions per range and codec
An exact height match in one range denied the 16:9 canvas fallback to the others, so a cropped HDR10 or SDR track was dropped whenever an uncropped DV track matched the requested height. Also sweep the hybrid L5 temp files so a killed run cannot leave a stale RPU behind.
2026-08-27 14:32:36 -06:00
imSp4rky dcc1c8af18 feat(serve)!: gate the server's own proxies behind server_proxy
The server no longer spends its configured proxy providers on a remote client unless the API key sets server_proxy. It places the client by geolocating the connection address and asks for a proxy when that region does not match its own.
2026-08-27 12:43:53 -06:00
imSp4rky 3aa275035b feat(serve): gate server_cdm per service and let clients follow it
serve.users.<key>.server_cdm accepts a list of service tags; retry re-attaches the job service and a bare string no longer fails open. An unset client server_cdm now follows the server's per-service /tracks flag.
2026-08-27 10:10:46 -06:00
imSp4rky 5128fef473 feat(serve): hot-reload service repos on a timer without a restart
Add serve.services_refresh_interval; refresh pulls the repos and re-imports only the changed services, staging any with active jobs until they finish. Report skipped/broken services in the log and on /api/services.
2026-08-26 23:14:23 -06:00
imSp4rky 4964869258 feat(services): add services_repo_force and compact refresh output
Force-reset repo clones on the automatic TTL refresh when enabled. Report refresh changes as one +/~/-/!TAG line per repo.
2026-08-26 22:15:39 -06:00
imSp4rky 97c939630c fix(remote): carry the full title and track state across the remote API
Services set the original language, track names, repack flags, editions and track.data inside get_tracks; the client dropped them so --remote muxed with no default audio and could not select "orig". Also round-trip Song titles, subtitle DRM, PlayReady PSSH, exact bitrate and path-only attachments.
2026-08-26 21:33:17 -06:00
imSp4rky 89f09f8e84 perf(drm): decrypt fMP4 segments during download with mp4decrypt
Opt-in decrypt_segments runs mp4decrypt --fragments-info per segment on a thread pool as segments land (DASH, single-init HLS), then decrypts the init alone; hides the post-download decrypt step with byte-identical output.
2026-08-26 16:27:55 -06:00
imSp4rky b94f338619 docs(post-scripts): use post-script as the one term for hooks
Add the post-script row to the ste-writing terminology contract and
replace hook/postscript/post-download script across docs and docstrings.
2026-08-25 19:57:41 -06:00
imSp4rky 40cad41cc4 feat(post-scripts): add wait option to block until the script exits
Per-entry `wait: true` (default false) makes dispatch() wait for the script and log its exit code; a non-zero exit never fails the download.
2026-08-25 19:19:41 -06:00
imSp4rky e804d09f0a feat(dl): add --cdm to pin one CDM device for a run
Overrides the cdm config mapping (and its quality/DRM sub-entries) for the whole run; the REST API cdm field now flows through the same param.
2026-08-24 16:37:48 -06:00
imSp4rky 8c43250c9b feat(dl): add --no-attachments to skip cover art and subtitle fonts
Drops service attachments at track selection and skips the font attach pass; exposed as no_attachments in the REST dl params and documented.
2026-08-24 16:21:52 -06:00
imSp4rky 1f96a4bd78 fix(subtitle): keep WebVTT-only cue markup out of converted subtitles
Strip cue classes, <v>/<lang>/ruby and karaoke timestamps before conversion, decode entities for SRT/SSA/ASS, load pysubs2 as utf-8-sig, and route sdh_method: filter-subs through convert_before_strip instead of raising.
2026-08-24 15:55:06 -06:00
imSp4rky 0a68cc2452 fix(services): match service aliases without case
Uppercase entries in ALIASES never resolved, because get_tag lowercased the input but not the alias. Match real tags first so a service's own tag cannot be taken by another service's alias.
2026-08-24 11:56:46 -06:00
imSp4rky d8739b3561 feat(dl): add --require-audio/--require-video and --warn-only alias
Gate a title on audio or video languages that must exist, independent of what -l/-al/-vl select. --require-subs joins the same gate: its --s-lang conflict and download-all side effect are gone, so -sl now decides what to keep. Requiring a language that is also excluded fails at parse time.
2026-08-23 12:24:45 -06:00
imSp4rky a4be2cd23a fix(music): remux songs into the container of their codec
A song skips the muxer, so the decrypted fragmented MP4 was the delivered file: its header states a length of zero and FLAC in an MP4 is not a FLAC stream, so playback stopped early and tagging failed.
2026-08-21 14:00:04 -06:00
imSp4rky 79cabc9a70 docs(dev): correct get_chapters guidance on markers at timestamp 0 2026-08-21 10:46:03 -06:00
imSp4rky 5cdba70760 docs: widen supported shaka-packager range to 2.6.1 or >= 3.10.0 2026-08-20 18:50:03 -06:00
imSp4rky 537a1dc973 perf(dl): parallelise mux, licensing, and vault lookups; size the shared pool
Grow the service session pool to downloads * workers before track downloads, run mkvmerge jobs concurrently (muxing.concurrency, default 4), lock DRM preparation per key set instead of globally, and query local vaults first then remote vaults together.
2026-08-20 11:24:12 -06:00
imSp4rky 8b10b793e2 docs: phase 2 of the prose style across docs and docstrings 2026-08-19 20:59:09 -06:00
imSp4rky 66971230c3 docs: apply simplified technical english across docs and docstrings. 2026-08-19 16:31:06 -06:00
imSp4rky 4177cb2267 fix(hls): keep ad-filtered segments out of DRM key state 2026-08-19 14:39:09 -06:00
imSp4rky 29d0828c33 style: clean up prose 2026-08-19 13:45:58 -06:00
imSp4rky 68c7d95173 refactor(music)!: make Song an ordinary Title on the generic path
Delete the dead grouped-download block, the planner, and the music service hooks; Song now flows through the one download loop, gets tagged via tag_file, and answers -w with {disc}x{track} keys.

BREAKING CHANGE: GROUP_AUDIO_DOWNLOADS, get_music_track_options and get_music_collection_label are gone. A music service returns one Audio track per quality and lets the framework choose.
2026-08-18 15:05:30 -06:00
imSp4rky 89acfab279 feat(dl): run user post-download scripts with metadata variables
New post_scripts config and repeatable --postscript flag run a command per output, season/album folder, or run, substituting filename-template variables into pre-tokenized argv. The REST API rejects hook commands.

Closes #150
2026-08-18 08:26:14 -06:00
imSp4rky 42718cbd99 fix(titles): drop folder {year?} when it repeats the dated season label
Dated episodes turn the season folder into the air year, so a folder template's {year?} rendered the same year twice (Title.2025.2025).
2026-08-16 22:01:12 -06:00
imSp4rky 619c86cd10 feat(downloader): resume failed downloads from completed segments across runs
Fingerprint-gated reuse of atomically-published segment files (DASH/ISM/HLS) behind a continue_downloads config option and one-off dl --continue-downloads flag.
2026-08-16 19:38:06 -06:00