flickraw 0.3.2 → 0.4

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.
@@ -8,8 +8,8 @@ require 'open-uri'
8
8
  DESKTOP=1
9
9
 
10
10
  list = flickr.interestingness.getList
11
- photo = list[rand( 100)]
12
- sizes = flickr.photos.getSizes( :photo_id => photo.id)
11
+ photo = list[rand(100)]
12
+ sizes = flickr.photos.getSizes(:photo_id => photo.id)
13
13
  original = sizes.find {|s| s.label == 'Original' }
14
14
 
15
15
  url = original.source
data/flickraw_rdoc.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require "rdoc/parsers/parserfactory"
2
2
  require "rdoc/parsers/parse_rb"
3
- require "cgi"
4
3
 
5
4
  FLICKR_API_URL='http://www.flickr.com/services/api'
6
5
 
@@ -56,14 +55,12 @@ module RDoc
56
55
  m.singleton = false
57
56
 
58
57
  m.start_collecting_tokens
59
- m.add_token FakedToken.new( <<END
60
- # Generated automatically from the flickr api
58
+ m.add_token FakedToken.new( %{
59
+ # Generated automatically from flickr api
61
60
  def #{name}(*args)
62
- Request.call '#{flickr_method}', *args
61
+ @flickr.call '#{flickr_method}', *args
63
62
  end
64
- END
65
- )
66
-
63
+ } )
67
64
  doc.add_method m
68
65
  progress(".")
69
66
  @stats.num_methods += 1
@@ -86,7 +83,7 @@ END
86
83
  arguments << "[#{arg.name} "
87
84
  arguments << "<em>(required)</em> " if arg.optional == '0'
88
85
  arguments << "] "
89
- arguments << "#{CGI.unescapeHTML(arg.to_s)}\n"
86
+ arguments << "#{unescapeHTML(arg.to_s)}\n"
90
87
  }
91
88
  end
92
89
  end
@@ -95,13 +92,13 @@ END
95
92
  errors = "<b>Error codes</b>\n"
96
93
  info.errors.each {|e|
97
94
  errors << "* #{e.code}: <em>#{e.message}</em>\n\n"
98
- errors << " #{e.to_s}\n"
95
+ errors << " #{unescapeHTML e.to_s}\n"
99
96
  }
100
97
  end
101
98
 
102
99
  if info.method.respond_to? :response
103
100
  response = "<b>Returns</b>\n"
104
- raw = CGI.unescapeHTML(info.method.response.to_s)
101
+ raw = unescapeHTML(info.method.response.to_s)
105
102
  response << raw.collect { |line| line.insert(0, ' ') }.join
106
103
  else
107
104
  response = ''
@@ -133,14 +130,16 @@ END
133
130
  end
134
131
 
135
132
  def unescapeHTML(string)
133
+ string.gsub!('\/', '/')
136
134
  string.gsub(/&(.*?);/n) do
137
135
  match = $1.dup
138
136
  case match
139
- when /\Aamp\z/ni then '&'
140
- when /\Aquot\z/ni then '"'
141
- when /\Agt\z/ni then '>'
142
- when /\Alt\z/ni then '<'
143
- else "&#{match};"
137
+ when /\Aamp\z/ni then '&'
138
+ when /\Aquot\z/ni then '"'
139
+ when /\Agt\z/ni then '>'
140
+ when /\Alt\z/ni then '<'
141
+ when /\Anbsp\z/ni then ' '
142
+ else "&#{match};"
144
143
  end
145
144
  end
146
145
  end
data/lib/flickraw.rb CHANGED
@@ -20,12 +20,12 @@
20
20
  # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
 
23
- require 'rexml/document'
24
23
  require 'net/http'
25
24
  require 'md5'
25
+ require 'yaml'
26
26
 
27
27
  module FlickRaw
28
- VERSION='0.3.2'
28
+ VERSION='0.4'
29
29
 
30
30
  FLICKR_HOST='api.flickr.com'.freeze
31
31
 
@@ -40,67 +40,45 @@ module FlickRaw
40
40
 
41
41
  @api_key = '7b124df89b638e545e3165293883ef62'
42
42
 
