koala 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,6 +1,26 @@
1
+ v1.5
2
+ New methods:
3
+ -- Added Koala::Utils.logger to enable debugging (thanks, KentonWhite!)
4
+ -- Expose fb_error_message and fb_error_code directly in APIError
5
+ Updated methods:
6
+ -- GraphCollection.parse_page_url now uses the URI library and can parse any address (thanks, bnorton!)
7
+ Internal improvements:
8
+ -- Update MultiJson dependency to support the Oj library (thanks, eckz and zinenko!)
9
+ -- Loosened Faraday dependency (thanks, rewritten and romanbsd!)
10
+ -- Fixed typos (thanks, nathanbertram!)
11
+ -- Switched uses of put_object to the more semantically accurate put_connections
12
+ -- Cleaned up gemspec
13
+ -- Handle invalid batch API responses better
14
+ Documentation:
15
+ -- Added HTTP Services description for Faraday 0.8/persistent connections (thanks, romanbsd!)
16
+ -- Remove documentation of the old pre-1.2 HTTP Service options
17
+
18
+ v.1.4.1
19
+ -- Update MultiJson to 1.3 and change syntax to silence warnings (thanks, eckz and masterkain!)
20
+
1
21
  v1.4
2
22
  New methods:
3
- -- OAuth#exchange_access_token(_info) allows you to extend access tokens you receive (thanks, etiennebarrie!)
23
+ -- OAuth#exchange_access_token(_info) allows you to extend access tokens you receive (thanks, etiennebarrie!)
4
24
  Updated methods:
5
25
  -- HTTPServices#encode_params sorts parameters to aid in URL comparison (thanks, sholden!)
6
26
  -- get_connections is now aliased as get_connection (use whichever makes sense to you)
data/koala.gemspec CHANGED
@@ -2,47 +2,26 @@
2
2
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
3
  require 'koala/version'
4
4
 
