slipsquare 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG.md +21 -0
  5. data/CONTRIBUTING.md +28 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +22 -0
  8. data/README.md +93 -0
  9. data/Rakefile +6 -0
  10. data/bin/slipsquare +7 -0
  11. data/lib/slipsquare.rb +6 -0
  12. data/lib/slipsquare/cli.rb +105 -0
  13. data/lib/slipsquare/config.rb +67 -0
  14. data/lib/slipsquare/middleware.rb +106 -0
  15. data/lib/slipsquare/middleware/account.rb +14 -0
  16. data/lib/slipsquare/middleware/ask_for_credentials.rb +39 -0
  17. data/lib/slipsquare/middleware/base.rb +28 -0
  18. data/lib/slipsquare/middleware/check_configuration.rb +18 -0
  19. data/lib/slipsquare/middleware/check_credentials.rb +27 -0
  20. data/lib/slipsquare/middleware/chunked_upload.rb +29 -0
  21. data/lib/slipsquare/middleware/delete_file.rb +13 -0
  22. data/lib/slipsquare/middleware/download_file.rb +25 -0
  23. data/lib/slipsquare/middleware/inject_client.rb +27 -0
  24. data/lib/slipsquare/middleware/inject_configuration.rb +15 -0
  25. data/lib/slipsquare/middleware/list_files.rb +19 -0
  26. data/lib/slipsquare/middleware/make_directory.rb +25 -0
  27. data/lib/slipsquare/middleware/upload_file.rb +17 -0
  28. data/lib/slipsquare/version.rb +3 -0
  29. data/slipsquare.gemspec +34 -0
  30. data/spec/cli/account.rb +24 -0
  31. data/spec/cli/authorize_spec.rb +46 -0
  32. data/spec/cli/chunked_upload_spec.rb +39 -0
  33. data/spec/cli/delete_file.rb +23 -0
  34. data/spec/cli/download_file.rb +43 -0
  35. data/spec/cli/get_keys_spec.rb +30 -0
  36. data/spec/cli/help_cli_spec.rb +17 -0
  37. data/spec/cli/ls_spec.rb +36 -0
  38. data/spec/cli/mkdir_spec.rb +52 -0
  39. data/spec/cli/upload_file.rb +33 -0
  40. data/spec/cli/verify_spec.rb +33 -0
  41. data/spec/cli/version_cli_spec.rb +16 -0
  42. data/spec/config_spec.rb +70 -0
  43. data/spec/fixtures/account.json +11 -0
  44. data/spec/fixtures/chunked_upload.json +5 -0
  45. data/spec/fixtures/commit_chunked_upload.json +13 -0
  46. data/spec/fixtures/find_foo_directory.json +15 -0
  47. data/spec/fixtures/ls_path_success.json +29 -0
  48. data/spec/fixtures/ls_success.json +14 -0
  49. data/spec/fixtures/mkdir_success.json +12 -0
  50. data/spec/fixtures/mkdir_success_multiple_path.json +12 -0
  51. data/spec/fixtures/upload_success.json +13 -0
  52. data/spec/fixtures/verify_success.json +14 -0
  53. data/spec/middleware/base_spec.rb +15 -0
  54. data/spec/middleware/check_configuration_spec.rb +16 -0
  55. data/spec/middleware/inject_configuration_spec.rb +16 -0
  56. data/spec/shared/environment.rb +49 -0
  57. data/spec/spec_helper.rb +20 -0
  58. data/tmp/.gitkeep +0 -0
  59. metadata +270 -0
