userharmony-flickr_fu 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.gitignore +13 -0
  2. data/LICENSE +22 -0
  3. data/README +147 -0
  4. data/Rakefile +73 -0
  5. data/VERSION.yml +4 -0
  6. data/flickr_fu.gemspec +117 -0
  7. data/lib/flickr/auth.rb +80 -0
  8. data/lib/flickr/base.rb +151 -0
  9. data/lib/flickr/comment.rb +16 -0
  10. data/lib/flickr/contact.rb +16 -0
  11. data/lib/flickr/contacts.rb +55 -0
  12. data/lib/flickr/errors.rb +20 -0
  13. data/lib/flickr/geo.rb +42 -0
  14. data/lib/flickr/license.rb +24 -0
  15. data/lib/flickr/location.rb +15 -0
  16. data/lib/flickr/note.rb +16 -0
  17. data/lib/flickr/people.rb +54 -0
  18. data/lib/flickr/person.rb +82 -0
  19. data/lib/flickr/photo.rb +303 -0
  20. data/lib/flickr/photo_response.rb +37 -0
  21. data/lib/flickr/photos.rb +246 -0
  22. data/lib/flickr/photoset.rb +66 -0
  23. data/lib/flickr/photosets.rb +40 -0
  24. data/lib/flickr/size.rb +16 -0
  25. data/lib/flickr/status.rb +19 -0
  26. data/lib/flickr/test.rb +31 -0
  27. data/lib/flickr/token.rb +22 -0
  28. data/lib/flickr/uploader.rb +162 -0
  29. data/lib/flickr/urls.rb +44 -0
  30. data/lib/flickr_fu.rb +48 -0
  31. data/spec/fixtures/flickr/contacts/get_list-fail-99.xml +4 -0
  32. data/spec/fixtures/flickr/contacts/get_public_list-0.xml +7 -0
  33. data/spec/fixtures/flickr/photos/geo/get_location-0.xml +11 -0
  34. data/spec/fixtures/flickr/photos/geo/get_location-fail-2.xml +4 -0
  35. data/spec/fixtures/flickr/photos/get_info-0.xml +41 -0
  36. data/spec/fixtures/flickr/photos/get_info-1.xml +19 -0
  37. data/spec/fixtures/flickr/photos/get_sizes-0.xml +10 -0
  38. data/spec/fixtures/flickr/photos/get_sizes-1.xml +8 -0
  39. data/spec/fixtures/flickr/photos/licenses/get_info.xml +12 -0
  40. data/spec/fixtures/flickr/photosets/get_list-0.xml +13 -0
  41. data/spec/fixtures/flickr/photosets/get_photos-0.xml +7 -0
  42. data/spec/fixtures/flickr/test/echo-0.xml +5 -0
  43. data/spec/fixtures/flickr/test/null-fail-99.xml +4 -0
  44. data/spec/fixtures/flickr/urls/get_group-0.xml +4 -0
  45. data/spec/fixtures/flickr/urls/get_group-fail-1.xml +4 -0
  46. data/spec/fixtures/flickr/urls/get_user_photos-0.xml +4 -0
  47. data/spec/fixtures/flickr/urls/get_user_photos-fail-1.xml +4 -0
  48. data/spec/fixtures/flickr/urls/get_user_photos-fail-2.xml +4 -0
  49. data/spec/fixtures/flickr/urls/get_user_profile-0.xml +4 -0
  50. data/spec/fixtures/flickr/urls/get_user_profile-fail-1.xml +4 -0
  51. data/spec/fixtures/flickr/urls/get_user_profile-fail-2.xml +4 -0
  52. data/spec/fixtures/flickr/urls/lookup_group-0.xml +6 -0
  53. data/spec/fixtures/flickr/urls/lookup_group-fail-1.xml +4 -0
  54. data/spec/fixtures/flickr/urls/lookup_user-0.xml +6 -0
  55. data/spec/fixtures/flickr/videos/get_info-0.xml +31 -0
  56. data/spec/fixtures/flickr/videos/get_sizes-0.xml +13 -0
  57. data/spec/flickr/base_spec.rb +97 -0
  58. data/spec/flickr/contacts_spec.rb +47 -0
  59. data/spec/flickr/errors_spec.rb +21 -0
  60. data/spec/flickr/geo_spec.rb +20 -0
  61. data/spec/flickr/photo_spec.rb +140 -0
  62. data/spec/flickr/photos_spec.rb +50 -0
  63. data/spec/flickr/photosets_spec.rb +49 -0
  64. data/spec/flickr/test_spec.rb +34 -0
  65. data/spec/flickr/urls_spec.rb +99 -0
  66. data/spec/spec.opts +4 -0
  67. data/spec/spec_helper.rb +20 -0
  68. metadata +176 -0
