1use std::collections::BTreeMap;
2use std::path::{Path, PathBuf};
3
4use serde::{Deserialize, Serialize};
5
6use crate::error::YukiError;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct AdminEntry {
10 pub domain_id: String,
11 pub admin_id: String,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct Config {
16 pub api_key: String,
17 pub default_admin: String,
18 pub administrations: BTreeMap<String, AdminEntry>,
19 #[serde(default)]
22 pub unmatched_ignore: Vec<String>,
23}
24
25impl Config {
26 pub fn default_path() -> PathBuf {
27 #[cfg(unix)]
28 {
29 let home = std::env::var("HOME").unwrap_or_else(|_| ".".into());
30 PathBuf::from(home).join(".config/yuki/config.toml")
31 }
32 #[cfg(not(unix))]
33 {
34 directories::ProjectDirs::from("nl", "yukiworks", "yuki")
35 .map(|d| d.config_dir().join("config.toml"))
36 .unwrap_or_else(|| PathBuf::from("config.toml"))
37 }
38 }
39
40 pub fn load() -> Result<Self, YukiError> {
41 Self::load_from(&Self::default_path())
42 }
43
44 pub fn load_from(path: &Path) -> Result<Self, YukiError> {
45 let content = std::fs::read_to_string(path)
46 .map_err(|e| YukiError::Config(format!("failed to read {}: {e}", path.display())))?;
47 toml::from_str(&content).map_err(|e| YukiError::Config(format!("invalid config: {e}")))
48 }
49
50 pub fn save_to(&self, path: &Path) -> Result<(), YukiError> {
51 if let Some(parent) = path.parent() {
52 std::fs::create_dir_all(parent)
53 .map_err(|e| YukiError::Config(format!("cannot create config dir: {e}")))?;
54 }
55 let content = toml::to_string_pretty(self)
56 .map_err(|e| YukiError::Config(format!("serialize error: {e}")))?;
57 std::fs::write(path, content)
58 .map_err(|e| YukiError::Config(format!("failed to write {}: {e}", path.display())))
59 }
60
61 pub fn resolve_admin(&self, override_name: Option<&str>) -> Result<AdminEntry, YukiError> {
62 let name = override_name.unwrap_or(&self.default_admin);
63 self.administrations
64 .get(name)
65 .cloned()
66 .ok_or_else(|| YukiError::Config(format!("unknown administration: {name}")))
67 }
68}