use std::sync::Arc;
use crate::error::Error;
use crate::http::HttpClient;
use crate::types::{
contact_sort_by_to_string, sort_order_to_string, BatchCreateContactsData,
BatchCreateContactsResult, Contact, ContactCreateRequest, ContactListParams, ContactStatus,
ContactUpdateRequest, DeletionResponse, ListResponse, ResourceResponse,
};
#[derive(Clone, Debug)]
pub struct ContactsResource {
http: Arc<HttpClient>,
}
impl ContactsResource {
pub(crate) fn new(http: Arc<HttpClient>) -> Self {
Self { http }
}
pub async fn list(&self, params: ContactListParams) -> Result<ListResponse<Contact>, Error> {
self.http
.get("/api/contacts", Some(contact_query(params)))
.await
}
pub async fn create(&self, input: ContactCreateRequest) -> Result<Contact, Error> {
let response: ResourceResponse<Contact> = self.http.post("/api/contacts", &input).await?;
Ok(response.data)
}
pub async fn create_batch(
&self,
input: Vec<ContactCreateRequest>,
) -> Result<BatchCreateContactsData, Error> {
let response: BatchCreateContactsResult = self.http.post("/api/contacts", &input).await?;
Ok(response.data)
}
pub async fn get(&self, id: impl AsRef<str>) -> Result<Contact, Error> {
let response: ResourceResponse<Contact> = self
.http
.get(&format!("/api/contacts/{}", encode(id.as_ref())), None)
.await?;
Ok(response.data)
}
pub async fn update(
&self,
id: impl AsRef<str>,
input: ContactUpdateRequest,
) -> Result<Contact, Error> {
let response: ResourceResponse<Contact> = self
.http
.patch(&format!("/api/contacts/{}", encode(id.as_ref())), &input)
.await?;
Ok(response.data)
}
pub async fn delete(&self, id: impl AsRef<str>) -> Result<DeletionResponse, Error> {
self.http
.delete(&format!("/api/contacts/{}", encode(id.as_ref())))
.await
}
}
fn contact_query(params: ContactListParams) -> Vec<(&'static str, String)> {
let mut query = Vec::new();
if let Some(value) = params.page {
query.push(("page", value.to_string()));
}
if let Some(value) = params.limit {
query.push(("limit", value.to_string()));
}
if let Some(value) = params.status {
query.push(("status", contact_status_to_string(&value).to_string()));
}
if let Some(value) = params.search {
query.push(("search", value));
}
if let Some(value) = params.external_id {
query.push(("external_id", value));
}
if let Some(value) = params.sort_by {
query.push(("sort_by", contact_sort_by_to_string(&value).to_string()));
}
if let Some(value) = params.sort_order {
query.push(("sort_order", sort_order_to_string(&value).to_string()));
}
query
}
fn contact_status_to_string(value: &ContactStatus) -> &'static str {
match value {
ContactStatus::Active => "active",
ContactStatus::Unsubscribed => "unsubscribed",
ContactStatus::Bounced => "bounced",
ContactStatus::SpamComplaint => "spam_complaint",
ContactStatus::Inactive => "inactive",
}
}
fn encode(value: &str) -> String {
url::form_urlencoded::byte_serialize(value.as_bytes()).collect()
}