google_drive 2.1.8 → 2.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/google_drive.rb +9 -4
- data/lib/google_drive/acl.rb +16 -11
- data/lib/google_drive/acl_entry.rb +18 -16
- data/lib/google_drive/api_client_fetcher.rb +3 -3
- data/lib/google_drive/collection.rb +50 -39
- data/lib/google_drive/config.rb +2 -2
- data/lib/google_drive/file.rb +35 -25
- data/lib/google_drive/list.rb +3 -1
- data/lib/google_drive/list_row.rb +11 -10
- data/lib/google_drive/response_code_error.rb +4 -1
- data/lib/google_drive/session.rb +191 -122
- data/lib/google_drive/spreadsheet.rb +34 -24
- data/lib/google_drive/util.rb +44 -25
- data/lib/google_drive/worksheet.rb +126 -53
- metadata +4 -4
data/lib/google_drive/list.rb
CHANGED
@@ -116,7 +116,9 @@ module GoogleDrive
|
|
116
116
|
def key_to_col(key)
|
117
117
|
key = key.to_s
|
118
118
|
col = (1..@worksheet.num_cols).find { |c| @worksheet[1, c] == key }
|
119
|
-
|
119
|
+
unless col
|
120
|
+
raise(GoogleDrive::Error, format("Column doesn't exist: %p", key))
|
121
|
+
end
|
120
122
|
col
|
121
123
|
end
|
122
124
|
end
|
@@ -13,9 +13,10 @@ module GoogleDrive
|
|
13
13
|
extend(Forwardable)
|
14
14
|
|
15
15
|
def_delegators(:to_hash,
|
16
|
-
:keys, :values, :each_key, :each_value, :each, :each_pair,
|
17
|
-
:assoc, :fetch, :flatten, :key, :invert, :size,
|
18
|
-
:merge, :reject, :select, :sort, :to_a,
|
16
|
+
:keys, :values, :each_key, :each_value, :each, :each_pair,
|
17
|
+
:hash, :assoc, :fetch, :flatten, :key, :invert, :size,
|
18
|
+
:length, :rassoc, :merge, :reject, :select, :sort, :to_a,
|
19
|
+
:values_at)
|
19
20
|
|
20
21
|
# @api private
|
21
22
|
def initialize(list, index)
|
@@ -43,9 +44,9 @@ module GoogleDrive
|
|
43
44
|
@list.keys.include?(key)
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
alias include? has_key?
|
48
|
+
alias key? has_key?
|
49
|
+
alias member? has_key?
|
49
50
|
|
50
51
|
def update(hash)
|
51
52
|
hash.each do |k, v|
|
@@ -53,7 +54,7 @@ module GoogleDrive
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
+
alias merge! update
|
57
58
|
|
58
59
|
def replace(hash)
|
59
60
|
clear
|
@@ -78,11 +79,11 @@ module GoogleDrive
|
|
78
79
|
self.class == other.class && to_hash == other.to_hash
|
79
80
|
end
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
alias === ==
|
83
|
+
alias eql? ==
|
83
84
|
|
84
85
|
def inspect
|
85
|
-
"\#<%p %p>"
|
86
|
+
format("\#<%p %p>", self.class, to_hash)
|
86
87
|
end
|
87
88
|
end
|
88
89
|
end
|
@@ -12,7 +12,10 @@ module GoogleDrive
|
|
12
12
|
def initialize(code, body, method, url)
|
13
13
|
@code = code
|
14
14
|
@body = body
|
15
|
-
super(
|
15
|
+
super(format(
|
16
|
+
'Response code %s for %s %s: %s',
|
17
|
+
code, method, url, CGI.unescapeHTML(body)
|
18
|
+
))
|
16
19
|
end
|
17
20
|
|
18
21
|
attr_reader(:code, :body)
|
data/lib/google_drive/session.rb
CHANGED
@@ -23,8 +23,8 @@ require 'google_drive/access_token_credentials'
|
|
23
23
|
module GoogleDrive
|
24
24
|
# A session for Google Drive operations.
|
25
25
|
#
|
26
|
-
# Use from_credentials, from_access_token, from_service_account_key or
|
27
|
-
# class method to construct a GoogleDrive::Session object.
|
26
|
+
# Use from_credentials, from_access_token, from_service_account_key or
|
27
|
+
# from_config class method to construct a GoogleDrive::Session object.
|
28
28
|
class Session
|
29
29
|
include(Util)
|
30
30
|
extend(Util)
|
@@ -32,7 +32,7 @@ module GoogleDrive
|
|
32
32
|
DEFAULT_SCOPE = [
|
33
33
|
'https://www.googleapis.com/auth/drive',
|
34
34
|
'https://spreadsheets.google.com/feeds/'
|
35
|
-
]
|
35
|
+
].freeze
|
36
36
|
|
37
37
|
# Equivalent of either from_credentials or from_access_token.
|
38
38
|
def self.login_with_oauth(credentials_or_access_token, proxy = nil)
|
@@ -47,7 +47,9 @@ module GoogleDrive
|
|
47
47
|
# Constructs a GoogleDrive::Session object from OAuth2 credentials such as
|
48
48
|
# Google::Auth::UserRefreshCredentials.
|
49
49
|
#
|
50
|
-
# See
|
50
|
+
# See
|
51
|
+
# https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md
|
52
|
+
# for a usage example.
|
51
53
|
def self.from_credentials(credentials)
|
52
54
|
Session.new(credentials)
|
53
55
|
end
|
@@ -59,29 +61,38 @@ module GoogleDrive
|
|
59
61
|
|
60
62
|
# Constructs a GoogleDrive::Session object from a service account key JSON.
|
61
63
|
#
|
62
|
-
# You can pass either the path to a JSON file, or an IO-like object with the
|
64
|
+
# You can pass either the path to a JSON file, or an IO-like object with the
|
65
|
+
# JSON.
|
63
66
|
#
|
64
|
-
# See
|
65
|
-
|
67
|
+
# See
|
68
|
+
# https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md
|
69
|
+
# for a usage example.
|
70
|
+
def self.from_service_account_key(
|
71
|
+
json_key_path_or_io, scope = DEFAULT_SCOPE
|
72
|
+
)
|
66
73
|
if json_key_path_or_io.is_a?(String)
|
67
74
|
open(json_key_path_or_io) do |f|
|
68
75
|
from_service_account_key(f, scope)
|
69
76
|
end
|
70
77
|
else
|
71
78
|
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
|
72
|
-
|
79
|
+
json_key_io: json_key_path_or_io, scope: scope
|
80
|
+
)
|
73
81
|
Session.new(credentials)
|
74
82
|
end
|
75
83
|
end
|
76
84
|
|
77
|
-
# Returns GoogleDrive::Session constructed from a config JSON file at
|
85
|
+
# Returns GoogleDrive::Session constructed from a config JSON file at
|
86
|
+
# +config+.
|
78
87
|
#
|
79
88
|
# +config+ is the path to the config file.
|
80
89
|
#
|
81
|
-
# This will prompt the credential via command line for the first time and
|
82
|
-
# +config+ for later usages.
|
90
|
+
# This will prompt the credential via command line for the first time and
|
91
|
+
# save it to +config+ for later usages.
|
83
92
|
#
|
84
|
-
# See
|
93
|
+
# See
|
94
|
+
# https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md
|
95
|
+
# for a usage example.
|
85
96
|
#
|
86
97
|
# You can also provide a config object that must respond to:
|
87
98
|
# client_id
|
@@ -97,7 +108,8 @@ module GoogleDrive
|
|
97
108
|
config = Config.new(config_path)
|
98
109
|
if config.type == 'service_account'
|
99
110
|
return from_service_account_key(
|
100
|
-
|
111
|
+
config_path, options[:scope] || DEFAULT_SCOPE
|
112
|
+
)
|
101
113
|
end
|
102
114
|
end
|
103
115
|
|
@@ -108,23 +120,31 @@ module GoogleDrive
|
|
108
120
|
config.client_secret = options[:client_secret]
|
109
121
|
end
|
110
122
|
if !config.client_id && !config.client_secret
|
111
|
-
config.client_id =
|
123
|
+
config.client_id =
|
124
|
+
'452925651630-egr1f18o96acjjvphpbbd1qlsevkho1d.' \
|
125
|
+
'apps.googleusercontent.com'
|
112
126
|
config.client_secret = '1U3-Krii5x1oLPrwD5zgn-ry'
|
113
127
|
elsif !config.client_id || !config.client_secret
|
114
|
-
|
128
|
+
raise(
|
129
|
+
ArgumentError,
|
130
|
+
'client_id and client_secret must be both specified or both omitted'
|
131
|
+
)
|
115
132
|
end
|
116
133
|
|
117
134
|
credentials = Google::Auth::UserRefreshCredentials.new(
|
118
135
|
client_id: config.client_id,
|
119
136
|
client_secret: config.client_secret,
|
120
137
|
scope: config.scope,
|
121
|
-
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob'
|
138
|
+
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob'
|
139
|
+
)
|
122
140
|
|
123
141
|
if config.refresh_token
|
124
142
|
credentials.refresh_token = config.refresh_token
|
125
143
|
credentials.fetch_access_token!
|
126
144
|
else
|
127
|
-
$stderr.print(
|
145
|
+
$stderr.print(
|
146
|
+
format("\n1. Open this page:\n%s\n\n", credentials.authorization_uri)
|
147
|
+
)
|
128
148
|
$stderr.print('2. Enter the authorization code shown in the page: ')
|
129
149
|
credentials.code = $stdin.gets.chomp
|
130
150
|
credentials.fetch_access_token!
|
@@ -138,9 +158,11 @@ module GoogleDrive
|
|
138
158
|
|
139
159
|
def initialize(credentials_or_access_token, proxy = nil)
|
140
160
|
if proxy
|
141
|
-
|
161
|
+
raise(
|
142
162
|
ArgumentError,
|
143
|
-
'Specifying a proxy object is no longer supported.
|
163
|
+
'Specifying a proxy object is no longer supported. ' \
|
164
|
+
'Set ENV["http_proxy"] instead.'
|
165
|
+
)
|
144
166
|
end
|
145
167
|
|
146
168
|
if credentials_or_access_token
|
@@ -148,8 +170,12 @@ module GoogleDrive
|
|
148
170
|
credentials = AccessTokenCredentials.new(credentials_or_access_token)
|
149
171
|
# Equivalent of credentials_or_access_token.is_a?(OAuth2::AccessToken),
|
150
172
|
# without adding dependency to "oauth2" library.
|
151
|
-
elsif credentials_or_access_token
|
152
|
-
|
173
|
+
elsif credentials_or_access_token
|
174
|
+
.class
|
175
|
+
.ancestors
|
176
|
+
.any? { |m| m.name == 'OAuth2::AccessToken' }
|
177
|
+
credentials =
|
178
|
+
AccessTokenCredentials.new(credentials_or_access_token.token)
|
153
179
|
else
|
154
180
|
credentials = credentials_or_access_token
|
155
181
|
end
|
@@ -168,16 +194,18 @@ module GoogleDrive
|
|
168
194
|
@fetcher.drive
|
169
195
|
end
|
170
196
|
|
171
|
-
# Returns list of files for the user as array of GoogleDrive::File or its
|
172
|
-
# You can specify parameters documented at
|
197
|
+
# Returns list of files for the user as array of GoogleDrive::File or its
|
198
|
+
# subclass. You can specify parameters documented at
|
173
199
|
# https://developers.google.com/drive/v3/web/search-parameters
|
174
200
|
#
|
175
201
|
# e.g.
|
176
202
|
# session.files
|
177
203
|
# session.files(q: "name = 'hoge'")
|
178
|
-
#
|
204
|
+
# # Same as above with a placeholder
|
205
|
+
# session.files(q: ["name = ?", "hoge"])
|
179
206
|
#
|
180
|
-
# By default, it returns the first 100 files. You can get all files by
|
207
|
+
# By default, it returns the first 100 files. You can get all files by
|
208
|
+
# calling with a block:
|
181
209
|
# session.files do |file|
|
182
210
|
# p file
|
183
211
|
# end
|
@@ -190,21 +218,24 @@ module GoogleDrive
|
|
190
218
|
def files(params = {}, &block)
|
191
219
|
params = convert_params(params)
|
192
220
|
execute_paged!(
|
193
|
-
method:
|
194
|
-
parameters: {fields: '*', supports_team_drives: true}.merge(params),
|
221
|
+
method: drive.method(:list_files),
|
222
|
+
parameters: { fields: '*', supports_team_drives: true }.merge(params),
|
195
223
|
items_method_name: :files,
|
196
224
|
converter: proc { |af| wrap_api_file(af) },
|
197
|
-
&block
|
225
|
+
&block
|
226
|
+
)
|
198
227
|
end
|
199
228
|
|
200
|
-
# Returns a file (including a spreadsheet and a folder) whose title exactly
|
229
|
+
# Returns a file (including a spreadsheet and a folder) whose title exactly
|
230
|
+
# matches +title+.
|
201
231
|
#
|
202
|
-
# Returns an instance of GoogleDrive::File or its subclass
|
203
|
-
# GoogleDrive::Collection). Returns nil if not
|
204
|
-
# found, returns one of them.
|
232
|
+
# Returns an instance of GoogleDrive::File or its subclass
|
233
|
+
# (GoogleDrive::Spreadsheet, GoogleDrive::Collection). Returns nil if not
|
234
|
+
# found. If multiple files with the +title+ are found, returns one of them.
|
205
235
|
#
|
206
|
-
# If given an Array, traverses folders by title. e.g
|
207
|
-
# session.file_by_title(
|
236
|
+
# If given an Array, traverses folders by title. e.g.:
|
237
|
+
# session.file_by_title(
|
238
|
+
# ["myfolder", "mysubfolder/even/w/slash", "myfile"])
|
208
239
|
def file_by_title(title)
|
209
240
|
if title.is_a?(Array)
|
210
241
|
root_collection.file_by_title(title)
|
@@ -212,46 +243,49 @@ module GoogleDrive
|
|
212
243
|
files(q: ['name = ?', title], page_size: 1)[0]
|
213
244
|
end
|
214
245
|
end
|
215
|
-
|
246
|
+
|
216
247
|
alias file_by_name file_by_title
|
217
248
|
|
218
249
|
# Returns a file (including a spreadsheet and a folder) with a given +id+.
|
219
250
|
#
|
220
|
-
# Returns an instance of GoogleDrive::File or its subclass
|
221
|
-
# GoogleDrive::Collection).
|
251
|
+
# Returns an instance of GoogleDrive::File or its subclass
|
252
|
+
# (GoogleDrive::Spreadsheet, GoogleDrive::Collection).
|
222
253
|
def file_by_id(id)
|
223
|
-
api_file =
|
254
|
+
api_file = drive.get_file(id, fields: '*', supports_team_drives: true)
|
224
255
|
wrap_api_file(api_file)
|
225
256
|
end
|
226
257
|
|
227
258
|
# Returns a file (including a spreadsheet and a folder) with a given +url+.
|
228
|
-
# +url+ must be
|
229
|
-
#
|
230
|
-
# - URL of worksheet-based feed of a spreadseet
|
259
|
+
# +url+ must be the URL of the page you open to access a
|
260
|
+
# document/spreadsheet in your browser.
|
231
261
|
#
|
232
|
-
# Returns an instance of GoogleDrive::File or its subclass
|
233
|
-
# GoogleDrive::Collection).
|
262
|
+
# Returns an instance of GoogleDrive::File or its subclass
|
263
|
+
# (GoogleDrive::Spreadsheet, GoogleDrive::Collection).
|
234
264
|
def file_by_url(url)
|
235
265
|
file_by_id(url_to_id(url))
|
236
266
|
end
|
237
267
|
|
238
|
-
# Returns list of spreadsheets for the user as array of
|
268
|
+
# Returns list of spreadsheets for the user as array of
|
269
|
+
# GoogleDrive::Spreadsheet.
|
239
270
|
# You can specify parameters documented at
|
240
271
|
# https://developers.google.com/drive/v3/web/search-parameters
|
241
272
|
#
|
242
273
|
# e.g.
|
243
274
|
# session.spreadsheets
|
244
275
|
# session.spreadsheets(q: "name = 'hoge'")
|
245
|
-
#
|
276
|
+
# # Same as above with a placeholder
|
277
|
+
# session.spreadsheets(q: ["name = ?", "hoge"])
|
246
278
|
#
|
247
|
-
# By default, it returns the first 100 spreadsheets. See document of files
|
248
|
-
# all spreadsheets.
|
279
|
+
# By default, it returns the first 100 spreadsheets. See document of files
|
280
|
+
# method for how to get all spreadsheets.
|
249
281
|
def spreadsheets(params = {}, &block)
|
250
282
|
params = convert_params(params)
|
251
|
-
query = construct_and_query(
|
252
|
-
|
253
|
-
|
254
|
-
|
283
|
+
query = construct_and_query(
|
284
|
+
[
|
285
|
+
"mimeType = 'application/vnd.google-apps.spreadsheet'",
|
286
|
+
params[:q]
|
287
|
+
]
|
288
|
+
)
|
255
289
|
files(params.merge(q: query), &block)
|
256
290
|
end
|
257
291
|
|
@@ -259,63 +293,76 @@ module GoogleDrive
|
|
259
293
|
#
|
260
294
|
# e.g.
|
261
295
|
# # https://docs.google.com/spreadsheets/d/1L3-kvwJblyW_TvjYD-7pE-AXxw5_bkb6S_MljuIPVL0/edit
|
262
|
-
# session.spreadsheet_by_key(
|
296
|
+
# session.spreadsheet_by_key(
|
297
|
+
# "1L3-kvwJblyW_TvjYD-7pE-AXxw5_bkb6S_MljuIPVL0")
|
263
298
|
def spreadsheet_by_key(key)
|
264
299
|
file = file_by_id(key)
|
265
300
|
unless file.is_a?(Spreadsheet)
|
266
|
-
|
301
|
+
raise(
|
302
|
+
GoogleDrive::Error,
|
303
|
+
format('The file with the ID is not a spreadsheet: %s', key)
|
304
|
+
)
|
267
305
|
end
|
268
306
|
file
|
269
307
|
end
|
270
308
|
|
271
|
-
# Returns GoogleDrive::Spreadsheet with given +url+. You must specify either
|
309
|
+
# Returns GoogleDrive::Spreadsheet with given +url+. You must specify either
|
310
|
+
# of:
|
272
311
|
# - URL of the page you open to access the spreadsheet in your browser
|
273
312
|
# - URL of worksheet-based feed of the spreadseet
|
274
313
|
#
|
275
314
|
# e.g.
|
276
315
|
# session.spreadsheet_by_url(
|
277
|
-
# "https://docs.google.com/spreadsheets/d/
|
278
|
-
#
|
279
|
-
# "https://spreadsheets.google.com/feeds/" +
|
280
|
-
# "worksheets/1L3-kvwJblyW_TvjYD-7pE-AXxw5_bkb6S_MljuIPVL0/private/full")
|
316
|
+
# "https://docs.google.com/spreadsheets/d/" \
|
317
|
+
# "1L3-kvwJblyW_TvjYD-7pE-AXxw5_bkb6S_MljuIPVL0/edit")
|
281
318
|
def spreadsheet_by_url(url)
|
282
319
|
file = file_by_url(url)
|
283
320
|
unless file.is_a?(Spreadsheet)
|
284
|
-
|
321
|
+
raise(
|
322
|
+
GoogleDrive::Error,
|
323
|
+
format('The file with the URL is not a spreadsheet: %s', url)
|
324
|
+
)
|
285
325
|
end
|
286
326
|
file
|
287
327
|
end
|
288
328
|
|
289
329
|
# Returns GoogleDrive::Spreadsheet with given +title+.
|
290
|
-
# Returns nil if not found. If multiple spreadsheets with the +title+ are
|
291
|
-
# one of them.
|
330
|
+
# Returns nil if not found. If multiple spreadsheets with the +title+ are
|
331
|
+
# found, returns one of them.
|
292
332
|
def spreadsheet_by_title(title)
|
293
333
|
spreadsheets(q: ['name = ?', title], page_size: 1)[0]
|
294
334
|
end
|
295
|
-
|
335
|
+
|
296
336
|
alias spreadsheet_by_name spreadsheet_by_title
|
297
337
|
|
298
338
|
# Returns GoogleDrive::Worksheet with given +url+.
|
299
|
-
# You must specify URL of either worksheet feed or cell-based feed of the
|
339
|
+
# You must specify URL of either worksheet feed or cell-based feed of the
|
340
|
+
# worksheet.
|
300
341
|
#
|
301
342
|
# e.g.:
|
302
343
|
# # Worksheet feed URL
|
303
344
|
# session.worksheet_by_url(
|
304
|
-
# "https://spreadsheets.google.com/feeds/worksheets/"
|
345
|
+
# "https://spreadsheets.google.com/feeds/worksheets/" \
|
305
346
|
# "1smypkyAz4STrKO4Zkos5Z4UPUJKvvgIza32LnlQ7OGw/private/full/od7")
|
306
347
|
# # Cell-based feed URL
|
307
348
|
# session.worksheet_by_url(
|
308
|
-
# "https://spreadsheets.google.com/feeds/cells/"
|
349
|
+
# "https://spreadsheets.google.com/feeds/cells/" \
|
309
350
|
# "1smypkyAz4STrKO4Zkos5Z4UPUJKvvgIza32LnlQ7OGw/od7/private/full")
|
310
351
|
def worksheet_by_url(url)
|
311
352
|
case url
|
312
353
|
when %r{^https?://spreadsheets.google.com/feeds/worksheets/.*/.*/full/.*$}
|
313
354
|
worksheet_feed_url = url
|
314
355
|
when %r{^https?://spreadsheets.google.com/feeds/cells/(.*)/(.*)/private/full((\?.*)?)$}
|
315
|
-
worksheet_feed_url =
|
316
|
-
|
356
|
+
worksheet_feed_url =
|
357
|
+
'https://spreadsheets.google.com/feeds/worksheets/' \
|
358
|
+
"#{Regexp.last_match(1)}/private/full/" \
|
359
|
+
"#{Regexp.last_match(2)}#{Regexp.last_match(3)}"
|
317
360
|
else
|
318
|
-
|
361
|
+
raise(
|
362
|
+
GoogleDrive::Error,
|
363
|
+
'URL is neither a worksheet feed URL nor a cell-based feed URL: ' \
|
364
|
+
"#{url}"
|
365
|
+
)
|
319
366
|
end
|
320
367
|
|
321
368
|
worksheet_feed_entry = request(:get, worksheet_feed_url)
|
@@ -326,45 +373,49 @@ module GoogleDrive
|
|
326
373
|
def root_collection
|
327
374
|
@root_collection ||= file_by_id('root')
|
328
375
|
end
|
329
|
-
|
376
|
+
|
330
377
|
alias root_folder root_collection
|
331
378
|
|
332
379
|
# Returns the top-level folders (direct children of the root folder).
|
333
380
|
#
|
334
|
-
# By default, it returns the first 100 folders. See document of files method
|
335
|
-
# all folders.
|
381
|
+
# By default, it returns the first 100 folders. See document of files method
|
382
|
+
# for how to get all folders.
|
336
383
|
def collections(params = {}, &block)
|
337
384
|
root_collection.subcollections(params, &block)
|
338
385
|
end
|
339
|
-
|
386
|
+
|
340
387
|
alias folders collections
|
341
388
|
|
342
389
|
# Returns a top-level folder whose title exactly matches +title+ as
|
343
390
|
# GoogleDrive::Collection.
|
344
|
-
# Returns nil if not found. If multiple folders with the +title+ are found,
|
345
|
-
# one of them.
|
391
|
+
# Returns nil if not found. If multiple folders with the +title+ are found,
|
392
|
+
# returns one of them.
|
346
393
|
def collection_by_title(title)
|
347
394
|
root_collection.subcollection_by_title(title)
|
348
395
|
end
|
349
|
-
|
396
|
+
|
350
397
|
alias folders_by_name collection_by_title
|
351
398
|
|
352
399
|
# Returns GoogleDrive::Collection with given +url+.
|
353
400
|
#
|
354
|
-
# You must specify the URL of the page you get when you go to
|
355
|
-
# with your browser and open a folder.
|
401
|
+
# You must specify the URL of the page you get when you go to
|
402
|
+
# https://drive.google.com/ with your browser and open a folder.
|
356
403
|
#
|
357
404
|
# e.g.
|
358
405
|
# session.collection_by_url(
|
359
|
-
# "https://drive.google.com/drive/folders/
|
406
|
+
# "https://drive.google.com/drive/folders/" \
|
407
|
+
# "1u99gpfHIk08RVK5q_vXxUqkxR1r6FUJH")
|
360
408
|
def collection_by_url(url)
|
361
409
|
file = file_by_url(url)
|
362
410
|
unless file.is_a?(Collection)
|
363
|
-
|
411
|
+
raise(
|
412
|
+
GoogleDrive::Error,
|
413
|
+
format('The file with the URL is not a folder: %s', url)
|
414
|
+
)
|
364
415
|
end
|
365
416
|
file
|
366
417
|
end
|
367
|
-
|
418
|
+
|
368
419
|
alias folder_by_url collection_by_url
|
369
420
|
|
370
421
|
# Creates new spreadsheet and returns the new GoogleDrive::Spreadsheet.
|
@@ -376,7 +427,7 @@ module GoogleDrive
|
|
376
427
|
name: title,
|
377
428
|
mime_type: 'application/vnd.google-apps.spreadsheet'
|
378
429
|
}
|
379
|
-
file =
|
430
|
+
file = drive.create_file(file_metadata, fields: '*')
|
380
431
|
wrap_api_file(file)
|
381
432
|
end
|
382
433
|
|
@@ -386,15 +437,17 @@ module GoogleDrive
|
|
386
437
|
# e.g.
|
387
438
|
# # Uploads and converts to a Google Docs document:
|
388
439
|
# session.upload_from_string(
|
389
|
-
# "Hello world.", "Hello", :
|
440
|
+
# "Hello world.", "Hello", content_type: "text/plain")
|
390
441
|
#
|
391
442
|
# # Uploads without conversion:
|
392
443
|
# session.upload_from_string(
|
393
|
-
# "Hello world.", "Hello", :
|
444
|
+
# "Hello world.", "Hello", content_type: "text/plain", convert: false)
|
394
445
|
#
|
395
446
|
# # Uploads and converts to a Google Spreadsheet:
|
396
|
-
# session.upload_from_string(
|
397
|
-
#
|
447
|
+
# session.upload_from_string(
|
448
|
+
# "hoge\tfoo\n", "Hoge", content_type: "text/tab-separated-values")
|
449
|
+
# session.upload_from_string(
|
450
|
+
# "hoge,foo\n", "Hoge", content_type: "text/tsv")
|
398
451
|
def upload_from_string(content, title = 'Untitled', params = {})
|
399
452
|
upload_from_source(StringIO.new(content), title, params)
|
400
453
|
end
|
@@ -407,14 +460,16 @@ module GoogleDrive
|
|
407
460
|
# session.upload_from_file("/path/to/hoge.txt")
|
408
461
|
#
|
409
462
|
# # Uploads without conversion:
|
410
|
-
# session.upload_from_file("/path/to/hoge.txt", "Hoge", :
|
463
|
+
# session.upload_from_file("/path/to/hoge.txt", "Hoge", convert: false)
|
411
464
|
#
|
412
465
|
# # Uploads with explicit content type:
|
413
|
-
# session.upload_from_file(
|
466
|
+
# session.upload_from_file(
|
467
|
+
# "/path/to/hoge", "Hoge", content_type: "text/plain")
|
414
468
|
#
|
415
469
|
# # Uploads a text file and converts to a Google Spreadsheet:
|
416
470
|
# session.upload_from_file("/path/to/hoge.csv", "Hoge")
|
417
|
-
# session.upload_from_file(
|
471
|
+
# session.upload_from_file(
|
472
|
+
# "/path/to/hoge", "Hoge", content_type: "text/csv")
|
418
473
|
def upload_from_file(path, title = nil, params = {})
|
419
474
|
# TODO: Add a feature to upload to a folder.
|
420
475
|
file_name = ::File.basename(path)
|
@@ -424,7 +479,8 @@ module GoogleDrive
|
|
424
479
|
upload_from_source(
|
425
480
|
path,
|
426
481
|
title || file_name,
|
427
|
-
{content_type: default_content_type}.merge(params)
|
482
|
+
{ content_type: default_content_type }.merge(params)
|
483
|
+
)
|
428
484
|
end
|
429
485
|
|
430
486
|
# Uploads a file. Reads content from +io+.
|
@@ -437,11 +493,11 @@ module GoogleDrive
|
|
437
493
|
def wrap_api_file(api_file)
|
438
494
|
case api_file.mime_type
|
439
495
|
when 'application/vnd.google-apps.folder'
|
440
|
-
|
496
|
+
Collection.new(self, api_file)
|
441
497
|
when 'application/vnd.google-apps.spreadsheet'
|
442
|
-
|
498
|
+
Spreadsheet.new(self, api_file)
|
443
499
|
else
|
444
|
-
|
500
|
+
File.new(self, api_file)
|
445
501
|
end
|
446
502
|
end
|
447
503
|
|
@@ -450,8 +506,10 @@ module GoogleDrive
|
|
450
506
|
if block
|
451
507
|
page_token = nil
|
452
508
|
loop do
|
453
|
-
parameters
|
454
|
-
|
509
|
+
parameters =
|
510
|
+
(opts[:parameters] || {}).merge(page_token: page_token)
|
511
|
+
(items, page_token) =
|
512
|
+
execute_paged!(opts.merge(parameters: parameters))
|
455
513
|
items.each(&block)
|
456
514
|
break unless page_token
|
457
515
|
end
|
@@ -461,11 +519,11 @@ module GoogleDrive
|
|
461
519
|
items = response.__send__(opts[:items_method_name]).map do |item|
|
462
520
|
opts[:converter] ? opts[:converter].call(item) : item
|
463
521
|
end
|
464
|
-
|
522
|
+
[items, response.next_page_token]
|
465
523
|
|
466
524
|
else
|
467
|
-
parameters = (opts[:parameters] || {}).merge(
|
468
|
-
(items,
|
525
|
+
parameters = (opts[:parameters] || {}).merge(page_token: nil)
|
526
|
+
(items,) = execute_paged!(opts.merge(parameters: parameters))
|
469
527
|
items
|
470
528
|
end
|
471
529
|
end
|
@@ -478,28 +536,32 @@ module GoogleDrive
|
|
478
536
|
auth = params[:auth] || :wise
|
479
537
|
response_type = params[:response_type] || :xml
|
480
538
|
|
481
|
-
if params[:header]
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
539
|
+
extra_header = if params[:header]
|
540
|
+
params[:header]
|
541
|
+
elsif data
|
542
|
+
{
|
543
|
+
'Content-Type' => 'application/atom+xml;charset=utf-8'
|
544
|
+
}
|
545
|
+
else
|
546
|
+
{}
|
547
|
+
end
|
488
548
|
extra_header = { 'GData-Version' => '3.0' }.merge(extra_header)
|
489
549
|
|
490
550
|
loop do
|
491
551
|
response = @fetcher.request_raw(method, url, data, extra_header, auth)
|
492
552
|
next if response.code == '401' && @on_auth_fail && @on_auth_fail.call
|
493
553
|
unless response.code =~ /^2/
|
494
|
-
|
495
|
-
|
554
|
+
raise(
|
555
|
+
(response.code == '401' ? AuthenticationError : ResponseCodeError)
|
556
|
+
.new(response.code, response.body, method, url)
|
557
|
+
)
|
496
558
|
end
|
497
559
|
return convert_response(response, response_type)
|
498
560
|
end
|
499
561
|
end
|
500
562
|
|
501
563
|
def inspect
|
502
|
-
'#<%p:0x%x>'
|
564
|
+
format('#<%p:0x%x>', self.class, object_id)
|
503
565
|
end
|
504
566
|
|
505
567
|
private
|
@@ -512,7 +574,7 @@ module GoogleDrive
|
|
512
574
|
supports_team_drives: true
|
513
575
|
}
|
514
576
|
for k, v in params
|
515
|
-
|
577
|
+
unless %i[convert convert_mime_type parents].include?(k)
|
516
578
|
api_params[k] = v
|
517
579
|
end
|
518
580
|
end
|
@@ -521,34 +583,34 @@ module GoogleDrive
|
|
521
583
|
content_type = api_params[:content_type]
|
522
584
|
if params[:convert_mime_type]
|
523
585
|
file_metadata[:mime_type] = params[:convert_mime_type]
|
524
|
-
elsif params.fetch(:convert, true) &&
|
586
|
+
elsif params.fetch(:convert, true) &&
|
587
|
+
IMPORTABLE_CONTENT_TYPE_MAP.key?(content_type)
|
525
588
|
file_metadata[:mime_type] = IMPORTABLE_CONTENT_TYPE_MAP[content_type]
|
526
589
|
end
|
527
|
-
if params[:parents]
|
528
|
-
file_metadata[:parents] = params[:parents]
|
529
|
-
end
|
590
|
+
file_metadata[:parents] = params[:parents] if params[:parents]
|
530
591
|
|
531
|
-
file =
|
592
|
+
file = drive.create_file(file_metadata, api_params)
|
532
593
|
wrap_api_file(file)
|
533
594
|
end
|
534
595
|
|
535
596
|
def convert_response(response, response_type)
|
536
597
|
case response_type
|
537
598
|
when :xml
|
538
|
-
|
599
|
+
Nokogiri.XML(response.body)
|
539
600
|
when :raw
|
540
|
-
|
601
|
+
response.body
|
541
602
|
when :response
|
542
|
-
|
603
|
+
response
|
543
604
|
else
|
544
|
-
|
545
|
-
|
605
|
+
raise(GoogleDrive::Error,
|
606
|
+
format('Unknown params[:response_type]: %s', response_type))
|
546
607
|
end
|
547
608
|
end
|
548
609
|
|
549
610
|
def url_to_id(url)
|
550
611
|
uri = URI.parse(url)
|
551
|
-
if ['spreadsheets.google.com', 'docs.google.com', 'drive.google.com']
|
612
|
+
if ['spreadsheets.google.com', 'docs.google.com', 'drive.google.com']
|
613
|
+
.include?(uri.host)
|
552
614
|
case uri.path
|
553
615
|
# Document feed.
|
554
616
|
when /^\/feeds\/\w+\/private\/full\/\w+%3A(.*)$/
|
@@ -564,10 +626,14 @@ module GoogleDrive
|
|
564
626
|
return Regexp.last_match(1)
|
565
627
|
# Human-readable old folder view.
|
566
628
|
when /\/folderview$/
|
567
|
-
|
629
|
+
if (uri.query || '').split(/&/).find { |s| s =~ /^id=(.*)$/ }
|
630
|
+
return Regexp.last_match(1)
|
631
|
+
end
|
568
632
|
# Human-readable old spreadsheet.
|
569
633
|
when /\/ccc$/
|
570
|
-
|
634
|
+
if (uri.query || '').split(/&/).find { |s| s =~ /^key=(.*)$/ }
|
635
|
+
return Regexp.last_match(1)
|
636
|
+
end
|
571
637
|
end
|
572
638
|
case uri.fragment
|
573
639
|
# Human-readable old folder page.
|
@@ -575,7 +641,10 @@ module GoogleDrive
|
|
575
641
|
return Regexp.last_match(1)
|
576
642
|
end
|
577
643
|
end
|
578
|
-
|
644
|
+
raise(
|
645
|
+
GoogleDrive::Error,
|
646
|
+
format('The given URL is not a known Google Drive URL: %s', url)
|
647
|
+
)
|
579
648
|
end
|
580
649
|
end
|
581
650
|
end
|