Fetch TVDB's English-translated episode names instead of original-language

Plain /episodes/default returns names in the show's original airing
language — for a lot of anime that's Japanese with no English name at all,
which is what was ending up embedded in generated filenames. TVDB carries
real crowd-sourced English translations at /episodes/default/eng (same
numbering/air-date fields, just a better name) — try that first and only
fall back to the original-language endpoint if a show has no English data.
This commit is contained in:
Breadway 2026-07-21 20:09:24 +08:00
parent dcf9ee241c
commit 17d82b84c2

View file

@ -110,8 +110,6 @@ impl TvdbClient {
} }
pub async fn episodes(&self, series_id: &str) -> Result<Vec<EpisodeInfo>> { pub async fn episodes(&self, series_id: &str) -> Result<Vec<EpisodeInfo>> {
let token = self.token().await?;
#[derive(Deserialize)] #[derive(Deserialize)]
struct EpisodesResponse { struct EpisodesResponse {
data: EpisodesData, data: EpisodesData,
@ -131,20 +129,47 @@ impl TvdbClient {
aired: Option<String>, aired: Option<String>,
} }
let resp: EpisodesResponse = self // TVDB's plain `/episodes/default` returns names in the show's
.client // original airing language — for a lot of anime that's Japanese,
.get(format!( // with no English name at all (verified live: entire shows came
"https://api4.thetvdb.com/v4/series/{series_id}/episodes/default" // back Japanese-only). `/episodes/default/eng` is the same episode
)) // list (same numbering/air-date fields) but with TVDB's own
.bearer_auth(token) // crowd-sourced English translation substituted in for `name`
.send() // wherever one exists — a real translation, not a guess, so it's
.await // tried first and only falls back to the original-language
.context("tvdb episodes request failed")? // endpoint if TVDB has no English data for this show at all.
.error_for_status() let token = self.token().await?;
.context("tvdb episodes returned an error status")? let fetch = |url: String| {
.json() let client = self.client.clone();
.await let token = token.clone();
.context("tvdb episodes response was not valid JSON")?; async move {
client
.get(url)
.bearer_auth(token)
.send()
.await
.context("tvdb episodes request failed")?
.error_for_status()
.context("tvdb episodes returned an error status")?
.json::<EpisodesResponse>()
.await
.context("tvdb episodes response was not valid JSON")
}
};
let resp = match fetch(format!(
"https://api4.thetvdb.com/v4/series/{series_id}/episodes/default/eng"
))
.await
{
Ok(resp) => resp,
Err(_) => {
fetch(format!(
"https://api4.thetvdb.com/v4/series/{series_id}/episodes/default"
))
.await?
}
};
Ok(resp Ok(resp
.data .data