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.
- 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: []
|