drive_v3/resources/comments.rs
1use reqwest::Method;
2use drive_v3_macros::{DriveRequestBuilder, request};
3
4use super::DriveRequestBuilder;
5use crate::{objects, Credentials};
6
7#[request(
8 method=Method::POST,
9 url="https://www.googleapis.com/drive/v3/files/{file_id}/comments",
10 returns=objects::Comment,
11)]
12#[derive(DriveRequestBuilder)]
13/// A request builder to create a comment on a file.
14pub struct CreateRequest {
15 /// The comment to be created
16 #[drive_v3(body)]
17 comment: Option<objects::Comment>
18}
19
20#[request(
21 method=Method::DELETE,
22 url="https://www.googleapis.com/drive/v3/files/{file_id}/comments/{comment_id}",
23 returns=(),
24)]
25#[derive(DriveRequestBuilder)]
26/// A request builder to delete a comment on a file.
27pub struct DeleteRequest {}
28
29#[request(
30 method=Method::GET,
31 url="https://www.googleapis.com/drive/v3/files/{file_id}/comments/{comment_id}",
32 returns=objects::Comment,
33)]
34#[derive(DriveRequestBuilder)]
35/// A request builder to get a comment on a file.
36pub struct GetRequest {
37 /// Whether to return deleted comments.
38 ///
39 /// Deleted comments will not include their original content.
40 #[drive_v3(parameter)]
41 include_deleted: Option<bool>
42}
43
44#[request(
45 method=Method::GET,
46 url="https://www.googleapis.com/drive/v3/files/{file_id}/comments",
47 returns=objects::CommentList,
48)]
49#[derive(DriveRequestBuilder)]
50/// A request builder to list the comments on a file.
51pub struct ListRequest {
52 /// Whether to return deleted comments.
53 ///
54 /// Deleted comments will not include their original content.
55 #[drive_v3(parameter)]
56 include_deleted: Option<bool>,
57
58 /// The maximum number of comments to return per page.
59 #[drive_v3(parameter)]
60 page_size: Option<i64>,
61
62 /// The token for continuing a previous list request on the next page.
63 ///
64 /// This should be set to the value of
65 /// [`next_page_token`](objects::CommentList::next_page_token) from the
66 /// previous response.
67 #[drive_v3(parameter)]
68 page_token: Option<String>,
69
70 /// The minimum value of `modifiedTime` for the result comments
71 /// (RFC 3339 date-time).
72 #[drive_v3(parameter)]
73 start_modified_time: Option<String>,
74}
75
76#[request(
77 method=Method::PATCH,
78 url="https://www.googleapis.com/drive/v3/files/{file_id}/comments/{comment_id}",
79 returns=objects::Comment,
80)]
81#[derive(DriveRequestBuilder)]
82/// A request builder to update a comment on a file.
83pub struct UpdateRequest {
84 /// The updated comment
85 #[drive_v3(body)]
86 comment: Option<objects::Comment>
87}
88
89/// Comments on a file.
90///
91/// Some resource methods (such as [`comments.update`](Comments::update))
92/// require a `comment_id`. Use the [`comments.list`](Comments::list) method
93/// to retrieve the ID for a comment in a file.
94///
95/// # Examples:
96///
97/// List the comments in a file
98///
99/// ```no_run
100/// # use drive_v3::{Error, Credentials, Drive};
101/// #
102/// # let drive = Drive::new( &Credentials::from_file(
103/// # "../.secure-files/google_drive_credentials.json",
104/// # &["https://www.googleapis.com/auth/drive.file"],
105/// # )? );
106/// #
107/// let file_id = "some-file-id";
108///
109/// let comment_list = drive.comments.list(&file_id)
110/// .fields("*") // You must set the fields
111/// .page_size(10)
112/// .execute()?;
113///
114/// if let Some(comments) = comment_list.comments {
115/// for comment in comments {
116/// println!("{}", comment);
117/// }
118/// }
119/// # Ok::<(), Error>(())
120/// ```
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct Comments {
123 /// Credentials used to authenticate a user's access to this resource.
124 credentials: Credentials,
125}
126
127impl Comments {
128 /// Creates a new [`Comments`] resource with the given [`Credentials`].
129 pub fn new( credentials: &Credentials ) -> Self {
130 Self { credentials: credentials.clone() }
131 }
132
133 /// Creates a comment on a file.
134 ///
135 /// See Google's
136 /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/comments/create)
137 /// for more information.
138 ///
139 /// # Requires one of the following OAuth scopes:
140 ///
141 /// - `https://www.googleapis.com/auth/drive`
142 /// - `https://www.googleapis.com/auth/drive.file`
143 ///
144 /// # Examples:
145 ///
146 /// ```no_run
147 /// use drive_v3::objects::Comment;
148 /// # use drive_v3::{Error, Credentials, Drive};
149 /// #
150 /// # let drive = Drive::new( &Credentials::from_file(
151 /// # "../.secure-files/google_drive_credentials.json",
152 /// # &["https://www.googleapis.com/auth/drive.file"],
153 /// # )? );
154 ///
155 /// let comment = Comment {
156 /// content: Some( "this is my comment".to_string() ),
157 /// ..Default::default()
158 /// };
159 ///
160 /// let file_id = "some-file-id";
161 ///
162 /// let created_comment = drive.comments.create(&file_id)
163 /// .fields("*")
164 /// .comment(&comment)
165 /// .execute()?;
166 ///
167 /// assert_eq!(created_comment.content, comment.content);
168 /// # Ok::<(), Error>(())
169 /// ```
170 pub fn create<T: AsRef<str>> ( &self, file_id: T ) -> CreateRequest {
171 CreateRequest::new(&self.credentials, file_id)
172 }
173
174 /// Deletes a comment.
175 ///
176 /// See Google's
177 /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/comments/delete)
178 /// for more information.
179 ///
180 /// # Requires one of the following OAuth scopes:
181 ///
182 /// - `https://www.googleapis.com/auth/drive`
183 /// - `https://www.googleapis.com/auth/drive.file`
184 ///
185 /// # Examples:
186 ///
187 /// ```no_run
188 /// # use drive_v3::{Error, Credentials, Drive};
189 /// #
190 /// # let drive = Drive::new( &Credentials::from_file(
191 /// # "../.secure-files/google_drive_credentials.json",
192 /// # &["https://www.googleapis.com/auth/drive.file"],
193 /// # )? );
194 /// #
195 /// let file_id = "some-file-id";
196 /// let comment_id = "some-comment-id";
197 ///
198 /// let response = drive.comments.delete(&file_id, &comment_id).execute();
199 ///
200 /// assert!( response.is_ok() );
201 /// # Ok::<(), Error>(())
202 /// ```
203 pub fn delete<T, U> ( &self, file_id: T, comment_id: U ) -> DeleteRequest
204 where
205 T: AsRef<str>,
206 U: AsRef<str>
207 {
208 DeleteRequest::new(&self.credentials, file_id, comment_id)
209 }
210
211 /// Gets a comment by ID.
212 ///
213 /// See Google's
214 /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/comments/get)
215 /// for more information.
216 ///
217 /// # Note:
218 ///
219 /// This request requires you to set the [`fields`](GetRequest::fields)
220 /// parameter.
221 ///
222 /// # Requires one of the following OAuth scopes:
223 ///
224 /// - `https://www.googleapis.com/auth/drive`
225 /// - `https://www.googleapis.com/auth/drive.file`
226 /// - `https://www.googleapis.com/auth/drive.readonly`
227 ///
228 /// # Examples:
229 ///
230 /// ```no_run
231 /// # use drive_v3::{Error, Credentials, Drive};
232 /// #
233 /// # let drive = Drive::new( &Credentials::from_file(
234 /// # "../.secure-files/google_drive_credentials.json",
235 /// # &["https://www.googleapis.com/auth/drive.file"],
236 /// # )? );
237 /// #
238 /// let file_id = "some-file-id";
239 /// let comment_id = "some-comment-id";
240 ///
241 /// let created_comment = drive.comments.get(&file_id, &comment_id)
242 /// .fields("id, author, createdTime, content") // You must set the fields
243 /// .execute()?;
244 ///
245 /// println!("This is the comment:\n{}", created_comment);
246 /// # Ok::<(), Error>(())
247 /// ```
248 pub fn get<T, U> ( &self, file_id: T, comment_id: U ) -> GetRequest
249 where
250 T: AsRef<str>,
251 U: AsRef<str>
252 {
253 GetRequest::new(&self.credentials, file_id, comment_id)
254 }
255
256 /// Lists a file's comments.
257 ///
258 /// See Google's
259 /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/comments/list)
260 /// for more information.
261 ///
262 /// # Note:
263 ///
264 /// This request requires you to set the [`fields`](ListRequest::fields)
265 /// parameter.
266 ///
267 /// # Requires one of the following OAuth scopes:
268 ///
269 /// - `https://www.googleapis.com/auth/drive`
270 /// - `https://www.googleapis.com/auth/drive.file`
271 /// - `https://www.googleapis.com/auth/drive.readonly`
272 ///
273 /// # Examples:
274 ///
275 /// ```no_run
276 /// # use drive_v3::{Error, Credentials, Drive};
277 /// #
278 /// # let drive = Drive::new( &Credentials::from_file(
279 /// # "../.secure-files/google_drive_credentials.json",
280 /// # &["https://www.googleapis.com/auth/drive.file"],
281 /// # )? );
282 /// #
283 /// let file_id = "some-file-id";
284 ///
285 /// let comment_list = drive.comments.list(&file_id)
286 /// .fields("*") // You must set the fields
287 /// .page_size(10)
288 /// .execute()?;
289 ///
290 /// if let Some(comments) = comment_list.comments {
291 /// for comment in comments {
292 /// println!("{}", comment);
293 /// }
294 /// }
295 /// # Ok::<(), Error>(())
296 /// ```
297 pub fn list<T: AsRef<str>> ( &self, file_id: T ) -> ListRequest {
298 ListRequest::new(&self.credentials, file_id)
299 }
300
301 /// Updates a comment with patch semantics.
302 ///
303 /// See Google's
304 /// [documentation](https://developers.google.com/drive/api/reference/rest/v3/comments/update)
305 /// for more information.
306 ///
307 /// # Requires one of the following OAuth scopes:
308 ///
309 /// - `https://www.googleapis.com/auth/drive`
310 /// - `https://www.googleapis.com/auth/drive.file`
311 ///
312 /// # Examples:
313 ///
314 /// ```no_run
315 /// use drive_v3::objects::Comment;
316 /// # use drive_v3::{Error, Credentials, Drive};
317 /// #
318 /// # let drive = Drive::new( &Credentials::from_file(
319 /// # "../.secure-files/google_drive_credentials.json",
320 /// # &["https://www.googleapis.com/auth/drive.file"],
321 /// # )? );
322 ///
323 /// let updated_comment = Comment {
324 /// content: Some( "this is the updated content of my comment".to_string() ),
325 /// ..Default::default()
326 /// };
327 ///
328 /// let file_id = "some-file-id";
329 /// let comment_id = "some-comment-id";
330 ///
331 /// let modified_comment = drive.comments.update(&file_id, &comment_id)
332 /// .fields("*")
333 /// .comment(&updated_comment)
334 /// .execute()?;
335 ///
336 /// assert_eq!(modified_comment.content, updated_comment.content);
337 /// # Ok::<(), Error>(())
338 /// ```
339 pub fn update<T, U> ( &self, file_id: T, comment_id: U ) -> UpdateRequest
340 where
341 T: AsRef<str>,
342 U: AsRef<str>
343 {
344 UpdateRequest::new(&self.credentials, file_id, comment_id)
345 }
346}
347
348#[cfg(test)]
349mod tests {
350 use super::Comments;
351 use crate::{ErrorKind, objects, resources};
352 use crate::utils::test::{INVALID_CREDENTIALS, VALID_CREDENTIALS};
353
354 fn get_resource() -> Comments {
355 Comments::new(&VALID_CREDENTIALS)
356 }
357
358 fn get_invalid_resource() -> Comments {
359 Comments::new(&INVALID_CREDENTIALS)
360 }
361
362 fn get_files_resource() -> resources::Files {
363 resources::Files::new(&VALID_CREDENTIALS)
364 }
365
366 fn delete_file( file: &objects::File ) -> crate::Result<()> {
367 get_files_resource().delete( file.clone().id.unwrap() ).execute()
368 }
369
370 fn get_test_file_metadata() -> objects::File {
371 objects::File {
372 name: Some( "test.txt".to_string() ),
373 description: Some( "a test file".to_string() ),
374 mime_type: Some( "text/plain".to_string() ),
375 ..Default::default()
376 }
377 }
378
379 fn get_test_drive_file() -> crate::Result<objects::File> {
380 let metadata = get_test_file_metadata();
381
382 get_files_resource().create()
383 .fields("*")
384 .upload_type(objects::UploadType::Multipart)
385 .metadata(&metadata)
386 .content_string("content")
387 .execute()
388 }
389
390 fn get_test_comment() -> objects::Comment {
391 objects::Comment {
392 content: Some( "test comment".to_string() ),
393 ..Default::default()
394 }
395 }
396
397 fn get_test_drive_comment( file: &objects::File ) -> crate::Result<objects::Comment> {
398 let test_comment = get_test_comment();
399
400 get_resource().create( &file.clone().id.unwrap() )
401 .fields("*")
402 .comment(&test_comment)
403 .execute()
404 }
405
406 #[test]
407 fn new_test() {
408 let valid_resource = get_resource();
409 let invalid_resource = get_invalid_resource();
410
411 assert_eq!( valid_resource.credentials, VALID_CREDENTIALS.clone() );
412 assert_eq!( invalid_resource.credentials, INVALID_CREDENTIALS.clone() );
413 }
414
415 #[test]
416 fn create_test() {
417 let test_drive_file = get_test_drive_file().unwrap();
418 let test_comment = get_test_comment();
419
420 let response = get_resource().create( &test_drive_file.clone().id.unwrap() )
421 .fields("*")
422 .comment(&test_comment)
423 .execute();
424
425 assert!( response.is_ok() );
426
427 let comment = response.unwrap();
428 assert_eq!(comment.content, test_comment.content);
429
430 delete_file(&test_drive_file).expect("Failed to cleanup created file");
431 }
432
433 #[test]
434 fn create_invalid_test() {
435 let response = get_invalid_resource().create("invalid-id")
436 .execute();
437
438 assert!( response.is_err() );
439 assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
440 }
441
442 #[test]
443 fn delete_test() {
444 let test_drive_file = get_test_drive_file().unwrap();
445 let test_drive_comment = get_test_drive_comment(&test_drive_file).unwrap();
446
447 let response = get_resource().delete(
448 &test_drive_file.clone().id.unwrap(),
449 &test_drive_comment.clone().id.unwrap(),
450 )
451 .execute();
452
453 assert!( response.is_ok() );
454
455 delete_file(&test_drive_file).expect("Failed to cleanup created file");
456 }
457
458 #[test]
459 fn delete_invalid_test() {
460 let response = get_invalid_resource().delete("invalid-id", "invalid-id")
461 .execute();
462
463 assert!( response.is_err() );
464 assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
465 }
466
467 #[test]
468 fn get_test() {
469 let test_drive_file = get_test_drive_file().unwrap();
470 let test_drive_comment = get_test_drive_comment(&test_drive_file).unwrap();
471
472 let response = get_resource().get(
473 &test_drive_file.clone().id.unwrap(),
474 &test_drive_comment.clone().id.unwrap(),
475 )
476 .fields("*")
477 .execute();
478
479 assert!( response.is_ok() );
480
481 let comment = response.unwrap();
482 assert_eq!(comment, test_drive_comment);
483
484 delete_file(&test_drive_file).expect("Failed to cleanup created file");
485 }
486
487 #[test]
488 fn get_invalid_test() {
489 let response = get_invalid_resource().get("invalid-id", "invalid-id")
490 .execute();
491
492 assert!( response.is_err() );
493 assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
494 }
495
496 #[test]
497 fn list_test() {
498 let test_drive_file = get_test_drive_file().unwrap();
499 let test_drive_comment = get_test_drive_comment(&test_drive_file).unwrap();
500
501 let response = get_resource().list( &test_drive_file.clone().id.unwrap() )
502 .fields("*")
503 .execute();
504
505 assert!( response.is_ok() );
506
507 let comment_list = response.unwrap();
508 assert_eq!( comment_list.comments, Some(vec![test_drive_comment]) );
509
510 delete_file(&test_drive_file).expect("Failed to cleanup created file");
511 }
512
513 #[test]
514 fn list_invalid_test() {
515 let response = get_invalid_resource().list("invalid-id")
516 .execute();
517
518 assert!( response.is_err() );
519 assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
520 }
521
522 #[test]
523 fn update_test() {
524 let test_drive_file = get_test_drive_file().unwrap();
525 let test_drive_comment = get_test_drive_comment(&test_drive_file).unwrap();
526
527 let mut updated_comment = test_drive_comment.clone();
528 updated_comment.content = Some( "updated comment".to_string() );
529
530 let response = get_resource().update(
531 &test_drive_file.clone().id.unwrap(),
532 &test_drive_comment.clone().id.unwrap(),
533 )
534 .fields("*")
535 .comment(&updated_comment)
536 .execute();
537
538 assert!( response.is_ok() );
539
540 let comment = response.unwrap();
541 assert_eq!(comment.content, updated_comment.content);
542
543 delete_file(&test_drive_file).expect("Failed to cleanup created file");
544 }
545
546 #[test]
547 fn update_invalid_test() {
548 let response = get_invalid_resource().update("invalid-id", "invalid-id")
549 .execute();
550
551 assert!( response.is_err() );
552 assert_eq!( response.unwrap_err().kind, ErrorKind::Response );
553 }
554}