flickraw 0.9 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,11 +17,11 @@ This will recreate the documentation by fetching the methods descriptions from f
17
17
 
18
18
  = Features
19
19
 
20
- * Small single file: flickraw.rb is less than 400 lines
21
20
  * Minimal dependencies
22
21
  * Complete support of flickr API. This doesn't require an update of the library
23
22
  * Ruby syntax similar to the flickr api
24
23
  * Flickr authentication
24
+ * HTTPS Support
25
25
  * Photo upload
26
26
  * Proxy support
27
27
  * Flickr URLs helpers
@@ -57,7 +57,7 @@ This will recreate the documentation by fetching the methods descriptions from f
57
57
  FlickRaw.api_key="... Your API key ..."
58
58
  FlickRaw.shared_secret="... Your shared secret ..."
59
59
 
60
- token = flickr.get_request_token(:perms => 'delete')
60
+ token = flickr.get_request_token
61
61
  auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
62
62
 
63
63
  puts "Open this url in your process to complete the authication process : #{auth_url}"
@@ -86,6 +86,10 @@ If the user has already been authenticated, you can reuse the access token and a
86
86
  login = flickr.test.login
87
87
  puts "You are now authenticated as #{login.username}"
88
88
 
89
+ If you need to have several users authenticated at the same time in your application (ex: a public web application) you need to create separate FlickRaw objects since it keeps the authentication data internally.
90
+
91
+ flickr = FlickRaw::Flickr.new
92
+
89
93
  == Upload
90
94
 
91
95
  require 'flickraw'
@@ -103,6 +107,11 @@ If the user has already been authenticated, you can reuse the access token and a
103
107
  require 'flickraw'
104
108
  FlickRaw.proxy = "http://user:pass@proxy.example.com:3129/"
105
109
 
110
+ == Secure endpoints
111
+
112
+ require 'flickraw'
113
+ FlickRaw.secure = true
114
+
106
115
  == Flickr URL Helpers
107
116
 
108
117
  There are some helpers to build flickr urls :
@@ -152,10 +161,3 @@ instead of
152
161
 
153
162
  This way it it doesn't fetch available flickr methods each time it is loaded.
154
163
  The flickraw-cached gem is on rubygems.org and should be up-to-date with regard to flickr api most of the time.
155
-
156
- = Notes
157
-
158
- If you want to use the api authenticated with several user at the same time, you must pass the authentication token explicitely each time.
159
- This is because it is keeping the authentication token internally.
160
- As an alternative, you can create new Flickr objects besides Kernel.flickr which is created for you. Use Flickr.new to this effect.
161
-
@@ -8,7 +8,7 @@ SHARED_SECRET=''
8
8
  FlickRaw.api_key=API_KEY
9
9
  FlickRaw.shared_secret=SHARED_SECRET
10
10
 
11
- token = flickr.get_request_token(:perms => 'delete')
11
+ token = flickr.get_request_token
12
12
  auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
13
13
 
14
14
  puts "Open this url in your process to complete the authication process : #{auth_url}"
@@ -6,17 +6,26 @@ FlickRaw.shared_secret = SHARED_SECRET
6
6
  enable :sessions
7
7
 
8
8
  get '/authenticate' do
9
- token = flickr.get_request_token(:oauth_callback => to('authenticated'))
9
+ token = flickr.get_request_token(:oauth_callback => to('check'))
10
10
  session[:token] = token
11
11
  redirect flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
12
12
  end
13
13
 
14
+ get '/check' do
15
+ token = session.delete :token
16
+ session[:auth_flickr] = @auth_flickr = FlickRaw::Flickr.new
17
+ @auth_flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], params['oauth_verifier'])
18
+
19
+ redirect to('/authenticated')
20
+ end
21
+
14
22
  get '/authenticated' do
15
- token = session[:token]
16
- flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], params['oauth_verifier'])
17
- login = flickr.test.login
23
+ @auth_flickr = session[:auth_flickr]
24
+
25
+ login = @auth_flickr.test.login
18
26
  %{
19
- You are now authenticated as <b>#{login.username}</b>
20
- with token <b>#{flickr.access_token}</b> and secret <b>#{flickr.access_secret}</b>.
27
+ You are now authenticated as <em>#{login.username}</em>
28
+ with token <strong>#{@auth_flickr.access_token}</strong> and secret <strong>#{@auth_flickr.access_secret}</strong>.
21
29
  }
22
30
  end
31
+
@@ -1,7 +1,6 @@
1
1
  require "rdoc"
2
2
  require "rdoc/parser/ruby"
3
3
  require "nokogiri"
4
- require "cgi"
5
4
 
6
5
  FLICKR_API_URL='http://www.flickr.com/services/api'
7
6
 
@@ -78,7 +77,7 @@ module RDoc
78
77
  arguments << "[#{arg.name} "
79
78
  arguments << "<em>(required)</em> " if arg.optional == '0'
80
79
  arguments << "] "
81
- arguments << "#{CGI.unescapeHTML(arg.to_s)}\n"
80
+ arguments << "#{Nokogiri::HTML(arg.to_s).text}\n"
82
81
  }
83
82
  end
84
83
  end
@@ -87,13 +86,13 @@ module RDoc
87
86
  errors = "<b>Error codes</b>\n"
88
87
  info.errors.each {|e|
89
88
  errors << "* #{e.code}: <em>#{e.message}</em>\n\n"
90
- errors << " #{CGI.unescapeHTML e.to_s}\n"
89
+ errors << " #{Nokogiri::HTML(e.to_s).text}\n"
91
90
  }
92
91
  end
93
92
 
94
93
  if info.method.respond_to? :response
95
94
  response = "<b>Returns</b>\n"
96
- raw = CGI.unescapeHTML(info.method.response.to_s)
95
+ raw = Nokogiri::HTML(info.method.response.to_s).text
97
96
  response << raw.lines.collect { |line| line.insert(0, ' ') }.join
98
97
  else
99
98
  response = ''
@@ -1,421 +1,12 @@
1
- # encoding: ascii-8bit
2
- # Copyright (c) 2006 Mael Clerambault <maelclerambault@yahoo.fr>
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all
13
- # copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- require 'net/http'
24
1
  require 'json'
2
+ require 'flickraw/oauth'
3
+ require 'flickraw/request'
4
+ require 'flickraw/response'
5
+ require 'flickraw/api'
25
6
 
