flickraw 0.9 → 0.9.2

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