Commit Graph
101 Commits
Author SHA1 Message Date
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 b2dc70ff56 docs(dev): align self.config description with the merge in dl 2026-10-22 11:04:51 -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 5b9120a7f1 fix(api): refuse peer cache files that name types other than datetime
The server and the client both check a forwarded cache file before they write it, because Cacher decodes it with jsonpickle. The session-create cache write now runs off the event loop.
2026-10-20 19:48:13 -06:00
imSp4rky ef75ea7d7a feat(dl): add --local to override a remote: true service config 2026-10-19 14:25:03 -06:00
imSp4rky 3aaf9c4107 fix(services): route a service remote from services.<TAG>.dl.remote
Click picks the subcommand before the dl callback applies the service config, so Services.resolve_command now applies remote and server first. A REST API job routes from its request only.
2026-10-19 14:19:07 -06:00
imSp4rky 1a8e633fdc feat(dash): flag dv profile 8 tracks from supplementalCodecs and use hdr10+dv as the hybrid 2026-10-18 17:18:11 -06:00
imSp4rky 2cc5e44957 feat(search): add --remote to search through a remote server
The client sends its credentials, cookies and cache, but none for an anonymous-search service. The API relay uses the same path.
2026-10-18 13:23:04 -06:00
imSp4rky d7c6907329 feat(tracks): probe dv tracks for hdr10+ and list them as DV+HDR10P
A DV track that carries HDR10+ keeps its DV range and gets Video.hdr10plus, sent in the REST track JSON and to remote clients.
2026-10-18 11:43:44 -06:00
imSp4rky 811e0a19c0 feat(tracks): probe HDR10 tracks for HDR10+ SEI before selection
Relabel HEVC HDR10 tracks whose first fragment carries ST 2094-40 SEI as HDR10P, for dl, the REST API and remote sessions. Config key hdr10plus_probe (default true).
2026-10-17 18:58:48 -06:00
imSp4rky 35871f3a52 feat(hybrid): generate dolby vision from hdr10+ with --generate-dv
Builds per-scene L1 in unshackle (PQ mean, letterbox-aware) with a generate_dv_mode config (v29/v40/legacy); a failed hybrid no longer exits 0 with no video.
2026-10-17 16:40:14 -06:00
imSp4rky 14bd2f2c7e feat(api): relay services from remote servers with pooled sessions and login prompts 2026-10-16 19:03:56 -06:00
imSp4rky bfda31ce4a fix(proxy): keep service traffic on --proxy and warn about requests that bypass it
--proxy now overrides HTTP(S)_PROXY and the Windows system proxy while keeping the env CA bundle. Core fallback sessions use the run's proxy, and a warn-only audit hook names service code that sends a request or opens a raw socket outside the proxy; a session with proxy_exempt = True opts out.
2026-10-16 16:12:42 -06:00
imSp4rky a4ce70a53c feat(tracks)!: match a language tag to the variant it means
A tag with a region (en-US, es-419) matches only that variant and reports a miss instead of taking another region. A bare tag takes the variant it means (pt -> pt-BR, es -> es-ES) and falls back to any variant only when that one is missing. `orig` prefers the title's own tag, `-sl orig` resolves, forced and SDH subtitles are picked from their own pools, and the track name no longer strips the region from the cached language.

