Commit Graph
280 Commits
Author SHA1 Message Date
imSp4rky e509db618e fix(api): keep a pooled remote session to the api key that opened it
The pool key now includes the caller's API key and client_region, so a hit never skips the server_proxy and region checks that a fresh session runs.
2026-11-01 19:47:19 -07:00
imSp4rky 96c3840b82 fix(session): keep cookie paths so same-name cookies stay on their own path
RnetCookieAdapter stores cookies by domain, path and name and sends path, secure and a leading-dot domain to rnet. It also takes server-rotated values, and worker children and track sessions get the cookies with their paths.
2026-10-31 22:57:22 -06:00
imSp4rky 86f26c31d5 refactor(tracks): name and match resolutions by one standard-height rule
standard_resolution() replaces the aspect-ratio logic in naming and is shared by -q matching, export names and progress/hybrid labels, so 1920x1088, 1916x1076, portrait and DCI sizes get standard names.
2026-10-31 22:05:26 -06:00
imSp4rky 15e46d8bcc fix(titles): name a PQ video track without HDR10 metadata HDR 2026-10-31 21:42:11 -06:00
imSp4rky f9c1c3d390 feat(tracks): add subtitle.dedupe_codecs to keep one codec per subtitle variant 2026-10-31 16:35:01 -06:00
imSp4rky 65e807bf5f fix(subtitle): join cues that a segment boundary splits in stpp and wvtt
Share one append_cue join across DASH fTTML, ISM and fVTT parsing. Also map "geo-block" and "geolocation" errors to GEOFENCE in the API.
2026-10-31 15:59:12 -06:00
imSp4rky cbeff379fb fix(subtitle): place fragment-relative ISM TTML cues on the track timeline
Smooth Streaming TTML times cues from each fragment's start; a whole track stacked into the first fragment. Also stop rebase_ttml failing on a track with no cues.
2026-10-30 23:40:46 -06:00
imSp4rky 0c45195fe2 fix(subtitle): remove the DASH presentationTimeOffset from stpp and wvtt cues
STPP and WVTT cues sit on the media timeline, so they played late by the offset after the mux.
2026-10-30 23:22:47 -06:00
imSp4rky e6a627118f feat(tracks): add a display-only note shown in --list and over --remote 2026-10-30 16:17:36 -06:00
imSp4rky 5206b3cab6 refactor(remote)!: send service options only in service_params
A service option named like a dl option (e.g. --profile) is no longer dropped or mixed with the dl value; the server casts nested values and keeps cli defaults nested.
2026-10-30 16:16:56 -06:00
imSp4rky 17d4905577 fix(titles): compare dub languages under their macrolanguage
A cmn track on a zh title no longer gets DUBBED, and nb and nn count as no; yue stays separate.
2026-10-29 21:23:45 -06:00
imSp4rky d4abcb51d9 feat(naming): add audio_contain_all language tag condition
An empty audio_contain_all or subs_contain_all list now never matches; before this, an empty subs_contain_all list matched every release.
2026-10-29 14:41:06 -06:00
imSp4rky bd64f3a8c4 fix(api): stop a service's sys.exit from killing the serve process
Catch SystemExit at service import, in the heartbeat task, the 5xx middleware, search, samples and chapters, and answer it as SERVICE_ERROR.
2026-10-29 11:23:53 -06:00
imSp4rky 7b927934e0 feat(remote)!: let server_cdm outrank a service's cdm entry and set it per service
server_cdm: true on a remote_services entry now licenses remote runs with the server CDM even when the service has its own cdm entry, which stays the local-run device and the fallback. A services.<TAG>.server_cdm replaces the server value for one service, per-service entries match the tag in any case, and the configured fallback logs at info.