5
- Gem::Specification.new do |s|
6
- s.name = %q{koala}
7
- s.version = Koala::VERSION
8
-
9
- s.summary = %q{A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication.}
10
- s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
11
- s.homepage = %q{http://github.com/arsduo/koala}
12
-
13
- s.authors = ["Alex Koppel"]
14
- s.email = %q{alex@alexkoppel.com}
15
-
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
-
19
- s.extra_rdoc_files = ["readme.md", "CHANGELOG"]
20
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
21
-
22
- s.require_paths = ["lib"]
23
-
24
- s.rubygems_version = %q{1.4.2}
25
-
26
- s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
27
-
28
- if s.respond_to? :specification_version then
29
- s.specification_version = 3
30
-
31
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
32
- s.add_runtime_dependency(%q<multi_json>, ["~> 1.0"])
33
- s.add_runtime_dependency(%q<faraday>, ["~> 0.7.0"])
34
- s.add_development_dependency(%q<rspec>, ["~> 2.8.0rc1"])
35
- s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
36
- else
37
- s.add_dependency(%q<multi_json>, ["~> 1.0"])
38
- s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
39
- s.add_dependency(%q<rake>, ["~> 0.8.7"])
40
- s.add_dependency(%q<faraday>, ["~> 0.7.0"])
41
- end
42
- else
43
- s.add_dependency(%q<multi_json>, ["~> 1.0"])
44
- s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
45
- s.add_dependency(%q<rake>, ["~> 0.8.7"])
46
- s.add_dependency(%q<faraday>, ["~> 0.7.0"])
47
- end
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "koala"
7
+ gem.summary = "A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication."
8
+ gem.description = "Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services."
9
+ gem.homepage = "http://github.com/arsduo/koala"
10
+ gem.version = Koala::VERSION
11
+
12
+ gem.authors = ["Alex Koppel"]
13
+ gem.email = "alex@alexkoppel.com"
14
+
15
+ gem.require_paths = ["lib"]
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+
20
+ gem.extra_rdoc_files = ["readme.md", "CHANGELOG"]
21
+ gem.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
22
+
23
+ gem.add_runtime_dependency(%q<multi_json>, ["~> 1.3"])
24
+ gem.add_runtime_dependency(%q<faraday>, ["~> 0.7"])
25
+ gem.add_development_dependency(%q<rspec>, ["~> 2.8"])
26
+ gem.add_development_dependency(%q<rake>, ["~> 0.8"])
48
27
  end
@@ -72,8 +72,7 @@ module Koala
72
72
  # Please use put_connections; in a future version of Koala (2.0?),
73
73
  # put_object will issue a POST directly to an individual object, not to a connection.
74
74
  def put_object(parent_object, connection_name, args = {}, options = {})
75
- raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token
76
- graph_call("#{parent_object}/#{connection_name}", args, "post", options)
75
+ put_connections(parent_object, connection_name, args, options)
77
76
  end
78
77
 
79
78
  # Delete an object from the Graph if you have appropriate permissions.
@@ -115,7 +114,7 @@ module Koala
115
114
  # @note (see #get_connection)
116
115
  #
117
116
  # @example
118
- # graph.put_object("me", "feed", :message => "Hello, world")
117
+ # graph.put_connections("me", "feed", :message => "Hello, world")
119
118
  # => writes "Hello, world" to the active user's wall
120
119
  #
121
120
  # Most write operations require extended permissions. For example,
@@ -192,7 +191,7 @@ module Koala
192
191
  #
193
192
  # @return (see #put_connections)
194
193
  def put_picture(*picture_args)
195
- put_object(*parse_media_args(picture_args, "photos"))
194
+ put_connections(*parse_media_args(picture_args, "photos"))
196
195
  end
197
196
 
198
197
  # Upload a video. Functions exactly the same as put_picture.
@@ -200,11 +199,11 @@ module Koala
200
199
  def put_video(*video_args)
201
200
  args = parse_media_args(video_args, "videos")
202
201
  args.last[:video] = true
203
- put_object(*args)
202
+ put_connections(*args)
204
203
  end
205
204
 
206
205
  # Write directly to the user's wall.
207
- # Convenience method equivalent to put_object(id, "feed").
206
+ # Convenience method equivalent to put_connections(id, "feed").
208
207
  #
209
208
  # To get wall posts, use get_connections(user, "feed")
210
209
  # To delete a wall post, use delete_object(post_id)
@@ -227,7 +226,7 @@ module Koala
227
226
  # @see #put_connections
228
227
  # @return (see #put_connections)
229
228
  def put_wall_post(message, attachment = {}, target_id = "me", options = {})
230
- self.put_object(target_id, "feed", attachment.merge({:message => message}), options)
229
+ put_connections(target_id, "feed", attachment.merge({:message => message}), options)
231
230
  end
232
231
 
233
232
  # Comment on a given object.
@@ -243,7 +242,7 @@ module Koala
243
242
  # @return (see #put_connections)
244
243
  def put_comment(id, message, options = {})
245
244
  # Writes the given comment on the given post.
246
- self.put_object(id, "comments", {:message => message}, options)
245
+ put_connections(id, "comments", {:message => message}, options)
247
246
  end
248
247
 
249
248
  # Like a given object.
@@ -257,7 +256,7 @@ module Koala
257
256
  # @return (see #put_connections)
258
257
  def put_like(id, options = {})
259
258
  # Likes the given post.
260
- self.put_object(id, "likes", {}, options)
259
+ put_connections(id, "likes", {}, options)
261
260
  end
262
261
 
263
262
  # Unlike a given object.
@@ -318,7 +317,7 @@ module Koala
318
317
  #
319
318
  # @return a hash of FQL results keyed to the appropriate query
320
319
  def fql_multiquery(queries = {}, args = {}, options = {})
321
- if results = get_object("fql", args.merge(:q => MultiJson.encode(queries)), options)
320
+ if results = get_object("fql", args.merge(:q => MultiJson.dump(queries)), options)
322
321
  # simplify the multiquery result format
323
322
  results.inject({}) {|outcome, data| outcome[data["name"]] = data["fql_result_set"]; outcome}
324
323
  end
@@ -353,7 +352,7 @@ module Koala
353
352
  end
354
353
 
355
354
  def set_app_restrictions(app_id, restrictions_hash, args = {}, options = {})
356
- graph_call(app_id, args.merge(:restrictions => MultiJson.encode(restrictions_hash)), "post", options)
355
+ graph_call(app_id, args.merge(:restrictions => MultiJson.dump(restrictions_hash)), "post", options)
357
356
  end
358
357
 
359
358
  # Certain calls such as {#get_connections} return an array of results which you can page through
@@ -447,7 +446,7 @@ module Koala
447
446
 
448
447
  def parse_media_args(media_args, method)
449
448
  # photo and video uploads can accept different types of arguments (see above)
450
- # so here, we parse the arguments into a form directly usable in put_object
449
+ # so here, we parse the arguments into a form directly usable in put_connections
451
450
  raise KoalaError.new("Wrong number of arguments for put_#{method == "photos" ? "picture" : "video"}") unless media_args.size.between?(1, 5)
452
451
 
453
452
  args_offset = media_args[1].kind_of?(Hash) || media_args.size == 1 ? 0 : 1
@@ -41,7 +41,7 @@ module Koala
41
41
  end
42
42
 
43
43
  # redefine the graph_call and check_response methods
44
- # so we can use this API inside the batch block just like any regular Graph API
44
+ # so we can use this API inside the batch block just like any regular Graph API
45
45
  alias_method :graph_call_outside_batch, :graph_call
46
46
  alias_method :graph_call, :graph_call_in_batch
47
47
 
@@ -53,12 +53,18 @@ module Koala
53
53
  return [] unless batch_calls.length > 0
54
54
  # Turn the call args collected into what facebook expects
55
55
  args = {}
56
- args["batch"] = MultiJson.encode(batch_calls.map { |batch_op|
56
+ args["batch"] = MultiJson.dump(batch_calls.map { |batch_op|
57
57
  args.merge!(batch_op.files) if batch_op.files
58
58
  batch_op.to_batch_params(access_token)
59
59
  })
60
60
 
61
61
  batch_result = graph_call_outside_batch('/', args, 'post', http_options) do |response|
62
+ unless response
63
+ # Facebook sometimes reportedly returns an empty body at times
64
+ # see https://github.com/arsduo/koala/issues/184
65
+ raise APIError.new({"type" => "BadFacebookResponse", "message" => "Facebook returned invalid batch response: #{response.inspect}"})
66
+ end
67
+
62
68
  # map the results with post-processing included
63
69
  index = 0 # keep compat with ruby 1.8 - no with_index for map
64
70
  response.map do |call_result|
@@ -68,7 +74,7 @@ module Koala
68
74
 
69
75
  if call_result
70
76
  # (see note in regular api method about JSON parsing)
71
- body = MultiJson.decode("[#{call_result['body'].to_s}]")[0]
77
+ body = MultiJson.load("[#{call_result['body'].to_s}]")[0]
72
78
 
73
79
  unless call_result["code"].to_i >= 500 || error = check_response(body)
74
80
  # Get the HTTP component they want
@@ -92,7 +98,7 @@ module Koala
92
98
  end
93
99
  end
94
100
  end
95
-
101
+
96
102
  # turn any results that are pageable into GraphCollections
97
103
  batch_result.inject([]) {|processed_results, raw| processed_results << GraphCollection.evaluate(raw, @original_api)}
98
104
  end
@@ -87,10 +87,11 @@ module Koala
87
87
  #
88
88
  # @return an array of parameters that can be provided via graph_call(*parsed_params)
89
89
  def self.parse_page_url(url)
90
- match = url.match(/.com\/(.*)\?(.*)/)
91
- base = match[1]
92
- args = match[2]
93
- params = CGI.parse(args)
90
+ uri = URI.parse(url)
91
+
92
+ base = uri.path.sub(/^\//, '')
93
+ params = CGI.parse(uri.query)
94
+
94
95
  new_params = {}
95
96
  params.each_pair do |key,value|
96
97
  new_params[key] = value.join ","
@@ -22,7 +22,7 @@ module Koala
22
22
  # @return true if successful, false if not. (This call currently doesn't give useful feedback on failure.)
23
23
  def set_app_properties(properties, args = {}, options = {})
24
24
  raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "setAppProperties requires an access token"}) unless @access_token
25
- rest_call("admin.setAppProperties", args.merge(:properties => MultiJson.encode(properties)), options, "post")
25
+ rest_call("admin.setAppProperties", args.merge(:properties => MultiJson.dump(properties)), options, "post")
26
26
  end
27
27
 
28
28
  # Make a call to the REST API.
data/lib/koala/api.rb CHANGED
@@ -12,12 +12,12 @@ module Koala
12
12
  def initialize(access_token = nil)
13
13
  @access_token = access_token
14
14
  end
15
-
15
+
16
16
  attr_reader :access_token
17
17
 
18
18
  include GraphAPIMethods
19
19
  include RestAPIMethods
20
-
20
+
21
21
  # Makes a request to the appropriate Facebook API.
22
22
  # @note You'll rarely need to call this method directly.
23
23
  #
@@ -27,17 +27,17 @@ module Koala
27
27
  # @param path the server path for this request (leading / is prepended if not present)
28
28
  # @param args arguments to be sent to Facebook
29
29
  # @param verb the HTTP method to use
30
- # @param options request-related options for Koala and Faraday.
30
+ # @param options request-related options for Koala and Faraday.
31
31
  # See https://github.com/arsduo/koala/wiki/HTTP-Services for additional options.
32
32
  # @option options [Symbol] :http_component which part of the response (headers, body, or status) to return
33
33
  # @option options [Boolean] :beta use Facebook's beta tier
34
- # @option options [Boolean] :use_ssl force SSL for this request, even if it's tokenless.
34
+ # @option options [Boolean] :use_ssl force SSL for this request, even if it's tokenless.
35
35
  # (All API requests with access tokens use SSL.)
36
- # @param error_checking_block a block to evaluate the response status for additional JSON-encoded errors
36
+ # @param error_checking_block a block to evaluate the response status for additional JSON-encoded errors
37
37
  #
38
38
  # @yield The response body for evaluation
39
39
  #
40
- # @raise [Koala::Facebook::APIError] if Facebook returns an error (response status >= 500)
40
+ # @raise [Koala::Facebook::APIError] if Facebook returns an error (response status >= 500)
41
41
  #
42
42
  # @return the body of the response from Facebook (unless another http_component is requested)
43
43
  def api(path, args = {}, verb = "get", options = {}, &error_checking_block)
@@ -57,8 +57,8 @@ module Koala
57
57
 
58
58
  # parse the body as JSON and run it through the error checker (if provided)
59
59
  # Note: Facebook sometimes sends results like "true" and "false", which aren't strictly objects
60
- # and cause MultiJson.decode to fail -- so we account for that by wrapping the result in []
61
- body = MultiJson.decode("[#{result.body.to_s}]")[0]
60
+ # and cause MultiJson.load to fail -- so we account for that by wrapping the result in []
61
+ body = MultiJson.load("[#{result.body.to_s}]")[0]
62
62
  yield body if error_checking_block
63
63
 
64
64
  # if we want a component other than the body (e.g. redirect header for images), return that
@@ -69,11 +69,11 @@ module Koala
69
69
  end
70
70
  end
71
71
  end
72
-
72
+
73
73
  class APIError < StandardError
74
- attr_accessor :fb_error_type, :raw_response
74
+ attr_accessor :fb_error_type, :fb_error_code, :fb_error_message, :raw_response
75
75
 
76
- # Creates a new APIError.
76
+ # Creates a new APIError.
77
77
  #
78
78
  # Assigns the error type (as reported by Facebook) to #fb_error_type
79
79
  # and the raw error response available to #raw_response.
@@ -82,6 +82,8 @@ module Koala
82
82
  def initialize(details = {})
83
83
  self.raw_response = details
84
84
  self.fb_error_type = details["type"]
85
+ self.fb_error_code = details["code"]
86
+ self.fb_error_message = details["message"]
85
87
  super("#{fb_error_type}: #{details["message"]}")
86
88
  end
87
89
  end
@@ -4,7 +4,7 @@ require 'koala/http_service/uploadable_io'
4
4
  require 'koala/http_service/response'
5
5
 
6
6
  module Koala
7
- module HTTPService
7
+ module HTTPService
8
8
  class << self
9
9
  # A customized stack of Faraday middleware that will be used to make each request.
10
10
  attr_accessor :faraday_middleware
@@ -13,9 +13,9 @@ module Koala
13
13
  end
14
14
 
15
15
  @http_options ||= {}
16
-
17
- # Koala's default middleware stack.
18
- # We encode requests in a Facebook-compatible multipart request,
16
+
17
+ # Koala's default middleware stack.
18
+ # We encode requests in a Facebook-compatible multipart request,
19
19
  # and use whichever adapter has been configured for this application.
20
20
  DEFAULT_MIDDLEWARE = Proc.new do |builder|
21
21
  builder.use Koala::HTTPService::MultipartRequest
@@ -30,7 +30,7 @@ module Koala
30
30
  # @option options :video use the server designated for video uploads
31
31
  # @option options :beta use the beta tier
32
32
  # @option options :use_ssl force https, even if not needed
33
- #
33
+ #
34
34
  # @return a complete server address with protocol
35
35
  def self.server(options = {})
36
36
  server = "#{options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER}"
@@ -48,9 +48,9 @@ module Koala
48
48
  #
49
49
  # @param path the server path for this request
50
50
  # @param args (see Koala::Facebook::API#api)
51
- # @param verb the HTTP method to use.
51
+ # @param verb the HTTP method to use.
52
52
  # If not get or post, this will be turned into a POST request with the appropriate :method
53
- # specified in the arguments.
53
+ # specified in the arguments.
54
54
  # @param options (see Koala::Facebook::API#api)
55
55
  #
56
56
  # @raise an appropriate connection error if unable to make the request to Facebook
@@ -63,23 +63,30 @@ module Koala
63
63
  # turn all the keys to strings (Faraday has issues with symbols under 1.8.7) and resolve UploadableIOs
64
64
  params = args.inject({}) {|hash, kv| hash[kv.first.to_s] = kv.last.is_a?(UploadableIO) ? kv.last.to_upload_io : kv.last; hash}
65
65
 
66
- # figure out our options for this request
66
+ # figure out our options for this request
67
67
  request_options = {:params => (verb == "get" ? params : {})}.merge(http_options || {}).merge(process_options(options))
68
68
  request_options[:use_ssl] = true if args["access_token"] # require https if there's a token
69
+ if request_options[:use_ssl]
70
+ ssl = (request_options[:ssl] ||= {})
71
+ ssl[:verify] = true unless ssl.has_key?(:verify)
72
+ end
69
73
 
70
74
  # set up our Faraday connection
71
75
  # we have to manually assign params to the URL or the
72
76
  conn = Faraday.new(server(request_options), request_options, &(faraday_middleware || DEFAULT_MIDDLEWARE))
73
77
 
74
78
  response = conn.send(verb, path, (verb == "post" ? params : {}))
79
+
80
+ # Log URL information
81
+ Koala::Utils.debug "#{verb.upcase}: #{path} params: #{params.inspect}"
75
82
  Koala::HTTPService::Response.new(response.status.to_i, response.body, response.headers)
76
83
  end
77
84
 
78
- # Encodes a given hash into a query string.
85
+ # Encodes a given hash into a query string.
79
86
  # This is used mainly by the Batch API nowadays, since Faraday handles this for regular cases.
80
- #
87
+ #
81
88
  # @param params_hash a hash of values to CGI-encode and appropriately join
82
- #
89
+ #
83
90
  # @example
84
91
  # Koala.http_service.encode_params({:a => 2, :b => "My String"})
85
92
  # => "a=2&b=My+String"
@@ -87,14 +94,14 @@ module Koala
87
94
  # @return the appropriately-encoded string
88
95
  def self.encode_params(param_hash)
89
96
  ((param_hash || {}).sort_by{|k, v| k.to_s}.collect do |key_and_value|
90
- key_and_value[1] = MultiJson.encode(key_and_value[1]) unless key_and_value[1].is_a? String
97
+ key_and_value[1] = MultiJson.dump(key_and_value[1]) unless key_and_value[1].is_a? String
91
98
  "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
92
99
  end).join("&")
93
100
  end
94
-
101
+
95
102
  # deprecations
96
103
  # not elegant or compact code, but temporary
97
-
104
+
98
105
  # @private
99
106
  def self.always_use_ssl
100
107
  Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
@@ -106,7 +113,7 @@ module Koala
106
113
  Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
107
114
  http_options[:use_ssl] = value
108
115
  end
109
-
116
+
110
117
  # @private
111
118
  def self.timeout
112
119
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
@@ -118,7 +125,7 @@ module Koala
118
125
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
119
126
  http_options[:timeout] = value
120
127
  end
121
-
128
+
122
129
  # @private
123
130
  def self.timeout
124
131
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
@@ -130,7 +137,7 @@ module Koala
130
137
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
131
138
  http_options[:timeout] = value
132
139
  end
133
-
140
+
134
141
  # @private
135
142
  def self.proxy
136
143
  Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
@@ -142,7 +149,7 @@ module Koala
142
149
  Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
143
150
  http_options[:proxy] = value
144
151
  end
145
-
152
+
146
153
  # @private
147
154
  def self.ca_path
148
155
  Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
@@ -154,7 +161,7 @@ module Koala
154
161
  Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
155
162
  (http_options[:ssl] ||= {})[:ca_path] = value
156
163
  end
157
-
164
+
158
165
  # @private
159
166
  def self.ca_file
160
167
  Koala::Utils.deprecate("HTTPService.ca_file is now (HTTPService.http_options[:ssl] ||= {})[:ca_file]; .ca_file will be removed in a future version.")
@@ -179,14 +186,14 @@ module Koala
179
186
  (http_options[:ssl] ||= {})[:verify_mode] = value
180
187
  end
181
188
 
182
- private
183
-
189
+ private
190
+
184
191
  def self.process_options(options)
185
192
  if typhoeus_options = options.delete(:typhoeus_options)
186
193
  Koala::Utils.deprecate("typhoeus_options should now be included directly in the http_options hash. Support for this key will be removed in a future version.")
187
194
  options = options.merge(typhoeus_options)
188
195
  end
189
-
196
+
190
197
  if ca_file = options.delete(:ca_file)
191
198
  Koala::Utils.deprecate("http_options[:ca_file] should now be passed inside (http_options[:ssl] = {}) -- that is, http_options[:ssl][:ca_file]. Support for this key will be removed in a future version.")
192
199
  (options[:ssl] ||= {})[:ca_file] = ca_file
@@ -201,11 +208,11 @@ module Koala
201
208
  Koala::Utils.deprecate("http_options[:verify_mode] should now be passed inside (http_options[:ssl] = {}) -- that is, http_options[:ssl][:verify_mode]. Support for this key will be removed in a future version.")
202
209
  (options[:ssl] ||= {})[:verify_mode] = verify_mode
203
210
  end
204
-
211
+
205
212
  options
206
- end
213
+ end
207
214
  end
208
-
215
+
209
216
  # @private
210
217
  module TyphoeusService
211
218
  def self.deprecated_interface
data/lib/koala/oauth.rb CHANGED
@@ -229,7 +229,7 @@ module Koala
229
229
  raise 'SignedRequest: Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
230
230
 
231
231
  signature = base64_url_decode(encoded_sig).unpack("H*").first
232
- envelope = MultiJson.decode(base64_url_decode(encoded_envelope))
232
+ envelope = MultiJson.load(base64_url_decode(encoded_envelope))
233
233
 
234
234
  raise "SignedRequest: Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
235
235
 
@@ -260,7 +260,7 @@ module Koala
260
260
  })
