1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use crate::{Client, FromMap, TwilioError, POST};
use serde::Deserialize;
use std::collections::BTreeMap;

pub struct OutboundCall<'a> {
    pub from: &'a str,
    pub to: &'a str,
    pub url: &'a str,
}

impl<'a> OutboundCall<'a> {
    pub fn new(from: &'a str, to: &'a str, url: &'a str) -> OutboundCall<'a> {
        OutboundCall { from, to, url }
    }
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CallStatus {
    Queued,
    Ringing,
    InProgress,
    Canceled,
    Completed,
    Failed,
    Busy,
    NoAnswer,
}

#[derive(Debug, Deserialize)]
pub struct Call {
    from: String,
    to: String,
    sid: String,
    status: CallStatus,
}

impl Client {
    pub async fn make_call(&self, call: OutboundCall<'_>) -> Result<Call, TwilioError> {
        let opts = [
            ("To", &*call.to),
            ("From", &*call.from),
            ("Url", &*call.url),
        ];
        self.send_request(POST, "Calls", &opts).await
    }
}

impl FromMap for Call {
    fn from_map(mut m: BTreeMap<String, String>) -> Result<Box<Call>, TwilioError> {
        let from = match m.remove("From") {
            Some(v) => v,
            None => return Err(TwilioError::ParsingError),
        };
        let to = match m.remove("To") {
            Some(v) => v,
            None => return Err(TwilioError::ParsingError),
        };
        let sid = match m.remove("CallSid") {
            Some(v) => v,
            None => return Err(TwilioError::ParsingError),
        };
        let stat = match m.get("CallStatus").map(|s| s.as_str()) {
            Some("queued") => CallStatus::Queued,
            Some("ringing") => CallStatus::Ringing,
            Some("in-progress") => CallStatus::InProgress,
            Some("canceled") => CallStatus::Canceled,
            Some("completed") => CallStatus::Completed,
            Some("failed") => CallStatus::Failed,
            Some("busy") => CallStatus::Busy,
            Some("no-answer") => CallStatus::NoAnswer,
            _ => return Err(TwilioError::ParsingError),
        };
        Ok(Box::new(Call {
            from,
            to,
            sid,
            status: stat,
        }))
    }
}