use std::fmt;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use strum_macros::{AsRefStr, Display, EnumIter, EnumString};
use crate::{participant_conversation::ParticipantConversations, Client, PageMeta, TwilioError};
pub struct Conversations<'a> {
pub client: &'a Client,
}
#[allow(dead_code)]
#[derive(Deserialize)]
pub struct ConversationPage {
conversations: Vec<Conversation>,
meta: PageMeta,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Conversation {
pub sid: String,
pub account_sid: String,
pub chat_service_sid: String,
pub messaging_service_sid: Option<String>,
pub unique_name: Option<String>,
pub friendly_name: Option<String>,
pub date_created: String,
pub date_updated: String,
pub state: Option<State>,
pub url: String,
pub attributes: String,
pub timers: Option<Timers>,
pub links: Links,
}
impl fmt::Display for Conversation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} - {}",
self.sid,
self.state.as_ref().map_or("None", |s| s.as_ref())
)
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all(serialize = "PascalCase"))]
pub struct UpdateConversation {
pub unique_name: Option<String>,
pub friendly_name: Option<String>,
pub state: Option<State>,
pub attributes: Option<String>,
pub timers: Option<Timers>,
}
#[derive(
AsRefStr,
Clone,
Display,
Default,
Debug,
EnumIter,
EnumString,
Serialize,
Deserialize,
PartialEq,
)]
#[serde(rename_all = "lowercase")]
pub enum State {
#[default]
#[strum(to_string = "Active")]
Active,
#[strum(to_string = "Inactive")]
Inactive,
#[strum(to_string = "Closed")]
Closed,
}
impl State {
pub fn as_str(&self) -> &'static str {
match self {
State::Active => "active",
State::Inactive => "inactive",
State::Closed => "closed",
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
pub struct Timers {
#[serde(rename(serialize = "Timers.Inactive"))]
pub date_inactive: Option<String>,
#[serde(rename(serialize = "Timers.Closed"))]
pub date_closed: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
pub struct Links {
pub participants: String,
pub messages: String,
pub webhooks: String,
}
#[derive(Serialize)]
#[serde(rename_all(serialize = "PascalCase"))]
pub struct ListParams {
pub start_date: Option<String>,
pub end_date: Option<String>,
pub state: Option<State>,
}
impl Conversations<'_> {
pub async fn get(&self, sid: &str) -> Result<Conversation, TwilioError> {
self.client
.send_request::<Conversation, ()>(
Method::GET,
&format!("https://conversations.twilio.com/v1/Conversations/{}", sid),
None,
None,
)
.await
}
pub async fn list(
&self,
start_date: Option<chrono::NaiveDate>,
end_date: Option<chrono::NaiveDate>,
state: Option<State>,
) -> Result<Vec<Conversation>, TwilioError> {
let params = ListParams {
start_date: start_date.map(|start_date| start_date.to_string()),
end_date: end_date.map(|end_date| end_date.to_string()),
state,
};
let mut conversations_page = self
.client
.send_request::<ConversationPage, ListParams>(
Method::GET,
"https://conversations.twilio.com/v1/Conversations",
Some(¶ms),
None,
)
.await?;
let mut results: Vec<Conversation> = conversations_page.conversations;
while (conversations_page.meta.next_page_url).is_some() {
conversations_page = self
.client
.send_request::<ConversationPage, ()>(
Method::GET,
&conversations_page.meta.next_page_url.unwrap(),
None,
None,
)
.await?;
results.append(&mut conversations_page.conversations);
}
Ok(results)
}
pub async fn update(
&self,
sid: &str,
updates: UpdateConversation,
) -> Result<Conversation, TwilioError> {
self.client
.send_request::<Conversation, UpdateConversation>(
Method::POST,
&format!("https://conversations.twilio.com/v1/Conversations/{}", sid),
Some(&updates),
None,
)
.await
}
pub async fn delete(&self, sid: &str) -> Result<(), TwilioError> {
self.client
.send_request_and_ignore_response::<()>(
Method::DELETE,
&format!("https://conversations.twilio.com/v1/Conversations/{}", sid),
None,
None,
)
.await
}
pub fn participant_conversations(&self) -> ParticipantConversations {
ParticipantConversations {
client: self.client,
}
}
}