use crate::result::{AppResult, AppError}; use crate::{CONFIG_PATH, UpdateOptions}; use std::io::{Write, Read}; #[derive(Serialize, Default, Deserialize)] pub struct Config { current_episode_count: usize, pattern: String, #[serde(default = "default_command")] pub command: String, } pub fn default_command() -> String { String::from("mpv --fullscreen \"{}\"") } impl Config { pub fn new(pattern: String, maybe_command: String) -> AppResult { let mut command = maybe_command; if pattern.is_empty() { return Err(AppError::RuntimeError( String::from("Pattern can't be empty") )); } if command.is_empty() { command = default_command(); } Ok(Self { current_episode_count: 0, pattern, command, }) } pub fn save(&self) -> AppResult<()> { let json = serde_json::to_string_pretty(self)?; let mut file = std::fs::File::create(CONFIG_PATH.as_str())?; file.write_all(json.as_bytes())?; Ok(()) } pub fn read() -> AppResult { let config_path = std::path::Path::new(CONFIG_PATH.as_str()); if !config_path.exists() { return Err( AppError::StdErr(String::from("Run 'awatch init' first.")) ); } let mut file = std::fs::File::open(CONFIG_PATH.as_str())?; let mut buffer = String::new(); file.read_to_string(&mut buffer)?; let config: Self = serde_json::from_str(buffer.as_str())?; Ok(config) } pub fn get_current_episode(&self) -> AppResult { let current_dir = std::env::current_dir()?; let mut names = Vec::new(); let episode_regex = regex::Regex::new(self.pattern.as_str())?; for entry in std::fs::read_dir(current_dir)? { let entry = entry?; let path = entry.path(); let meta = std::fs::metadata(&path)?; if meta.is_dir() { continue; } let name = entry.file_name(); let name_str = name.into_string(); if let Ok(name) = name_str { if episode_regex.is_match(name.as_str()) { names.push(name); } } } alphanumeric_sort::sort_str_slice(names.as_mut_slice()); if let Some(episode) = names.get(self.current_episode_count) { Ok(episode.clone()) } else { Err(AppError::RuntimeError(String::from("This is the end."))) } } } pub fn update_episode(episode_func: fn(usize) -> AppResult) -> AppResult<()> { let mut conf = Config::read()?; conf.current_episode_count = episode_func(conf.current_episode_count)?; conf.save() } pub fn update_config(options: UpdateOptions) -> AppResult<()> { let mut conf = Config::read()?; if let Some(pattern) = options.pattern { conf.pattern = pattern; } if let Some(command) = options.command { conf.command = command; } if let Some(episode) = options.last_episode { conf.current_episode_count = episode; } conf.save() }