261
261
  end
262
262
 
263
- MultiJson.decode(response)
263
+ MultiJson.load(response)
264
264
  end
265
265
 
266
266
  # @deprecated (see #get_token_info_from_session_keys)
@@ -285,7 +285,7 @@ module Koala
285
285
  result = fetch_token_string(args, post, "access_token", options)
286
286
 
287
287
  # if we have an error, parse the error JSON and raise an error
288
- raise APIError.new((MultiJson.decode(result)["error"] rescue nil) || {}) if result =~ /error/
288
+ raise APIError.new((MultiJson.load(result)["error"] rescue nil) || {}) if result =~ /error/
289
289
 
290
290
  # otherwise, parse the access token
291
291
  parse_access_token(result)
@@ -325,6 +325,7 @@ module Koala
325
325
 
326
326
  components.merge(token_info) if token_info
327
327
  else
328
+ Koala::Utils.logger.warn("Signed cookie didn't contain Facebook OAuth code! Components: #{components}")
328
329
  nil
329
330
  end
330
331
  end
data/lib/koala/utils.rb CHANGED
@@ -1,12 +1,27 @@
1
1
  module Koala
2
2
  module Utils
3
3
 
4
+ # Utility methods used by Koala.
5
+ require 'logger'
6
+ require 'forwardable'
7
+
8
+ extend Forwardable
9
+ extend self
10
+
11
+ def_delegators :logger, :debug, :info, :warn, :error, :fatal, :level, :level=
12
+
13
+ # The Koala logger, an instance of the standard Ruby logger, pointing to STDOUT by default.
14
+ # In Rails projects, you can set this to Rails.logger.
15
+ attr_accessor :logger
16
+ self.logger = Logger.new(STDOUT)
17
+ self.logger.level = Logger::ERROR
18
+
4
19
  # @private
