files_sdk/files/
file_comments.rs

1//! File comment operations
2//!
3//! This module provides operations for commenting on files:
4//! - List comments on a file
5//! - Create new comments
6//! - Update existing comments
7//! - Delete comments
8//! - React to comments
9
10use crate::utils::encode_path;
11use crate::{FilesClient, Result};
12use serde::{Deserialize, Serialize};
13use serde_json::json;
14
15/// Represents a comment on a file
16#[derive(Debug, Serialize, Deserialize, Clone)]
17pub struct FileCommentEntity {
18    /// File comment ID
19    pub id: Option<i64>,
20
21    /// Comment body text
22    pub body: Option<String>,
23
24    /// Reactions to this comment
25    pub reactions: Option<Vec<FileCommentReactionEntity>>,
26}
27
28/// Represents a reaction to a file comment
29#[derive(Debug, Serialize, Deserialize, Clone)]
30pub struct FileCommentReactionEntity {
31    /// Reaction ID
32    pub id: Option<i64>,
33
34    /// Emoji used for the reaction
35    pub emoji: Option<String>,
36}
37
38/// Handler for file comment operations
39#[derive(Debug, Clone)]
40pub struct FileCommentHandler {
41    client: FilesClient,
42}
43
44impl FileCommentHandler {
45    /// Creates a new FileCommentHandler
46    pub fn new(client: FilesClient) -> Self {
47        Self { client }
48    }
49
50    /// List comments for a file
51    ///
52    /// # Arguments
53    ///
54    /// * `path` - Path to the file
55    ///
56    /// # Examples
57    ///
58    /// ```rust,no_run
59    /// # use files_sdk::{FilesClient, FileCommentHandler};
60    /// # #[tokio::main]
61    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
62    /// let client = FilesClient::builder().api_key("key").build()?;
63    /// let handler = FileCommentHandler::new(client);
64    ///
65    /// let comments = handler.list("/path/to/file.txt").await?;
66    /// for comment in comments {
67    ///     println!("{}", comment.body.unwrap_or_default());
68    /// }
69    /// # Ok(())
70    /// # }
71    /// ```
72    pub async fn list(&self, path: &str) -> Result<Vec<FileCommentEntity>> {
73        let encoded_path = encode_path(path);
74        let endpoint = format!("/file_comments/files{}", encoded_path);
75        let response = self.client.get_raw(&endpoint).await?;
76        Ok(serde_json::from_value(response)?)
77    }
78
79    /// Create a new file comment
80    ///
81    /// # Arguments
82    ///
83    /// * `path` - Path to the file
84    /// * `body` - Comment text
85    pub async fn create(&self, path: &str, body: &str) -> Result<FileCommentEntity> {
86        let body_json = json!({
87            "body": body,
88            "path": path,
89        });
90
91        let response = self.client.post_raw("/file_comments", body_json).await?;
92        Ok(serde_json::from_value(response)?)
93    }
94
95    /// Update a file comment
96    ///
97    /// # Arguments
98    ///
99    /// * `id` - Comment ID
100    /// * `body` - New comment text
101    pub async fn update(&self, id: i64, body: &str) -> Result<FileCommentEntity> {
102        let body_json = json!({
103            "body": body,
104        });
105
106        let endpoint = format!("/file_comments/{}", id);
107        let response = self.client.patch_raw(&endpoint, body_json).await?;
108        Ok(serde_json::from_value(response)?)
109    }
110
111    /// Delete a file comment
112    ///
113    /// # Arguments
114    ///
115    /// * `id` - Comment ID
116    pub async fn delete(&self, id: i64) -> Result<()> {
117        let endpoint = format!("/file_comments/{}", id);
118        self.client.delete_raw(&endpoint).await?;
119        Ok(())
120    }
121
122    /// Add a reaction to a file comment
123    ///
124    /// # Arguments
125    ///
126    /// * `file_comment_id` - ID of the comment to react to
127    /// * `emoji` - Emoji for the reaction
128    pub async fn add_reaction(
129        &self,
130        file_comment_id: i64,
131        emoji: &str,
132    ) -> Result<FileCommentReactionEntity> {
133        let body = json!({
134            "file_comment_id": file_comment_id,
135            "emoji": emoji,
136        });
137
138        let response = self
139            .client
140            .post_raw("/file_comment_reactions", body)
141            .await?;
142        Ok(serde_json::from_value(response)?)
143    }
144
145    /// Delete a reaction from a file comment
146    ///
147    /// # Arguments
148    ///
149    /// * `id` - Reaction ID
150    pub async fn delete_reaction(&self, id: i64) -> Result<()> {
151        let endpoint = format!("/file_comment_reactions/{}", id);
152        self.client.delete_raw(&endpoint).await?;
153        Ok(())
154    }
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_handler_creation() {
163        let client = FilesClient::builder().api_key("test-key").build().unwrap();
164        let _handler = FileCommentHandler::new(client);
165    }
166}