26
7
  module FlickRaw
27
- VERSION='0.9'
28
- USER_AGENT = "Flickraw/#{VERSION}"
29
-
30
- FLICKR_OAUTH_REQUEST_TOKEN='http://www.flickr.com/services/oauth/request_token'.freeze
31
- FLICKR_OAUTH_AUTHORIZE='http://www.flickr.com/services/oauth/authorize'.freeze
32
- FLICKR_OAUTH_ACCESS_TOKEN='http://www.flickr.com/services/oauth/access_token'.freeze
33
-
34
- REST_PATH='http://api.flickr.com/services/rest/'.freeze
35
- UPLOAD_PATH='http://api.flickr.com/services/upload/'.freeze
36
- REPLACE_PATH='http://api.flickr.com/services/replace/'.freeze
37
-
38
- PHOTO_SOURCE_URL='http://farm%s.static.flickr.com/%s/%s_%s%s.%s'.freeze
39
- URL_PROFILE='http://www.flickr.com/people/'.freeze
40
- URL_PHOTOSTREAM='http://www.flickr.com/photos/'.freeze
41
- URL_SHORT='http://flic.kr/p/'.freeze
42
-
43
- class OAuth # :nodoc: all
44
- class FailedResponse < StandardError
45
- def initialize(str)
46
- @response = OAuth.parse_response(str)
47
- super(@response['oauth_problem'])
48
- end
49
- end
50
-
51
- class << self
52
- def escape(v); URI.escape(v.to_s, /[^a-zA-Z0-9\-\.\_\~]/) end
53
- def parse_response(text); Hash[text.split("&").map {|s| s.split("=")}] end
54
- end
55
-
56
- attr_accessor :user_agent
57
- attr_reader :proxy
58
- def proxy=(url); @proxy = URI.parse(url || '') end
59
-
60
- def initialize(consumer_key, consumer_secret)
61
- @consumer_key, @consumer_secret = consumer_key, consumer_secret
62
- self.proxy = nil
63
- end
64
-
65
- def sign(method, url, params, token_secret = nil, consumer_secret = @consumer_secret)
66
- params_norm = params.map {|k,v| OAuth.escape(k) + "=" + OAuth.escape(v) }.sort.join("&")
67
- text = method.to_s.upcase + "&" + OAuth.escape(url) + "&" + OAuth.escape(params_norm)
68
- key = consumer_secret.to_s + "&" + token_secret.to_s
69
- digest = OpenSSL::Digest::Digest.new("sha1")
70
- [OpenSSL::HMAC.digest(digest, key, text)].pack('m0').gsub(/\n$/,'')
71
- end
72
-
73
- def authorization_header(url, params)
74
- params_norm = params.map {|k,v| OAuth.escape(k) + "=\"" + OAuth.escape(v) + "\""}.sort.join(", ")
75
- "OAuth realm=\"" + url.to_s + "\", " + params_norm
76
- end
77
-
78
- def gen_timestamp; Time.now.to_i end
79
- def gen_nonce; [OpenSSL::Random.random_bytes(32)].pack('m0').gsub(/\n$/,'') end
80
- def gen_default_params
81
- { :oauth_version => "1.0", :oauth_signature_method => "HMAC-SHA1",
82
- :oauth_consumer_key => @consumer_key, :oauth_nonce => gen_nonce,
83
- :oauth_timestamp => gen_timestamp }
84
- end
85
-
86
- def request_token(url, oauth_params = {})
87
- r = post_form(url, nil, {:oauth_callback => "oob"}.merge(oauth_params))
88
- OAuth.parse_response(r.body)
89
- end
90
-
91
- def authorize_url(url, oauth_params = {})
92
- params_norm = oauth_params.map {|k,v| OAuth.escape(k) + "=" + OAuth.escape(v)}.sort.join("&")
93
- url = URI.parse(url)
94
- url.query = url.query ? url.query + "&" + params_norm : params_norm
95
- url.to_s
96
- end
97
-
98
- def access_token(url, token_secret, oauth_params = {})
99
- r = post_form(url, token_secret, oauth_params)
100
- OAuth.parse_response(r.body)
101
- end
102
-
103
- def post_form(url, token_secret, oauth_params = {}, params = {})
104
- oauth_params = gen_default_params.merge(oauth_params)
105
- oauth_params[:oauth_signature] = sign(:post, url, params.merge(oauth_params), token_secret)
106
- url = URI.parse(url)
107
- r = Net::HTTP.start(url.host, url.port, @proxy.host, @proxy.port, @proxy.user, @proxy.password) { |http|
108
- request = Net::HTTP::Post.new(url.path)
109
- request['User-Agent'] = @user_agent if @user_agent
110
- request['Authorization'] = authorization_header(url, oauth_params)
111
- request.form_data = params
112
- http.request(request)
113
- }
114
-
115
- raise FailedResponse.new(r.body) if r.is_a? Net::HTTPClientError
116
- r
117
- end
118
-
119
- def post_multipart(url, token_secret, oauth_params = {}, params = {})
120
- oauth_params = gen_default_params.merge(oauth_params)
121
- params_signed = params.reject {|k,v| v.is_a? File}.merge(oauth_params)
122
- oauth_params[:oauth_signature] = sign(:post, url, params_signed, token_secret)
123
- url = URI.parse(url)
124
- r = Net::HTTP.start(url.host, url.port, @proxy.host, @proxy.port, @proxy.user, @proxy.password) { |http|
125
- boundary = "FlickRaw#{gen_nonce}"
126
- request = Net::HTTP::Post.new(url.path)
127
- request['User-Agent'] = @user_agent if @user_agent
128
- request['Content-type'] = "multipart/form-data, boundary=#{boundary}"
129
- request['Authorization'] = authorization_header(url, oauth_params)
130
-
131
- request.body = ''
132
- params.each { |k, v|
133
- if v.is_a? File
134
- basename = File.basename(v.path).to_s
135
- basename = basename.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
136
- filename = basename
137
- request.body << "--#{boundary}\r\n" <<
138
- "Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" <<
139
- "Content-Transfer-Encoding: binary\r\n" <<
140
- "Content-Type: image/jpeg\r\n\r\n" <<
141
- v.read << "\r\n"
142
- else
143
- request.body << "--#{boundary}\r\n" <<
144
- "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n" <<
145
- "#{v}\r\n"
146
- end
147
- }
148
-
149
- request.body << "--#{boundary}--"
150
- http.request(request)
151
- }
152
-
153
- raise FailedResponse.new(r.body) if r.is_a? Net::HTTPClientError
154
- r
155
- end
156
- end
157
-
158
- class Response
159
- def self.build(h, type) # :nodoc:
160
- if h.is_a? Response
161
- h
162
- elsif type =~ /s$/ and (a = h[$`]).is_a? Array
163
- ResponseList.new(h, type, a.collect {|e| Response.build(e, $`)})
164
- elsif h.keys == ["_content"]
165
- h["_content"]
166
- else
167
- Response.new(h, type)
168
- end
169
- end
170
-
171
- attr_reader :flickr_type
172
- def initialize(h, type) # :nodoc:
173
- @flickr_type, @h = type, {}
174
- methods = "class << self;"
175
- h.each {|k,v|
176
- @h[k] = case v
177
- when Hash then Response.build(v, k)
178
- when Array then v.collect {|e| Response.build(e, k)}
179
- else v
180
- end
181
- methods << "def #{k}; @h['#{k}'] end;"
182
- }
183
- eval methods << "end"
184
- end
185
- def [](k); @h[k] end
186
- def to_s; @h["_content"] || super end
187
- def inspect; @h.inspect end
188
- def to_hash; @h end
189
- def marshal_dump; [@h, @flickr_type] end
190
- def marshal_load(data); initialize(*data) end
191
- end
192
-
193
- class ResponseList < Response
194
- include Enumerable
195
- def initialize(h, t, a); super(h, t); @a = a end
196
- def [](k); k.is_a?(Fixnum) ? @a[k] : super(k) end
197
- def each; @a.each{|e| yield e} end
198
- def to_a; @a end
199
- def inspect; @a.inspect end
200
- def size; @a.size end
201
- def marshal_dump; [@h, @flickr_type, @a] end
202
- alias length size
203
- end
204
-
205
- class FailedResponse < StandardError
206
- attr_reader :code
207
- alias :msg :message
208
- def initialize(msg, code, req)
209
- @code = code
210
- super("'#{req}' - #{msg}")
211
- end
212
- end
213
-
214
- class Request
215
- def initialize(flickr = nil) # :nodoc:
216
- @flickr = flickr
217
-
218
- self.class.flickr_objects.each {|name|
219
- klass = self.class.const_get name.capitalize
220
- instance_variable_set "@#{name}", klass.new(@flickr)
221
- }
222
- end
223
-
224
- def self.build_request(req) # :nodoc:
225
- method_nesting = req.split '.'
226
- raise "'#{@name}' : Method name mismatch" if method_nesting.shift != request_name.split('.').last
227
-
228
- if method_nesting.size > 1
229
- name = method_nesting.first
230
- class_name = name.capitalize
231
- if flickr_objects.include? name
232
- klass = const_get(class_name)
233
- else
234
- klass = Class.new Request
235
- const_set(class_name, klass)
236
- attr_reader name
237
- flickr_objects << name
238
- end
239
-
240
- klass.build_request method_nesting.join('.')
241
- else
242
- req = method_nesting.first
243
- module_eval %{
244
- def #{req}(*args, &block)
245
- @flickr.call("#{request_name}.#{req}", *args, &block)
246
- end
247
- }
248
- flickr_methods << req
249
- end
250
- end
251
-
252
- # List of the flickr subobjects of this object
253
- def self.flickr_objects; @flickr_objects ||= [] end
254
-
255
- # List of the flickr methods of this object
256
- def self.flickr_methods; @flickr_methods ||= [] end
257
-
258
- # Returns the prefix of the request corresponding to this class.
259
- def self.request_name; name.downcase.gsub(/::/, '.').sub(/[^\.]+\./, '') end
260
- end
261
-
262
- # Root class of the flickr api hierarchy.
263
- class Flickr < Request
264
- # Authenticated access token
265
- attr_accessor :access_token
266
-
267
- # Authenticated access token secret
268
- attr_accessor :access_secret
269
-
270
- def self.build(methods); methods.each { |m| build_request m } end
271
-
272
- def initialize # :nodoc:
273
- raise "No API key or secret defined !" if FlickRaw.api_key.nil? or FlickRaw.shared_secret.nil?
274
- @oauth_consumer = OAuth.new(FlickRaw.api_key, FlickRaw.shared_secret)
275
- @oauth_consumer.proxy = FlickRaw.proxy
276
- @oauth_consumer.user_agent = USER_AGENT
277
-
278
- Flickr.build(call('flickr.reflection.getMethods')) if Flickr.flickr_objects.empty?
279
- super self
280
- end
281
-
282
- # This is the central method. It does the actual request to the flickr server.
283
- #
284
- # Raises FailedResponse if the response status is _failed_.
285
- def call(req, args={}, &block)
286
- http_response = @oauth_consumer.post_form(REST_PATH, @access_secret, {:oauth_token => @access_token}, build_args(args, req))
287
- process_response(req, http_response.body)
288
- end
289
-
290
- # Get an oauth request token.
291
- #
292
- # token = flickr.get_request_token(:oauth_callback => "http://example.com")
293
- def get_request_token(args = {})
294
- request_token = @oauth_consumer.request_token(FLICKR_OAUTH_REQUEST_TOKEN, args)
295
- end
296
-
297
- # Get the oauth authorize url.
298
- #
299
- # auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
300
- def get_authorize_url(token, args = {})
301
- @oauth_consumer.authorize_url(FLICKR_OAUTH_AUTHORIZE, args.merge(:oauth_token => token))
302
- end
303
-
304
- # Get an oauth access token.
305
- #
306
- # flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], oauth_verifier)
307
- def get_access_token(token, secret, verify)
308
- access_token = @oauth_consumer.access_token(FLICKR_OAUTH_ACCESS_TOKEN, secret, :oauth_token => token, :oauth_verifier => verify)
309
- @access_token, @access_secret = access_token['oauth_token'], access_token['oauth_token_secret']
310
- access_token
311
- end
312
-
313
- # Use this to upload the photo in _file_.
314
- #
315
- # flickr.upload_photo '/path/to/the/photo', :title => 'Title', :description => 'This is the description'
316
- #
317
- # See http://www.flickr.com/services/api/upload.api.html for more information on the arguments.
318
- def upload_photo(file, args={}); upload_flickr(UPLOAD_PATH, file, args) end
319
-
320
- # Use this to replace the photo with :photo_id with the photo in _file_.
321
- #
322
- # flickr.replace_photo '/path/to/the/photo', :photo_id => id
323
- #
324
- # See http://www.flickr.com/services/api/replace.api.html for more information on the arguments.
325
- def replace_photo(file, args={}); upload_flickr(REPLACE_PATH, file, args) end
326
-
327
- private
328
- def build_args(args={}, method = nil)
329
- full_args = {'format' => 'json', :nojsoncallback => "1"}
330
- full_args['method'] = method if method
331
- args.each {|k, v|
332
- v = v.to_s.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
333
- full_args[k.to_s] = v
334
- }
335
- full_args
336
- end
337
-
338
- def process_response(req, response)
339
- if response =~ /^<\?xml / # upload_photo returns xml data whatever we ask
340
- if response[/stat="(\w+)"/, 1] == 'fail'
341
- msg = response[/msg="([^"]+)"/, 1]
342
- code = response[/code="([^"]+)"/, 1]
343
- raise FailedResponse.new(msg, code, req)
344
- end
345
-
346
- type = response[/<(\w+)/, 1]
347
- h = {
348
- "secret" => response[/secret="([^"]+)"/, 1],
349
- "originalsecret" => response[/originalsecret="([^"]+)"/, 1],
350
- "_content" => response[/>([^<]+)<\//, 1]
351
- }.delete_if {|k,v| v.nil? }
352
-
353
- Response.build h, type
354
- else
355
- json = JSON.load(response.empty? ? "{}" : response)
356
- raise FailedResponse.new(json['message'], json['code'], req) if json.delete('stat') == 'fail'
357
- type, json = json.to_a.first if json.size == 1 and json.all? {|k,v| v.is_a? Hash}
358
-
359
- Response.build json, type
360
- end
361
- end
362
-
363
- def upload_flickr(method, file, args={})
364
- args = build_args(args)
365
- args['photo'] = open(file, 'rb')
366
- http_response = @oauth_consumer.post_multipart(method, @access_secret, {:oauth_token => @access_token}, args)
367
- process_response(method, http_response.body)
368
- end
369
- end
370
-
371
- class << self
372
- # Your flickr API key, see http://www.flickr.com/services/api/keys for more information
373
- attr_accessor :api_key
374
-
375
- # The shared secret of _api_key_, see http://www.flickr.com/services/api/keys for more information
376
- attr_accessor :shared_secret
377
-
378
- # Use a proxy
379
- attr_accessor :proxy
380
-
381
- BASE58_ALPHABET="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".freeze
382
- def base58(id)
383
- id = id.to_i
384
- alphabet = BASE58_ALPHABET.split(//)
385
- base = alphabet.length
386
- begin
387
- id, m = id.divmod(base)
388
- r = alphabet[m] + (r || '')
389
- end while id > 0
390
- r
391
- end
392
-
393
- def url(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "", "jpg"] end
394
- def url_m(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_m", "jpg"] end
395
- def url_s(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_s", "jpg"] end
396
- def url_t(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_t", "jpg"] end
397
- def url_b(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_b", "jpg"] end
398
- def url_z(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_z", "jpg"] end
399
- def url_o(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.originalsecret, "_o", r.originalformat] end
400
- def url_profile(r); URL_PROFILE + (r.owner.respond_to?(:nsid) ? r.owner.nsid : r.owner) + "/" end
401
- def url_photopage(r); url_photostream(r) + r.id end
402
- def url_photosets(r); url_photostream(r) + "sets/" end
403
- def url_photoset(r); url_photosets(r) + r.id end
404
- def url_short(r); URL_SHORT + base58(r.id) end
405
- def url_short_m(r); URL_SHORT + "img/" + base58(r.id) + "_m.jpg" end
406
- def url_short_s(r); URL_SHORT + "img/" + base58(r.id) + ".jpg" end
407
- def url_short_t(r); URL_SHORT + "img/" + base58(r.id) + "_t.jpg" end
408
- def url_photostream(r)
409
- URL_PHOTOSTREAM +
410
- if r.respond_to?(:pathalias) and r.pathalias
411
- r.pathalias
412
- elsif r.owner.respond_to?(:nsid)
413
- r.owner.nsid
414
- else
415
- r.owner
416
- end + "/"
417
- end
418
- end
8
+ VERSION='0.9.2'
9
+ USER_AGENT = "FlickRaw/#{VERSION}"
419
10
  end
420
11
 
421
12
  # Use this to access the flickr API easily. You can type directly the flickr requests as they are described on the flickr website.
@@ -0,0 +1,198 @@
1
+ module FlickRaw
2
+ END_POINT='http://api.flickr.com/services'.freeze
3
+ END_POINT2='http://www.flickr.com/services'.freeze
4
+ END_POINT_SECURE='https://secure.flickr.com/services'.freeze
5
+
6
+ FLICKR_OAUTH_REQUEST_TOKEN=(END_POINT2 + '/oauth/request_token').freeze
7
+ FLICKR_OAUTH_AUTHORIZE=(END_POINT2 + '/oauth/authorize').freeze
8
+ FLICKR_OAUTH_ACCESS_TOKEN=(END_POINT2 + '/oauth/access_token').freeze
9
+
10
+ FLICKR_OAUTH_REQUEST_TOKEN_SECURE=(END_POINT_SECURE + '/oauth/request_token').freeze
11
+ FLICKR_OAUTH_AUTHORIZE_SECURE=(END_POINT_SECURE + '/oauth/authorize').freeze
12
+ FLICKR_OAUTH_ACCESS_TOKEN_SECURE=(END_POINT_SECURE + '/oauth/access_token').freeze
13
+
14
+ REST_PATH=(END_POINT + '/rest/').freeze
15
+ UPLOAD_PATH=(END_POINT + '/upload/').freeze
16
+ REPLACE_PATH=(END_POINT + '/replace/').freeze
17
+
18
+ REST_PATH_SECURE=(END_POINT_SECURE + '/rest/').freeze
19
+ UPLOAD_PATH_SECURE=(END_POINT_SECURE + '/upload/').freeze
20
+ REPLACE_PATH_SECURE=(END_POINT_SECURE + '/replace/').freeze
21
+
22
+ PHOTO_SOURCE_URL='http://farm%s.static.flickr.com/%s/%s_%s%s.%s'.freeze
23
+ URL_PROFILE='http://www.flickr.com/people/'.freeze
24
+ URL_PHOTOSTREAM='http://www.flickr.com/photos/'.freeze
25
+ URL_SHORT='http://flic.kr/p/'.freeze
26
+
27
+ # Root class of the flickr api hierarchy.
28
+ class Flickr < Request
29
+ # Authenticated access token
30
+ attr_accessor :access_token
31
+
32
+ # Authenticated access token secret
33
+ attr_accessor :access_secret
34
+
35
+ def self.build(methods); methods.each { |m| build_request m } end
36
+
37
+ def initialize # :nodoc:
38
+ raise "No API key or secret defined !" if FlickRaw.api_key.nil? or FlickRaw.shared_secret.nil?
39
+ @oauth_consumer = OAuthClient.new(FlickRaw.api_key, FlickRaw.shared_secret)
40
+ @oauth_consumer.proxy = FlickRaw.proxy
41
+ @oauth_consumer.user_agent = USER_AGENT
42
+
43
+ Flickr.build(call('flickr.reflection.getMethods')) if Flickr.flickr_objects.empty?
44
+ super self
45
+ end
46
+
47
+ # This is the central method. It does the actual request to the flickr server.
48
+ #
49
+ # Raises FailedResponse if the response status is _failed_.
50
+ def call(req, args={}, &block)
51
+ rest_path = FlickRaw.secure ? REST_PATH_SECURE : REST_PATH
52
+ http_response = @oauth_consumer.post_form(rest_path, @access_secret, {:oauth_token => @access_token}, build_args(args, req))
53
+ process_response(req, http_response.body)
54
+ end
55
+
56
+ # Get an oauth request token.
57
+ #
58
+ # token = flickr.get_request_token(:oauth_callback => "http://example.com")
59
+ def get_request_token(args = {})
60
+ flickr_oauth_request_token = FlickRaw.secure ? FLICKR_OAUTH_REQUEST_TOKEN_SECURE : FLICKR_OAUTH_REQUEST_TOKEN
61
+ @oauth_consumer.request_token(flickr_oauth_request_token, args)
62
+ end
63
+
64
+ # Get the oauth authorize url.
65
+ #
66
+ # auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
67
+ def get_authorize_url(token, args = {})
68
+ flickr_oauth_authorize = FlickRaw.secure ? FLICKR_OAUTH_AUTHORIZE_SECURE : FLICKR_OAUTH_AUTHORIZE
69
+ @oauth_consumer.authorize_url(flickr_oauth_authorize, args.merge(:oauth_token => token))
70
+ end
71
+
72
+ # Get an oauth access token.
73
+ #
74
+ # flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], oauth_verifier)
75
+ def get_access_token(token, secret, verify)
76
+ flickr_oauth_access_token = FlickRaw.secure ? FLICKR_OAUTH_ACCESS_TOKEN_SECURE : FLICKR_OAUTH_ACCESS_TOKEN
77
+ access_token = @oauth_consumer.access_token(flickr_oauth_access_token, secret, :oauth_token => token, :oauth_verifier => verify)
78
+ @access_token, @access_secret = access_token['oauth_token'], access_token['oauth_token_secret']
79
+ access_token
80
+ end
81
+
82
+ # Use this to upload the photo in _file_.
83
+ #
84
+ # flickr.upload_photo '/path/to/the/photo', :title => 'Title', :description => 'This is the description'
85
+ #
86
+ # See http://www.flickr.com/services/api/upload.api.html for more information on the arguments.
87
+ def upload_photo(file, args={})
88
+ upload_path = FlickRaw.secure ? UPLOAD_PATH_SECURE : UPLOAD_PATH
89
+ upload_flickr(upload_path, file, args)
90
+ end
91
+
92
+ # Use this to replace the photo with :photo_id with the photo in _file_.
93
+ #
94
+ # flickr.replace_photo '/path/to/the/photo', :photo_id => id
95
+ #
96
+ # See http://www.flickr.com/services/api/replace.api.html for more information on the arguments.
97
+ def replace_photo(file, args={})
98
+ replace_path = FlickRaw.secure ? REPLACE_PATH_SECURE : REPLACE_PATH
99
+ upload_flickr(replace_path, file, args)
100
+ end
101
+
102
+ private
103
+ def build_args(args={}, method = nil)
104
+ full_args = {'format' => 'json', 'nojsoncallback' => '1'}
105
+ full_args['method'] = method if method
106
+ args.each {|k, v|
107
+ v = v.to_s.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
108
+ full_args[k.to_s] = v
109
+ }
110
+ full_args
111
+ end
112
+
113
+ def process_response(req, response)
114
+ if response =~ /^<\?xml / # upload_photo returns xml data whatever we ask
115
+ if response[/stat="(\w+)"/, 1] == 'fail'
116
+ msg = response[/msg="([^"]+)"/, 1]
117
+ code = response[/code="([^"]+)"/, 1]
118
+ raise FailedResponse.new(msg, code, req)
119
+ end
120
+
121
+ type = response[/<(\w+)/, 1]
122
+ h = {
123
+ "secret" => response[/secret="([^"]+)"/, 1],
124
+ "originalsecret" => response[/originalsecret="([^"]+)"/, 1],
125
+ "_content" => response[/>([^<]+)<\//, 1]
126
+ }.delete_if {|k,v| v.nil? }
127
+
128
+ Response.build h, type
129
+ else
130
+ json = JSON.load(response.empty? ? "{}" : response)
131
+ raise FailedResponse.new(json['message'], json['code'], req) if json.delete('stat') == 'fail'
132
+ type, json = json.to_a.first if json.size == 1 and json.all? {|k,v| v.is_a? Hash}
133
+
134
+ Response.build json, type
135
+ end
136
+ end
137
+
138
+ def upload_flickr(method, file, args={})
139
+ args = build_args(args)
140
+ args['photo'] = open(file, 'rb')
141
+
142
+ http_response = @oauth_consumer.post_multipart(method, @access_secret, {:oauth_token => @access_token}, args)
143
+ process_response(method, http_response.body)
144
+ end
145
+ end
146
+
147
+ class << self
148
+ # Your flickr API key, see http://www.flickr.com/services/api/keys for more information
149
+ attr_accessor :api_key
150
+
151
+ # The shared secret of _api_key_, see http://www.flickr.com/services/api/keys for more information
152
+ attr_accessor :shared_secret
153
+
154
+ # Use a proxy
155
+ attr_accessor :proxy
156
+
157
+ # Use ssl connection
158
+ attr_accessor :secure
159
+
160
+ BASE58_ALPHABET="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".freeze
161
+ def base58(id)
162
+ id = id.to_i
163
+ alphabet = BASE58_ALPHABET.split(//)
164
+ base = alphabet.length
165
+ begin
166
+ id, m = id.divmod(base)
167
+ r = alphabet[m] + (r || '')
168
+ end while id > 0
169
+ r
170
+ end
171
+
172
+ def url(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "", "jpg"] end
173
+ def url_m(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_m", "jpg"] end
174
+ def url_s(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_s", "jpg"] end
175
+ def url_t(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_t", "jpg"] end
176
+ def url_b(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_b", "jpg"] end
177
+ def url_z(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.secret, "_z", "jpg"] end
178
+ def url_o(r); PHOTO_SOURCE_URL % [r.farm, r.server, r.id, r.originalsecret, "_o", r.originalformat] end
179
+ def url_profile(r); URL_PROFILE + (r.owner.respond_to?(:nsid) ? r.owner.nsid : r.owner) + "/" end
180
+ def url_photopage(r); url_photostream(r) + r.id end
181
+ def url_photosets(r); url_photostream(r) + "sets/" end
182
+ def url_photoset(r); url_photosets(r) + r.id end
183
+ def url_short(r); URL_SHORT + base58(r.id) end
184
+ def url_short_m(r); URL_SHORT + "img/" + base58(r.id) + "_m.jpg" end
185
+ def url_short_s(r); URL_SHORT + "img/" + base58(r.id) + ".jpg" end
186
+ def url_short_t(r); URL_SHORT + "img/" + base58(r.id) + "_t.jpg" end
187
+ def url_photostream(r)
188
+ URL_PHOTOSTREAM +
189
+ if r.respond_to?(:pathalias) and r.pathalias
190
+ r.pathalias
191
+ elsif r.owner.respond_to?(:nsid)
192
+ r.owner.nsid
193
+ else
194
+ r.owner
195
+ end + "/"
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,150 @@
1
+ require 'openssl'
2
+ require 'net/http'
3
+
4
+ module FlickRaw
5
+ class OAuthClient
6
+ class UnknownSignatureMethod < StandardError; end
7
+ class FailedResponse < StandardError
8
+ def initialize(str)
9
+ @response = OAuthClient.parse_response(str)
10
+ super(@response['oauth_problem'])
11
+ end
12
+ end
13
+
14
+ class << self
15
+ def escape(v); URI.escape(v.to_s, /[^a-zA-Z0-9\-\.\_\~]/) end
16
+ def parse_response(text); Hash[text.split("&").map {|s| s.split("=")}] end
17
+
18
+ def signature_base_string(method, url, params)
19
+ params_norm = params.map {|k,v| escape(k) + "=" + escape(v)}.sort.join("&")
20
+ method.to_s.upcase + "&" + escape(url) + "&" + escape(params_norm)
21
+ end
22
+
23
+ def sign_plaintext(method, url, params, token_secret, consumer_secret)
24
+ escape(consumer_secret) + "&" + escape(token_secret)
25
+ end
26
+
27
+ def sign_rsa_sha1(method, url, params, token_secret, consumer_secret)
28
+ text = signature_base_string(method, url, params)
29
+ key = OpenSSL::PKey::RSA.new(consumer_secret)
30
+ digest = OpenSSL::Digest::Digest.new("sha1")
31
+ [key.sign(digest, text)].pack('m0').gsub(/\n$/,'')
32
+ end
33
+
34
+ def sign_hmac_sha1(method, url, params, token_secret, consumer_secret)
35
+ text = signature_base_string(method, url, params)
36
+ key = escape(consumer_secret) + "&" + escape(token_secret)
37
+ digest = OpenSSL::Digest::Digest.new("sha1")
38
+ [OpenSSL::HMAC.digest(digest, key, text)].pack('m0').gsub(/\n$/,'')
39
+ end
40
+
41
+ def gen_timestamp; Time.now.to_i end
42
+ def gen_nonce; [OpenSSL::Random.random_bytes(32)].pack('m0').gsub(/\n$/,'') end
43
+ def gen_default_params
44
+ { :oauth_version => "1.0", :oauth_signature_method => "HMAC-SHA1",
45
+ :oauth_nonce => gen_nonce, :oauth_timestamp => gen_timestamp }
46
+ end
47
+
48
+ def authorization_header(url, params)
49
+ params_norm = params.map {|k,v| %(#{escape(k)}="#{escape(v)}")}.sort.join(", ")
50
+ %(OAuth realm="#{url.to_s}", #{params_norm})
51
+ end
52
+ end
53
+
54
+ attr_accessor :user_agent
55
+ attr_reader :proxy
56
+ def proxy=(url); @proxy = URI.parse(url || '') end
57
+
58
+ def initialize(consumer_key, consumer_secret)
59
+ @consumer_key, @consumer_secret = consumer_key, consumer_secret
60
+ self.proxy = nil
61
+ end
62
+
63
+ def request_token(url, oauth_params = {})
64
+ r = post(url, nil, {:oauth_callback => "oob"}.merge(oauth_params))
65
+ OAuthClient.parse_response(r.body)
66
+ end
67
+
68
+ def authorize_url(url, oauth_params = {})
69
+ params_norm = oauth_params.map {|k,v| OAuthClient.escape(k) + "=" + OAuthClient.escape(v)}.sort.join("&")
70
+ url = URI.parse(url)
71
+ url.query = url.query ? url.query + "&" + params_norm : params_norm
72
+ url.to_s
73
+ end
74
+
75
+ def access_token(url, token_secret, oauth_params = {})
76
+ r = post_form(url, token_secret, oauth_params)
77
+ OAuthClient.parse_response(r.body)
78
+ end
79
+
80
+ def post_form(url, token_secret, oauth_params = {}, params = {})
81
+ post(url, token_secret, oauth_params, params) {|request| request.form_data = params}
82
+ end
83
+
84
+ def post_multipart(url, token_secret, oauth_params = {}, params = {})
85
+ post(url, token_secret, oauth_params, params) {|request|
86
+ boundary = "FlickRaw#{OAuthClient.gen_nonce}"
87
+ request['Content-type'] = "multipart/form-data, boundary=#{boundary}"
88
+
89
+ request.body = ''
90
+ params.each { |k, v|
91
+ if v.is_a? File
92
+ basename = File.basename(v.path).to_s
93
+ basename = basename.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
94
+ filename = basename
95
+ request.body << "--#{boundary}\r\n" <<
96
+ "Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" <<
97
+ "Content-Transfer-Encoding: binary\r\n" <<
98
+ "Content-Type: image/jpeg\r\n\r\n" <<
99
+ v.read << "\r\n"
100
+ else
101
+ request.body << "--#{boundary}\r\n" <<
102
+ "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n" <<
103
+ "#{v}\r\n"
104
+ end
105
+ }
106
+
107
+ request.body << "--#{boundary}--"
108
+ }
109
+ end
110
+
111
+ private
112
+ def sign(method, url, params, token_secret = nil)
113
+ case params[:oauth_signature_method]
114
+ when "HMAC-SHA1"
115
+ OAuthClient.sign_hmac_sha1(method, url, params, token_secret, @consumer_secret)
116
+ when "RSA-SHA1"
117
+ OAuthClient.sign_rsa_sha1(method, url, params, token_secret, @consumer_secret)
118
+ when "PLAINTEXT"
119
+ OAuthClient.sign_plaintext(method, url, params, token_secret, @consumer_secret)
120
+ else
121
+ raise UnknownSignatureMethod, params[:oauth_signature_method]
122
+ end
123
+ end
124
+
125
+ def post(url, token_secret, oauth_params, params)
126
+ url = URI.parse(url)
127
+ default_oauth_params = OAuthClient.gen_default_params
128
+ default_oauth_params[:oauth_consumer_key] = @consumer_key
129
+ default_oauth_params[:oauth_signature_method] = "PLAINTEXT" if url.scheme == 'https'
130
+ oauth_params = default_oauth_params.merge(oauth_params)
131
+ params_signed = params.reject {|k,v| v.is_a? File}.merge(oauth_params)
132
+ oauth_params[:oauth_signature] = sign(:post, url, params_signed, token_secret)
133
+
134
+ r = Net::HTTP.start(url.host, url.port,
135
+ @proxy.host, @proxy.port, @proxy.user, @proxy.password,
136
+ :use_ssl => url.scheme == 'https') { |http|
137
+ request = Net::HTTP::Post.new(url.path)
138
+ request['User-Agent'] = @user_agent if @user_agent
139
+ request['Authorization'] = OAuthClient.authorization_header(url, oauth_params)
140
+
141
+ yield request
142
+ http.request(request)
143
+ }
144
+
145
+ raise FailedResponse.new(r.body) if r.is_a? Net::HTTPClientError
146
+ r
147
+ end
148
+ end
149
+
150
+ end
@@ -0,0 +1,50 @@
1
+ module FlickRaw
2
+ class Request
3
+ def initialize(flickr = nil) # :nodoc:
4
+ @flickr = flickr
5
+
6
+ self.class.flickr_objects.each {|name|
7
+ klass = self.class.const_get name.capitalize
8
+ instance_variable_set "@#{name}", klass.new(@flickr)
9
+ }
10
+ end
11
+
12
+ def self.build_request(req) # :nodoc:
13
+ method_nesting = req.split '.'
14
+ raise "'#{@name}' : Method name mismatch" if method_nesting.shift != request_name.split('.').last
15
+
16
+ if method_nesting.size > 1
17
+ name = method_nesting.first
18
+ class_name = name.capitalize
19
+ if flickr_objects.include? name
20
+ klass = const_get(class_name)
21
+ else
22
+ klass = Class.new Request
23
+ const_set(class_name, klass)
24
+ attr_reader name
25
+ flickr_objects << name
26
+ end
27
+
28
+ klass.build_request method_nesting.join('.')
29
+ else
30
+ req = method_nesting.first
31
+ module_eval %{
32
+ def #{req}(*args, &block)
33
+ @flickr.call("#{request_name}.#{req}", *args, &block)
34
+ end
35
+ }
36
+ flickr_methods << req
37
+ end
38
+ end
39
+
40
+ # List the flickr subobjects of this object
41
+ def self.flickr_objects; @flickr_objects ||= [] end
42
+
43
+ # List the flickr methods of this object
44
+ def self.flickr_methods; @flickr_methods ||= [] end
45
+
46
+ # Returns the prefix of the request corresponding to this class.
47
+ def self.request_name; name.downcase.gsub(/::/, '.').sub(/[^\.]+\./, '') end
48
+ end
49
+
50
+ end
@@ -0,0 +1,58 @@
1
+ module FlickRaw
2
+ class Response
3
+ def self.build(h, type) # :nodoc:
4
+ if h.is_a? Response
5
+ h
6
+ elsif type =~ /s$/ and (a = h[$`]).is_a? Array
7
+ ResponseList.new(h, type, a.collect {|e| Response.build(e, $`)})
8
+ elsif h.keys == ["_content"]
9
+ h["_content"]
10
+ else
11
+ Response.new(h, type)
12
+ end
13
+ end
14
+
15
+ attr_reader :flickr_type
16
+ def initialize(h, type) # :nodoc:
17
+ @flickr_type, @h = type, {}
18
+ methods = "class << self;"
19
+ h.each {|k,v|
20
+ @h[k] = case v
21
+ when Hash then Response.build(v, k)
22
+ when Array then v.collect {|e| Response.build(e, k)}
23
+ else v
24
+ end
25
+ methods << "def #{k}; @h['#{k}'] end;"
26
+ }
27
+ eval methods << "end"
28
+ end
29
+ def [](k); @h[k] end
30
+ def to_s; @h["_content"] || super end
31
+ def inspect; @h.inspect end
32
+ def to_hash; @h end
33
+ def marshal_dump; [@h, @flickr_type] end
34
+ def marshal_load(data); initialize(*data) end
35
+ end
36
+
37
+ class ResponseList < Response
38
+ include Enumerable
39
+ def initialize(h, t, a); super(h, t); @a = a end
40
+ def [](k); k.is_a?(Fixnum) ? @a[k] : super(k) end
41
+ def each; @a.each{|e| yield e} end
42
+ def to_a; @a end
43
+ def inspect; @a.inspect end
44
+ def size; @a.size end
45
+ def marshal_dump; [@h, @flickr_type, @a] end
46
+ alias length size
47
+ end
48
+
49
+ class FailedResponse < StandardError
50
+ attr_reader :code
51
+ alias :msg :message
52
+ def initialize(msg, code, req)
53
+ @code = code
54
+ super("'#{req}' - #{msg}")
55
+ end
56
+ end
57
+
58
+ end
data/rakefile CHANGED
@@ -1,12 +1,15 @@
1
1
  require 'rake/clean'
2
- require 'rake/rdoctask'
2
+ require 'rdoc/task'
3
3
  require 'rake/testtask'
4
4
 
5
- lib = File.dirname(__FILE__)
5
+ lib = File.expand_path('../lib/', __FILE__)
6
6
  $:.unshift lib unless $:.include?(lib)
7
7
 
8
- require 'lib/flickraw'
9
- require 'flickraw_rdoc' if RUBY_VERSION >= "1.9"
8
+ require 'flickraw'
9
+ require './flickraw_rdoc' if RUBY_VERSION >= "1.9"
10
+
11
+ FlickRaw.api_key = ENV['FLICKRAW_API_KEY']
12
+ FlickRaw.shared_secret = ENV['FLICKRAW_SHARED_SECRET']
10
13
 
11
14
  Rake::RDocTask.new do |rd|
12
15
  rd.main = "README.rdoc"
@@ -0,0 +1,10 @@
1
+ lib = File.expand_path('../../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'flickraw'
5
+
6
+ FlickRaw.api_key = ENV['FLICKRAW_API_KEY']
7
+ FlickRaw.shared_secret = ENV['FLICKRAW_SHARED_SECRET']
8
+
9
+ flickr.access_token = ENV['FLICKRAW_ACCESS_TOKEN']
10
+ flickr.access_secret = ENV['FLICKRAW_ACCESS_SECRET']
@@ -1,13 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- lib = File.expand_path('../../lib/', __FILE__)
3
+ lib = File.dirname(__FILE__)
4
4
  $:.unshift lib unless $:.include?(lib)
5
5
 
6
6
  require 'test/unit'
7
- require 'flickraw'
8
-
9
- # FlickRaw.shared_secret = # Shared secret
10
- # flickr.auth.checkToken :auth_token => # Auth token
7
+ require 'helper'
11
8
 
12
9
  class Basic < Test::Unit::TestCase
13
10
  def test_request
@@ -335,7 +332,13 @@ class Basic < Test::Unit::TestCase
335
332
  def test_photos_getSizes
336
333
  info = flickr.photos.getSizes :photo_id => "3839885270"
337
334
  assert_equal "http://www.flickr.com/photos/41650587@N02/3839885270/sizes/l/", info.find {|f| f.label == "Large"}.url
338
- assert_equal "http://farm3.static.flickr.com/2485/3839885270_6fb8b54e06_b.jpg", info.find {|f| f.label == "Large"}.source
335
+ if FlickRaw.secure
336
+ source = "https://farm3.static.flickr.com/2485/3839885270_6fb8b54e06_b.jpg"
337
+ else
338
+ source = "http://farm3.static.flickr.com/2485/3839885270_6fb8b54e06_b.jpg"
339
+ end
340
+
341
+ assert_equal source, info.find {|f| f.label == "Large"}.source
339
342
  end
340
343
 
341
344
  def test_photos_search
@@ -1,19 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- lib = File.expand_path('../../lib/', __FILE__)
3
+ lib = File.dirname(__FILE__)
4
4
  $:.unshift lib unless $:.include?(lib)
5
5
 
6
6
  require 'test/unit'
7
- require 'flickraw'
8
-
9
- # FlickRaw.api_key = # API key
10
- # FlickRaw.shared_secret = # Shared secret
11
- # flickr.access_token = # Auth token
12
- # flickr.access_secret = # Auth token secret
7
+ require 'helper'
13
8
 
14
9
  class Upload < Test::Unit::TestCase
15
10
  def test_upload
16
-
17
11
  path = File.dirname(__FILE__) + '/image testée.jpg'
18
12
  u = info = nil
19
13
  title = "Titre de l'image testée"
metadata CHANGED
@@ -1,11 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flickraw
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 9
8
- version: "0.9"
4
+ prerelease:
5
+ version: 0.9.2
9
6
  platform: ruby
10
7
  authors:
11
8
  - Mael Clerambault
@@ -13,8 +10,7 @@ autorequire:
13
10
  bindir: bin
14
11
  cert_chain: []
15
12
 
16
- date: 2011-09-20 00:00:00 +02:00
17
- default_executable:
13
+ date: 2011-10-09 00:00:00 Z
18
14
  dependencies: []
19
15
 
20
16
  description:
@@ -33,12 +29,16 @@ files:
33
29
  - examples/upload.rb
34
30
  - test/test_upload.rb
35
31
  - test/test.rb
32
+ - test/helper.rb
36
33
  - lib/flickraw.rb
34
+ - lib/flickraw/oauth.rb
35
+ - lib/flickraw/response.rb
36
+ - lib/flickraw/request.rb
37
+ - lib/flickraw/api.rb
37
38
  - flickraw_rdoc.rb
38
39
  - LICENSE
39
40
  - README.rdoc
40
41
  - rakefile
41
- has_rdoc: true
42
42
  homepage: http://hanklords.github.com/flickraw/
43
43
  licenses: []
44
44
 
@@ -52,21 +52,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
55
  version: "0"
58
56
  required_rubygems_version: !ruby/object:Gem::Requirement
59
57
  none: false
60
58
  requirements:
61
59
  - - ">="
62
60
  - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
61
  version: "0"
66
62
  requirements: []
67
63
 
68
64
  rubyforge_project:
69
- rubygems_version: 1.3.7
65
+ rubygems_version: 1.8.10
70
66
  signing_key:
71
67
  specification_version: 3
72
68
  summary: Flickr library with a syntax close to the syntax described on http://www.flickr.com/services/api