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