use crate::config::Config; use reqwest::blocking::Client; use serde::Deserialize; use std::collections::HashMap; use std::fmt::{self, Display, Formatter}; const TWILIO_BASE_URL: &str = "https://api.twilio.com/2010-04-01/Accounts"; #[derive(Deserialize, Debug)] pub struct Message { pub from: String, pub to: String, pub body: String, } // list of possible values: https://www.twilio.com/docs/sms/api/message-resource#message-status-values #[derive(Debug, Deserialize, Clone)] #[allow(non_camel_case_types)] pub enum MessageStatus { accepted, scheduled, queued, sending, sent, receiving, received, delivered, undelivered, failed, read, canceled, } #[derive(Deserialize, Debug, Clone)] pub struct MessageResponse { pub status: Option, } #[derive(Debug)] pub enum TwilioError { HTTPError(reqwest::StatusCode), } impl Display for TwilioError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { TwilioError::HTTPError(ref s) => write!(f, "Invalid HTTP status code: {}", s), } } } impl Message { pub fn send(&self, config: &Config) -> Result { let url = format!("{}/{}/Messages.json", TWILIO_BASE_URL, config.account_sid); let mut form = HashMap::new(); form.insert("From", &self.from); form.insert("To", &self.to); form.insert("Body", &self.body); let client = Client::new(); let response = client .post(url) .basic_auth(&config.account_sid, Some(&config.auth_token)) .form(&form) .send() .unwrap(); match response.status() { reqwest::StatusCode::CREATED | reqwest::StatusCode::OK => {} other => return Err(TwilioError::HTTPError(other)), }; Ok(response.json().unwrap()) } }