imSp4rky
9f4625d971
fix(proxy): do not warn about requests to a configured remote CDM
2026-10-16 17:58:38 -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
dc169f81e1
fix(vaults): stop querying sibling KIDs and skip unavailable vaults
...
The server CDM stub names only the manifest's KIDs; sibling keys stay content keys. API and HTTP vaults retry a 429, and a vault that is down or still rate limited costs one timeout per run.
2026-10-16 14:49:37 -06:00
imSp4rky
ecb8296de8
fix(import): add decrypts_samples to ImportService
2026-10-16 09:12:02 -06:00
imSp4rky
71a0383258
fix(console): count spacing combining marks as one cell
...
Rich measures Indic marks like ि as zero width, so the --list panel border drifted on Hindi, Telugu and Tamil labels.
2026-10-15 17:36:04 -06:00
imSp4rky
dedbf00f75
test(vaults): replace sleeps with events in the parallel retry test
2026-10-15 16:28:33 -06:00
imSp4rky
89f433963a
fix(session): log "Retrying" only when a retry follows
...
A per-call max_retries=0 logged "Retrying... (1/0)" before raising, and the last of the default retries logged "(6/5)".
2026-10-15 14:48:20 -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
c231114cda
feat(ip-info): return timezone and add a required-field filter
...
get_ip_info(require=...) skips a geolocation API whose result lacks a required field, so ipinfo Lite falls through to ipinfo.io or ip-api.in.
2026-10-15 10:30:21 -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
9ef7a8bd06
fix(session): cap Retry-After on the requests retry policies
...
A server-sent Retry-After could park a run for up to six hours.
2026-10-13 19:59:14 -06:00
imSp4rky
5ff2bef550
fix(cacher): resolve cache expiry by unix time
2026-10-13 19:58:50 -06:00
imSp4rky
6b04d7b137
fix(vaults): lengthen the whole-file key check and steady its HEVC test
...
Wrong-key HEVC noise can decode clean for seconds in small frames, so the tail check now decodes 8 s. The test clips are 640x360 with a fixed IV.
2026-10-13 17:32:29 -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
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
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
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
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
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
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
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
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
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
c06b00ec63
fix(import): read an HLS export that names no title language or master key
...
Probe each media playlist for its KIDs and refuse a manifest unshackle cannot read.
2026-09-23 16:20:49 -06:00
imSp4rky
1af7d86b88
test(import): assert on the ClickException, not the wrapped error panel
...
A long tmp path on macOS and Windows runners made rich-click split the message across lines.
2026-09-23 16:07:33 -06:00
imSp4rky
bc50167791
fix(import): give no title keys to a track that is clear
...
A subtitle, or a track the export lists no KID for while it lists others, gets no DRM.
2026-09-23 15:52:57 -06:00
imSp4rky
28ddd08917
fix(import): say an import uses the export's keys, not a server CDM
...
The CDM type stub now follows the exported DRM system.
2026-09-23 15:48:50 -06:00
imSp4rky
d014c69d00
feat(export): separate export file name parts with dots
...
Titles, scope and quality parts use dots and never follow output_template.
2026-09-23 15:26:46 -06:00
imSp4rky
a19c3e3879
fix(export): name the file from the first write
2026-09-23 15:11:15 -06:00
imSp4rky
ce42cd245b
feat(export): name export files after their titles and tracks
...
Log what each title and the run exported.
2026-09-23 15:11:14 -06:00
imSp4rky
80088fe4f6
feat(import): build tracks from direct-file export rows
...
Imports unidl json_manifest exports made of whole files.
2026-09-23 15:04:22 -06:00
imSp4rky
06866eb12e
feat(export): record each track's KIDs
...
An import reads them first, so a track gets its own keys without a probe.
2026-09-23 14:35:58 -06:00
imSp4rky
84bb07f589
fix(import): stop clearly when no export or vault key exists
...
The bad-key retry now requests each dropped KID.
2026-09-23 14:33:34 -06:00
imSp4rky
fc26297ff0
fix(import): give each track only the keys it declares
...
The whole title pool stays the fallback for a track that declares no KID.
2026-09-23 14:30:17 -06:00
imSp4rky
47f30668ee
fix(drm): give the zero-KID fallback only the track's own key
...
mp4decrypt and shaka use the last key for a repeated KID.
2026-09-23 14:27:30 -06:00