dropbox-api-alt 0.4.7

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,39 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ class Object < Hashie::Mash
5
+ attr_accessor :client
6
+
7
+ def self.init(response, client)
8
+ instance = self.new(response)
9
+ instance.client = client
10
+ instance
11
+ end
12
+
13
+ def self.resolve_class(hash)
14
+ hash['is_dir'] == true ? Dropbox::API::Dir : Dropbox::API::File
15
+ end
16
+
17
+ def self.convert(array_or_object, client)
18
+ if array_or_object.is_a?(Array)
19
+ array_or_object.collect do |item|
20
+ resolve_class(item).init(item, client)
21
+ end
22
+ else
23
+ resolve_class(array_or_object).init(array_or_object, client)
24
+ end
25
+ end
26
+
27
+ # Kill off the ability for recursive conversion
28
+ def deep_update(other_hash)
29
+ other_hash.each_pair do |k,v|
30
+ key = convert_key(k)
31
+ regular_writer(key, convert_value(v, true))
32
+ end
33
+ self
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ class Tasks
5
+
6
+ extend Rake::DSL if defined? Rake::DSL
7
+
8
+ def self.install
9
+
10
+ namespace :dropbox do
11
+ desc "Authorize wizard for Dropbox API"
12
+ task :authorize do
13
+ require "dropbox-api"
14
+ require "cgi"
15
+ print "Enter dropbox app key: "
16
+ consumer_key = $stdin.gets.chomp
17
+ print "Enter dropbox app secret: "
18
+ consumer_secret = $stdin.gets.chomp
19
+
20
+ Dropbox::API::Config.app_key = consumer_key
21
+ Dropbox::API::Config.app_secret = consumer_secret
22
+
23
+ consumer = Dropbox::API::OAuth.consumer(:authorize)
24
+ request_token = consumer.get_request_token
25
+ puts "\nGo to this url and click 'Authorize' to get the token:"
26
+ puts request_token.authorize_url
27
+ query = request_token.authorize_url.split('?').last
28
+ params = CGI.parse(query)
29
+ token = params['oauth_token'].first
30
+ print "\nOnce you authorize the app on Dropbox, press enter... "
31
+ $stdin.gets.chomp
32
+
33
+ access_token = request_token.get_access_token(:oauth_verifier => token)
34
+
35
+ puts "\nAuthorization complete!:\n\n"
36
+ puts " Dropbox::API::Config.app_key = '#{consumer.key}'"
37
+ puts " Dropbox::API::Config.app_secret = '#{consumer.secret}'"
38
+ puts " client = Dropbox::API::Client.new(:token => '#{access_token.token}', :secret => '#{access_token.secret}')"
39
+ puts "\n"
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ module Config
5
+
6
+ class << self
7
+ attr_accessor :endpoints
8
+ attr_accessor :prefix
9
+ attr_accessor :app_key
10
+ attr_accessor :app_secret
11
+ attr_accessor :mode
12
+ end
13
+
14
+ self.endpoints = {
15
+ :main => "https://api.dropbox.com",
16
+ :content => "https://api-content.dropbox.com",
17
+ :authorize => "https://www.dropbox.com"
18
+ }
19
+ self.prefix = "/1"
20
+ self.app_key = nil
21
+ self.app_secret = nil
22
+ self.mode = 'sandbox'
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ class Error < StandardError
5
+
6
+ class BadInput < Error; end
7
+ class ConnectionFailed < Error; end
8
+ class Config < Error; end
9
+ class Unauthorized < Error; end
10
+ class Forbidden < Error; end
11
+ class NotFound < Error; end
12
+ class Redirect < Error; end
13
+ class WrongMethod < Error; end
14
+ class RateLimit < Error; end
15
+ class StorageQuota < Error; end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ module OAuth
5
+
6
+ class << self
7
+
8
+ def consumer(endpoint)
9
+ if !Dropbox::API::Config.app_key or !Dropbox::API::Config.app_secret
10
+ raise Dropbox::API::Error::Config.new("app_key or app_secret not provided")
11
+ end
12
+ ::OAuth::Consumer.new(Dropbox::API::Config.app_key, Dropbox::API::Config.app_secret,
13
+ :site => Dropbox::API::Config.endpoints[endpoint],
14
+ :request_token_path => Dropbox::API::Config.prefix + "/oauth/request_token",
15
+ :authorize_path => Dropbox::API::Config.prefix + "/oauth/authorize",
16
+ :access_token_path => Dropbox::API::Config.prefix + "/oauth/access_token")
17
+ end
18
+
19
+ def access_token(consumer, options = {})
20
+ ::OAuth::AccessToken.new(consumer, options[:token], options[:secret])
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+
@@ -0,0 +1,27 @@
1
+ module Dropbox
2
+ module API
3
+
4
+ module Util
5
+
6
+ class << self
7
+
8
+ def escape(string)
9
+ string.gsub(/([^ a-zA-Z0-9\.\\\-\/\_]+)/) do
10
+ '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
11
+ end.gsub(' ', '%20')
12
+ end
13
+
14
+ def query(data)
15
+ data.inject([]) { |memo, entry| memo.push(entry.join('=')); memo }.join('&')
16
+ end
17
+
18
+ def remove_double_slashes(path)
19
+ path.gsub('//', '/')
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module Dropbox
2
+ module API
3
+ VERSION = "0.4.7"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ app_key: # CONSUMER KEY
2
+ app_secret: # CONSUMER SECRET
3
+ token: # ACCESS TOKEN
4
+ secret: # ACCESS SECRET
5
+ mode: # 'sandbox' or 'dropbox'
Binary file
@@ -0,0 +1,259 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "tempfile"
4
+
5
+ describe Dropbox::API::Client do
6
+
7
+ before do
8
+ # pending
9
+ @client = Dropbox::Spec.instance
10
+ end
11
+
12
+ describe "#initialize" do
13
+
14
+ it "has a handle to the connection" do
15
+ @client.connection.should be_an_instance_of(Dropbox::API::Connection)
16
+ end
17
+
18
+ end
19
+
20
+ describe "#account" do
21
+
22
+ it "retrieves the account object" do
23
+ response = @client.account
24
+ response.should be_an_instance_of(Dropbox::API::Object)
25
+ end
26
+
27
+ end
28
+
29
+ describe "#find" do
30
+
31
+ before do
32
+ @filename = "#{Dropbox::Spec.test_dir}/spec-find-file-test-#{Time.now.to_i}.txt"
33
+ @file = @client.upload @filename, "spec file"
34
+
35
+ @dirname = "#{Dropbox::Spec.test_dir}/spec-find-dir-test-#{Time.now.to_i}"
36
+ @dir = @client.mkdir @dirname
37
+ end
38
+
39
+ it "returns a single file" do
40
+ response = @client.find(@filename)
41
+ response.path.should == @file.path
42
+ response.should be_an_instance_of(Dropbox::API::File)
43
+ end
44
+
45
+ it "returns a single directory" do
46
+ response = @client.find(@dirname)
47
+ response.path.should == @dir.path
48
+ response.should be_an_instance_of(Dropbox::API::Dir)
49
+ end
50
+
51
+ end
52
+
53
+ describe "#ls" do
54
+
55
+ it "returns an array of files and dirs" do
56
+ result = @client.ls
57
+ result.should be_an_instance_of(Array)
58
+ end
59
+
60
+ it "returns a single item array of if we ls a file" do
61
+ result = @client.ls(Dropbox::Spec.test_dir)
62
+ first_file = result.detect { |f| f.class == Dropbox::API::File }
63
+ result = @client.ls first_file.path
64
+ result.should be_an_instance_of(Array)
65
+ end
66
+
67
+ end
68
+
69
+ describe "#mkdir" do
70
+
71
+ it "returns an array of files and dirs" do
72
+ dirname = "#{Dropbox::Spec.test_dir}/test-dir-#{Dropbox::Spec.namespace}"
73
+ response = @client.mkdir dirname
74
+ response.path.should == dirname
75
+ response.should be_an_instance_of(Dropbox::API::Dir)
76
+ end
77
+
78
+ it "creates dirs with tricky characters" do
79
+ dirname = "#{Dropbox::Spec.test_dir}/test-dir |!@\#$%^&*{b}[].;'.,<>?: #{Dropbox::Spec.namespace}"
80
+ response = @client.mkdir dirname
81
+ response.path.should == dirname.gsub(/[\\\:\?\*\<\>\"\|]+/, '')
82
+ response.should be_an_instance_of(Dropbox::API::Dir)
83
+ end
84
+
85
+ it "creates dirs with utf8 characters" do
86
+ dirname = "#{Dropbox::Spec.test_dir}/test-dir łółą #{Dropbox::Spec.namespace}"
87
+ response = @client.mkdir dirname
88
+ response.path.should == dirname
89
+ response.should be_an_instance_of(Dropbox::API::Dir)
90
+ end
91
+
92
+ end
93
+
94
+ describe "#upload" do
95
+
96
+ it "puts the file in dropbox" do
97
+ filename = "#{Dropbox::Spec.test_dir}/test-#{Dropbox::Spec.namespace}.txt"
98
+ response = @client.upload filename, "Some file"
99
+ response.path.should == filename
100
+ response.bytes.should == 9
101
+ end
102
+
103
+ it "uploads the file with tricky characters" do
104
+ filename = "#{Dropbox::Spec.test_dir}/test ,|!@\#$%^&*{b}[].;'.,<>?:-#{Dropbox::Spec.namespace}.txt"
105
+ response = @client.upload filename, "Some file"
106
+ response.path.should == filename
107
+ response.bytes.should == 9
108
+ end
109
+
110
+ it "uploads the file with utf8" do
111
+ filename = "#{Dropbox::Spec.test_dir}/test łołąó-#{Dropbox::Spec.namespace}.txt"
112
+ response = @client.upload filename, "Some file"
113
+ response.path.should == filename
114
+ response.bytes.should == 9
115
+ end
116
+ end
117
+
118
+ describe "#chunked_upload" do
119
+
120
+ before do
121
+ @size = 5*1024*1024 # 5MB, to test the 4MB chunk size
122
+ @file = File.open("/tmp/dropbox-api-test", "w") {|f| f.write "a"*@size}
123
+ end
124
+
125
+ it "puts a 5MB file in dropbox" do
126
+ filename = "#{Dropbox::Spec.test_dir}/test-#{Dropbox::Spec.namespace}.txt"
127
+ response = @client.chunked_upload filename, File.open("/tmp/dropbox-api-test")
128
+ response.path.should == filename
129
+ response.bytes.should == @size
130
+ end
131
+
132
+ after do
133
+ FileUtils.rm "/tmp/dropbox-api-test"
134
+ end
135
+
136
+ end
137
+
138
+ describe "#destroy" do
139
+
140
+ before do
141
+ @client = Dropbox::Spec.instance
142
+ @filename = "#{Dropbox::Spec.test_dir}/spec-test-#{Time.now.to_i}.txt"
143
+ @file = @client.upload @filename, "spec file"
144
+ end
145
+
146
+ it "destroys the file properly" do
147
+ file = @client.destroy(@filename)
148
+ file.is_deleted.should == true
149
+ end
150
+
151
+ end
152
+
153
+ describe "#search" do
154
+
155
+ let(:term) { "searchable-test-#{Dropbox::Spec.namespace}" }
156
+
157
+ before do
158
+ filename = "#{Dropbox::Spec.test_dir}/searchable-test-#{Dropbox::Spec.namespace}.txt"
159
+ @client.upload filename, "Some file"
160
+ end
161
+
162
+ after do
163
+ @response.size.should == 1
164
+ @response.first.class.should == Dropbox::API::File
165
+ end
166
+
167
+ it "finds a file" do
168
+ @response = @client.search term, :path => "#{Dropbox::Spec.test_dir}"
169
+ end
170
+
171
+ it "works if leading slash is present in path" do
172
+ @response = @client.search term, :path => "/#{Dropbox::Spec.test_dir}"
173
+ end
174
+
175
+ end
176
+
177
+ describe "#copy_from_copy_ref" do
178
+
179
+ it "copies a file from a copy_ref" do
180
+ filename = "test/searchable-test-#{Dropbox::Spec.namespace}.txt"
181
+ @client.upload filename, "Some file"
182
+ response = @client.search "searchable-test-#{Dropbox::Spec.namespace}", :path => 'test'
183
+ ref = response.first.copy_ref['copy_ref']
184
+ @client.copy_from_copy_ref ref, "#{filename}.copied"
185
+ response = @client.search "searchable-test-#{Dropbox::Spec.namespace}.txt.copied", :path => 'test'
186
+ response.size.should == 1
187
+ response.first.class.should == Dropbox::API::File
188
+ end
189
+
190
+ end
191
+
192
+ describe "#download" do
193
+
194
+ it "downloads a file from Dropbox" do
195
+ @client.upload "#{Dropbox::Spec.test_dir}/test.txt", "Some file"
196
+ file = @client.download "#{Dropbox::Spec.test_dir}/test.txt"
197
+ file.should == "Some file"
198
+ end
199
+
200
+ it "raises a 404 when a file is not found in Dropbox" do
201
+ lambda {
202
+ @client.download "#{Dropbox::Spec.test_dir}/no.txt"
203
+ }.should raise_error(Dropbox::API::Error::NotFound)
204
+ end
205
+
206
+ end
207
+
208
+ describe "#delta" do
209
+ it "returns a cursor and list of files" do
210
+ filename = "#{Dropbox::Spec.test_dir}/delta-test-#{Dropbox::Spec.namespace}.txt"
211
+ @client.upload filename, 'Some file'
212
+ response = @client.delta
213
+ cursor, files = response.cursor, response.entries
214
+ cursor.should be_an_instance_of(String)
215
+ files.should be_an_instance_of(Array)
216
+ files.last.should be_an_instance_of(Dropbox::API::File)
217
+ end
218
+
219
+ it "returns the files that have changed since the cursor was made" do
220
+ filename = "#{Dropbox::Spec.test_dir}/delta-test-#{Dropbox::Spec.namespace}.txt"
221
+ delete_filename = "#{Dropbox::Spec.test_dir}/delta-test-delete-#{Dropbox::Spec.namespace}.txt"
222
+ @client.upload delete_filename, 'Some file'
223
+ response = @client.delta
224
+ cursor, files = response.cursor, response.entries
225
+ files.last.path.should == delete_filename
226
+ files.last.destroy
227
+ @client.upload filename, 'Another file'
228
+ response = @client.delta(cursor)
229
+ cursor, files = response.cursor, response.entries
230
+ files.length.should == 2
231
+ files.first.is_deleted.should == true
232
+ files.first.path.should == delete_filename
233
+ files.last.path.should == filename
234
+ end
235
+
236
+ context "with extra params" do
237
+
238
+ let(:response) do
239
+ {
240
+ 'cursor' => nil,
241
+ 'has_more' => false,
242
+ 'entries' => []
243
+ }
244
+ end
245
+
246
+ let(:params) do
247
+ { :path_prefix => 'my_path' }
248
+
249
+ end
250
+
251
+ it "passes them to raw delta" do
252
+ @client.raw.should_receive(:delta).with(params).and_return(response)
253
+ @client.delta nil, params
254
+ end
255
+
256
+ end
257
+ end
258
+
259
+ end