flickraw 0.3.2 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/flickr_KDE.rb +2 -2
- data/flickraw_rdoc.rb +14 -15
- data/lib/flickraw.rb +72 -95
- data/rakefile +3 -1
- data/test/test.rb +46 -0
- metadata +4 -3
data/examples/flickr_KDE.rb
CHANGED
@@ -8,8 +8,8 @@ require 'open-uri'
|
|
8
8
|
DESKTOP=1
|
9
9
|
|
10
10
|
list = flickr.interestingness.getList
|
11
|
-
photo = list[rand(
|
12
|
-
sizes = flickr.photos.getSizes(
|
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(
|
60
|
-
# Generated automatically from
|
58
|
+
m.add_token FakedToken.new( %{
|
59
|
+
# Generated automatically from flickr api
|
61
60
|
def #{name}(*args)
|
62
|
-
|
61
|
+
@flickr.call '#{flickr_method}', *args
|
63
62
|
end
|
64
|
-
|
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 << "#{
|
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 =
|
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
|
140
|
-
when /\Aquot\z/ni
|
141
|
-
when /\Agt\z/ni
|
142
|
-
when /\Alt\z/ni
|
143
|
-
|
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.
|
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
|
-
|
44
|
-
|
45
|
-
|
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
|
47
|
+
meta.class_eval { attr_reader k.to_s }
|
85
48
|
end
|
86
49
|
end
|
87
50
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
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 =
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
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?(
|
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
|
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.
|
7
|
-
date:
|
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: []
|