5
20
  DEPRECATION_PREFIX = "KOALA: Deprecation warning: "
6
21
 
7
- # Prints a deprecation message.
22
+ # Prints a deprecation message.
8
23
  # Each individual message will only be printed once to avoid spamming.
9
- def self.deprecate(message)
24
+ def deprecate(message)
10
25
  @posted_deprecations ||= []
11
26
  unless @posted_deprecations.include?(message)
12
27
  # only include each message once
data/lib/koala/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "1.4.0"
3
- end
2
+ VERSION = "1.5.0"
3
+ end
data/readme.md CHANGED
@@ -23,17 +23,17 @@ Or in Bundler:
23
23
  Graph API
24
24
  ----
25
25
  The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
26
-
26
+
27
27
  @graph = Koala::Facebook::API.new(oauth_access_token)
28
28
  # in 1.1 or earlier, use GraphAPI instead of API
29
-
29
+
30
30
  profile = @graph.get_object("me")
31
31
  friends = @graph.get_connections("me", "friends")
32
- @graph.put_object("me", "feed", :message => "I am writing on my wall!")
33
-
32
+ @graph.put_connections("me", "feed", :message => "I am writing on my wall!")
33
+
34
34
  # three-part queries are easy too!
35
35
  @graph.get_connections("me", "mutualfriends/#{friend_id}")
