android_sms_gateway/types/
settings.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5pub enum LimitPeriod {
6 #[serde(rename = "Disabled")]
7 Disabled,
8 #[serde(rename = "PerMinute")]
9 PerMinute,
10 #[serde(rename = "Per30Minutes")]
11 Per30Minutes,
12 #[serde(rename = "PerHour")]
13 PerHour,
14 #[serde(rename = "PerDay")]
15 PerDay,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub enum SimSelectionMode {
21 #[serde(rename = "OSDefault")]
22 OSDefault,
23 #[serde(rename = "RoundRobin")]
24 RoundRobin,
25 #[serde(rename = "Random")]
26 Random,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub enum MessagesProcessingOrder {
32 #[serde(rename = "LIFO")]
33 Lifo,
34 #[serde(rename = "FIFO")]
35 Fifo,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct DeviceSettings {
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub encryption: Option<SettingsEncryption>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub messages: Option<SettingsMessages>,
46 #[serde(default, skip_serializing_if = "Option::is_none")]
47 pub ping: Option<SettingsPing>,
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 pub logs: Option<SettingsLogs>,
50 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub webhooks: Option<SettingsWebhooks>,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
53 pub gateway: Option<SettingsGateway>,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub receiver: Option<SettingsReceiver>,
56}
57
58impl DeviceSettings {
59 pub fn validate(&self) -> Result<(), crate::Error> {
60 if let Some(ref messages) = self.messages {
61 messages.validate()?;
62 }
63 Ok(())
64 }
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct SettingsEncryption {
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub passphrase: Option<String>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case")]
77pub struct SettingsMessages {
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub send_interval_min: Option<i32>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub send_interval_max: Option<i32>,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub limit_period: Option<LimitPeriod>,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub limit_value: Option<i32>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub sim_selection_mode: Option<SimSelectionMode>,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub log_lifetime_days: Option<i32>,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 pub processing_order: Option<MessagesProcessingOrder>,
92 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub work_hours_enabled: Option<bool>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 pub work_hours_start: Option<String>,
96 #[serde(default, skip_serializing_if = "Option::is_none")]
97 pub work_hours_end: Option<String>,
98}
99
100impl SettingsMessages {
101 pub fn validate(&self) -> Result<(), crate::Error> {
102 if let (Some(min), Some(max)) = (self.send_interval_min, self.send_interval_max) {
103 if max < min {
104 return Err(crate::Error::Validation(
105 "sendIntervalMax must be greater than or equal to sendIntervalMin".to_string(),
106 ));
107 }
108 }
109
110 if let Some(true) = self.work_hours_enabled {
111 self.validate_work_hours()?;
112 }
113
114 Ok(())
115 }
116
117 fn validate_work_hours(&self) -> Result<(), crate::Error> {
118 let start = self.work_hours_start.as_deref().ok_or_else(|| {
119 crate::Error::Validation(
120 "workHoursStart is required when work hours are enabled".to_string(),
121 )
122 })?;
123
124 let end = self.work_hours_end.as_deref().ok_or_else(|| {
125 crate::Error::Validation(
126 "workHoursEnd is required when work hours are enabled".to_string(),
127 )
128 })?;
129
130 let (h1, m1) = parse_time(start).ok_or_else(|| {
131 crate::Error::Validation(format!(
132 "workHoursStart must be in HH:mm format with valid values, got \"{}\"",
133 start
134 ))
135 })?;
136 let (h2, m2) = parse_time(end).ok_or_else(|| {
137 crate::Error::Validation(format!(
138 "workHoursEnd must be in HH:mm format with valid values, got \"{}\"",
139 end
140 ))
141 })?;
142 let _ = (h1, m1, h2, m2);
143
144 Ok(())
145 }
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct SettingsPing {
151 #[serde(default, skip_serializing_if = "Option::is_none")]
152 pub interval_seconds: Option<i32>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct SettingsLogs {
158 #[serde(default, skip_serializing_if = "Option::is_none")]
159 pub lifetime_days: Option<i32>,
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct SettingsWebhooks {
165 #[serde(default, skip_serializing_if = "Option::is_none")]
166 pub internet_required: Option<bool>,
167 #[serde(default, skip_serializing_if = "Option::is_none")]
168 pub retry_count: Option<i32>,
169 #[serde(default, skip_serializing_if = "Option::is_none")]
170 pub signing_key: Option<String>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct SettingsGateway {
176 #[serde(default, skip_serializing_if = "Option::is_none")]
177 pub cloud_url: Option<String>,
178 #[serde(default, skip_serializing_if = "Option::is_none")]
179 pub private_token: Option<String>,
180 #[serde(default, skip_serializing_if = "Option::is_none")]
181 pub notification_channel: Option<String>,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct SettingsReceiver {
187 #[serde(default, skip_serializing_if = "Option::is_none")]
188 pub content_provider_enabled: Option<bool>,
189}
190
191fn parse_time(s: &str) -> Option<(u8, u8)> {
192 let b = s.as_bytes();
193 if s.len() == 5
194 && b[0].is_ascii_digit()
195 && b[1].is_ascii_digit()
196 && b[2] == b':'
197 && b[3].is_ascii_digit()
198 && b[4].is_ascii_digit()
199 {
200 let h = (b[0] - b'0') * 10 + (b[1] - b'0');
201 let m = (b[3] - b'0') * 10 + (b[4] - b'0');
202 if h <= 23 && m <= 59 {
203 return Some((h, m));
204 }
205 }
206 None
207}