fleakr 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +32 -5
- data/Rakefile +1 -1
- data/lib/fleakr.rb +34 -6
- data/lib/fleakr/api.rb +1 -0
- data/lib/fleakr/api/method_request.rb +9 -4
- data/lib/fleakr/api/option.rb +175 -0
- data/lib/fleakr/api/parameter_list.rb +7 -6
- data/lib/fleakr/api/upload_request.rb +17 -11
- data/lib/fleakr/core_ext.rb +3 -1
- data/lib/fleakr/core_ext/false_class.rb +7 -0
- data/lib/fleakr/core_ext/true_class.rb +7 -0
- data/lib/fleakr/objects/authentication_token.rb +25 -8
- data/lib/fleakr/objects/photo.rb +21 -6
- data/lib/fleakr/support/object.rb +4 -2
- data/lib/fleakr/version.rb +1 -1
- data/test/fixtures/auth.getToken.xml +8 -0
- data/test/unit/fleakr/api/method_request_test.rb +0 -10
- data/test/unit/fleakr/api/option_test.rb +179 -0
- data/test/unit/fleakr/api/parameter_list_test.rb +33 -18
- data/test/unit/fleakr/api/upload_request_test.rb +21 -9
- data/test/unit/fleakr/core_ext/false_class_test.rb +13 -0
- data/test/unit/fleakr/core_ext/true_class_test.rb +13 -0
- data/test/unit/fleakr/objects/authentication_token_test.rb +16 -2
- data/test/unit/fleakr/objects/photo_test.rb +22 -8
- data/test/unit/fleakr_test.rb +72 -4
- metadata +10 -3
data/lib/fleakr/core_ext.rb
CHANGED
@@ -17,22 +17,39 @@ module Fleakr
|
|
17
17
|
|
18
18
|
flickr_attribute :value, :from => 'auth/token'
|
19
19
|
flickr_attribute :permissions, :from => 'auth/perms'
|
20
|
+
flickr_attribute :user_id, :from => 'auth/user@nsid'
|
21
|
+
flickr_attribute :user_name, :from => 'auth/user@username'
|
22
|
+
flickr_attribute :full_name, :from => 'auth/user@fullname'
|
20
23
|
|
21
24
|
# Retrieve a full authentication token from the supplied mini-token (e.g. 123-456-789)
|
22
25
|
#
|
23
|
-
def self.from_mini_token(
|
24
|
-
|
25
|
-
response = Fleakr::Api::MethodRequest.with_response!('auth.getFullToken', parameters)
|
26
|
-
|
27
|
-
self.new(response.body)
|
26
|
+
def self.from_mini_token(mini_token)
|
27
|
+
from :mini_token, mini_token
|
28
28
|
end
|
29
29
|
|
30
30
|
# Retrieve a full authentication token from the supplied auth_token string
|
31
31
|
# (e.g. 45-76598454353455)
|
32
32
|
#
|
33
|
-
def self.from_auth_token(
|
34
|
-
|
35
|
-
|
33
|
+
def self.from_auth_token(auth_token)
|
34
|
+
from :auth_token, auth_token
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieve a full authentication token from the supplied frob
|
38
|
+
def self.from_frob(frob)
|
39
|
+
from :frob, frob
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from(thing, value) # :nodoc:
|
43
|
+
api_methods = {
|
44
|
+
:mini_token => 'getFullToken',
|
45
|
+
:auth_token => 'checkToken',
|
46
|
+
:frob => 'getToken'
|
47
|
+
}
|
48
|
+
|
49
|
+
method = "auth.#{api_methods[thing]}"
|
50
|
+
|
51
|
+
parameters = {thing => value, :authenticate? => false}
|
52
|
+
response = Fleakr::Api::MethodRequest.with_response!(method, parameters)
|
36
53
|
|
37
54
|
self.new(response.body)
|
38
55
|
end
|
data/lib/fleakr/objects/photo.rb
CHANGED
@@ -3,6 +3,9 @@ module Fleakr
|
|
3
3
|
|
4
4
|
# = Photo
|
5
5
|
#
|
6
|
+
# Handles both the retrieval of Photo objects from various associations (e.g. User / Set) as
|
7
|
+
# well as the ability to upload images to the Flickr site.
|
8
|
+
#
|
6
9
|
# == Attributes
|
7
10
|
#
|
8
11
|
# [id] The ID for this photo
|
@@ -59,20 +62,32 @@ module Fleakr
|
|
59
62
|
|
60
63
|
has_many :images
|
61
64
|
|
62
|
-
# Upload the photo specified by <tt>filename</tt> to the user's Flickr account.
|
63
|
-
#
|
65
|
+
# Upload the photo specified by <tt>filename</tt> to the user's Flickr account. When uploading,
|
66
|
+
# there are several options available (none are required):
|
67
|
+
#
|
68
|
+
# [:title] The title for this photo. Any string is allowed.
|
69
|
+
# [:description] The description for this photo. Any string is allowed.
|
70
|
+
# [:tags] A collection of tags for this photo. This can be a string or array of strings.
|
71
|
+
# [:viewable_by] Who can view this photo? Acceptable values are one of <tt>:everyone</tt>,
|
72
|
+
# <tt>:friends</tt> or <tt>:family</tt>. This can also take an array of values
|
73
|
+
# (e.g. <tt>[:friends, :family]</tt>) to make it viewable by friends and family.
|
74
|
+
# [:level] The safety level of this photo. Acceptable values are one of <tt>:safe</tt>,
|
75
|
+
# <tt>:moderate</tt>, or <tt>:restricted</tt>.
|
76
|
+
# [:type] The type of image this is. Acceptable values are one of <tt>:photo</tt>,
|
77
|
+
# <tt>:screenshot</tt>, or <tt>:other</tt>.
|
78
|
+
# [:hide?] Should this photo be hidden from public searches? Takes a boolean.
|
64
79
|
#
|
65
|
-
def self.upload(filename)
|
66
|
-
response = Fleakr::Api::UploadRequest.with_response!(filename)
|
80
|
+
def self.upload(filename, options = {})
|
81
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :create, options)
|
67
82
|
photo = Photo.new(response.body)
|
68
|
-
Photo.find_by_id(photo.id
|
83
|
+
Photo.find_by_id(photo.id)
|
69
84
|
end
|
70
85
|
|
71
86
|
# Replace the current photo's image with the one specified by filename. This
|
72
87
|
# call requires authentication.
|
73
88
|
#
|
74
89
|
def replace_with(filename)
|
75
|
-
response = Fleakr::Api::UploadRequest.with_response!(filename, :photo_id => self.id
|
90
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :update, :photo_id => self.id)
|
76
91
|
self.populate_from(response.body)
|
77
92
|
self
|
78
93
|
end
|
@@ -33,8 +33,10 @@ module Fleakr
|
|
33
33
|
target_class = options[:class_name].nil? ? self.name : "Fleakr::Objects::#{options[:class_name]}"
|
34
34
|
|
35
35
|
class_eval <<-CODE
|
36
|
-
def self.find_all_#{condition}(value)
|
37
|
-
|
36
|
+
def self.find_all_#{condition}(value, options = {})
|
37
|
+
options.merge!(:#{attribute} => value)
|
38
|
+
|
39
|
+
response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', options)
|
38
40
|
(response.body/'rsp/#{options[:path]}').map {|e| #{target_class}.new(e) }
|
39
41
|
end
|
40
42
|
CODE
|
data/lib/fleakr/version.rb
CHANGED
@@ -26,16 +26,6 @@ module Fleakr::Api
|
|
26
26
|
request.parameters[:method].value.should == 'flickr.people.findByUsername'
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should know that it needs to sign the request" do
|
30
|
-
ParameterList.expects(:new).with(:sign? => true).returns(stub(:<< => nil))
|
31
|
-
request = MethodRequest.new('people.findByUsername', :sign? => true)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should know that it needs to authenticate the request" do
|
35
|
-
ParameterList.expects(:new).with(:authenticate? => true).returns(stub(:<< => nil))
|
36
|
-
request = MethodRequest.new('activity.userPhotos', :authenticate? => true)
|
37
|
-
end
|
38
|
-
|
39
29
|
it "should know the endpoint with full parameters" do
|
40
30
|
query_parameters = 'foo=bar'
|
41
31
|
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../test_helper'
|
2
|
+
|
3
|
+
module Fleakr::Api
|
4
|
+
|
5
|
+
class OptionTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def self.should_know_the_class_for(type, options)
|
8
|
+
it "should know the class for the :#{type} type" do
|
9
|
+
Option.class_for(type).should == options[:is]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "The Option class" do
|
14
|
+
should_know_the_class_for :title, :is => Fleakr::Api::SimpleOption
|
15
|
+
should_know_the_class_for :description, :is => Fleakr::Api::SimpleOption
|
16
|
+
should_know_the_class_for :tags, :is => Fleakr::Api::TagOption
|
17
|
+
should_know_the_class_for :viewable_by, :is => Fleakr::Api::ViewOption
|
18
|
+
should_know_the_class_for :level, :is => Fleakr::Api::LevelOption
|
19
|
+
should_know_the_class_for :type, :is => Fleakr::Api::TypeOption
|
20
|
+
should_know_the_class_for :hide?, :is => Fleakr::Api::HiddenOption
|
21
|
+
|
22
|
+
it "should be able to create an option for a type" do
|
23
|
+
option = stub()
|
24
|
+
|
25
|
+
Option.expects(:class_for).with(:title).returns(Fleakr::Api::SimpleOption)
|
26
|
+
Fleakr::Api::SimpleOption.expects(:new).with(:title, 'blip').returns(option)
|
27
|
+
|
28
|
+
Option.for(:title, 'blip').should == option
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class SimpleOptionTest < Test::Unit::TestCase
|
35
|
+
|
36
|
+
describe "An instance of the SimpleOption class" do
|
37
|
+
it "should have a type" do
|
38
|
+
so = SimpleOption.new(:title, 'blip')
|
39
|
+
so.type.should == :title
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have a value" do
|
43
|
+
so = SimpleOption.new(:title, 'blip')
|
44
|
+
so.value.should == 'blip'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be able to generate a hash representation of itself" do
|
48
|
+
so = SimpleOption.new(:title, 'blip')
|
49
|
+
so.to_hash.should == {:title => 'blip'}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class TagOptionTest < Test::Unit::TestCase
|
56
|
+
|
57
|
+
describe "An instance of the TagOption class" do
|
58
|
+
|
59
|
+
it "should normalize the input value to an array" do
|
60
|
+
to = TagOption.new(:tags, 'blip')
|
61
|
+
to.value.should == ['blip']
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be able to generate a hash representation of itself with tags joined on spaces" do
|
65
|
+
to = TagOption.new(:tags, %w(bop bip))
|
66
|
+
to.to_hash.should == {:tags => '"bop" "bip"'}
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should quote tag values with spaces" do
|
70
|
+
to = TagOption.new(:tags, ['tag', 'one with spaces'])
|
71
|
+
to.to_hash.should == {:tags => '"tag" "one with spaces"'}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
class ViewOptionTest < Test::Unit::TestCase
|
78
|
+
|
79
|
+
describe "An instance of the ViewOption class" do
|
80
|
+
it "should be able to generate a hash representation for viewing by :everyone" do
|
81
|
+
vo = ViewOption.new(:viewable_by, :everyone)
|
82
|
+
vo.to_hash.should == {:is_public => 1, :is_family => 0, :is_friend => 0}
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should be able to generate a hash representation for viewing by :family" do
|
86
|
+
vo = ViewOption.new(:viewable_by, :family)
|
87
|
+
vo.to_hash.should == {:is_public => 0, :is_family => 1, :is_friend => 0}
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be able to generate a hash representation for viewing by :friends" do
|
91
|
+
vo = ViewOption.new(:viewable_by, :friends)
|
92
|
+
vo.to_hash.should == {:is_public => 0, :is_family => 0, :is_friend => 1}
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should know the visibility is public if value is set to :everyone" do
|
96
|
+
vo = ViewOption.new(:viewable_by, :everyone)
|
97
|
+
vo.public?.should be(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should know the visibility is not public if :everyone is not the only value" do
|
101
|
+
vo = ViewOption.new(:viewable_by, [:everyone, :family])
|
102
|
+
vo.public?.should be(false)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should know that its visible to friends and family if specified as such" do
|
106
|
+
vo = ViewOption.new(:viewable_by, [:friends, :family])
|
107
|
+
vo.friends?.should be(true)
|
108
|
+
vo.family?.should be(true)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
class LevelOptionTest < Test::Unit::TestCase
|
116
|
+
|
117
|
+
describe "An instance of the LevelOption class" do
|
118
|
+
|
119
|
+
it "should be able to generate a hash representation for the :safe level" do
|
120
|
+
lo = LevelOption.new(:level, :safe)
|
121
|
+
lo.to_hash.should == {:safety_level => 1}
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should be able to generate a hash representation for the :moderate level" do
|
125
|
+
lo = LevelOption.new(:level, :moderate)
|
126
|
+
lo.to_hash.should == {:safety_level => 2}
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should be able to generate a hash representation for the :restricted level" do
|
130
|
+
lo = LevelOption.new(:level, :restricted)
|
131
|
+
lo.to_hash.should == {:safety_level => 3}
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
class TypeOptionTest < Test::Unit::TestCase
|
139
|
+
|
140
|
+
describe "An instance of the TypeOption class" do
|
141
|
+
|
142
|
+
it "should be able to generate a hash representation for the :photo type" do
|
143
|
+
to = TypeOption.new(:type, :photo)
|
144
|
+
to.to_hash.should == {:content_type => 1}
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should be able to generate a hash representation for the :screenshot type" do
|
148
|
+
to = TypeOption.new(:type, :screenshot)
|
149
|
+
to.to_hash.should == {:content_type => 2}
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should be able to generate a hash representation for the :other type" do
|
153
|
+
to = TypeOption.new(:type, :other)
|
154
|
+
to.to_hash.should == {:content_type => 3}
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
class HiddenOptionTest < Test::Unit::TestCase
|
162
|
+
|
163
|
+
describe "An instance of the HiddenOption class" do
|
164
|
+
|
165
|
+
it "should be able to generate a hash representation when set to true" do
|
166
|
+
ho = HiddenOption.new(:hide?, true)
|
167
|
+
ho.to_hash.should == {:hidden => 2}
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should be able to generate a hash representation when set to false" do
|
171
|
+
ho = HiddenOption.new(:hide?, false)
|
172
|
+
ho.to_hash.should == {:hidden => 1}
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
@@ -9,7 +9,6 @@ module Fleakr::Api
|
|
9
9
|
@api_key = 'key'
|
10
10
|
@secret = 'foobar'
|
11
11
|
|
12
|
-
Fleakr.stubs(:shared_secret).with().returns(@secret)
|
13
12
|
Fleakr.stubs(:api_key).with().returns(@api_key)
|
14
13
|
@parameter_list = ParameterList.new
|
15
14
|
end
|
@@ -24,7 +23,7 @@ module Fleakr::Api
|
|
24
23
|
parameter_list = ParameterList.new(:one => 'two')
|
25
24
|
parameter_list[:one].value.should == 'two'
|
26
25
|
end
|
27
|
-
|
26
|
+
|
28
27
|
it "should be able to add parameters to its list" do
|
29
28
|
parameter = ValueParameter.new('foo', 'bar')
|
30
29
|
|
@@ -47,11 +46,15 @@ module Fleakr::Api
|
|
47
46
|
end
|
48
47
|
|
49
48
|
it "should be able to calculate the signature of the parameters" do
|
49
|
+
Fleakr.stubs(:shared_secret).with().returns(@secret)
|
50
|
+
|
50
51
|
@parameter_list << ValueParameter.new('foo', 'bar')
|
51
52
|
@parameter_list.signature.should == Digest::MD5.hexdigest("#{@secret}api_key#{@api_key}foobar")
|
52
53
|
end
|
53
54
|
|
54
55
|
it "should use the correct order when signing a list of multiple parameters" do
|
56
|
+
Fleakr.stubs(:shared_secret).with().returns(@secret)
|
57
|
+
|
55
58
|
@parameter_list << ValueParameter.new('z', 'a')
|
56
59
|
@parameter_list << ValueParameter.new('a', 'z')
|
57
60
|
|
@@ -59,6 +62,8 @@ module Fleakr::Api
|
|
59
62
|
end
|
60
63
|
|
61
64
|
it "should ignore the parameters that aren't included in the signature" do
|
65
|
+
Fleakr.stubs(:shared_secret).with().returns(@secret)
|
66
|
+
|
62
67
|
@parameter_list << ValueParameter.new('foo', 'bar')
|
63
68
|
@parameter_list << ValueParameter.new('yes', 'no', false)
|
64
69
|
|
@@ -76,15 +81,30 @@ module Fleakr::Api
|
|
76
81
|
@parameter_list.sign?.should be(false)
|
77
82
|
end
|
78
83
|
|
79
|
-
it "should know that it needs to sign the request when
|
80
|
-
|
81
|
-
parameter_list.sign?.should be(true)
|
84
|
+
it "should know that it needs to sign the request when a shared secret is available" do
|
85
|
+
Fleakr.expects(:shared_secret).with().returns(@secret)
|
86
|
+
@parameter_list.sign?.should be(true)
|
82
87
|
end
|
83
88
|
|
84
89
|
it "should know that it doesn't need to authenticate the request by default" do
|
85
90
|
@parameter_list.authenticate?.should be(false)
|
86
91
|
end
|
87
92
|
|
93
|
+
it "should know to authenticate the request when a token is available" do
|
94
|
+
Fleakr.stubs(:token).with().returns(stub(:value => 'toke'))
|
95
|
+
parameter_list = ParameterList.new
|
96
|
+
|
97
|
+
parameter_list.authenticate?.should be(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not authenticate the request if it's been specifically told not to" do
|
101
|
+
Fleakr.expects(:token).with().never
|
102
|
+
|
103
|
+
parameter_list = ParameterList.new(:authenticate? => false)
|
104
|
+
parameter_list.authenticate?.should be(false)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
88
108
|
it "should know to authenticate the request when asked" do
|
89
109
|
Fleakr.expects(:token).with().returns(stub(:value => 'toke'))
|
90
110
|
|
@@ -103,15 +123,10 @@ module Fleakr::Api
|
|
103
123
|
auth_param.include_in_signature?.should be(true)
|
104
124
|
end
|
105
125
|
|
106
|
-
it "should know that it needs to sign the request when it is to be authenticated" do
|
107
|
-
Fleakr.expects(:token).with().returns(stub(:value => 'toke'))
|
108
|
-
|
109
|
-
parameter_list = ParameterList.new(:authenticate? => true)
|
110
|
-
parameter_list.sign?.should be(true)
|
111
|
-
end
|
112
|
-
|
113
126
|
it "should include the signature in the list of parameters if the request is to be signed" do
|
114
|
-
parameter_list = ParameterList.new
|
127
|
+
parameter_list = ParameterList.new
|
128
|
+
|
129
|
+
parameter_list.stubs(:sign?).with().returns(true)
|
115
130
|
parameter_list.stubs(:signature).with().returns('sig')
|
116
131
|
|
117
132
|
signature_param = parameter_list[:api_sig]
|
@@ -122,24 +137,24 @@ module Fleakr::Api
|
|
122
137
|
end
|
123
138
|
|
124
139
|
context "with associated parameters" do
|
125
|
-
|
140
|
+
|
126
141
|
before do
|
127
142
|
@p1 = ValueParameter.new('a', 'b')
|
128
143
|
@p2 = ValueParameter.new('c', 'd')
|
129
|
-
|
144
|
+
|
130
145
|
@p1.stubs(:to_query).with().returns('q1')
|
131
146
|
@p1.stubs(:to_form).with().returns('f1')
|
132
147
|
|
133
148
|
@p2.stubs(:to_query).with().returns('q2')
|
134
149
|
@p2.stubs(:to_form).with().returns('f2')
|
135
|
-
|
150
|
+
|
136
151
|
@parameter_list.stubs(:list).with().returns('a' => @p1, 'c' => @p2)
|
137
152
|
end
|
138
|
-
|
153
|
+
|
139
154
|
it "should be able to generate a query representation of itself" do
|
140
155
|
@parameter_list.to_query.should == 'q1&q2'
|
141
156
|
end
|
142
|
-
|
157
|
+
|
143
158
|
it "should be able to represent a form representation of itself" do
|
144
159
|
@parameter_list.stubs(:boundary).returns('bound')
|
145
160
|
|