google_drive 2.1.8 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|