Commit Graph
1065 Commits
Author SHA1 Message Date
imSp4rky 83eef01fad chore(release): bump version to 6.0.0 6.0.0 2026-10-13 16:32:19 -06:00
imSp4rky e7bb825def perf(manifests): decode manifests without charset detection
Parse an MPD from bytes and read every M3U8 playlist as UTF-8 unless the server sent a charset. Fixes mojibake on text/* responses.
2026-10-13 16:11:13 -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 3e64a7d684 fix(api): follow the cdm config key order for the server CDM 2026-10-13 13:40:38 -06:00
imSp4rky 2ba442f50e feat(dl): load the DRM system a cdm entry lists first
The first of the widevine / playready config keys in a cdm entry sets which device loads first and which DRM system licenses a track that offers the two. An entry that lists playready first changes from Widevine to PlayReady.
2026-10-13 12:44:11 -06:00
imSp4rky af4e6d5d47 fix(hls): read the key id from the init segment when the PSSH has none
An EXT-X-KEY whose Widevine PSSH holds a content id and no key id raised KIDNotFound. Covers download, licence-only, --all-drm, session keys, import and the server CDM path. Fixes #166.
2026-10-13 12:14:34 -06:00
imSp4rky b4136e1cf5 perf(sample): download only the subtitle segments around the window
A segmented subtitle track took every segment in a --sample run. It now takes the window plus one segment on each side.
2026-10-11 19:14:14 -06:00
imSp4rky 4c2e74de80 test(sample): skip the kid probe in the single-file dash test 2026-10-11 18:30:49 -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 0cded6427f fix(cdm): simplify cached keys retrieval in CustomRemoteCDM 2026-10-10 00:58:08 -06:00
imSp4rky 355df2e54f fix(import): carry the HLS segment filter in an export
An import kept the segments a service drops and failed on their key. A licence-only run now also licenses a key that starts part-way.
2026-10-08 10:38:49 -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 f86359de5d feat(serve): reload unshackle.yaml on SIGHUP without a restart
Extract the serve validation and app config builder so startup and reload share them. A bad file or a restart-only change keeps the running config; open CDM sessions survive.
2026-10-06 17:56:47 -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 94e5264396 fix(cdm): send a PlayReady licence without an XML declaration as XML
A remote CDM tried base64 first on any licence not starting with "<?xml", which can decode XML text into garbage. Also lists L3 as a device_name.
2026-10-06 13:59:40 -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 b530d96e9f fix(docs): hide the release version in the header repo widget 2026-10-04 21:52:38 -06:00
imSp4rky 9bc6f5fb58 fix(dl): keep the --enrich title and year after get_tracks
A service that sets its title again in get_tracks, as a remote session does, replaced the metadata name and year, so the file took the service's title. A song takes only the language.
2026-10-04 15:57:51 -06:00
imSp4rky 07e6a75165 fix(attachment): keep custom fonts after mux cleanup
Attachment.delete() now removes a file only when it is in the temp directory, so fonts attached from the custom fonts directory survive.
2026-10-04 12:18:02 -06:00
imSp4rky 825678a1c4 fix(dl): keep the --enrich original language after get_tracks
A service that sets title.language in get_tracks replaced the metadata language, so 'orig' picked the wrong audio. Video tags and original flags move to the enrich language with the title.
2026-10-02 20:06:56 -06:00
imSp4rky 73bdb98d3e fix(console): write UTF-8 to redirected streams on Windows 2026-10-02 14:07:05 -06:00
imSp4rky 34eb94b55d fix(sanitize): normalise filenames to NFC and keep combining marks
Remove only control characters in unicode mode. A mark after a zero width joiner or a digit was still dropped (#161). In ASCII mode a decomposed title now transliterates like the composed one.

Names change for titles with combining marks, compatibility ideographs or decomposed spellings, so an existing library can get a second folder.
2026-10-02 13:22:04 -06:00
Chaloemchai 7b3794333f fix(sanitize): keep nonspacing marks on letters in unicode filenames (#162) 2026-10-02 11:56:56 -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 af17bad010 chore: mark install.sh executable 2026-10-01 12:22:49 -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 c81c99fd96 fix(api): stop dashboard event and log reads racing worker threads
Readers filter a deque copy, publish takes a re-entrant lock, seq moves after the append, and poll endpoints return a cursor that never skips a record.
2026-09-28 08:28:02 -06:00
imSp4rkyandCodeName393 4bb3d2a414 Merge last minute changes from dev
Co-authored-by: CodeName393 <62503817+CodeName393@users.noreply.github.com>
2026-09-26 11:01:12 -06:00
sp4rk.y 1cb375c380 Merge pull request #160 from CodeName393/custom-api
feat(cdm): API Improvements
2026-09-26 10:50:32 -06:00
CodeName393 1679cae735 feat(cdm): API Improvements
- license_type and privacy_mode are requested together with the request to the server instead of being discarded
- Use the permissions value of key_obj itself
2026-09-27 01:45:37 +09:00
imSp4rky 4f188b866f fix(cdm): skip the server header probe for pywidevine and pyplayready remote CDMs
A reverse proxy or CDN rewrites the Server header, so upstream refused a working serve API.
2026-09-25 22:54:08 -06:00
imSp4rky 2ff02f2afd fix(proxies): link to the expressvpn device login with the code prefilled
The bare verification_uri renders a blank page; verification_uri_complete opens the sign-in form.
2026-09-25 19:29:59 -06:00
imSp4rky 746bf184d2 refactor(proxies): share proxy dispatch between dl, search and resolve_proxy
A bare query skips a failing provider and errors when none answers; an unknown prefix such as us:seattle fails with a hint. The REST path now loads WindscribeVPN.
2026-09-25 18:14:26 -06:00
imSp4rky 80c0dc4ebf fix(proxies): return None for unservable queries and repair live providers
Basic, NordVPN, Windscribe, Gluetun and Hola no longer raise on a query they cannot serve. Hola parses stdout only and reports a ban; NordVPN cities use the API filter; uk maps to gb.
2026-09-25 18:13:31 -06:00
imSp4rky 40281660f1 fix(proxies): skip a proxy provider that fails to load
A bare --proxy query moves past it; naming it (--proxy nordvpn:us) fails with the load error. dl, search and the REST path share one loader.
2026-09-25 17:28:29 -06:00
imSp4rky 34c04e0587 fix(proxies): match surfshark's current server api
Server names replace numeric server IDs; unknown queries return None so the next proxy provider can answer.
2026-09-25 17:27:36 -06:00
imSp4rky 5838f2aed6 fix(tracks): keep the Dolby Vision record when remuxing video with ffmpeg
The MP4 muxer drops dvcC/dvvC unless -strict unofficial is set, so a repacked DV track muxed as plain HEVC and lost its DV tag
2026-09-25 16:55:51 -06:00
imSp4rky c071a00ba6 fix(remote): report a missing title list and a refused track URI clearly
A service returning no titles now fails with a service error instead of an unsupported "other" title, and the init segment read names the HTTP status.
2026-09-25 14:37:18 -06:00
imSp4rky 1883386539 test(serve): remove reader-thread races in prompt relay tests 2026-09-25 13:18:13 -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