diff --git a/src/main.rs b/src/main.rs index 83c4ba8..bb62355 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,14 @@ async fn main() { loop { let (title, show) = shows.iter().choose(&mut rng).expect("No shows found!"); - let (num, file) = show.episodes.iter().choose(&mut rng).unwrap(); + let episodes = match show.episodes() { + Ok(eps) => eps, + Err(e) => { + error!("Failed to get episodes for {}: {}", title, e); + continue; + } + }; + let (num, file) = episodes.iter().choose(&mut rng).unwrap(); let descriptor = format!( "{}{}", diff --git a/src/shows/mod.rs b/src/shows/mod.rs index 1dd894b..9abed11 100644 --- a/src/shows/mod.rs +++ b/src/shows/mod.rs @@ -6,7 +6,7 @@ use serde::Deserialize; mod enumeration; #[derive(Deserialize)] -pub struct ShowSpec { +pub struct Show { pub path: PathBuf, pub tags: Vec, } @@ -20,71 +20,50 @@ pub enum EpisodeNumber { type Episodes = HashMap; -pub struct Show { - pub episodes: Episodes, - pub tags: Vec, -} - pub fn load(shows_file: PathBuf) -> HashMap { - let show_specs: HashMap = - serde_yaml::from_reader(fs::File::open(shows_file).expect("Failed to open shows file")) - .expect("Failed to parse YAML from shows file"); - - show_specs - .into_iter() - .filter_map(|(name, show)| { - debug!("Enumerating show {}: {}", name, show.path.display()); - load_path(show.path) - .map_err(|e| { - error!("Error processing {}: {}", name, e); - }) - .ok() - .map(|eps| { - ( - name, - Show { - episodes: eps, - tags: show.tags, - }, - ) - }) - }) - .collect() + serde_yaml::from_reader(fs::File::open(shows_file).expect("Failed to open shows file")) + .expect("Failed to parse YAML from shows file") } -fn load_path(path: PathBuf) -> std::io::Result { - let metadata = fs::metadata(&path)?; - if metadata.is_file() { - debug!("{} is a file, standalone", path.display()); - Ok(HashMap::from([(EpisodeNumber::Standalone, path)])) - } else if metadata.is_dir() { - debug!("{} is a directory, enumerating episodes", path.display()); - let files: Vec = fs::read_dir(&path)? - .map(|entry| { - let entry = entry?; - if !entry.file_type()?.is_file() { - debug!("Skipping {}, not a file", entry.path().display()); - return Ok(None); - } - if entry.file_name().into_string().is_err() { - debug!( - "Skipping {}, contains invalid unicode", - entry.path().display() - ); - return Ok(None); - } - Ok(Some(entry.path())) - }) - .filter_map(|r| r.transpose()) - .collect::>>()?; - enumeration::enumerate_episodes(files).ok_or(std::io::Error::new( - ErrorKind::InvalidData, - "No valid prefixes found", - )) - } else { - Err(std::io::Error::new( - ErrorKind::InvalidInput, - format!("Invalid file type for {}", path.display()), - )) +impl Show { + pub fn episodes(&self) -> std::io::Result { + let path = &self.path; + let metadata = fs::metadata(path)?; + if metadata.is_file() { + debug!("{} is a file, standalone", path.display()); + Ok(HashMap::from([( + EpisodeNumber::Standalone, + path.to_path_buf(), + )])) + } else if metadata.is_dir() { + debug!("{} is a directory, enumerating episodes", path.display()); + let files: Vec = fs::read_dir(path)? + .map(|entry| { + let entry = entry?; + if !entry.file_type()?.is_file() { + debug!("Skipping {}, not a file", entry.path().display()); + return Ok(None); + } + if entry.file_name().into_string().is_err() { + error!( + "Path {} contains invalid unicode, skipping", + entry.path().display() + ); + return Ok(None); + } + Ok(Some(entry.path())) + }) + .filter_map(|r| r.transpose()) + .collect::>>()?; + enumeration::enumerate_episodes(files).ok_or(std::io::Error::new( + ErrorKind::InvalidData, + "No valid prefixes found", + )) + } else { + Err(std::io::Error::new( + ErrorKind::InvalidInput, + format!("Invalid file type for {}", path.display()), + )) + } } }