43
- # This is a wrapper around the xml response which provides an easy interface.
44
- class Xml
45
- include Enumerable
46
- # Returns the text content of the response
47
- attr_reader :to_s
48
-
49
- # Returns the raw xml of the response
50
- attr_reader :to_xml
51
-
52
- def initialize(xml) # :nodoc:
53
- @to_s = xml.texts.join(' ')
54
- @to_xml = xml.to_s
55
-
56
- xml.attributes.each {|a, v| attribute a, v }
57
-
58
- if xml.name =~ /s\z/
59
- elements = REXML::XPath.match( xml, xml.name.sub(/s\z/, ''))
60
- @list = elements.collect { |e| Xml.new e }
61
- else
62
- @list = [self]
63
- xml.elements.each {|e|
64
- if instance_variable_get "@#{e.name}"
65
- send(e.name) << Xml.new(e)
66
- else
67
- attribute e.name, Xml.new(e)
68
- end
69
- }
70
- end
71
- end
72
-
73
- def [](index); @list[index]; end
74
- def each; @list.each { |el| yield el }; end
75
- def length; @list.length; end
76
-
77
- protected
78
- def << el; @list << el; end
79
-
80
- private
81
- def attribute(sym, value)
82
- instance_variable_set "@#{sym}", value
43
+ module SimpleOStruct # :nodoc:
44
+ def __attr_define(k,v)
45
+ instance_variable_set "@#{k}", v
83
46
  meta = class << self; self; end
84
- meta.class_eval { attr_reader sym.to_s }
47
+ meta.class_eval { attr_reader k.to_s }
85
48
  end
86
49
  end
87
50
 
88
- # This is what you get in response to an API call.
89
- class Response < Xml
90
- # This is called internally. It builds the response object according to xml response from the server.
91
- def initialize(raw_xml)
92
- doc = REXML::Document.new raw_xml
93
- super doc.root
94
- super doc.root.elements[1] if doc.root.elements.size == 1
51
+ class Response # :nodoc:
52
+ include SimpleOStruct
53
+ def initialize(h); h.each {|k, v| __attr_define k, Response.structify(v, k) } end
54
+ def self.structify(obj, name = '')
55
+ if obj.is_a? Hash
56
+ if name =~ /s$/ and obj[$`].is_a? Array
57
+ list = structify obj[$`]
58
+ list.extend SimpleOStruct
59
+ list.instance_eval { obj.each {|kv, vv| __attr_define kv, vv } }
60
+ list
61
+ elsif content = obj['_content']
62
+ content.extend SimpleOStruct
63
+ content.instance_eval { obj.each {|kv, vv| __attr_define kv, vv } }
64
+ content
65
+ else
66
+ blank = Response.new(obj)
67
+ end
68
+ elsif obj.is_a? Array
69
+ obj.collect {|e| structify e}
70
+ else
71
+ obj
72
+ end
95
73
  end
96
74
  end
97
75
 
98
76
  class FailedResponse < StandardError
99
77
  attr_reader :code
100
78
  alias :msg :message
101
- def initialize(msg, code)
79
+ def initialize(msg, code, req)
102
80
  @code = code
103
- super( msg)
81
+ super("'#{req}' - #{msg}")
104
82
  end
105
83
  end
106
84
 
@@ -142,20 +120,13 @@ module FlickRaw
142
120
  end
143
121
 
144
122
  # List of the flickr subobjects of this object
145
- def self.flickr_objects
146
- @flickr_objects ||= []
147
- end
123
+ def self.flickr_objects; @flickr_objects ||= [] end
148
124
 
149
125
  # List of the flickr methods of this object
150
- def self.flickr_methods
151
- @flickr_methods ||= []
152
- end
126
+ def self.flickr_methods; @flickr_methods ||= [] end
153
127
 
154
128
  # Returns the prefix of the request corresponding to this class.
155
- def self.request_name
156
- class_req = name.downcase.gsub( /::/, '.')
157
- class_req.sub( /[^\.]+\./, '') # Removes RawFlickr at the beginning
158
- end
129
+ def self.request_name; name.downcase.gsub(/::/, '.').sub(/[^\.]+\./, '') end
159
130
  end
160
131
 
161
132
  # Root class of the flickr api hierarchy.
@@ -170,14 +141,8 @@ module FlickRaw
170
141
  # Raises FailedResponse if the response status is _failed_.
171
142
  def call(req, args={})
172
143
  path = REST_PATH + build_args(args, req).collect { |a, v| "#{a}=#{v}" }.join('&')