BREAKING CHANGE: with server_cdm: true, a per-service cdm entry no longer makes your own device license remote sessions; use dl --cdm or services.<TAG>.server_cdm: false.
2026-10-29 10:18:15 -06:00
imSp4rky d12a943d96 fix(api): show filename codec and range labels in codec_display and range_display 2026-10-28 15:34:52 -06:00
imSp4rky b0c006d7f6 feat(naming): add codec_names to rename codec and HDR labels in filenames
A codec name that ends in a digit now gets a separator before the channels, so AC-4 2.0 gives AC-4.2.0 and no longer AC-42.0.
2026-10-28 14:19:23 -06:00
imSp4rky 2e75cc35a1 feat(kv): accept an sqlite vault file path and read plain-tag tables on copy
A kv vault argument can be the path to an SQLite vault file. With -s, kv copy reads the VAULT_TAG table and the plain-tag table into the VAULT_TAG table.
2026-10-27 13:58:14 -06:00
imSp4rky 9f86464826 fix(api): cache the health update check and fix a remote-session test fixture 2026-10-27 13:38:57 -06:00
imSp4rky 756c2ce2b5 feat(remote): reopen a lost remote session and resume at the current title 2026-10-27 13:24:31 -06:00
imSp4rky 9017ab95b7 feat(tracks): add Video.hdr10_base and forward s_lang over remote and REST
A DV track with an HDR10 base (profile 8.1) lists as DV+HDR10; dl_params now carry s_lang.
2026-10-27 13:06:48 -06:00
imSp4rky 84fd0a4bee feat(tracks): add Tracks.dedupe and match variant tracks by signature
get_tracks_for_variants skips a later manifest's track when a held track has the same signature, so a track whose ID changes per manifest is listed once.
2026-10-27 10:44:12 -06:00
imSp4rky 8454f40929 fix(tunnel): block local networks instead of allowing public ones for --local-proxy
A VPN's synthetic DNS answer (fake-IP 198.18.0.0/15, 192.0.0.69) now works for a host name. An IP from the server, in any numeric form, must be public; dials to the client itself are closed.
2026-10-27 10:07:23 -06:00
imSp4rky 06f87dafa3 feat(drm): add blowfish stripe cipher and mp3 audio codec
BlowfishStripe decrypts on the client after download, so a --remote client gets clear audio.
2026-10-26 18:59:42 -06:00
imSp4rky ffeb58f808 feat(manifests): add dts-hd, mpeg-h and lcevc codecs and a manifest corpus
Fix DASH SegmentTimeline negative @r and Pattern, TTML sidecar sets with no contentType, HLS CHANNELS identifiers and Dolby channel masks; test against 408 public DASH/HLS/ISM manifests.
2026-10-26 10:30:43 -06:00
imSp4rky cb2ffdb55a fix(tunnel): accept fake-ip dns answers for --local-proxy host names
A TUN-mode VPN with fake-IP DNS answers names from 198.18.0.0/15 or 2001:2::/48, which the LAN guard refused, so every dial failed. Refused hosts now warn once.
2026-10-25 12:22:28 -06:00
imSp4rky cc33600cc7 feat(tracks): add muxing.original_label to mark original-language tracks
Adds the label to audio, subtitle and embedded audio names unless the name already says it, and escapes track lines in the --list tree.
2026-10-24 22:51:35 -06:00
imSp4rky 80bda08f36 feat(tracks): add muxing.track_names none to leave unnamed tracks unnamed
A track the service gives no name keeps none (--list shows [VTT] | en); SDH, CC, Forced and Descriptive labels still apply.
2026-10-24 21:24:31 -06:00
imSp4rky 34e8e37fdc fix(services): clear service-repo bytecode with git pathspecs before a pull
Delete untracked __pycache__ before each pull and drop the global dont_write_bytecode, so service bytecode is cached again
2026-10-24 15:57:08 -06:00
imSp4rky ecf17baffe feat(tracks): add native track names with muxing.track_names
Set muxing.track_names to native to name an unnamed track in its own language (中文(繁體), Português (Portugal)) in place of English. The same script and region rules apply. --list, the muxed names and the REST API track_name follow the option. A test fixture resets the muxing options, so a local unshackle.yaml cannot change test results.
2026-10-24 12:43:50 -06:00
imSp4rky 1175035317 feat(tracks): name unnamed tracks by language and tag subtitle scripts
Unnamed tracks get the English language name (default region left out); subtitle tags gain the script their region implies (zh-TW -> zh-Hant-TW). Refs #169
2026-10-24 10:59:21 -06:00
imSp4rky 83514d12fe fix(core): cut user-facing errors and warnings to one line 2026-10-23 20:23:05 -06:00
imSp4rky dfc99783b5 fix(downloader): report spent segment retries in one line without the URL
The session message names the host, not the signed URL, and a segment that fails every attempt prints one line with no traceback. API job errors come from the exception.
2026-10-23 19:47:12 -06:00
imSp4rky 9f054269db fix(vaults): copy no vault key from a clear track
kid_windows returns an empty map for an MP4 with no encrypted sample entry or protecting senc, so the key check judges, flags and copies nothing for it.
2026-10-23 16:59:40 -06:00
imSp4rky cc4bf19706 fix(vaults): stop false bad-key flags from a failed decode check
Judge a vault KID only on a file whose KID map holds it, tell remote vaults of a bad pair only once another key replaces it, and let the server CDM unflag a pair it returns; the server never flags a CDM-licensed pair. Log FFmpeg stderr on a failed check and name the missing CDM when none is set.
2026-10-23 15:31:26 -06:00
imSp4rky eeaf16cd83 fix(remote): keep each session cookie's domain, path and secure flag
The client set server cookies with no domain and sent all of them to every host, so a CDN refused segment requests with 400 header too large. rnet sessions now send cookies too.
2026-10-23 09:42:01 -06:00
imSp4rky af69e8aad4 feat(proxy): try bare --proxy providers in proxy_providers key order
Basic stays first and Control D last; the rest follow their config key order. Geofence and proxy_map lookups go through pick_proxy and skip a provider that fails.
2026-10-23 08:20:39 -06:00
imSp4rky 71f293161e fix(cfg): show only the duplicate-key warning, once 2026-10-22 20:43:40 -06:00
imSp4rky 9dd97bcd25 feat(config): warn with the lines of a duplicate key in any config load 2026-10-22 20:12:59 -06:00
imSp4rky f83a594c91 fix(cfg): give the lines of each duplicate config key instead of crashing 2026-10-22 19:45:46 -06:00
imSp4rky 1ec236f61b feat(proxy): accept an @ selector as a server_map value
A value starting with - or @ applies to its region (fr: -datacamp); a value with @ after a server is a whole query (fr: fr-bod@195.86.24.103). A selector in --proxy still wins.
2026-10-22 14:03:25 -06:00
imSp4rky 4753fcd7bc feat(proxy): select a vpn server by network or ip with @
On NordVPN, Windscribe and Surfshark, `@<name>` keeps and `@-<name>` skips a hosting network; `@<ip>` and `@-<ip>` pick or skip one server. The connect line names the server, IP and network. Surfshark pins an IP through a loopback TLS port.
2026-10-22 13:53:30 -06:00
imSp4rky b2dc70ff56 docs(dev): align self.config description with the merge in dl 2026-10-22 11:04:51 -06:00
imSp4rky 0eaefcaa2b fix(proxy): name the reason when the Control D forwarder answers 502 2026-10-21 18:35:26 -06:00
imSp4rky 5086dafff3 feat(api)!: add a server drain and never answer with a 5xx
POST/DELETE /api/dashboard/drain refuses new sessions and jobs (SERVER_DRAINING, 409) and warns open sessions. A CDN can replace a 5xx body, so server errors are now 422, retryable ones and the tunnel check 424, and a new middleware turns any 5xx into 422.

