diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..bf867e0 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/src/settings.rs b/src/settings.rs index 23a7deb..e51e58e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -3,10 +3,16 @@ use crate::error::SpotifyError; use serde::{Deserialize, Serialize}; use tokio::{ + fs::create_dir_all, fs::File, io::{AsyncReadExt, AsyncWriteExt}, }; +use std::{ + env, + path::{Path, PathBuf}, +}; + // Structure for holding all the settings #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Settings { @@ -18,6 +24,23 @@ pub struct Settings { pub downloader: DownloaderConfig, } +// On UNIX systems (eg. Linux, *BSD, even macOS), follow the +// XDG Base Directory Specification for storing config files +#[cfg(target_family = "unix")] +fn get_config_folder_path() -> PathBuf { + match env::var("XDG_CONFIG_HOME") { + Ok(v) => Path::new(&v).join("down_on_spot").to_path_buf(), + + Err(_) => Path::new(&env::var("HOME").unwrap()).join(".config/down_on_spot"), + } +} + +// On Windows, follow whatever windows does for AppData +#[cfg(target_family = "windows")] +fn get_config_folder_path() -> PathBuf { + Path::new(&env::var("APPDATA").unwrap()).join("down_on_spot"); +} + impl Settings { // Create new instance pub fn new(username: &str, password: &str, client_id: &str, client_secret: &str) -> Settings { @@ -31,17 +54,28 @@ impl Settings { } } - // Serialize the settings to a json file + // Save config pub async fn save(&self) -> Result<(), SpotifyError> { + // Get and create config folder path, generate config file path + let config_folder_path = get_config_folder_path(); + create_dir_all(&config_folder_path).await?; + let config_file_path = config_folder_path.join("settings.json"); + + // Serialize the settings to a json file let data = serde_json::to_string_pretty(self)?; - let mut file = File::create("settings.json").await?; + let mut file = File::create(config_file_path).await?; file.write_all(data.as_bytes()).await?; Ok(()) } - // Deserialize the settings from a json file + // Load config pub async fn load() -> Result { - let mut file = File::open("settings.json").await?; + // Get config folder path, generate config file path + let config_folder_path = get_config_folder_path(); + let config_file_path = config_folder_path.join("settings.json"); + + // Deserialize the settings from a json file + let mut file = File::open(config_file_path).await?; let mut buf = String::new(); file.read_to_string(&mut buf).await?; Ok(serde_json::from_str(&buf)?)