173
-
174
- http_response = Net::HTTP.start(FLICKR_HOST) { |http|
175
- http.get(path, 'User-Agent' => "Flickraw/#{VERSION}")
176
- }
177
- res = Response.new http_response.body
178
- raise FailedResponse.new(res.msg, res.code) if res.stat == 'fail'
179
- lookup_token(req, res)
180
- res
144
+ http_response = Net::HTTP.start(FLICKR_HOST) { |http| http.get(path, 'User-Agent' => "Flickraw/#{VERSION}") }
145
+ parse_response(http_response, req)
181
146
  end
182
147
 
183
148
  # Use this to upload the photo in _file_.
@@ -190,30 +155,45 @@ module FlickRaw
190
155
  boundary = MD5.md5(photo).to_s
191
156
 
192
157
  header = {'Content-type' => "multipart/form-data, boundary=#{boundary} ", 'User-Agent' => "Flickraw/#{VERSION}"}
193
- query = build_args(args).collect { |a, v|
194
- "--#{boundary}\r\n" <<
195
- "Content-Disposition: form-data; name=\"#{a}\"\r\n\r\n" <<
196
- "#{v}\r\n"
197
- }.join('')
198
- query << "--#{boundary}\r\n" <<
199
- "Content-Disposition: form-data; name=\"photo\"; filename=\"#{file}\"\r\n" <<
200
- "Content-Transfer-Encoding: binary\r\n" <<
201
- "Content-Type: image/jpeg\r\n\r\n" <<
202
- photo <<
203
- "\r\n" <<
204
- "--#{boundary}--"
205
-
206
- http_response = Net::HTTP.start(FLICKR_HOST) { |http|
207
- http.post(UPLOAD_PATH, query, header)
158
+ query = ''
159
+ build_args(args).each { |a, v|
160
+ query <<
161
+ "--#{boundary}\r\n" <<
162
+ "Content-Disposition: form-data; name=\"#{a}\"\r\n\r\n" <<
163
+ "#{v}\r\n"
208
164
  }
209
- res = Response.new http_response.body
210
- raise FailedResponse.new(res.msg, res.code) if res.stat == 'fail'
211
- res
165
+ query <<
166
+ "--#{boundary}\r\n" <<
167
+ "Content-Disposition: form-data; name=\"photo\"; filename=\"#{file}\"\r\n" <<
168
+ "Content-Transfer-Encoding: binary\r\n" <<
169
+ "Content-Type: image/jpeg\r\n\r\n" <<
170
+ photo <<
171
+ "\r\n" <<
172
+ "--#{boundary}--"
173
+
174
+ http_response = Net::HTTP.start(FLICKR_HOST) { |http| http.post(UPLOAD_PATH, query, header) }
175
+ xml = http_response.body
176
+ if xml[/stat="(\w+)"/, 1] == 'fail'
177
+ msg = xml[/msg="([^"]+)"/, 1]
178
+ code = xml[/code="([^"]+)"/, 1]
179
+ raise FailedResponse.new(msg, code, 'flickr.upload')
180
+ end
181
+ Response.structify( {:stat => 'ok', :photoid => xml[/<photoid>(\w+)<\/photoid>/, 1], :ticketid => xml[/<ticketid>(\w+)<\/ticketid>/, 1]})
212
182
  end
213
183
 
214
184
  private
185
+ def parse_response(response, req = nil)
186
+ yaml = YAML.load(response.body.gsub(/:([^\s])/, ': \1'))
187
+ raise FailedResponse.new(yaml['message'], yaml['code'], req) if yaml.delete('stat') == 'fail'
188
+ name, yaml = yaml.to_a.first if yaml.size == 1
189
+
190
+ res = Response.structify yaml, name
191
+ lookup_token(req, res)
192
+ res
193
+ end
194
+
215
195
  def build_args(args={}, req = nil)
216
- full_args = {:api_key => FlickRaw.api_key}
196
+ full_args = {:api_key => FlickRaw.api_key, :format => 'json', :nojsoncallback => 1}
217
197
  full_args[:method] = req if req
218
198
  full_args[:auth_token] = @token if @token
219
199
  args.each {|k, v| full_args[k.to_sym] = v }
@@ -223,7 +203,7 @@ module FlickRaw
223
203
 
