use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::inbox::IncomingMessageType;
#[derive(Debug, Clone, Default)]
pub struct SendOptions {
pub skip_phone_validation: Option<bool>,
pub device_active_within: Option<u32>,
}
impl SendOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_skip_phone_validation(mut self, val: bool) -> Self {
self.skip_phone_validation = Some(val);
self
}
pub fn with_device_active_within(mut self, hours: u32) -> Self {
self.device_active_within = Some(hours);
self
}
}
impl ToQueryParams for SendOptions {
fn to_query_params(&self) -> Vec<(String, String)> {
let mut params = Vec::new();
if let Some(val) = self.skip_phone_validation {
params.push(("skipPhoneValidation".to_string(), val.to_string()));
}
if let Some(hours) = self.device_active_within {
params.push(("deviceActiveWithin".to_string(), hours.to_string()));
}
params
}
}
#[derive(Debug, Clone, Default)]
pub struct ListInboxOptions {
pub message_type: Option<IncomingMessageType>,
pub limit: Option<i32>,
pub offset: Option<i32>,
pub from: Option<DateTime<Utc>>,
pub to: Option<DateTime<Utc>>,
pub device_id: Option<String>,
pub include_attachments: Option<bool>,
}
impl ListInboxOptions {
pub fn new() -> Self {
Self::default()
}
pub fn validate(&self) -> Result<(), crate::Error> {
if let (Some(ref from), Some(ref to)) = (self.from, self.to) {
if from > to {
return Err(crate::Error::Validation(
"`from` date must be before `to` date".to_string(),
));
}
}
if let Some(limit) = self.limit {
if !(1..=100).contains(&limit) {
return Err(crate::Error::Validation(
"`limit` must be between 1 and 100".to_string(),
));
}
}
if let Some(offset) = self.offset {
if offset < 0 {
return Err(crate::Error::Validation(
"`offset` must be non-negative".to_string(),
));
}
}
Ok(())
}
pub fn with_message_type(mut self, val: IncomingMessageType) -> Self {
self.message_type = Some(val);
self
}
pub fn with_limit(mut self, val: i32) -> Self {
self.limit = Some(val);
self
}
pub fn with_offset(mut self, val: i32) -> Self {
self.offset = Some(val);
self
}
pub fn with_from(mut self, val: DateTime<Utc>) -> Self {
self.from = Some(val);
self
}
pub fn with_to(mut self, val: DateTime<Utc>) -> Self {
self.to = Some(val);
self
}
pub fn with_device_id(mut self, val: impl Into<String>) -> Self {
self.device_id = Some(val.into());
self
}
pub fn with_include_attachments(mut self, val: bool) -> Self {
self.include_attachments = Some(val);
self
}
}
impl ToQueryParams for ListInboxOptions {
fn to_query_params(&self) -> Vec<(String, String)> {
let mut params = Vec::new();
if let Some(ref val) = self.message_type {
let s = serde_json::to_string(val)
.map(|s| s.trim_matches('"').to_string())
.unwrap_or_else(|_| panic!("failed to serialize IncomingMessageType"));
params.push(("type".to_string(), s));
}
if let Some(val) = self.limit {
params.push(("limit".to_string(), val.to_string()));
}
if let Some(val) = self.offset {
params.push(("offset".to_string(), val.to_string()));
}
if let Some(ref val) = self.from {
params.push(("from".to_string(), val.to_rfc3339()));
}
if let Some(ref val) = self.to {
params.push(("to".to_string(), val.to_rfc3339()));
}
if let Some(ref val) = self.device_id {
params.push(("deviceId".to_string(), val.clone()));
}
if let Some(val) = self.include_attachments {
params.push(("includeAttachments".to_string(), val.to_string()));
}
params
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessagesSortOrder {
#[serde(rename = "created_at")]
CreatedAtAscending,
#[serde(rename = "-created_at")]
CreatedAtDescending,
}
#[derive(Debug, Clone, Default)]
pub struct ListMessagesOptions {
pub from: Option<DateTime<Utc>>,
pub to: Option<DateTime<Utc>>,
pub state: Option<String>,
pub device_id: Option<String>,
pub limit: Option<i32>,
pub offset: Option<i32>,
pub include_content: Option<bool>,
pub sort: Option<MessagesSortOrder>,
}
impl ListMessagesOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_from(mut self, val: DateTime<Utc>) -> Self {
self.from = Some(val);
self
}
pub fn with_to(mut self, val: DateTime<Utc>) -> Self {
self.to = Some(val);
self
}
pub fn with_state(mut self, val: impl Into<String>) -> Self {
self.state = Some(val.into());
self
}
pub fn with_device_id(mut self, val: impl Into<String>) -> Self {
self.device_id = Some(val.into());
self
}
pub fn with_limit(mut self, val: i32) -> Self {
self.limit = Some(val);
self
}
pub fn with_offset(mut self, val: i32) -> Self {
self.offset = Some(val);
self
}
pub fn with_include_content(mut self, val: bool) -> Self {
self.include_content = Some(val);
self
}
pub fn with_sort(mut self, val: MessagesSortOrder) -> Self {
self.sort = Some(val);
self
}
pub fn validate(&self) -> Result<(), crate::Error> {
if let (Some(ref from), Some(ref to)) = (self.from, self.to) {
if from > to {
return Err(crate::Error::Validation(
"`from` date must be before `to` date".to_string(),
));
}
}
if let Some(limit) = self.limit {
if !(1..=100).contains(&limit) {
return Err(crate::Error::Validation(
"`limit` must be between 1 and 100".to_string(),
));
}
}
if let Some(offset) = self.offset {
if offset < 0 {
return Err(crate::Error::Validation(
"`offset` must be non-negative".to_string(),
));
}
}
Ok(())
}
}
impl ToQueryParams for ListMessagesOptions {
fn to_query_params(&self) -> Vec<(String, String)> {
let mut params = Vec::new();
if let Some(ref val) = self.from {
params.push(("from".to_string(), val.to_rfc3339()));
}
if let Some(ref val) = self.to {
params.push(("to".to_string(), val.to_rfc3339()));
}
if let Some(ref val) = self.state {
params.push(("state".to_string(), val.clone()));
}
if let Some(ref val) = self.device_id {
params.push(("deviceId".to_string(), val.clone()));
}
if let Some(val) = self.limit {
params.push(("limit".to_string(), val.to_string()));
}
if let Some(val) = self.offset {
params.push(("offset".to_string(), val.to_string()));
}
if let Some(val) = self.include_content {
params.push(("includeContent".to_string(), val.to_string()));
}
if let Some(ref val) = self.sort {
let s = serde_json::to_value(val)
.ok()
.and_then(|v| v.as_str().map(String::from))
.unwrap_or_default();
params.push(("sort".to_string(), s));
}
params
}
}
pub trait ToQueryParams {
fn to_query_params(&self) -> Vec<(String, String)>;
fn to_url_query(&self) -> String {
let pairs = self.to_query_params();
if pairs.is_empty() {
return String::new();
}
let mut serializer = url::form_urlencoded::Serializer::new(String::new());
for (key, value) in &pairs {
serializer.append_pair(key, value);
}
serializer.finish()
}
}