flickraw 0.8.4 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -5,26 +5,25 @@ It maps exactly the methods described in {the official api documentation}[http:/
5
5
  It also tries to present the data returned in a simple and intuitive way.
6
6
  The methods are fetched from flickr when loading the library by using introspection capabilities. So it is always up-to-date with regards to new methods added by flickr.
7
7
 
8
- The rubyforge project : http://rubyforge.org/projects/flickraw
9
-
10
- The github repository: http://github.com/hanklords/flickraw/tree/master
8
+ The github repository: http://github.com/hanklords/flickraw
11
9
 
12
10
  = Installation
13
11
  Type this in a console (you might need to be superuser)
14
12
  gem install flickraw
15
13
 
16
14
  This will recreate the documentation by fetching the methods descriptions from flickr and then virtually plugging them in standard rdoc documentation.
17
- rake rdoc
15
+ $ cd flickraw
16
+ $ rake rdoc
18
17
 
19
18
  = Features
20
19
 
21
- * Small single file: flickraw.rb is less than 300 lines
20
+ * Small single file: flickraw.rb is less than 400 lines
21
+ * Minimal dependencies
22
22
  * Complete support of flickr API. This doesn't require an update of the library
23
23
  * Ruby syntax similar to the flickr api
24
24
  * Flickr authentication
25
25
  * Photo upload
26
26
  * Proxy support
27
- * Delayed library loading (for rails users)
28
27
  * Flickr URLs helpers
29
28
 
30
29
  = Usage
@@ -42,14 +41,14 @@ This will recreate the documentation by fetching the methods descriptions from f
42
41
  secret = list[0].secret
43
42
  info = flickr.photos.getInfo :photo_id => id, :secret => secret
44
43
 
45
- info.title # => "PICT986"
46
- info.dates.taken # => "2006-07-06 15:16:18"
44
+ puts info.title # => "PICT986"
45
+ puts info.dates.taken # => "2006-07-06 15:16:18"
47
46
 
48
47
 
49
48
  sizes = flickr.photos.getSizes :photo_id => id
50
49
 
51
50
  original = sizes.find {|s| s.label == 'Original' }
52
- original.width # => "800"
51
+ puts original.width # => "800" -- may fail if they have no original marked image
53
52
 
54
53
  == Authentication
55
54
 
@@ -58,32 +57,34 @@ This will recreate the documentation by fetching the methods descriptions from f
58
57
  FlickRaw.api_key="... Your API key ..."
59
58
  FlickRaw.shared_secret="... Your shared secret ..."
60
59
 
61
- frob = flickr.auth.getFrob
62
- auth_url = FlickRaw.auth_url :frob => frob, :perms => 'read'
60
+ token = flickr.get_request_token(:perms => 'delete')
61
+ auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
63
62
 
64
63
  puts "Open this url in your process to complete the authication process : #{auth_url}"
65
- puts "Press Enter when you are finished."
66
- STDIN.getc
64
+ puts "Copy here the number given when you complete the process."
65
+ verify = gets.strip
67
66
 
68
67
  begin
69
- auth = flickr.auth.getToken :frob => frob
68
+ flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], verify)
70
69
  login = flickr.test.login
71
- puts "You are now authenticated as #{login.username} with token #{auth.token}"
70
+ puts "You are now authenticated as #{login.username} with token #{flickr.access_token} and secret #{flickr.access_secret}"
72
71
  rescue FlickRaw::FailedResponse => e
73
72
  puts "Authentication failed : #{e.msg}"
74
73
  end
75
74
 
76
- You don't need to do that each time, you can reuse your token:
75
+ If the user has already been authenticated, you can reuse the access token and access secret:
77
76
 
78
77
  require 'flickraw'
79
78
 
80
79
  FlickRaw.api_key="... Your API key ..."
81
80
  FlickRaw.shared_secret="... Your shared secret ..."
82
81
 
83
- auth = flickr.auth.checkToken :auth_token => "... Your saved token ..."
82
+ flickr.access_token = "... Your access token ..."
83
+ flickr.access_secret = "... Your access secret ..."
84
84
 
85
85
  # From here you are logged:
86
- puts auth.user.username
86
+ login = flickr.test.login
87
+ puts "You are now authenticated as #{login.username}"
87
88
 
