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)); } }