36
-
36
+
37
37
  # you can even use the new Timeline API
38
38
  # see https://developers.facebook.com/docs/beta/opengraph/tutorial/
39
39
  @graph.put_connections("me", "namespace:action", :object => object_url)
@@ -70,7 +70,7 @@ Fortunately, Koala supports the REST API using the very same interface; to use t
70
70
 
71
71
  @rest = Koala::Facebook::API.new(oauth_access_token)
72
72
  # in 1.1 or earlier, use RestAPI instead of API
73
-
73
+
74
74
  @rest.fql_query(my_fql_query) # convenience method
75
75
  @rest.fql_multiquery(fql_query_hash) # convenience method
76
76
  @rest.rest_call("stream.publish", arguments_hash) # generic version
@@ -79,11 +79,11 @@ Of course, you can use the Graph API methods on the same object -- the power of
79
79
 
80
80
  @api = Koala::Facebook::API.new(oauth_access_token)
81
81
  # in 1.1 or earlier, use GraphAndRestAPI instead of API
82
-
82
+
83
83
  @api = Koala::Facebook::API.new(oauth_access_token)
84
84
  fql = @api.fql_query(my_fql_query)
85
85
  @api.put_wall_post(process_result(fql))
86
-
86
+
87
87
 
88
88
  OAuth
