Commit Graph
797 Commits
Author SHA1 Message Date
imSp4rky 1af77d395d fix(downloaders): submit segments in a window so progress can drain
Submitting every segment up front convoyed on ThreadPoolExecutor's process-global lock, starving the event drain so per-track progress bars only advanced once the download had finished.
2026-08-16 11:06:17 -06:00
imSp4rky 21d5f1c5e1 refactor(core)!: drop leading underscores from internal definitions
Renames 314 defs and 41 module/class-level constants. Keeps 11 names underscored where the stripped form collides in scope, plus 5.5.0 shims for the three symbols external service repos call.
2026-08-15 22:07:41 -06:00
imSp4rky db4f0b39f9 refactor(console): route interactive prompts through a themed helper
Adds prompt_user() and uses it for local, remote, and Proton VPN input. Replaces click.prompt on the remote auth path, which ignored the theme and overlapped active Live displays. Remote auth now exits on EOF instead of POSTing an empty answer and spinning the poll loop.
2026-08-15 18:13:05 -06:00
imSp4rky a6cb0231d5 chore: bump dev version to 5.5.0 2026-08-15 16:00:14 -06:00
imSp4rky 0576d9d03c chore(release): 5.4.0 5.4.0 2026-08-15 15:54:07 -06:00
imSp4rky 9a2f7a6661 fix(kv): search remote vaults that cannot list their tables
Probe locally installed service tags in parallel when a vault has no table listing, and report every vault holding the KID instead of the first hit.
2026-08-15 15:09:42 -06:00
imSp4rky e1fbd11678 fix(dash): resolve representations by adaptation set, not id alone
Representation ids are only unique within an AdaptationSet, so re-finding a track by id could download a sibling set's stream (audio description in place of dialog). Applies to download_track and extract_dash.
2026-08-15 14:26:45 -06:00
imSp4rky 415a195957 test(serve): strip ANSI from CLI output before asserting error message 2026-08-13 16:33:08 -06:00
imSp4rky db9ec3e334 feat(cli): add named color themes and rich-formatted help
Render all click help through rich-click, themed by a new `theme` config key (9 palettes + aliases, previewable via `unshackle env theme`), and show service docstrings in local and remote `dl <TAG> -h`.
2026-08-13 16:25:14 -06:00
imSp4rky a248ae79bd feat(serve): gate server CDM licensing behind a per-key server_cdm opt-in
Keys configured under serve.users default to off, so they license with their own local CDM; session licensing and download jobs both refuse otherwise.
2026-08-13 11:40:30 -06:00
imSp4rky ccb4a69302 fix(services): re-raise ClickException for better error handling in remote services cache 2026-08-13 09:23:23 -06:00
imSp4rky 5796729bf3 feat(remote): accept serve.users keys in api-only mode and add client auth-header fallback
api-only/remote-only serve now authenticates every serve.users key (str-coerced), not just api_secret, so per-user service allowlists apply. RemoteClient tries X-Secret-Key then X-Api-Key on 401 (sticky winner); remote_services.auth_headers prepends extra header names to the defaults.
2026-08-12 17:58:55 -06:00
imSp4rky 274b2fc308 fix(subtitle): keep cue-less webvtt instead of failing the download
A rendition with headers but no cues raised CaptionReadNoCaptions when preserve_formatting is false, aborting the whole download.
2026-08-12 11:42:15 -06:00
imSp4rky 16ae73e3a0 feat(api): stream download job progress over server-sent events
Adds GET /api/download/jobs/{job_id}/events with snapshot, status, progress and terminal events, query-param auth for EventSource in both serve modes, atomic progress-file writes, and stream-safe CORS and compression middleware.
2026-08-12 10:35:43 -06:00
imSp4rky 581979c5a8 fix(dl): reset per-title language and range selection each iteration 2026-08-12 07:23:59 -06:00
imSp4rky c2f3577540 chore(changelog): update changelog 2026-08-11 21:46:54 -06:00
imSp4rky b5e1c3e6a7 fix(hls): take the key id from EXT-X-KEY when the PSSH carries none 2026-08-11 21:24:05 -06:00
imSp4rky 356d6fb984 fix(dl): treat audio muxed into the video as an available language
A muxed stream carries its audio in the video track, so -l orig no longer
fails when the only separate audio tracks are dubs.
2026-08-11 21:24:04 -06:00
imSp4rky 9016b526af chore(env): drop ML-Worker from the dependency check 2026-08-11 18:36:03 -06:00
imSp4rky ec594b0b9c fix(api): carry air_date, absolute, anime and daily across the title wire
serialize_title and title_to_meta now emit them as conditional keys,
_build_title restores them, and service-class flags stamp per title.
2026-08-11 17:50:38 -06:00
imSp4rky 4a21dbebb5 feat(dl): add daily date-based episodes with tvdb air-date fill
--daily flag plus Service.DAILY/Title.daily, -w selection by ISO air
date or colon date range, and a pre-1970 air-date guard.
2026-08-11 17:50:22 -06:00
imSp4rky e4f6ddec85 feat(dl): add absolute episode numbers filled from tvdb absolute order
Episode gains an additive absolute field services can set, an {absolute}
naming token (3-wide), and an --enrich fill from TVDB's absolute order
that never rewrites season or episode numbers.
2026-08-11 16:42:07 -06:00
imSp4rky 72581ba5d2 feat(metadata)!: replace animeapi with a first-class anilist provider
--anilist supersedes --animeapi (REST: anilist_id); the keyless AniList
GraphQL provider joins the registry with title search, mal: ID lookup,
an ANILIST mkv tag, and the anilist_title_language config option.
Services mark anime via Service.ANIME / Title.anime for anilist-first
metadata resolution with fall-through.
2026-08-11 16:42:05 -06:00
imSp4rky ebb4e74318 feat(metadata)!: authoritative id resolver and keyless imdb provider
Supplied IDs resolve directly via a shared resolve_by_ids and never fall back to title search; metadata_providers gains per-kind ordering and a disable_metadata switch stops all automatic lookups while explicit IDs keep working.
BREAKING: --tmdb/--imdb/--tvdb are now mutually exclusive and require a usable provider; --enrich also overwrites original language; the imdbapi provider and imdb_api_enabled are replaced by a keyless imdb provider.
2026-08-11 15:07:24 -06:00
imSp4rky 0cec6c9686 docs(api): note the - language exclusion prefix in the OpenAPI spec 2026-08-10 12:51:20 -06:00
imSp4rky d6f3958a16 fix(dl): warn when --enrich source is missing title, year, or language 2026-08-10 12:33:23 -06:00
imSp4rky 79ad70a9cf feat(dl): exclude languages with a - prefix on -l, -vl, -al, -sl and -fsl 2026-08-10 12:18:30 -06:00
imSp4rky 8a7022a091 feat(dl): allow --tvdb as an --enrich metadata source 2026-08-09 11:55:06 -06:00
imSp4rky 8d3785b460 feat(enrich): fill in the original language from metadata providers
--enrich now sets Title.language when the service left it unset, so video tracks stop falling back to und. Adds original_language to MetadataResult (TMDB, TVDB, OMDb, IMDxAPI) and falls back to OMDb for --imdb, which previously did nothing while imdb_api_enabled defaults to false.
2026-08-08 13:52:55 -06:00
imSp4rky 97fa834b1e chore(changelog): update entries for new features and bug fixes 2026-08-07 12:15:51 -06:00
imSp4rky d7e08e979b fix(downloader): surface failed downloads instead of returning silently 2026-08-07 11:31:11 -06:00
imSp4rky d448ee8ff9 fix(downloader): decode content-encoded bodies instead of writing raw
Reading .raw skips urllib3's decoding, so brotli-served subtitles landed compressed and converted to empty files. Also drops a partial rather than Range-resuming an encoded body, since a Range indexes the encoded bytes.
2026-08-05 17:56:33 -06:00
imSp4rky 02fd7b9387 fix(subtitles): strip X-TIMESTAMP-MAP so WebVTT cues are not offset on conversion 2026-08-05 11:07:38 -06:00
imSp4rky 041ba5293b feat(titles): add optional Episode.part, selected with -w s1e1.2
Opt-in and additive: an episode without a part behaves exactly as before.
2026-08-04 17:38:30 -06:00
imSp4rky 10bfaf6a73 merge dev (tag_rules) into split-config-docs
# Conflicts:
#	docs/guide/output-and-naming.md
#	docs/reference/configuration.md
2026-08-04 10:25:47 -06:00
imSp4rky c4b25756eb docs: split configuration reference into per-area pages 2026-08-04 10:25:32 -06:00
imSp4rky 3e0d7b5f75 feat(dl): add tag_rules to conditionally swap the group tag 2026-08-04 09:42:42 -06:00
imSp4rky 051f1e668f style(vaults): fix formatting from #147 2026-08-04 08:22:02 -06:00
hifumi eb40c67385 feat(vaults): support custom headers on API vault 2026-08-04 08:20:24 -06:00
imSp4rky a5f5e7d14d refactor(tracks): honour the best token and share one match rule
sort_subtitles resolved only the all token, while the video and audio sorts
resolved all and best. by_language now asks matching_languages rather than
repeating the RFC 4647 preference, with no behaviour change.
2026-08-03 10:29:09 -06:00
imSp4rky a6997f6bca feat(tracks): add language_priority to sort preferred languages first
subtitle.language_priority and audio.language_priority prepend to the CLI
languages, so the named languages sort first and nothing is filtered.
--exact-lang now applies to the sorts too, through matching_languages, which
follows the same RFC 4647 rule as Tracks.by_language and ignores invalid tags.
2026-08-03 10:15:05 -06:00
imSp4rky 4e1ccf3230 feat(dl): add -fsl/--forced-s-lang to filter forced subtitles by language 2026-08-03 09:27:40 -06:00
imSp4rky b580ccdd42 fix(tools): pass -nostdin to all ffmpeg calls
When ffmpeg runs with the terminal on stdin it turns off echo for its
interactive keys. If several run at once, or one gets killed, echo never
comes back and the terminal is left broken after dl exits.
2026-08-02 13:44:21 -06:00
imSp4rky 330e274da6 feat(temp): give each download task its own temp directory
Each dl run works in temp/task_<id>/, removed on every exit path. Orphans from hard-killed processes are swept via lock liveness, and env clear temp skips directories whose task is still running.
2026-08-02 13:28:23 -06:00
imSp4rky b8824b819d merge: subtitle.group_by track option 2026-08-02 10:50:20 -06:00
imSp4rky 1a0beebf70 merge: TheTVDB v4 metadata provider 2026-08-02 10:50:19 -06:00
imSp4rky 786309ea5c docs: cover the TVDB provider, episode ordering and provider order
Document tvdb_api_key, tvdb_pin, tvdb_order and metadata_providers, the
--tvdb and --tvdb-order flags with their behaviour when an order does
not cover a whole series, the new REST API parameters, and the Matroska
TVDB2 tag prefixes.
2026-08-02 10:48:39 -06:00
imSp4rky 4ac34069ec feat(providers): add TheTVDB v4 as a metadata provider
TVDB covers TV far better than the existing sources, so add it as a
provider and let users decide where it sits in the lookup chain.