88
89
  == Upload
89
90
 
@@ -97,27 +98,10 @@ You don't need to do that each time, you can reuse your token:
97
98
  # You need to be authentified to do that, see the previous examples.
98
99
  flickr.upload_photo PHOTO_PATH, :title => "Title", :description => "This is the description"
99
100
 
100
- == Flickraw Options
101
-
102
- You can pass some options to modify flickraw behavior:
103
-
104
- FlickRawOptions = {
105
- "api_key" => "... Your API key ...",
106
- "shared_secret" => "... Your shared secret ...",
107
- "auth_token" => "... Your saved token..." # if you set this you will be automatically loggued
108
- "lazyload" => true, # This delay the loading of the library until the first call
109
-
110
- # Proxy support. alternatively, you can use the http_proxy environment variable
111
- "proxy_host" => "proxy_host",
112
- "proxy_port" => "proxy_port",
113
- "proxy_user" => "proxy_user",
114
- "proxy_password" => "proxy_password",
115
-
116
- "timeout" => 5, # Set the request timeout
117
- "auth_token" => "SAVED_TOKEN" # Set the initial token
118
- }
101
+ == Proxy
119
102
 
120
103
  require 'flickraw'
104
+ FlickRaw.proxy = "http://user:pass@proxy.example.com:3129/"
121
105
 
122
106
  == Flickr URL Helpers
123
107
 
@@ -136,22 +120,22 @@ There are some helpers to build flickr urls :
136
120
  === url_photopage
137
121
 
138
122
  info = flickr.photos.getInfo(:photo_id => "3839885270")
139
- FlickRaw.url_photopage(photo) # => "http://www.flickr.com/photos/41650587@N02/3839885270"
123
+ FlickRaw.url_photopage(info) # => "http://www.flickr.com/photos/41650587@N02/3839885270"
140
124
 
141
125
  === url_photoset, url_photosets
142
126
 
143
127
  info = flickr.photos.getInfo(:photo_id => "3839885270")
144
- FlickRaw.url_photosets(photo) # => "http://www.flickr.com/photos/41650587@N02/sets/"
128
+ FlickRaw.url_photosets(info) # => "http://www.flickr.com/photos/41650587@N02/sets/"
145
129
 
146
- === url_short
130
+ === url_short, url_short_m, url_short_s, url_short_t
147
131
 
148
132
  info = flickr.photos.getInfo(:photo_id => "3839885270")
149
- FlickRaw.url_short(photo) # => "http://flic.kr/p/6Rjq7s"
133
+ FlickRaw.url_short(info) # => "http://flic.kr/p/6Rjq7s"
150
134
 
151
135
  === url_photostream
152
136
 
153
137
  info = flickr.photos.getInfo(:photo_id => "3839885270")
154
- FlickRaw.url_photostream(photo) # => "http://flic.kr/p/6Rjq7s"
138
+ FlickRaw.url_photostream(info) # => "http://www.flickr.com/photos/41650587@N02/"
155
139
 
156
140
 
157
141
  See the _examples_ directory to find more examples.
@@ -167,9 +151,10 @@ instead of
167
151
  require 'flickraw'
168
152
 
169
153
  This way it it doesn't fetch available flickr methods each time it is loaded.
170
- The flickraw-cached gem is on rubyforge and should be up-to-date with regard to flickr api most of the time.
154
+ The flickraw-cached gem is on rubygems.org and should be up-to-date with regard to flickr api most of the time.
171
155
 
172
156
  = Notes
157
+
173
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.
174
159
  This is because it is keeping the authentication token internally.
175
160
  As an alternative, you can create new Flickr objects besides Kernel.flickr which is created for you. Use Flickr.new to this effect.
data/examples/auth.rb CHANGED
@@ -8,18 +8,17 @@ SHARED_SECRET=''
8
8
  FlickRaw.api_key=API_KEY
9
9
  FlickRaw.shared_secret=SHARED_SECRET
10
10
 
11
- frob = flickr.auth.getFrob
12
- auth_url = FlickRaw.auth_url :frob => frob, :perms => 'read'
11
+ token = flickr.get_request_token(:perms => 'delete')
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}"
15
- puts "Press Enter when you are finished."
16
- STDIN.getc
15
+ puts "Copy here the number given when you complete the process."
16
+ verify = gets.strip
17
17
 