224
204
  def lookup_token(req, res)
225
205
  token_reqs = ['flickr.auth.getToken', 'flickr.auth.getFullToken', 'flickr.auth.checkToken']
226
- @token = res.token if token_reqs.include?(req) and res.respond_to?( :token)
206
+ @token = res.token if token_reqs.include?(req) and res.respond_to?(:token)
227
207
  end
228
208
  end
229
209
 
@@ -238,7 +218,6 @@ module FlickRaw
238
218
  def auth_url(args={})
239
219
  full_args = {:api_key => FlickRaw.api_key, :perms => 'read'}
240
220
  args.each {|k, v| full_args[k.to_sym] = v }
241
-
242
221
  full_args[:api_sig] = api_sig(full_args) if FlickRaw.shared_secret
243
222
 
244
223
  'http://' + FLICKR_HOST + AUTH_PATH + full_args.collect { |a, v| "#{a}=#{v}" }.join('&')
@@ -251,7 +230,7 @@ module FlickRaw
251
230
  end
252
231
 
253
232
  methods = Flickr.new.call 'flickr.reflection.getMethods'
254
- methods.each { |method| Flickr.build_request method.to_s }
233
+ methods.each { |method| Flickr.build_request method }
255
234
  end
256
235
 
257
236
  class Object
@@ -260,7 +239,5 @@ class Object
260
239
  #
261
240
  # recent_photos = flickr.photos.getRecent
262
241
  # puts recent_photos[0].title
263
- def flickr
264
- @flickr ||= FlickRaw::Flickr.new
265
- end
242
+ def flickr; @flickr ||= FlickRaw::Flickr.new end
266
243
  end
data/rakefile CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'rake/rdoctask'
2
2
  require 'rake/packagetask'
3
3
  require 'rake/gempackagetask'
4
+ require 'rake/testtask'
4
5
 
5
6
  require 'lib/flickraw'
6
7
  require 'flickraw_rdoc'
7
8
 
8
- PKG_FILES = FileList["lib/flickraw.rb", "flickraw_rdoc.rb", "copying.txt", "README", "TODO", "rakefile", "examples/*.rb"].to_a
9
+ PKG_FILES = FileList["lib/flickraw.rb", "flickraw_rdoc.rb", "copying.txt", "README", "TODO", "rakefile", "examples/*.rb", "test/*.rb"].to_a
9
10
 
10
11
  spec = Gem::Specification.new do |s|
11
12
  s.summary = "Flickr library with a syntax close to the syntax described on http://www.flickr.com/services/api"
@@ -29,3 +30,4 @@ Rake::GemPackageTask.new spec do |p|
29
30
  p.need_tar_gz = true
30
31
  end
31
32
 
