]>
Commit | Line | Data |
---|---|---|
1 | use std::env; | |
2 | use std::fs::{create_dir_all, write, File}; | |
3 | use std::io::{Read, Result}; | |
4 | use std::path::PathBuf; | |
5 | use serde::{Deserialize, Serialize}; | |
6 | use serde_json; | |
7 | ||
8 | const CONFIG_ENV_VARIABLE: &str = "LYRICLI_CONFIG_DIRECTORY"; | |
9 | const CONFIG_DEFAULT_LOCATION: &str = "XDG_CONFIG_HOME"; | |
10 | const CONFIG_FALLBACK_LOCATION: &str = ".config"; | |
11 | const CONFIG_SUBDIRECTORY: &str = ".config"; | |
12 | const CONFIG_FILENAME: &str = "lyricli.conf"; | |
13 | ||
14 | #[derive(Serialize, Deserialize, Debug)] | |
15 | pub struct Configuration { | |
16 | enabled_sources: Vec<String> | |
17 | } | |
18 | ||
19 | impl Configuration { | |
20 | ||
21 | pub fn new() -> Self { | |
22 | ||
23 | if let Some(configuration) = Configuration::read() { | |
24 | return configuration; | |
25 | } | |
26 | ||
27 | let configuration = Configuration::default(); | |
28 | ||
29 | // Write the defaults. | |
30 | Configuration::write(&configuration).ok(); | |
31 | configuration | |
32 | } | |
33 | ||
34 | // Public API | |
35 | ||
36 | pub fn is_enabled(&self, source_name: &String) -> bool { | |
37 | self.enabled_sources.contains(source_name) | |
38 | } | |
39 | ||
40 | pub fn enable_source(&mut self, source_name: &String) -> Result<()> { | |
41 | if !self.enabled_sources.contains(source_name) { | |
42 | self.enabled_sources.push(source_name.to_owned()) | |
43 | } | |
44 | Configuration::write(self) | |
45 | } | |
46 | ||
47 | pub fn disable_source(&mut self, source_name: &String) -> Result<()> { | |
48 | self.enabled_sources.retain(|source| source != source_name); | |
49 | Configuration::write(self) | |
50 | } | |
51 | ||
52 | // Helpers | |
53 | ||
54 | fn default() -> Configuration { | |
55 | Configuration { | |
56 | enabled_sources: vec![ | |
57 | "apple_music".to_string(), | |
58 | "spotify".to_string() | |
59 | ] | |
60 | } | |
61 | } | |
62 | ||
63 | fn read() -> Option<Configuration> { | |
64 | let config_file_path = Configuration::file_path(); | |
65 | ||
66 | let mut config_file = File::open(&config_file_path).ok()?; | |
67 | let mut config_contents = String::new(); | |
68 | config_file.read_to_string(&mut config_contents).ok()?; | |
69 | serde_json::from_str(&config_contents).ok()? | |
70 | } | |
71 | ||
72 | fn write(configuration: &Configuration) -> Result<()> { | |
73 | let config_file_path = Configuration::file_path(); | |
74 | if let Ok(serialized_configuration) = serde_json::to_string(&configuration) { | |
75 | write(&config_file_path, serialized_configuration)?; | |
76 | } | |
77 | Ok(()) | |
78 | } | |
79 | ||
80 | fn file_path() -> PathBuf { | |
81 | let config_directory = Configuration::directory(); | |
82 | create_dir_all(&config_directory).ok(); | |
83 | config_directory.join(CONFIG_FILENAME) | |
84 | } | |
85 | ||
86 | fn directory() -> PathBuf { | |
87 | match env::var(CONFIG_ENV_VARIABLE) { | |
88 | Ok(directory) => PathBuf::from(directory), | |
89 | Err(_) => match env::var(CONFIG_DEFAULT_LOCATION) { | |
90 | Ok(directory) => PathBuf::from(directory), | |
91 | Err(_) => match env::var("HOME") { | |
92 | Ok(directory) => PathBuf::from(directory).join(CONFIG_FALLBACK_LOCATION), | |
93 | Err(_) => panic!("Could not find required directory, {} or {} should be set and readable.", CONFIG_ENV_VARIABLE, CONFIG_DEFAULT_LOCATION), | |
94 | }, | |
95 | }, | |
96 | }.join(CONFIG_SUBDIRECTORY) | |
97 | } | |
98 | } |