From 0b4f5443b70287f6bb57dda6237229fd5cfaa362 Mon Sep 17 00:00:00 2001 From: rays Date: Mon, 5 Oct 2026 16:19:12 +0000 Subject: [PATCH] File Apple's Football and Soccer under Sports in the Directory (#125) The Directory listed Football (6 feeds), Soccer (7) and "Soccer," (2) as categories of their own beside Sports, and Software How-To (2) beside Technology. CATEGORIES spelt two of Apple's Sports subcategories American Football and Football (Soccer), names no feed uses: Apple's list says Football and Soccer, so a feed naming either fell through as a category of its own. They are Apple's spelling now. The old spellings are aliases, since Jev picked from the list while it had them and its answers are stored, and so is Software How-To, Apple's Technology subcategory before its 2019 list. A comma or full stop at the end of a feed's category, as in "Soccer,", is dropped. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + src/feed.rs | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd4fc83..35500ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Feeds that file themselves under Apple's Football or Soccer show under Sports, and those under the old Software How-To under Technology, instead of as categories of their own. - The download queue, in `ipx status`, `/api/status` and the dashboard, counts only what iPX will download on its own: older episodes beyond a show's limit, and files of feeds that do not download automatically, are listed but no longer counted as waiting. - Artwork published on http is stored on https when its host serves it there, so the page loads it directly; the rest still comes through iPX. - An iPhone adding the site to its home screen finds the icon at the first address it tries. diff --git a/src/feed.rs b/src/feed.rs index 9704946..bca17aa 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -13,7 +13,7 @@ pub struct ParsedFeed { pub image: Option, /// The site the feed belongs to, where a favicon can stand in for missing artwork. pub site: Option, - /// The channel's first ``, for the Directory's chips. + /// The channel's first ``, for the Directory's categories. pub category: Option, pub entries: Vec, } @@ -1010,7 +1010,7 @@ fn parse_date(s: &str) -> Option { /// Apple's podcast categories, each with its subcategories /// (https://podcasters.apple.com/support/1691-apple-podcasts-categories): the list a podcast's own -/// `` comes from, and a fixed one, so the Directory's chips stay few. +/// `` comes from, and a fixed one, so the Directory's categories stay few. const CATEGORIES: &[(&str, &[&str])] = &[ ("Arts", &["Books", "Design", "Fashion & Beauty", "Food", "Performing Arts", "Visual Arts"]), ("Business", &["Careers", "Entrepreneurship", "Investing", "Management", "Marketing", "Non-Profit"]), @@ -1027,16 +1027,25 @@ const CATEGORIES: &[(&str, &[&str])] = &[ ("Religion & Spirituality", &["Buddhism", "Christianity", "Hinduism", "Islam", "Judaism", "Religion", "Spirituality"]), ("Science", &["Astronomy", "Chemistry", "Earth Sciences", "Life Sciences", "Mathematics", "Natural Sciences", "Nature", "Physics", "Social Sciences"]), ("Society & Culture", &["Documentary", "Personal Journals", "Philosophy", "Places & Travel", "Relationships"]), - ("Sports", &["Baseball", "Basketball", "Cricket", "Fantasy Sports", "American Football", "Golf", "Hockey", "Rugby", "Running", "Football (Soccer)", "Swimming", "Tennis", "Volleyball", "Wilderness", "Wrestling"]), + ("Sports", &["Baseball", "Basketball", "Cricket", "Fantasy Sports", "Football", "Golf", "Hockey", "Rugby", "Running", "Soccer", "Swimming", "Tennis", "Volleyball", "Wilderness", "Wrestling"]), ("Technology", &[]), ("True Crime", &[]), ("TV & Film", &["After Shows", "Film History", "Film Interviews", "Film Reviews", "TV Reviews"]), ]; +/// Names that are not in Apple's list but mean one that is (#125). Jev picked from this list when +/// it spelt Football and Soccer its own way, and stored those answers; Software How-To is Apple's +/// Technology subcategory from before its 2019 list, which older feeds still name. +const ALIASES: &[(&str, &str)] = + &[("American Football", "Football"), ("Football (Soccer)", "Soccer"), ("Software How-To", "Technology")]; + /// Where a category sits in Apple's list, as (category, subcategory), so the Directory browses a /// category and then its subcategories as Apple's does (#118). A podcast's own is stored as its /// subcategory, and one an admin typed that is not Apple's stands as a category of its own. pub fn category_path(name: &str) -> (String, Option) { + // A feed's own text, which can end in a stray comma: "Soccer," was a category of its own. + let name = name.trim().trim_end_matches([',', ';', '.']).trim_end(); + let name = ALIASES.iter().find(|(old, _)| old.eq_ignore_ascii_case(name)).map_or(name, |(_, now)| now); for (category, subs) in CATEGORIES { if category.eq_ignore_ascii_case(name) { return (category.to_string(), None); @@ -1594,6 +1603,12 @@ mod tests { assert_eq!(category_path("video games"), ("Leisure".into(), Some("Video Games".into())), "Apple's spelling"); assert_eq!(category_path("Technology"), ("Technology".into(), None)); assert_eq!(category_path("Homebrew"), ("Homebrew".into(), None), "not Apple's: its own category"); + // Apple's spelling, an old answer of Jev's, a stray comma and Apple's old list (#125). + assert_eq!(category_path("Soccer"), ("Sports".into(), Some("Soccer".into()))); + assert_eq!(category_path("Football (Soccer)"), ("Sports".into(), Some("Soccer".into()))); + assert_eq!(category_path("Soccer,"), ("Sports".into(), Some("Soccer".into()))); + assert_eq!(category_path("Football"), ("Sports".into(), Some("Football".into()))); + assert_eq!(category_path("Software How-To"), ("Technology".into(), None)); } }