1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct DdnsConfig {
8 #[serde(default)]
10 pub enabled: bool,
11
12 #[serde(default = "default_ddns_interval")]
14 pub interval: u64,
15
16 #[serde(default = "default_ipv4_urls")]
18 pub ipv4_urls: Vec<String>,
19
20 #[serde(default)]
22 pub ipv6_urls: Vec<String>,
23
24 #[serde(default)]
26 pub cloudflare: Option<CloudflareDdnsConfig>,
27}
28
29impl Default for DdnsConfig {
30 fn default() -> Self {
31 Self {
32 enabled: false,
33 interval: default_ddns_interval(),
34 ipv4_urls: default_ipv4_urls(),
35 ipv6_urls: Vec::new(),
36 cloudflare: None,
37 }
38 }
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct CloudflareDdnsConfig {
44 pub api_token: String,
46
47 pub zone: String,
49
50 pub records: Vec<String>,
52
53 #[serde(default)]
55 pub proxied: bool,
56
57 #[serde(default = "default_ddns_ttl")]
59 pub ttl: u32,
60}
61
62fn default_ddns_interval() -> u64 {
63 300
64}
65
66fn default_ddns_ttl() -> u32 {
67 1
68}
69
70fn default_ipv4_urls() -> Vec<String> {
71 vec![
72 "https://api.ipify.org".into(),
73 "https://ifconfig.me/ip".into(),
74 "https://ip.sb".into(),
75 ]
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn ddns_config_default() {
84 let cfg = DdnsConfig::default();
85 assert!(!cfg.enabled);
86 assert_eq!(cfg.interval, 300);
87 assert!(!cfg.ipv4_urls.is_empty());
88 assert!(cfg.ipv6_urls.is_empty());
89 assert!(cfg.cloudflare.is_none());
90 }
91
92 #[test]
93 fn ddns_config_deserialize_minimal() {
94 let toml_str = r#"enabled = true"#;
95 let cfg: DdnsConfig = toml::from_str(toml_str).unwrap();
96 assert!(cfg.enabled);
97 assert_eq!(cfg.interval, 300);
98 assert_eq!(cfg.ipv4_urls.len(), 3);
99 }
100
101 #[test]
102 fn ddns_config_deserialize_full() {
103 let toml_str = r#"
104enabled = true
105interval = 600
106ipv4_urls = ["https://api.ipify.org"]
107
108[cloudflare]
109api_token = "test-token"
110zone = "example.com"
111records = ["example.com", "*.example.com"]
112proxied = true
113ttl = 300
114"#;
115 let cfg: DdnsConfig = toml::from_str(toml_str).unwrap();
116 assert!(cfg.enabled);
117 assert_eq!(cfg.interval, 600);
118 assert_eq!(cfg.ipv4_urls, vec!["https://api.ipify.org"]);
119 let cf = cfg.cloudflare.unwrap();
120 assert_eq!(cf.api_token, "test-token");
121 assert_eq!(cf.zone, "example.com");
122 assert_eq!(cf.records, vec!["example.com", "*.example.com"]);
123 assert!(cf.proxied);
124 assert_eq!(cf.ttl, 300);
125 }
126}