18
18
  begin
19
- flickr.auth.getToken :frob => frob
19
+ flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], verify)
20
20
  login = flickr.test.login
21
- puts "You are now authenticated as #{login.username}"
21
+ puts "You are now authenticated as #{login.username} with token #{flickr.access_token} and secret #{flickr.access_secret}"
22
22
  rescue FlickRaw::FailedResponse => e
23
23
  puts "Authentication failed : #{e.msg}"
24
24
  end
25
-
@@ -0,0 +1,22 @@
1
+ require 'flickraw'
2
+
3
+ # search for pictures taken within 60 miles of new brunswick, between 1890-1920
4
+
5
+ # FlickRaw.api_key="..."
6
+ # FlickRaw.shared_secret="..."
7
+
8
+ new_b = flickr.places.find :query => "new brunswick"
9
+ latitude = new_b[0]['latitude'].to_f
10
+ longitude = new_b[0]['longitude'].to_f
11
+
12
+ # within 60 miles of new brunswick, let's use a bbox
13
+ radius = 1
14
+ args = {}
15
+ args[:bbox] = "#{longitude - radius},#{latitude - radius},#{longitude + radius},#{latitude + radius}"
16
+
17
+ # requires a limiting factor, so let's give it one
18
+ args[:min_taken_date] = '1890-01-01 00:00:00'
19
+ args[:max_taken_date] = '1920-01-01 00:00:00'
20
+ args[:accuracy] = 1 # the default is street only granularity [16], which most images aren't...
21
+ discovered_pictures = flickr.photos.search args
22
+ discovered_pictures.each{|p| url = FlickRaw.url p; puts url}
@@ -0,0 +1,22 @@
1
+ require 'flickraw'
2
+ require 'sinatra'
3
+
4
+ FlickRaw.api_key = API_KEY
5
+ FlickRaw.shared_secret = SHARED_SECRET
6
+ enable :sessions
7
+
8
+ get '/authenticate' do
9
+ token = flickr.get_request_token(:oauth_callback => to('authenticated'))
10
+ session[:token] = token
11
+ redirect flickr.get_authorize_url(token['oauth_token'], :perms => 'delete')
12
+ end
13
+
14
+ 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
18
+ %{
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>.
21
+ }
22
+ end
data/examples/upload.rb CHANGED
@@ -2,21 +2,16 @@ require 'flickraw'
2
2
 
3
3
  # This is how to upload photos on flickr.
4
4
  # You need to be authentified to do that.
5
+
5
6
  API_KEY=''
6
7
  SHARED_SECRET=''
8
+ ACCESS_TOKEN=''
9
+ ACCESS _SECRET=''
7
10
  PHOTO_PATH='photo.jpg'
8
11
 
9
- FlickRaw.api_key=API_KEY
10
- FlickRaw.shared_secret=SHARED_SECRET
11
-
12
- frob = flickr.auth.getFrob
13
- auth_url = FlickRaw.auth_url :frob => frob, :perms => 'write'
14
-
15
- puts "Open this url in your process to complete the authication process : #{auth_url}"
16
- puts "Press Enter when you are finished."
17
- STDIN.getc
18
-
19
- flickr.auth.getToken :frob => frob
20
- login = flickr.test.login
12
+ FlickRaw.api_key = API_KEY
13
+ FlickRaw.shared_secret = SHARED_SECRET
14
+ flickr.access_token = ACCESS_TOKEN
15
+ flickr.access_secret = ACCESS_SECRET
21
16
 
22
17
  flickr.upload_photo PHOTO_PATH, :title => 'Title', :description => 'This is the description'
data/flickraw_rdoc.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "rdoc"
2
2
  require "rdoc/parser/ruby"
3
+ require "nokogiri"
3
4
  require "cgi"
4
5
 
5
6
  FLICKR_API_URL='http://www.flickr.com/services/api'
@@ -66,11 +67,7 @@ module RDoc
66
67
  end
67
68
 
68
69
  def flickr_method_comment(info)
69
- description = CGI.unescapeHTML(info.method.description.to_s)
70
- # description.gsub!( /<\/?(\w+)>/ ) {|b|
71
- # return b if ['em', 'b', 'tt'].include? $1
72
- # return ''
73
- # }
70
+ description = Nokogiri::HTML(info.method.description.to_s).text
74
71
 
