slipsquare 0.0.1

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.
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
+