From 72280b9ccd4d84b20fcba7aeac11e75d086d6c16 Mon Sep 17 00:00:00 2001 From: rays Date: Thu, 10 Sep 2026 01:48:56 +0000 Subject: [PATCH] Pin RSS 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 --- PROGRESS.md | 18 ++++++++++++++++++ src/feed.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/PROGRESS.md b/PROGRESS.md index 73f3da6..6fc97bf 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -56,6 +56,24 @@ and until now nothing set them. --- +## 2026-09-10 — Titles: RSS `<title>` is the only source + +Confirmed against the live feed rather than assumed: 131 feed items, 131 stored, **0 mismatches** — +entry titles are byte-for-byte what the RSS `<title>` publishes, separators included. `feed.rs` never +consults `itunes:title`, and season/episode live in their own columns, rendered as chips rather than +folded into the title. + +Pinned with a test: a fixture whose `itunes:title` differs from its `<title>` must still yield the +RSS title, and an item with `itunes:season` but no `itunes:episode` keeps a null episode instead of +inventing one. + +That null-episode case is real in the wild — this feed's `Music from a Darkened Room | Session Zero` +carries S8 with no episode number, while Parts 1-5 get E1-E5, and it drops the "Part N" convention +its siblings use. The arc is 11 items: Session Zero plus five parts, each part being a main episode +and its shorter `Junk in the Trunk` companion. + +--- + ## 2026-09-10 — Phase 3: full-featured UI Rewrite of `web/index.html` (~714 lines) plus the backend it needed. diff --git a/src/feed.rs b/src/feed.rs index 2f94fb6..e15e9fc 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -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>Showhttps://xd + + Music from a Darkened Room | Session Zero + Session Zero + sz + 8 + 6720 + + + + Music from a Darkened Room Part 1 | Murphy's Drawer + p1 + 81 + + + "#; + 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));