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