X-Git-Url: https://git.r.bdr.sh/rbdr/lyricli/blobdiff_plain/b2096fb3958d9e9cdcca77931aadfb947cab24ee..44e7b4de4073e6dc25681bb2fa6977bf5869689a:/src/configuration.rs?ds=sidebyside diff --git a/src/configuration.rs b/src/configuration.rs new file mode 100644 index 0000000..f678461 --- /dev/null +++ b/src/configuration.rs @@ -0,0 +1,98 @@ +use std::env; +use std::fs::{create_dir_all, write, File}; +use std::io::{Read, Result}; +use std::path::PathBuf; +use serde::{Deserialize, Serialize}; +use serde_json; + +const CONFIG_ENV_VARIABLE: &str = "LYRICLI_CONFIG_DIRECTORY"; +const CONFIG_DEFAULT_LOCATION: &str = "XDG_CONFIG_HOME"; +const CONFIG_FALLBACK_LOCATION: &str = ".config"; +const CONFIG_SUBDIRECTORY: &str = ".config"; +const CONFIG_FILENAME: &str = "lyricli.conf"; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Configuration { + enabled_sources: Vec +} + +impl Configuration { + + pub fn new() -> Self { + + if let Some(configuration) = Configuration::read() { + return configuration; + } + + let configuration = Configuration::default(); + + // Write the defaults. + Configuration::write(&configuration).ok(); + configuration + } + + // Public API + + pub fn is_enabled(&self, source_name: &String) -> bool { + self.enabled_sources.contains(source_name) + } + + pub fn enable_source(&mut self, source_name: &String) -> Result<()> { + if !self.enabled_sources.contains(source_name) { + self.enabled_sources.push(source_name.to_owned()) + } + Configuration::write(self) + } + + pub fn disable_source(&mut self, source_name: &String) -> Result<()> { + self.enabled_sources.retain(|source| source != source_name); + Configuration::write(self) + } + + // Helpers + + fn default() -> Configuration { + Configuration { + enabled_sources: vec![ + "apple_music".to_string(), + "spotify".to_string() + ] + } + } + + fn read() -> Option { + let config_file_path = Configuration::file_path(); + + let mut config_file = File::open(&config_file_path).ok()?; + let mut config_contents = String::new(); + config_file.read_to_string(&mut config_contents).ok()?; + serde_json::from_str(&config_contents).ok()? + } + + fn write(configuration: &Configuration) -> Result<()> { + let config_file_path = Configuration::file_path(); + if let Ok(serialized_configuration) = serde_json::to_string(&configuration) { + write(&config_file_path, serialized_configuration)?; + } + Ok(()) + } + + fn file_path() -> PathBuf { + let config_directory = Configuration::directory(); + create_dir_all(&config_directory).ok(); + config_directory.join(CONFIG_FILENAME) + } + + fn directory() -> PathBuf { + match env::var(CONFIG_ENV_VARIABLE) { + Ok(directory) => PathBuf::from(directory), + Err(_) => match env::var(CONFIG_DEFAULT_LOCATION) { + Ok(directory) => PathBuf::from(directory), + Err(_) => match env::var("HOME") { + Ok(directory) => PathBuf::from(directory).join(CONFIG_FALLBACK_LOCATION), + Err(_) => panic!("Could not find required directory, {} or {} should be set and readable.", CONFIG_ENV_VARIABLE, CONFIG_DEFAULT_LOCATION), + }, + }, + }.join(CONFIG_SUBDIRECTORY) + } +}