divshare 0.1.0 → 0.3.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.
- data/{License.txt → LICENSE} +1 -1
- data/{README.txt → README} +0 -0
- data/Rakefile +33 -3
- data/VERSION +1 -0
- data/lib/divshare.rb +0 -3
- data/lib/divshare/client.rb +101 -77
- data/lib/divshare/divshare_file.rb +8 -11
- data/lib/divshare/encoder.rb +50 -0
- data/lib/divshare/multipart.rb +37 -0
- data/spec/client_spec.rb +97 -107
- data/spec/divshare_file_spec.rb +1 -1
- data/spec/encoder_spec.rb +100 -0
- data/spec/spec_helper.rb +9 -3
- data/spec/user_spec.rb +1 -3
- metadata +42 -45
- data/History.txt +0 -4
- data/Manifest.txt +0 -35
- data/config/hoe.rb +0 -72
- data/config/requirements.rb +0 -17
- data/lib/divshare/post_args.rb +0 -16
- data/lib/divshare/version.rb +0 -9
- data/log/debug.log +0 -0
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/test_run_client +0 -59
- data/script/txt2html +0 -74
- data/setup.rb +0 -1585
- data/spec/fixtures/divshare_mock_valid_audio.html +0 -299
- data/spec/fixtures/divshare_mock_valid_video.html +0 -294
- data/spec/post_args_spec.rb +0 -54
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/website/index.html +0 -93
- data/website/index.txt +0 -39
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -138
- data/website/template.rhtml +0 -48
data/{License.txt → LICENSE}
RENAMED
data/{README.txt → README}
RENAMED
File without changes
|
data/Rakefile
CHANGED
@@ -1,4 +1,34 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
begin
|
2
|
+
require "spec/rake/spectask"
|
3
|
+
desc "Run all specs"
|
4
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
5
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
6
|
+
t.libs = ['spec', 'lib']
|
7
|
+
t.spec_opts = ["-c", "-f s"]
|
8
|
+
t.ruby_opts = ["-r rubygems"] # If you want to use rubygems for requires
|
9
|
+
end
|
10
|
+
rescue LoadError
|
11
|
+
puts "RSpec not available. Can't run specs without it. Install with: sudo gem install rspec"
|
12
|
+
end
|
3
13
|
|
4
|
-
|
14
|
+
task :default => :spec
|
15
|
+
|
16
|
+
begin
|
17
|
+
require "jeweler"
|
18
|
+
Jeweler::Tasks.new do |gemspec|
|
19
|
+
gemspec.name = "divshare"
|
20
|
+
gemspec.description = "A Ruby interface to the DivShare file hosting service"
|
21
|
+
gemspec.summary = "A Ruby interface to the DivShare file hosting service"
|
22
|
+
gemspec.date = Time.now.strftime("%Y-%m-%d")
|
23
|
+
gemspec.files = ["README", "LICENSE", "VERSION", "Rakefile", Dir::glob("lib/**/**")].flatten
|
24
|
+
gemspec.authors = ["Eric Watson"]
|
25
|
+
gemspec.email = "wasnotrice@gmail.com"
|
26
|
+
gemspec.homepage = "http://github.com/wasnotrice/divshare"
|
27
|
+
gemspec.rubyforge_project = "divshare"
|
28
|
+
|
29
|
+
gemspec.add_dependency "hpricot"
|
30
|
+
gemspec.add_dependency "mime-types"
|
31
|
+
end
|
32
|
+
rescue LoadError
|
33
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
34
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/divshare.rb
CHANGED
data/lib/divshare/client.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'cgi'
|
3
2
|
require 'net/http'
|
4
3
|
require 'hpricot'
|
5
4
|
require 'digest/md5'
|
6
|
-
require 'divshare/errors'
|
7
5
|
require 'divshare/divshare_file'
|
8
|
-
require 'divshare/
|
6
|
+
require 'divshare/encoder'
|
7
|
+
require 'divshare/errors'
|
8
|
+
require 'divshare/multipart'
|
9
9
|
require 'divshare/user'
|
10
10
|
|
11
11
|
module Divshare
|
@@ -18,19 +18,49 @@ module Divshare
|
|
18
18
|
# client.logout
|
19
19
|
#
|
20
20
|
class Client
|
21
|
+
|
22
|
+
API_URL = 'http://www.divshare.com/api/'
|
23
|
+
UPLOAD_URL = 'http://upload.divshare.com'
|
24
|
+
UPLOAD_PATH = '/api/upload'
|
25
|
+
|
21
26
|
SUCCESS = '1'
|
22
27
|
FAILURE = '0'
|
23
28
|
|
24
|
-
|
29
|
+
attr_accessor :debug # If true, extended debugging information is printed
|
30
|
+
|
31
|
+
def initialize(key, secret)
|
32
|
+
@encoder = Encoder.new(key, secret)
|
33
|
+
# @debug = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def key
|
37
|
+
@encoder.key
|
38
|
+
end
|
25
39
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def
|
31
|
-
@
|
32
|
-
|
33
|
-
|
40
|
+
def secret
|
41
|
+
@encoder.secret
|
42
|
+
end
|
43
|
+
|
44
|
+
def session_key
|
45
|
+
@encoder.session_key
|
46
|
+
end
|
47
|
+
|
48
|
+
def login(email, password)
|
49
|
+
logout if @encoder.session_key
|
50
|
+
response = send_method(:login, {'user_email' => email, 'user_password' => password})
|
51
|
+
@encoder.session_key = response.at(:api_session_key).inner_html
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if logout is successful.
|
55
|
+
def logout
|
56
|
+
response = send_method(:logout)
|
57
|
+
debug response.to_html
|
58
|
+
if response[:status] == SUCCESS
|
59
|
+
@encoder.session_key = nil
|
60
|
+
true
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
34
64
|
end
|
35
65
|
|
36
66
|
# file_ids should be an array of file ids
|
@@ -45,8 +75,8 @@ module Divshare
|
|
45
75
|
# logged-in user.
|
46
76
|
def get_files(file_ids)
|
47
77
|
file_ids = [file_ids] unless file_ids.is_a? Array
|
78
|
+
debug "DivShare.get_files(): #{file_ids.class}"
|
48
79
|
files = get_user_files
|
49
|
-
puts file_ids.class
|
50
80
|
files.delete_if {|f| file_ids.include?(f.file_id) == false}
|
51
81
|
end
|
52
82
|
|
@@ -57,8 +87,9 @@ module Divshare
|
|
57
87
|
get_files(file_id).first
|
58
88
|
end
|
59
89
|
|
60
|
-
# Returns an array of Divshare::DivshareFile objects belonging to the
|
61
|
-
# <tt>offset</tt> to narrow things
|
90
|
+
# Returns an array of Divshare::DivshareFile objects belonging to the
|
91
|
+
# logged-in user. Use <tt>limit</tt> and <tt>offset</tt> to narrow things
|
92
|
+
# down.
|
62
93
|
def get_user_files(limit=nil, offset=nil)
|
63
94
|
args = {}
|
64
95
|
args['limit'] = limit unless limit.nil?
|
@@ -67,8 +98,8 @@ module Divshare
|
|
67
98
|
files_from response
|
68
99
|
end
|
69
100
|
|
70
|
-
# Returns an array of Divshare::DivshareFile objects in the specified
|
71
|
-
# <tt>offset</tt> to narrow things down.
|
101
|
+
# Returns an array of Divshare::DivshareFile objects in the specified
|
102
|
+
# folder. Use <tt>limit</tt> and <tt>offset</tt> to narrow things down.
|
72
103
|
def get_folder_files(folder_id, limit=nil, offset=nil)
|
73
104
|
args = {}
|
74
105
|
args['limit'] = limit unless limit.nil?
|
@@ -80,51 +111,63 @@ module Divshare
|
|
80
111
|
|
81
112
|
# Returns information about the logged-in user
|
82
113
|
def get_user_info
|
83
|
-
response = send_method
|
84
|
-
user_from
|
114
|
+
response = send_method(:get_user_info)
|
115
|
+
user_from(response)
|
85
116
|
end
|
86
117
|
|
87
118
|
# Returns an upload ticket string for use in uploading files. See
|
88
119
|
# http://www.divshare.com/integrate/api#uploading for more information on
|
89
120
|
# how to use the upload ticket once you've got it.
|
90
121
|
def get_upload_ticket
|
91
|
-
|
92
|
-
upload_ticket_from response
|
122
|
+
send_method(:get_upload_ticket).at(:upload_ticket).inner_html
|
93
123
|
end
|
94
124
|
|
95
|
-
#
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
125
|
+
# Uploads a file or files to the user's DivShare account, and returns the
|
126
|
+
# file id(s).
|
127
|
+
#
|
128
|
+
# The DivShare API is written for use with actual HTML forms, so the API
|
129
|
+
# method requires a 'response_url', and makes a GET request to that url,
|
130
|
+
# sending the file id(s) as query parameters.
|
131
|
+
#
|
132
|
+
# Here, we're simulating the form, so we parse DivShare's GET request and
|
133
|
+
# simply return the file id(s). In this case, response_url is just a
|
134
|
+
# filler so that the server doesn't complain.
|
135
|
+
def upload(ticket, file_path, response_url='www.divshare.com/upload_result')
|
136
|
+
location = nil
|
137
|
+
File.open(file_path, 'r') { |file|
|
138
|
+
uri = URI.parse(UPLOAD_URL)
|
139
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
140
|
+
# API methods can be SLOW. Timeout interval should be long.
|
141
|
+
http.read_timeout = 15*60
|
142
|
+
request = Net::HTTP::Post.new(UPLOAD_PATH)
|
143
|
+
fields = Hash.new
|
144
|
+
fields['upload_ticket'] = ticket
|
145
|
+
# API doesn't allow blank response_url. This is just filler.
|
146
|
+
fields['response_url'] = response_url
|
108
147
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
148
|
+
fields['file1'] = file
|
149
|
+
request.multipart_params = fields
|
150
|
+
# Until DivShare supports direct upload API, we deal with its response location field
|
151
|
+
location = http.request(request)['location']
|
152
|
+
}
|
153
|
+
|
154
|
+
# if error, throw, otherwise return file ID for caller to do whatever they like
|
155
|
+
resp = {}
|
156
|
+
location.split('?')[1].split('&').each { |param|
|
157
|
+
k, v = param.split('=', 2) # some params could contain two '=' for some reason
|
158
|
+
resp[k]=CGI.unescape(v)
|
159
|
+
}
|
160
|
+
if resp['error']
|
161
|
+
raise Divshare::APIError, resp['description']
|
115
162
|
else
|
116
|
-
|
163
|
+
resp['file1'] # return the file ID
|
117
164
|
end
|
118
|
-
true
|
119
165
|
end
|
120
166
|
|
121
|
-
|
122
|
-
# http://www.divshare.com/integrate/api#sig
|
123
|
-
def sign(method, args)
|
124
|
-
Digest::MD5.hexdigest(string_to_sign(args))
|
125
|
-
end
|
167
|
+
|
126
168
|
|
127
169
|
private
|
170
|
+
|
128
171
|
def files_from(xml)
|
129
172
|
xml = xml/:file
|
130
173
|
xml = [xml] unless xml.respond_to?(:each)
|
@@ -136,11 +179,6 @@ module Divshare
|
|
136
179
|
Divshare::User.new(xml)
|
137
180
|
end
|
138
181
|
|
139
|
-
def upload_ticket_from(xml)
|
140
|
-
xml = xml.at(:upload_ticket).inner_html
|
141
|
-
end
|
142
|
-
|
143
|
-
# Since login and logout aren't easily re-nameable to use method missing
|
144
182
|
def send_method(method_id, *params)
|
145
183
|
response = http_post(method_id, *params)
|
146
184
|
xml = Hpricot(response).at(:response)
|
@@ -149,44 +187,30 @@ module Divshare
|
|
149
187
|
raise Divshare::APIError, errors.join("\n")
|
150
188
|
end
|
151
189
|
xml
|
152
|
-
end
|
153
|
-
|
154
|
-
def post_args(method, args)
|
155
|
-
PostArgs.new(self, method, args)
|
156
190
|
end
|
157
|
-
|
191
|
+
|
158
192
|
def http_post(method, args={})
|
159
|
-
url = URI.parse(
|
193
|
+
url = URI.parse(API_URL)
|
160
194
|
tries = 3
|
161
195
|
response = ""
|
196
|
+
form_args = @encoder.encode(method, args)
|
162
197
|
begin
|
163
|
-
response = Net::HTTP.post_form(url,
|
198
|
+
response = Net::HTTP.post_form(url, form_args).body
|
164
199
|
rescue
|
165
200
|
tries -= 1
|
166
|
-
|
201
|
+
debug "DivShare\#http_post() failed: #{tries} tries remaining"
|
167
202
|
if tries > 0
|
168
203
|
retry
|
169
204
|
else
|
170
|
-
raise Divshare::ConnectionError, "Couldn't connect for '#{method}' using #{
|
205
|
+
raise Divshare::ConnectionError, "Couldn't connect to #{API_URL} for '#{method}' using #{form_args.inspect}"
|
171
206
|
end
|
172
207
|
end
|
173
208
|
response
|
174
209
|
end
|
175
|
-
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
# * Your session key is 456-session.
|
180
|
-
# * You are using the get_user_files method, and you're sending the
|
181
|
-
# parameters limit=5 and offset=10.
|
182
|
-
#
|
183
|
-
# The string used to create your signature will be:
|
184
|
-
# 123-secret456-sessionlimit5offset10. Note that the parameters must be in
|
185
|
-
# alphabetical order, so limit always comes before offset. Each parameter
|
186
|
-
# should be paired with its value as shown.
|
187
|
-
def string_to_sign(args)
|
188
|
-
args_for_string = args.dup.delete_if {|k,v| %w(api_key method api_sig api_session_key).include?(k) }
|
189
|
-
"#{@api_secret}#{@api_session_key}#{args_for_string.to_a.sort.flatten.join}"
|
210
|
+
|
211
|
+
# Outputs whatever is given to $stderr if debugging is enabled.
|
212
|
+
def debug(*args)
|
213
|
+
$stderr.puts(sprintf(*args)) if @debug
|
190
214
|
end
|
191
215
|
end
|
192
|
-
end
|
216
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'hpricot'
|
3
2
|
|
4
3
|
module Divshare
|
@@ -64,11 +63,10 @@ module Divshare
|
|
64
63
|
def find_medium
|
65
64
|
ext = @file_name ? File.extname(@file_name) : nil
|
66
65
|
medium = case
|
67
|
-
when AUDIO.match(ext)
|
68
|
-
when VIDEO.match(ext)
|
69
|
-
when DOCUMENT.match(ext)
|
70
|
-
when IMAGE.match(ext)
|
71
|
-
else nil
|
66
|
+
when AUDIO.match(ext) then "audio"
|
67
|
+
when VIDEO.match(ext) then "video"
|
68
|
+
when DOCUMENT.match(ext) then "document"
|
69
|
+
when IMAGE.match(ext) then "image"
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
@@ -102,11 +100,10 @@ module Divshare
|
|
102
100
|
|
103
101
|
def image_embed_tag_template(opts={:size=>:midsize})
|
104
102
|
size = case opts[:size]
|
105
|
-
when :midsize, :mid
|
106
|
-
when :thumb, :thumbnail
|
107
|
-
|
108
|
-
end
|
103
|
+
when :midsize, :mid then "midsize/"
|
104
|
+
when :thumb, :thumbnail then "thumb/"
|
105
|
+
end || ""
|
109
106
|
tag = "http://www.divshare.com/img/#{size}[FILE ID]"
|
110
107
|
end
|
111
108
|
end
|
112
|
-
end
|
109
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Divshare
|
2
|
+
|
3
|
+
# Manages the arguments send along with a POST to the DivShare API URL.
|
4
|
+
# Takes care of organizing arguments and generating API signatures for
|
5
|
+
# requests
|
6
|
+
class Encoder # :nodoc:
|
7
|
+
attr_reader :key, :secret
|
8
|
+
attr_accessor :session_key
|
9
|
+
|
10
|
+
def initialize(key, secret)
|
11
|
+
@key, @secret = key, secret
|
12
|
+
end
|
13
|
+
|
14
|
+
# Prepares arguments for a post using the given method and arguments.
|
15
|
+
# Returns a hash of arguments and values
|
16
|
+
def encode(method, args={})
|
17
|
+
# Stringifies incoming keys and values
|
18
|
+
post_args = Hash.new
|
19
|
+
args.each { |k, v| post_args[k.to_s] = v.to_s }
|
20
|
+
post_args.merge!({'method' => method.to_s, 'api_key' => @key.to_s})
|
21
|
+
if @session_key
|
22
|
+
sig = sign(post_args)
|
23
|
+
post_args.merge!({'api_session_key' => @session_key.to_s, 'api_sig' => sig})
|
24
|
+
end
|
25
|
+
post_args
|
26
|
+
end
|
27
|
+
|
28
|
+
# Generates the required MD5 signature as described in
|
29
|
+
# http://www.divshare.com/integrate/api#sig
|
30
|
+
def sign(args)
|
31
|
+
Digest::MD5.hexdigest(string_to_sign(args))
|
32
|
+
end
|
33
|
+
|
34
|
+
# From http://www.divshare.com/integrate/api
|
35
|
+
#
|
36
|
+
# * Your secret key is 123-secret.
|
37
|
+
# * Your session key is 456-session.
|
38
|
+
# * You are using the get_user_files method, and you're sending the
|
39
|
+
# parameters limit=5 and offset=10.
|
40
|
+
#
|
41
|
+
# The string used to create your signature will be:
|
42
|
+
# 123-secret456-sessionlimit5offset10. Note that the parameters must be in
|
43
|
+
# alphabetical order, so limit always comes before offset. Each parameter
|
44
|
+
# should be paired with its value as shown.
|
45
|
+
def string_to_sign(args)
|
46
|
+
args_for_string = args.dup.delete_if {|k,v| %w(api_key method api_sig api_session_key).include?(k) }
|
47
|
+
"#{@secret}#{@session_key}#{args_for_string.to_a.sort.flatten.join}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# This is based on this article from Pivot Labs:
|
2
|
+
# http://pivots.pivotallabs.com/users/damon/blog/articles/227-standup-04-27-07-testing-file-uploads
|
3
|
+
|
4
|
+
require 'net/https'
|
5
|
+
require "mime/types" # Requires gem install mime-types
|
6
|
+
|
7
|
+
module Net #:nodoc:all
|
8
|
+
class HTTP::Post
|
9
|
+
def multipart_params=(param_hash={})
|
10
|
+
boundary_token = [Array.new(8) {rand(256)}].join
|
11
|
+
self.content_type = "multipart/form-data; boundary=#{boundary_token}"
|
12
|
+
boundary_marker = "--#{boundary_token}\r\n"
|
13
|
+
self.body = param_hash.map { |param_name, param_value|
|
14
|
+
boundary_marker + case param_value
|
15
|
+
when File
|
16
|
+
file_to_multipart(param_name, param_value)
|
17
|
+
else
|
18
|
+
text_to_multipart(param_name, param_value.to_s)
|
19
|
+
end
|
20
|
+
}.join('') + "--#{boundary_token}--\r\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def file_to_multipart(key,file)
|
25
|
+
filename = File.basename(file.path)
|
26
|
+
mime_types = MIME::Types.of(filename)
|
27
|
+
mime_type = mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
|
28
|
+
part = %Q|Content-Disposition: form-data; name="#{key}"; filename="#{filename}"\r\n|
|
29
|
+
part += "Content-Transfer-Encoding: binary\r\n"
|
30
|
+
part += "Content-Type: #{mime_type}\r\n\r\n#{file.read}\r\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
def text_to_multipart(key,value)
|
34
|
+
"Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n#{value}\r\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -1,175 +1,150 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'divshare/client'
|
3
3
|
include Divshare
|
4
4
|
|
5
5
|
module ClientSpecHelper
|
6
6
|
include DivshareMockXML
|
7
|
-
|
8
|
-
Client.new('api_key', 'api_secret')
|
9
|
-
end
|
10
|
-
|
11
|
-
def new_client_with_email_and_password
|
12
|
-
Client.new('api_key', 'api_secret', 'email', 'password')
|
13
|
-
end
|
14
|
-
|
15
|
-
def login(client, api_session_key='123-abcdefghijkl')
|
16
|
-
client.stub!(:login).and_return(api_session_key)
|
17
|
-
client.instance_variable_set(:@api_session_key, client.login)
|
18
|
-
api_session_key
|
19
|
-
end
|
20
|
-
|
7
|
+
|
21
8
|
# Each setup must declare what @mock_response will return
|
22
|
-
def common_setup(
|
23
|
-
|
24
|
-
@
|
25
|
-
@api_session_key =
|
9
|
+
def common_setup()
|
10
|
+
@api_key = 'api_key'
|
11
|
+
@api_secret = 'api_secret'
|
12
|
+
@api_session_key = '123-abcdefghijkl'
|
13
|
+
@user_email = 'fake_user_email'
|
14
|
+
@password = 'fake_password'
|
26
15
|
@files = ['2734485-1fc', '2735059-62d']
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
@api_url = URI.parse(Divshare::Client::API_URL)
|
17
|
+
end
|
18
|
+
|
19
|
+
def no_login_setup
|
31
20
|
@mock_response = mock('response')
|
32
|
-
Net::HTTP.
|
21
|
+
Net::HTTP.should_receive(:post_form).once.and_return(@mock_response)
|
22
|
+
@client = Client.new(@api_key, @api_secret)
|
33
23
|
end
|
34
24
|
|
35
|
-
def
|
36
|
-
|
25
|
+
def login_setup
|
26
|
+
@mock_response = mock('response')
|
27
|
+
@mock_login_response = mock('login_response')
|
28
|
+
Net::HTTP.should_receive(:post_form).twice.and_return(@mock_login_response, @mock_response)
|
29
|
+
@mock_login_response.should_receive(:body).and_return(successful_login_xml)
|
30
|
+
@client = Client.new(@api_key, @api_secret)
|
31
|
+
@client.login(@user_email, @password)
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
40
35
|
describe "A new Divshare Client" do
|
41
36
|
include ClientSpecHelper
|
42
|
-
|
43
|
-
|
44
|
-
new_client.should be_instance_of(Divshare::Client)
|
37
|
+
before :all do
|
38
|
+
common_setup
|
45
39
|
end
|
46
40
|
|
47
|
-
|
48
|
-
|
41
|
+
before :each do
|
42
|
+
@client = Client.new(@api_key, @api_secret)
|
49
43
|
end
|
50
|
-
|
51
|
-
it "should
|
52
|
-
client
|
53
|
-
[client.api_key, client.api_secret, client.email, client.password].should == ['api_key', 'api_secret', 'email', 'password']
|
44
|
+
|
45
|
+
it "should be created successfully" do
|
46
|
+
@client.should be_instance_of(Divshare::Client)
|
54
47
|
end
|
55
48
|
|
56
49
|
it "should know the proper post url" do
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
# Using string 'api_secret123-abcdefghijklfiles2734485-1fc'
|
61
|
-
it "should generate a correct signature" do
|
62
|
-
api_sig = '0e1c483506dd413808c80183333e1fc2'
|
63
|
-
common_setup(:stub_sign => false)
|
64
|
-
@client.sign("get_files", {"files" => @files.first}).should == api_sig
|
50
|
+
Divshare::Client::API_URL.should == "http://www.divshare.com/api/"
|
65
51
|
end
|
66
52
|
|
67
53
|
it "should raise Divshare::ConnectionError on timeout" do
|
68
|
-
|
69
|
-
|
70
|
-
lambda { new_client_with_email_and_password.login }.should raise_error(Divshare::ConnectionError)
|
54
|
+
pending 'Timeout code implementation'
|
55
|
+
lambda { @client.login('email', 'password') }.should raise_error(Divshare::ConnectionError)
|
71
56
|
end
|
72
57
|
|
73
58
|
end
|
74
59
|
|
60
|
+
describe Divshare::Client, "making a request to the API" do
|
61
|
+
# spec the request format. This should suffice for all requests.
|
62
|
+
|
63
|
+
end
|
64
|
+
|
75
65
|
describe "A Divshare Client getting one file" do
|
76
66
|
include ClientSpecHelper
|
77
|
-
before(:
|
67
|
+
before(:all) do
|
78
68
|
common_setup
|
79
69
|
end
|
80
|
-
|
81
|
-
# If it generates a PostArgs object, it's doing the right thing
|
82
|
-
it "should generate arguments for post" do
|
83
|
-
pending("Fix to API that allows correct get_files method")
|
84
|
-
@mock_response.should_receive(:body).and_return(get_one_file_xml)
|
85
|
-
PostArgs.should_receive(:new).with(@client,:get_files,{'files' => @files.first})
|
86
|
-
@client.get_files(@files.first)
|
87
|
-
end
|
88
70
|
|
89
71
|
it "should return an array of one DivshareFile when requesting a file through get_files" do
|
72
|
+
login_setup
|
90
73
|
@mock_response.should_receive(:body).and_return(get_one_file_xml)
|
91
74
|
@client.get_files('123456-abc').map {|f| f.class}.should == [DivshareFile]
|
92
75
|
end
|
93
76
|
|
94
77
|
it "should return a DivshareFile when requesting a file through get_file" do
|
78
|
+
login_setup
|
95
79
|
@mock_response.should_receive(:body).and_return(get_one_file_xml)
|
96
80
|
@client.get_file('123456-abc').class.should == DivshareFile
|
97
81
|
end
|
98
82
|
|
99
83
|
it "should raise ArgumentError if an array is passed to get_file" do
|
84
|
+
@client = Client.new(@api_key, @api_secret)
|
100
85
|
lambda {@client.get_file(['123456-abc'])}.should raise_error(ArgumentError)
|
101
86
|
end
|
102
87
|
end
|
103
88
|
|
104
89
|
describe "A Divshare Client getting two files" do
|
105
90
|
include ClientSpecHelper
|
106
|
-
before(:
|
91
|
+
before(:all) do
|
107
92
|
common_setup
|
108
93
|
end
|
109
94
|
|
95
|
+
before :each do
|
96
|
+
login_setup
|
97
|
+
@mock_response.should_receive(:body).and_return(get_two_files_xml)
|
98
|
+
end
|
99
|
+
|
110
100
|
it "should return an array of two DivshareFiles" do
|
111
|
-
mock_response = mock('response')
|
112
|
-
Net::HTTP.stub!(:post_form).and_return(mock_response)
|
113
|
-
mock_response.should_receive(:body).and_return(get_two_files_xml)
|
114
101
|
@client.get_files(['123456-abc', '456789-def']).map {|f| f.class}.should == [DivshareFile, DivshareFile]
|
115
102
|
end
|
116
103
|
end
|
117
104
|
|
118
105
|
describe "A Divshare Client getting user files" do
|
119
106
|
include ClientSpecHelper
|
120
|
-
before
|
107
|
+
before :all do
|
121
108
|
common_setup
|
122
|
-
|
109
|
+
end
|
110
|
+
|
111
|
+
before :each do
|
112
|
+
login_setup
|
113
|
+
@mock_response.should_receive(:body).and_return(get_two_files_xml)
|
123
114
|
end
|
124
115
|
|
125
116
|
it "should return an array of files" do
|
126
117
|
@client.get_user_files.map {|f| f.class }.should == [DivshareFile, DivshareFile]
|
127
118
|
end
|
128
|
-
|
129
|
-
# If it generates a PostArgs object, it's doing the right thing
|
130
|
-
it "should generate arguments for post" do
|
131
|
-
PostArgs.should_receive(:new).with(@client,:get_user_files, {})
|
132
|
-
@client.get_user_files
|
133
|
-
end
|
134
|
-
|
135
|
-
it "should generate arguments for post with limit and offset" do
|
136
|
-
PostArgs.should_receive(:new).with(@client, :get_user_files, {"limit" => 5, "offset" => 2})
|
137
|
-
@client.get_user_files(5, 2)
|
138
|
-
end
|
139
|
-
|
140
119
|
end
|
141
120
|
|
142
121
|
describe "A Divshare Client getting folder files" do
|
143
122
|
include ClientSpecHelper
|
144
|
-
before
|
123
|
+
before :all do
|
145
124
|
common_setup
|
146
|
-
@mock_response.should_receive(:body).and_return(get_two_files_xml)
|
147
125
|
end
|
148
126
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
# If it generates a PostArgs object, it's doing the right thing
|
154
|
-
it "should generate arguments for post" do
|
155
|
-
PostArgs.should_receive(:new).with(@client,:get_folder_files, {'folder_id' => '12345'})
|
156
|
-
@client.get_folder_files('12345')
|
127
|
+
before :each do
|
128
|
+
login_setup
|
129
|
+
@mock_response.should_receive(:body).and_return(get_two_files_xml)
|
157
130
|
end
|
158
131
|
|
159
|
-
it "should
|
160
|
-
|
161
|
-
@client.get_folder_files('12345', 5, 2)
|
132
|
+
it "should return an array of files" do
|
133
|
+
@client.get_folder_files('12345').map {|f| f.class }.should == [DivshareFile, DivshareFile]
|
162
134
|
end
|
163
|
-
|
164
|
-
|
165
135
|
end
|
166
136
|
|
167
137
|
describe "A Divshare Client, creating an upload ticket" do
|
168
138
|
include ClientSpecHelper
|
169
|
-
before
|
139
|
+
before :all do
|
170
140
|
common_setup
|
141
|
+
end
|
142
|
+
|
143
|
+
before :each do
|
144
|
+
login_setup
|
171
145
|
@mock_response.should_receive(:body).and_return(get_upload_ticket_xml)
|
172
146
|
end
|
147
|
+
|
173
148
|
it "should return an upload ticket" do
|
174
149
|
@client.get_upload_ticket.should == '123-abcdefghijkl'
|
175
150
|
end
|
@@ -177,45 +152,60 @@ end
|
|
177
152
|
|
178
153
|
describe "A Divshare Client, logging in" do
|
179
154
|
include ClientSpecHelper
|
180
|
-
before
|
181
|
-
common_setup
|
182
|
-
@api_session_key = login(new_client)
|
183
|
-
@mock_response.should_receive(:body).and_return(successful_login_xml)
|
155
|
+
before :all do
|
156
|
+
common_setup
|
184
157
|
end
|
185
158
|
|
186
|
-
|
187
|
-
|
159
|
+
before :each do
|
160
|
+
no_login_setup
|
161
|
+
@mock_response.should_receive(:body).and_return(successful_login_xml)
|
188
162
|
end
|
189
|
-
|
163
|
+
|
190
164
|
it "should set api session key" do
|
191
|
-
@client.
|
192
|
-
@client.login
|
193
|
-
@client.
|
165
|
+
@client.session_key.should_not == @api_session_key
|
166
|
+
@client.login(@user_email, @password)
|
167
|
+
@client.session_key.should == @api_session_key
|
194
168
|
end
|
195
169
|
end
|
196
170
|
|
197
171
|
describe "A DivshareClient, unsuccessfully logging in" do
|
198
172
|
include ClientSpecHelper
|
199
173
|
it "should raise Divshare::APIError" do
|
200
|
-
common_setup
|
174
|
+
common_setup
|
175
|
+
no_login_setup
|
201
176
|
@mock_response.should_receive(:body).and_return(error_xml("Couldn't log in"))
|
202
|
-
lambda {@client.login}.should raise_error(Divshare::APIError)
|
177
|
+
lambda {@client.login(@user_email, @password)}.should raise_error(Divshare::APIError)
|
203
178
|
end
|
204
179
|
end
|
205
180
|
|
206
|
-
describe "A Divshare Client, logging out" do
|
181
|
+
describe "A Divshare Client, successfully logging out" do
|
207
182
|
include ClientSpecHelper
|
208
|
-
before
|
183
|
+
before :all do
|
209
184
|
common_setup
|
185
|
+
end
|
186
|
+
|
187
|
+
before :each do
|
188
|
+
login_setup
|
210
189
|
@mock_response.should_receive(:body).and_return(successful_logout_xml)
|
211
190
|
end
|
212
191
|
|
213
|
-
it "should
|
192
|
+
it "should return true" do
|
214
193
|
@client.logout.should be_true
|
215
194
|
end
|
216
|
-
|
217
|
-
it "should remove api session key
|
195
|
+
|
196
|
+
it "should remove api session key" do
|
218
197
|
@client.logout
|
219
|
-
@client.
|
198
|
+
@client.session_key.should be_nil
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "A Divshare Client, unsuccessfully logging out" do
|
203
|
+
include ClientSpecHelper
|
204
|
+
|
205
|
+
it "should return false" do
|
206
|
+
common_setup
|
207
|
+
login_setup
|
208
|
+
@mock_response.should_receive(:body).and_return(unsuccessful_logout_xml)
|
209
|
+
lambda {@client.logout}.should raise_error(Divshare::APIError)
|
220
210
|
end
|
221
211
|
end
|