use serde::{Serialize, Deserialize}; use std::{fs, path::Path}; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Config { pub bind_address: Option, pub bind_port: Option, pub client_storage_path: Option, pub receiver_whitelist: Option>, pub clients: Vec, pub mappings: Vec, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ClientConfig { pub mxid: String, pub password: String, pub device_id: Option, pub access_token: Option, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Mapping { pub from: Option, pub to: Option, pub mxid_sender: Option, pub room_id: String, pub room_alias: Option, } pub fn load_config(file_path: &str) -> Config { let yaml_str = fs::read_to_string(file_path).expect("Error while reading config file"); let mut cfg: Config = serde_yaml::from_str(&yaml_str).expect("Config file not in expected format"); // Set default values if necessary if cfg.bind_address.is_none() { cfg.bind_address = Some("127.0.0.1".to_string()); } if cfg.bind_port.is_none() { cfg.bind_port = Some("25".to_string()); } if cfg.client_storage_path.is_none() { let path = Path::new(file_path).parent().unwrap().join("client_storage"); cfg.client_storage_path = Some(path.to_str().unwrap().to_string()); } cfg } pub fn write_config(config: &Config, old_config: &Config, file_path: &str) { let new_yaml_str = serde_yaml::to_string(config).expect("Failed to serialize new config."); let old_yaml_str = serde_yaml::to_string(old_config).expect("Failed to serialize old config."); if new_yaml_str != old_yaml_str { rotate_configs(file_path); fs::write(file_path, &new_yaml_str).expect("Error writing new config to file"); } } fn rotate_configs(base_path: &str) { for i in 9..2 { std::fs::copy(&format!("{}.{}", base_path, i - 1), &format!("{}.{}", base_path, i)).expect(""); } std::fs::copy(base_path, &format!("{}.1", base_path)).expect(""); }