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)]
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 req(&self) -> &Arc<Requester> {
55        self.requester.as_ref().expect("requester not injected")
56    }
57
58    fn endpoint(&self) -> String {
59        format!("conversations/{}", self.id)
60    }
61
62    /// Add a message to this conversation.
63    ///
64    /// `POST /api/v1/conversations/:id/add_message`
65    pub async fn add_message(&self, body: &str) -> Result<Conversation> {
66        let params = vec![("body".into(), body.to_string())];
67        let endpoint = format!("{}/add_message", self.endpoint());
68        let mut c: Conversation = self.req().post(&endpoint, &params).await?;
69        c.requester = self.requester.clone();
70        Ok(c)
71    }
72
73    /// Add recipients to this conversation.
74    ///
75    /// `POST /api/v1/conversations/:id/add_recipients`
76    pub async fn add_recipients(&self, recipients: &[&str]) -> Result<Conversation> {
77        let params: Vec<(String, String)> = recipients
78            .iter()
79            .map(|r| ("recipients[]".into(), r.to_string()))
80            .collect();
81        let endpoint = format!("{}/add_recipients", self.endpoint());
82        let mut c: Conversation = self.req().post(&endpoint, &params).await?;
83        c.requester = self.requester.clone();
84        Ok(c)
85    }
86
87    /// Delete this conversation.
88    ///
89    /// `DELETE /api/v1/conversations/:id`
90    pub async fn delete(&self) -> Result<Conversation> {
91        let mut c: Conversation = self.req().delete(&self.endpoint(), &[]).await?;
92        c.requester = self.requester.clone();
93        Ok(c)
94    }
95
96    /// Delete specific messages from this conversation.
97    ///
98    /// `POST /api/v1/conversations/:id/remove_messages`
99    pub async fn delete_messages(&self, message_ids: &[u64]) -> Result<serde_json::Value> {
100        let params: Vec<(String, String)> = message_ids
101            .iter()
102            .map(|id| ("remove[]".into(), id.to_string()))
103            .collect();
104        let endpoint = format!("{}/remove_messages", self.endpoint());
105        self.req().post(&endpoint, &params).await
106    }
107
108    /// Update this conversation (mark read, star, subscribe, etc.).
109    ///
110    /// `PUT /api/v1/conversations/:id`
111    pub async fn edit(&self, params: &[(String, String)]) -> Result<Conversation> {
112        let mut c: Conversation = self.req().put(&self.endpoint(), params).await?;
113        c.requester = self.requester.clone();
114        Ok(c)
115    }
116
117    /// Update this conversation's workflow_state.
118    ///
119    /// `PUT /api/v1/conversations/:id`
120    pub async fn set_workflow_state(&self, state: &str) -> Result<Conversation> {
121        let params = wrap_params(
122            "conversation",
123            &serde_json::json!({ "workflow_state": state }),
124        );
125        self.edit(&params).await
126    }
127}