BREAKING CHANGE: -l es-419 no longer selects es-ES, and language_priority, language_tags and muxing.default_language treat a regional tag as exact.
2026-10-15 12:26:39 -06:00
imSp4rky 8a1fbf2de1 feat(music): embed plain lyrics and save timed lyrics from Song.synced_lyrics 2026-10-14 12:37:43 -06:00
imSp4rky b107bca168 feat(music): save lyrics beside the audio and keep song fields over remote
Song.lyrics_suffix writes the lyrics file; song fields set in get_tracks now reach a remote client.
2026-10-14 11:04:29 -06:00
imSp4rky d41bb73d9e feat(remote): decrypt service-owned cbcs samples on the server
The client downloads the file and sends binary sample frames to a new samples route.
2026-10-14 11:03:14 -06:00
imSp4rky 5ffa9a4e2b feat(drm): add in-process cbcs decrypter with an external sample decrypter hook 2026-10-14 09:42:07 -06:00
imSp4rky 4fbaf2a61a feat(api): forward exact_lang to the service context
The remote-dl client sends exact_lang in dl_params, and REST download jobs set it in the service ctx, so a service can skip the manifests of close-match languages.
2026-10-13 15:07:01 -06:00
imSp4rky ecdfb667c9 feat(dl): add --sample and --include-sample
--sample downloads only a time window of a title (default 120-180 s) and cuts the mux to it. --include-sample cuts a 60 s sample from a finished file. Both write to a Sample folder with a SAMPLE tag on the filename
2026-10-11 14:53:50 -06:00
imSp4rky 0a7c76561c feat(search): add ANONYMOUS_SEARCH to skip the login for a service
A service that sets the flag gets no cookie load, no authenticate() call and no cookie save on a search, on the CLI and in the REST search handler. /api/services reports it as anonymous_search.
2026-10-10 13:21:14 -06:00
imSp4rky 09cae2ec3f feat(serve): relay approval messages to jobs and proxy remote downloads
A REST job shows a wait_for_approval message as its notice field. search, list-titles and list-tracks fail at once on a login that needs the user. A remote client downloads through the --proxy it sends.
2026-10-07 11:15:16 -06:00
imSp4rky 5b0369e63a feat(service): add wait_for_approval and return the cache for a login with no prompt
A pair code shown in a log line never answers a prompt, so the server read that login as anonymous and kept the session cache.
2026-10-07 09:03:18 -06:00
imSp4rky 3fd69e8039 feat(serve): add --cdm-only for a CDM backend with no REST API
Mounts only the pywidevine and pyplayready routes plus /api/health and the dashboard; no session store, service refresh or Swagger.
2026-10-06 18:24:21 -06:00
imSp4rky eea4b41b70 feat(serve): log CDM calls for the dashboard
Add GET /api/dashboard/cdm-logs: one record per pywidevine/pyplayready call plus open sessions per device, with no key or licence material.
2026-10-06 14:58:08 -06:00
imSp4rky 3477d09cc2 feat(dl): add --audio-description-only and --forced-subs-only
Each keeps one kind of track inside its track type. A run of more than one title skips a title that has no such track. The REST API rejects a non-boolean value for a boolean dl param, and the DASH parser reads audio description from Role elements.
2026-10-06 12:45:52 -06:00
imSp4rky 9fc25e53d5 fix(hybrid): read the container file for a base that had the DV fixup
The fixup replaces a track with a raw HEVC file, which has no duration and cannot be seeked, so Level 5 crop detection raised KeyError.
2026-10-05 17:32:30 -06:00
imSp4rky 1d2cb3a102 fix(dl): read the vaults first under --all-drm
A DRM system sends a challenge only for a KID with no content key. --cdm-only keeps one challenge per system for each set of KIDs.
2026-10-05 16:43:54 -06:00
imSp4rky ee38477b11 feat(dl): add --all-drm to license Widevine and PlayReady per track
Each DRM system sends one challenge per KID set in a run, also when a vault has the content keys. Needs a CDM for each system in the cdm config.
2026-10-05 15:22:01 -06:00
imSp4rky 9a1abd23b6 feat(remote): license with the client's device when the user picked one
A remote client that passes --cdm, has a cdm entry for the service that named the loaded device, or sets server_cdm: false now declines the server CDM at session create, and warns when the server keeps it. A service option listed in SERVER_DEVICE_OPTIONS keeps the server CDM.
2026-10-01 13:21:53 -06:00
imSp4rky c7ab04028a feat(setup): add unshackle setup command and cross-platform install scripts
setup downloads the external tools, writes a first config and imports CDM devices; install.sh and install.bat bootstrap uv and run it.
2026-10-01 12:21:24 -06:00
imSp4rky fdcc653b66 fix(api): keep the worker's error on failed jobs, gate tracebacks behind --debug-api
Failed jobs now keep the worker's traceback, error_details and error_code instead of the "Worker exited" wrapper. error_traceback and worker_stderr only reach API clients under --debug-api.
2026-09-29 15:53:10 -06:00
imSp4rky 37e2b59bce feat(dl): add --latest-episodes N to download the N newest episodes
Split episodes count once. Exposed as latest_episodes on the REST API. Closes #159.
2026-09-28 09:01:40 -06:00
imSp4rky 69360d1b4c feat(remote): let a remote client license with its own device identity
Relay the service's CDM calls to the client, accept the service's allowed identity config (for example ESN/Kpe/Kph), add the server_vault grant and a lent server-device mode that reads keys only from vaults and returns no login cache. Also fixes the proxied certificate fetch, Base64 Widevine licences, an answered call that stayed pending and a missing default quality.
2026-09-25 12:32:49 -06:00
imSp4rky 174192882f feat(serve): relay service prompts from download jobs to the REST client
A job's input_prompt carries a service's request_input() prompt; the client answers it with POST /api/download/jobs/{job_id}/input.
2026-09-25 09:32:35 -06:00
imSp4rky 0e4e6f2ec6 feat(remote): list only configured services on the dashboard
/api/dashboard/services and the /status count now use serve.services, else the union of serve.users services lists; ?all=1 lists every installed service.
2026-09-24 17:14:18 -06:00
imSp4rky 7d31153c7f feat(remote): cap server CDM licensing by height per API key and service
A session above the cap licenses with the client's own device, and a track above it in an uncapped -q run is handed back to the client. Also names the fallback in the ccextractor crash warning.
2026-09-24 16:50:26 -06:00
imSp4rky 91db1fa0b1 feat(remote): keep slow remote session requests alive with a heartbeat
Titles, tracks and licence stream a newline every 30s until the body is ready, so a slow service outlasts the client timeout and proxy idle limits; add a per-server timeout.
2026-09-24 10:18:03 -06:00
imSp4rkyandAntCardFr 783c8ae1c2 feat(proxies): add Control D proxy provider
Runs a loopback forwarder per region-named profile (unshackle-<region>), so
--proxy and --proxy-download can exit in different countries