BREAKING CHANGE: INTERNAL_ERROR, DOWNLOAD_ERROR, WORKER_ERROR and the fallback return 422 instead of 500; NETWORK_ERROR and SERVICE_UNAVAILABLE return 424 instead of 503; /api/tunnel/check failures return 424 instead of 502.
2026-10-21 17:15:33 -06:00
imSp4rky 23614fd938 feat(remote): add --local-proxy to send server requests through the client
A reverse tunnel over the remote connection: the server's service traffic leaves through the client's own network. Only the client dials. Adds the tunnel-test command.
2026-10-21 17:09:37 -06:00
imSp4rky afaff8e070 feat(api): tag each error with a ref and count errors by service
Every structured error carries a short ref, appended to its message and logged with the request; /api/dashboard/status gains per-service error counts. Gzip now compresses in place.
2026-10-21 14:39:37 -06:00
imSp4rky 39ec591c48 fix(api)!: send service and DRM errors as 422, not 502
Cloudflare replaces an origin 502 body with its own page, so clients got "502: Bad gateway" in place of the error and resent each failed licence.

BREAKING CHANGE: SERVICE_ERROR and DRM_ERROR now return HTTP 422 instead of 502.
2026-10-21 11:43:33 -06:00
imSp4rky e5c339934c fix(remote): send the typed --proxy to the server when it resolved to loopback
dl and search keep the typed --proxy value, so --proxy controld:ca --remote sends the server the Control D resolver, not this machine's forwarder. The Control D log names the location and masks the resolver ID in place of 127.0.0.1.
2026-10-21 11:03:10 -06:00
imSp4rky 96d6a4f1b2 fix(api): split global speed limit across job workers 2026-10-20 20:03:03 -06:00
imSp4rky 639d51c41b feat(api): apply services.<TAG>.dl as defaults for API download jobs 2026-10-20 19:57:03 -06:00