use std::{env, fs::{self}, path::{Path, PathBuf}}; use serde::{Deserialize, Serialize}; #[derive(Debug)] pub struct ConfigError(pub String); impl From for ConfigError { fn from(value: serde_json::Error) -> Self { Self(value.to_string()) } } impl From for ConfigError { fn from(value: std::io::Error) -> Self { Self(value.to_string()) } } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Instance { pub name: String, pub url: String, #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] pub token: Option } impl Instance { pub fn new(name: String, url: String) -> Self { Self { name, url, token: None } } } #[derive(Debug, Serialize, Deserialize)] pub struct Config { pub instances: Vec, #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] pub last_instance: Option, } impl Config { fn config_path() -> PathBuf { let mut prefix = Path::new(&env::var("HOME").expect("HOME environment variable was not set")).join(".config"); if let Ok(config_home) = env::var("XDG_CONFIG_HOME") { prefix = config_home.into(); } prefix.join("gamenight-cli").join("config.json") } pub fn new() -> Config { Config { instances: vec![], last_instance: None } } pub fn load() -> Result { let config_path = Self::config_path(); if !fs::exists(&config_path)? { let config_error = ConfigError(format!("Cannot create parent directory for config file: {}", &config_path.display()).to_string()); let _ = fs::create_dir_all(&config_path.parent().ok_or(config_error)?)?; let config = Config::new(); fs::write(&config_path, serde_json::to_string_pretty(&config)?.as_bytes())?; Ok(config) } else { let config_string = fs::read_to_string(Self::config_path())?; Ok(serde_json::from_str(&config_string)?) } } pub fn save(gamenight_configuration: &Config) -> Result<(), ConfigError> { let config_path = Self::config_path(); fs::write(&config_path, serde_json::to_string_pretty(gamenight_configuration)?.as_bytes())?; Ok(()) } }