75
72
  if info.respond_to? :arguments
76
73
  args = info.arguments.select { |arg| arg.name != 'api_key' }
data/lib/flickraw.rb CHANGED
@@ -20,30 +20,140 @@
20
20
  # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
21
  # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
 
23
-
24
23
  require 'net/http'
25
- require 'digest/md5'
26
24
  require 'json'
27
25
 
28
- FlickRawOptions = {} if not Object.const_defined? :FlickRawOptions # :nodoc:
29
- if ENV['http_proxy'] and not FlickRawOptions['proxy_host']
30
- proxy = URI.parse ENV['http_proxy']
31
- FlickRawOptions.update('proxy_host' => proxy.host, 'proxy_port' => proxy.port, 'proxy_user' => proxy.user, 'proxy_password' => proxy.password)
32
- end
33
-
34
26
  module FlickRaw
35
- VERSION='0.8.4'
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
36
33
 
37
- FLICKR_HOST='api.flickr.com'.freeze
38
- REST_PATH='/services/rest/?'.freeze
39
- UPLOAD_PATH='/services/upload/'.freeze
40
- REPLACE_PATH='/services/replace/'.freeze
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
41
37
 
42
- AUTH_PATH='http://flickr.com/services/auth/?'.freeze
43
38
  PHOTO_SOURCE_URL='http://farm%s.static.flickr.com/%s/%s_%s%s.%s'.freeze
44
39
  URL_PROFILE='http://www.flickr.com/people/'.freeze
45
40
  URL_PHOTOSTREAM='http://www.flickr.com/photos/'.freeze
46
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
47
157
 
48
158
  class Response
49
159
  def self.build(h, type) # :nodoc:
@@ -89,6 +199,7 @@ module FlickRaw
89
199
  def inspect; @a.inspect end
90
200
  def size; @a.size end
91
201
  def marshal_dump; [@h, @flickr_type, @a] end
202
+ alias length size
92
203
  end
93
204
 
94
205
  class FailedResponse < StandardError
@@ -150,25 +261,53 @@ module FlickRaw
150
261
 
151
262
  # Root class of the flickr api hierarchy.
152
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
+
153
270
  def self.build(methods); methods.each { |m| build_request m } end
154
271
 
155
- def initialize(token = FlickRawOptions['auth_token']) # :nodoc:
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
+
156
278
  Flickr.build(call('flickr.reflection.getMethods')) if Flickr.flickr_objects.empty?
157
279
  super self
158
- @token = token
159
280
  end
160
-
281
+
161
282
  # This is the central method. It does the actual request to the flickr server.
162
283
  #
163
284
  # Raises FailedResponse if the response status is _failed_.
164
285
  def call(req, args={}, &block)
165
- @token = nil if req == "flickr.auth.getFrob"
166
- http_response = open_flickr do |http|
167
- request = Net::HTTP::Post.new(REST_PATH, 'User-Agent' => "Flickraw/#{VERSION}")
168
- request.set_form_data(build_args(args, req))
169
- http.request(request)
170
- end
171
- process_response(req, http_response)
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
172
311
  end
173
312
 
174
313
  # Use this to upload the photo in _file_.
@@ -186,97 +325,58 @@ module FlickRaw
186
325
  def replace_photo(file, args={}); upload_flickr(REPLACE_PATH, file, args) end
187
326
 
188
327
  private
189
- def build_args(args={}, req = nil)
190
- full_args = {:api_key => FlickRaw.api_key, :format => 'json', :nojsoncallback => "1"}
191
- full_args[:method] = req if req
192
- full_args[:auth_token] = @token if @token
328
+ def build_args(args={}, method = nil)
329
+ full_args = {'format' => 'json', :nojsoncallback => "1"}
330
+ full_args['method'] = method if method
193
331
  args.each {|k, v|
194
332
  v = v.to_s.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
195
- full_args[k.to_sym] = v.to_s
333
+ full_args[k.to_s] = v
196
334
  }
197
- full_args[:api_sig] = FlickRaw.api_sig(full_args) if FlickRaw.shared_secret
198
335
  full_args
199
336
  end
200
337
 
