feat: enrich AniList episode metadata rows

This commit is contained in:
2026-10-25 17:01:14 +01:00
parent e328ff3883
commit a5aea5adcf
2 changed files with 21 additions and 1 deletions
+2
View File
@@ -86,6 +86,8 @@ Choose **AniList** or use `--anilist`. Search/detail metadata comes directly fro
Rows, metadata and selection prompts label availability UNVERIFIED. Terebi resolves the current selection fresh; unavailable episodes, malformed/protected pages and network failures appear as distinct player errors, while launch/catalog errors remain visible in Tubular. A successful handoff does not mark an episode watched. Rows, metadata and selection prompts label availability UNVERIFIED. Terebi resolves the current selection fresh; unavailable episodes, malformed/protected pages and network failures appear as distinct player errors, while launch/catalog errors remain visible in Tubular. A successful handoff does not mark an episode watched.
AniList episode metadata rows lead with the available series-average runtime (`25 min avg`), format and series year, followed by `sub · UNVERIFIED` and collection/watch markers. Missing or zero average runtimes are omitted. These are explicitly series-level facts, not measured episode durations or individual air dates; legacy Miruro retains its returned episode-specific dates and durations.
Identities are `anilist:<positive decimal AniList ID>:<positive episode>`, with both numbers bounded by Int32. The stable handoff is `https://zokoanime.video/stream/ani/ID/EPISODE/sub` (`ani`, not the broken `anilist` route). Sources, tokens and subtitle URLs are never stored in collections or playback snapshots. Queues use the same stable URL and per-item private progress files; version-2 reports identify `provider = "anilist"`, decimal-string `media_id`, and numeric `episode`. Identities are `anilist:<positive decimal AniList ID>:<positive episode>`, with both numbers bounded by Int32. The stable handoff is `https://zokoanime.video/stream/ani/ID/EPISODE/sub` (`ani`, not the broken `anilist` route). Sources, tokens and subtitle URLs are never stored in collections or playback snapshots. Queues use the same stable URL and per-item private progress files; version-2 reports identify `provider = "anilist"`, decimal-string `media_id`, and numeric `episode`.
`anilist-library.toml` stores AniList shows/tags separately from the untouched `miruro-library.toml`. Shared episode collection/state files use exact provider-qualified keys and filter each catalog independently; `miruro:1:1` is not `anilist:1:1`. No opaque Miruro IDs, saved show metadata or old playback sessions are mapped or reinterpreted. `anilist-library.toml` stores AniList shows/tags separately from the untouched `miruro-library.toml`. Shared episode collection/state files use exact provider-qualified keys and filter each catalog independently; `miruro:1:1` is not `anilist:1:1`. No opaque Miruro IDs, saved show metadata or old playback sessions are mapped or reinterpreted.
+19 -1
View File
@@ -281,7 +281,25 @@ impl Screen {
details.push(format!("{}:{:02}", seconds / 60, seconds % 60)); details.push(format!("{}:{:02}", seconds / 60, seconds % 60));
} }
if self.provider == Provider::AniList { if self.provider == Provider::AniList {
details.push("UNVERIFIED · sub".into()); if let Some(minutes) = media
.metadata
.get("episode_duration_minutes")
.and_then(Value::as_u64)
.filter(|minutes| *minutes > 0)
{
details.push(format!("{minutes} min avg"));
}
if let Some(format) =
media.metadata.get("format").and_then(Value::as_str)
{
details.push(safe(format));
}
if let Some(year) =
media.metadata.get("season_year").and_then(Value::as_u64)
{
details.push(format!("{year} series"));
}
details.push("sub · UNVERIFIED".into());
} }
let details = details.join(" · "); let details = details.join(" · ");
let mut metadata = title.clone(); let mut metadata = title.clone();