Thanks to Orni_ for the original code and the test account.

Co-authored-by: AntCardFr <24798811+AntCardFR@users.noreply.github.com>
2026-09-23 13:23:50 -06:00
imSp4rky db771a13c6 fix(remote): forward dl track selection and profile to remote sessions
Remote sessions now carry -l/-vl/-al/-a/-fs under a nested dl_params, so services fetch the requested audio versions. Server-account tokens for non-default accounts move from default to the account name, so each account logs in once after upgrade.
2026-09-22 12:52:05 -06:00
imSp4rky 4639d9d496 fix(remote): let the server's CDM mapping decide the DRM system under server_cdm
A client with a local PlayReady device asked the server for a PlayReady licence on a service the server maps to a Widevine device. Both server_cdm routes now share one candidate list from one config lookup, report the system that licensed in drm_type, and the client adopts it.
2026-09-22 10:54:31 -06:00
imSp4rky cd6a38aec8 fix(remote): stop warning about missing keys for tracks that carry no DRM
The server names the clear tracks in the licence response and the client skips them instead of warning for every requested track without keys.
2026-09-19 22:05:30 -06:00
imSp4rky 9c9e059e2d fix(remote): forward nested service cache files to and from the server
Cache keys are now the path relative to the service cache dir without .json, so Cacher keys like session_web/<sha1> reach the remote session. The credential filter runs on every path segment, the suffix is appended rather than substituted, and both sides cap the map at 64 keys.
2026-09-19 21:42:01 -06:00
imSp4rky cf2906f120 fix(cli): make the click param types the one source of codec spellings
--acodec now lists its codecs in --help, --vcodec drops the duplicate entries, and the REST API derives its allowlists from the same types, so AC-4, DDP, VORB and sub_format "original" stop being rejected and H264 stops being silently dropped. Adds shell completion for --acodec and repairs MultipleChoice completion. Raises the click floor to 8.2.
2026-09-17 19:22:19 -06:00
imSp4rky ffda836442 fix(remote): return session cache for device-code and cache-only logins
Answered login prompts and uploaded cache now count as client auth; the client closes on exit and keeps the remote session alive during long downloads.
2026-09-16 19:36:31 -06:00
imSp4rky aec45e30cc feat(service): add GEOBLOCK negative geofence
Regions in GEOBLOCK refuse the service and everything else is allowed. A hit stops the run with a region error instead of auto-proxying; the check also covers proxy exits and the remote-dl client region.
2026-09-16 15:06:43 -06:00
imSp4rky aa36d4c225 feat(vaults): report bad keys to the vault that served them 2026-09-13 20:46:38 -06:00