use std::{ collections::BTreeMap, env, fs::{self, read_to_string}, path::PathBuf, }; use serde::{Deserialize, Serialize}; mod eol_rule; use eol_rule::EolRule; use crate::{Error, MessageAge, Retention}; /// Configuration file for the program #[derive(Debug, Serialize, Deserialize)] pub struct Config { credentials: Option, rules: BTreeMap, } impl Default for Config { fn default() -> Self { let rules = BTreeMap::new(); let mut cfg = Self { credentials: Some("credential.json".to_string()), rules, }; cfg.add_rule(Retention::new(MessageAge::Years(1), true)) .add_rule(Retention::new(MessageAge::Weeks(1), true)) .add_rule(Retention::new(MessageAge::Months(1), true)) .add_rule(Retention::new(MessageAge::Years(5), true)); cfg } } impl Config { /// Create a new configuration file pub fn new() -> Self { Config::default() } /// Set a name for the credentials file pub fn set_credentials(&mut self, file_name: &str) -> &mut Self { self.credentials = Some(file_name.to_string()); self } /// Add a new rule to the rule set by setting the retention age pub fn add_rule(&mut self, retention: Retention) -> &mut Self { if self .rules .contains_key(retention.age().to_string().as_str()) { log::warn!("rule already exists"); return self; } let id = if let Some((_, max)) = self.rules.iter().max_by_key(|(_, r)| r.id()) { max.id() + 1 } else { 1 }; let mut rule = EolRule::new(id); rule.set_retention(retention); log::info!("added rule: {rule}"); self.rules.insert(rule.retention().to_string(), rule); self } /// Save the current configuration to the file pub fn save(&self) -> Result<(), Error> { let home_dir = env::home_dir().unwrap(); let path = PathBuf::new() .join(home_dir) .join(".cull-gmail/cull-gmail.toml"); if let Ok(output) = toml::to_string(self) { fs::write(path, output)?; } Ok(()) } /// Load the current configuration pub fn load() -> Result { let home_dir = env::home_dir().unwrap(); let path = PathBuf::new() .join(home_dir) .join(".cull-gmail/cull-gmail.toml"); let input = read_to_string(path)?; let config = toml::from_str::(&input)?; Ok(config) } /// Return the credential file name pub fn credential_file(&self) -> &str { if let Some(file) = &self.credentials { file } else { "" } } /// List the end of life rules set in the configuration pub fn list_rules(&self) -> Result<(), Error> { for rule in self.rules.values() { println!("{rule}"); } Ok(()) } }