Pin RSS <title> as the only source of an episode title

Confirmed byte-for-byte against a live feed, and tested against a fixture
whose itunes:title differs: the RSS title wins, and season/episode stay
metadata rather than being folded into the displayed name. An item with a
season but no episode number keeps a null episode instead of inventing one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPyeapneuXrCdojsaiXGbe
This commit is contained in:
2026-09-10 01:48:56 +00:00
parent 5666166769
commit 72280b9ccd
2 changed files with 58 additions and 0 deletions

View File

@@ -351,6 +351,46 @@ mod tests {
);
}
#[test]
fn the_rss_title_always_wins_and_episode_numbers_stay_metadata() {
// Some feeds set a different itunes:title. The displayed title is always the RSS
// <title>, verbatim -- separators and all -- and season/episode are stored
// alongside it rather than folded into it.
let xml = br#"<?xml version="1.0"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<channel><title>Show</title><link>https://x</link><description>d</description>
<item>
<title>Music from a Darkened Room | Session Zero</title>
<itunes:title>Session Zero</itunes:title>
<guid>sz</guid>
<itunes:season>8</itunes:season>
<itunes:duration>6720</itunes:duration>
<enclosure url="https://x/sz.mp3" length="1" type="audio/mpeg"/>
</item>
<item>
<title>Music from a Darkened Room Part 1 | Murphy's Drawer</title>
<guid>p1</guid>
<itunes:season>8</itunes:season><itunes:episode>1</itunes:episode>
<enclosure url="https://x/p1.mp3" length="1" type="audio/mpeg"/>
</item>
</channel></rss>"#;
let feed = parse(xml).unwrap();
let sz = &feed.entries[0];
assert_eq!(
sz.title.as_deref(),
Some("Music from a Darkened Room | Session Zero"),
"itunes:title must not override the RSS title"
);
assert_eq!(sz.season, Some(8));
assert_eq!(sz.episode, None, "a missing episode number stays missing");
assert_eq!(sz.duration, Some(6720));
let p1 = &feed.entries[1];
assert_eq!(p1.title.as_deref(), Some("Music from a Darkened Room Part 1 | Murphy's Drawer"));
assert_eq!((p1.season, p1.episode), (Some(8), Some(1)));
}
#[test]
fn durations_parse_from_seconds_or_a_clock() {
assert_eq!(parse_duration("5649"), Some(5649));