google_drive 1.0.4 → 1.0.5
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 +5 -13
- data/README.rdoc +15 -18
- data/lib/google_drive.rb +66 -59
- data/lib/google_drive/config.rb +37 -0
- data/lib/google_drive/error.rb +0 -4
- data/lib/google_drive/session.rb +18 -17
- metadata +28 -47
- data/lib/google_drive_v0.rb +0 -148
- data/lib/google_drive_v0/acl.rb +0 -115
- data/lib/google_drive_v0/acl_entry.rb +0 -100
- data/lib/google_drive_v0/api_client_fetcher.rb +0 -47
- data/lib/google_drive_v0/authentication_error.rb +0 -14
- data/lib/google_drive_v0/basic_fetcher.rb +0 -50
- data/lib/google_drive_v0/client_login_fetcher.rb +0 -31
- data/lib/google_drive_v0/collection.rb +0 -167
- data/lib/google_drive_v0/error.rb +0 -12
- data/lib/google_drive_v0/file.rb +0 -258
- data/lib/google_drive_v0/list.rb +0 -119
- data/lib/google_drive_v0/list_row.rb +0 -88
- data/lib/google_drive_v0/oauth1_fetcher.rb +0 -26
- data/lib/google_drive_v0/oauth2_fetcher.rb +0 -24
- data/lib/google_drive_v0/record.rb +0 -31
- data/lib/google_drive_v0/session.rb +0 -522
- data/lib/google_drive_v0/spreadsheet.rb +0 -248
- data/lib/google_drive_v0/table.rb +0 -60
- data/lib/google_drive_v0/util.rb +0 -73
- data/lib/google_drive_v0/worksheet.rb +0 -498
@@ -1,31 +0,0 @@
|
|
1
|
-
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
|
-
# The license of this source is "New BSD Licence"
|
3
|
-
|
4
|
-
require "google_drive_v0/basic_fetcher"
|
5
|
-
|
6
|
-
|
7
|
-
module GoogleDriveV0
|
8
|
-
|
9
|
-
class ClientLoginFetcher < BasicFetcher #:nodoc:
|
10
|
-
|
11
|
-
def initialize(auth_tokens, proxy)
|
12
|
-
super(proxy)
|
13
|
-
@auth_tokens = auth_tokens
|
14
|
-
end
|
15
|
-
|
16
|
-
attr_accessor(:auth_tokens)
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def auth_header(auth)
|
21
|
-
token = auth == :none ? nil : @auth_tokens[auth]
|
22
|
-
if token
|
23
|
-
return {"Authorization" => "GoogleLogin auth=#{token}"}
|
24
|
-
else
|
25
|
-
return {}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
@@ -1,167 +0,0 @@
|
|
1
|
-
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
|
-
# The license of this source is "New BSD Licence"
|
3
|
-
|
4
|
-
require "google_drive_v0/util"
|
5
|
-
require "google_drive_v0/error"
|
6
|
-
require "google_drive_v0/spreadsheet"
|
7
|
-
|
8
|
-
|
9
|
-
module GoogleDriveV0
|
10
|
-
|
11
|
-
# Use GoogleDriveV0::Session#root_collection, GoogleDriveV0::Collection#subcollections,
|
12
|
-
# or GoogleDriveV0::Session#collection_by_url to get GoogleDriveV0::Collection object.
|
13
|
-
class Collection < GoogleDriveV0::File
|
14
|
-
|
15
|
-
include(Util)
|
16
|
-
|
17
|
-
ROOT_URL = "#{DOCS_BASE_URL}/folder%3Aroot" #:nodoc:
|
18
|
-
|
19
|
-
alias collection_feed_url document_feed_url
|
20
|
-
|
21
|
-
def contents_url
|
22
|
-
if self.root?
|
23
|
-
# The root collection doesn't have document feed.
|
24
|
-
return concat_url(ROOT_URL, "/contents")
|
25
|
-
else
|
26
|
-
return self.document_feed_entry_internal.css(
|
27
|
-
"content[type='application/atom+xml;type=feed']")[0]["src"]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Title of the collection.
|
32
|
-
#
|
33
|
-
# Set <tt>params[:reload]</tt> to true to force reloading the title.
|
34
|
-
def title(params = {})
|
35
|
-
if self.root?
|
36
|
-
# The root collection doesn't have document feed.
|
37
|
-
return nil
|
38
|
-
else
|
39
|
-
return super
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def resource_id
|
44
|
-
return self.root? ? nil : super
|
45
|
-
end
|
46
|
-
|
47
|
-
# Adds the given GoogleDriveV0::File to the collection.
|
48
|
-
def add(file)
|
49
|
-
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
|
50
|
-
xml = <<-"EOS"
|
51
|
-
<entry xmlns="http://www.w3.org/2005/Atom">
|
52
|
-
<id>#{h(file.document_feed_url)}</id>
|
53
|
-
</entry>
|
54
|
-
EOS
|
55
|
-
@session.request(
|
56
|
-
:post, self.contents_url, :data => xml, :header => header, :auth => :writely)
|
57
|
-
return nil
|
58
|
-
end
|
59
|
-
|
60
|
-
# Creates a sub-collection with given title. Returns GoogleDriveV0::Collection object.
|
61
|
-
def create_subcollection(title)
|
62
|
-
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
|
63
|
-
xml = <<-EOS
|
64
|
-
<entry xmlns="http://www.w3.org/2005/Atom">
|
65
|
-
<category scheme="http://schemas.google.com/g/2005#kind"
|
66
|
-
term="http://schemas.google.com/docs/2007#folder"/>
|
67
|
-
<title>#{h(title)}</title>
|
68
|
-
</entry>
|
69
|
-
EOS
|
70
|
-
doc = @session.request(
|
71
|
-
:post, contents_url, :data => xml, :header => header, :auth => :writely)
|
72
|
-
return @session.entry_element_to_file(doc)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Removes the given GoogleDriveV0::File from the collection.
|
76
|
-
def remove(file)
|
77
|
-
url = to_v3_url("#{contents_url}/#{file.resource_id}")
|
78
|
-
@session.request(:delete, url, :auth => :writely, :header => {"If-Match" => "*"})
|
79
|
-
end
|
80
|
-
|
81
|
-
# Returns true if this is a root collection
|
82
|
-
def root?
|
83
|
-
self.document_feed_url == ROOT_URL
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns all the files (including spreadsheets, documents, subcollections) in the collection.
|
87
|
-
#
|
88
|
-
# You can specify query parameters described at
|
89
|
-
# https://developers.google.com/google-apps/documents-list/#getting_a_list_of_documents_and_files
|
90
|
-
#
|
91
|
-
# e.g.
|
92
|
-
#
|
93
|
-
# # Gets all the files in collection, including subcollections.
|
94
|
-
# collection.files
|
95
|
-
#
|
96
|
-
# # Gets only files with title "hoge".
|
97
|
-
# collection.files("title" => "hoge", "title-exact" => "true")
|
98
|
-
def files(params = {})
|
99
|
-
return files_with_type(nil, params)
|
100
|
-
end
|
101
|
-
|
102
|
-
alias contents files
|
103
|
-
|
104
|
-
# Returns all the spreadsheets in the collection.
|
105
|
-
def spreadsheets(params = {})
|
106
|
-
return files_with_type("spreadsheet", params)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Returns all the Google Docs documents in the collection.
|
110
|
-
def documents(params = {})
|
111
|
-
return files_with_type("document", params)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns all its subcollections.
|
115
|
-
def subcollections(params = {})
|
116
|
-
return files_with_type("folder", params)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Returns a file (can be a spreadsheet, document, subcollection or other files) in the
|
120
|
-
# collection which exactly matches +title+ as GoogleDriveV0::File.
|
121
|
-
# Returns nil if not found. If multiple collections with the +title+ are found, returns
|
122
|
-
# one of them.
|
123
|
-
#
|
124
|
-
# If given an Array, does a recursive subcollection traversal.
|
125
|
-
def file_by_title(title)
|
126
|
-
return file_by_title_with_type(title, nil)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns its subcollection whose title exactly matches +title+ as GoogleDriveV0::Collection.
|
130
|
-
# Returns nil if not found. If multiple collections with the +title+ are found, returns
|
131
|
-
# one of them.
|
132
|
-
#
|
133
|
-
# If given an Array, does a recursive subcollection traversal.
|
134
|
-
def subcollection_by_title(title)
|
135
|
-
return file_by_title_with_type(title, "folder")
|
136
|
-
end
|
137
|
-
|
138
|
-
protected
|
139
|
-
|
140
|
-
def file_by_title_with_type(title, type)
|
141
|
-
if title.is_a?(Array)
|
142
|
-
rel_path = title
|
143
|
-
if rel_path.empty?
|
144
|
-
return self
|
145
|
-
else
|
146
|
-
parent = subcollection_by_title(rel_path[0...-1])
|
147
|
-
return parent && parent.file_by_title_with_type(rel_path[-1], type)
|
148
|
-
end
|
149
|
-
else
|
150
|
-
return files_with_type(type, "title" => title, "title-exact" => "true")[0]
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
private
|
155
|
-
|
156
|
-
def files_with_type(type, params = {})
|
157
|
-
contents_url = self.contents_url
|
158
|
-
contents_url = concat_url(contents_url, "/-/#{type}") if type
|
159
|
-
contents_url = concat_url(contents_url, "?" + encode_query(params))
|
160
|
-
header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml;charset=utf-8"}
|
161
|
-
doc = @session.request(:get, contents_url, :header => header, :auth => :writely)
|
162
|
-
return doc.css("feed > entry").map(){ |e| @session.entry_element_to_file(e) }
|
163
|
-
end
|
164
|
-
|
165
|
-
end
|
166
|
-
|
167
|
-
end
|
data/lib/google_drive_v0/file.rb
DELETED
@@ -1,258 +0,0 @@
|
|
1
|
-
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
|
-
# The license of this source is "New BSD Licence"
|
3
|
-
|
4
|
-
require "cgi"
|
5
|
-
require "stringio"
|
6
|
-
|
7
|
-
require "google_drive_v0/util"
|
8
|
-
require "google_drive_v0/acl"
|
9
|
-
|
10
|
-
|
11
|
-
module GoogleDriveV0
|
12
|
-
|
13
|
-
# A file in Google Drive, including Google Docs document/spreadsheet/presentation.
|
14
|
-
#
|
15
|
-
# Use GoogleDriveV0::Session#files or GoogleDriveV0::Session#file_by_title to
|
16
|
-
# get this object.
|
17
|
-
class File
|
18
|
-
|
19
|
-
include(Util)
|
20
|
-
|
21
|
-
def initialize(session, entry_or_url) #:nodoc:
|
22
|
-
@session = session
|
23
|
-
if !entry_or_url
|
24
|
-
# TODO Delete this after editing spreadsheet.rb.
|
25
|
-
@document_feed_entry = nil
|
26
|
-
@document_feed_url = entry_or_url
|
27
|
-
elsif entry_or_url.is_a?(String)
|
28
|
-
@document_feed_entry = nil
|
29
|
-
@document_feed_url = entry_or_url
|
30
|
-
else
|
31
|
-
@document_feed_entry = entry_or_url
|
32
|
-
# This is usually equal to the URL in <link rel="self">. But the URL in
|
33
|
-
# <link rel="self"> in collection feed is e.g.
|
34
|
-
# https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents/folder%3Axxx
|
35
|
-
# and deletion of the URL doesn't delete the file itself.
|
36
|
-
# So we construct the URL here using resource ID instead.
|
37
|
-
@document_feed_url = "%s/%s?v=3" % [DOCS_BASE_URL, CGI.escape(self.resource_id)]
|
38
|
-
end
|
39
|
-
@acl = nil
|
40
|
-
end
|
41
|
-
|
42
|
-
# URL of feed used in document list feed API.
|
43
|
-
attr_reader(:document_feed_url)
|
44
|
-
|
45
|
-
# <entry> element of document list feed as Nokogiri::XML::Element.
|
46
|
-
#
|
47
|
-
# Set <tt>params[:reload]</tt> to true to force reloading the feed.
|
48
|
-
def document_feed_entry(params = {})
|
49
|
-
warn(
|
50
|
-
"WARNING: GoogleDriveV0::file\#document_feed_entry is deprecated and will be removed " +
|
51
|
-
"in the next version.")
|
52
|
-
return self.document_feed_entry_internal(params)
|
53
|
-
end
|
54
|
-
|
55
|
-
def document_feed_entry_internal(params = {}) #:nodoc:
|
56
|
-
if !@document_feed_entry || params[:reload]
|
57
|
-
@document_feed_entry =
|
58
|
-
@session.request(:get, self.document_feed_url, :auth => :writely).css("entry")[0]
|
59
|
-
end
|
60
|
-
return @document_feed_entry
|
61
|
-
end
|
62
|
-
|
63
|
-
# Resource ID.
|
64
|
-
def resource_id
|
65
|
-
return self.document_feed_entry_internal.css("gd|resourceId").text
|
66
|
-
end
|
67
|
-
|
68
|
-
# The type of resourse. e.g. "document", "spreadsheet", "folder"
|
69
|
-
def resource_type
|
70
|
-
return self.resource_id.split(/:/)[0]
|
71
|
-
end
|
72
|
-
|
73
|
-
# Title of the file.
|
74
|
-
#
|
75
|
-
# Set <tt>params[:reload]</tt> to true to force reloading the title.
|
76
|
-
def title(params = {})
|
77
|
-
return document_feed_entry_internal(params).css("title").text
|
78
|
-
end
|
79
|
-
|
80
|
-
# URL to view/edit the file in a Web browser.
|
81
|
-
#
|
82
|
-
# e.g. "https://docs.google.com/file/d/xxxx/edit"
|
83
|
-
def human_url
|
84
|
-
return self.document_feed_entry_internal.css("link[rel='alternate']")[0]["href"]
|
85
|
-
end
|
86
|
-
|
87
|
-
# ACL feed URL of the file.
|
88
|
-
def acl_feed_url
|
89
|
-
orig_acl_feed_url = self.document_feed_entry_internal.css(
|
90
|
-
"gd|feedLink[rel='http://schemas.google.com/acl/2007#accessControlList']")[0]["href"]
|
91
|
-
case orig_acl_feed_url
|
92
|
-
when %r{^https?://docs.google.com/feeds/default/private/full/.*/acl(\?.*)?$}
|
93
|
-
return orig_acl_feed_url
|
94
|
-
when %r{^https?://docs.google.com/feeds/acl/private/full/([^\?]*)(\?.*)?$}
|
95
|
-
# URL of old API version. Converts to v3 URL.
|
96
|
-
return "#{DOCS_BASE_URL}/#{$1}/acl"
|
97
|
-
else
|
98
|
-
raise(GoogleDriveV0::Error,
|
99
|
-
"ACL feed URL is in unknown format: #{orig_acl_feed_url}")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Content types you can specify in methods download_to_file, download_to_string,
|
104
|
-
# download_to_io .
|
105
|
-
def available_content_types
|
106
|
-
return self.document_feed_entry_internal.css("content").map(){ |c| c["type"] }
|
107
|
-
end
|
108
|
-
|
109
|
-
# Downloads the file to a local file.
|
110
|
-
#
|
111
|
-
# e.g.
|
112
|
-
# file.download_to_file("/path/to/hoge.txt")
|
113
|
-
# file.download_to_file("/path/to/hoge", :content_type => "text/plain")
|
114
|
-
def download_to_file(path, params = {})
|
115
|
-
params = params.dup()
|
116
|
-
if !params[:content_type]
|
117
|
-
params[:content_type] = EXT_TO_CONTENT_TYPE[::File.extname(path).downcase]
|
118
|
-
params[:content_type_is_hint] = true
|
119
|
-
end
|
120
|
-
open(path, "wb") do |f|
|
121
|
-
download_to_io(f, params)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Downloads the file and returns as a String.
|
126
|
-
#
|
127
|
-
# e.g.
|
128
|
-
# file.download_to_string() #=> "Hello world."
|
129
|
-
# file.download_to_string(:content_type => "text/plain") #=> "Hello world."
|
130
|
-
def download_to_string(params = {})
|
131
|
-
sio = StringIO.new()
|
132
|
-
download_to_io(sio, params)
|
133
|
-
return sio.string
|
134
|
-
end
|
135
|
-
|
136
|
-
# Downloads the file and writes it to +io+.
|
137
|
-
def download_to_io(io, params = {})
|
138
|
-
all_contents = self.document_feed_entry_internal.css("content")
|
139
|
-
if params[:content_type] && (!params[:content_type_is_hint] || all_contents.size > 1)
|
140
|
-
contents = all_contents.select(){ |c| c["type"] == params[:content_type] }
|
141
|
-
else
|
142
|
-
contents = all_contents
|
143
|
-
end
|
144
|
-
if contents.size == 1
|
145
|
-
url = contents[0]["src"]
|
146
|
-
else
|
147
|
-
if contents.empty?
|
148
|
-
raise(GoogleDriveV0::Error,
|
149
|
-
("Downloading with content type %p not supported for this file. " +
|
150
|
-
"Specify one of these to content_type: %p") %
|
151
|
-
[params[:content_type], self.available_content_types])
|
152
|
-
else
|
153
|
-
raise(GoogleDriveV0::Error,
|
154
|
-
("Multiple content types are available for this file. " +
|
155
|
-
"Specify one of these to content_type: %p") %
|
156
|
-
[self.available_content_types])
|
157
|
-
end
|
158
|
-
end
|
159
|
-
# TODO Use streaming if possible.
|
160
|
-
body = @session.request(:get, url, :response_type => :raw, :auth => :writely)
|
161
|
-
io.write(body)
|
162
|
-
end
|
163
|
-
|
164
|
-
# Updates the file with the content of the local file.
|
165
|
-
#
|
166
|
-
# e.g.
|
167
|
-
# file.update_from_file("/path/to/hoge.txt")
|
168
|
-
def update_from_file(path, params = {})
|
169
|
-
params = {:file_name => ::File.basename(path)}.merge(params)
|
170
|
-
open(path, "rb") do |f|
|
171
|
-
update_from_io(f, params)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
# Updates the file with +content+.
|
176
|
-
#
|
177
|
-
# e.g.
|
178
|
-
# file.update_from_string("Good bye, world.")
|
179
|
-
def update_from_string(content, params = {})
|
180
|
-
update_from_io(StringIO.new(content), params)
|
181
|
-
end
|
182
|
-
|
183
|
-
# Reads content from +io+ and updates the file with the content.
|
184
|
-
def update_from_io(io, params = {})
|
185
|
-
params = {:header => {"If-Match" => "*"}}.merge(params)
|
186
|
-
initial_url = self.document_feed_entry_internal.css(
|
187
|
-
"link[rel='http://schemas.google.com/g/2005#resumable-edit-media']")[0]["href"]
|
188
|
-
@document_feed_entry = @session.upload_raw(
|
189
|
-
:put, initial_url, io, self.title, params)
|
190
|
-
end
|
191
|
-
|
192
|
-
# If +permanent+ is +false+, moves the file to the trash.
|
193
|
-
# If +permanent+ is +true+, deletes the file permanently.
|
194
|
-
def delete(permanent = false)
|
195
|
-
url = to_v3_url(self.document_feed_url)
|
196
|
-
url = concat_url(url, "?delete=true") if permanent
|
197
|
-
@session.request(:delete, url,
|
198
|
-
:auth => :writely, :header => {"If-Match" => "*"})
|
199
|
-
end
|
200
|
-
|
201
|
-
# Renames title of the file.
|
202
|
-
def rename(title)
|
203
|
-
edit_url = self.document_feed_entry_internal.css("link[rel='edit']").first["href"]
|
204
|
-
xml = <<-"EOS"
|
205
|
-
<atom:entry
|
206
|
-
xmlns:atom="http://www.w3.org/2005/Atom"
|
207
|
-
xmlns:docs="http://schemas.google.com/docs/2007">
|
208
|
-
<atom:title>#{h(title)}</atom:title>
|
209
|
-
</atom:entry>
|
210
|
-
EOS
|
211
|
-
header = {"Content-Type" => "application/atom+xml;charset=utf-8", "If-Match" => "*"}
|
212
|
-
@session.request(:put, edit_url, :data => xml, :auth => :writely, :header => header)
|
213
|
-
end
|
214
|
-
|
215
|
-
alias title= rename
|
216
|
-
|
217
|
-
# Returns GoogleDriveV0::Acl object for the file.
|
218
|
-
#
|
219
|
-
# With the object, you can see and modify people who can access the file.
|
220
|
-
# Modifications take effect immediately.
|
221
|
-
#
|
222
|
-
# Set <tt>params[:reload]</tt> to true to force reloading the data.
|
223
|
-
#
|
224
|
-
# e.g.
|
225
|
-
# # Dumps people who have access:
|
226
|
-
# for entry in file.acl
|
227
|
-
# p [entry.scope_type, entry.scope, entry.role]
|
228
|
-
# # => e.g. ["user", "example1@gmail.com", "owner"]
|
229
|
-
# end
|
230
|
-
#
|
231
|
-
# # Shares the file with new people:
|
232
|
-
# # NOTE: This sends email to the new people.
|
233
|
-
# file.acl.push(
|
234
|
-
# {:scope_type => "user", :scope => "example2@gmail.com", :role => "reader"})
|
235
|
-
# file.acl.push(
|
236
|
-
# {:scope_type => "user", :scope => "example3@gmail.com", :role => "writer"})
|
237
|
-
#
|
238
|
-
# # Changes the role of a person:
|
239
|
-
# file.acl[1].role = "writer"
|
240
|
-
#
|
241
|
-
# # Deletes an ACL entry:
|
242
|
-
# file.acl.delete(file.acl[1])
|
243
|
-
def acl(params = {})
|
244
|
-
if !@acl || params[:reload]
|
245
|
-
@acl = Acl.new(@session, self.acl_feed_url)
|
246
|
-
end
|
247
|
-
return @acl
|
248
|
-
end
|
249
|
-
|
250
|
-
def inspect
|
251
|
-
fields = {:document_feed_url => self.document_feed_url}
|
252
|
-
fields[:title] = self.title if @document_feed_entry
|
253
|
-
return "\#<%p %s>" % [self.class, fields.map(){ |k, v| "%s=%p" % [k, v] }.join(", ")]
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
|
-
end
|