@@ -0,0 +1,303 @@
1
+ # wrapping class to hold an flickr photo
2
+ class Flickr::Photos::Photo
3
+ attr_accessor :id, :owner, :secret, :server, :farm, :title, :is_public, :is_friend, :is_family # standard attributes
4
+ attr_accessor :license_id, :uploaded_at, :taken_at, :owner_name, :icon_server, :original_format, :updated_at, :geo, :tags, :machine_tags, :o_dims, :views, :media # extra attributes
5
+ attr_accessor :info_added, :description, :original_secret, :owner_username, :owner_realname, :url_photopage, :notes # info attributes
6
+ attr_accessor :comments # comment attributes
7
+
8
+ # create a new instance of a flickr photo.
9
+ #
10
+ # Params
11
+ # * flickr (Required)
12
+ # the flickr object
13
+ # * attributes (Required)
14
+ # a hash of attributes used to set the initial values of the photo object
15
+ def initialize(flickr, attributes)
16
+ @flickr = flickr
17
+ attributes.each do |k,v|
18
+ send("#{k}=", v)
19
+ end
20
+ end
21
+
22
+ # Alias to image_url method
23
+ def url(size = :medium)
24
+ image_url(size)
25
+ end
26
+
27
+ # retreive the url to the image stored on flickr
28
+ #
29
+ # == Params
30
+ # * size (Optional)
31
+ # the size of the image to return. Optional sizes are:
32
+ # :square - square 75x75
33
+ # :thumbnail - 100 on longest side
34
+ # :small - 240 on longest side
35
+ # :medium - 500 on longest side
36
+ # :large - 1024 on longest side (only exists for very large original images)
37
+ # :original - original image, either a jpg, gif or png, depending on source format
38
+ #
39
+ def image_url(size = :medium)
40
+ # It turns out that flickr always stores all the sizes of the picture even when getSizes call returns otherwise.
41
+ # Not calling getSizes is also very important for performance reasons.
42
+ # Retrieving 30 search results means calling the API 31 times if you call getSizes every time.
43
+ # Mind that you still need to call getSizes if you go out for the original image.
44
+ if size == :original
45
+ size_hash[size.to_s].source if size_hash.has_key? size.to_s
46
+ else
47
+ key = "_#{size_key(size.to_sym)}"
48
+ key = "" if key == "_"
49
+ "http://farm#{farm}.static.flickr.com/#{server}/#{id}_#{secret}#{key}.jpg"
50
+ end
51
+ end
52
+
53
+ def photopage_url
54
+ # Keeping the same convention as image_url (foo_url)
55
+ url_photopage
56
+ end
57
+
58
+ def video_url
59
+ if size_hash['video player']
60
+ size_hash['video player'].source
61
+ end
62
+ end
63
+
64
+ # save the current photo to the local computer
65
+ #
66
+ # == Params
67
+ # * filename (Required)
68
+ # name of the new file omiting the extention (ex. photo_1)
69
+ # * size (Optional)
70
+ # the size of the image to return. Optional sizes are:
71
+ # :small - square 75x75
72
+ # :thumbnail - 100 on longest side
73
+ # :small - 240 on longest side
74
+ # :medium - 500 on longest side
75
+ # :large - 1024 on longest side (only exists for very large original images)
76
+ # :original - original image, either a jpg, gif or png, depending on source format
77
+ #
78
+ def save_as(filename, size = :medium)
79
+ format = size.to_sym == :original ? (self.original_format || 'jpg') : 'jpg'
80
+ filename = "#{filename}.#{format}"
81
+
82
+ if File.exists?(filename) or not self.url(size)
83
+ false
84
+ else
85
+ f = File.new(filename, 'w+')
86
+ f.puts open(self.url(size)).read
87
+ f.close
88
+ f
89
+ end
90
+ end
91
+
92
+ # Add tags to a photo.
93
+ #
94
+ # Params
95
+ # * tags (Required)
96
+ # comma seperated list of tags
97
+ #
98
+ def add_tags(tags)
99
+ @flickr.send_request('flickr.photos.addTags', {:photo_id => self.id, :tags => tags}, :post)
100
+ true
101
+ end
102
+
103
+ # Add comment to a photo as the currently authenticated user.
104
+ #
105
+ # Params
106
+ # * message (Required)
107
+ # text of the comment
108
+ #
109
+ def add_comment(message)
110
+ @flickr.send_request('flickr.photos.comments.addComment', {:photo_id => self.id, :comment_text => message}, :post)
111
+ true
112
+ end
113
+
114
+ # Add a note to a photo. Coordinates and sizes are in pixels, based on the 500px image size shown on individual photo pages.
115
+ #
116
+ # Params
117
+ # * message (Required)
118
+ # The text of the note
119
+ # * x (Required)
120
+ # The left coordinate of the note
121
+ # * y (Required)
122
+ # The top coordinate of the note
123
+ # * w (Required)
124
+ # The width of the note
125
+ # * h (Required)
126
+ # The height of the note
127
+ #
128
+ def add_note(message, x, y, w, h)
129
+ @flickr.send_request('flickr.photos.notes.add', {:photo_id => self.id, :note_x => x, :note_y => y, :note_w => w, :note_h => h, :note_text => message}, :post)
130
+ true
131
+ end
132
+
133
+ # Rotate a photo.
134
+ #
135
+ # Params
136
+ # * degrees (Required)
137
+ # The amount of degrees by which to rotate the photo (clockwise) from it's current orientation. Valid values are 90, 180 and 270.
138
+ #
139
+ def rotate(degrees)
140
+ @flickr.send_request('flickr.photos.transform.rotate', {:photo_id => self.id, :degrees => degrees}, :post)
141
+ true
142
+ end
143
+
144
+ # return the license associated with the photo
145
+ #
146
+ def license
147
+ @flickr.photos.licenses[self.license_id]
148
+ end
149
+
150
+ # Returns the location of the photo (if available)
151
+ # or nil if photo is not geo-tagged.
152
+ def location
153
+ begin
154
+ @location ||= @flickr.photos.geo.get_location(self.id)
155
+ rescue Flickr::Error => e
156
+ if e.code == 2 # 2: Photo has no location information.
157
+ return nil
158
+ else
159
+ raise e
160
+ end
161
+ end
162
+ end
163
+
164
+ def location= location
165
+ if !location.nil?
166
+ @flickr.photos.geo.set_location(self.id, location.latitude, location.longitude, location.accuracy)
167
+ else
168
+ @flickr.photos.geo.remove_location(self.id)
169
+ end
170
+ @location = location
171
+ end
172
+
173
+ # Sets the license for a photo.
174
+ #
175
+ # Params
176
+ # * license_id (Required)
177
+ # The license to apply, or 0 (zero) to remove the current license.
178
+ def set_license(license_id)
179
+ @flickr.send_request('flickr.photos.licenses.setLicense', {:photo_id => self.id, :license_id => license_id}, :post)
180
+ true
181
+ end
182
+
183
+ def description # :nodoc:
184
+ attach_info
185
+ @description
186
+ end
187
+
188
+ def original_secret # :nodoc:
189
+ attach_info
190
+ @original_secret
191
+ end
192
+
193
+ def owner_username # :nodoc:
194
+ attach_info
195
+ @owner_username
196
+ end
197
+
198
+ def owner_realname # :nodoc:
199
+ attach_info
200
+ @owner_realname
201
+ end
202
+
203
+ def url_photopage # :nodoc:
204
+ attach_info
205
+ @url_photopage
206
+ end
207
+
208
+ def comments # :nodoc:
209
+ @comments ||= begin
210
+ if @comment_count == 0
211
+ self.comments = []
212
+ else
213
+ rsp = @flickr.send_request('flickr.photos.comments.getList', :photo_id => self.id)
214
+
215
+ self.comments = []
216
+
217
+ rsp.comments.comment.each do |comment|
218
+ self.comments << Flickr::Photos::Comment.new(:id => comment[:id],
219
+ :comment => comment.to_s,
220
+ :author => comment[:author],
221
+ :author_name => comment[:authorname],
222
+ :permalink => comment[:permalink],
223
+ :created_at => (Time.at(comment[:datecreate].to_i) rescue nil))
224
+ end
225
+ end
226
+
227
+ self.comments
228
+ end
229
+ end
230
+
231
+ def sizes # :nodoc:
232
+ @sizes ||= begin
233
+ rsp = @flickr.send_request('flickr.photos.getSizes', :photo_id => self.id)
234
+
235
+ _sizes = []
236
+ rsp.sizes.size.each do |size|
237
+ _sizes << Flickr::Photos::Size.new(:label => size[:label], :width => size[:width],
238
+ :height => size[:height], :source => size[:source], :url => size[:url])
239
+ end
240
+ _sizes
241
+ end
242
+ end
243
+
244
+ def notes # :nodoc:
245
+ attach_info
246
+ @notes
247
+ end
248
+
249
+ protected
250
+ def size_hash
251
+ @size_hash ||= begin
252
+ hash = {}
253
+ sizes.each do |size|
254
+ hash[size.label.downcase] = size
255
+ end
256
+ hash
257
+ end
258
+ end
259
+
260
+ private
261
+ attr_accessor :comment_count
262
+
263
+ # convert the size to the key used in the flickr url
264
+ def size_key(size)
265
+ case size.to_sym
266
+ when :square then 's'
267
+ when :thumb, :thumbnail then 't'
268
+ when :small then 'm'
269
+ when :medium then ''
270
+ when :large then 'b'
271
+ when :original then 'o'
272
+ else ''
273
+ end
274
+ end
275
+
276
+ # loads photo info when a field is requested that requires additional info
277
+ def attach_info
278
+ unless self.info_added
279
+ rsp = @flickr.send_request('flickr.photos.getInfo', :photo_id => self.id, :secret => self.secret)
280
+
281
+ self.info_added = true
282
+ self.description = rsp.photo.description.to_s.strip
283
+ self.original_secret = rsp.photo[:originalsecret]
284
+ self.owner_username = rsp.photo.owner[:username]
285
+ self.owner_realname = rsp.photo.owner[:realname]
286
+ self.url_photopage = rsp.photo.urls.url.to_s
287
+ self.comment_count = rsp.photo.comments.to_s.to_i
288
+
289
+ self.notes = []
290
+
291
+ rsp.photo.notes.note.each do |note|
292
+ self.notes << Flickr::Photos::Note.new(:id => note[:id],
293
+ :note => note.to_s,
294
+ :author => note[:author],
295
+ :author_name => note[:authorname],
296
+ :x => note[:x],
297
+ :y => note[:y],
298
+ :width => note[:w],
299
+ :height => note[:h])
300
+ end if rsp.photo.notes.note
301
+ end
302
+ end
303
+ end
@@ -0,0 +1,37 @@
1
+ # wrapping class to hold a photos response from the flickr api
2
+ #
3
+ class Flickr::Photos::PhotoResponse
4
+ attr_accessor :page, :pages, :per_page, :total, :photos, :api, :method, :options
5
+
6
+ # creates an object to hold the search response.
7
+ #
8
+ # Params
9
+ # * attributes (Required)
10
+ # a hash of attributes used to set the initial values of the response object
11
+ def initialize(attributes)
12
+ attributes.each do |k,v|
13
+ send("#{k}=", v)
14
+ end
15
+ end
16
+
17
+ # Add a Flickr::Photos::Photo object to the photos array. It does nothing if you pass a non photo object
18
+ def <<(photo)
19
+ self.photos ||= []
20
+ self.photos << photo if photo.is_a?(Flickr::Photos::Photo)
21
+ end
22
+
23
+ # gets the next page from flickr if there are anymore pages in the current photos object
24
+ def next_page
25
+ api.send(self.method, options.merge(:page => self.page.to_i + 1)) if self.page.to_i < self.pages.to_i
26
+ end
27
+
28
+ # gets the previous page from flickr if there is a previous page in the current photos object
29
+ def previous_page
30
+ api.send(self.method, options.merge(:page => self.page.to_i - 1)) if self.page.to_i > 1
31
+ end
32
+
33
+ # passes all unknown request to the photos array if it responds to the method
34
+ def method_missing(method, *args, &block)
35
+ self.photos.respond_to?(method) ? self.photos.send(method, *args, &block) : super
36
+ end
37
+ end
@@ -0,0 +1,246 @@
1
+ class Flickr::Photos < Flickr::Base
2
+ def initialize(flickr)
3
+ @flickr = flickr
4
+ end
5
+
6
+ # Return a list of photos matching some criteria. Only photos visible to the calling user will be returned. To return private or semi-private photos,
7
+ # the caller must be authenticated with 'read' permissions, and have permission to view the photos. Unauthenticated calls will only return public photos.
8
+ #
9
+ # == Authentication
10
+ # This method does not require authentication.
11
+ #
12
+ # == Options
13
+ # * user_id (Optional)
14
+ # The NSID of the user who's photo to search. If this parameter isn't passed then everybody's public photos will be searched. A value of "me" will
15
+ # search against the calling user's photos for authenticated calls.
16
+ # * tags (Optional)
17
+ # A comma-delimited list of tags. Photos with one or more of the tags listed will be returned.
18
+ # * tag_mode (Optional)
19
+ # Either 'any' for an OR combination of tags, or 'all' for an AND combination. Defaults to 'any' if not specified.
20
+ # * text (Optional)
21
+ # A free text search. Photos who's title, description or tags contain the text will be returned.
22
+ # * min_upload_date (Optional)
23
+ # Minimum upload date. Photos with an upload date greater than or equal to this value will be returned. The date should be in the form of a unix timestamp.
24
+ # * max_upload_date (Optional)
25
+ # Maximum upload date. Photos with an upload date less than or equal to this value will be returned. The date should be in the form of a unix timestamp.
26
+ # * min_taken_date (Optional)
27
+ # Minimum taken date. Photos with an taken date greater than or equal to this value will be returned. The date should be in the form of a mysql datetime.
28
+ # * max_taken_date (Optional)
29
+ # Maximum taken date. Photos with an taken date less than or equal to this value will be returned. The date should be in the form of a mysql datetime.
30
+ # * license (Optional)
31
+ # The license id for photos (for possible values see the flickr.photos.licenses.getInfo method). Multiple licenses may be comma-separated.
32
+ # * sort (Optional)
33
+ # The order in which to sort returned photos. Deafults to date-posted-desc. The possible values are: date-posted-asc, date-posted-desc, date-taken-asc,
34
+ # date-taken-desc, interestingness-desc, interestingness-asc, and relevance.
35
+ # * privacy_filter (Optional)
36
+ # Return photos only matching a certain privacy level. This only applies when making an authenticated call to view photos you own. Valid values are:
37
+ # 1 public photos
38
+ # 2 private photos visible to friends
39
+ # 3 private photos visible to family
40
+ # 4 private photos visible to friends & family
41
+ # 5 completely private photos
42
+ # * bbox (Optional)
43
+ # A comma-delimited list of 4 values defining the Bounding Box of the area that will be searched.
44
+ #
45
+ # The 4 values represent the bottom-left corner of the box and the top-right corner, minimum_longitude, minimum_latitude, maximum_longitude, maximum_latitude.
46
+ #
47
+ # Longitude has a range of -180 to 180 , latitude of -90 to 90. Defaults to -180, -90, 180, 90 if not specified.
48
+ #
49
+ # Unlike standard photo queries, geo (or bounding box) queries will only return 250 results per page.
50
+ #
51
+ # Geo queries require some sort of limiting agent in order to prevent the database from crying. This is basically like the check against "parameterless searches"
52
+ # for queries without a geo component.
53
+ #
54
+ # A tag, for instance, is considered a limiting agent as are user defined min_date_taken and min_date_upload parameters — If no limiting factor is passed we
55
+ # return only photos added in the last 12 hours (though we may extend the limit in the future).
56
+ # * accuracy (Optional)
57
+ # Recorded accuracy level of the location information. Current range is 1-16 :
58
+ # World level is 1
59
+ # Country is ~3
60
+ # Region is ~6
61
+ # City is ~11
62
+ # Street is ~16
63
+ # Defaults to maximum value if not specified.
64
+ # * safe_search (Optional)
65
+ # Safe search setting:
66
+ # 1 for safe.
67
+ # 2 for moderate.
68
+ # 3 for restricted.
69
+ # (Please note: Un-authed calls can only see Safe content.)
70
+ # * content_type (Optional)
71
+ # Content Type setting:
72
+ # 1 for photos only.
73
+ # 2 for screenshots only.
74
+ # 3 for 'other' only.
75
+ # 4 for photos and screenshots.
76
+ # 5 for screenshots and 'other'.
77
+ # 6 for photos and 'other'.
78
+ # 7 for photos, screenshots, and 'other' (all).
79
+ # * machine_tags (Optional)
80
+ # Aside from passing in a fully formed machine tag, there is a special syntax for searching on specific properties :
81
+ # Find photos using the 'dc' namespace : "machine_tags" => "dc:"
82
+ # Find photos with a title in the 'dc' namespace : "machine_tags" => "dc:title="
83
+ # Find photos titled "mr. camera" in the 'dc' namespace : "machine_tags" => "dc:title=\"mr. camera\"
84
+ # Find photos whose value is "mr. camera" : "machine_tags" => "*:*=\"mr. camera\""
85
+ # Find photos that have a title, in any namespace : "machine_tags" => "*:title="
86
+ # Find photos that have a title, in any namespace, whose value is "mr. camera" : "machine_tags" => "*:title=\"mr. camera\""
87
+ # Find photos, in the 'dc' namespace whose value is "mr. camera" : "machine_tags" => "dc:*=\"mr. camera\""
88
+ # Multiple machine tags may be queried by passing a comma-separated list. The number of machine tags you can pass in a single query depends on
89
+ # the tag mode (AND or OR) that you are querying with. "AND" queries are limited to (16) machine tags. "OR" queries are limited to (8).
90
+ # * machine_tag_mode (Required)
91
+ # Either 'any' for an OR combination of tags, or 'all' for an AND combination. Defaults to 'any' if not specified.
92
+ # * group_id (Optional)
93
+ # The id of a group who's pool to search. If specified, only matching photos posted to the group's pool will be returned.
94
+ # * woe_id (Optional)
95
+ # A 32-bit identifier that uniquely represents spatial entities. (not used if bbox argument is present). Experimental.
96
+ #
97
+ # Geo queries require some sort of limiting agent in order to prevent the database from crying. This is basically like the check against "parameterless searches"
98
+ # for queries without a geo component.
99
+ #
100
+ # A tag, for instance, is considered a limiting agent as are user defined min_date_taken and min_date_upload parameters &emdash; If no limiting factor is passed
101
+ # we return only photos added in the last 12 hours (though we may extend the limit in the future).
102
+ # * place_id (Optional)
103
+ # A Flickr place id. (not used if bbox argument is present). Experimental.
104
+ #
105
+ # Geo queries require some sort of limiting agent in order to prevent the database from crying. This is basically like the check against "parameterless searches"
106
+ # for queries without a geo component.
107
+ #
108
+ # A tag, for instance, is considered a limiting agent as are user defined min_date_taken and min_date_upload parameters &emdash; If no limiting factor is passed
109
+ # we return only photos added in the last 12 hours (though we may extend the limit in the future).
110
+ # * per_page (Optional)
111
+ # Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.
112
+ # * page (Optional)
113
+ # The page of results to return. If this argument is omitted, it defaults to 1.
114
+ # * media (Optional)
115
+ # The type of media to search for. 'photo', 'video', or 'both' are allowed arguments, with 'both' being the default.
116
+ #
117
+ def search(options)
118
+ options.merge!({:extras => "license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo,tags,machine_tags,o_dims,views,media"})
119
+
120
+ rsp = @flickr.send_request('flickr.photos.search', options)
121
+
122
+ returning PhotoResponse.new(:page => rsp.photos[:page].to_i,
123
+ :pages => rsp.photos[:pages].to_i,
124
+ :per_page => rsp.photos[:perpage].to_i,
125
+ :total => rsp.photos[:total].to_i,
126
+ :photos => [],
127
+ :api => self,
128
+ :method => 'search',
129
+ :options => options) do |photos|
130
+ rsp.photos.photo.each do |photo|
131
+ attributes = create_attributes(photo)
132
+
133
+ photos << Photo.new(@flickr, attributes)
134
+ end if rsp.photos.photo
135
+ end
136
+ end
137
+
138
+ # Returns a list of the latest public photos uploaded to flickr.
139
+ #
140
+ # == Authentication
141
+ # This method does not require authentication.
142
+ #
143
+ # == Options
144
+ # * per_page (Optional)
145
+ # Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.
146
+ # * page (Optional)
147
+ # The page of results to return. If this argument is omitted, it defaults to 1.
148
+ # * media (Optional)
149
+ # The type of media to search for. 'photo', 'video', or 'both' are allowed arguments, with 'both' being the default.
150
+ #
151
+ def get_recent(options = {})
152
+ options.merge!({:extras => "license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo,tags,machine_tags,o_dims,views,media"})
153
+
154
+ rsp = @flickr.send_request('flickr.photos.getRecent', options)
155
+
156
+ returning PhotoResponse.new(:page => rsp.photos[:page].to_i,
157
+ :pages => rsp.photos[:pages].to_i,
158
+ :per_page => rsp.photos[:perpage].to_i,
159
+ :total => rsp.photos[:total].to_i,
160
+ :photos => [], :api => self,
161
+ :method => 'flickr.photos.getRecent',
162
+ :options => options) do |photos|
163
+ rsp.photos.photo.each do |photo|
164
+ attributes = create_attributes(photo)
165
+
166
+ photos << Photo.new(@flickr, attributes)
167
+ end if rsp.photos.photo
168
+ end
169
+ end
170
+
171
+ def interesting(options)
172
+ options.merge!({:extras => "license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo,tags,machine_tags,o_dims,views,media"})
173
+
174
+ rsp = @flickr.send_request('flickr.interestingness.getList', options)
175
+
176
+ returning PhotoResponse.new(:page => rsp.photos[:page].to_i,
177
+ :pages => rsp.photos[:pages].to_i,
178
+ :per_page => rsp.photos[:perpage].to_i,
179
+ :total => rsp.photos[:total].to_i,
180
+ :photos => [],
181
+ :api => self,
182
+ :method => 'flickr.interestingness.getList',
183
+ :options => options) do |photos|
184
+ rsp.photos.photo.each do |photo|
185
+ attributes = create_attributes(photo)
186
+
187
+
188
+ photos << Photo.new(@flickr, attributes)
189
+ end if rsp.photos.photo
190
+ end
191
+ end
192
+
193
+ def licenses
194
+ @licenses ||= begin
195
+ rsp = @flickr.send_request('flickr.photos.licenses.getInfo')
196
+
197
+ returning Hash.new do |licenses|
198
+ rsp.licenses.license.each do |license|
199
+ licenses[license[:id].to_i] = Flickr::Photos::License.new(:id => license[:id].to_i, :name => license[:name], :url => license[:url])
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ # creates and/or returns the Flickr::Photos::Geo object
206
+ def geo
207
+ @geo ||= Flickr::Photos::Geo.new(@flickr)
208
+ end
209
+
210
+ # Returns a Flickr::Photos::Photo object of the given id.
211
+ # Raises an error if photo not found
212
+ def find_by_id(photo_id)
213
+ rsp = @flickr.send_request('flickr.photos.getInfo', :photo_id => photo_id)
214
+ Photo.new(@flickr, :id => rsp.photo[:id].to_i, :owner => rsp.photo.owner,
215
+ :secret => rsp.photo[:secret], :server => rsp.photo[:server].to_i, :farm => rsp.photo[:farm],
216
+ :title => rsp.photo.title,
217
+ :is_public => rsp.photo.visibility[:public], :is_friend => rsp.photo.visibility[:is_friend], :is_family => rsp.photo.visibility[:is_family])
218
+ end
219
+
220
+ protected
221
+ def create_attributes(photo)
222
+ {:id => photo[:id],
223
+ :owner => photo[:owner],
224
+ :secret => photo[:secret],
225
+ :server => photo[:server],
226
+ :farm => photo[:farm],
227
+ :title => photo[:title],
228
+ :is_public => photo[:ispublic],
229
+ :is_friend => photo[:isfriend],
230
+ :is_family => photo[:isfamily],
231
+ :license_id => photo[:license].to_i,
232
+ :uploaded_at => (Time.at(photo[:dateupload].to_i) rescue nil),
233
+ :taken_at => (Time.parse(photo[:datetaken]) rescue nil),
234
+ :owner_name => photo[:ownername],
235
+ :icon_server => photo[:icon_server],
236
+ :original_format => photo[:originalformat],
237
+ :updated_at => (Time.at(photo[:lastupdate].to_i) rescue nil),
238
+ :geo => photo[:geo],
239
+ :tags => photo[:tags],
240
+ :machine_tags => photo[:machine_tags],
241
+ :o_dims => photo[:o_dims],
242
+ :views => photo[:views].to_i,
243
+ :media => photo[:media]}
244
+ end
245
+
246
+ end