ralertsinua_models/
alert.rs1use crate::{alert_type::*, LocationType};
2use serde::{Deserialize, Serialize};
3use serde_with::{serde_as, skip_serializing_none, DisplayFromStr};
4use time::OffsetDateTime;
5
6#[skip_serializing_none]
7#[serde_as]
8#[derive(Debug, Deserialize, Clone, PartialEq, Serialize)]
9pub struct Alert {
10 pub id: i32,
11 pub location_title: String,
12 #[serde_as(as = "DisplayFromStr")] pub location_type: LocationType,
14 #[serde(with = "time::serde::iso8601")]
15 pub started_at: OffsetDateTime,
16 #[serde(with = "time::serde::iso8601")]
17 pub updated_at: OffsetDateTime,
18 pub finished_at: Option<String>, #[serde_as(as = "DisplayFromStr")] pub alert_type: AlertType,
22 pub location_oblast: String,
23 #[serde(with = "into_int")]
24 pub location_uid: i32,
25 pub location_oblast_uid: i32,
26 pub notes: Option<String>,
27 #[serde(default)]
28 pub country: Option<String>,
29 #[serde(default)]
30 pub calculated: Option<bool>,
31}
32
33pub mod into_int {
34 use super::*;
35 use serde::{de::*, Serializer};
36
37 pub fn serialize<S>(value: &i32, serializer: S) -> Result<S::Ok, S::Error>
38 where
39 S: Serializer,
40 {
41 serializer.serialize_str(&value.to_string())
42 }
43
44 pub fn deserialize<'de, D>(deserializer: D) -> Result<i32, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 let s = String::deserialize(deserializer)?;
49 s.parse::<i32>().map_err(Error::custom)
50 }
51}
52
53impl Alert {
54 pub fn get_alert_duration(&self) -> std::time::Duration {
55 let now = OffsetDateTime::now_utc();
56 let offset_duration = now - self.started_at;
57 offset_duration.try_into().unwrap()
58 }
59}
60
61mod tests {
62
63 #[test]
64 fn test_alert_deserialization() {
65 use super::*;
66 use serde_json::json;
67
68 let data = json!({
69 "alert_type": "air_raid",
70 "calculated": null,
71 "country": null,
72 "finished_at": null,
73 "id": 8757,
74 "location_oblast": "Луганська область",
75 "location_oblast_uid": 16,
76 "location_title": "Луганська область",
77 "location_type": "oblast",
78 "location_uid": "16",
79 "notes": null,
80 "started_at": "2022-04-04T16:45:39.000Z",
81 "updated_at": "2023-10-29T18:22:37.357Z"
82 });
83
84 let alert = serde_json::from_value(data);
85 if alert.is_err() {
86 let err = alert.err().unwrap();
87 panic!("Failed to deserialize Alert: {:?}", err);
88 }
89 let alert: Alert = alert.unwrap();
90
91 assert_eq!(alert.id, 8757);
92 assert_eq!(alert.location_title, "Луганська область");
93 assert_eq!(alert.location_type, LocationType::Oblast);
94 assert_eq!(alert.location_oblast, "Луганська область");
95 assert_eq!(alert.location_uid, 16);
96 assert_eq!(alert.location_oblast_uid, 16);
97 assert_eq!(alert.alert_type, AlertType::AirRaid);
98 assert_eq!(alert.notes, None);
99 assert_eq!(alert.country, None);
100 assert_eq!(alert.calculated, None);
101 assert_eq!(alert.started_at.unix_timestamp(), 1_649_090_739);
102 assert_eq!(alert.updated_at.unix_timestamp(), 1_698_603_757);
103 assert_eq!(alert.finished_at, None);
104 }
105}