]> git.r.bdr.sh - rbdr/lyricli/blobdiff - src/configuration.rs
Add macos sources
[rbdr/lyricli] / src / configuration.rs
diff --git a/src/configuration.rs b/src/configuration.rs
new file mode 100644 (file)
index 0000000..f678461
--- /dev/null
@@ -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<String>
+}
+
+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<Configuration> {
+        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)
+    }
+}