fleakr 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.rdoc +114 -19
  2. data/Rakefile +1 -1
  3. data/lib/fleakr/api/file_parameter.rb +47 -0
  4. data/lib/fleakr/api/method_request.rb +57 -0
  5. data/lib/fleakr/api/parameter.rb +35 -0
  6. data/lib/fleakr/api/parameter_list.rb +96 -0
  7. data/lib/fleakr/api/response.rb +2 -2
  8. data/lib/fleakr/api/upload_request.rb +64 -0
  9. data/lib/fleakr/api/value_parameter.rb +36 -0
  10. data/lib/fleakr/api.rb +7 -0
  11. data/lib/fleakr/core_ext/hash.rb +22 -0
  12. data/lib/fleakr/core_ext.rb +1 -0
  13. data/lib/fleakr/objects/authentication_token.rb +43 -0
  14. data/lib/fleakr/objects/contact.rb +5 -5
  15. data/lib/fleakr/objects/error.rb +2 -2
  16. data/lib/fleakr/objects/group.rb +2 -2
  17. data/lib/fleakr/objects/image.rb +7 -7
  18. data/lib/fleakr/objects/photo.rb +69 -5
  19. data/lib/fleakr/objects/search.rb +3 -6
  20. data/lib/fleakr/objects/set.rb +11 -5
  21. data/lib/fleakr/objects/user.rb +14 -26
  22. data/lib/fleakr/objects.rb +9 -0
  23. data/lib/fleakr/support/attribute.rb +30 -12
  24. data/lib/fleakr/support/object.rb +20 -4
  25. data/lib/fleakr/support.rb +2 -0
  26. data/lib/fleakr/version.rb +1 -1
  27. data/lib/fleakr.rb +66 -7
  28. data/test/fixtures/auth.checkToken.xml +8 -0
  29. data/test/fixtures/auth.getFullToken.xml +8 -0
  30. data/test/fixtures/people.getInfo.xml +1 -1
  31. data/test/fixtures/photos.getInfo.xml +20 -0
  32. data/test/test_helper.rb +18 -3
  33. data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
  34. data/test/unit/fleakr/api/method_request_test.rb +103 -0
  35. data/test/unit/fleakr/api/parameter_list_test.rb +161 -0
  36. data/test/unit/fleakr/api/parameter_test.rb +34 -0
  37. data/test/unit/fleakr/api/upload_request_test.rb +133 -0
  38. data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
  39. data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
  40. data/test/unit/fleakr/objects/authentication_token_test.rb +47 -0
  41. data/test/unit/fleakr/objects/image_test.rb +10 -5
  42. data/test/unit/fleakr/objects/photo_test.rb +96 -36
  43. data/test/unit/fleakr/objects/search_test.rb +1 -1
  44. data/test/unit/fleakr/objects/set_test.rb +12 -1
  45. data/test/unit/fleakr/objects/user_test.rb +2 -16
  46. data/test/unit/fleakr/support/attribute_test.rb +82 -24
  47. data/test/unit/fleakr/support/object_test.rb +26 -3
  48. data/test/unit/fleakr_test.rb +65 -6
  49. metadata +28 -5
  50. data/lib/fleakr/api/request.rb +0 -58
  51. data/test/unit/fleakr/api/request_test.rb +0 -93
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == Description
4
4
 
5
- A teeny tiny gem to interface with Flickr photostreams
5
+ A small, yet powerful, gem to interface with Flickr photostreams
6
6
 
7
7
  == Installation
8
8
 
@@ -22,16 +22,24 @@ Or ...
22
22
 
23
23
  == Usage
24
24
 
25
- Before doing anything, require the library:
25
+ To get started, you'll need to grab an API key from Flickr to at least perform any of
26
+ the non-authenticated, read-only calls. Head on over to the Flickr site to grab one, I'll
27
+ be here when you get back: http://www.flickr.com/services/api/misc.api_keys.html
26
28
 
27
- >> require 'rubygems'
28
- >> require 'fleakr'
29
+ Now that you have your key, you can get things rolling with irb and the fleakr gem:
29
30
 