33
+ Rake::TestTask.new
data/test/test.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'test/unit'
2
+ require 'lib/flickraw'
3
+
4
+ class Basic < Test::Unit::TestCase
5
+ def test_known
6
+ known_methods = ["flickr.activity.userComments", "flickr.activity.userPhotos", "flickr.auth.checkToken", "flickr.auth.getFrob", "flickr.auth.getFullToken", "flickr.auth.getToken", "flickr.blogs.getList", "flickr.blogs.postPhoto", "flickr.contacts.getList", "flickr.contacts.getPublicList", "flickr.favorites.add", "flickr.favorites.getList", "flickr.favorites.getPublicList", "flickr.favorites.remove", "flickr.groups.browse", "flickr.groups.getInfo", "flickr.groups.pools.add", "flickr.groups.pools.getContext", "flickr.groups.pools.getGroups", "flickr.groups.pools.getPhotos", "flickr.groups.pools.remove", "flickr.groups.search", "flickr.interestingness.getList", "flickr.people.findByEmail", "flickr.people.findByUsername", "flickr.people.getInfo", "flickr.people.getPublicGroups", "flickr.people.getPublicPhotos", "flickr.people.getUploadStatus", "flickr.photos.addTags", "flickr.photos.comments.addComment", "flickr.photos.comments.deleteComment", "flickr.photos.comments.editComment", "flickr.photos.comments.getList", "flickr.photos.delete", "flickr.photos.geo.getLocation", "flickr.photos.geo.getPerms", "flickr.photos.geo.removeLocation", "flickr.photos.geo.setLocation", "flickr.photos.geo.setPerms", "flickr.photos.getAllContexts", "flickr.photos.getContactsPhotos", "flickr.photos.getContactsPublicPhotos", "flickr.photos.getContext", "flickr.photos.getCounts", "flickr.photos.getExif", "flickr.photos.getFavorites", "flickr.photos.getInfo", "flickr.photos.getNotInSet", "flickr.photos.getPerms", "flickr.photos.getRecent", "flickr.photos.getSizes", "flickr.photos.getUntagged", "flickr.photos.getWithGeoData", "flickr.photos.getWithoutGeoData", "flickr.photos.licenses.getInfo", "flickr.photos.licenses.setLicense", "flickr.photos.notes.add", "flickr.photos.notes.delete", "flickr.photos.notes.edit", "flickr.photos.recentlyUpdated", "flickr.photos.removeTag", "flickr.photos.search", "flickr.photos.setDates", "flickr.photos.setMeta", "flickr.photos.setPerms", "flickr.photos.setTags", "flickr.photos.transform.rotate", "flickr.photos.upload.checkTickets", "flickr.photosets.addPhoto", "flickr.photosets.comments.addComment", "flickr.photosets.comments.deleteComment", "flickr.photosets.comments.editComment", "flickr.photosets.comments.getList", "flickr.photosets.create", "flickr.photosets.delete", "flickr.photosets.editMeta", "flickr.photosets.editPhotos", "flickr.photosets.getContext", "flickr.photosets.getInfo", "flickr.photosets.getList", "flickr.photosets.getPhotos", "flickr.photosets.orderSets", "flickr.photosets.removePhoto", "flickr.reflection.getMethodInfo", "flickr.reflection.getMethods", "flickr.tags.getHotList", "flickr.tags.getListPhoto", "flickr.tags.getListUser", "flickr.tags.getListUserPopular", "flickr.tags.getListUserRaw", "flickr.tags.getRelated", "flickr.test.echo", "flickr.test.login", "flickr.test.null", "flickr.urls.getGroup", "flickr.urls.getUserPhotos", "flickr.urls.getUserProfile", "flickr.urls.lookupGroup", "flickr.urls.lookupUser"]
7
+ found_methods = flickr.reflection.getMethods
8
+ assert_instance_of Array, found_methods
9
+ known_methods.each { |m| assert found_methods.include?(m), m}
10
+ end
11
+
12
+ def test_found
13
+ found_methods = flickr.reflection.getMethods
14
+ found_methods.each { |m|
15
+ assert_nothing_raised {
16
+ begin
17
+ eval m
18
+ rescue FlickRaw::FailedResponse
19
+ end
20
+ }
21
+ }
22
+ end
23
+
24
+ def test_photos
25
+ list = flickr.photos.getRecent :per_page => '10'
26
+ assert_instance_of Array, list
27
+ assert_equal(list.size, 10)
28
+
29
+ id = secret = info = nil
30
+ assert_nothing_raised(NoMethodError) {
31
+ id = list[0].id
32
+ secret = list[0].secret
33
+ }
34
+ assert_nothing_raised(FlickRaw::FailedResponse) {
35
+ info = flickr.photos.getInfo :photo_id => id, :secret => secret
36
+ }
37
+ assert_respond_to info, :id
38
+ assert_respond_to info, :secret
39
+ assert_respond_to info, :title
40
+ assert_respond_to info, :description
41
+ assert_respond_to info, :owner
42
+ assert_respond_to info, :dates
43
+ assert_respond_to info, :comments
44
+ assert_respond_to info, :tags
45
+ end
46
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: flickraw
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.2
7
- date: 2006-10-24 00:00:00 +02:00
6
+ version: "0.4"
7
+ date: 2007-01-09 00:00:00 +01:00
8
8
  summary: Flickr library with a syntax close to the syntax described on http://www.flickr.com/services/api
9
9
  require_paths:
10
10
  - lib
@@ -35,10 +35,11 @@ files:
35
35
  - README
36
36
  - TODO
37
37
  - rakefile
38
+ - examples/flickr_KDE.rb
38
39
  - examples/auth.rb
39
40
  - examples/interestingness.rb
40
- - examples/flickr_KDE.rb
41
41
  - examples/upload.rb
42
+ - test/test.rb
42
43
  test_files: []
43
44
 
44
45
  rdoc_options: []