userharmony-flickr_fu 0.3.6

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.
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