google_drive 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,89 @@
1
+ This is a Ruby 1.8/1.9 library to read/write files/spreadsheets in Google Drive/Docs.
2
+
3
+
4
+ = How to install
5
+
6
+ $ sudo gem install google_drive
7
+
8
+
9
+ = How to use
10
+
11
+ Example to read/write files in Google Drive:
12
+
13
+ require "rubygems"
14
+ require "google_drive"
15
+
16
+ # Logs in.
17
+ # You can also use OAuth. See document of
18
+ # GoogleDrive.login_with_oauth for details.
19
+ session = GoogleDrive.login("username@gmail.com", "mypassword")
20
+
21
+ # Gets list of remote files.
22
+ for file in session.files
23
+ p file.title
24
+ end
25
+
26
+ # Uploads a local file.
27
+ session.upload_from_file("/path/to/hello.txt", "hello.txt", :convert => false)
28
+
29
+ # Downloads to a local file.
30
+ file = session.file_by_title("hello.txt")
31
+ file.download_to_file("/path/to/hello.txt")
32
+
33
+ # Updates content of the remote file.
34
+ file.update_from_file("/path/to/hello.txt")
35
+
36
+ Example to read/write spreadsheets:
37
+
38
+ require "rubygems"
39
+ require "google_drive"
40
+
41
+ # Logs in.
42
+ # You can also use OAuth. See document of
43
+ # GoogleDrive.login_with_oauth for details.
44
+ session = GoogleDrive.login("username@gmail.com", "mypassword")
45
+
46
+ # First worksheet of
47
+ # https://docs.google.com/spreadsheet/ccc?key=pz7XtlQC-PYx-jrVMJErTcg
48
+ ws = session.spreadsheet_by_key("pz7XtlQC-PYx-jrVMJErTcg").worksheets[0]
49
+
50
+ # Gets content of A2 cell.
51
+ p ws[2, 1] #==> "hoge"
52
+
53
+ # Changes content of cells.
54
+ # Changes are not sent to the server until you call ws.save().
55
+ ws[2, 1] = "foo"
56
+ ws[2, 2] = "bar"
57
+ ws.save()
58
+
59
+ # Dumps all cells.
60
+ for row in 1..ws.num_rows
61
+ for col in 1..ws.num_cols
62
+ p ws[row, col]
63
+ end
64
+ end
65
+
66
+ # Yet another way to do so.
67
+ p ws.rows #==> [["fuga", ""], ["foo", "bar]]
68
+
69
+ # Reloads the worksheet to get changes by other clients.
70
+ ws.reload()
71
+
72
+ API document: http://gimite.net/doc/google-drive-ruby/
73
+
74
+
75
+ = Source code
76
+
77
+ http://github.com/gimite/google-drive-ruby
78
+
79
+ The license of this source is "New BSD Licence"
80
+
81
+
82
+ = Supported environments
83
+
84
+ Ruby 1.8.x and Ruby 1.9.x. Checked with Ruby 1.8.7 and Ruby 1.9.3.
85
+
86
+
87
+ = Author
88
+
89
+ Hiroshi Ichikawa - http://gimite.net/en/index.php?Contact
@@ -0,0 +1,20 @@
1
+ module GoogleDrive
2
+
3
+ class Acl
4
+
5
+ # Returns the number of entries.
6
+ def size
7
+ end
8
+
9
+ # Returns GoogleDrive::AclEntry object at +index+.
10
+ def [](index)
11
+ end
12
+
13
+ # Iterates over GoogleDrive::AclEntry objects.
14
+ def each(&block)
15
+ yield(entry)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,33 @@
1
+ module GoogleDrive
2
+
3
+ class AclEntry
4
+
5
+ # Type of the scope. One of:
6
+ #
7
+ # - "user": scope is a user's email address.
8
+ # - "group": scope is a Google Group email address.
9
+ # - "domain": scope is a Google Apps domain.
10
+ # - "default": Publicly shared with all users. scope is +nil+.
11
+ attr_reader(:scope_type)
12
+
13
+ # The scope. See scope_type.
14
+ attr_reader(:scope)
15
+
16
+ # The role given to the scope. One of:
17
+ # - "owner": The owner.
18
+ # - "writer": With read/write access.
19
+ # - "reader": With read-only access.
20
+ attr_reader(:role)
21
+
22
+ # Title of the entry.
23
+ attr_reader(:title)
24
+
25
+ # Edit URL of the entry.
26
+ attr_reader(:edit_url)
27
+
28
+ # E-tag of the entry.
29
+ attr_reader(:etag)
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,120 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+ require "google_drive/session"
5
+
6
+
7
+ module GoogleDrive
8
+
9
+ # Authenticates with given +mail+ and +password+, and returns GoogleDrive::Session
10
+ # if succeeds. Raises GoogleDrive::AuthenticationError if fails.
11
+ # Google Apps account is supported.
12
+ #
13
+ # +proxy+ can be nil or return value of Net::HTTP.Proxy. If +proxy+ is specified, all
14
+ # HTTP access in the session uses the proxy. If +proxy+ is nil, it uses the proxy
15
+ # specified by http_proxy environment variable if available. Otherwise it performs direct
16
+ # access.
17
+ def self.login(mail, password, proxy = nil)
18
+ return Session.login(mail, password, proxy)
19
+ end
20
+
21
+ # Authenticates with given OAuth1 or OAuth2 token.
22
+ #
23
+ # OAuth2 code example:
24
+ #
25
+ # client = OAuth2::Client.new(
26
+ # your_client_id, your_client_secret,
27
+ # :site => "https://accounts.google.com",
28
+ # :token_url => "/o/oauth2/token",
29
+ # :authorize_url => "/o/oauth2/auth")
30
+ # auth_url = client.auth_code.authorize_url(
31
+ # :redirect_uri => "http://example.com/",
32
+ # "scope" => "https://spreadsheets.google.com/feeds https://docs.google.com/feeds/")
33
+ # # Redirect the user to auth_url and get authorization code from redirect URL.
34
+ # auth_token = client.auth_code.get_token(
35
+ # authorization_code, :redirect_uri => "http://example.com/")
36
+ # session = GoogleDrive.login_with_oauth(auth_token)
37
+ #
38
+ # Or, from existing refresh token:
39
+ #
40
+ # access_token = OAuth2::AccessToken.from_hash(client,
41
+ # {:refresh_token => refresh_token, :expires_at => expires_at})
42
+ # access_token = access_token.refresh!
43
+ # session = GoogleDrive.login_with_oauth(access_token)
44
+ #
45
+ # OAuth1 code example:
46
+ #
47
+ # 1) First generate OAuth consumer object with key and secret for your site by registering site
48
+ # with Google.
49
+ # @consumer = OAuth::Consumer.new( "key","secret", {:site=>"https://agree2"})
50
+ # 2) Request token with OAuth.
51
+ # @request_token = @consumer.get_request_token
52
+ # session[:request_token] = @request_token
53
+ # redirect_to @request_token.authorize_url
54
+ # 3) Create an oauth access token.
55
+ # @oauth_access_token = @request_token.get_access_token
56
+ # @access_token = OAuth::AccessToken.new(
57
+ # @consumer, @oauth_access_token.token, @oauth_access_token.secret)
58
+ #
59
+ # See these documents for details:
60
+ #
61
+ # - https://github.com/intridea/oauth2
62
+ # - http://code.google.com/apis/accounts/docs/OAuth2.html
63
+ # - http://oauth.rubyforge.org/
64
+ # - http://code.google.com/apis/accounts/docs/OAuth.html
65
+ def self.login_with_oauth(oauth_token)
66
+ return Session.login_with_oauth(oauth_token)
67
+ end
68
+
69
+ # Restores session using return value of auth_tokens method of previous session.
70
+ #
71
+ # See GoogleDrive.login for description of parameter +proxy+.
72
+ def self.restore_session(auth_tokens, proxy = nil)
73
+ return Session.restore_session(auth_tokens, proxy)
74
+ end
75
+
76
+ # Restores GoogleDrive::Session from +path+ and returns it.
77
+ # If +path+ doesn't exist or authentication has failed, prompts mail and password on console,
78
+ # authenticates with them, stores the session to +path+ and returns it.
79
+ #
80
+ # See login for description of parameter +proxy+.
81
+ #
82
+ # This method requires Highline library: http://rubyforge.org/projects/highline/
83
+ def self.saved_session(path = ENV["HOME"] + "/.ruby_google_drive.token", proxy = nil)
84
+ tokens = {}
85
+ if ::File.exist?(path)
86
+ open(path) do |f|
87
+ for auth in [:wise, :writely]
88
+ line = f.gets()
89
+ tokens[auth] = line && line.chomp()
90
+ end
91
+ end
92
+ end
93
+ session = Session.new(tokens, nil, proxy)
94
+ session.on_auth_fail = proc() do
95
+ begin
96
+ require "highline"
97
+ rescue LoadError
98
+ raise(LoadError,
99
+ "GoogleDrive.saved_session requires Highline library.\n" +
100
+ "Run\n" +
101
+ " \$ sudo gem install highline\n" +
102
+ "to install it.")
103
+ end
104
+ highline = HighLine.new()
105
+ mail = highline.ask("Mail: ")
106
+ password = highline.ask("Password: "){ |q| q.echo = false }
107
+ session.login(mail, password)
108
+ open(path, "w", 0600) do |f|
109
+ f.puts(session.auth_token(:wise))
110
+ f.puts(session.auth_token(:writely))
111
+ end
112
+ true
113
+ end
114
+ if !session.auth_token
115
+ session.on_auth_fail.call()
116
+ end
117
+ return session
118
+ end
119
+
120
+ end
@@ -0,0 +1,124 @@
1
+ # Author: Guy Boertje <https://github.com/guyboertje>
2
+ # Author: David R. Albrecht <https://github.com/eldavido>
3
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
4
+ # The license of this source is "New BSD Licence"
5
+
6
+ require "google_drive/acl_entry"
7
+
8
+
9
+ module GoogleDrive
10
+
11
+ # ACL (access control list) of a spreadsheet.
12
+ #
13
+ # Use GoogleDrive::Spreadsheet#acl to get GoogleDrive::Acl object.
14
+ # See GoogleDrive::Spreadsheet#acl for usage example.
15
+ #
16
+ # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
17
+ class Acl
18
+
19
+ include(Util)
20
+ extend(Forwardable)
21
+
22
+ def initialize(session, acls_feed_url) #:nodoc:
23
+ @session = session
24
+ @acls_feed_url = acls_feed_url
25
+ header = {"GData-Version" => "3.0"}
26
+ doc = @session.request(:get, @acls_feed_url, :header => header, :auth => :writely)
27
+ @acls = doc.css("entry").map(){ |e| AclEntry.new(entry_to_params(e)) }
28
+ end
29
+
30
+ def_delegators(:@acls, :size, :[], :each)
31
+
32
+ # Adds a new entry. +entry+ is either a GoogleDrive::AclEntry or a Hash with keys
33
+ # :scope_type, :scope and :role. See GoogleDrive::AclEntry#scope_type and
34
+ # GoogleDrive::AclEntry#role for the document of the fields.
35
+ #
36
+ # NOTE: This sends email to the new people.
37
+ #
38
+ # e.g.
39
+ # spreadsheet.acl.push(
40
+ # {:scope_type => "user", :scope => "example2@gmail.com", :role => "reader"})
41
+ # spreadsheet.acl.push(
42
+ # {:scope_type => "user", :scope => "example3@gmail.com", :role => "writer"})
43
+ def push(entry)
44
+
45
+ entry = AclEntry.new(entry) if entry.is_a?(Hash)
46
+
47
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
48
+ value_attr = entry.scope ? "value='#{h(entry.scope)}'" : ""
49
+ xml = <<-EOS
50
+ <entry
51
+ xmlns='http://www.w3.org/2005/Atom'
52
+ xmlns:gAcl='http://schemas.google.com/acl/2007'>
53
+ <category scheme='http://schemas.google.com/g/2005#kind'
54
+ term='http://schemas.google.com/acl/2007#accessRule'/>
55
+ <gAcl:role value='#{h(entry.role)}'/>
56
+ <gAcl:scope type='#{h(entry.scope_type)}' #{value_attr}/>
57
+ </entry>
58
+ EOS
59
+ doc = @session.request(
60
+ :post, @acls_feed_url, :data => xml, :header => header, :auth => :writely)
61
+
62
+ entry.params = entry_to_params(doc.root)
63
+ @acls.push(entry)
64
+ return entry
65
+
66
+ end
67
+
68
+ # Deletes an ACL entry.
69
+ #
70
+ # e.g.
71
+ # spreadsheet.acl.delete(spreadsheet.acl[1])
72
+ def delete(entry)
73
+ header = {"GData-Version" => "3.0"}
74
+ @session.request(:delete, entry.edit_url, :header => header, :auth => :writely)
75
+ @acls.delete(entry)
76
+ end
77
+
78
+ def update_role(entry, role) #:nodoc:
79
+
80
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
81
+ value_attr = entry.scope ? "value='#{h(entry.scope)}'" : ""
82
+ xml = <<-EOS
83
+ <entry
84
+ xmlns='http://www.w3.org/2005/Atom'
85
+ xmlns:gAcl='http://schemas.google.com/acl/2007'
86
+ xmlns:gd='http://schemas.google.com/g/2005'
87
+ gd:etag='#{h(entry.etag)}'>
88
+ <category
89
+ scheme='http://schemas.google.com/g/2005#kind'
90
+ term='http://schemas.google.com/acl/2007#accessRule'/>
91
+ <gAcl:role value='#{h(role)}'/>
92
+ <gAcl:scope type='#{h(entry.scope_type)}' #{value_attr}/>
93
+ </entry>
94
+ EOS
95
+ doc = @session.request(
96
+ :put, entry.edit_url, :data => xml, :header => header, :auth => :writely)
97
+
98
+ entry.params = entry_to_params(doc.root)
99
+ return entry
100
+
101
+ end
102
+
103
+ def inspect
104
+ return "\#<%p %p>" % [self.class, @acls]
105
+ end
106
+
107
+ private
108
+
109
+ def entry_to_params(entry)
110
+ # TODO Support with-link roles.
111
+ return {
112
+ :acl => self,
113
+ :scope_type => entry.css("gAcl|scope")[0]["type"],
114
+ :scope => entry.css("gAcl|scope")[0]["value"],
115
+ :role => entry.css("gAcl|role")[0]["value"],
116
+ :title => entry.css("title").text,
117
+ :edit_url => entry.css("link[rel='edit']")[0]["href"],
118
+ :etag => entry["etag"],
119
+ }
120
+ end
121
+
122
+ end
123
+
124
+ end
@@ -0,0 +1,58 @@
1
+ # Author: Guy Boertje <https://github.com/guyboertje>
2
+ # Author: David R. Albrecht <https://github.com/eldavido>
3
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
4
+ # The license of this source is "New BSD Licence"
5
+
6
+ # acl.rb, derived from https://github.com/guyboertje/gdata-spreadsheet-ruby/blob/master/lib/document.rb
7
+ # more frankensteining of the original library
8
+
9
+ module GoogleDrive
10
+
11
+ # An entry of an ACL (access control list) of a spreadsheet.
12
+ #
13
+ # Use GoogleDrive::Acl#[] to get GoogleDrive::AclEntry object.
14
+ #
15
+ # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
16
+ class AclEntry
17
+
18
+ include(Util)
19
+
20
+ PARAM_NAMES = [:acl, :scope_type, :scope, :role, :title, :edit_url, :etag] #:nodoc:
21
+
22
+ # +params+ is a Hash object with keys +:scope_type+, +:scope+ and +:role+.
23
+ # See scope_type and role for the document of the fields.
24
+ def initialize(params)
25
+ @params = {:role => "reader"}
26
+ for name, value in params
27
+ if !PARAM_NAMES.include?(name)
28
+ raise(ArgumentError, "Invalid key: %p" % name)
29
+ end
30
+ @params[name] = value
31
+ end
32
+ end
33
+
34
+ attr_accessor(:params) #:nodoc:
35
+
36
+ PARAM_NAMES.each() do |name|
37
+ define_method(name) do
38
+ return @params[name]
39
+ end
40
+ end
41
+
42
+ # Changes the role of the scope.
43
+ #
44
+ # e.g.
45
+ # spreadsheet.acl[1].role = "writer"
46
+ def role=(role)
47
+ @params[:acl].update_role(self, role)
48
+ end
49
+
50
+ def inspect
51
+ return "\#<%p scope_type=%p, scope=%p, role=%p>" %
52
+ [self.class, @params[:scope_type], @params[:scope], @params[:role]]
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+