201
- def process_response(req, http_response)
202
- json = JSON.load(http_response.body.empty? ? "{}" : http_response.body)
203
- raise FailedResponse.new(json['message'], json['code'], req) if json.delete('stat') == 'fail'
204
- type, json = json.to_a.first if json.size == 1 and json.all? {|k,v| v.is_a? Hash}
205
-
206
- res = Response.build json, type
207
- @token = res.token if res.respond_to? :flickr_type and res.flickr_type == "auth"
208
- res
209
- end
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}
210
358
 
211
- def open_flickr
212
- Net::HTTP::Proxy(FlickRawOptions['proxy_host'], FlickRawOptions['proxy_port'], FlickRawOptions['proxy_user'], FlickRawOptions['proxy_password']).start(FLICKR_HOST) {|http|
213
- http.read_timeout = FlickRawOptions['timeout'] if FlickRawOptions.key?('timeout')
214
- yield http
215
- }
359
+ Response.build json, type
360
+ end
216
361
  end
217
362
 
218
363
  def upload_flickr(method, file, args={})
219
- photo = open(file, 'rb') { |f| f.read }
220
- boundary = Digest::MD5.hexdigest(photo)
221
-
222
- header = {'Content-type' => "multipart/form-data, boundary=#{boundary} ", 'User-Agent' => "Flickraw/#{VERSION}"}
223
- query = ''
224
-
225
- file = file.to_s.encode("utf-8").force_encoding("ascii-8bit") if RUBY_VERSION >= "1.9"
226
- build_args(args).each { |a, v|
227
- query <<
228
- "--#{boundary}\r\n" <<
229
- "Content-Disposition: form-data; name=\"#{a}\"\r\n\r\n" <<
230
- "#{v}\r\n"
231
- }
232
- query <<
233
- "--#{boundary}\r\n" <<
234
- "Content-Disposition: form-data; name=\"photo\"; filename=\"#{file}\"\r\n" <<
235
- "Content-Transfer-Encoding: binary\r\n" <<
236
- "Content-Type: image/jpeg\r\n\r\n" <<
237
- photo <<
238
- "\r\n" <<
239
- "--#{boundary}--"
240
-
241
- http_response = open_flickr {|http| http.post(method, query, header) }
242
- xml = http_response.body
243
- if xml[/stat="(\w+)"/, 1] == 'fail'
244
- msg = xml[/msg="([^"]+)"/, 1]
245
- code = xml[/code="([^"]+)"/, 1]
246
- raise FailedResponse.new(msg, code, 'flickr.upload')
247
- end
248
- type = xml[/<(\w+)/, 1]
249
- h = {
250
- "secret" => xml[/secret="([^"]+)"/, 1],
251
- "originalsecret" => xml[/originalsecret="([^"]+)"/, 1],
252
- "_content" => xml[/>([^<]+)<\//, 1]
253
- }.delete_if {|k,v| v.nil? }
254
- Response.build(h, type)
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)
255
368
  end
256
369
  end
257
370
 
258
371
  class << self
259
372
  # Your flickr API key, see http://www.flickr.com/services/api/keys for more information
260
- def api_key; FlickRawOptions['api_key'] end
261
- def api_key=(key); FlickRawOptions['api_key'] = key end
262
-
373
+ attr_accessor :api_key
374
+
263
375
  # The shared secret of _api_key_, see http://www.flickr.com/services/api/keys for more information
264
- def shared_secret; FlickRawOptions['shared_secret'] end
265
- def shared_secret=(key); FlickRawOptions['shared_secret'] = key end
266
-
267
- # Returns the flickr auth URL.
268
- def auth_url(args={})
269
- full_args = {:api_key => api_key, :perms => 'read'}
270
- args.each {|k, v| full_args[k.to_sym] = v }
271
- full_args[:api_sig] = api_sig(full_args) if shared_secret
272
-
273
- AUTH_PATH + full_args.collect { |a, v| "#{a}=#{v}" }.join('&')
274
- end
275
-
276
- # Returns the signature of hsh. This is meant to be passed in the _api_sig_ parameter.
277
- def api_sig(hsh)
278
- Digest::MD5.hexdigest(FlickRaw.shared_secret + hsh.sort{|a, b| a[0].to_s <=> b[0].to_s }.flatten.join)
279
- end
376
+ attr_accessor :shared_secret
377
+
378
+ # Use a proxy
379
+ attr_accessor :proxy
280
380
 