- new TVDB v4 provider: search, get_by_id, get_external_ids and
  find_by_imdb_id, with a process-level token cache and 401 re-auth
- metadata_providers config both orders and filters the providers used,
  so TVDB can be primary rather than a TMDB fallback. Cross-validation
  keeps its own fixed trust ranking, unchanged by search order
- --tvdb-order renumbers episodes into a TVDB season order. A service
  does not always use aired order, so the source order is detected
  rather than assumed, and the renumber is refused when an order that
  omits episodes would give two of them the same filename
- --tvdb sets the series ID directly, skipping the lookup
- the Matroska TVDB2 tag now populates on every lookup path, including
  --imdb, which previously produced no ID tags when IMDxAPI was off

Search matches on year as well as title so an identically named remake
cannot win on title alone.
2026-08-02 10:48:32 -06:00
imSp4rky 8baf064750 feat(tracks): add subtitle.group_by to keep a language with its variants
sort_subtitles applied the language sort before the type sort. Python sorts
are stable, so the last pass wins and type became the major key: every forced
track, then every normal, then every SDH, each block ordered by language. In a
title with many languages this put a track far from its own SDH version, for
example Finnish at track 5 and Finnish SDH at track 42.

Add a group_by parameter that selects the major key. "type" is the default and
keeps the current order byte for byte. "language" swaps the two passes so each
language stays next to its own variants. Read it from the new subtitle.group_by
config key.

Also correct the docs: type_priority was described as sorting the variants
within each language, which was never true. It ranks the types across all
languages.
2026-08-02 10:45:28 -06:00
imSp4rky bf85c948b4 fix(dl): honour --no-proxy-download for attachments 2026-07-31 13:22:18 -06:00