use crate::{Client, PageMeta, TwilioError};
use reqwest::{header::HeaderMap, Method};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_with::skip_serializing_none;
#[allow(dead_code)]
#[derive(Deserialize)]
pub struct ListItemPage {
items: Vec<SyncListItem>,
meta: PageMeta,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SyncListItem {
pub index: u32,
pub account_sid: String,
pub service_sid: String,
pub list_sid: String,
pub url: String,
pub data: Value,
pub date_created: String,
pub date_updated: String,
pub date_expires: Option<String>,
pub created_by: String,
pub revision: String,
}
pub struct CreateParams<'a, T>
where
T: ?Sized + Serialize,
{
pub data: &'a T,
pub ttl: Option<u16>,
pub collection_ttl: Option<u16>,
}
#[skip_serializing_none]
#[derive(Serialize)]
#[serde(rename_all(serialize = "PascalCase"))]
struct CreateParamsWithJson {
data: String,
ttl: Option<u16>,
collection_ttl: Option<u16>,
}
#[derive(Serialize)]
pub enum Order {
Asc,
Desc,
}
#[derive(Serialize)]
pub enum Bounds {
Inclusive,
Exclusive,
}
#[skip_serializing_none]
#[derive(Serialize)]
#[serde(rename_all(serialize = "PascalCase"))]
pub struct ListParams {
pub order: Option<Order>,
pub from: Option<String>,
pub bounds: Option<Bounds>,
}
pub struct UpdateParams<'a, T>
where
T: ?Sized + Serialize,
{
pub if_match: Option<String>,
pub data: &'a T,
pub ttl: Option<u16>,
pub collection_ttl: Option<u16>,
}
#[skip_serializing_none]
#[derive(Serialize)]
#[serde(rename_all(serialize = "PascalCase"))]
struct UpdateParamsWithJson {
#[serde(rename(serialize = "If-Match"))]
if_match: Option<String>,
data: String,
ttl: Option<u16>,
collection_ttl: Option<u16>,
}
pub struct ListItems<'a, 'b> {
pub client: &'a Client,
pub service_sid: &'b str,
pub list_sid: &'b str,
}
impl ListItems<'_, '_> {
pub async fn create<T>(&self, params: CreateParams<'_, T>) -> Result<SyncListItem, TwilioError>
where
T: ?Sized + Serialize,
{
let params = CreateParamsWithJson {
data: serde_json::to_string(params.data)
.expect("Unable to convert provided data value to a JSON string"),
ttl: params.ttl,
collection_ttl: params.collection_ttl,
};
self.client
.send_request::<SyncListItem, CreateParamsWithJson>(
Method::POST,
&format!(
"https://sync.twilio.com/v1/Services/{}/Lists/{}/Items",
self.service_sid, self.list_sid
),
Some(¶ms),
None,
)
.await
}
pub async fn list(&self, params: ListParams) -> Result<Vec<SyncListItem>, TwilioError> {
let mut list_items_page = self
.client
.send_request::<ListItemPage, ListParams>(
Method::GET,
&format!(
"https://sync.twilio.com/v1/Services/{}/Lists/{}/Items?PageSize=50",
self.service_sid, self.list_sid
),
Some(¶ms),
None,
)
.await?;
let mut results: Vec<SyncListItem> = list_items_page.items;
while (list_items_page.meta.next_page_url).is_some() {
list_items_page = self
.client
.send_request::<ListItemPage, ListParams>(
Method::GET,
&list_items_page.meta.next_page_url.unwrap(),
None,
None,
)
.await?;
results.append(&mut list_items_page.items);
}
Ok(results)
}
}
pub struct ListItem<'a, 'b> {
pub client: &'a Client,
pub service_sid: &'b str,
pub list_sid: &'b str,
pub index: &'b u32,
}
impl ListItem<'_, '_> {
pub async fn get(&self) -> Result<SyncListItem, TwilioError> {
self.client
.send_request::<SyncListItem, ()>(
Method::GET,
&format!(
"https://sync.twilio.com/v1/Services/{}/Lists/{}/Items/{}",
self.service_sid, self.list_sid, self.index
),
None,
None,
)
.await
}
pub async fn update<T>(&self, params: UpdateParams<'_, T>) -> Result<SyncListItem, TwilioError>
where
T: ?Sized + Serialize,
{
let params = UpdateParamsWithJson {
if_match: params.if_match,
data: serde_json::to_string(params.data)
.expect("Unable to convert provided data value to a JSON string"),
ttl: params.ttl,
collection_ttl: params.collection_ttl,
};
let mut headers = HeaderMap::new();
if let Some(if_match) = params.if_match.clone() {
headers.append("If-Match", if_match.parse().unwrap());
}
self.client
.send_request::<SyncListItem, UpdateParamsWithJson>(
Method::POST,
&format!(
"https://sync.twilio.com/v1/Services/{}/Lists/{}/Items/{}",
self.service_sid, self.list_sid, self.index
),
Some(¶ms),
Some(headers),
)
.await
}
pub async fn delete(&self) -> Result<(), TwilioError> {
self.client
.send_request_and_ignore_response::<()>(
Method::DELETE,
&format!(
"https://sync.twilio.com/v1/Services/{}/Lists/{}/Items/{}",
self.service_sid, self.list_sid, self.index
),
None,
None,
)
.await
}
}