gdsh 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ea4c9787d401d716741f4db5606ddc739b16a8f9
4
+ data.tar.gz: 3f7a0aada9445817f3c3efdaaba3e3ddc6425ed8
5
+ SHA512:
6
+ metadata.gz: 482ad86b93d60e9a832485aad59ccfd86043e60e366e594a086cab8350bcdfcbfe96b8ca714995ee570441a37753771890ef4c8b5e2650db9bfea90692cb325d
7
+ data.tar.gz: e0acf4d5cc78838575181a6b38164db73c165f150748f41fb30eb8b632dbeec54f1b2aa05dc430ebd1c54bce1f59f1c81d48ae3b93a129e2db1822e28d824239
@@ -0,0 +1,21 @@
1
+ auth.json
2
+ .session.yaml
3
+
4
+ # Bundle generated
5
+ *.gem
6
+ *.rbc
7
+ .bundle
8
+ .config
9
+ .yardoc
10
+ Gemfile.lock
11
+ installedfiles
12
+ _yardoc
13
+ coverage
14
+ doc/
15
+ lib/bundler/man
16
+ pkg
17
+ rdoc
18
+ spec/reports
19
+ test/tmp
20
+ test/version_tmp
21
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gdsh.gemspec
4
+ gemspec
5
+
6
+ # forked from JakobR's branch + patch
7
+ gem 'differ', git: 'git://github.com/emintham/differ'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Emin Tham
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.
@@ -0,0 +1,31 @@
1
+ # gdsh [![Code Climate](https://codeclimate.com/github/emintham/gdsh.png)](https://codeclimate.com/github/emintham/gdsh)
2
+
3
+ A Google Drive shell in Ruby.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'gdsh'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install gdsh
18
+
19
+ ## Usage
20
+
21
+ (adapted from https://developers.google.com/drive/web/quickstart/quickstart-ruby)
22
+
23
+ 1. Set up a project in [Google](https://console.developers.google.com//start/api?id=drive&credential=client_key).
24
+ 2. Select the created project and select APIs & auth and make sure the status
25
+ is **ON** for the Drive API.
26
+ 3. In the sidebar on the left, select Credentials and set up new credentials
27
+ for this project.
28
+ 4. Download (as JSON) or save the client id and client secret.
29
+ 5. `bundle exec ruby gdsh.rb <credentials_json>` or `bundle exec ruby gdsh.rb`. In the former, credentials
30
+ will be automatically retrieved from JSON; in the latter, you will need to
31
+ copy and paste the `client_id` and `client_secret` from the credentials above.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,10 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative '../lib/gdsh'
4
+
5
+ # if run as standalone script, launch shell
6
+ if __FILE__ == $PROGRAM_NAME
7
+ filename = ARGV.first if ARGV.length > 0
8
+ s = Gdsh::Gdsh.new(filename)
9
+ s.shell
10
+ end
@@ -0,0 +1,2 @@
1
+ hello
2
+ world
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gdsh/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'gdsh'
8
+ spec.version = Gdsh::VERSION
9
+ spec.authors = ['Emin Tham']
10
+ spec.email = ['emintham@gmail.com']
11
+ spec.summary = 'A Google Drive shell in Ruby.'
12
+ spec.description = ''
13
+ spec.homepage = 'https://github.com/emintham/gdsh'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.5'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_runtime_dependency 'google-api-client'
25
+ spec.add_runtime_dependency 'launchy'
26
+ spec.add_runtime_dependency 'differ'
27
+ spec.add_runtime_dependency 'colorize'
28
+ end
@@ -0,0 +1,61 @@
1
+ require 'google/api_client'
2
+ require 'launchy'
3
+ require 'json'
4
+
5
+ require_relative 'gdsh/version'
6
+ require_relative 'gdsh/drive'
7
+ require_relative 'gdsh/command_factory'
8
+
9
+ ##
10
+ # Implements a command interpreter to wrap Google Drive API.
11
+ #
12
+ module Gdsh
13
+ ##
14
+ # Gdsh Class
15
+ #
16
+ class Gdsh < DriveService
17
+ include CommandFactory
18
+
19
+ def puts_banner
20
+ puts ''
21
+ puts 'CLI tool to interface with Google Drive'.colorize(:green)
22
+ puts '======================================='.colorize(:green)
23
+ end
24
+
25
+ def puts_hint
26
+ puts 'Hint: type \'help\'.'.colorize(:green)
27
+ end
28
+
29
+ def clear_screen
30
+ system('clear') || system('cls')
31
+ end
32
+
33
+ def init_shell
34
+ puts_banner
35
+ authorize
36
+ clear_screen
37
+ puts_hint
38
+ end
39
+
40
+ def prints_prompt
41
+ print 'gdsh> '.colorize(:light_blue)
42
+ end
43
+
44
+ ##
45
+ # Command interpreter
46
+ #
47
+ def shell
48
+ init_shell
49
+
50
+ loop do
51
+ prints_prompt
52
+ params = parsed_inputs
53
+ command = next_command(params)
54
+ command.new(@client, params).execute
55
+ break if command.terminal?
56
+ end
57
+
58
+ write_session_info_to_file
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'commands'
2
+
3
+ module Commands
4
+ ##
5
+ # Clear screen.
6
+ #
7
+ class Clear < Command
8
+ def self.command_name
9
+ 'clear'
10
+ end
11
+
12
+ def self.function
13
+ 'Clears the screen.'
14
+ end
15
+
16
+ def execute
17
+ system('clear') || system('cls')
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'commands'
2
+ require_relative 'clear'
3
+ require_relative 'help'
4
+ require_relative 'list_files'
5
+ require_relative 'query_revision'
6
+ require_relative 'quit'
7
+ require_relative 'unrecognized'
8
+ require_relative 'upload_template'
9
+ require_relative 'get_file'
10
+ require_relative 'revision_diff'
11
+ require_relative 'remove'
12
+ require_relative 'share_read_only'
13
+ require_relative 'share_read_write'
14
+
15
+ ##
16
+ # Factory pattern to create the appropriate command.
17
+ #
18
+ module CommandFactory
19
+ include Commands
20
+
21
+ def parsed_inputs
22
+ # gets user input, defaulting to empty and removing newline
23
+ user_input = $stdin.gets || ''
24
+
25
+ # if command has parameters, split it up
26
+ user_input.chomp.split(/[\(,\),\,,\ ]/)
27
+ end
28
+
29
+ def next_command(params)
30
+ Commands.interpret(params[0])
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ require 'colorize'
2
+
3
+ ##
4
+ # Commands
5
+ #
6
+ module Commands
7
+ ##
8
+ # Command mixin
9
+ #
10
+ module CommandMixin
11
+ def execute
12
+ fail 'Method not implemented.'
13
+ end
14
+
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+
19
+ ##
20
+ # Every 'useful' Command class should override the following
21
+ # (except terminal?)
22
+ #
23
+ module ClassMethods
24
+ def command_name
25
+ ''
26
+ end
27
+
28
+ def function
29
+ ''
30
+ end
31
+
32
+ def parameters
33
+ ''
34
+ end
35
+
36
+ def description
37
+ (command_name + parameters + ":\n ").colorize(:green) +
38
+ function.colorize(:yellow)
39
+ end
40
+
41
+ def terminal?
42
+ false
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ require 'google/api_client'
2
+ require 'json'
3
+ require 'colorize'
4
+
5
+ require_relative 'command_mixin'
6
+ require_relative 'error'
7
+
8
+ ##
9
+ # Commands
10
+ #
11
+ module Commands
12
+ ##
13
+ # Command with an initialized client object.
14
+ #
15
+ class Command
16
+ include CommandMixin
17
+ include DriveError
18
+
19
+ def initialize(client, params)
20
+ @client, @params = client, params
21
+ end
22
+ end
23
+
24
+ module_function
25
+
26
+ def commands
27
+ constants.select { |c| const_get(c).is_a? Class }
28
+ end
29
+
30
+ def puts_usage_header
31
+ puts 'Commands'.colorize(:green)
32
+ puts '--------'.colorize(:green)
33
+ end
34
+
35
+ def usage
36
+ puts_usage_header
37
+ commands.each do |c|
38
+ klass = const_get(c)
39
+ puts klass.description unless klass.command_name.empty?
40
+ end
41
+ end
42
+
43
+ def interpret(input)
44
+ return Quit if input.nil?
45
+
46
+ commands.each do |c|
47
+ klass = const_get(c)
48
+ return klass if input == klass.command_name
49
+ end
50
+
51
+ Unrecognized
52
+ end
53
+ end
@@ -0,0 +1,113 @@
1
+ require 'google/api_client'
2
+ require 'launchy'
3
+ require 'json'
4
+ require 'colorize'
5
+ require 'yaml'
6
+
7
+ ##
8
+ # DriveService module implements a service that interfaces with
9
+ # Google Drive using Google Drive API.
10
+ #
11
+ class DriveService
12
+ ##
13
+ # Creates a new Google Drive Shell object.
14
+ #
15
+ # @param [String] filename
16
+ # filename of json containing credentials downloaded from Google.
17
+ #
18
+ def initialize(filename = nil)
19
+ # default to per-file permissions
20
+ @oauth_scope = 'https://www.googleapis.com/auth/drive.file'
21
+ @redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
22
+ @filename = filename
23
+
24
+ if filename && File.exist?(filename)
25
+ credentials_from_file
26
+ else
27
+ credentials_from_stdin
28
+ end
29
+ end
30
+
31
+ def credentials_from_file
32
+ File.open(@filename, 'r') do |f|
33
+ buffer = f.read
34
+ credentials = JSON.parse(buffer)
35
+ @client_id = credentials['installed']['client_id']
36
+ @client_secret = credentials['installed']['client_secret']
37
+ end
38
+ end
39
+
40
+ def init_client
41
+ # Create a new API client & load the Google Drive API
42
+ @client = Google::APIClient.new
43
+
44
+ # Request authorization
45
+ @client.authorization.client_id = @client_id
46
+ @client.authorization.client_secret = @client_secret
47
+ @client.authorization.scope = @oauth_scope
48
+ @client.authorization.redirect_uri = @redirect_uri
49
+ end
50
+
51
+ def puts_refresh_error
52
+ puts 'Could not refresh token from saved session.'.colorize(:red)
53
+ end
54
+
55
+ def authorize
56
+ init_client
57
+
58
+ begin
59
+ authorize_from_refresh_token
60
+ rescue
61
+ puts_refresh_error
62
+ authorize_from_authorization_code
63
+ ensure
64
+ @client.authorization.fetch_access_token!
65
+ end
66
+ end
67
+
68
+ def authorize_from_refresh_token
69
+ fail StandardError unless File.exist?('.session.yaml')
70
+
71
+ f = File.open('.session.yaml', 'r')
72
+ session = YAML.load(f.read)
73
+ @client.authorization.grant_type = 'refresh_token'
74
+ @client.authorization.refresh_token = session.authorization.refresh_token
75
+ f.close
76
+ end
77
+
78
+ def authorize_from_authorization_code
79
+ uri = @client.authorization.authorization_uri
80
+ Launchy.open(uri)
81
+
82
+ # Exchange authorization code for access token
83
+ print 'Enter authorization code: '.colorize(:light_blue)
84
+ @client.authorization.code = $stdin.gets.chomp
85
+ end
86
+
87
+ ##
88
+ # Get credentials from shell if no credentials file was specified.
89
+ #
90
+ def credentials_from_stdin
91
+ # get preset if exists
92
+ @client_id ||= ''
93
+ @client_secret ||= ''
94
+
95
+ # Ask from user otherwise
96
+ if @client_id == ''
97
+ print 'Please enter your client id: '
98
+ @client_id = $stdin.gets.chomp
99
+ end
100
+
101
+ if @client_secret == ''
102
+ print 'Please enter your client secret: '
103
+ @client_secret = $stdin.gets.chomp
104
+ end
105
+ end
106
+
107
+ def write_session_info_to_file
108
+ return if @client.nil?
109
+ f = File.new('.session.yaml', 'w')
110
+ f.write(@client.to_yaml)
111
+ f.close
112
+ end
113
+ end