bunkr_client/config/
config.rs1use serde::{Deserialize, Serialize};
2#[cfg(feature = "cli")]
3use std::fs;
4#[cfg(feature = "cli")]
5use std::path::PathBuf;
6use anyhow::Result;
7
8#[derive(Debug, Deserialize, Serialize, Clone)]
9pub struct Config {
10 pub default_batch_size: Option<usize>,
11 pub default_album_id: Option<String>,
12 pub default_album_name: Option<String>,
13 pub preprocess_videos: Option<bool>,
14}
15
16impl Default for Config {
17 fn default() -> Self {
18 Config {
19 default_batch_size: Some(1),
20 default_album_id: None,
21 default_album_name: None,
22 preprocess_videos: Some(true),
23 }
24 }
25}
26
27#[derive(Clone, Copy)]
28enum ConfigKey {
29 DefaultBatchSize,
30 DefaultAlbumId,
31 DefaultAlbumName,
32 PreprocessVideos,
33}
34
35impl ConfigKey {
36 fn as_str(&self) -> &str {
37 match self {
38 ConfigKey::DefaultBatchSize => "default_batch_size",
39 ConfigKey::DefaultAlbumId => "default_album_id",
40 ConfigKey::DefaultAlbumName => "default_album_name",
41 ConfigKey::PreprocessVideos => "preprocess_videos",
42 }
43 }
44
45 fn from_str(s: &str) -> Option<Self> {
46 match s {
47 "default_batch_size" => Some(ConfigKey::DefaultBatchSize),
48 "default_album_id" => Some(ConfigKey::DefaultAlbumId),
49 "default_album_name" => Some(ConfigKey::DefaultAlbumName),
50 "preprocess_videos" => Some(ConfigKey::PreprocessVideos),
51 _ => None,
52 }
53 }
54
55 fn get(&self, config: &Config) -> String {
56 match self {
57 ConfigKey::DefaultBatchSize => config.default_batch_size.map(|v| v.to_string()).unwrap_or_else(|| "1".to_string()),
58 ConfigKey::DefaultAlbumId => config.default_album_id.clone().unwrap_or_else(|| "none".to_string()),
59 ConfigKey::DefaultAlbumName => config.default_album_name.clone().unwrap_or_else(|| "none".to_string()),
60 ConfigKey::PreprocessVideos => config.preprocess_videos.map(|v| v.to_string()).unwrap_or_else(|| "true".to_string()),
61 }
62 }
63
64 fn set(&self, config: &mut Config, value: &str) -> Result<()> {
65 match self {
66 ConfigKey::DefaultBatchSize => {
67 config.default_batch_size = Some(value.parse()?);
68 }
69 ConfigKey::DefaultAlbumId => {
70 config.default_album_id = if value == "none" { None } else { Some(value.to_string()) };
71 }
72 ConfigKey::DefaultAlbumName => {
73 config.default_album_name = if value == "none" { None } else { Some(value.to_string()) };
74 }
75 ConfigKey::PreprocessVideos => {
76 config.preprocess_videos = Some(value.parse()?);
77 }
78 }
79 Ok(())
80 }
81
82 fn default(&self) -> String {
83 match self {
84 ConfigKey::DefaultBatchSize => "1".to_string(),
85 ConfigKey::DefaultAlbumId => "none".to_string(),
86 ConfigKey::DefaultAlbumName => "none".to_string(),
87 ConfigKey::PreprocessVideos => "true".to_string(),
88 }
89 }
90
91 const fn all() -> &'static [Self] {
92 &[
93 ConfigKey::DefaultBatchSize,
94 ConfigKey::DefaultAlbumId,
95 ConfigKey::DefaultAlbumName,
96 ConfigKey::PreprocessVideos,
97 ]
98 }
99}
100
101impl Config {
102 #[cfg(feature = "cli")]
103 pub fn load() -> Result<Self> {
104 let config_path = Self::config_path();
105 if config_path.exists() {
106 let content = fs::read_to_string(config_path)?;
107 Ok(toml::from_str(&content)?)
108 } else {
109 Ok(Self::default())
110 }
111 }
112
113 #[cfg(not(feature = "cli"))]
114 pub fn load() -> Result<Self> {
115 Ok(Self::default())
116 }
117
118 #[cfg(feature = "cli")]
119 pub fn save(&self) -> Result<()> {
120 let config_path = Self::config_path();
121 if let Some(parent) = config_path.parent() {
122 fs::create_dir_all(parent)?;
123 }
124 let content = toml::to_string(self)?;
125 fs::write(config_path, content)?;
126 Ok(())
127 }
128
129 #[cfg(not(feature = "cli"))]
130 pub fn save(&self) -> Result<()> {
131 Err(anyhow::anyhow!("CLI feature is not enabled."))
132 }
133
134 pub fn get_value(&self, key: &str) -> String {
135 if let Some(k) = ConfigKey::from_str(key) {
136 k.get(self)
137 } else {
138 "unknown key".to_string()
139 }
140 }
141
142 pub fn set_value(&mut self, key: &str, value: &str) -> Result<()> {
143 if let Some(k) = ConfigKey::from_str(key) {
144 k.set(self, value)
145 } else {
146 Err(anyhow::anyhow!("Unknown key: {}", key))
147 }
148 }
149
150 pub fn print_all(&self) {
151 println!("Key Value | Default");
152 println!("─────────────────────────────────────────");
153 for key in ConfigKey::all() {
154 let current = key.get(self);
155 let default = key.default();
156 println!("{:<22} {:<9} | \x1b[3m{}\x1b[0m", key.as_str(), current, default);
157 }
158 }
159
160 #[cfg(feature = "cli")]
161 fn config_path() -> PathBuf {
162 dirs::config_dir()
163 .unwrap_or_else(|| PathBuf::from("."))
164 .join("bunkr_client.toml")
165 }
166}