cloudpub_client/
options.rs

1use crate::config::{ClientConfig, MaskedString, Platform};
2use anyhow::{bail, Context, Result};
3use std::str::FromStr;
4
5macro_rules! config_options {
6    ($(
7        $variant:ident => $key:literal,
8        get: $getter:expr,
9        set: $setter:expr
10    ),* $(,)?) => {
11        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
12        pub enum ConfigOption {
13            $($variant,)*
14        }
15
16        impl ConfigOption {
17            pub fn all() -> &'static [Self] {
18                &[$(Self::$variant,)*]
19            }
20
21            pub fn as_str(&self) -> &'static str {
22                match self {
23                    $(Self::$variant => $key,)*
24                }
25            }
26
27
28            pub fn get_value(&self, config: &ClientConfig) -> Result<String> {
29                match self {
30                    $(Self::$variant => $getter(config),)*
31                }
32            }
33
34            pub fn set_value(&self, config: &mut ClientConfig, value: &str) -> Result<()> {
35                match self {
36                    $(Self::$variant => $setter(config, value)?,)*
37                }
38                Ok(())
39            }
40        }
41
42        impl FromStr for ConfigOption {
43            type Err = anyhow::Error;
44
45            fn from_str(s: &str) -> Result<Self, Self::Err> {
46                match s {
47                    $($key => Ok(Self::$variant),)*
48                    _ => bail!("Unknown config option: {}", s),
49                }
50            }
51        }
52    };
53}
54
55config_options! {
56    Server => "server",
57    get: |config: &ClientConfig| Ok(config.server.to_string()),
58    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
59        config.server = value.parse().context("Invalid server URL")?;
60        Ok(())
61    },
62
63    Token => "token",
64    get: |config: &ClientConfig| Ok(config.token.as_ref().map_or("".to_string(), |t| t.to_string())),
65    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
66        config.token = Some(MaskedString::from(value));
67        Ok(())
68    },
69
70    Hwid => "hwid",
71    get: |config: &ClientConfig| Ok(config.get_hwid()),
72    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
73        config.hwid = Some(value.to_string());
74        Ok(())
75    },
76
77    HeartbeatTimeout => "heartbeat_timeout",
78    get: |config: &ClientConfig| Ok(config.heartbeat_timeout.to_string()),
79    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
80        config.heartbeat_timeout = value.parse().context("Invalid heartbeat_timeout")?;
81        Ok(())
82    },
83
84    OneCHome => "1c_home",
85    get: |config: &ClientConfig| Ok(config.one_c_home.clone().unwrap_or_default()),
86    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
87        config.one_c_home = if value.is_empty() { None } else { Some(value.to_string()) };
88        Ok(())
89    },
90
91    OneCPlatform => "1c_platform",
92    get: |config: &ClientConfig| Ok(config.one_c_platform.as_ref().map(|p| p.to_string()).unwrap_or_default()),
93    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
94        config.one_c_platform = if value.is_empty() {
95            None
96        } else {
97            Some(value.parse::<Platform>().context("Invalid platform")?)
98        };
99        Ok(())
100    },
101
102    OneCPublishDir => "1c_publish_dir",
103    get: |config: &ClientConfig| Ok(config.one_c_publish_dir.clone().unwrap_or_default()),
104    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
105        config.one_c_publish_dir = if value.is_empty() { None } else { Some(value.to_string()) };
106        Ok(())
107    },
108
109    MinecraftServer => "minecraft_server",
110    get: |config: &ClientConfig| Ok(config.minecraft_server.clone().unwrap_or_default()),
111    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
112        config.minecraft_server = if value.is_empty() { None } else { Some(value.to_string()) };
113        Ok(())
114    },
115
116    MinecraftJavaOpts => "minecraft_java_opts",
117    get: |config: &ClientConfig| Ok(config.minecraft_java_opts.clone().unwrap_or_default()),
118    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
119        config.minecraft_java_opts = if value.is_empty() { None } else { Some(value.to_string()) };
120        Ok(())
121    },
122
123    MinimizeToTrayOnClose => "minimize_to_tray_on_close",
124    get: |config: &ClientConfig| Ok(config.minimize_to_tray_on_close.map_or("false".to_string(), |v| v.to_string())),
125    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
126        config.minimize_to_tray_on_close = Some(value.parse().context("Invalid boolean value")?);
127        Ok(())
128    },
129
130    MinimizeToTrayOnStart => "minimize_to_tray_on_start",
131    get: |config: &ClientConfig| Ok(config.minimize_to_tray_on_start.map_or("false".to_string(), |v| v.to_string())),
132    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
133        config.minimize_to_tray_on_start = Some(value.parse().context("Invalid boolean value")?);
134        Ok(())
135    },
136
137    UnsafeTls => "unsafe_tls",
138    get: |config: &ClientConfig| Ok(config.transport.tls.as_ref().map_or("".to_string(), |tls| {
139        tls.danger_ignore_certificate_verification.map_or("".to_string(), |v| v.to_string())
140    })),
141    set: |config: &mut ClientConfig, value: &str| -> Result<(), anyhow::Error> {
142        let allow = value.parse().context("Invalid boolean value")?;
143        if config.transport.tls.is_none() {
144            config.transport.tls = Some(Default::default());
145        }
146        if let Some(tls) = config.transport.tls.as_mut() {
147            tls.danger_ignore_certificate_verification = Some(allow);
148        }
149        Ok(())
150    },
151}
152
153impl ClientConfig {
154    pub fn get_option(&self, option: ConfigOption) -> Result<String> {
155        option.get_value(self)
156    }
157
158    pub fn set_option(&mut self, option: ConfigOption, value: &str) -> Result<()> {
159        option.set_value(self, value)?;
160        self.save()
161    }
162
163    pub fn get_all_config_options(&self) -> Vec<(String, String)> {
164        ConfigOption::all()
165            .iter()
166            .filter_map(|&option| {
167                option
168                    .get_value(self)
169                    .ok()
170                    .map(|value| (option.as_str().to_string(), value))
171            })
172            .collect()
173    }
174}