messagebird_async/sms/
notification.rs

1//! Notification via a registered callback from message bird
2//!
3//! Message bird calls a callback url as specified with a certain
4//! set query parameters, virtual mobile number (VMN) and shortcode.
5//! Both are represented here as structs which can be easily deserialized.
6//!
7//! messagebird documentation at
8//! https://developers.messagebird.com/docs/sms-messaging#receive-a-message
9
10// trait CallbackSpecifier {}
11
12// pub struct ShortCode;
13// impl CallbackSpecifier for ShortCode {}
14
15// pub struct VirtualMobileNumber;
16// impl CallbackSpecifier for VirtualMobileNumber {}
17
18use super::*;
19use std::str::FromStr;
20
21#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
22pub struct NotificationQueryVMN {
23    id: String,
24    recipient: Msisdn,
25    originator: Originator,
26    #[serde(rename = "body")]
27    payload: Payload,
28    #[serde(rename = "createdDatetime")]
29    created_datetime: DateTime, // RFC3339 format (Y-m-d\TH:i:sP)
30}
31
32impl FromStr for NotificationQueryVMN {
33    type Err = MessageBirdError;
34    fn from_str(query: &str) -> Result<Self, Self::Err> {
35        serde_qs::from_str(query).map_err(|e| {
36            debug!("{:?}", e);
37            MessageBirdError::ParseError
38        })
39    }
40}
41
42#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
43pub struct NotificationQueryShort {
44    mid: u64,
45    shortcode: String,
46    keyword: String,
47    originator: Originator,
48    operator: u64, //MCCMNC
49    #[serde(rename = "message")]
50    payload: Payload, // The body of the SMS message, including the (sub)keyword.
51    receive_datetime: DateTime, // stamp format YmdHis
52}
53
54impl FromStr for NotificationQueryShort {
55    type Err = MessageBirdError;
56    fn from_str(query: &str) -> Result<Self, Self::Err> {
57        serde_qs::from_str(query).map_err(|e| {
58            debug!("{:?}", e);
59            MessageBirdError::ParseError
60        })
61    }
62}
63
64#[cfg(test)]
65mod test {
66    use super::*;
67
68    mod vmn {
69        use super::*;
70
71        static RAW: &str = r#"http://your-own.url/script?id=e8077d803532c0b5937c639b60216938&recipient=31642500190&originator=31612345678&body=This+is+an+incoming+message&createdDatetime=2016-05-03T14:26:57+00:00"#;
72        #[test]
73        fn de() {
74            let lh = NotificationQueryVMN {
75                id: "e8077d803532c0b5937c639b60216938".to_string(),
76                recipient: Msisdn::try_from(31642500190).unwrap(),
77                originator: 31612345678.into(),
78                payload: Payload::from_str("This is an incoming message").unwrap(),
79                created_datetime: DateTime::from_str("2016-05-03T14:26:57+00:00").unwrap(),
80            };
81
82            let url = Url::parse(RAW).expect("Expected a valid url");
83            // TODO the timestamp is modified due to the `+` sign which is replaced by a space character,
84            // XXX as such parsing with rfc3339 fails
85            let rh =
86                serde_qs::from_str(url.query().unwrap()).expect("Failed to tokenize query string");
87            assert_eq!(lh, rh);
88        }
89    }
90    mod short {
91        use super::*;
92        use crate::sms::DateTime;
93
94        static RAW: &str = r#"http://your-own.url/script?mid=123456789&shortcode=1008&keyword=MESSAGEBIRD&originator=31612345678&operator=20401&message=This+is+an+incoming+message&receive_datetime=20160503142657"#;
95        #[test]
96        fn de() {
97            let lh = NotificationQueryShort {
98                mid: 123456789,
99                shortcode: "1008".to_string(),
100                keyword: "MESSAGEBIRD".to_string(),
101                originator: 31612345678.into(),
102                operator: 20401,
103                payload: Payload::from_str("This is an incoming message").unwrap(),
104                receive_datetime: DateTime::from_str("2016-05-03T14:26:57+00:00").unwrap(),
105            };
106
107            let url = Url::parse(RAW).expect("Expected a valid url");
108            let rh =
109                serde_qs::from_str(url.query().unwrap()).expect("Failed to tokenize query string");
110            assert_eq!(lh, rh);
111        }
112    }
113}