File Coverage

blib/lib/Net/Google/Drive/Simple/V3.pm
Criterion Covered Total %
statement 93 401 23.1
branch 48 252 19.0
condition 9 190 4.7
subroutine 20 73 27.4
pod 46 46 100.0
total 216 962 22.4


line stmt bran cond sub pod time code
1             ###########################################
2             ###########################################
3              
4             use strict;
5 9     9   1240666 use warnings;
  9         50  
  9         202  
6 9     9   39 use parent qw< Net::Google::Drive::Simple::Core >;
  9         14  
  9         193  
7 9     9   35  
  9         12  
  9         39  
8             use URI ();
9 9     9   392 use URI::QueryParam ();
  9         59  
  9         130  
10 9     9   3230 use Log::Log4perl qw(:easy);
  9         5592  
  9         181  
11 9     9   45  
  9         83  
  9         57  
12             use constant {
13             'HTTP_METHOD_GET' => 'GET',
14 9         54779 'HTTP_METHOD_POST' => 'POST',
15             'HTTP_METHOD_PATCH' => 'PATCH',
16             'HTTP_METHOD_DELETE' => 'DELETE',
17              
18             'TYPE_STRING' => 'string',
19             'TYPE_INTEGER' => 'integer',
20             'TYPE_LONG' => 'long',
21             'TYPE_BOOLEAN' => 'boolean',
22             'TYPE_OBJECT' => 'object',
23             'TYPE_BYTES' => 'bytes',
24             };
25 9     9   5781  
  9         15  
26             our $VERSION = '3.00';
27              
28             # TODO:
29             # * requestId are random UUIDs that we should probably generate (drive_create)
30             # * Support for Request Body values
31             # * Support fields format: https://developers.google.com/drive/api/guides/fields-parameter
32             # * Add validation for path parameters
33             # * Specific types (like ISO 639-1)
34             # * Extended upload support: https://developers.google.com/drive/api/guides/manage-uploads
35              
36             # These are only the defaults
37             my %default_deprecated_param_names = (
38             'corpus' => 'corpora',
39             'includeTeamDriveItems' => 'includeItemsFromAllDrives',
40             'supportsTeamDrives' => 'supportsAllDrives',
41             'teamDriveId' => 'driveId',
42             );
43              
44             ###########################################
45             ###########################################
46             my ( $class, %options ) = @_;
47             return $class->SUPER::new(
48 7     7 1 648 %options,
49 7         72 'api_base_url' => 'https://www.googleapis.com/drive/v3/',
50             'api_upload_url' => 'https://www.googleapis.com/upload/drive/v3/files',
51              
52             # to make sure api_test() works:
53             'api_file_url' => 'https://www.googleapis.com/drive/v3/files',
54             );
55             }
56              
57             ###########################################
58             ###########################################
59             my ( $self, $method, $param_data, $param_values ) = @_;
60              
61             my %validation_types = (
62 37     37   18551 TYPE_STRING() => sub { defined and length },
63             TYPE_INTEGER() => sub { defined and m{^[0-9]+$}xms },
64             TYPE_LONG() => sub { defined and m{^[0-9]+$}xms },
65 5 100   5   28 TYPE_BOOLEAN() => sub { defined and m{^[01]$}xms },
66 8 100   8   74 TYPE_OBJECT() => sub { ref eq 'HASH' },
67 4 100   4   33 TYPE_BYTES() => sub { defined and length },
68 6 100   6   52 );
69 7     7   28  
70 3 100   3   18 foreach my $param_name ( sort keys %{$param_values} ) {
71 37         231 if ( !exists $param_data->{$param_name} ) {
72             LOGDIE("[$method] Parameter name '$param_name' does not exist");
73 37         45 }
  37         106  
74 35 100       83 }
75 1         6  
76             foreach my $param_name ( sort keys %{$param_data} ) {
77             my ( $param_type, $is_required ) = @{ $param_data->{$param_name} };
78             my $param_value = $param_values->{$param_name};
79 36         46  
  36         66  
80 36         47 # You did not provide a parameter that is needed
  36         55  
81 36         50 if ( !exists $param_values->{$param_name} ) {
82             $is_required
83             and LOGDIE("[$method] Parameter '$param_name' is required");
84 36 100       55  
85 2 100       8 next;
86             }
87              
88 1         2 my $validation_cb = $validation_types{$param_type};
89             if ( !$validation_cb ) {
90             LOGDIE("[$method] Parameter type '$param_type' does not exist");
91 34         46 }
92 34 100       54  
93 1         5 local $_ = $param_value;
94             my $success = $validation_cb->()
95             or LOGDIE("[$method] Parameter type '$param_name' does not validate as '$param_type'");
96 33         44 }
97 33 100       42  
98             return 1;
99             }
100              
101 14         67 ###########################################
102             ###########################################
103             my ( $self, $method, $options ) = @_;
104              
105             if ( my $perm_for_view = $options->{'includePermissionsForView'} ) {
106             $perm_for_view eq 'published'
107 21     21   13511 or LOGDIE("[$method] Parameter 'includePermissionsForView' must be: published");
108             }
109 21 100       42  
110 2 100       10 my $page_size = $options->{'pageSize'};
111             if ( defined $page_size ) {
112             $page_size >= 1 && $page_size <= 1_000
113             or LOGDIE("[$method] Parameter 'pageSize' must be: 1 to 1000");
114 20         26 }
115 20 100       34  
116 8 100 100     32 if ( my $upload_type = $options->{'uploadType'} ) {
117             $upload_type =~ /^( media | multipart | resumable )$/xms
118             or LOGDIE("[$method] Parameter 'uploadType' must be: media|multipart|resumable");
119             }
120 16 100       28  
121 6 100       29 return 1;
122             }
123              
124             ###########################################
125 13         21 ###########################################
126             my ( $self, $path, $options ) = @_;
127             my $uri = URI->new( $path =~ /^http/xms ? $path : $self->{'api_base_url'} . $path );
128              
129             $options
130             and $uri->query_form($options);
131 7     7   5513  
132 7 100       55 return $uri;
133             }
134 7 100       11058  
135             ###########################################
136             ###########################################
137 7         350 my ( $self, $method, $info, $options ) = @_;
138              
139             foreach my $dep_name ( sort keys %{$options} ) {
140             my $alt = $info->{'deprecated_param_names'}{$dep_name}
141             || $default_deprecated_param_names{$dep_name};
142              
143 27     27   14984 if ($alt) {
144             WARN("[$method] Parameter name '$dep_name' is deprecated, use '$alt' instead");
145 27         32 }
  27         58  
146             }
147 26   100     93  
148             return;
149 26 100       39 }
150 13         39  
151             ###########################################
152             ###########################################
153             my ( $self, $options, $body_param_names ) = @_;
154 27         192  
155             my $body_options = {
156             map +( exists $options->{$_} ? ( $_ => delete $options->{$_} ) : () ),
157             @{$body_param_names},
158             };
159              
160 6     6   4587 return $body_options;
161             }
162              
163             ###########################################
164 6 50       8 ###########################################
  6         24  
