//! Apple Podcasts' categories, and where a feed's category sits among them (#118). /// 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 categories stay few. pub(crate) const CATEGORIES: &[(&str, &[&str])] = &[ ("Arts", &["Books", "Design", "Fashion & Beauty", "Food", "Performing Arts", "Visual Arts"]), ("Business", &["Careers", "Entrepreneurship", "Investing", "Management", "Marketing", "Non-Profit"]), ("Comedy", &["Comedy Interviews", "Improv", "Stand-Up"]), ("Education", &["Courses", "How To", "Language Learning", "Self-Improvement"]), ("Fiction", &["Comedy Fiction", "Drama", "Science Fiction"]), ("Government", &[]), ("History", &[]), ("Health & Fitness", &["Alternative Health", "Fitness", "Medicine", "Mental Health", "Nutrition", "Sexuality"]), ("Kids & Family", &["Education for Kids", "Parenting", "Pets & Animals", "Stories for Kids"]), ( "Leisure", &["Animation & Manga", "Automotive", "Aviation", "Crafts", "Games", "Hobbies", "Home & Garden", "Video Games"], ), ("Music", &["Music Commentary", "Music History", "Music Interviews"]), ( "News", &[ "Business News", "Daily News", "Entertainment News", "News Commentary", "Politics", "Sports News", "Tech News", ], ), ( "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", "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. pub(crate) const ALIASES: &[(&str, &str)] = &[("American Football", "Football"), ("Football (Soccer)", "Soccer"), ("Software How-To", "Technology")]; /// Apple's categories as ipx has them, for the directory to check against Apple's own (#252). #[must_use] pub fn categories() -> &'static [(&'static str, &'static [&'static str])] { CATEGORIES } /// 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. #[must_use] 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); } if let Some(sub) = subs.iter().find(|s| s.eq_ignore_ascii_case(name)) { return (category.to_string(), Some(sub.to_string())); } } (name.to_string(), None) } #[cfg(test)] mod tests { #[test] fn category_path_finds_a_subcategory_s_category() { use super::category_path; assert_eq!(category_path("Tech News"), ("News".into(), Some("Tech News".into()))); 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)); } }