281
381
  BASE58_ALPHABET="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".freeze
282
382
  def base58(id)
@@ -324,9 +424,3 @@ end
324
424
  # recent_photos = flickr.photos.getRecent
325
425
  # puts recent_photos[0].title
326
426
  def flickr; $flickraw ||= FlickRaw::Flickr.new end
327
-
328
- # Load the methods if the option lazyload is not specified
329
- begin
330
- flickr
331
- rescue
332
- end if not FlickRawOptions['lazyload']
data/rakefile CHANGED
@@ -1,36 +1,15 @@
1
1
  require 'rake/clean'
2
2
  require 'rake/rdoctask'
3
- require 'rake/packagetask'
4
- require 'rake/gempackagetask'
5
3
  require 'rake/testtask'
6
4
 
7
- FlickRawOptions = {'lazyload' => true}
8
- require './lib/flickraw'
9
- require './flickraw_rdoc' if RUBY_VERSION >= "1.9"
5
+ lib = File.dirname(__FILE__)
6
+ $:.unshift lib unless $:.include?(lib)
10
7
 
11
- PKG_FILES = FileList["lib/flickraw.rb", "flickraw_rdoc.rb", "LICENSE", "README.rdoc", "rakefile", "examples/*.rb", "test/*.rb"].to_a
12
-
13
- spec = Gem::Specification.new do |s|
14
- s.summary = "Flickr library with a syntax close to the syntax described on http://www.flickr.com/services/api"
15
- s.name = "flickraw"
16
- s.author = "Mael Clerambault"
17
- s.email = "maelclerambault@yahoo.fr"
18
- s.homepage = "http://hanklords.github.com/flickraw/"
19
- s.version = FlickRaw::VERSION
20
- s.files = PKG_FILES
21
- s.add_dependency 'json', '>= 1.1.1'
22
- end
23
-
24
- Rake::GemPackageTask.new(spec).define
25
-
26
- desc "Create default gemspec file"
27
- file "flickraw.gemspec" do
28
- open("flickraw.gemspec", "w") {|g| g.puts spec.to_ruby }
29
- end
30
- task :gem => ["flickraw.gemspec"]
31
- CLOBBER.add "flickraw.gemspec"
8
+ require 'lib/flickraw'
9
+ require 'flickraw_rdoc' if RUBY_VERSION >= "1.9"
32
10
 
33
11
  Rake::RDocTask.new do |rd|
12
+ rd.main = "README.rdoc"
34
13
  rd.rdoc_files.include "README.rdoc", "lib/flickraw.rb"
35
14
  end
36
15
 
data/test/test.rb CHANGED
@@ -1,13 +1,19 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ lib = File.expand_path('../../lib/', __FILE__)
4
+ $:.unshift lib unless $:.include?(lib)
5
+
3
6
  require 'test/unit'
4
7
  require 'flickraw'
5
8
 
9
+ # FlickRaw.shared_secret = # Shared secret
10
+ # flickr.auth.checkToken :auth_token => # Auth token
11
+
6
12
  class Basic < Test::Unit::TestCase
7
13
  def test_request
8
14
  flickr_objects = %w{activity auth blogs collections commons contacts
9
15
  favorites galleries groups interestingness machinetags panda
10
- people photos photosets places prefs reflection stats tags
16
+ people photos photosets places prefs push reflection stats tags
11
17
  test urls
12
18
  }
13
19
  assert_equal FlickRaw::Flickr.flickr_objects, flickr_objects
@@ -25,6 +31,7 @@ class Basic < Test::Unit::TestCase
25
31
  flickr.auth.getFrob
26
32
  flickr.auth.getFullToken
27
33
  flickr.auth.getToken
34
+ flickr.auth.oauth.getAccessToken
28
35
  flickr.blogs.getList
29
36
  flickr.blogs.getServices
30
37
  flickr.blogs.postPhoto
@@ -35,6 +42,7 @@ class Basic < Test::Unit::TestCase
35
42
  flickr.contacts.getListRecentlyUploaded
36
43
  flickr.contacts.getPublicList
37
44
  flickr.favorites.add
