Skip to main content

canvas_lms_api/resources/
conversation.rs

1use crate::error::Result;
2use crate::http::Requester;
3use crate::params::wrap_params;
4use serde::{Deserialize, Serialize};
5use std::sync::Arc;
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
8pub struct ConversationParticipant {
9    pub id: u64,
10    pub name: Option<String>,
11    pub avatar_url: Option<String>,
12}
13
14#[derive(Debug, Clone, Deserialize, Serialize)]
15pub struct ConversationMessage {
16    pub id: u64,
17    pub created_at: Option<String>,
18    pub body: Option<String>,
19    pub author_id: Option<u64>,
20    pub generated: Option<bool>,
21}
22
23#[derive(Debug, Clone, Deserialize, Serialize, canvas_lms_api_derive::CanvasResource)]
24pub struct Conversation {
25    pub id: u64,
26    pub subject: Option<String>,
27    pub workflow_state: Option<String>,
28    pub last_message: Option<String>,
29    pub last_message_at: Option<String>,
30    pub message_count: Option<u64>,
31    pub subscribed: Option<bool>,
32    pub private: Option<bool>,
33    pub starred: Option<bool>,
34    pub audience: Option<Vec<u64>>,
35    pub participants: Option<Vec<ConversationParticipant>>,
36    pub messages: Option<Vec<ConversationMessage>>,
37    #[serde(skip)]
38    pub(crate) requester: Option<Arc<Requester>>,
39}
40
41#[derive(Debug, Clone, Default, Serialize)]
42pub struct ConversationParams {
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub subject: Option<String>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub force_new: Option<bool>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub group_conversation: Option<bool>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub context_code: Option<String>,
51}
52
53impl Conversation {
54    fn endpoint(&self) -> String {
55        format!("conversations/{}", self.id)
56    }
57
58    /// Add a message to this conversation.
59    ///
60    /// `POST /api/v1/conversations/:id/add_message`
61    pub async fn add_message(&self, body: &str) -> Result<Conversation> {
62        let params = vec![("body".into(), body.to_string())];
63        let endpoint = format!("{}/add_message", self.endpoint());
64        let mut c: Conversation = self.req().post(&endpoint, &params).await?;
65        c.requester = self.requester.clone();
66        Ok(c)
67    }
68
69    /// Add recipients to this conversation.
70    ///
71    /// `POST /api/v1/conversations/:id/add_recipients`
72    pub async fn add_recipients(&self, recipients: &[&str]) -> Result<Conversation> {
73        let params: Vec<(String, String)> = recipients
74            .iter()
75            .map(|r| ("recipients[]".into(), r.to_string()))
76            .collect();
77        let endpoint = format!("{}/add_recipients", self.endpoint());
78        let mut c: Conversation = self.req().post(&endpoint, &params).await?;
79        c.requester = self.requester.clone();
80        Ok(c)
81    }
82
83    /// Delete this conversation.
84    ///
85    /// `DELETE /api/v1/conversations/:id`
86    pub async fn delete(&self) -> Result<Conversation> {
87        let mut c: Conversation = self.req().delete(&self.endpoint(), &[]).await?;
88        c.requester = self.requester.clone();
89        Ok(c)
90    }
91
92    /// Delete specific messages from this conversation.
93    ///
94    /// `POST /api/v1/conversations/:id/remove_messages`
95    pub async fn delete_messages(&self, message_ids: &[u64]) -> Result<serde_json::Value> {
96        let params: Vec<(String, String)> = message_ids
97            .iter()
98            .map(|id| ("remove[]".into(), id.to_string()))
99            .collect();
100        let endpoint = format!("{}/remove_messages", self.endpoint());
101        self.req().post(&endpoint, &params).await
102    }
103
104    /// Update this conversation (mark read, star, subscribe, etc.).
105    ///
106    /// `PUT /api/v1/conversations/:id`
107    pub async fn edit(&self, params: &[(String, String)]) -> Result<Conversation> {
108        let mut c: Conversation = self.req().put(&self.endpoint(), params).await?;
109        c.requester = self.requester.clone();
110        Ok(c)
111    }
112
113    /// Update this conversation's workflow_state.
114    ///
115    /// `PUT /api/v1/conversations/:id`
116    pub async fn set_workflow_state(&self, state: &str) -> Result<Conversation> {
117        let params = wrap_params(
118            "conversation",
119            &serde_json::json!({ "workflow_state": state }),
120        );
121        self.edit(&params).await
122    }
123}