fleakr 0.4.1 → 0.4.2
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/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/README.rdoc
CHANGED
@@ -169,7 +169,33 @@ Searches can also be scoped to other entities in the system (namely Users and Gr
|
|
169
169
|
=> [#<Fleakr::Objects::Photo:0x18a6960 @server_id="41", @id="81370156",
|
170
170
|
@farm_id="1", @title="Clear and Serpent Danger", @secret="013091582a">]
|
171
171
|
|
172
|
-
===
|
172
|
+
=== Uploading Files
|
173
|
+
|
174
|
+
Before you can upload files, you need to be able to make authenticated calls to the Flickr
|
175
|
+
API. Skip to the next section (Authenticated Calls) for details on how to make this work.
|
176
|
+
|
177
|
+
Uploading single files is simple:
|
178
|
+
|
179
|
+
>> Fleakr.upload('/path/to/image.jpg')
|
180
|
+
=> [#<Fleakr::Objects::Photo:0x217fb54 @updated="1236133594", @server_id="3266", ...>]
|
181
|
+
|
182
|
+
Notice that the newly-uploaded image is returned. You can further inspect / modify this as
|
183
|
+
necessary. The real magic is in uploading multiple files - the upload method takes a file
|
184
|
+
glob:
|
185
|
+
|
186
|
+
>> Fleakr.upload('/path/to/images/*.jpg')
|
187
|
+
=> [#<Fleakr::Objects::Photo:0x217faa0 ...>,
|
188
|
+
#<Fleakr::Objects::Photo:0x212fb18 ...>,
|
189
|
+
#<Fleakr::Objects::Photo:0x20e09c8 ...>]
|
190
|
+
|
191
|
+
You can also set options on the file(s) that you're uploading:
|
192
|
+
|
193
|
+
>> Fleakr.upload('/path/to/party/images/*.jpg', :viewable_by => :everyone,
|
194
|
+
:title => 'Party Pics')
|
195
|
+
|
196
|
+
The full list of options can be found in the Fleakr::Objects::Photo documentation.
|
197
|
+
|
198
|
+
=== Authenticated Calls
|
173
199
|
|
174
200
|
While read-only access to the API gets you quite a bit of data, you'll need to generate an
|
175
201
|
authentication token if you want access to the more powerful features (like uploading your
|
@@ -197,7 +223,9 @@ confirm access to get your mini-token. Now you're ready to make authenticated re
|
|
197
223
|
Fleakr.token.value # => "34132412341235-12341234ef34"
|
198
224
|
|
199
225
|
Once you use the mini-token once, it is no longer available. To use the generated auth_token
|
200
|
-
for future requests, just set Fleakr.auth_token to the generated value.
|
226
|
+
for future requests, just set Fleakr.auth_token to the generated value. Similarly, if you have
|
227
|
+
an authenticated frob from Flickr (using authentication for desktop applications, for example)
|
228
|
+
you can also set <tt>Fleakr.frob</tt> to the frob value returned from the API.
|
201
229
|
|
202
230
|
=== What Went Wrong?
|
203
231
|
|
@@ -223,20 +251,19 @@ API requests.
|
|
223
251
|
|
224
252
|
=== 0.4.x
|
225
253
|
|
226
|
-
* Allow passing of parameters to file uploads to allow for access control / naming
|
227
254
|
* Implement remaining bits of person and photo-related API calls (read-only)
|
228
|
-
* Automatically sign all calls (if we have a secret), authenticate all calls (if we have a token)
|
229
255
|
|
230
256
|
=== 0.5.x
|
231
257
|
|
232
258
|
* Implement asynchronous file upload / replacement w/ ticket checking
|
233
|
-
* Provide a better searching interface
|
259
|
+
* Provide a better searching interface with ruby-like option syntax
|
234
260
|
|
235
261
|
=== Future
|
236
262
|
|
237
263
|
* Implement save-able search results (e.g. Fleakr.search('ponies').save_to('/path', :medium))
|
238
264
|
* Implement deeper associations for core elements (e.g. tags / etc..)
|
239
265
|
* Implement write methods for photos & photosets
|
266
|
+
* Implement flickr.places.* portion of API
|
240
267
|
|
241
268
|
== License
|
242
269
|
|
data/Rakefile
CHANGED
@@ -19,7 +19,7 @@ spec = Gem::Specification.new do |s|
|
|
19
19
|
s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
|
20
20
|
|
21
21
|
s.add_dependency('hpricot', '~> 0.6.0')
|
22
|
-
s.add_dependency('activesupport', '~> 2.
|
22
|
+
s.add_dependency('activesupport', '~> 2.0')
|
23
23
|
s.add_dependency('loggable', '~> 0.2.0')
|
24
24
|
end
|
25
25
|
|
data/lib/fleakr.rb
CHANGED
@@ -5,7 +5,15 @@ require 'uri'
|
|
5
5
|
require 'cgi'
|
6
6
|
require 'net/http'
|
7
7
|
require 'hpricot'
|
8
|
-
|
8
|
+
|
9
|
+
# Require only what we need from ActiveSupport
|
10
|
+
require 'active_support/core_ext/array'
|
11
|
+
require 'active_support/core_ext/module'
|
12
|
+
require 'active_support/core_ext/blank'
|
13
|
+
require 'active_support/core_ext/time'
|
14
|
+
require 'active_support/inflector'
|
15
|
+
require 'active_support/core_ext/string'
|
16
|
+
|
9
17
|
require 'md5'
|
10
18
|
require 'loggable'
|
11
19
|
|
@@ -75,7 +83,7 @@ module Fleakr
|
|
75
83
|
# Generic catch-all exception for any API errors
|
76
84
|
class ApiError < StandardError; end
|
77
85
|
|
78
|
-
mattr_accessor :api_key, :shared_secret, :mini_token, :auth_token
|
86
|
+
mattr_accessor :api_key, :shared_secret, :mini_token, :auth_token, :frob
|
79
87
|
|
80
88
|
# Find a user based on some unique user data. This method will try to find
|
81
89
|
# the user based on username and will fall back to email if that fails. Example:
|
@@ -113,8 +121,12 @@ module Fleakr
|
|
113
121
|
# Fleakr.upload('/path/to/my/mug.jpg')
|
114
122
|
# Fleakr.upload('/User/Pictures/Party/*.jpg')
|
115
123
|
#
|
116
|
-
|
117
|
-
|
124
|
+
# Additionally, options can be supplied as part of the upload that will apply to all files
|
125
|
+
# that are matched by the pattern passed to <tt>glob</tt>. For a full list, see
|
126
|
+
# Fleakr::Objects::Photo.
|
127
|
+
#
|
128
|
+
def self.upload(glob, options = {})
|
129
|
+
Dir[glob].map {|file| Fleakr::Objects::Photo.upload(file, options) }
|
118
130
|
end
|
119
131
|
|
120
132
|
# Get the authentication token needed for authenticated requests. Will either use
|
@@ -122,13 +134,29 @@ module Fleakr
|
|
122
134
|
#
|
123
135
|
def self.token
|
124
136
|
@token ||= begin
|
125
|
-
if
|
137
|
+
if Fleakr.auth_token
|
126
138
|
Fleakr::Objects::AuthenticationToken.from_auth_token(Fleakr.auth_token)
|
127
|
-
|
139
|
+
elsif Fleakr.frob
|
140
|
+
Fleakr::Objects::AuthenticationToken.from_frob(Fleakr.frob)
|
141
|
+
elsif Fleakr.mini_token
|
128
142
|
Fleakr::Objects::AuthenticationToken.from_mini_token(Fleakr.mini_token)
|
129
143
|
end
|
130
144
|
end
|
131
145
|
end
|
146
|
+
|
147
|
+
# Reset the cached token whenever setting a new value for the mini_token, auth_token, or frob
|
148
|
+
#
|
149
|
+
[:mini_token, :auth_token, :frob].each do |attribute|
|
150
|
+
class_eval <<-ACCESSOR
|
151
|
+
def self.#{attribute}=(#{attribute})
|
152
|
+
reset_token
|
153
|
+
@@#{attribute} = #{attribute}
|
154
|
+
end
|
155
|
+
ACCESSOR
|
156
|
+
end
|
132
157
|
|
158
|
+
def self.reset_token # :nodoc: #
|
159
|
+
@token = nil
|
160
|
+
end
|
133
161
|
|
134
162
|
end
|
data/lib/fleakr/api.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
module Fleakr
|
2
2
|
module Api # :nodoc:
|
3
3
|
|
4
|
+
# = MethodRequest
|
5
|
+
#
|
6
|
+
# Handles all API requests that are non-upload related. For upload requests see the
|
7
|
+
# UploadRequest class.
|
8
|
+
#
|
4
9
|
class MethodRequest
|
5
10
|
attr_reader :parameters, :method
|
6
11
|
|
7
12
|
# Makes a request to the Flickr API and returns a valid Response object. If
|
8
13
|
# there are errors on the response it will raise an ApiError exception. See
|
9
|
-
# #
|
14
|
+
# MethodRequest#new for details about the additional parameters
|
10
15
|
#
|
11
16
|
def self.with_response!(method, additional_parameters = {})
|
12
17
|
request = self.new(method, additional_parameters)
|
@@ -25,9 +30,9 @@ module Fleakr
|
|
25
30
|
# see (#Fleakr.api_key=)
|
26
31
|
#
|
27
32
|
# The <tt>additional_parameters</tt> is a list of parameters to pass directly to
|
28
|
-
# the Flickr API call.
|
29
|
-
#
|
30
|
-
#
|
33
|
+
# the Flickr API call. The exception to this is the <tt>:authenticate?</tt> option
|
34
|
+
# that will force the call to not be authenticated if it is set to false (The default
|
35
|
+
# behavior is to authenticate all calls when we have a token).
|
31
36
|
#
|
32
37
|
def initialize(method, additional_parameters = {})
|
33
38
|
@parameters = ParameterList.new(additional_parameters)
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Api # :nodoc:
|
3
|
+
|
4
|
+
# = Option
|
5
|
+
#
|
6
|
+
# Top-level class for creating specific option instances based on type
|
7
|
+
#
|
8
|
+
class Option
|
9
|
+
|
10
|
+
MAPPING = {
|
11
|
+
:tags => 'TagOption',
|
12
|
+
:viewable_by => 'ViewOption',
|
13
|
+
:level => 'LevelOption',
|
14
|
+
:type => 'TypeOption',
|
15
|
+
:hide? => 'HiddenOption'
|
16
|
+
}
|
17
|
+
|
18
|
+
# Initialize a new option for the specified type and value
|
19
|
+
#
|
20
|
+
def self.for(type, value)
|
21
|
+
class_for(type).new(type, value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.class_for(type) # :nodoc:
|
25
|
+
class_name = MAPPING[type] || 'SimpleOption'
|
26
|
+
"Fleakr::Api::#{class_name}".constantize
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# = SimpleOption
|
32
|
+
#
|
33
|
+
# Simple name / value option pair
|
34
|
+
#
|
35
|
+
class SimpleOption
|
36
|
+
|
37
|
+
attr_reader :type, :value
|
38
|
+
|
39
|
+
# Create an option of the specified type and value
|
40
|
+
#
|
41
|
+
def initialize(type, value)
|
42
|
+
@type = type
|
43
|
+
@value = value
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generate hash representation of this option
|
47
|
+
#
|
48
|
+
def to_hash
|
49
|
+
{type => value}
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# = TagOption
|
55
|
+
#
|
56
|
+
# Represents values for tags
|
57
|
+
#
|
58
|
+
class TagOption < SimpleOption
|
59
|
+
|
60
|
+
# Tag with specified values. Value passed will be converted to an array if it isn't
|
61
|
+
# already
|
62
|
+
#
|
63
|
+
def initialize(type, value)
|
64
|
+
super type, value
|
65
|
+
@value = Array(self.value)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Hash representation of tag values (separated by spaces). Handles multi-word tags
|
69
|
+
# by enclosing each tag in double quotes.
|
70
|
+
#
|
71
|
+
def to_hash
|
72
|
+
tags = value.map {|tag| "\"#{tag}\"" }
|
73
|
+
{type => tags.join(' ')}
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# = ViewOption
|
79
|
+
#
|
80
|
+
# Specify who is able to view the photo.
|
81
|
+
#
|
82
|
+
class ViewOption < SimpleOption
|
83
|
+
|
84
|
+
# Specify who this is viewable by (e.g. everyone / friends / family).
|
85
|
+
#
|
86
|
+
def initialize(type, value)
|
87
|
+
super type, Array(value)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Is this publicly viewable? (i.e. :everyone)
|
91
|
+
#
|
92
|
+
def public?
|
93
|
+
value == [:everyone]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Is this viewable by friends? (i.e. :friends)
|
97
|
+
#
|
98
|
+
def friends?
|
99
|
+
value.include?(:friends)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Is this viewable by family? (i.e. :family)
|
103
|
+
#
|
104
|
+
def family?
|
105
|
+
value.include?(:family)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Hash representation of photo permissions
|
109
|
+
#
|
110
|
+
def to_hash
|
111
|
+
{:is_public => public?.to_i, :is_friend => friends?.to_i, :is_family => family?.to_i}
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# = LevelOption
|
117
|
+
#
|
118
|
+
# Specify the "safety level" of this photo (e.g. safe / moderate / restricted)
|
119
|
+
#
|
120
|
+
class LevelOption < SimpleOption
|
121
|
+
|
122
|
+
def value # :nodoc:
|
123
|
+
case @value
|
124
|
+
when :safe: 1
|
125
|
+
when :moderate: 2
|
126
|
+
when :restricted: 3
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Hash representation of the safety_level for this photo
|
131
|
+
#
|
132
|
+
def to_hash
|
133
|
+
{:safety_level => value}
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
# = TypeOption
|
139
|
+
#
|
140
|
+
# Specify the type of this photo (e.g. photo / screenshot / other)
|
141
|
+
#
|
142
|
+
class TypeOption < SimpleOption
|
143
|
+
|
144
|
+
def value # :nodoc:
|
145
|
+
case @value
|
146
|
+
when :photo: 1
|
147
|
+
when :screenshot: 2
|
148
|
+
when :other: 3
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Hash representation of this type
|
153
|
+
#
|
154
|
+
def to_hash
|
155
|
+
{:content_type => value}
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
# = HiddenOption
|
161
|
+
#
|
162
|
+
# Specify whether this photo should be hidden from search
|
163
|
+
#
|
164
|
+
class HiddenOption < SimpleOption
|
165
|
+
|
166
|
+
# Hash representation of whether to hide this photo
|
167
|
+
#
|
168
|
+
def to_hash
|
169
|
+
{:hidden => (value ? 2 : 1)}
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
@@ -10,8 +10,8 @@ module Fleakr
|
|
10
10
|
class ParameterList
|
11
11
|
|
12
12
|
# Create a new parameter list with optional parameters:
|
13
|
-
# [:
|
14
|
-
#
|
13
|
+
# [:authenticate?] Request will automatically be authenticated if Fleakr.token is available
|
14
|
+
# set this to false to force it not to authenticate
|
15
15
|
#
|
16
16
|
# Any additional name / value pairs will be created as individual
|
17
17
|
# ValueParameters as part of the list. Example:
|
@@ -22,7 +22,8 @@ module Fleakr
|
|
22
22
|
# => #<Fleakr::Api::ValueParameter:0x1656da4 @include_in_signature=true, @name="foo", @value="bar">
|
23
23
|
#
|
24
24
|
def initialize(options = {})
|
25
|
-
|
25
|
+
# TODO: need to find a way to move the unexpected behavior in Fleakr.token elsewhere
|
26
|
+
@api_options = options.extract!(:authenticate?)
|
26
27
|
|
27
28
|
@list = Hash.new
|
28
29
|
|
@@ -41,13 +42,13 @@ module Fleakr
|
|
41
42
|
# Should this parameter list be signed?
|
42
43
|
#
|
43
44
|
def sign?
|
44
|
-
|
45
|
+
!Fleakr.shared_secret.blank?
|
45
46
|
end
|
46
47
|
|
47
48
|
# Should we send the auth_token with the request?
|
48
49
|
#
|
49
50
|
def authenticate?
|
50
|
-
|
51
|
+
@api_options.has_key?(:authenticate?) ? @api_options[:authenticate?] : !Fleakr.token.blank?
|
51
52
|
end
|
52
53
|
|
53
54
|
# Access an individual parameter by key (symbol or string)
|
@@ -64,7 +65,7 @@ module Fleakr
|
|
64
65
|
# list - e.g. <tt>foo=bar&blee=baz</tt>
|
65
66
|
#
|
66
67
|
def to_query
|
67
|
-
list.values.map
|
68
|
+
list.values.map {|element| element.to_query }.join('&')
|
68
69
|
end
|
69
70
|
|
70
71
|
# Generate the form representation of this parameter list including the
|
@@ -19,8 +19,8 @@ module Fleakr
|
|
19
19
|
# a Fleakr::ApiError with the reason for the error. See UploadRequest#new for more
|
20
20
|
# details.
|
21
21
|
#
|
22
|
-
def self.with_response!(filename, options = {})
|
23
|
-
request = self.new(filename, options)
|
22
|
+
def self.with_response!(filename, type = :create, options = {})
|
23
|
+
request = self.new(filename, type, options)
|
24
24
|
response = request.send
|
25
25
|
|
26
26
|
raise(Fleakr::ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
|
@@ -28,21 +28,27 @@ module Fleakr
|
|
28
28
|
response
|
29
29
|
end
|
30
30
|
|
31
|
-
# Create a new UploadRequest with the specified filename and options
|
31
|
+
# Create a new UploadRequest with the specified filename, type, and options. Type
|
32
|
+
# is one of <tt>:create</tt> or <tt>:update</tt> to specify whether we are saving a new
|
33
|
+
# image or replacing an existing one.
|
32
34
|
#
|
33
|
-
#
|
34
|
-
# photos or replacing existing ones
|
35
|
+
# For a list of available options, see the documentation in Fleakr::Objects::Photo
|
35
36
|
#
|
36
|
-
def initialize(filename, options = {})
|
37
|
-
|
38
|
-
options
|
37
|
+
def initialize(filename, type = :create, options = {})
|
38
|
+
@type = type
|
39
|
+
@options = options
|
39
40
|
|
40
|
-
@
|
41
|
-
|
42
|
-
@parameters = ParameterList.new(options)
|
41
|
+
@parameters = ParameterList.new(upload_options)
|
43
42
|
@parameters << FileParameter.new('photo', filename)
|
44
43
|
end
|
45
44
|
|
45
|
+
# A list of upload options for this upload request (see Fleakr::Api::Option)
|
46
|
+
#
|
47
|
+
def upload_options
|
48
|
+
option_list = @options.map {|key, value| Option.for(key, value) }
|
49
|
+
option_list.inject({}) {|hash, option| hash.merge(option.to_hash)}
|
50
|
+
end
|
51
|
+
|
46
52
|
def headers # :nodoc:
|
47
53
|
{'Content-Type' => "multipart/form-data; boundary=#{self.parameters.boundary}"}
|
48
54
|
end
|