45
+ flickr.favorites.getContext
38
46
  flickr.favorites.getList
39
47
  flickr.favorites.getPublicList
40
48
  flickr.favorites.remove
@@ -162,6 +170,10 @@ class Basic < Test::Unit::TestCase
162
170
  flickr.prefs.getHidden
163
171
  flickr.prefs.getPrivacy
164
172
  flickr.prefs.getSafetyLevel
173
+ flickr.push.getSubscriptions
174
+ flickr.push.getTopics
175
+ flickr.push.subscribe
176
+ flickr.push.unsubscribe
165
177
  flickr.reflection.getMethodInfo
166
178
  flickr.reflection.getMethods
167
179
  flickr.stats.getCollectionDomains
@@ -199,7 +211,7 @@ class Basic < Test::Unit::TestCase
199
211
  }
200
212
  found_methods = flickr.reflection.getMethods
201
213
  assert_instance_of FlickRaw::ResponseList, found_methods
202
- assert_equal known_methods, found_methods.to_a
214
+ assert_equal known_methods.sort, found_methods.to_a.sort
203
215
  end
204
216
 
205
217
  def test_list
data/test/test_upload.rb CHANGED
@@ -1,10 +1,15 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ lib = File.expand_path('../../lib/', __FILE__)
4
+ $:.unshift lib unless $:.include?(lib)
5
+
3
6
  require 'test/unit'
4
7
  require 'flickraw'
5
8
 
9
+ # FlickRaw.api_key = # API key
6
10
  # FlickRaw.shared_secret = # Shared secret
7
- # flickr.auth.checkToken :auth_token => # Auth token
11
+ # flickr.access_token = # Auth token
12
+ # flickr.access_secret = # Auth token secret
8
13
 
9
14
  class Upload < Test::Unit::TestCase
10
15
  def test_upload
metadata CHANGED
@@ -4,9 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 8
8
- - 4
9
- version: 0.8.4
7
+ - 9
8
+ version: "0.9"
10
9
  platform: ruby
11
10
  authors:
12
11
  - Mael Clerambault
@@ -14,24 +13,10 @@ autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2011-02-09 00:00:00 +01:00
16
+ date: 2011-09-20 00:00:00 +02:00
18
17
  default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: json
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 1
31
- - 1
32
- version: 1.1.1
33
- type: :runtime
34
- version_requirements: *id001
18
+ dependencies: []
19
+
35
20
  description:
36
21
  email: maelclerambault@yahoo.fr
37
22
  executables: []
@@ -41,17 +26,18 @@ extensions: []
41
26
  extra_rdoc_files: []
42
27
 
43
28
  files:
44
- - lib/flickraw.rb
45
- - flickraw_rdoc.rb
46
- - LICENSE
47
- - README.rdoc
48
- - rakefile
49
- - examples/flickr_KDE.rb
50
29
  - examples/auth.rb
51
30
  - examples/interestingness.rb
31
+ - examples/search.rb
32
+ - examples/sinatra.rb
52
33
  - examples/upload.rb
53
34
  - test/test_upload.rb
54
35
  - test/test.rb
36
+ - lib/flickraw.rb
37
+ - flickraw_rdoc.rb
38
+ - LICENSE
39
+ - README.rdoc
40
+ - rakefile
55
41
  has_rdoc: true
56
42
  homepage: http://hanklords.github.com/flickraw/
57
43
  licenses: []
@@ -1,23 +0,0 @@
1
- #!/usr/bin/ruby
2
- # Chooses a photo from the current interesting
3
- # photo and set it as the background image on
4
- # your first KDE desktop.
5
-
6
- require 'flickraw'
7
- require 'open-uri'
8
- DESKTOP=1
9
-
10
- list = flickr.interestingness.getList
11
- photo = list[rand(100)]
12
- sizes = flickr.photos.getSizes(:photo_id => photo.id)
13
- original = sizes.find {|s| s.label == 'Original' }
14
-
15
- url = original.source
16
- file = File.basename url
17
- full_path = File.join(Dir.pwd, file)
18
-
19
- open url do |remote|
20
- open(file, 'wb') { |local| local << remote.read }
21
- end
22
-
23
- `dcop kdesktop KBackgroundIface setWallpaper #{DESKTOP} #{full_path} 7`