1use std::fs;
2use std::path::PathBuf;
3
4use serde::{Deserialize, Serialize};
5
6use crate::error::{AmError, AmResult};
7
8#[derive(Debug, Default, Serialize, Deserialize)]
9pub struct Config {
10 #[serde(default)]
11 pub default_identity: Option<String>,
12
13 #[serde(default)]
14 pub relays: Vec<String>,
15
16 #[serde(default)]
17 pub format: Option<String>,
18}
19
20pub fn data_dir() -> AmResult<PathBuf> {
21 let base = dirs::data_dir()
22 .ok_or_else(|| AmError::Config("cannot determine data directory".into()))?;
23 Ok(base.join("am"))
24}
25
26pub fn config_dir() -> AmResult<PathBuf> {
27 let base = dirs::config_dir()
28 .ok_or_else(|| AmError::Config("cannot determine config directory".into()))?;
29 Ok(base.join("am"))
30}
31
32pub fn config_path() -> AmResult<PathBuf> {
33 Ok(config_dir()?.join("config.toml"))
34}
35
36pub fn identity_dir() -> AmResult<PathBuf> {
37 Ok(data_dir()?.join("identities"))
38}
39
40pub fn ensure_dirs() -> AmResult<()> {
41 fs::create_dir_all(config_dir()?)?;
42 fs::create_dir_all(identity_dir()?)?;
43 Ok(())
44}
45
46pub fn load_config() -> AmResult<Config> {
47 let path = config_path()?;
48 if !path.exists() {
49 return Ok(Config::default());
50 }
51 let contents = fs::read_to_string(&path)?;
52 let config: Config = toml::from_str(&contents)?;
53 Ok(config)
54}
55
56pub fn save_config(config: &Config) -> AmResult<()> {
57 ensure_dirs()?;
58 let contents = toml::to_string_pretty(config)?;
59 fs::write(config_path()?, contents)?;
60 Ok(())
61}