165             my ( $self, $info, $options ) = @_;
166             my $method = $info->{'method_name'};
167 6         13  
168             # We yank out all the body parameters so we don't validate them
169             # TODO: Support body parameter validation
170             my $body_options = $self->_prepare_body_options( $options, $info->{'body_parameters'} );
171              
172             # We validate the options left
173 5     5   18607 $self->_validate_param_type( $method, $info->{'query_parameters'}, $options );
174 5         9  
175             # We might have a more complicated type checking specified
176             if ( my $param_check = $info->{'parameter_checks'} ) {
177             foreach my $name ( sort keys %{$param_check} ) {
178 5         14 defined $options->{$name}
179             or next;
180              
181 5         17 my $cb = $param_check->{$name};
182             ref $cb eq 'CODE'
183             or LOGDIE("[$method] Parameter '$name' missing validation callback");
184 5 100       13  
185 1         3 local $_ = $options->{$name};
  1         4  
186 3 100       7 my $error_str = $cb->();
187             $error_str
188             and LOGDIE("[$method] Parameter '$name' failed validation: $error_str");
189 2         4 }
190 2 50       6 }
191              
192             # We check for deprecated parameters (from a list of known deprecated parameters)
193 2         5 $self->_handle_deprecated_params( $method, $info, $options );
194 2         4  
195 2 100       1169 # We handle some more specific validation rules (from a list of known parameters)
196             $self->_handle_complex_types( $method, $options );
197              
198             $self->init();
199              
200             # We generate the URI path
201 4         9 my $uri = $self->_generate_uri( $info->{'path'}, $options );
202              
203             # GET requests cannot have a body
204 4         8 if ( $info->{'http_method'} eq HTTP_METHOD_GET()
205             || $info->{'http_method'} eq HTTP_METHOD_DELETE() ) {
206 4         10 undef $body_options;
207             }
208              
209 4         15 # We make the request and get a response
210             return $self->http_json( $uri, [ $info->{'http_method'}, $body_options ] );
211             }
212 4 100 100     15  
213             # --- about
214 2         4  
215             ###########################################
216             ###########################################
217             my ( $self, $options ) = @_;
218 4         13  
219             ref $options eq 'HASH'
220             or LOGDIE('about() missing parameters');
221              
222             my $info = {
223             'query_parameters' => {
224             'fields' => [ TYPE_STRING(), 1 ],
225             },
226 0     0 1   'path' => 'about',
227             'method_name' => 'about',
228 0 0         'http_method' => HTTP_METHOD_GET(),
229             };
230              
231 0           return $self->_handle_api_method( $info, $options );
232             }
233              
234             # --- changes
235              
236             ###########################################
237             ###########################################
238             my ( $self, $options ) = @_;
239              
240 0           $options //= {};
241              
242             my $info = {
243             'query_parameters' => {
244             'driveId' => [ TYPE_STRING(), 0 ],
245             'fields' => [ TYPE_STRING(), 0 ],
246             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
247             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ], # Deprecated
248 0     0 1   'teamDriveId' => [ TYPE_STRING(), 0 ], # Deprecated
249             },
250 0   0        
251             'path' => 'changes/startPageToken',
252 0           'http_method' => HTTP_METHOD_GET(),
253             'method_name' => 'getStartPageToken',
254             };
255              
256             return $self->_handle_api_method( $info, $options );
257             }
258              
259             ###########################################
260             ###########################################
261             my ( $self, $options ) = @_;
262              
263             ref $options eq 'HASH'
264             or LOGDIE('changes() missing parameters');
265              
266 0           my $info = {
267             'query_parameters' => {
268             'pageToken' => [ TYPE_STRING(), 1 ],
269             'driveId' => [ TYPE_STRING(), 0 ],
270             'fields' => [ TYPE_STRING(), 0 ],
271             'includeCorpusRemovals' => [ TYPE_BOOLEAN(), 0 ],
272 0     0 1   'includeItemsFromAllDrives' => [ TYPE_BOOLEAN(), 0 ],
273             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
274 0 0         'includeRemoved' => [ TYPE_BOOLEAN(), 0 ],
275             'includeTeamDriveItems' => [ TYPE_BOOLEAN(), 0 ],
276             'pageSize' => [ TYPE_INTEGER(), 0 ],
277             'restrictToMyDrive' => [ TYPE_BOOLEAN(), 0 ],
278             'spaces' => [ TYPE_STRING(), 0 ],
279             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
280             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
281             'teamDriveId' => [ TYPE_STRING(), 0 ],
282             },
283              
284             'parameter_checks' => {
285             'spaces' => sub {
286             /^( drive | appDataFolder | photos )$/xms
287             or return 'must be: drive|appDataFolder|photos';
288              
289             return 0;
290             },
291             },
292              
293             'path' => 'changes',
294             'http_method' => HTTP_METHOD_GET(),
295             'method_name' => 'changes',
296             };
297 0 0   0      
298             return $self->_handle_api_method( $info, $options );
299             }
300 0            
301             ###########################################
302             ###########################################
303             my ( $self, $options ) = @_;
304 0            
305             $options //= {};
306              
307             my $info = {
308             'query_parameters' => {
309 0           'fields' => [ TYPE_STRING(), 0 ],
310             },
311              
312             'body_parameters' => [
313             qw<
314             kind
315 0     0 1   id
316             resourceId
317 0   0       resourceUri
318             token
319 0           expiration
320             type
321             address
322             payload
323             params
324             >
325             ],
326              
327             'path' => 'changes/watch',
328             'http_method' => HTTP_METHOD_POST(),
329             'method_name' => 'watch_changes',
330             };
331              
332             $options->{'kind'} = 'api#channel';
333              
334             return $self->_handle_api_method( $info, $options );
335             }
336              
337             # --- channels
338              
339             ###########################################
340             ###########################################
341             my ( $self, $options ) = @_;
342              
343             ref $options eq 'HASH'
344 0           or LOGDIE('stop_channels() missing parameters');
345              
346 0           my $info = {
347             'body_parameters' => [
348             qw<
349             kind
350             id
351             resourceId
352             resourceUri
353             token
354 0     0 1   expiration
355             type
356 0 0         address
357             payload
358             params
359             >
360             ],
361              
362             'parameter_checks' => {
363             'type' => sub {
364             m{^web_?hook$}xms
365             or return 'must be: webhook|web_hook';
366              
367             return 0;
368             },
369             },
370              
371             'path' => 'channels/stop',
372             'http_method' => HTTP_METHOD_POST(),
373             'method_name' => 'stop_channels',
374             };
375              
376             $options->{'kind'} = 'api#channel';
377 0 0   0      
378             return $self->_handle_api_method( $info, $options );
379             }
380 0            
381             # --- comments
382              
383             ###########################################
384 0           ###########################################
385             my ( $self, $fileId, $options ) = @_;
386              
387             defined $fileId && length $fileId
388             or LOGDIE('create_comment() missing file ID');
389 0            
390             ref $options eq 'HASH'
391 0           or LOGDIE('create_comment() missing parameters');
392              
393             my $info = {
394             'query_parameters' => {
395             'fields' => [ TYPE_STRING(), 1 ],
396             },
397              
398             'body_parameters' => [
399 0     0 1   qw<
400             content
401 0 0 0       anchor
402             quotedFileContent
403             >
404 0 0         ],
405              
406             'path' => "files/$fileId/comments",
407 0           'method_name' => 'create_comment',
408             'http_method' => HTTP_METHOD_POST(),
409             };
410              
411             return $self->_handle_api_method( $info, $options );
412             }
413              
414             ###########################################
415             ###########################################
416             my ( $self, $fileId, $commentId ) = @_;
417              
418             defined $fileId && length $fileId
419             or LOGDIE('create_comment() missing file ID');
420              
421             defined $commentId && length $commentId
422             or LOGDIE('create_comment() missing comment ID');
423              
424             my $info = {
425 0           'path' => "files/$fileId/comments/$commentId",
426             'method_name' => 'delete_comment',
427             'http_method' => HTTP_METHOD_DELETE(),
428             };
429              
430             return $self->_handle_api_method( $info, {} );
431 0     0 1   }
432              
433 0 0 0       ###########################################
434             ###########################################
435             my ( $self, $fileId, $commentId, $options ) = @_;
436 0 0 0        
437             defined $fileId && length $fileId
438             or LOGDIE('get_comment() missing file ID');
439 0            
440             defined $commentId && length $commentId
441             or LOGDIE('get_comment() missing comment ID');
442              
443             ref $options eq 'HASH'
444             or LOGDIE('get_comment() missing parameters');
445 0            
446             my $info = {
447             'query_parameters' => {
448             'fields' => [ TYPE_STRING(), 1 ],
449             'includeDeleted' => [ TYPE_BOOLEAN(), 0 ],
450             },
451 0     0 1    
452             'path' => "files/$fileId/comments/$commentId",
453 0 0 0       'method_name' => 'get_comment',
454             'http_method' => HTTP_METHOD_GET(),
455             };
456 0 0 0        
457             return $self->_handle_api_method( $info, $options );
458             }
459 0 0          
460             ###########################################
461             ###########################################
462 0           my ( $self, $fileId, $options ) = @_;
463              
464             defined $fileId && length $fileId
465             or LOGDIE('comments() missing file ID');
466              
467             ref $options eq 'HASH'
468             or LOGDIE('comments() missing parameters');
469              
470             my $info = {
471             'query_parameters' => {
472             'fields' => [ TYPE_STRING(), 1 ],
473 0           'includeDeleted' => [ TYPE_BOOLEAN(), 0 ],
474             'pageSize' => [ TYPE_INTEGER(), 0 ],
475             'pageToken' => [ TYPE_STRING(), 0 ],
476             'startModifiedTime' => [ TYPE_STRING(), 0 ],
477             },
478              
479 0     0 1   'path' => "files/$fileId/comments",
480             'method_name' => 'comments',
481 0 0 0       'http_method' => HTTP_METHOD_GET(),
482             };
483              
484 0 0         return $self->_handle_api_method( $info, $options );
485             }
486              
487 0           ###########################################
488             ###########################################
489             my ( $self, $fileId, $commentId, $options ) = @_;
490              
491             defined $fileId && length $fileId
492             or LOGDIE('update_comment() missing file ID');
493              
494             defined $commentId && length $commentId
495             or LOGDIE('update_comment() missing comment ID');
496              
497             ref $options eq 'HASH'
498             or LOGDIE('update_comment() missing parameters');
499              
500             my $info = {
501 0           'query_parameters' => {
502             'fields' => [ TYPE_STRING(), 1 ],
503             },
504              
505             'body_parameters' => [
506             qw<
507 0     0 1   content
508             >
509 0 0 0       ],
510              
511             'path' => "files/$fileId/comments/$commentId",
512 0 0 0       'method_name' => 'update_comment',
513             'http_method' => HTTP_METHOD_PATCH(),
514             };
515 0 0          
516             return $self->_update_api_method( $info, $options );
517             }
518 0            
519             # --- files
520              
521             ###########################################
522             ###########################################
523             my ( $self, $fileId, $options ) = @_;
524              
525             defined $fileId && length $fileId
526             or LOGDIE('copy_file() missing file ID');
527              
528             ref $options eq 'HASH'
529             or LOGDIE('copy_file() missing parameters');
530              
531             # TODO: ocrLanguage is ISO 639-1 code
532              
533             my $info = {
534 0           'query_parameters' => {
535             'fields' => [ TYPE_STRING(), 0 ],
536             'ignoreDefaultVisibility' => [ TYPE_BOOLEAN(), 0 ],
537             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
538             'keepRevisionForever' => [ TYPE_BOOLEAN(), 0 ],
539             'ocrLanguage' => [ TYPE_STRING(), 0 ],
540             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
541             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
542 0     0 1   },
543              
544 0 0 0       'body_parameters' => [
545             qw<
546             appProperties
547 0 0         contentHints
548             contentRestrictions
549             copyRequiresWriterPermission
550             description
551             id
552 0           mimeType
553             modifiedTime
554             name
555             parents
556             properties
557             starred
558             viewedByMeTime
559             writersCanShare
560             >
561             ],
562              
563             'path' => "files/$fileId/copy",
564             'method_name' => 'copy_file',
565             'http_method' => HTTP_METHOD_POST(),
566             };
567              
568             return $self->_handle_api_method( $info, $options );
569             }
570              
571             # Metadata only
572             ###########################################
573             ###########################################
574             my ( $self, $options ) = @_;
575              
576             ref $options eq 'HASH'
577             or LOGDIE('create_file() missing parameters');
578              
579             my $info = {
580             'query_parameters' => {
581             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
582             'ignoreDefaultVisibility' => [ TYPE_BOOLEAN(), 0 ],
583             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
584             'keepRevisionForever' => [ TYPE_BOOLEAN(), 0 ],
585             'ocrLanguage' => [ TYPE_STRING(), 0 ],
586             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
587 0           'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
588             'useContentAsIndexableText' => [ TYPE_BOOLEAN(), 0 ]
589             },
590              
591             'body_parameters' => [
592             qw<
593             appProperties
594 0     0 1   contentHints
595             contentRestrictions
596 0 0         copyRequiresWriterPermission
597             createdTime
598             description
599 0           folderColorRgb
600             id
601             mimeType
602             modifiedTime
603             name
604             originalFilename
605             parents
606             properties
607             shortcutDetails.targetId
608             starred
609             viewedByMeTime
610             writersCanShare
611             >
612             ],
613              
614             'path' => 'files',
615             'method_name' => 'create_file',
616             'http_method' => HTTP_METHOD_POST(),
617             };
618              
619             if ( defined $options->{'enforceSingleParent'} ) {
620             LOGDIE("[$info->{'method_name'}] Creating files in multiple folders is no longer supported");
621             }
622              
623             return $self->_update_api_method( $info, $options );
624             }
625              
626             # Uploading file
627             ###########################################
628             ###########################################
629             my ( $self, $options ) = @_;
630              
631             ref $options eq 'HASH'
632             or LOGDIE('upload_file() missing parameters');
633              
634             # TODO: Use this
635             my $max_filesize = 5_120_000_000_000; # 5120GB
636              
637             my $info = {
638             'query_parameters' => {
639 0 0         'uploadType' => [ TYPE_STRING(), 1 ],
640 0           'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
641             'ignoreDefaultVisibility' => [ TYPE_BOOLEAN(), 0 ],
642             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
643 0           'keepRevisionForever' => [ TYPE_BOOLEAN(), 0 ],
644             'ocrLanguage' => [ TYPE_STRING(), 0 ],
645             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
646             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
647             'useContentAsIndexableText' => [ TYPE_BOOLEAN(), 0 ]
648             },
649              
650 0     0 1   'body_parameters' => [
651             qw<
652 0 0         appProperties
653             contentHints
654             contentRestrictions
655             copyRequiresWriterPermission
656 0           createdTime
657             description
658             folderColorRgb
659             id
660             mimeType
661             modifiedTime
662             name
663             originalFilename
664             parents
665             properties
666             shortcutDetails.targetId
667             starred
668             viewedByMeTime
669             writersCanShare
670             >
671             ],
672              
673             'path' => $self->{'api_upload_url'},
674             'method_name' => 'upload_file',
675             'http_method' => HTTP_METHOD_POST(),
676             };
677              
678             if ( defined $options->{'enforceSingleParent'} ) {
679             LOGDIE("[$info->{'method_name'}] Creating files in multiple folders is no longer supported");
680             }
681              
682             return $self->_update_api_method( $info, $options );
683             }
684              
685             ###########################################
686             ###########################################
687             my ( $self, $fileId, $options ) = @_;
688              
689             defined $fileId && length $fileId
690             or LOGDIE('delete_file() missing file ID');
691              
692             $options //= {};
693              
694 0           my $info = {
695             'query_parameters' => {
696             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
697             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
698             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
699 0 0         },
700 0            
701             'path' => "files/$fileId",
702             'method_name' => 'delete_file',
703 0           'http_method' => HTTP_METHOD_DELETE(),
704             };
705              
706             if ( defined $options->{'enforceSingleParent'} ) {
707             LOGDIE("[$info->{'method_name'}] If an item is not in a shared drive and its last parent is deleted but the item itself is not, the item will be placed under its owner's root");
708             }
709 0     0 1    
710             return $self->http_json( $info, $options );
711 0 0 0       }
712              
713             ###########################################
714 0   0       ###########################################
715             my ( $self, $fileId, $options ) = @_;
716 0            
717             defined $fileId && length $fileId
718             or LOGDIE('export_file() missing file ID');
719              
720             ref $options eq 'HASH'
721             or LOGDIE('export_file() missing parameters');
722              
723             my $info = {
724             'query_parameters' => {
725             'mimeType' => [ TYPE_STRING(), 1 ],
726             'fields' => [ TYPE_STRING(), 0 ],
727             },
728 0 0          
729 0           'path' => "files/$fileId/export",
730             'method_name' => 'export_file',
731             'http_method' => HTTP_METHOD_GET(),
732 0           };
733              
734             return $self->_handle_api_method( $info, $options );
735             }
736              
737             ###########################################
738 0     0 1   ###########################################
739             my ( $self, $options ) = @_;
740 0 0 0        
741             $options //= {};
742              
743 0 0         my $info = {
744             'query_parameters' => {
745             'count' => [ TYPE_INTEGER(), 0 ],
746 0           'fields' => [ TYPE_STRING(), 0 ],
747             'space' => [ TYPE_STRING(), 0 ],
748             'type' => [ TYPE_STRING(), 0 ],
749             },
750              
751             'parameter_checks' => {
752             'spaces' => sub {
753             /^( files | shortcuts )$/xms
754             or return 'must be: files|shortcuts';
755              
756             return 0;
757 0           }
758             },
759              
760             'path' => 'files/generateIds',
761             'method_name' => 'generateIds',
762             'http_method' => HTTP_METHOD_GET(),
763 0     0 1   };
764              
765 0   0       return $self->_handle_api_method( $info, $options );
766             }
767              
768             ###########################################
769             ###########################################
770             my ( $self, $fileId, $options ) = @_;
771              
772             defined $fileId && length $fileId
773             or LOGDIE('get_file() missing file ID');
774              
775             $options //= {};
776              
777 0 0   0     my $info = {
778             'query_parameters' => {
779             'acknowledgeAbuse' => [ TYPE_BOOLEAN(), 0 ],
780 0           'fields' => [ TYPE_STRING(), 0 ],
781             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
782             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
783             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
784 0           },
785              
786             'path' => "files/$fileId",
787             'method_name' => 'get_file',
788             'http_method' => HTTP_METHOD_GET(),
789 0           };
790              
791             return $self->_handle_api_method( $info, $options );
792             }
793              
794             ###########################################
795 0     0 1   ###########################################
796             my ( $self, $options ) = @_;
797 0 0 0        
798             $options //= {};
799              
800 0   0       # TODO: orderBy
801             # 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', 'name', 'name_natural', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', and 'viewedByMeTime'.
802 0           # ?orderBy=folder,modifiedTime desc,name
803              
804             # TODO: Steal the struct to query syntax from MetaCPAN::Client
805             # https://developers.google.com/drive/api/guides/search-files
806             #if ( my $query_str = $options->{'q'} ) {...}
807              
808             my $info = {
809             'query_parameters' => {
810             'corpora' => [ TYPE_STRING(), 0 ],
811             'corpus' => [ TYPE_STRING(), 0 ], # deprecated
812             'driveId' => [ TYPE_STRING(), 0 ],
813             'fields' => [ TYPE_STRING(), 0 ],
814             'includeItemsFromAllDrives' => [ TYPE_BOOLEAN(), 0 ],
815             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
816 0           'includeTeamDriveItems' => [ TYPE_BOOLEAN(), 0 ], # deprecated
817             'orderBy' => [ TYPE_STRING(), 0 ],
818             'pageSize' => [ TYPE_INTEGER(), 0 ],
819             'pageToken' => [ TYPE_STRING(), 0 ],
820             'q' => [ TYPE_STRING(), 0 ],
821             'spaces' => [ TYPE_STRING(), 0 ],
822 0     0 1   'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
823             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ], # deprecated
824 0   0       'teamDriveId' => [ TYPE_STRING(), 0 ], # deprecated
825             'trashed' => [ TYPE_BOOLEAN(), 0 ], # not documented
826             },
827              
828             'parameter_checks' => {
829             'corpora' => sub {
830             /^( user | drive | domain | allDrives )$/xms
831             or return 'must be: user|drive|domain|allDrives';
832              
833             if ( $_ eq 'drive' ) {
834             defined $options->{'driveId'}
835             or return 'if corpora is drive, parameter driveId must be set';
836             }
837              
838             return 0;
839             },
840              
841             'corpus' => sub {
842             /^( domain | user )$/xms
843             or return 'must be: domain|user';
844              
845             return 0;
846             },
847              
848             'spaces' => sub {
849             /^( drive | appDataFolder )$/xms
850             or return 'must be: drive|appDataFolder';
851              
852             return 0;
853             },
854             },
855              
856 0 0   0     'path' => 'files',
857             'method_name' => 'files',
858             'http_method' => HTTP_METHOD_GET(),
859 0 0         };
860 0 0          
861             return $self->_handle_api_method( $info, $options );
862             }
863              
864 0           # Update with upload
865             ###########################################
866             ###########################################
867             my ( $self, $fileId, $options ) = @_;
868 0 0   0      
869             defined $fileId && length $fileId
870             or LOGDIE('update_file() missing file ID');
871 0            
872             ref $options eq 'HASH'
873             or LOGDIE('update_file() missing parameters');
874              
875 0 0   0     my $info = {
876             'query_parameters' => {
877             'uploadType' => [ TYPE_STRING(), 1 ],
878 0           'addParents' => [ TYPE_STRING(), 0 ],
879             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
880             'includePermissionsForView' => [ TYPE_STRING(), 0 ],
881             'keepRevisionForever' => [ TYPE_BOOLEAN(), 0 ],
882 0           'ocrLanguage' => [ TYPE_STRING(), 0 ],
883             'removeParents' => [ TYPE_STRING(), 0 ],
884             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
885             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
886             'useContentAsIndexableText' => [ TYPE_BOOLEAN(), 0 ],
887 0           },
888              
889             'body_parameters' => [
890             qw<
891             appProperties
892             contentHints
893             contentRestrictions
894 0     0 1   copyRequiresWriterPermission
895             description
896 0 0 0       folderColorRgb
897             mimeType
898             modifiedTime
899 0 0         name
900             originalFilename
901             properties
902             starred
903             trashed
904             viewedByMeTime
905             writersCanShare
906             >
907             ],
908              
909             'path' => $self->{'api_upload_file'} . "/$fileId",
910             'method_name' => 'update_file',
911             'http_method' => HTTP_METHOD_PATCH(),
912             };
913              
914             if ( defined $options->{'enforceSingleParent'} ) {
915             LOGDIE("[$info->{'method_name'}] Adding files to multiple folders is no longer supported. Use shortcuts instead");
916             }
917              
918             return $self->_handle_api_method( $info, $options );
919             }
920              
921             # Metadata
922             ###########################################
923             ###########################################
924             my ( $self, $fileId, $options ) = @_;
925              
926             defined $fileId && length $fileId
927             or LOGDIE('update_file_metadata() missing file ID');
928              
929             ref $options eq 'HASH'
930             or LOGDIE('update_file_metadata() missing parameters');
931              
932             my $info = {
933             'query_parameters' => {
934             'addParents' => [ TYPE_STRING(), 0 ],
935             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
936 0           'includePermissionsForView' => [ TYPE_STRING(), 0 ],
937             'keepRevisionForever' => [ TYPE_BOOLEAN(), 0 ],
938             'ocrLanguage' => [ TYPE_STRING(), 0 ],
939             'removeParents' => [ TYPE_STRING(), 0 ],
940             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
941 0 0         'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
942 0           'useContentAsIndexableText' => [ TYPE_BOOLEAN(), 0 ],
943             },
944              
945 0           'body_parameters' => [
946             qw<
947             appProperties
948             contentHints
949             contentRestrictions
950             copyRequiresWriterPermission
951             description
952 0     0 1   folderColorRgb
953             mimeType
954 0 0 0       modifiedTime
955             name
956             originalFilename
957 0 0         properties
958             starred
959             trashed
960 0           viewedByMeTime
961             writersCanShare
962             >
963             ],
964              
965             'path' => "files/$fileId",
966             'method_name' => 'update_file_metadata',
967             'http_method' => HTTP_METHOD_PATCH(),
968             };
969              
970             if ( defined $options->{'enforceSingleParent'} ) {
971             LOGDIE("[$info->{'method_name'}] Adding files to multiple folders is no longer supported. Use shortcuts instead");
972             }
973              
974             return $self->_handle_api_method( $info, $options );
975             }
976              
977             ###########################################
978             ###########################################
979             my ( $self, $fileId, $options ) = @_;
980              
981             defined $fileId && length $fileId
982             or LOGDIE('watch_file() missing file ID');
983              
984             ref $options eq 'HASH'
985             or LOGDIE('watch_file() missing parameters');
986              
987             my $info = {
988             'query_parameters' => {
989             'acknowledgeAbuse' => [ TYPE_BOOLEAN(), 0 ],
990             'fields' => [ TYPE_STRING(), 0 ],
991             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
992             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
993             },
994              
995             'body_parameters' => [
996             qw<
997             kind
998 0 0         id
999 0           resourceId
1000             resourceUri
1001             token
1002 0           expiration
1003             type
1004             address
1005             payload
1006             params
1007             >
1008 0     0 1   ],
1009              
1010 0 0 0       'path' => "files/$fileId/watch",
1011             'method_name' => 'watch_file',
1012             'http_method' => HTTP_METHOD_POST(),
1013 0 0         };
1014              
1015             $options->{'kind'} = 'api#channel';
1016 0            
1017             return $self->_handle_api_method( $info, $options );
1018             }
1019              
1020             ###########################################
1021             ###########################################
1022             my ( $self, $options ) = @_;
1023              
1024             $options //= {};
1025              
1026             my $info = {
1027             'query_parameters' => {
1028             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
1029             },
1030              
1031             'path' => 'files/trash',
1032             'method' => 'empty_trash',
1033             'http_method' => HTTP_METHOD_DELETE(),
1034             };
1035              
1036             if ( defined $options->{'enforceSingleParent'} ) {
1037             LOGDIE("[$info->{'method_name'}] If an item is not in a shared drive and its last parent is deleted but the item itself is not, the item will be placed under its owner's root");
1038             }
1039              
1040             return $self->_handle_api_method( $info, {} );
1041             }
1042              
1043             # --- permissions
1044 0            
1045             ###########################################
1046 0           ###########################################
1047             my ( $self, $fileId, $options ) = @_;
1048              
1049             defined $fileId && length $fileId
1050             or LOGDIE('create_permission() missing file ID');
1051              
1052 0     0 1   ref $options eq 'HASH'
1053             or LOGDIE('create_permission() missing parameters');
1054 0   0        
1055             my $info = {
1056 0           'query_parameters' => {
1057             'emailMessage' => [ TYPE_STRING(), 0 ],
1058             'enforceSingleParent' => [ TYPE_BOOLEAN(), 0 ],
1059             'fields' => [ TYPE_STRING(), 0 ],
1060             'moveToNewOwnersRoot' => [ TYPE_BOOLEAN(), 0 ],
1061             'sendNotificationEmail' => [ TYPE_BOOLEAN(), 0 ],
1062             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
1063             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
1064             'transferOwnership' => [ TYPE_BOOLEAN(), 0 ],
1065             'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1066 0 0         },
1067 0            
1068             'body_parameters' => [
1069             qw<
1070 0           role
1071             type
1072             allowFileDiscovery
1073             domain
1074             emailAddress
1075             pendingOwner
1076             view
1077             >
1078 0     0 1   ],
1079              
1080 0 0 0       'deprecated_param_names' => {
1081             'enforceSingleParent' => 'moveToNewOwnersRoot',
1082             },
1083 0 0          
1084             'path' => "files/$fileId/permissions",
1085             'method_name' => 'create_permission',
1086 0           'http_method' => HTTP_METHOD_POST(),
1087             };
1088              
1089             return $self->_handle_api_method( $info, $options );
1090             }
1091              
1092             ###########################################
1093             ###########################################
1094             my ( $self, $fileId, $permissionId, $options ) = @_;
1095              
1096             defined $fileId && length $fileId
1097             or LOGDIE('delete_permission() missing file ID');
1098              
1099             defined $permissionId && length $permissionId
1100             or LOGDIE('delete_permission() missing permission ID');
1101              
1102             $options //= {};
1103              
1104             my $info = {
1105             'query_parameters' => {
1106             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
1107             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
1108             'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1109             },
1110              
1111             'path' => "files/$fileId/permissions/$permissionId",
1112             'method_name' => 'delete_permission',
1113             'http_method' => HTTP_METHOD_DELETE(),
1114             };
1115              
1116             return $self->_handle_api_method( $info, $options );
1117             }
1118              
1119             ###########################################
1120 0           ###########################################
1121             my ( $self, $fileId, $permissionId, $options ) = @_;
1122              
1123             defined $fileId && length $fileId
1124             or LOGDIE('get_permission() missing file ID');
1125              
1126 0     0 1   defined $permissionId && length $permissionId
1127             or LOGDIE('get_permission() missing permission ID');
1128 0 0 0        
1129             $options //= {};
1130              
1131 0 0 0       my $info = {
1132             'query_parameters' => {
1133             'fields' => [ TYPE_STRING(), 0 ],
1134 0   0       'supportsAllDrivee' => [ TYPE_BOOLEAN(), 0 ],
1135             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
1136 0           'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1137             },
1138              
1139             'path' => "files/$fileId/permissions/$permissionId",
1140             'method_name' => 'get_permission',
1141             'http_method' => HTTP_METHOD_GET(),
1142             };
1143              
1144             return $self->_handle_api_method( $info, $options );
1145             }
1146              
1147             ###########################################
1148 0           ###########################################
1149             my ( $self, $fileId, $options ) = @_;
1150              
1151             defined $fileId && length $fileId
1152             or LOGDIE('permissions() missing file ID');
1153              
1154 0     0 1   $options //= {};
1155              
1156 0 0 0       my $info = {
1157             'query_parameters' => {
1158             'fields' => [ TYPE_STRING(), 0 ],
1159 0 0 0       'includePermissionsForView' => [ TYPE_STRING(), 0 ],
1160             'pageSize' => [ TYPE_INTEGER(), 0 ],
1161             'pageToken' => [ TYPE_STRING(), 0 ],
1162 0   0       'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
1163             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
1164 0           'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1165             },
1166              
1167             'path' => "files/$fileId/permissions",
1168             'method_name' => 'permissions',
1169             'http_method' => HTTP_METHOD_GET(),
1170             };
1171              
1172             return $self->_handle_api_method( $info, $options );
1173             }
1174              
1175             ###########################################
1176             ###########################################
1177 0           my ( $self, $fileId, $permissionId, $options ) = @_;
1178              
1179             defined $fileId && length $fileId
1180             or LOGDIE('update_permission() missing file ID');
1181              
1182             defined $permissionId && length $permissionId
1183 0     0 1   or LOGDIE('update_permission() missing permission ID');
1184              
1185 0 0 0       $options //= {};
1186              
1187             my $info = {
1188 0   0       'query_parameters' => {
1189             'fields' => [ TYPE_STRING(), 0 ],
1190 0           'removeExpiration' => [ TYPE_BOOLEAN(), 0 ],
1191             'supportsAllDrives' => [ TYPE_BOOLEAN(), 0 ],
1192             'supportsTeamDrives' => [ TYPE_BOOLEAN(), 0 ],
1193             'transferOwnership' => [ TYPE_BOOLEAN(), 0 ],
1194             'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1195             },
1196              
1197             'path' => "files/$fileId/permissions/$permissionId",
1198             'method_name' => 'update_permission',
1199             'http_method' => HTTP_METHOD_PATCH(),
1200             };
1201              
1202             return $self->_handle_api_method( $info, $options );
1203             }
1204              
1205             # --- replies
1206 0            
1207             ###########################################
1208             ###########################################
1209             my ( $self, $fileId, $commentId, $options ) = @_;
1210              
1211             defined $fileId && length $fileId
1212 0     0 1   or LOGDIE('create_reply() missing file ID');
1213              
1214 0 0 0       defined $commentId && length $commentId
1215             or LOGDIE('create_reply() missing comment ID');
1216              
1217 0 0 0       ref $options eq 'HASH'
1218             or LOGDIE('create_reply() missing parameters');
1219              
1220 0   0       my $info = {
1221             'query_parameters' => {
1222 0           'fields' => [ TYPE_STRING(), 1 ],
1223             },
1224              
1225             'body_parameters' => [
1226             qw<
1227             action
1228             content
1229             >
1230             ],
1231              
1232             'parameter_checks' => {
1233             'action' => sub {
1234             m{^( resolve | reopen )$}xms
1235             or return 'must be: resolve|reopen';
1236              
1237 0           return 0;
1238             },
1239             },
1240              
1241             'path' => "files/$fileId/comments/$commentId/replies",
1242             'method_name' => 'create_reply',
1243             'http_method' => HTTP_METHOD_POST(),
1244             };
1245 0     0 1    
1246             return $self->_handle_api_method( $info, $options );
1247 0 0 0       }
1248              
1249             ###########################################
1250 0 0 0       ###########################################
1251             my ( $self, $fileId, $commentId, $replyId ) = @_;
1252              
1253 0 0         defined $fileId && length $fileId
1254             or LOGDIE('delete_reply() missing file ID');
1255              
1256             defined $commentId && length $commentId
1257             or LOGDIE('delete_reply() missing comment ID');
1258              
1259             my $info = {
1260             'path' => "files/$fileId/comments/$commentId/replies/$replyId",
1261             'method_name' => 'delete_reply',
1262             'http_method' => HTTP_METHOD_DELETE(),
1263             };
1264              
1265             return $self->_handle_api_method( $info, {} );
1266             }
1267              
1268             ###########################################
1269             ###########################################
1270 0 0   0     my ( $self, $fileId, $commentId, $replyId, $options ) = @_;
1271              
1272             defined $fileId && length $fileId
1273 0           or LOGDIE('get_reply() missing file ID');
1274              
1275             defined $commentId && length $commentId
1276             or LOGDIE('get_reply() missing comment ID');
1277 0            
1278             defined $replyId && length $replyId
1279             or LOGDIE('get_reply() missing reply ID');
1280              
1281             ref $options eq 'HASH'
1282 0           or LOGDIE('get_reply() missing parameters');
1283              
1284             my $info = {
1285             'query_parameters' => {
1286             'fields' => [ TYPE_STRING(), 1 ],
1287             'includeDeleted' => [ TYPE_BOOLEAN(), 0 ],
1288 0     0 1   },
1289              
1290 0 0 0       'path' => "files/$fileId/comments/$commentId/replies/$replyId",
1291             'method_name' => 'get_reply',
1292             'http_method' => HTTP_METHOD_GET(),
1293 0 0 0       };
1294              
1295             return $self->_handle_api_method( $info, $options );
1296 0           }
1297              
1298             ###########################################
1299             ###########################################
1300             my ( $self, $fileId, $commentId, $options ) = @_;
1301              
1302 0           defined $fileId && length $fileId
1303             or LOGDIE('replies() missing file ID');
1304              
1305             defined $commentId && length $commentId
1306             or LOGDIE('replies() missing comment ID');
1307              
1308 0     0 1   ref $options eq 'HASH'
1309             or LOGDIE('replies() missing parameters');
1310 0 0 0        
1311             my $info = {
1312             'query_parameters' => {
1313 0 0 0       'fields' => [ TYPE_STRING(), 1 ],
1314             'includeDeleted' => [ TYPE_BOOLEAN(), 0 ],
1315             'pageSize' => [ TYPE_INTEGER(), 0 ],
1316 0 0 0       'pageToken' => [ TYPE_STRING(), 0 ],
1317             },
1318              
1319 0 0         'path' => "files/$fileId/comments/$commentId/replies",
1320             'method_name' => 'replies',
1321             'http_method' => HTTP_METHOD_GET(),
1322 0           };
1323              
1324             return $self->_handle_api_method( $info, $options );
1325             }
1326              
1327             ###########################################
1328             ###########################################
1329             my ( $self, $fileId, $commentId, $replyId, $options ) = @_;
1330              
1331             defined $fileId && length $fileId
1332             or LOGDIE('update_reply() missing file ID');
1333 0            
1334             defined $commentId && length $commentId
1335             or LOGDIE('update_reply() missing comment ID');
1336              
1337             defined $replyId && length $replyId
1338             or LOGDIE('update_reply() missing reply ID');
1339 0     0 1    
1340             ref $options eq 'HASH'
1341 0 0 0       or LOGDIE('update_reply() missing parameters');
1342              
1343             my $info = {
1344 0 0 0       'query_parameters' => {
1345             'fields' => [ TYPE_STRING(), 1 ],
1346             },
1347 0 0          
1348             'body_parameters' => {
1349             'content' => [ TYPE_STRING(), 1 ],
1350 0           },
1351              
1352             'path' => "files/$fileId/comments/$commentId/replies/$replyId",
1353             'method_name' => 'update_reply',
1354             'http_method' => HTTP_METHOD_PATCH(),
1355             };
1356              
1357             return $self->_handle_api_method( $info, $options );
1358             }
1359              
1360             # --- revisions
1361              
1362             ###########################################
1363 0           ###########################################
1364             my ( $self, $fileId, $revisionId ) = @_;
1365              
1366             defined $fileId && length $fileId
1367             or LOGDIE('delete_revision() missing file ID');
1368              
1369 0     0 1   my $info = {
1370             'path' => "files/$fileId/revisions/$revisionId",
1371 0 0 0       'method_name' => 'delete_revision',
1372             'http_method' => HTTP_METHOD_DELETE(),
1373             };
1374 0 0 0        
1375             return $self->_handle_api_method( $info, {} );
1376             }
1377 0 0 0        
1378             ###########################################
1379             ###########################################
1380 0 0         my ( $self, $fileId, $revisionId, $options ) = @_;
1381              
1382             defined $fileId && length $fileId
1383 0           or LOGDIE('get_revision() missing file ID');
1384              
1385             defined $revisionId && length $revisionId
1386             or LOGDIE('get_revision() missing revision ID');
1387              
1388             $options //= {};
1389              
1390             my $info = {
1391             'query_parameters' => {
1392             'acknowledgeAbuse' => [ TYPE_BOOLEAN(), 0 ],
1393             'fields' => [ TYPE_STRING(), 0 ],
1394             },
1395              
1396             'path' => "files/$fileId/revisions/$revisionId",
1397 0           'method_name' => 'get_revision',
1398             'http_method' => HTTP_METHOD_GET(),
1399             };
1400              
1401             return $self->_handle_api_method( $info, $options );
1402             }
1403              
1404             ###########################################
1405 0     0 1   ###########################################
1406             my ( $self, $fileId, $options ) = @_;
1407 0 0 0        
1408             defined $fileId && length $fileId
1409             or LOGDIE('revisions() missing file ID');
1410 0            
1411             $options //= {};
1412              
1413             my $info = {
1414             'query_parameters' => {
1415             'fields' => [ TYPE_STRING(), 0 ],
1416 0           'pageSize' => [ TYPE_INTEGER(), 0 ],
1417             'pageToken' => [ TYPE_STRING(), 0 ],
1418             },
1419              
1420             'path' => "files/$fileId/revisions",
1421             'method_name' => 'revisions',
1422 0     0 1   'http_method' => HTTP_METHOD_GET(),
1423             };
1424 0 0 0        
1425             return $self->_handle_api_method( $info, $options );
1426             }
1427 0 0 0        
1428             ###########################################
1429             ###########################################
1430 0   0       my ( $self, $fileId, $revisionId, $options ) = @_;
1431              
1432 0           defined $fileId && length $fileId
1433             or LOGDIE('update_revision() missing file ID');
1434              
1435             defined $revisionId && length $revisionId
1436             or LOGDIE('update_revision() missing revision ID');
1437              
1438             ref $options eq 'HASH'
1439             or LOGDIE('update_revision() missing parameters');
1440              
1441             my $info = {
1442             'query_parameters' => {
1443 0           'fields' => [ TYPE_STRING(), 0 ],
1444             },
1445              
1446             'body_parameter' => [
1447             qw<
1448             keepForever
1449 0     0 1   publishAuto
1450             published
1451 0 0 0       publishedOutsideDomain
1452             >
1453             ],
1454 0   0        
1455             'path' => "files/$fileId/revisions/$revisionId",
1456 0           'method_name' => 'update_revision',
1457             'http_method' => HTTP_METHOD_PATCH(),
1458             };
1459              
1460             return $self->_handle_api_method( $info, $options );
1461             }
1462              
1463             # --- drives
1464              
1465             ###########################################
1466             ###########################################
1467             my ( $self, $options ) = @_;
1468 0            
1469             ref $options eq 'HASH'
1470             or LOGDIE('create_drive() missing parameters');
1471              
1472             my $info = {
1473             'query_parameters' => {
1474 0     0 1   'requestId' => [ TYPE_STRING(), 1 ],
1475             },
1476 0 0 0        
1477             'body_parameters' => {
1478             'name' => [ TYPE_STRING(), 1 ],
1479 0 0 0       'themeId' => [ TYPE_STRING(), 0 ],
1480             },
1481              
1482 0 0         'path' => 'drives',
1483             'method_name' => 'create_drive',
1484             'http_method' => HTTP_METHOD_POST(),
1485 0           };
1486              
1487             return $self->_handle_api_method( $info, $options );
1488             }
1489              
1490             ###########################################
1491             ###########################################
1492             my ( $self, $driveId ) = @_;
1493              
1494             defined $driveId && length $driveId
1495             or LOGDIE('delete_drive() missing drive ID');
1496              
1497             my $info = {
1498             'path' => "drives/$driveId",
1499             'method_name' => 'delete_drive',
1500             'http_method' => HTTP_METHOD_DELETE(),
1501             };
1502              
1503             return $self->_handle_api_method( $info, {} );
1504 0           }
1505              
1506             ###########################################
1507             ###########################################
1508             my ( $self, $driveId, $options ) = @_;
1509              
1510             defined $driveId && length $driveId
1511             or LOGDIE('get_drive() missing drive ID');
1512 0     0 1    
1513             $options //= {};
1514 0 0          
1515             my $info = {
1516             'query_parameters' => {
1517 0           'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1518             },
1519              
1520             'path' => "drives/$driveId",
1521             'method_name' => 'get_drive',
1522             'http_method' => HTTP_METHOD_GET(),
1523             };
1524              
1525             return $self->_handle_api_method( $info, $options );
1526             }
1527              
1528             ###########################################
1529             ###########################################
1530             my ( $self, $driveId ) = @_;
1531              
1532 0           defined $driveId && length $driveId
1533             or LOGDIE('hide_drive() missing drive ID');
1534              
1535             my $info = {
1536             'path' => "drives/$driveId/hide",
1537             'method_name' => 'hide_drive',
1538 0     0 1   'http_method' => HTTP_METHOD_POST(),
1539             };
1540 0 0 0        
1541             return $self->_handle_api_method( $info, {} );
1542             }
1543 0            
1544             ###########################################
1545             ###########################################
1546             my ( $self, $options ) = @_;
1547              
1548             $options //= {};
1549 0            
1550             my $info = {
1551             'query_parameters' => {
1552             'pageSize' => [ TYPE_INTEGER(), 0 ],
1553             'pageToken' => [ TYPE_STRING(), 0 ],
1554             'q' => [ TYPE_STRING(), 0 ],
1555 0     0 1   'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1556             },
1557 0 0 0        
1558             'path' => 'drives',
1559             'method_name' => 'drives',
1560 0   0       'http_method' => HTTP_METHOD_GET(),
1561             };
1562 0            
1563             return $self->_handle_api_method( $info, $options );
1564             }
1565              
1566             ###########################################
1567             ###########################################
1568             my ( $self, $driveId ) = @_;
1569              
1570             defined $driveId && length $driveId
1571             or LOGDIE('unhide_drive() missing drive ID');
1572 0            
1573             my $info = {
1574             'path' => "drives/$driveId/unhide",
1575             'method_name' => 'unhide_drive',
1576             'http_method' => HTTP_METHOD_POST(),
1577             };
1578 0     0 1    
1579             return $self->_handle_api_method( $info, {} );
1580 0 0 0       }
1581              
1582             ###########################################
1583 0           ###########################################
1584             my ( $self, $driveId, $options ) = @_;
1585              
1586             defined $driveId && length $driveId
1587             or LOGDIE('update_drive() missing drive ID');
1588              
1589 0           ref $options eq 'HASH'
1590             or LOGDIE('update_drive() missing parameters');
1591              
1592             my $info = {
1593             'query_parameters' => {
1594             'useDomainAdminAccess' => [ TYPE_BOOLEAN(), 0 ],
1595 0     0 1   },
1596              
1597 0   0       'body_parameters' => [
1598             qw<
1599 0           backgroundImageFile
1600             colorRgb
1601             name
1602             restrictions
1603             themeId
1604             >
1605             ],
1606              
1607             'path' => "drives/$driveId",
1608             'method_name' => 'update_drive',
1609             'http_method' => HTTP_METHOD_PATCH(),
1610             };
1611              
1612 0           return $self->_handle_api_method( $info, $options );
1613             }
1614              
1615             # Helper methods
1616              
1617             ###########################################
1618 0     0 1   ###########################################
1619             my ( $self, $path, $opts, $search_opts ) = @_;
1620 0 0 0        
1621             DEBUG("Determine children of $path");
1622             LOGDIE("No $path given") unless defined $path;
1623 0            
1624             $search_opts //= {};
1625              
1626             my ( $folder_id, $parent ) = $self->_path_resolve( $path, $search_opts );
1627              
1628             return unless defined $folder_id;
1629 0            
1630             DEBUG("Getting content of folder $folder_id");
1631             my $children = $self->children_by_folder_id( $folder_id, $opts, $search_opts ) or return;
1632              
1633             return $children;
1634             }
1635 0     0 1    
1636             # "'page' => 1" is now "'auto_paging' => 1"
1637 0 0 0       ###########################################
1638             ###########################################
1639             my ( $self, $folder_id, $opts, $search_opts ) = @_;
1640 0 0          
1641             $folder_id
1642             or LOGDIE("Must provide a folder id");
1643 0            
1644             $self->init();
1645              
1646             $search_opts = {} unless defined $search_opts;
1647             $opts = {} unless defined $opts;
1648              
1649             exists $search_opts->{'page'}
1650             and LOGDIE("Search option 'page' is deprecated, use 'auto_paging'");
1651              
1652             exists $search_opts->{'title'}
1653             and LOGDIE("Search option 'title' is deprecated, set 'q' parameter accordingly");
1654              
1655             $search_opts->{'auto_paging'} //= 1;
1656              
1657             # Append or create a search in folder
1658             if ( defined $opts->{'q'} && length $opts->{'q'} ) {
1659             $opts->{'q'} .= ' AND ';
1660             }
1661             else {
1662             $opts->{'q'} = '';
1663 0           }
1664              
1665             $opts->{'q'} .= "'$folder_id' in parents";
1666              
1667             # Find only those not in the trash
1668             # possibly go through all paged results
1669             my @children;
1670             while (1) {
1671 0     0 1   my $data = $self->files($opts)
1672             or return;
1673 0            
1674 0 0         my @items = @{ $data->{'files'} || [] };
1675              
1676 0   0       while ( my $item = shift @items ) {
1677             if ( $item->{'labels'}{'trashed'} ) {
1678 0           DEBUG("Skipping $item->{'title'} (item in trash)");
1679             next;
1680 0 0         }
1681              
1682 0           # use the Item.pm object with AUTOLOAD, is_folder, and is_file
1683 0 0         # TODO: I dislke the AUTOLOAD format...
1684             push @children, $self->data_factory($item);
1685 0           }
1686              
1687             if ( $search_opts->{'auto_paging'} && $data->{'nextPageToken'} ) {
1688             $opts->{'pageToken'} = $data->{'nextPageToken'};
1689             }
1690             else {
1691             last;
1692 0     0 1   }
1693             }
1694 0 0          
1695             return \@children;
1696             }
1697 0            
1698             ###########################################
1699 0 0         ###########################################
1700 0 0         my ( $self, $path, $search_opts );
1701              
1702 0 0         $search_opts = {} if !defined $search_opts;
1703              
1704             my @parts = grep length, split '/', $path;
1705 0 0          
1706             my @ids = qw(root);
1707             my $folder_id = my $parent = 'root';
1708 0   0       DEBUG("Parent: $parent");
1709              
1710             PART:
1711 0 0 0       foreach my $part (@parts) {
1712 0           DEBUG("Looking up part $part (folder_id=$folder_id)");
1713              
1714             # We append to 'q' parameter in case the user provided it
1715 0           my $title = $part =~ s{\'}{\\\'}xmsgr;
1716             if ( defined $search_opts->{'q'} && length $search_opts->{'q'} ) {
1717             $search_opts->{'q'} .= ' AND ';
1718 0           }
1719             else {
1720             $search_opts->{'q'} = '';
1721             }
1722 0           $search_opts->{'q'} .= "title = '$title'";
1723 0            
1724 0 0         my $children = $self->children_by_folder_id( $folder_id, {}, $search_opts )
1725             or return;
1726              
1727 0 0         for my $child (@$children) {
  0            
1728             DEBUG("Found child: $child->{'title'}");
1729 0            
1730 0 0         if ( $child->{'title'} eq $part ) {
1731 0           $folder_id = $child->{'id'};
1732 0           unshift @ids, $folder_id;
1733             $parent = $folder_id;
1734             DEBUG("Parent: $parent");
1735             next PART;
1736             }
1737 0           }
1738              
1739             my $msg = "Child $part not found";
1740 0 0 0       $self->error($msg);
1741 0           ERROR($msg);
1742             return;
1743             }
1744 0            
1745             # parent of root is root
1746             if ( @ids == 1 ) {
1747             push @ids, $ids[0];
1748 0           }
1749              
1750             return @ids;
1751             }
1752              
1753             # TODO: Placed here until I have a use for it
1754 0     0     #my %IMPORT_FORMATS = (
1755             # 'application/x-vnd.oasis.opendocument.presentation' => ['application/vnd.google-apps.presentation'],
1756 0 0         # 'text/tab-separated-values' => ['application/vnd.google-apps.spreadsheet'],
1757             # 'image/jpeg' => ['application/vnd.google-apps.document'],
1758 0           # 'image/bmp' => ['application/vnd.google-apps.document'],
1759             # 'image/gif' => ['application/vnd.google-apps.document'],
1760 0           # 'application/vnd.ms-excel.sheet.macroenabled.12' => ['application/vnd.google-apps.spreadsheet'],
1761 0           # 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['application/vnd.google-apps.document'],
1762 0           # 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['application/vnd.google-apps.presentation'],
1763             # 'application/vnd.ms-word.template.macroenabled.12' => ['application/vnd.google-apps.document'],
1764             # 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['application/vnd.google-apps.document'],
1765 0           # 'image/pjpeg' => ['application/vnd.google-apps.document'],
1766 0           # 'application/vnd.google-apps.script+text/plain' => ['application/vnd.google-apps.script'],
1767             # 'application/vnd.ms-excel' => ['application/vnd.google-apps.spreadsheet'],
1768             # 'application/vnd.sun.xml.writer' => ['application/vnd.google-apps.document'],
1769 0           # 'application/vnd.ms-word.document.macroenabled.12' => ['application/vnd.google-apps.document'],
1770 0 0 0       # 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['application/vnd.google-apps.presentation'],
1771 0           # 'text/rtf' => ['application/vnd.google-apps.document'],
1772             # 'application/vnd.oasis.opendocument.spreadsheet' => ['application/vnd.google-apps.spreadsheet'],
1773             # 'text/plain' => ['application/vnd.google-apps.document'],
1774 0           # 'application/x-vnd.oasis.opendocument.spreadsheet' => ['application/vnd.google-apps.spreadsheet'],
1775             # 'application/x-vnd.oasis.opendocument.text' => ['application/vnd.google-apps.document'],
1776 0           # 'image/png' => ['application/vnd.google-apps.document'],
1777             # 'application/msword' => ['application/vnd.google-apps.document'],
1778 0 0         # 'application/pdf' => ['application/vnd.google-apps.document'],
1779             # 'application/x-msmetafile' => ['application/vnd.google-apps.drawing'],
1780             # 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['application/vnd.google-apps.spreadsheet'],
1781 0           # 'application/vnd.ms-powerpoint' => ['application/vnd.google-apps.presentation'],
1782 0           # 'application/vnd.ms-excel.template.macroenabled.12' => ['application/vnd.google-apps.spreadsheet'],
1783             # 'image/x-bmp' => ['application/vnd.google-apps.document'],
1784 0 0         # 'application/rtf' => ['application/vnd.google-apps.document'],
1785 0           # 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['application/vnd.google-apps.presentation'],
1786 0           # 'image/x-png' => ['application/vnd.google-apps.document'],
1787 0           # 'text/html' => ['application/vnd.google-apps.document'],
1788 0           # 'application/vnd.oasis.opendocument.text' => ['application/vnd.google-apps.document'],
1789 0           # 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['application/vnd.google-apps.presentation'],
1790             # 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['application/vnd.google-apps.spreadsheet'],
1791             # 'application/vnd.google-apps.script+json' => ['application/vnd.google-apps.script'],
1792             # 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['application/vnd.google-apps.presentation'],
1793 0           # 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['application/vnd.google-apps.presentation'],
1794 0           # 'text/csv' => ['application/vnd.google-apps.spreadsheet'],
1795 0           # 'application/vnd.oasis.opendocument.presentation' => ['application/vnd.google-apps.presentation'],
1796 0           # 'image/jpg' => ['application/vnd.google-apps.document'],
1797             # 'text/richtext' => ['application/vnd.google-apps.document']
1798             #);
1799             #
1800 0 0         #my @ERXPORT_FORMATS = (
1801 0           # 'application/vnd.google-apps.document' => [
1802             # 'application/rtf',
1803             # 'application/vnd.oasis.opendocument.text',
1804 0           # 'text/html',
1805             # 'application/pdf',
1806             # 'application/epub+zip',
1807             # 'application/zip',
1808             # 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
1809             # 'text/plain'
1810             # ],
1811             #
1812             # 'application/vnd.google-apps.spreadsheet' => [
1813             # 'application/x-vnd.oasis.opendocument.spreadsheet',
1814             # 'text/tab-separated-values',
1815             # 'application/pdf',
1816             # 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
1817             # 'text/csv',
1818             # 'application/zip',
1819             # 'application/vnd.oasis.opendocument.spreadsheet'
1820             # ],
1821             #
1822             # 'application/vnd.google-apps.jam' => ['application/pdf'],
1823             # 'application/vnd.google-apps.script' => ['application/vnd.google-apps.script+json'],
1824             #
1825             # 'application/vnd.google-apps.presentation' => [
1826             # 'application/vnd.oasis.opendocument.presentation',
1827             # 'application/pdf',
1828             # 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
1829             # 'text/plain'
1830             # ],
1831             # 'application/vnd.google-apps.form' => ['application/zip'],
1832             # 'application/vnd.google-apps.drawing' => [ 'image/svg+xml', 'image/png', 'application/pdf', 'image/jpeg' ],
1833             # 'application/vnd.google-apps.site' => ['text/plain']
1834             #);
1835              
1836             1;
1837              
1838              
1839             =head1 SYNOPSIS
1840              
1841             my $gd_v3 = Net::Google::Drive::Simple->new( 'version' => 3 );
1842             # same as:
1843             my $gd_v3 = Net::Google::Drive::Simple::V3->new();
1844              
1845             $gd->changes(...);
1846             $gd->create_comment(...);
1847             $gd->delete_file(...);
1848              
1849             =head1 DESCRIPTION
1850              
1851             This is a complete implementation of the Google Drive API V3. You can
1852             use all the documented methods below.
1853              
1854             =head1 METHODS
1855              
1856             =head2 C<new>
1857              
1858             my $gd = Net::Google::Drive::Simple::V3->new();
1859              
1860             Create a new instance.
1861              
1862             You can also create an instance using L<Net::Google::Drive::Simple>:
1863              
1864             my $gd = Net::Google::Drive::Simple->new( 'version' => 3 );
1865              
1866             =head2 C<about>
1867              
1868             my $about = $gd->about({%params});
1869              
1870             This serves the path to C</about>.
1871              
1872             It's also referred to as C<about.get>.
1873              
1874             You can read about the parameters on the Google Drive
1875             L<API page|https://developers.google.com/drive/api/v3/reference/about/get>.
1876              
1877             =head2 C<getStartPageToken>
1878              
1879             my $data = $gd->getStartPageToken({%params});
1880              
1881             This serves the path to C</changes/startPageToken>.
1882              
1883             This is also known as C<changes_getStartPageToken>.
1884              
1885             You can read about the parameters on the Google Drive
1886             L<API page|https://developers.google.com/drive/api/v3/reference/changes/getStartPageToken>.
1887              
1888             =head2 C<changes>
1889              
1890             my $changes_list = $gd->changes({%params});
1891              
1892             This serves the path to C</changes>.
1893              
1894             This is also known as C<changes.list>.
1895              
1896             You can read about the parameters on the Google Drive
1897             L<API page|https://developers.google.com/drive/api/v3/reference/changes/list>.
1898              
1899             =head2 C<watch_changes>
1900              
1901             my $data = $gd->watch_changes({%params});
1902              
1903             This serves the path to C</changes/watch>.
1904              
1905             This is also known as C<changes.watch>.
1906              
1907             You can read about the parameters on the Google Drive
1908             L<API page|https://developers.google.com/drive/api/v3/reference/changes/watch>.
1909              
1910             =head2 C<stop_channels>
1911              
1912             $gd->stop_channels({%params});
1913              
1914             This serves the path to C</channels/stop>.
1915              
1916             This is also known as C<channels.stop>.
1917              
1918             You can read about the parameters on the Google Drive
1919             L<API page|https://developers.google.com/drive/api/v3/reference/channels/stop>.
1920              
1921             =head2 C<create_comment>
1922              
1923             my $comment = $gd->create_comment( $fileId, {%params} );
1924              
1925             This serves the path to C</files/$fileId/comments>.
1926              
1927             This is also known as C<comments.create>.
1928              
1929             You can read about the parameters on the Google Drive
1930             L<API page|https://developers.google.com/drive/api/v3/reference/comments/create>.
1931              
1932             =head2 C<delete_comment( $fileId, $commentId )>
1933              
1934             $gd->delete_comment( $fileId, $commentId );
1935              
1936             This serves the path to C</files/$fileId/comments/$commentId>.
1937              
1938             This is also known as C<comments.delete>.
1939              
1940             You can read about the parameters on the Google Drive
1941             L<API page|https://developers.google.com/drive/api/v3/reference/comments/delete>.
1942              
1943             =head2 C<get_comment( $fileId, $commentId, $params )>
1944              
1945             my $comment = $gd->get_comment( $fileId, $commentId, {%params} );
1946              
1947             This serves the path to C</files/$fileId/comments/$commentId>.
1948              
1949             This is also known as C<comments.get>.
1950              
1951             You can read about the parameters on the Google Drive
1952             L<API page|https://developers.google.com/drive/api/v3/reference/comments/get>.
1953              
1954             =head2 C<comments>
1955              
1956             my $comments = $gd->comments( $fileId, {%params} );
1957              
1958             This serves the path to C</files/$fileId/comments>.
1959              
1960             This is also known as C<comments.list>.
1961              
1962             You can read about the parameters on the Google Drive
1963             L<API page|https://developers.google.com/drive/api/v3/reference/comments/list>.
1964              
1965             =head2 C<update_comment>
1966              
1967             my $comment = $gd->update_comment( $fileId, $commentId, {%params} );
1968              
1969             This serves the path to C</files/$fileId/comments/$commentId>.
1970              
1971             This is also known as C<comments.update>.
1972              
1973             You can read about the parameters on the Google Drive
1974             L<API page|https://developers.google.com/drive/api/v3/reference/comments/update>.
1975              
1976             =head2 C<copy_file>
1977              
1978             my $file = $gd->copy_file( $fileId, {%params} );
1979              
1980             This serves the path to C</files/$fileId/copy>.
1981              
1982             This is also known as C<files.copy>.
1983              
1984             You can read about the parameters on the Google Drive
1985             L<API page|https://developers.google.com/drive/api/v3/reference/files/copy>.
1986              
1987             =head2 C<create_file>
1988              
1989             my $file = $gd->create_file({%params});
1990              
1991             This serves the path to C</files>.
1992              
1993             This is also known as C<files.create>.
1994              
1995             This one is for creating metadata for a file.
1996              
1997             You can read about the parameters on the Google Drive
1998             L<API page|https://developers.google.com/drive/api/v3/reference/files/create>.
1999              
2000             =head2 C<upload_file>
2001              
2002             my $file = $gd->upload_file({%params});
2003              
2004             This serves the path to C</files>.
2005              
2006             This is also known as C<files.create>.
2007              
2008             This one is for uploading a file, even though it shares a moniker with the
2009             C<create_file()> method in the Google Drive API.
2010              
2011             You can read about the parameters on the Google Drive
2012             L<API page|https://developers.google.com/drive/api/v3/reference/files/create>.
2013              
2014             =head2 C<delete_file>
2015              
2016             $gd->delete_file( $fileId, {%params} );
2017              
2018             This serves the path to C</files/$fileId>.
2019              
2020             This is also known as C<files.delete>.
2021              
2022             You can read about the parameters on the Google Drive
2023             L<API page|https://developers.google.com/drive/api/v3/reference/files/delete>.
2024              
2025             =head2 C<export_file>
2026              
2027             my $file_content_in_bytes = $gd->export_file( $fileId, {%params} );
2028              
2029             This serves the path to C</files/$fileId/export>.
2030              
2031             This is also known as C<files.export>.
2032              
2033             You can read about the parameters on the Google Drive
2034             L<API page|https://developers.google.com/drive/api/v3/reference/files/export>.
2035              
2036             =head2 C<generateIds>
2037              
2038             my $data = $gd->generateIds({%params});
2039              
2040             This serves the path to C</files/generateIds>.
2041              
2042             This is also known as C<files.generateIds>.
2043              
2044             You can read about the parameters on the Google Drive
2045             L<API page|https://developers.google.com/drive/api/v3/reference/files/generateIds>.
2046              
2047             =head2 C<get_file>
2048              
2049             my $file = $gd->get_file( $fileId, {%params} );
2050              
2051             This serves the path to C</files/$fileId>.
2052              
2053             This is also known as C<files.get>.
2054              
2055             You can read about the parameters on the Google Drive
2056             L<API page|https://developers.google.com/drive/api/v3/reference/files/get>.
2057              
2058             =head2 C<files>
2059              
2060             my $files = $gd->files({%params});
2061              
2062             This serves the path to C</files>.
2063              
2064             This is also known as C<files.list>.
2065              
2066             You can read about the parameters on the Google Drive
2067             L<API page|https://developers.google.com/drive/api/v3/reference/files/list>.
2068              
2069             =head2 C<update_file>
2070              
2071             my $file = $gd->update_file( $fileId, {%params} );
2072              
2073             This serves the path to C</files/$fileId>.
2074              
2075             This is also known as C<files.update>.
2076              
2077             This is for updating a file's metadata and content.
2078              
2079             You can read about the parameters on the Google Drive
2080             L<API page|https://developers.google.com/drive/api/v3/reference/files/update>.
2081              
2082             =head2 C<update_file_metadata>
2083              
2084             my $file = $gd->update_file_metadata( $fileId, {%params} );
2085              
2086             This serves the path to C</files/$fileId>.
2087              
2088             This is also known as C<files.update>.
2089              
2090             This one is only for updating a file's metadata, even though it shares
2091             a moniker with the C<update_file()> method in the Google Drive API.
2092              
2093             You can read about the parameters on the Google Drive
2094             L<API page|https://developers.google.com/drive/api/v3/reference/files/update>.
2095              
2096             =head2 C<watch_file>
2097              
2098             my $data = $gd->watch_file( $fileId, {%params} );
2099              
2100             This serves the path to C</files/$fileId/watch>.
2101              
2102             This is also known as C<files.watch>.
2103              
2104             You can read about the parameters on the Google Drive
2105             L<API page|https://developers.google.com/drive/api/v3/reference/files/watch>.
2106              
2107             =head2 C<empty_trash>
2108              
2109             $gd->empty_trash({%params})
2110              
2111             This serves the path to C</files/trash>.
2112              
2113             This is also known as C<files.emptyTrash>.
2114              
2115             You can read about the parameters on the Google Drive
2116             L<API page|https://developers.google.com/drive/api/v3/reference/files/emptyTrash>.
2117              
2118             =head2 C<create_permission>
2119              
2120             my $permission = $gd-><create_permission( $fileId, {%params} );
2121              
2122             This serves the path to C</files/$fileId/permissions>.
2123              
2124             This is also known as C<permissions.create>.
2125              
2126             You can read about the parameters on the Google Drive
2127             L<API page|https://developers.google.com/drive/api/v3/reference/permissions/create>.
2128              
2129             =head2 C<delete_permission>
2130              
2131             $gd->delete_permission( $fileId, $permissionId, {%params} );
2132              
2133             This serves the path to C</files/$fileId/permissions/$permissionId>.
2134              
2135             This is also known as C<permissions.delete>.
2136              
2137             You can read about the parameters on the Google Drive
2138             L<API page|https://developers.google.com/drive/api/v3/reference/permissions/delete>.
2139              
2140             =head2 C<get_permission>
2141              
2142             my $permission = $gd->get_permission( $fileId, $permissionId, {%params} );
2143              
2144             This serves the path to C</files/$fileId/permissions/$permissionId>.
2145              
2146             This is also known as C<permissions.get>.
2147              
2148             You can read about the parameters on the Google Drive
2149             L<API page|https://developers.google.com/drive/api/v3/reference/permissions/get>.
2150              
2151             =head2 C<permissions>
2152              
2153             my $permissions = $gd->permissions( $fileId, {%params} );
2154              
2155             This serves the path to C</files/$fileId/permissions>.
2156              
2157             This is also known as C<permissions.list>.
2158              
2159             You can read about the parameters on the Google Drive
2160             L<API page|https://developers.google.com/drive/api/v3/reference/permissions/list>.
2161              
2162             =head2 C<update_permission>
2163              
2164             my $permission = $gd->update_permission( $fileId, $permissionId, {%params} );
2165              
2166             This serves the path to C</files/$fileId/permissions/$permissionId>.
2167              
2168             This is also known as C<permissions.update>.
2169              
2170             You can read about the parameters on the Google Drive
2171             L<API page|https://developers.google.com/drive/api/v3/reference/permissions/update>.
2172              
2173             =head2 C<create_reply>
2174              
2175             my $reply = $gd->create_reply( $fileId, $commentId, {%params} );
2176              
2177             This serves the path to C</files/$fileId/comments/$commentId/replies>.
2178              
2179             This is also known as C<replies.create>.
2180              
2181             You can read about the parameters on the Google Drive
2182             L<API page|https://developers.google.com/drive/api/v3/reference/replies/create>.
2183              
2184             =head2 C<delete_reply( $fileId, $commentId, $replyId )>
2185              
2186             $gd->delete_reply( $fileId, $commentId, $replyId );
2187              
2188             This serves the path to C</files/$fileId/comments/$commentId/replies/$replyId>.
2189              
2190             This is also known as C<replies.delete>.
2191              
2192             You can read about the parameters on the Google Drive
2193             L<API page|https://developers.google.com/drive/api/v3/reference/replies/delete>.
2194              
2195             =head2 C<get_reply>
2196              
2197             my $reply = %gd->get_reply( $fileId, $commentId, $replyId, {%params} );
2198              
2199             This serves the path to C</files/$fileId/comments/$commentId/replies/$replyId>.
2200              
2201             This is also known as C<replies.get>.
2202              
2203             You can read about the parameters on the Google Drive
2204             L<API page|https://developers.google.com/drive/api/v3/reference/replies/get>.
2205              
2206             =head2 C<replies>
2207              
2208             my $replies = $gd->replies( $fileId, $commentId, {%params} );
2209              
2210             This serves the path to C</files/$fileId/comments/$commentId/replies>.
2211              
2212             This is also known as C<replies.list>.
2213              
2214             You can read about the parameters on the Google Drive
2215             L<API page|https://developers.google.com/drive/api/v3/reference/replies/list>.
2216              
2217             =head2 C<update_reply>
2218              
2219             my $reply = $gd->update_reply( $fileId, $commentId, $replyId, {%params} );
2220              
2221             This serves the path to C</files/$fileId/comments/$commentId/replies/$replyId>.
2222              
2223             This is also known as C<replies.update>.
2224              
2225             You can read about the parameters on the Google Drive
2226             L<API page|https://developers.google.com/drive/api/v3/reference/replies/update>.
2227              
2228             =head2 C<delete_revision>
2229              
2230             $gd->delete_revision( $fileId, {%params} );
2231              
2232             This serves the path to C</files/$fileId/revisions/$revisionId>.
2233              
2234             This is also known as C<revisions.delete>.
2235              
2236             You can read about the parameters on the Google Drive
2237             L<API page|https://developers.google.com/drive/api/v3/reference/revisions/delete>.
2238              
2239             =head2 C<get_revision( $fileId, $revisionId, $params )>
2240              
2241             my $revision = $gd->get_revision( $fileId, $revisionId, {%params} );
2242              
2243             This serves the path to C</files/$fileId/revisions/$revisionId>.
2244              
2245             This is also known as C<revisions.get>.
2246              
2247             You can read about the parameters on the Google Drive
2248             L<API page|https://developers.google.com/drive/api/v3/reference/revisions/get>.
2249              
2250             =head2 C<revisions>
2251              
2252             my $revisions = $gd->revisions( $fileId, {%params} );
2253              
2254             This serves the path to C</files/$fileId/revisions>.
2255              
2256             This is also known as C<revisions.list>.
2257              
2258             You can read about the parameters on the Google Drive
2259             L<API page|https://developers.google.com/drive/api/v3/reference/revisions/list>.
2260              
2261             =head2 C<update_revision>
2262              
2263             my $revision = $gd->update_revision( $fileId, $revisionId, {%params} );
2264              
2265             This serves the path to C</files/$fileId/revisions/$revisionId>.
2266              
2267             This is also known as C<revisions.update>.
2268              
2269             You can read about the parameters on the Google Drive
2270             L<API page|https://developers.google.com/drive/api/v3/reference/revisions/update>.
2271              
2272             =head2 C<create_drive>
2273              
2274             my $drive = $gd->create_drive({%params});
2275              
2276             This serves the path to C</drives>.
2277              
2278             This is also known as C<drives.create>.
2279              
2280             You can read about the parameters on the Google Drive
2281             L<API page|https://developers.google.com/drive/api/v3/reference/drives/create>.
2282              
2283             =head2 C<delete_drive>
2284              
2285             $gd->delete_drive($driveId);
2286              
2287             This serves the path to C</drives/$driveId>.
2288              
2289             This is also known as C<drives.delete>.
2290              
2291             You can read about the parameters on the Google Drive
2292             L<API page|https://developers.google.com/drive/api/v3/reference/drives/delete>.
2293              
2294             =head2 C<get_drive>
2295              
2296             my $drive = $gd->get_drive( $driveId, {%params} );
2297              
2298             This serves the path to C</drives/$driveId>.
2299              
2300             This is also known as C<drives.get>.
2301              
2302             You can read about the parameters on the Google Drive
2303             L<API page|https://developers.google.com/drive/api/v3/reference/drives/get>.
2304              
2305             =head2 C<hide_drive>
2306              
2307             my $drive = $gd->hide_drive($driveId);
2308              
2309             This serves the path to C</drives/$driveId/hide>.
2310              
2311             This is also known as C<drives.hide>.
2312              
2313             You can read about the parameters on the Google Drive
2314             L<API page|https://developers.google.com/drive/api/v3/reference/drives/hide>.
2315              
2316             =head2 C<drives>
2317              
2318             my $drives = $gd->drives({%params});
2319              
2320             This serves the path to C</drives>.
2321              
2322             This is also known as C<drives.list>.
2323              
2324             You can read about the parameters on the Google Drive
2325             L<API page|https://developers.google.com/drive/api/v3/reference/drives/list>.
2326              
2327             =head2 C<unhide_drive>
2328              
2329             my $drive = $gd->unhide_drive($driveId);
2330              
2331             This serves the path to C</drives/$driveId/unhide>.
2332              
2333             This is also known as C<drives.unhide>.
2334              
2335             You can read about the parameters on the Google Drive
2336             L<API page|https://developers.google.com/drive/api/v3/reference/drives/unhide>.
2337              
2338             =head2 C<update_drive>
2339              
2340             my $drive = $gd->update_drive( $driveId, {%params} );
2341              
2342             This serves the path to C</drives/$driveId>.
2343              
2344             This is also known as C<drives.update>.
2345              
2346             You can read about the parameters on the Google Drive
2347             L<API page|https://developers.google.com/drive/api/v3/reference/drives/update>.
2348              
2349             =head2 C<children>
2350              
2351             my $children = $gd->children( "/path/to" )>
2352              
2353             Return the entries under a given path on the Google Drive as a reference
2354             to an array. Each entry
2355             is an object composed of the JSON data returned by the Google Drive API.
2356             Each object offers methods named like the fields in the JSON data, e.g.
2357             C<originalFilename()>, C<downloadUrl>, etc.
2358              
2359             Will return all entries found unless C<maxResults> is set:
2360              
2361             my $children = $gd->children( "/path/to", { maxResults => 3 } )
2362              
2363             Due to the somewhat capricious ways Google Drive handles its directory
2364             structures, the method needs to traverse the path component by component
2365             and determine the ID of each directory to get to the next level. To speed
2366             up subsequent lookups, it also returns the ID of the last component to the
2367             caller:
2368              
2369             my( $children, $parent ) = $gd->children( "/path/to" );
2370              
2371             If the caller now wants to e.g. insert a file into the directory, its
2372             ID is available in $parent.
2373              
2374             Each child comes back as a files#resource type and gets mapped into
2375             an object that offers access to the various fields via methods:
2376              
2377             for my $child ( @$children ) {
2378             print $child->kind(), " ", $child->title(), "\n";
2379             }
2380              
2381             Please refer to
2382              
2383             https://developers.google.com/drive/v3/reference/files#resource
2384              
2385             for details on which fields are available.
2386              
2387             =head2 C<children_by_folder_id>
2388              
2389             my $children = $gd->children_by_folder_id($folderId);
2390              
2391             # Search with a particular query and stop at the first page
2392             my $children = $gd->children_by_folder_id(
2393             $folderId,
2394             { 'q' => q{name contains 'hello'} },
2395             { 'auto_paging' => 0 },
2396             );
2397              
2398             Similar to C<children()> but uses a folder ID.
2399              
2400             The second parameter is the parameters the C<files()> method receives.
2401              
2402             The third parameter is for additional options on how to conduct this
2403             search. Only one option is supported: C<auto_paging>.
2404              
2405             When C<auto_paging> is turned on (which is the default), the search
2406             will be done on every page of the results instead of stopping at the
2407             first page.
2408              
2409             =head1 LEGALESE
2410              
2411             Copyright 2012-2019 by Mike Schilli, all rights reserved.
2412             This program is free software, you can redistribute it and/or
2413             modify it under the same terms as Perl itself.
2414              
2415             =head1 AUTHOR
2416              
2417             Sawyer X <xsawyerx@cpan.org>