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.
This commit is contained in:
imSp4rky
2026-08-11 17:50:22 -06:00
parent e4f6ddec85
commit 4a21dbebb5
16 changed files with 425 additions and 8 deletions
+2 -1
View File
@@ -112,7 +112,7 @@ The special language tokens `orig`, `all`, and `best` are honoured everywhere a
| Flag | Description |
|---|---|
| `-w`, `--wanted` | Wanted episodes, e.g. `S01-S05,S07`, `S01E01-S02E03`. Supports exclusions with a leading `-` (e.g. `-S03`). For a [split episode](downloading.md#split-episodes), `.N` picks one part (`S01E01.2`), a range must stay inside the episode (`S01E01.1-S01E01.3`), and `S01E01` on its own takes every part. |
| `-w`, `--wanted` | Wanted episodes, e.g. `S01-S05,S07`, `S01E01-S02E03`. Supports exclusions with a leading `-` (e.g. `-S03`). For a [split episode](downloading.md#split-episodes), `.N` picks one part (`S01E01.2`), a range must stay inside the episode (`S01E01.1-S01E01.3`), and `S01E01` on its own takes every part. For [dated content](downloading.md#daily-and-date-based-content), a token can also be an ISO air date (`2026-08-11`) or a date range with a colon (`2026-08-01:2026-08-31`). |
| `--select-titles` | Interactively select what to download: episodes of a series, or films when a title has more than one. **Cannot combine with `-w`.** |
| `--latest-episode` | Download only the single most recent episode. |
| `--list-titles` | List titles only; do not download. |
@@ -155,6 +155,7 @@ Keep only certain track types, or skip certain track types. Attachments are alwa
| `--tvdb` | TVDB ID (integer). Used for the tags. Skips the series lookup that `--tvdb-order` would otherwise do. `--enrich` reads it too. Needs `tvdb_api_key`. |
| `--anilist` | AniList ID (integer), e.g. `--anilist 21`. A MyAnimeList ID is accepted as `mal:12345` and resolved to the AniList entry. Used for the tags. Skips the title search. `--enrich` reads it too. Needs no key. |
| `--enrich` | Overwrite show title, year and original language with the external source's. **Requires** one of `--tmdb`, `--imdb`, `--tvdb`, or `--anilist`. |
| `--daily` | Treat the title as daily/date-based content and fill missing episode air dates from TVDB. The fill needs `--enrich` and a TVDB ID. See [Daily and date-based content](downloading.md#daily-and-date-based-content). |
| `--tvdb-order` | Renumber episodes to a TVDB season order: `official` (aired), `dvd`, `absolute`, `alternate`, or `regional`. Needs `tvdb_api_key`. |
!!! note "One ID at a time"
+42 -1
View File
@@ -427,6 +427,43 @@ with `-` to exclude it.
unshackle dl -w S01,-S01E01.2 EXAMPLE 81234567
```
=== "Air dates"
```shell
# One day
unshackle dl -w 2026-08-11 EXAMPLE 81234567
# A range of days, colon separated
unshackle dl -w 2026-08-01:2026-08-31 EXAMPLE 81234567
# August, but not the 15th
unshackle dl -w 2026-08-01:2026-08-31,-2026-08-15 EXAMPLE 81234567
```
### Daily and date-based content
Talk shows, news and sports have no official episode numbering, so unshackle names them
by air date. An episode that carries an air date is written as `Show.YYYY.MM.DD` instead of
`SxxExx`, the `{date}` token holds the ISO date, and the season folder becomes the year.
A service that only carries this kind of content sets `DAILY = True` on its class, and a
service can set `air_date` on each episode itself. Add `--daily` to mark any other title
as date-based:
```shell
unshackle dl --daily --tvdb 73871 --enrich EXAMPLE 81234567
```
With `--enrich` and a TVDB ID, `--daily` fills in the air date of every episode that has
none. An air date the service already set is kept. Dates before 1970 and dates in the
future are skipped, because TVDB carries placeholder schedule dates for episodes that
have not aired. Without `--enrich` unshackle has no source to fill from, and says so.
A dated episode answers to its air date in `-w`, as well as to its `SxxExx` key. A date
token is a plain ISO date (`2026-08-11`). A date range uses a colon (`2026-08-01:2026-08-31`),
because the dashes in a date are part of the date. A range cannot span more than 1000 days.
Date tokens and `SxxExx` tokens can be mixed in one `-w`.
### Split episodes
A few services split one episode into several separately playable videos. Where a service
@@ -704,6 +741,9 @@ usual beneficiary, but no part of this is limited to anime. This only adds the
[`{absolute}`](../reference/configuration/output.md#output_template) naming variable. The
season and episode numbers are never changed.
With `--daily`, `--enrich` also fills in the air date of each episode from TVDB. See
[Daily and date-based content](#daily-and-date-based-content).
!!! warning "`--enrich` replaces the original language, which affects more than the filename"
Track selection reads the original language, so replacing it changes which audio is
treated as the original. That is the point when a service mislabels it, but it means a
@@ -762,7 +802,8 @@ authoritative list.
| `--forced-subs` | `-fs` | Include forced subtitles. |
| `--forced-s-lang` | `-fsl` | Forced subtitle language(s); implies `-fs`. `-` excludes. |
| `--sub-format` | | Output subtitle format. |
| `--wanted` | `-w` | Episode/season range. |
| `--wanted` | `-w` | Episode/season range, or an air date. |
| `--daily` | | Fill missing air dates from TVDB during `--enrich`. |
| `--select-titles` | | Interactively pick episodes or films. |
| `--latest-episode` | | Only the newest episode. |
| `--video-only` / `--audio-only` / `--subs-only` | `-V` / `-A` / `-S` | Restrict track types. |