89
89
  -----
@@ -91,7 +91,7 @@ You can use the Graph and REST APIs without an OAuth access token, but the real
91
91
 
92
92
  @oauth = Koala::Facebook::OAuth.new(app_id, app_secret, callback_url)
93
93
 
94
- If your application uses Koala and the Facebook [JavaScript SDK](http://github.com/facebook/connect-js) (formerly Facebook Connect), you can use the OAuth class to parse the cookies:
94
+ If your application uses Koala and the Facebook [JavaScript SDK](http://github.com/facebook/facebook-js-sdk) (formerly Facebook Connect), you can use the OAuth class to parse the cookies:
95
95
 
96
96
  @oauth.get_user_from_cookies(cookies) # gets the user's ID
97
97
  @oauth.get_user_info_from_cookies(cookies) # parses and returns the entire hash
@@ -166,7 +166,7 @@ Koala uses Faraday to make HTTP requests, which means you have complete control
166
166
  }
167
167
  # or on a per-request basis
168
168
  @api.get_object(id, args_hash, { :timeout => 10 })
169
-
169
+
170
170
  The <a href="https://github.com/arsduo/koala/wiki/HTTP-Services">HTTP Services wiki page</a> has more information on what options are available, as well as on how to configure your own Faraday middleware stack (for instance, to implement request logging).
171
171
 
172
172
  See examples, ask questions