@@ -0,0 +1,14 @@
1
+ require 'table_print'
2
+
3
+ module Slipsquare
4
+ module Middleware
5
+ class Account < Base
6
+ def call(env)
7
+
8
+ tp env['dropbox-client'].account
9
+
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ require "dropbox-api"
2
+ require "cgi"
3
+
4
+ module Slipsquare
5
+ module Middleware
6
+ # Ask for user credentials from the command line, then write them out.
7
+ class AskForCredentials < Base
8
+ def call(env)
9
+
10
+ say "If you dont know your app and secret key, try `slipsquare get-keys`"
11
+
12
+ app_key = ask "Enter your App key:"
13
+ secret_key = ask "Enter your Secret key:"
14
+
15
+ Dropbox::API::Config.app_key = app_key
16
+ Dropbox::API::Config.app_secret = secret_key
17
+
18
+ consumer = Dropbox::API::OAuth.consumer(:authorize)
19
+ request_token = consumer.get_request_token
20
+ say "Go to this url and click 'Authorize' to get the token:"
21
+ say request_token.authorize_url, :green
22
+ query = request_token.authorize_url.split('?').last
23
+ params = CGI.parse(query)
24
+ token = params['oauth_token'].first
25
+ yes? "Once you authorize the app on Dropbox, type yes... "
26
+ access_token = request_token.get_access_token(:oauth_verifier => token)
27
+
28
+ # Write the config file.
29
+ env['config'].create_config_file(app_key, secret_key, access_token.token, access_token.secret)
30
+ env['config'].reload!
31
+
32
+ say "Credentials saved to ~/.slipsquare"
33
+
34
+ @app.call(env)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,28 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ # A base middleware class to initalize.
4
+ class Base
5
+ # Some colors for making things pretty.
6
+ CLEAR = "\e[0m"
7
+ RED = "\e[31m"
8
+ GREEN = "\e[32m"
9
+ YELLOW = "\e[33m"
10
+
11
+ # We want access to all of the fun thor cli helper methods,
12
+ # like say, yes?, ask, etc.
13
+ include Thor::Shell
14
+
15
+ def initialize(app)
16
+ @app = app
17
+ # This resets the color to "clear" on the user's terminal.
18
+ say "", :clear, false
19
+ end
20
+
21
+ def call(env)
22
+ @app.call(env)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,18 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ # Check if the client has set-up configuration yet.
4
+ class CheckConfiguration < Base
5
+ def call(env)
6
+ config = env["config"]
7
+
8
+ if !config || !config.data || !config.app_key || !config.secret_key
9
+ say "You must run `slipsquare authorize` in order to connect to Dropbox", :red
10
+ exit 1
11
+ end
12
+
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,27 @@
1
+ require 'thor'
2
+ require 'dropbox-api'
3
+ require 'cgi'
4
+
5
+ module Slipsquare
6
+ module Middleware
7
+ class CheckCredentials < Base
8
+ def call(env)
9
+
10
+ say "Checking credentials with Dropbox..."
11
+
12
+ begin
13
+ env['dropbox-client'].ls
14
+ rescue Dropbox::API::Error => e
15
+ say "Connection to Dropbox failed (#{e})", :red
16
+ say "Check your .slipsquare file, and double check your credentials are correct", :yellow
17
+ exit 1
18
+ end
19
+
20
+ say "Connection to dropbox successful!", :green
21
+
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,29 @@
1
+ require 'ruby-progressbar'
2
+
3
+ module Slipsquare
4
+ module Middleware
5
+ class ChunkedUpload < Base
6
+ def call(env)
7
+ say "Starting chunked upload"
8
+
9
+ file_name = env['chunked_upload_file_name']
10
+ contents = File.open(env['chunked_upload_file_name'])
11
+ total_size = File.size(env['chunked_upload_file_name'])
12
+
13
+ say "Total Size: #{total_size} bytes"
14
+ upload_progress_bar = ProgressBar.create(:title => "Upload progress",
15
+ :format => '%a <%B> %p%% %t',
16
+ :starting_at => 0,
17
+ :total => total_size)
18
+
19
+ response = env['dropbox-client'].chunked_upload file_name, contents do |offset, upload|
20
+ upload_progress_bar.progress += offset
21
+ end
22
+
23
+ say "File uploaded successfully!"
24
+
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ class DeleteFile < Base
4
+ def call(env)
5
+ say "Deleting file on Dropbox..."
6
+
7
+ say "To be implemented...", :yellow
8
+
9
+ @app.call(env)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ class DownloadFile < Base
4
+ def call(env)
5
+ say "Download file..."
6
+
7
+ begin
8
+ contents = env['dropbox-client'].download env['download_file_name']
9
+ rescue Dropbox::API::Error::NotFound => e
10
+ say "File Not Found! Could not download", :red
11
+ exit 1
12
+ rescue Dropbox::API::Error => e
13
+ say "Connection to Dropbox failed (#{e})", :red
14
+ exit 1
15
+ end
16
+
17
+ File.open(env['download_file_name'], 'w') {|f| f.write(contents) }
18
+
19
+ say "File '#{env['download_file_name']}' downloaded successfully!"
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require 'thor'
2
+ require "dropbox-api"
3
+
4
+ module Slipsquare
5
+ module Middleware
6
+ class InjectClient < Base
7
+ def call(env)
8
+
9
+ Dropbox::API::Config.app_key = env['config'].app_key
10
+ Dropbox::API::Config.app_secret = env['config'].secret_key
11
+ Dropbox::API::Config.mode = 'dropbox'
12
+
13
+ begin
14
+ client = Dropbox::API::Client.new(:token => env['config'].app_token, :secret => env['config'].app_secret)
15
+ rescue Dropbox::API::Error => e
16
+ say "Connection to Dropbox failed (#{e})", :red
17
+ exit 1
18
+ end
19
+
20
+ env['dropbox-client'] = client
21
+
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,15 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ # Check if the client has set-up configuration yet.
4
+ class InjectConfiguration < Base
5
+ def call(env)
6
+ config = Slipsquare::Configuration.instance
7
+
8
+ env["config"] = config
9
+
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,19 @@
1
+ require 'table_print'
2
+
3
+ module Slipsquare
4
+ module Middleware
5
+ class ListFiles < Base
6
+ def call(env)
7
+ say "Listing files from Dropbox..."
8
+
9
+ if env["list_files_path"].nil?
10
+ tp env['dropbox-client'].ls, 'path', 'mime_type', 'size'
11
+ else
12
+ tp env['dropbox-client'].ls(env["list_files_path"]), 'path', 'mime_type', 'size'
13
+ end
14
+
15
+ @app.call(env)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ require 'table_print'
2
+
3
+ module Slipsquare
4
+ module Middleware
5
+ class MakeDirectory < Base
6
+ def call(env)
7
+ say "Creating directory on Dropbox..."
8
+
9
+ friendly_path = env["mkdir_path"]
10
+
11
+ if friendly_path =~ (/[\\\:\?\*\<\>\"\|]+/)
12
+ friendly_path = friendly_path.gsub(/[\\\:\?\*\<\>\"\|]+/, '')
13
+ say "Illegal character found! Escaping...", :yellow
14
+ say "Escaped directory path: #{friendly_path}"
15
+ end
16
+
17
+ new_folder_response = env['dropbox-client'].mkdir(env["mkdir_path"])
18
+
19
+ say "Directory `#{friendly_path}` created successfully", :green
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Slipsquare
2
+ module Middleware
3
+ class UploadFile < Base
4
+ def call(env)
5
+ say "Uploading file..."
6
+
7
+ contents = File.read(env['upload_file_name'])
8
+
9
+ env['dropbox-client'].upload env['upload_file_name'], contents
10
+
11
+ say "File '#{env['upload_file_name']}' uploaded successfully"
12
+
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Slipsquare
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'slipsquare/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "slipsquare"
8
+ gem.version = Slipsquare::VERSION
9
+ gem.authors = ["Peter Souter"]
10
+ gem.email = ["p.morsou@gmail.com"]
11
+ gem.description = %q{A command line tool for uploading to dropbox.}
12
+ gem.summary = %q{Slipsquare is a CLI for Dropbox, for downloading and uploading files.}
13
+ gem.homepage = "https://github.com/petems/slipsquare"
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency "thor", "~> 0.18.1"
22
+ gem.add_dependency "middleware" , "~> 0.1.0"
23
+
24
+ gem.add_dependency "dropbox-api-petems", "0.4.2"
25
+ gem.add_dependency "table_print", "~> 1.1.5"
26
+ gem.add_dependency "ruby-progressbar", "~> 1.2.0"
27
+
28
+ gem.add_development_dependency "rake", "~> 10.1.0"
29
+ gem.add_development_dependency "rspec-core", "~> 2.13.0"
30
+ gem.add_development_dependency "rspec-expectations", "~> 2.13.0"
31
+ gem.add_development_dependency "rspec-mocks", "~> 2.13.0"
32
+ gem.add_development_dependency "webmock", "~> 1.11.0"
33
+
34
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slipsquare::CLI do
4
+ include_context "spec"
5
+
6
+ describe "account" do
7
+ it "returns account info" do
8
+
9
+ stub_request(:get, "https://api.dropbox.com/1/account/info?").
10
+ with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'User-Agent'=>'OAuth gem v0.4.7'}).
11
+ to_return(:status => 200, :body => fixture('account'))
12
+
13
+ @cli.account
14
+ expect($stdout.string).to eq <<-eos
15
+ REFERRAL_LINK | DISPLAY_NAME | UID | COUNTRY | QUOTA_INFO
16
+ -------------------------------|--------------|----------|---------|-------------------------------
17
+ https://www.dropbox.com/ref... | John P. User | 12345678 | US | #<Dropbox::API::Object norm...
18
+ eos
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slipsquare::CLI do
4
+ include_context "spec"
5
+
6
+ describe "authorize" do
7
+ before do
8
+ stub_request(:post, "https://www.dropbox.com/1/oauth/request_token").
9
+ with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_callback="oob", oauth_consumer_key="foo", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_version="1.0"/, 'Content-Length'=>'0', 'User-Agent'=>'OAuth gem v0.4.7'}).
10
+ to_return(:status => 200, :body => "oauth_token_secret=b9q1n5il4lcc&oauth_token=mh7an9dkrg59")
11
+
12
+ stub_request(:post, "https://www.dropbox.com/1/oauth/access_token").
13
+ with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="\S+", oauth_verifier="\S+", oauth_version="1.0"/, 'Content-Length'=>'0', 'User-Agent'=>'OAuth gem v0.4.7'}).
14
+ to_return(:status => 200, :body => "oauth_token_secret=95grkd9na7hm&oauth_token=ccl4li5n1q9b&uid=100")
15
+
16
+ stub_request(:get, "https://api.dropbox.com/1/metadata/dropbox/?").
17
+ with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="\S+", oauth_version="1.0"/, 'User-Agent'=>'OAuth gem v0.4.7'}).
18
+ to_return(:status => 200, :body => fixture("verify_success"))
19
+ end
20
+
21
+ it "asks the right questions and saves then checks credentials" do
22
+
23
+ $stdout.should_receive(:print).exactly(6).times
24
+ $stdout.should_receive(:print).with("Enter your App key: ")
25
+ $stdin.should_receive(:gets).and_return(app_key)
26
+ $stdout.should_receive(:print).with("Enter your Secret key: ")
27
+ $stdin.should_receive(:gets).and_return(secret_key)
28
+ $stdout.should_receive(:print).with("Once you authorize the app on Dropbox, type yes... ")
29
+ $stdin.should_receive(:gets).and_return('yes')
30
+
31
+ @cli.authorize
32
+
33
+ expect($stdout.string).to eq <<-eos
34
+ If you dont know your app and secret key, try `slipsquare get-keys`
35
+ Go to this url and click 'Authorize' to get the token:
36
+ https://www.dropbox.com/1/oauth/authorize?oauth_token=mh7an9dkrg59
37
+ Credentials saved to ~/.slipsquare
38
+ Checking credentials with Dropbox...
39
+ Connection to dropbox successful!
40
+ eos
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slipsquare::CLI do
4
+ include_context "spec"
5
+
6
+ before :each do
7
+ File.open("foo.txt", 'w') {|f| f.write("Laugh and grow fat...") }
8
+ end
9
+
10
+ after :each do
11
+ File.delete("foo.txt") if File.exist?("foo.txt")
12
+ end
13
+
14
+ describe "upload-chunked" do
15
+
16
+ it "uploads a larger file and gives progress" do
17
+
18
+ stub_request(:put, "https://api-content.dropbox.com/1/chunked_upload?offset=0").
19
+ with(:body => "Laugh and grow fat...",
20
+ :headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'Content-Length'=>'21', 'Content-Type'=>'application/octet-stream', 'User-Agent'=>'OAuth gem v0.4.7'}).
21
+ to_return(:status => 200, :body => fixture('chunked_upload'))
22
+
23
+ stub_request(:post, "https://api-content.dropbox.com/1/commit_chunked_upload/dropbox/foo.txt?upload_id=v0k84B0AT9fYkfMUp0sBTA").
24
+ with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'Content-Length'=>'0', 'Content-Type'=>'application/octet-stream', 'User-Agent'=>'OAuth gem v0.4.7'}).
25
+ to_return(:status => 200, :body => fixture('commit_chunked_upload'), :headers => {})
26
+
27
+ @cli.chunked_upload('foo.txt')
28
+ expect($stdout.string).to eq <<-eos
29
+ Starting chunked upload
30
+ Total Size: 21 bytes
31
+ Time: 00:00:00 <==========================================> 100% Upload progress
32
+ File uploaded successfully!
33
+ eos
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+