google-simple-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in google-simple-client.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Anders Janmyr
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # GoogleSimpleClient
2
+
3
+ Simplifies the usage of google-api-client and provides a command line tool for
4
+ finding and getting documents from Google Drive.
5
+
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'google-simple-client'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install google-simple-client
20
+
21
+ ## Register an App with Google Drive
22
+
23
+ Enable [Google drive](https://developers.google.com/drive/register).
24
+ Make sure that you enable both the `Drive API` and the `Drive SDK`.
25
+
26
+ ## Usage API
27
+
28
+ session = GoogleSimpleClient::Session.new({
29
+ client_id: 'cid',
30
+ client_secret: 'secret',
31
+ email: 'email',
32
+ password: 'password',
33
+ verbose: true
34
+ })
35
+ session.authenticate
36
+ pdf = session.get 'title', 'pdf'
37
+
38
+ ## Usage CLI
39
+
40
+ $ google-simple-client [options] title
41
+
42
+ Options are ...
43
+ -f, --format FORMAT Format of the file to get
44
+ -v, --verbose Log to standard output.
45
+ -V, --version Display the program version.
46
+ -h, --help Display this help message.P
47
+
48
+ ## Configuration
49
+
50
+ It is also possible to set the options to `Session.new` in a configuration
51
+ file called `~/.google-simple-client` or `$HOME/.google-simple-client`. The
52
+ format of the file is YAML. Example:
53
+
54
+ #.google-simple-client
55
+
56
+ client_id: cid
57
+ client_secret: secret
58
+ email: email
59
+ password: password
60
+
61
+ Command line parameters and code parameters override the configuration file
62
+ options as expected.
63
+
64
+
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
4
+ $LOAD_PATH.unshift lib_dir if File.directory?(lib_dir)
5
+
6
+ require 'google-simple-client'
7
+ require 'optparse'
8
+ require 'ostruct'
9
+
10
+ PROGRAM_NAME = $0
11
+
12
+ def main
13
+ begin
14
+ init_option_parser
15
+ @option_parser.parse!
16
+ title = get_title
17
+ get_from_google title, @options
18
+ rescue OptionParser::ParseError => error
19
+ puts error.message
20
+ puts @option_parser
21
+ exit
22
+ end
23
+ end
24
+
25
+
26
+ def init_option_parser
27
+ @option_parser = OptionParser.new do |opts|
28
+ opts.banner = "#{PROGRAM_NAME} [options] title"
29
+ opts.separator ""
30
+ opts.separator "Options are:"
31
+
32
+ # Add the command on_tail, to make it appear as the last option in the list.
33
+ opts.on_tail("-h", "--help", "Display this help message.") do
34
+ puts opts
35
+ exit
36
+ end
37
+
38
+ program_options.each { |args| opts.on(*args) }
39
+ end
40
+ end
41
+
42
+ def program_options
43
+ @options = OpenStruct.new
44
+ [
45
+ # The values of the array are,
46
+ # [long_option, short_option and parameter, description, code to execute]
47
+ ['--format FORMAT', '-f', "Format of the file to get",
48
+ lambda { |value| @options.format = value }
49
+ ],
50
+ ['--verbose', '-v', "Log to standard output.",
51
+ lambda { |value| @options.verbose = true }
52
+ ],
53
+ ['--version', '-V', "Display the program version.",
54
+ lambda { |value|
55
+ puts "#{PROGRAM_NAME}, version #{GoogleSimpleClient::VERSION}"
56
+ exit
57
+ }
58
+ ]
59
+ ]
60
+ end
61
+
62
+ def get_title
63
+ if ARGV.empty?
64
+ puts 'A title to search for is required'
65
+ puts @option_parser
66
+ exit
67
+ end
68
+ ARGV.join
69
+ end
70
+
71
+ def get_from_google title, options
72
+ session = GoogleSimpleClient::Session.new(verbose: @options.verbose)
73
+ session.authenticate
74
+ puts session.get title, options.format
75
+ end
76
+
77
+ main
78
+
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/google-simple-client/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Anders Janmyr']
6
+ gem.email = ['anders@janmyr.com']
7
+ gem.description = %q{Simplifies the usage of google-api-client and
8
+ provides a command line tool for finding and
9
+ getting documents from Google Drive.}
10
+ gem.summary = %q{Simplifies the usage of google-api-client.}
11
+ gem.homepage = "https://github.com/andersjanmyr/google-simple-client"
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = 'google-simple-client'
17
+ gem.require_paths = ['lib']
18
+ gem.version = GoogleSimpleClient::VERSION
19
+ gem.add_dependency 'mechanize'
20
+ gem.add_dependency 'google-api-client'
21
+
22
+ gem.add_development_dependency 'rspec'
23
+ end
@@ -0,0 +1,5 @@
1
+ module GoogleSimpleClient
2
+ class Error < Exception
3
+ end
4
+ end
5
+
@@ -0,0 +1,132 @@
1
+ require 'yaml'
2
+ require 'google/api_client'
3
+ require 'mechanize'
4
+
5
+ require 'google-simple-client/error'
6
+
7
+ module GoogleSimpleClient
8
+ class Session
9
+ OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive.readonly'
10
+ REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
11
+
12
+ def initialize options = {}
13
+ @options = {
14
+ redirect_uri: REDIRECT_URI,
15
+ scope: OAUTH_SCOPE,
16
+ client_id: nil,
17
+ client_secret: nil,
18
+ email: nil,
19
+ password: nil
20
+ }
21
+ init_file_options = read_options_from_init_file
22
+ @options.merge!(init_file_options)
23
+ @options.merge!(options)
24
+ @verbose = options.delete(:verbose)
25
+ raise Error.new("Missing option error #{@options.inspect}") unless @options.values.all?
26
+ end
27
+
28
+ def authenticate
29
+ init_client
30
+ uri = @client.authorization.authorization_uri
31
+ code = scrape_web_and_return_code(uri)
32
+ @client.authorization.code = code
33
+ @client.authorization.fetch_access_token!
34
+ @drive = @client.discovered_api('drive', 'v2')
35
+ end
36
+
37
+ def get(title, format)
38
+ files = find_files(title)
39
+ return "No files found for title #{title}" if files.empty?
40
+ if format
41
+ files.map { |f| download_file(f, format) }
42
+ else
43
+ files.map { |f| f.title }
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def read_options_from_init_file
50
+ file = find_init_file
51
+ if file
52
+ hash = YAML.load_file(file)
53
+ hash.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
54
+ else
55
+ {}
56
+ end
57
+ end
58
+
59
+ def find_init_file
60
+ return '.google-simple-client' if File.exist?('.google-simple-client')
61
+ return "#{ENV['HOME']}/.google-simple-client" if File.exist?("#{ENV['HOME']}/.google-simple-client")
62
+ end
63
+
64
+ def init_client
65
+ @client = Google::APIClient.new
66
+
67
+ @client.authorization.client_id = @options[:client_id]
68
+ @client.authorization.client_secret = @options[:client_secret]
69
+ @client.authorization.scope = @options[:scope]
70
+ @client.authorization.redirect_uri = @options[:redirect_uri]
71
+ end
72
+
73
+ def scrape_web_and_return_code uri
74
+ agent = Mechanize.new
75
+
76
+ # Start loggin in
77
+ log "Logging into #{uri}"
78
+ page = agent.get(uri)
79
+ log page.title
80
+
81
+ # Login
82
+ form = page.form_with(:id => 'gaia_loginform')
83
+ form.Email = @options[:email]
84
+ form.Passwd = @options[:password]
85
+ log "Submitting form"
86
+ page = agent.submit(form)
87
+ log page.title
88
+
89
+ # Accept
90
+ accept_form = page.forms[0]
91
+ raise Error.new("Cannot obtain code from #{page.title}") unless accept_form
92
+ log "Accepting form"
93
+ page = agent.submit(accept_form)
94
+ log page.title
95
+
96
+ # Code is the string after the =
97
+ code = page.title.split('=')[1]
98
+ raise Error.new("Cannot obtain code from #{page.title}") unless code
99
+ log "Retrieved code: #{code}"
100
+ code
101
+ end
102
+
103
+
104
+ def find_files(title)
105
+ log "Searching for '#{title}'"
106
+ result = @client.execute(
107
+ :api_method => @drive.files.list,
108
+ :parameters => { :q => "title contains '#{title}'" }
109
+ )
110
+ raise Error.new(result.data['error']['message']) if result.status != 200
111
+ files = result.data
112
+ log "Found #{files.items.size} files"
113
+ files.items
114
+ end
115
+
116
+ def download_file(file, format)
117
+ url = file.export_links['application/pdf']
118
+ raise Error.new("Cannot download file #{file}") unless url
119
+ fetch_url = url.sub('pdf', format)
120
+ log "Fetching file: #{fetch_url}"
121
+ result = @client.execute(:uri => fetch_url)
122
+ raise Error.new(result.data['error']['message']) unless result.status == 200
123
+
124
+ log result.body
125
+ return result.body
126
+ end
127
+
128
+ def log text
129
+ puts text if @verbose
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,3 @@
1
+ module GoogleSimpleClient
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "google-simple-client/version"
2
+ require "google-simple-client/error"
3
+ require "google-simple-client/session"
4
+
5
+ module GoogleSimpleClient
6
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ require 'google-simple-client/session'
3
+
4
+ module GoogleSimpleClient
5
+ describe Session do
6
+ describe '#initialize' do
7
+ describe 'with all required options' do
8
+ session = Session.new({
9
+ client_id: 'cid',
10
+ client_secret: 'secret',
11
+ email: 'email',
12
+ password: 'password'
13
+ })
14
+
15
+ it 'is properly initialized' do
16
+ session.should be
17
+ end
18
+ end
19
+
20
+ describe 'with missing required options' do
21
+ it 'raises error when a required option is missing' do
22
+ expect {
23
+ Session.new({
24
+ client_id: nil,
25
+ client_secret: 'secret',
26
+ email: 'email',
27
+ password: 'password'
28
+ })
29
+ }.to raise_error Error
30
+ end
31
+ end
32
+
33
+ describe 'with options in init file' do
34
+ before do
35
+ File.open('.google-simple-client', 'w') do |f|
36
+ f.puts('client_id: cid')
37
+ f.puts('client_secret: secret')
38
+ f.puts('email: email')
39
+ f.puts('password: password')
40
+ end
41
+ end
42
+
43
+ it 'uses the options from the local file' do
44
+ Session.new
45
+ end
46
+
47
+ after do
48
+ File.delete('.google-simple-client')
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ require 'google-simple-client'
4
+
5
+ describe 'session integration' do
6
+ before do
7
+ File.exist?("#{ENV['HOME']}/.google-simple-client").should be
8
+ end
9
+
10
+ describe '#authenticate' do
11
+ it 'works with valid credentials' do
12
+ session = GoogleSimpleClient::Session.new
13
+ session.authenticate
14
+ end
15
+
16
+ it 'raises error with invalid credentials' do
17
+ session = GoogleSimpleClient::Session.new({email: 'missing'})
18
+ expect {
19
+ session.authenticate
20
+ }.to raise_error GoogleSimpleClient::Error
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google-simple-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Anders Janmyr
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mechanize
16
+ requirement: &2153159840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2153159840
25
+ - !ruby/object:Gem::Dependency
26
+ name: google-api-client
27
+ requirement: &2153159360 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2153159360
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &2153158920 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2153158920
47
+ description: ! "Simplifies the usage of google-api-client and\n provides
48
+ a command line tool for finding and\n getting documents
49
+ from Google Drive."
50
+ email:
51
+ - anders@janmyr.com
52
+ executables:
53
+ - google-simple-client
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - .gitignore
58
+ - Gemfile
59
+ - LICENSE
60
+ - README.md
61
+ - Rakefile
62
+ - bin/google-simple-client
63
+ - google-simple-client.gemspec
64
+ - lib/google-simple-client.rb
65
+ - lib/google-simple-client/error.rb
66
+ - lib/google-simple-client/session.rb
67
+ - lib/google-simple-client/version.rb
68
+ - spec/google-simple-client/session_spec.rb
69
+ - spec/integration/session_integration_spec.rb
70
+ - spec/spec_helper.rb
71
+ homepage: https://github.com/andersjanmyr/google-simple-client
72
+ licenses: []
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 1.8.17
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Simplifies the usage of google-api-client.
95
+ test_files:
96
+ - spec/google-simple-client/session_spec.rb
97
+ - spec/integration/session_integration_spec.rb
98
+ - spec/spec_helper.rb