Skip to main content

mailchimp/types/
conversations.rs

1//! Conversations
2//!
3
4use super::conversation_messages::{
5    CollectionConversationMessages, ConversationMessage, MessagesBuider, MessagesFilter,
6};
7use serde::{Deserialize, Serialize};
8use std::rc::Rc;
9
10use super::link::LinkType;
11use crate::api::MailchimpApi;
12use crate::internal::request::MailchimpResult;
13use crate::iter::{BuildIter, MailchimpCollection, MalchimpIter, ResourceFilter};
14use log::error;
15use std::collections::HashMap;
16
17///
18/// Conversation tracking is a paid feature that lets you view subscribers’
19/// replies to your campaigns in your Mailchimp account.
20///
21#[derive(Serialize, Deserialize, Debug, Clone)]
22pub struct Conversation {
23    /// A string that uniquely identifies this conversation.
24    #[serde(default)]
25    pub id: String,
26    /// The total number of messages in this conversation.
27    #[serde(default)]
28    pub message_count: u64,
29    /// The unique identifier of the campaign for this conversation.
30    #[serde(default)]
31    pub campaign_id: String,
32    /// The unique identifier of the list for this conversation.
33    #[serde(default)]
34    pub list_id: String,
35    /// The number of unread messages in this conversation.
36    #[serde(default)]
37    pub unread_messages: u64,
38    /// A label representing the sender of this message.
39    #[serde(default)]
40    pub from_label: String,
41    /// A label representing the email of the sender of this message.
42    #[serde(default)]
43    pub from_email: String,
44    /// The subject of the message.
45    #[serde(default)]
46    pub subject: String,
47    /// The most recent message in the conversation.
48    #[serde(default)]
49    pub last_message: ConversationMessage,
50    /// A list of link types and descriptions for the API schema documents.
51    #[serde(default)]
52    pub _links: Vec<LinkType>,
53
54    /// Mailchimp API
55    #[serde(skip)]
56    _api: Rc<MailchimpApi>,
57}
58
59///
60/// Param Message
61///
62#[derive(Serialize, Deserialize, Debug, Clone)]
63pub struct ParamMessage {
64    /// A label representing the email of the sender of this message
65    #[serde(default)]
66    pub from_email: String,
67    /// The subject of this message.
68    #[serde(default)]
69    pub subject: String,
70    /// The plain-text content of the message.
71    #[serde(default)]
72    pub message: String,
73    /// Whether this message has been marked as read.
74    #[serde(default)]
75    pub read: bool,
76}
77
78impl Conversation {
79    ///
80    /// Post a new message to a conversation.
81    ///
82    pub fn create_message(&self, message: ParamMessage) -> MailchimpResult<ConversationMessage> {
83        // POST /conversations/{conversation_id}/messages
84        let mut endpoint = self.get_base_endpoint();
85        endpoint.push_str("/messages");
86        self._api
87            .post::<ConversationMessage, ParamMessage>(&endpoint, message)
88    }
89
90    ///
91    /// Get conversation messages
92    ///
93    pub fn get_conversation_messages(
94        &self,
95        filter: Option<MessagesFilter>,
96    ) -> MalchimpIter<MessagesBuider> {
97        // GET  /conversations/{conversation_id}/messages
98        let mut endpoint = self.get_base_endpoint();
99        endpoint.push_str("/messages");
100
101        let mut filter_params = MessagesFilter::default();
102
103        if let Some(f) = filter {
104            filter_params = f;
105        }
106
107        match self
108            ._api
109            .get::<CollectionConversationMessages>(&endpoint, filter_params.build_payload())
110        {
111            Ok(collection) => MalchimpIter {
112                builder: MessagesBuider {},
113                data: collection.conversation_messages,
114                cur_filters: filter_params.clone(),
115                cur_it: 0,
116                total_items: collection.total_items,
117                api: self._api.clone(),
118                endpoint: endpoint.to_string(),
119            },
120            Err(e) => {
121                error!( target: "mailchimp",  "Get Activities: Response Error details: {:?}", e);
122                MalchimpIter {
123                    builder: MessagesBuider {},
124                    data: Vec::new(),
125                    cur_filters: filter_params.clone(),
126                    cur_it: 0,
127                    total_items: 0,
128                    api: self._api.clone(),
129                    endpoint: endpoint.to_string(),
130                }
131            }
132        }
133    }
134
135    ///
136    /// Get a specific conversation message
137    ///
138    pub fn get_conversation_message<'a>(
139        &self,
140        message_id: &'a str,
141    ) -> MailchimpResult<ConversationMessage> {
142        let mut endpoint = self.get_base_endpoint();
143        endpoint.push_str("/messages/");
144        endpoint.push_str(message_id);
145
146        let mut payload = HashMap::new();
147        payload.insert("message_id".to_string(), message_id.to_string());
148        self._api.get::<ConversationMessage>(&endpoint, payload)
149    }
150    ///
151    /// Update API
152    ///
153    pub fn set_api(&mut self, n_api: Rc<MailchimpApi>) {
154        self._api = n_api;
155    }
156
157    fn get_base_endpoint(&self) -> String {
158        let mut endpoint = "conversations/".to_string();
159        endpoint.push_str(&self.id);
160        endpoint
161    }
162}
163
164///
165/// Collection Conversations
166///
167#[derive(Serialize, Deserialize, Debug, Clone)]
168pub struct CollectionConversations {
169    /// Recent list activity.
170    #[serde(default)]
171    pub conversations: Vec<Conversation>,
172    /// The total number of items matching the query regardless of pagination.
173    #[serde(default)]
174    pub total_items: u64,
175    /// A list of link types and descriptions for the API schema documents.
176    #[serde(default)]
177    pub _links: Vec<LinkType>,
178}
179
180impl MailchimpCollection<Conversation> for CollectionConversations {
181    /// Total Items
182    fn get_total_items(&self) -> u64 {
183        self.total_items
184    }
185
186    /// Data
187    fn get_values(&self) -> Vec<Conversation> {
188        self.conversations.clone()
189    }
190}
191
192impl Default for CollectionConversations {
193    fn default() -> Self {
194        CollectionConversations {
195            conversations: Vec::new(),
196            total_items: 0,
197            _links: Vec::new(),
198        }
199    }
200}
201
202///
203/// Conversations Filter
204///
205#[derive(Debug, Clone)]
206pub struct ConversationsFilter {
207    /// A comma-separated list of fields to return. Reference
208    /// parameters of sub-objects with dot notation.
209    pub fields: Option<String>,
210    /// A comma-separated list of fields to exclude. Reference
211    /// parameters of sub-objects with dot notation.
212    pub exclude_fields: Option<String>,
213    /// The number of records to return. Default value is 10.
214    pub count: Option<u64>,
215    /// The number of records from a collection to skip. Iterating over
216    /// large collections with this parameter can be slow. Default value is 0..
217    pub offset: Option<u64>,
218    /// Whether the conversation has any unread messages. Posible value "true" or "false"
219    pub has_unread_messages: Option<String>,
220    /// The unique id for the list.
221    pub list_id: Option<String>,
222    /// The unique id for the campaign.
223    pub campaign_id: Option<u64>,
224}
225
226impl Default for ConversationsFilter {
227    fn default() -> Self {
228        ConversationsFilter {
229            fields: None,
230            exclude_fields: None,
231            count: Some(50),
232            offset: Some(0),
233            has_unread_messages: None,
234            list_id: None,
235            campaign_id: None,
236        }
237    }
238}
239
240impl ResourceFilter for ConversationsFilter {
241    fn build_payload(&self) -> HashMap<String, String> {
242        let mut payload = HashMap::new();
243
244        if self.fields.is_some() {
245            payload.insert("fields".to_string(), self.fields.as_ref().unwrap().clone());
246        }
247        if self.exclude_fields.is_some() {
248            payload.insert(
249                "exclude_fields".to_string(),
250                self.exclude_fields.as_ref().unwrap().clone(),
251            );
252        }
253        if self.count.is_some() {
254            payload.insert(
255                "count".to_string(),
256                format!("{:}", self.count.as_ref().unwrap().clone()),
257            );
258        }
259        if self.offset.is_some() {
260            payload.insert(
261                "offset".to_string(),
262                format!("{:}", self.offset.as_ref().unwrap().clone()),
263            );
264        }
265
266        if self.has_unread_messages.is_some() {
267            payload.insert(
268                "has_unread_messages".to_string(),
269                format!("{:}", self.has_unread_messages.as_ref().unwrap().clone()),
270            );
271        }
272        if self.list_id.is_some() {
273            payload.insert(
274                "list_id".to_string(),
275                format!("{:}", self.list_id.as_ref().unwrap().clone()),
276            );
277        }
278        if self.campaign_id.is_some() {
279            payload.insert(
280                "campaign_id".to_string(),
281                format!("{:}", self.campaign_id.as_ref().unwrap().clone()),
282            );
283        }
284        payload
285    }
286}
287
288///
289/// Conversation Builder
290///
291#[derive(Debug)]
292pub struct ConversationBuilder {}
293
294impl BuildIter for ConversationBuilder {
295    type Item = Conversation;
296    type FilterItem = ConversationsFilter;
297    type Collection = CollectionConversations;
298
299    ///
300    /// Return a new data updated
301    ///
302    fn update_item(&self, data: &Self::Item, api: Rc<MailchimpApi>) -> Self::Item {
303        let mut in_data = data.clone();
304        in_data.set_api(api);
305        in_data
306    }
307    ///
308    /// Update the offset for pagination
309    ///
310    fn update_filter_offset(&self, filter: &Self::FilterItem) -> Self::FilterItem {
311        let mut f = filter.clone();
312        f.offset = Some(f.count.unwrap() + f.offset.unwrap());
313        f
314    }
315}