sms_client/http/
types.rs

1//! HTTP interface related request/response types.
2
3use serde::{Serialize, Deserialize};
4
5/// HTTP pagination options allow for lazy reading of large sets of data,
6/// for example if thousands of messages have been sent and received from
7/// a phone number it would be impractical to request all of them at the
8/// same time, instead it can be read in shorter pages using limit+offset.
9/// This is applied at the server level when requesting data from database.
10#[derive(Serialize, PartialEq, Default, Debug, Clone, Copy)]
11pub struct HttpPaginationOptions {
12
13    /// The maximum amount of return values.
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub limit: Option<u64>,
16
17    /// The offset in index to start getting values from.
18    /// Eg, if the limit was 5, and you want to view page 2,
19    /// the offset would be 5, then 10, 15, ...
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub offset: Option<u64>,
22
23    /// Should return values be reversed? This is useful for getting the
24    /// first results from a large set without having to know it's size.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub reverse: Option<bool>
27}
28impl HttpPaginationOptions {
29
30    /// Set the limit/page size.
31    pub fn with_limit(mut self, limit: u64) -> Self {
32        self.limit = Some(limit);
33        self
34    }
35
36    /// Set request position offset.
37    pub fn with_offset(mut self, offset: u64) -> Self {
38        self.offset = Some(offset);
39        self
40    }
41
42    /// Set the reverse state for options.
43    pub fn with_reverse(mut self, reverse: bool) -> Self {
44        self.reverse = Some(reverse);
45        self
46    }
47
48    /// Add pagination options to a json Value.
49    pub fn add_to_body(&self, body: &mut serde_json::Value) {
50        if let Some(limit) = self.limit {
51            body["limit"] = serde_json::json!(limit);
52        }
53        if let Some(offset) = self.offset {
54            body["offset"] = serde_json::json!(offset);
55        }
56        if let Some(reverse) = self.reverse {
57            body["reverse"] = serde_json::json!(reverse);
58        }
59    }
60}
61
62/// The outgoing SMS message to be sent to a target number.
63#[derive(Serialize, PartialEq, Default, Debug, Clone)]
64pub struct HttpOutgoingSmsMessage {
65
66    /// The target phone number, this should be in international format.
67    pub to: String,
68
69    /// The full message content. This will be split into multiple messages
70    /// by the server if required. This also supports Unicode emojis etc.
71    pub content: String,
72
73    /// The relative validity period to use for message sending. This determines
74    /// how long the message should remain waiting while undelivered.
75    /// By default, this is determined by the server (24 hours).
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub validity_period: Option<u8>,
78
79    /// Should the SMS message be sent as a Silent class? This makes a popup
80    /// show on the users device with the message content if they're logged in.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub flash: Option<bool>,
83
84    /// A timeout that should be applied to the entire request.
85    /// If one is not set, the default timeout is used.
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub timeout: Option<u32>
88}
89impl HttpOutgoingSmsMessage {
90
91    /// Create a new outgoing message with a default validity period and no flash.
92    /// The default validity period is applied by SMS-API, so usually 24 hours.
93    pub fn simple_message(
94        to: impl Into<String>,
95        content: impl Into<String>
96    ) -> Self {
97        Self {
98            to: to.into(),
99            content: content.into(),
100            ..Default::default()
101        }
102    }
103
104    /// Set the message flash state. This will show a popup if the recipient is
105    /// logged-in to their phone, otherwise as a normal text message.
106    pub fn with_flash(mut self, flash: bool) -> Self {
107        self.flash = Some(flash);
108        self
109    }
110
111    /// Set a relative validity period value.
112    pub fn with_validity_period(mut self, period: u8) -> Self {
113        self.validity_period = Some(period);
114        self
115    }
116
117    /// Set a request timeout value.
118    pub fn with_timeout(mut self, timeout: u32) -> Self {
119        self.timeout = Some(timeout);
120        self
121    }
122}
123
124/// Response returned after sending an SMS message.
125#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
126pub struct HttpSmsSendResponse {
127
128    /// The unique ID assigned to the already sent message.
129    pub message_id: i64,
130
131    /// Reference ID for tracking the message.
132    pub reference_id: u8
133}
134
135/// Delivery report for an already sent SMS message.
136#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
137pub struct HttpSmsDeliveryReport {
138
139    /// Unique identifier for this delivery report.
140    pub report_id: Option<i64>,
141
142    /// Delivery status code from the network.
143    pub status: u8,
144
145    /// Whether this is the final delivery report for the message.
146    pub is_final: bool,
147
148    /// Unix timestamp when this report was created.
149    pub created_at: Option<u32>
150}
151
152/// Network registration status of the modem.
153#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
154pub struct HttpModemNetworkStatusResponse {
155
156    /// Registration status code (0=not registered, 1=registered home, 5=registered roaming).
157    pub registration: u8,
158
159    /// Network technology in use (e.g., 2G, 3G, 4G).
160    pub technology: u8
161}
162
163/// Signal strength information from the modem.
164#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
165pub struct HttpModemSignalStrengthResponse {
166
167    /// Received Signal Strength Indicator (0-31, 99=unknown).
168    pub rssi: u8,
169
170    /// Bit Error Rate (0-7, 99=unknown).
171    pub ber: u8
172}
173
174/// Network operator information from the modem.
175#[derive(Deserialize, PartialEq, Debug, Clone)]
176pub struct HttpModemNetworkOperatorResponse {
177
178    /// Operator selection status (0=automatic, 1=manual).
179    pub status: u8,
180
181    /// Format of the operator name (0=long alphanumeric, 1=short alphanumeric, 2=numeric).
182    pub format: u8,
183
184    /// Name or code of the network operator.
185    pub operator: String
186}
187
188/// Battery status information from the modem.
189#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
190pub struct HttpModemBatteryLevelResponse {
191
192    /// Battery status (0=not charging, 1=charging, 2=no battery).
193    pub status: u8,
194
195    /// Battery charge level percentage (0-100).
196    pub charge: u8,
197
198    /// Battery voltage in volts.
199    pub voltage: f32
200}
201
202/// Combine an outgoing message and send response into a dummy SmsStoredMessage.
203impl From<(HttpOutgoingSmsMessage, HttpSmsSendResponse)> for crate::types::SmsStoredMessage {
204    fn from(value: (HttpOutgoingSmsMessage, HttpSmsSendResponse)) -> crate::types::SmsStoredMessage {
205        crate::types::SmsStoredMessage {
206            message_id: value.1.message_id,
207            phone_number: value.0.to,
208            message_content: value.0.content,
209            message_reference: Some(value.1.reference_id),
210            is_outgoing: true,
211            status: "Unknown".to_string(),
212            created_at: None,
213            completed_at: None
214        }
215    }
216}
217
218/// The raw DeviceInfoResponse with raw values.
219#[derive(Deserialize, PartialEq, Debug, Clone)]
220pub struct HttpSmsDeviceInfoResponse {
221
222    /// SMS API version string, including features.
223    pub version: String,
224
225    /// The phone number associated with the SMS device
226    pub phone_number: Option<String>,
227
228    /// The name of the cellular service provider
229    pub service_provider: Option<String>,
230
231    /// Network operator information as (code1, code2, operator_name)
232    pub network_operator: Option<(u8, u8, String)>,
233
234    /// Current network connection status as (status_code, strength_indicator)
235    pub network_status: Option<(u8, u8)>,
236
237    /// Battery information as (level_percentage, charging_status, voltage)
238    pub battery: Option<(u8, u8, f32)>,
239
240    /// Signal strength information as (strength_level, quality_indicator)
241    pub signal: Option<(u8, u8)>
242}
243
244/// Formatted device info response, with each value packed into a proper optional response.
245#[derive(Deserialize, PartialEq, Debug, Clone)]
246pub struct HttpSmsDeviceInfoData {
247
248    /// SMS API version string, including features.
249    pub version: String,
250
251    /// The phone number associated with the SMS device
252    pub phone_number: Option<String>,
253
254    /// The name of the cellular service provider
255    pub service_provider: Option<String>,
256
257    /// Detailed network operator information and capabilities
258    pub network_operator: Option<HttpModemNetworkOperatorResponse>,
259
260    /// Current network connection status and diagnostics
261    pub network_status: Option<HttpModemNetworkStatusResponse>,
262
263    /// Battery level, charging state, and power metrics
264    pub battery: Option<HttpModemBatteryLevelResponse>,
265
266    /// Signal strength measurements and quality indicators
267    pub signal: Option<HttpModemSignalStrengthResponse>
268}
269impl From<HttpSmsDeviceInfoResponse> for HttpSmsDeviceInfoData {
270    fn from(value: HttpSmsDeviceInfoResponse) -> HttpSmsDeviceInfoData {
271        HttpSmsDeviceInfoData {
272            version: value.version,
273            phone_number: value.phone_number,
274            service_provider: value.service_provider,
275            network_operator: value.network_operator.map(|v|
276                HttpModemNetworkOperatorResponse {
277                    status: v.0, format: v.1, operator: v.2
278                }
279            ),
280            network_status: value.network_status.map(|v|
281                HttpModemNetworkStatusResponse {
282                    registration: v.0, technology: v.1
283                }
284            ),
285            battery: value.battery.map(|v|
286                HttpModemBatteryLevelResponse {
287                    status: v.0, charge: v.1, voltage: v.2
288                }
289            ),
290            signal: value.signal.map(|v|
291                HttpModemSignalStrengthResponse {
292                    rssi: v.0, ber: v.1
293                }
294            ),
295        }
296    }
297}
298
299/// Used in latest-numbers return value, as a number and friendly name.
300pub type LatestNumberFriendlyNamePair = (String, Option<String>);