31
+ $ irb -r rubygems
32
+ >> require 'fleakr'
33
+
30
34
  Then, set your API key (only need to do this once per session):
31
35
 
32
36
  >> Fleakr.api_key = '<your api key here>'
33
-
34
- Find a user by username:
37
+
38
+ === A Brief Tour
39
+
40
+ With just an API key, you have the ability to retrieve a substantial amount of data
41
+ about users, their photosets, photos, contacts, and groups. Let's start by finding a
42
+ user by his username:
35
43
 
36
44
  >> user = Fleakr.user('the decapitator')
37
45
  => #<Fleakr::Objects::User:0x692648 @username="the decapitator", @id="21775151@N06">
@@ -47,13 +55,18 @@ Once you have a user, you can find his associated sets:
47
55
  => [#<Fleakr::Objects::Set:0x671358 @title="The Decapitator", @description="">,
48
56
  #<Fleakr::Objects::Set:0x66d898 @title="londonpaper hijack", ...
49
57
 
58
+ His individual photos:
59
+
60
+ >> user.photos.first
61
+ => #<Fleakr::Objects::Photo:0x161b024 @title="\"Be Fabulous\"" ... >
62
+
50
63
  Or contacts:
51
64
 
52
65
  >> user.contacts.first
53
66
  => #<Fleakr::Objects::User:0x19039bc @username=".schill",
54
67
  @id="12289718@N00", @icon_farm="1", @icon_server="4">
55
68
 
56
- Or groups if you would like:
69
+ Or his groups if you would like:
57
70
 
58
71
  >> user.groups
59
72
  => [#<Fleakr::Objects::Group:0x11f2330 ...,
@@ -77,20 +90,59 @@ When accessing a set, you can also grab all the photos that are in that set:
77
90
  >> user.sets.first.photos.first.title
78
91
  => "Untitled1"
79
92
 
93
+ === Photos
94
+
95
+ Each photo object contains metadata about a collection of images, each representing different
96
+ sizes. Once we have a single photo:
97
+
98
+ >> photo = user.photos.first
99
+ => #<Fleakr::Objects::Photo:0x161b024 @title="\"Be Fabulous\"" ... >
100
+
101
+ We can get information about one of the sizes:
102
+
103
+ >> photo.small
104
+ => #<Fleakr::Objects::Image:0x1768f1c @height="172", @size="Small", @width="240",
105
+ @url="http://farm4.static.flickr.com/3250/2924549350_cbc1804258_m.jpg",
106
+ @page="http://www.flickr.com/photos/the_decapitator/2924549350/sizes/s/">
107
+
108
+ Grab the URL for the image itself:
109
+
110
+ >> photo.small.url
111
+ => "http://farm4.static.flickr.com/3250/2924549350_cbc1804258_m.jpg"
112
+
113
+ Or grab the URL for its page on the Flickr site:
114
+
115
+ >> photo.small.page
116
+ => "http://www.flickr.com/photos/the_decapitator/2924549350/sizes/s/"
117
+
118
+ Other sizes are available (:square, :thumbnail, :small, :medium, :large, :original) and
119
+ are accessed in the same way:
120
+
121
+ >> photo.original.url
122
+ => "http://farm4.static.flickr.com/3250/2924549350_1cf67c2d47_o.jpg"
123
+
124
+ === Saving Images
125
+
80
126
  If a photo interests you, save it down to a directory of your choosing:
81
127
 
82
- >> user.sets.first.photos.first.small.save_to('/tmp')
83
- => #<File:/tmp/2117922283_715587b2cb_m.jpg (closed)>
128
+ >> photo.original.save_to('/tmp')
129
+ => #<File:/tmp/2924549350_1cf67c2d47_o.jpg (closed)>
84
130
 
85
- If you can't decide on a photo and would rather just save the whole set, specify the target directory
86
- and the size of the images you're interested in:
131
+ Similarly, you can save down entire sets. Just specify the target directory and the size
132
+ of the images you're interested in:
87
133
 
88
134
  >> user.sets.first.save_to('/tmp', :square)
89
135
  => [#<Fleakr::Objects::Photo:0x1187a1c @secret="715587b2cb" ...
136
+
137
+ This creates a subdirectory within the target directory based on the set's name and preserves
138
+ the original order of the photos:
139
+
90
140
  >> Dir["/tmp/#{user.sets.first.title}/*.jpg"].map
91
- => ["/tmp/The Decapitator/2117919621_8b2d601bff_s.jpg",
92
- "/tmp/The Decapitator/2117921045_5fb15eff90_s.jpg",
93
- "/tmp/The Decapitator/2117922283_715587b2cb_s.jpg", ...
141
+ => ["/tmp/The Decapitator/01_2117922283_715587b2cb_s.jpg",
142
+ "/tmp/The Decapitator/02_2125604584_9c09348fd6_s.jpg",
143
+ "/tmp/The Decapitator/03_2118696542_8af5763bde_s.jpg", ... ]
144
+
145
+ === Searching
94
146
 
95
147
  If you would prefer to just search photos, you can do that with search text:
96
148
 
@@ -116,13 +168,56 @@ Searches can also be scoped to other entities in the system (namely Users and Gr
116
168
  >> user.search('serpent')
117
169
  => [#<Fleakr::Objects::Photo:0x18a6960 @server_id="41", @id="81370156",
118
170
  @farm_id="1", @title="Clear and Serpent Danger", @secret="013091582a">]
119
-
120
- == TODO
121
171
 
122
- * Implement remaining bits of person, photoset, and photo-releated APIs
172
+ === Authenticated Calls & Uploads
173
+
174
+ While read-only access to the API gets you quite a bit of data, you'll need to generate an
175
+ authentication token if you want access to the more powerful features (like uploading your
176
+ own photos).
177
+
178
+ Assuming you've already applied for a key, go back and make sure you have the right settings
179
+ to get your auth token. Click on the 'Edit key details' link and ensure that:
180
+
181
+ 1. Your application description and notes are up-to-date
182
+ 1. The value for 'Authentication Type' is set to 'Mobile Application'
183
+ 1. The value for 'Mobile Permissions' is set to either 'write' or 'delete'
184
+
185
+ Once this is set, you'll see your Authentication URL on the key details page (it will look
186
+ something like http://www.flickr.com/auth-534525246245). Paste this URL into your browser and
187
+ confirm access to get your mini-token. Now you're ready to make authenticated requests:
188
+
189
+ require 'rubygems'
190
+ require 'fleakr'
191
+
192
+ Fleakr.api_key = 'ABC123'
193
+ Fleakr.shared_secret = 'sekrit' # Available with your key details on the Flickr site
194
+ Fleakr.mini_token = '362-133-214'
195
+
196
+ Fleakr.upload('/path/to/my/photo.jpg')
197
+ Fleakr.token.value # => "34132412341235-12341234ef34"
198
+
199
+ 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.
201
+
202
+ == Roadmap / TODO
203
+
204
+ === 0.4.x
205
+
206
+ * Allow passing of parameters to file uploads to allow for access control / naming
207
+ * Implement remaining bits of person and photo-related API calls (read-only)
208
+ * Automatically sign all calls (if we have a secret), authenticate all calls (if we have a token)
209
+
210
+ === 0.5.x
211
+
212
+ * Implement asynchronous file upload / replacement w/ ticket checking
123
213
  * Provide a better searching interface
124
- * Lazily load attributes for objects that need to be accessed via secondary API call
125
-
214
+
215
+ === Future
216
+
217
+ * Implement save-able search results (e.g. Fleakr.search('ponies').save_to('/path', :medium))
218
+ * Implement deeper associations for core elements (e.g. tags / etc..)
219
+ * Implement write methods for photos & photosets
220
+
126
221
  == License
127
222
 
128
223
  Copyright (c) 2008 Patrick Reagan (reaganpr@gmail.com)
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ spec = Gem::Specification.new do |s|
12
12
  s.has_rdoc = true
13
13
  s.extra_rdoc_files = %w(README.rdoc)
14
14
  s.rdoc_options = %w(--main README.rdoc)
15
- s.summary = "A teeny tiny gem to interface with Flickr photostreams"
15
+ s.summary = "A small, yet powerful, gem to interface with Flickr photostreams"
16
16
  s.author = 'Patrick Reagan'
17
17
  s.email = 'reaganpr@gmail.com'
18
18
  s.homepage = 'http://sneaq.net'
@@ -0,0 +1,47 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ # = FileParameter
5
+ #
6
+ # Parameter class to encapsulate file data sent to the Flickr upload API
7
+ #
8
+ class FileParameter < Parameter
9
+
10
+ MIME_TYPES = {
11
+ '.jpg' => 'image/jpeg',
12
+ '.png' => 'image/png',
13
+ '.gif' => 'image/gif'
14
+ }
15
+
16
+ # Create a parameter with name and specified filename
17
+ #
18
+ def initialize(name, filename)
19
+ @filename = filename
20
+ super(name, false)
21
+ end
22
+
23
+ # Discover MIME type by file extension using MIME_TYPES constant
24
+ #
25
+ def mime_type
26
+ MIME_TYPES[File.extname(@filename)]
27
+ end
28
+
29
+ # File data (from @filename) to pass to the Flickr API
30
+ #
31
+ def value
32
+ @value ||= File.read(@filename)
33
+ end
34
+
35
+ # Generate a form representation of this file for upload (as multipart/form-data)
36
+ #
37
+ def to_form
38
+ "Content-Disposition: form-data; name=\"#{self.name}\"; filename=\"#{@filename}\"\r\n" +
39
+ "Content-Type: #{self.mime_type}\r\n" +
40
+ "\r\n" +
41
+ "#{self.value}\r\n"
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,57 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ class MethodRequest
5
+ attr_reader :parameters, :method
6
+
7
+ # Makes a request to the Flickr API and returns a valid Response object. If
8
+ # there are errors on the response it will raise an ApiError exception. See
9
+ # #Fleakr::Api::MethodRequest.new for details about the additional parameters
10
+ #
11
+ def self.with_response!(method, additional_parameters = {})
12
+ request = self.new(method, additional_parameters)
13
+ response = request.send
14
+
15
+ raise(Fleakr::ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
16
+
17
+ response
18
+ end
19
+
20
+ # Create a new request for the specified API method and pass along any additional
21
+ # parameters. The Flickr API uses namespacing for its methods - this is optional
22
+ # when calling this method.
23
+ #
24
+ # This must be called after initializing the library with the required API key
25
+ # see (#Fleakr.api_key=)
26
+ #
27
+ # The <tt>additional_parameters</tt> is a list of parameters to pass directly to
28
+ # the Flickr API call. Exceptions to this are the <tt>:sign?</tt> and
29
+ # <tt>:authenticate?</tt> options that determine if the call should be signed or
30
+ # authenticated.
31
+ #
32
+ def initialize(method, additional_parameters = {})
33
+ @parameters = ParameterList.new(additional_parameters)
34
+
35
+ self.method = method
36
+ end
37
+
38
+ def method=(method) # :nodoc:
39
+ @method = method.sub(/^(flickr\.)?/, 'flickr.')
40
+ @parameters << ValueParameter.new('method', @method)
41
+ end
42
+
43
+ def send # :nodoc:
44
+ Response.new(Net::HTTP.get(endpoint_uri))
45
+ end
46
+
47
+ private
48
+ def endpoint_uri
49
+ uri = URI.parse('http://api.flickr.com/services/rest/')
50
+ uri.query = self.parameters.to_query
51
+ uri
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ # = Parameter
5
+ #
6
+ # Base class for other parameters that get passed to the Flickr API - see
7
+ # #FileParameter and #ValueParameter for examples
8
+ #
9
+ class Parameter
10
+
11
+ attr_reader :name
12
+
13
+ # A new named parameter (never used directly)
14
+ #
15
+ def initialize(name, include_in_signature = true)
16
+ @name = name
17
+ @include_in_signature = include_in_signature
18
+ end
19
+
20
+ # Should this parameter be used when generating the signature?
21
+ #
22
+ def include_in_signature?
23
+ (@include_in_signature == true) ? true : false
24
+ end
25
+
26
+ # Used for sorting when generating a signature
27
+ #
28
+ def <=>(other)
29
+ self.name <=> other.name
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,96 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ # = ParameterList
5
+ #
6
+ # Represents a list of parameters that get passed as part of a
7
+ # MethodRequest or UploadRequest. These can be transformed as necessary
8
+ # into query strings (using #to_query) or form data (using #to_form)
9
+ #
10
+ class ParameterList
11
+
12
+ # Create a new parameter list with optional parameters:
13
+ # [:sign?] Will these parameters be used to sign the request?
14
+ # [:authenticate?] Will the request need to be authenticated?
15
+ #
16
+ # Any additional name / value pairs will be created as individual
17
+ # ValueParameters as part of the list. Example:
18
+ #
19
+ # >> list = Fleakr::Api::ParameterList.new(:foo => 'bar')
20
+ # => #<Fleakr::Api::ParameterList:0x1656e6c @list=... >
21
+ # >> list[:foo]
22
+ # => #<Fleakr::Api::ValueParameter:0x1656da4 @include_in_signature=true, @name="foo", @value="bar">
23
+ #
24
+ def initialize(options = {})
25
+ @api_options = options.extract!(:sign?, :authenticate?)
26
+
27
+ @list = Hash.new
28
+
29
+ options.each {|k,v| self << ValueParameter.new(k.to_s, v) }
30
+
31
+ self << ValueParameter.new('api_key', Fleakr.api_key)
32
+ self << ValueParameter.new('auth_token', Fleakr.token.value) if authenticate?
33
+ end
34
+
35
+ # Add a new parameter (ValueParameter / FileParameter) to the list
36
+ #
37
+ def <<(parameter)
38
+ @list.merge!(parameter.name => parameter)
39
+ end
40
+
41
+ # Should this parameter list be signed?
42
+ #
43
+ def sign?
44
+ (@api_options[:sign?] == true || authenticate?) ? true : false
45
+ end
46
+
47
+ # Should we send the auth_token with the request?
48
+ #
49
+ def authenticate?
50
+ (@api_options[:authenticate?] == true) ? true : false
51
+ end
52
+
53
+ # Access an individual parameter by key (symbol or string)
54
+ #
55
+ def [](key)
56
+ list[key.to_s]
57
+ end
58
+
59
+ def boundary # :nodoc:
60
+ @boundary ||= Digest::MD5.hexdigest(rand.to_s)
61
+ end
62
+
63
+ # Generate the query string representation of this parameter
64
+ # list - e.g. <tt>foo=bar&blee=baz</tt>
65
+ #
66
+ def to_query
67
+ list.values.map(&:to_query).join('&')
68
+ end
69
+
70
+ # Generate the form representation of this parameter list including the
71
+ # boundary
72
+ #
73
+ def to_form
74
+ form = list.values.map {|p| "--#{self.boundary}\r\n#{p.to_form}" }.join
75
+ form << "--#{self.boundary}--"
76
+
77
+ form
78
+ end
79
+
80
+ def signature # :nodoc:
81
+ parameters_to_sign = @list.values.reject {|p| !p.include_in_signature? }
82
+ signature_text = parameters_to_sign.sort.map {|p| "#{p.name}#{p.value}" }.join
83
+
84
+ Digest::MD5.hexdigest("#{Fleakr.shared_secret}#{signature_text}")
85
+ end
86
+
87
+ private
88
+ def list
89
+ list = @list
90
+ list.merge!('api_sig' => ValueParameter.new('api_sig', signature, false)) if self.sign?
91
+
92
+ list
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,11 +1,11 @@
1
1
  module Fleakr
2
- module Api
2
+ module Api # :nodoc:
3
3
 
4
4
  # = Response
5
5
  #
6
6
  # Response objects contain Hpricot documents that are traversed and parsed by
7
7
  # the model objects. This class is never called directly but is instantiated
8
- # during the request cycle (see: Fleakr::Api::Request.with_response!)
8
+ # during the request cycle (see: Fleakr::Api::MethodRequest.with_response!)
9
9
  #
10
10
  class Response
11
11
 
@@ -0,0 +1,64 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ # = UploadRequest
5
+ #
6
+ # This implements the upload functionality of the Flickr API which is needed
7
+ # to create new photos and replace the photo content of existing photos
8
+ #
9
+ class UploadRequest
10
+
11
+ ENDPOINT_URIS = {
12
+ :create => 'http://api.flickr.com/services/upload/',
13
+ :update => 'http://api.flickr.com/services/replace/'
14
+ }
15
+
16
+ attr_reader :parameters, :type
17
+
18
+ # Send a request and return a Response object. If an API error occurs, this raises
19
+ # a Fleakr::ApiError with the reason for the error. See UploadRequest#new for more
20
+ # details.
21
+ #
22
+ def self.with_response!(filename, options = {})
23
+ request = self.new(filename, options)
24
+ response = request.send
25
+
26
+ raise(Fleakr::ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
27
+
28
+ response
29
+ end
30
+
31
+ # Create a new UploadRequest with the specified filename and options:
32
+ #
33
+ # [:type] Valid values are :create and :update and are used when uploading new
34
+ # photos or replacing existing ones
35
+ #
36
+ def initialize(filename, options = {})
37
+ type_options = options.extract!(:type)
38
+ options.merge!(:authenticate? => true)
39
+
40
+ @type = type_options[:type] || :create
41
+
42
+ @parameters = ParameterList.new(options)
43
+ @parameters << FileParameter.new('photo', filename)
44
+ end
45
+
46
+ def headers # :nodoc:
47
+ {'Content-Type' => "multipart/form-data; boundary=#{self.parameters.boundary}"}
48
+ end
49
+
50
+ def send # :nodoc:
51
+ response = Net::HTTP.start(endpoint_uri.host, endpoint_uri.port) do |http|
52
+ http.post(endpoint_uri.path, self.parameters.to_form, self.headers)
53
+ end
54
+ Response.new(response.body)
55
+ end
56
+
57
+ private
58
+ def endpoint_uri
59
+ @endpoint_uri ||= URI.parse(ENDPOINT_URIS[self.type])
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ module Fleakr
2
+ module Api # :nodoc:
3
+
4
+ # = ValueParameter
5
+ #
6
+ # A simple name / value parameter for use in API calls
7
+ #
8
+ class ValueParameter < Parameter
9
+
10
+ attr_reader :value
11
+
12
+ # Create a new parameter with the specified name / value pair.
13
+ #
14
+ def initialize(name, value, include_in_signature = true)
15
+ @value = value
16
+ super(name, include_in_signature)
17
+ end
18
+
19
+ # Generate the query string representation of this parameter.
20
+ #
21
+ def to_query
22
+ "#{self.name}=#{CGI.escape(self.value.to_s)}"
23
+ end
24
+
25
+ # Generate the form representation of this parameter.
26
+ #
27
+ def to_form
28
+ "Content-Disposition: form-data; name=\"#{self.name}\"\r\n" +
29
+ "\r\n" +
30
+ "#{self.value}\r\n"
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
data/lib/fleakr/api.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "fleakr/api/response"
2
+ require "fleakr/api/method_request"
3
+ require "fleakr/api/upload_request"
4
+ require "fleakr/api/parameter_list"
5
+ require "fleakr/api/parameter"
6
+ require "fleakr/api/value_parameter"
7
+ require "fleakr/api/file_parameter"
@@ -0,0 +1,22 @@
1
+ class Hash
2
+
3
+ # Extract the matching keys from the source hash and return
4
+ # a new hash with those keys:
5
+ #
6
+ # >> h = {:a => 'b', :c => 'd'}
7
+ # => {:a=>"b", :c=>"d"}
8
+ # >> h.extract!(:a)
9
+ # => {:a=>"b"}
10
+ # >> h
11
+ # => {:c=>"d"}
12
+ #
13
+ def extract!(*keys)
14
+ value = {}
15
+
16
+ keys.each {|k| value.merge!({k => self[k]}) if self.has_key?(k) }
17
+ keys.each {|k| delete(k) }
18
+
19
+ value
20
+ end
21
+
22
+ end
@@ -0,0 +1 @@
1
+ require 'fleakr/core_ext/hash'
@@ -0,0 +1,43 @@
1
+ module Fleakr
2
+ module Objects # :nodoc:
3
+
4
+ # = AuthenticationToken
5
+ #
6
+ # This class represents an authentication token used for API calls that
7
+ # require authentication before they can be used
8
+ #
9
+ # == Attributes
10
+ #
11
+ # [value] The token value that is used in subsequent API calls
12
+ # [permissions] The permissions granted to this application (read / write / delete)
13
+ #
14
+ class AuthenticationToken
15
+
16
+ include Fleakr::Support::Object
17
+
18
+ flickr_attribute :value, :from => 'auth/token'
19
+ flickr_attribute :permissions, :from => 'auth/perms'
20
+
21
+ # Retrieve a full authentication token from the supplied mini-token (e.g. 123-456-789)
22
+ #
23
+ def self.from_mini_token(token)
24
+ parameters = {:mini_token => token, :sign? => true}
25
+ response = Fleakr::Api::MethodRequest.with_response!('auth.getFullToken', parameters)
26
+
27
+ self.new(response.body)
28
+ end
29
+
30
+ # Retrieve a full authentication token from the supplied auth_token string
31
+ # (e.g. 45-76598454353455)
32
+ #
33
+ def self.from_auth_token(token)
34
+ parameters = {:auth_token => token, :sign? => true}
35
+ response = Fleakr::Api::MethodRequest.with_response!('auth.checkToken', parameters)
36
+
37
+ self.new(response.body)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
@@ -4,15 +4,15 @@ module Fleakr
4
4
 
5
5
  include Fleakr::Support::Object
6
6
 
7
- flickr_attribute :id, :attribute => 'nsid'
8
- flickr_attribute :username, :attribute => 'username'
9
- flickr_attribute :icon_server, :attribute => 'iconserver'
10
- flickr_attribute :icon_farm, :attribute => 'iconfarm'
7
+ flickr_attribute :id, :from => '@nsid'
8
+ flickr_attribute :username
9
+ flickr_attribute :icon_server, :from => '@iconserver'
10
+ flickr_attribute :icon_farm, :from => '@iconfarm'
11
11
 
12
12
  # Retrieve a list of contacts for the specified user ID and return an initialized
13
13
  # collection of #User objects
14
14
  def self.find_all_by_user_id(user_id)
15
- response = Fleakr::Api::Request.with_response!('contacts.getPublicList', :user_id => user_id)
15
+ response = Fleakr::Api::MethodRequest.with_response!('contacts.getPublicList', :user_id => user_id)
16
16
  (response.body/'contacts/contact').map {|c| Contact.new(c).to_user }
17
17
  end
18
18
 
@@ -14,8 +14,8 @@ module Fleakr
14
14
 
15
15
  include Fleakr::Support::Object
16
16
 
17
- flickr_attribute :code, :xpath => 'rsp/err', :attribute => 'code'
18
- flickr_attribute :message, :xpath => 'rsp/err', :attribute => 'msg'
17
+ flickr_attribute :code, :from => 'err@code'
18
+ flickr_attribute :message, :from => 'err@msg'
19
19
 
20
20
  end
21
21
  end
@@ -12,8 +12,8 @@ module Fleakr
12
12
 
13
13
  include Fleakr::Support::Object
14
14
 
15
- flickr_attribute :id, :attribute => 'nsid'
16
- flickr_attribute :name, :attribute => 'name'
15
+ flickr_attribute :id, :from => '@nsid'
16
+ flickr_attribute :name
17
17
 
18
18
  find_all :by_user_id, :call => 'people.getPublicGroups', :path => 'groups/group'
19
19