koala 2.5.0 → 3.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -3
- data/Gemfile +1 -1
- data/ISSUE_TEMPLATE +25 -0
- data/PULL_REQUEST_TEMPLATE +11 -0
- data/changelog.md +66 -4
- data/code_of_conduct.md +64 -12
- data/koala.gemspec +3 -0
- data/lib/koala/api/batch_operation.rb +3 -6
- data/lib/koala/api/{graph_api.rb → graph_api_methods.rb} +13 -102
- data/lib/koala/api/graph_batch_api.rb +112 -65
- data/lib/koala/api/graph_collection.rb +19 -12
- data/lib/koala/api/graph_error_checker.rb +1 -1
- data/lib/koala/api.rb +49 -25
- data/lib/koala/configuration.rb +49 -0
- data/lib/koala/errors.rb +1 -1
- data/lib/koala/http_service/multipart_request.rb +6 -10
- data/lib/koala/http_service/request.rb +135 -0
- data/lib/koala/http_service/response.rb +6 -4
- data/lib/koala/http_service/uploadable_io.rb +0 -4
- data/lib/koala/http_service.rb +18 -76
- data/lib/koala/oauth.rb +7 -7
- data/lib/koala/realtime_updates.rb +26 -21
- data/lib/koala/test_users.rb +9 -8
- data/lib/koala/version.rb +1 -1
- data/lib/koala.rb +6 -8
- data/readme.md +50 -109
- data/spec/cases/api_spec.rb +99 -69
- data/spec/cases/configuration_spec.rb +11 -0
- data/spec/cases/graph_api_batch_spec.rb +73 -42
- data/spec/cases/graph_api_spec.rb +15 -29
- data/spec/cases/graph_collection_spec.rb +47 -34
- data/spec/cases/graph_error_checker_spec.rb +6 -1
- data/spec/cases/http_service/request_spec.rb +242 -0
- data/spec/cases/http_service/response_spec.rb +24 -0
- data/spec/cases/http_service_spec.rb +102 -296
- data/spec/cases/koala_spec.rb +7 -5
- data/spec/cases/oauth_spec.rb +40 -1
- data/spec/cases/realtime_updates_spec.rb +51 -13
- data/spec/cases/test_users_spec.rb +56 -2
- data/spec/cases/uploadable_io_spec.rb +31 -31
- data/spec/fixtures/cat.m4v +0 -0
- data/spec/fixtures/facebook_data.yml +4 -6
- data/spec/fixtures/mock_facebook_responses.yml +29 -69
- data/spec/fixtures/vcr_cassettes/app_test_accounts.yml +97 -0
- data/spec/integration/graph_collection_spec.rb +8 -5
- data/spec/spec_helper.rb +2 -2
- data/spec/support/graph_api_shared_examples.rb +143 -336
- data/spec/support/koala_test.rb +8 -10
- data/spec/support/mock_http_service.rb +9 -9
- data/spec/support/uploadable_io_shared_examples.rb +4 -4
- metadata +31 -11
- data/.autotest +0 -12
- data/Guardfile +0 -6
- data/autotest/discover.rb +0 -1
- data/lib/koala/api/rest_api.rb +0 -135
- data/spec/support/rest_api_shared_examples.rb +0 -168
data/lib/koala/http_service.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'faraday'
|
|
|
2
2
|
require 'koala/http_service/multipart_request'
|
|
3
3
|
require 'koala/http_service/uploadable_io'
|
|
4
4
|
require 'koala/http_service/response'
|
|
5
|
+
require 'koala/http_service/request'
|
|
5
6
|
|
|
6
7
|
module Koala
|
|
7
8
|
module HTTPService
|
|
@@ -23,98 +24,46 @@ module Koala
|
|
|
23
24
|
builder.adapter Faraday.default_adapter
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
# Default
|
|
27
|
-
#
|
|
27
|
+
# Default server information for Facebook. These can be overridden by setting config values.
|
|
28
|
+
# See Koala.config.
|
|
28
29
|
DEFAULT_SERVERS = {
|
|
29
30
|
:graph_server => 'graph.facebook.com',
|
|
30
31
|
:dialog_host => 'www.facebook.com',
|
|
31
|
-
:rest_server => 'api.facebook.com',
|
|
32
|
-
# certain Facebook services (beta, video) require you to access different
|
|
33
|
-
# servers. If you're using your own servers, for instance, for a proxy,
|
|
34
|
-
# you can change both the matcher and the replacement values.
|
|
35
|
-
# So for instance, if you're talking to fbproxy.mycompany.com, you could
|
|
36
|
-
# set up beta.fbproxy.mycompany.com for FB's beta tier, and set the
|
|
37
|
-
# matcher to /\.fbproxy/ and the beta_replace to '.beta.fbproxy'.
|
|
38
32
|
:host_path_matcher => /\.facebook/,
|
|
39
33
|
:video_replace => '-video.facebook',
|
|
40
34
|
:beta_replace => '.beta.facebook'
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
# The address of the appropriate Facebook server.
|
|
44
|
-
#
|
|
45
|
-
# @param options various flags to indicate which server to use.
|
|
46
|
-
# @option options :rest_api use the old REST API instead of the Graph API
|
|
47
|
-
# @option options :video use the server designated for video uploads
|
|
48
|
-
# @option options :beta use the beta tier
|
|
49
|
-
# @option options :use_ssl force https, even if not needed
|
|
50
|
-
#
|
|
51
|
-
# @return a complete server address with protocol
|
|
52
|
-
def self.server(options = {})
|
|
53
|
-
server = "#{options[:rest_api] ? Koala.config.rest_server : Koala.config.graph_server}"
|
|
54
|
-
server.gsub!(Koala.config.host_path_matcher, Koala.config.video_replace) if options[:video]
|
|
55
|
-
server.gsub!(Koala.config.host_path_matcher, Koala.config.beta_replace) if options[:beta]
|
|
56
|
-
"#{options[:use_ssl] ? "https" : "http"}://#{server}"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
37
|
# Makes a request directly to Facebook.
|
|
60
38
|
# @note You'll rarely need to call this method directly.
|
|
61
39
|
#
|
|
62
40
|
# @see Koala::Facebook::API#api
|
|
63
41
|
# @see Koala::Facebook::GraphAPIMethods#graph_call
|
|
64
|
-
# @see Koala::Facebook::RestAPIMethods#rest_call
|
|
65
42
|
#
|
|
66
|
-
# @param
|
|
67
|
-
# @param args (see Koala::Facebook::API#api)
|
|
68
|
-
# @param verb the HTTP method to use.
|
|
69
|
-
# If not get or post, this will be turned into a POST request with the appropriate :method
|
|
70
|
-
# specified in the arguments.
|
|
71
|
-
# @param options (see Koala::Facebook::API#api)
|
|
43
|
+
# @param request a Koala::HTTPService::Request object
|
|
72
44
|
#
|
|
73
45
|
# @raise an appropriate connection error if unable to make the request to Facebook
|
|
74
46
|
#
|
|
75
47
|
# @return [Koala::HTTPService::Response] a response object representing the results from Facebook
|
|
76
|
-
def self.make_request(
|
|
77
|
-
# if the verb isn't get or post, send it as a post argument with a method param
|
|
78
|
-
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
79
|
-
|
|
80
|
-
# turn all the keys to strings (Faraday has issues with symbols under 1.8.7) and resolve UploadableIOs
|
|
81
|
-
params = args.inject({}) {|hash, kv| hash[kv.first.to_s] = kv.last.is_a?(UploadableIO) ? kv.last.to_upload_io : kv.last; hash}
|
|
82
|
-
|
|
83
|
-
# figure out our options for this request
|
|
84
|
-
request_options = {:params => (verb == "get" ? params : {})}.merge(http_options || {}).merge(options)
|
|
85
|
-
request_options[:use_ssl] = true if args["access_token"] # require https if there's a token
|
|
86
|
-
if request_options[:use_ssl]
|
|
87
|
-
ssl = (request_options[:ssl] ||= {})
|
|
88
|
-
ssl[:verify] = true unless ssl.has_key?(:verify)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# if an api_version is specified and the path does not already contain
|
|
92
|
-
# one, prepend it to the path
|
|
93
|
-
api_version = request_options[:api_version] || Koala.config.api_version
|
|
94
|
-
if api_version && !path_contains_api_version?(path)
|
|
95
|
-
begins_with_slash = path[0] == "/"
|
|
96
|
-
divider = begins_with_slash ? "" : "/"
|
|
97
|
-
path = "/#{api_version}#{divider}#{path}"
|
|
98
|
-
end
|
|
99
|
-
|
|
48
|
+
def self.make_request(request)
|
|
100
49
|
# set up our Faraday connection
|
|
101
|
-
|
|
102
|
-
conn = Faraday.new(server(request_options), faraday_options(request_options), &(faraday_middleware || DEFAULT_MIDDLEWARE))
|
|
50
|
+
conn = Faraday.new(request.server, faraday_options(request.options), &(faraday_middleware || DEFAULT_MIDDLEWARE))
|
|
103
51
|
|
|
104
|
-
|
|
105
|
-
|
|
52
|
+
if request.verb == "post" && request.json?
|
|
53
|
+
# JSON requires a bit more handling
|
|
54
|
+
# remember, all non-GET requests are turned into POSTs, so this covers everything but GETs
|
|
106
55
|
response = conn.post do |req|
|
|
107
|
-
req.path = path
|
|
56
|
+
req.path = request.path
|
|
108
57
|
req.headers["Content-Type"] = "application/json"
|
|
109
|
-
req.body =
|
|
58
|
+
req.body = request.post_args.to_json
|
|
110
59
|
req
|
|
111
60
|
end
|
|
112
61
|
else
|
|
113
|
-
response = conn.send(verb, path,
|
|
62
|
+
response = conn.send(request.verb, request.path, request.post_args)
|
|
114
63
|
end
|
|
115
64
|
|
|
116
65
|
# Log URL information
|
|
117
|
-
Koala::Utils.debug "#{verb.upcase}: #{path} params: #{
|
|
66
|
+
Koala::Utils.debug "#{request.verb.upcase}: #{request.path} params: #{request.raw_args.inspect}"
|
|
118
67
|
Koala::HTTPService::Response.new(response.status.to_i, response.body, response.headers)
|
|
119
68
|
end
|
|
120
69
|
|
|
@@ -130,21 +79,14 @@ module Koala
|
|
|
130
79
|
# @return the appropriately-encoded string
|
|
131
80
|
def self.encode_params(param_hash)
|
|
132
81
|
((param_hash || {}).sort_by{|k, v| k.to_s}.collect do |key_and_value|
|
|
133
|
-
|
|
134
|
-
|
|
82
|
+
value = key_and_value[1]
|
|
83
|
+
unless value.is_a? String
|
|
84
|
+
value = value.to_json
|
|
85
|
+
end
|
|
86
|
+
"#{key_and_value[0].to_s}=#{CGI.escape value}"
|
|
135
87
|
end).join("&")
|
|
136
88
|
end
|
|
137
89
|
|
|
138
|
-
# Determines whether a given path already contains an API version.
|
|
139
|
-
#
|
|
140
|
-
# @param path the URL path.
|
|
141
|
-
#
|
|
142
|
-
# @return true or false accordingly.
|
|
143
|
-
def self.path_contains_api_version?(path)
|
|
144
|
-
match = /^\/?(v\d+(?:\.\d+)?)\//.match(path)
|
|
145
|
-
!!(match && match[1])
|
|
146
|
-
end
|
|
147
|
-
|
|
148
90
|
private
|
|
149
91
|
|
|
150
92
|
def self.faraday_options(options)
|
data/lib/koala/oauth.rb
CHANGED
|
@@ -12,10 +12,10 @@ module Koala
|
|
|
12
12
|
# @param app_id [String, Integer] a Facebook application ID
|
|
13
13
|
# @param app_secret a Facebook application secret
|
|
14
14
|
# @param oauth_callback_url the URL in your app to which users authenticating with OAuth will be sent
|
|
15
|
-
def initialize(app_id, app_secret, oauth_callback_url = nil)
|
|
16
|
-
@app_id = app_id
|
|
17
|
-
@app_secret = app_secret
|
|
18
|
-
@oauth_callback_url = oauth_callback_url
|
|
15
|
+
def initialize(app_id = nil, app_secret = nil, oauth_callback_url = nil)
|
|
16
|
+
@app_id = app_id || Koala.config.app_id
|
|
17
|
+
@app_secret = app_secret || Koala.config.app_secret
|
|
18
|
+
@oauth_callback_url = oauth_callback_url || Koala.config.oauth_callback_url
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# Parses the cookie set Facebook's JavaScript SDK.
|
|
@@ -134,7 +134,7 @@ module Koala
|
|
|
134
134
|
if response == ''
|
|
135
135
|
raise BadFacebookResponse.new(200, '', 'generate_client_code received an error: empty response body')
|
|
136
136
|
else
|
|
137
|
-
result = JSON.
|
|
137
|
+
result = JSON.parse(response)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
result.has_key?('code') ? result['code'] : raise(Koala::KoalaError.new("Facebook returned a valid response without the expected 'code' in the body (response = #{response})"))
|
|
@@ -240,7 +240,7 @@ module Koala
|
|
|
240
240
|
raise OAuthSignatureError, 'Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
|
|
241
241
|
|
|
242
242
|
signature = base64_url_decode(encoded_sig).unpack("H*").first
|
|
243
|
-
envelope = JSON.
|
|
243
|
+
envelope = JSON.parse(base64_url_decode(encoded_envelope))
|
|
244
244
|
|
|
245
245
|
raise OAuthSignatureError, "Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
|
|
246
246
|
|
|
@@ -260,7 +260,7 @@ module Koala
|
|
|
260
260
|
end
|
|
261
261
|
|
|
262
262
|
def parse_access_token(response_text)
|
|
263
|
-
JSON.
|
|
263
|
+
JSON.parse(response_text)
|
|
264
264
|
rescue JSON::ParserError
|
|
265
265
|
response_text.split("&").inject({}) do |hash, bit|
|
|
266
266
|
key, value = bit.split("=")
|
|
@@ -7,9 +7,6 @@ module Koala
|
|
|
7
7
|
# @note: to subscribe to real-time updates, you must have an application access token
|
|
8
8
|
# or provide the app secret when initializing your RealtimeUpdates object.
|
|
9
9
|
|
|
10
|
-
# The application API interface used to communicate with Facebook.
|
|
11
|
-
# @return [Koala::Facebook::API]
|
|
12
|
-
attr_reader :api
|
|
13
10
|
attr_reader :app_id, :app_access_token, :secret
|
|
14
11
|
|
|
15
12
|
# Create a new RealtimeUpdates instance.
|
|
@@ -23,20 +20,27 @@ module Koala
|
|
|
23
20
|
#
|
|
24
21
|
# @raise ArgumentError if the application ID and one of the app access token or the secret are not provided.
|
|
25
22
|
def initialize(options = {})
|
|
26
|
-
@app_id = options[:app_id]
|
|
27
|
-
@app_access_token = options[:app_access_token]
|
|
28
|
-
@secret = options[:secret]
|
|
23
|
+
@app_id = options[:app_id] || Koala.config.app_id
|
|
24
|
+
@app_access_token = options[:app_access_token] || Koala.config.app_access_token
|
|
25
|
+
@secret = options[:secret] || Koala.config.app_secret
|
|
29
26
|
unless @app_id && (@app_access_token || @secret) # make sure we have what we need
|
|
30
27
|
raise ArgumentError, "Initialize must receive a hash with :app_id and either :app_access_token or :secret! (received #{options.inspect})"
|
|
31
28
|
end
|
|
29
|
+
end
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
# The app access token, either provided on initialization or fetched from Facebook using the
|
|
32
|
+
# app_id and secret.
|
|
33
|
+
def app_access_token
|
|
34
|
+
# If a token isn't provided but we need it, fetch it
|
|
35
|
+
@app_access_token ||= Koala::Facebook::OAuth.new(@app_id, @secret).get_app_access_token
|
|
36
|
+
end
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
# The application API interface used to communicate with Facebook.
|
|
39
|
+
# @return [Koala::Facebook::API]
|
|
40
|
+
def api
|
|
41
|
+
# Only instantiate the API if needed. validate_update doesn't require it, so we shouldn't
|
|
42
|
+
# make an unnecessary request to get the app_access_token.
|
|
43
|
+
@api ||= API.new(app_access_token)
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
# Subscribe to realtime updates for certain fields on a given object (user, page, etc.).
|
|
@@ -60,7 +64,7 @@ module Koala
|
|
|
60
64
|
:callback_url => callback_url,
|
|
61
65
|
}.merge(verify_token ? {:verify_token => verify_token} : {})
|
|
62
66
|
# a subscription is a success if Facebook returns a 200 (after hitting your server for verification)
|
|
63
|
-
|
|
67
|
+
api.graph_call(subscription_path, args, 'post', options)
|
|
64
68
|
end
|
|
65
69
|
|
|
66
70
|
# Unsubscribe from updates for a particular object or from updates.
|
|
@@ -71,7 +75,7 @@ module Koala
|
|
|
71
75
|
#
|
|
72
76
|
# @raise A subclass of Koala::Facebook::APIError if the subscription request failed.
|
|
73
77
|
def unsubscribe(object = nil, options = {})
|
|
74
|
-
|
|
78
|
+
api.graph_call(subscription_path, object ? {:object => object} : {}, "delete", options)
|
|
75
79
|
end
|
|
76
80
|
|
|
77
81
|
# List all active subscriptions for this application.
|
|
@@ -80,7 +84,7 @@ module Koala
|
|
|
80
84
|
#
|
|
81
85
|
# @return [Array] a list of active subscriptions
|
|
82
86
|
def list_subscriptions(options = {})
|
|
83
|
-
|
|
87
|
+
api.graph_call(subscription_path, {}, "get", options)
|
|
84
88
|
end
|
|
85
89
|
|
|
86
90
|
# As a security measure (to prevent DDoS attacks), Facebook sends a verification request to your server
|
|
@@ -129,12 +133,13 @@ module Koala
|
|
|
129
133
|
raise AppSecretNotDefinedError, "You must init RealtimeUpdates with your app secret in order to validate updates"
|
|
130
134
|
end
|
|
131
135
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE']
|
|
137
|
+
return unless request_signature
|
|
138
|
+
|
|
139
|
+
signature_parts = request_signature.split("sha1=")
|
|
140
|
+
request_signature = signature_parts[1]
|
|
141
|
+
calculated_signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body)
|
|
142
|
+
calculated_signature == request_signature
|
|
138
143
|
end
|
|
139
144
|
|
|
140
145
|
# The Facebook subscription management URL for your application.
|
data/lib/koala/test_users.rb
CHANGED
|
@@ -14,7 +14,6 @@ module Koala
|
|
|
14
14
|
#
|
|
15
15
|
# See http://developers.facebook.com/docs/test_users/.
|
|
16
16
|
class TestUsers
|
|
17
|
-
|
|
18
17
|
# The application API interface used to communicate with Facebook.
|
|
19
18
|
# @return [Koala::Facebook::API]
|
|
20
19
|
attr_reader :api
|
|
@@ -31,9 +30,10 @@ module Koala
|
|
|
31
30
|
#
|
|
32
31
|
# @raise ArgumentError if the application ID and one of the app access token or the secret are not provided.
|
|
33
32
|
def initialize(options = {})
|
|
34
|
-
@app_id = options[:app_id]
|
|
35
|
-
@app_access_token = options[:app_access_token]
|
|
36
|
-
@secret = options[:secret]
|
|
33
|
+
@app_id = options[:app_id] || Koala.config.app_id
|
|
34
|
+
@app_access_token = options[:app_access_token] || Koala.config.app_access_token
|
|
35
|
+
@secret = options[:secret] || Koala.config.app_secret
|
|
36
|
+
|
|
37
37
|
unless @app_id && (@app_access_token || @secret) # make sure we have what we need
|
|
38
38
|
raise ArgumentError, "Initialize must receive a hash with :app_id and either :app_access_token or :secret! (received #{options.inspect})"
|
|
39
39
|
end
|
|
@@ -146,11 +146,12 @@ module Koala
|
|
|
146
146
|
raise ArgumentError, "TestUsers#befriend requires hash arguments for both users with id and access_token"
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
u1_graph_api = API.new(user1_token)
|
|
150
|
-
u2_graph_api = API.new(user2_token)
|
|
149
|
+
u1_graph_api = API.new(user1_token, secret)
|
|
150
|
+
u2_graph_api = API.new(user2_token, secret)
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
# if we have a secret token, flag that we want the appsecret_proof to be generated
|
|
153
|
+
u1_graph_api.graph_call("#{user1_id}/friends/#{user2_id}", {}, "post", options.merge(appsecret_proof: !!secret)) &&
|
|
154
|
+
u2_graph_api.graph_call("#{user2_id}/friends/#{user1_id}", {}, "post", options.merge(appsecret_proof: !!secret))
|
|
154
155
|
end
|
|
155
156
|
|
|
156
157
|
# Create a network of test users, all of whom are friends and have the same permissions.
|
data/lib/koala/version.rb
CHANGED
data/lib/koala.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'json'
|
|
|
5
5
|
# include koala modules
|
|
6
6
|
require 'koala/errors'
|
|
7
7
|
require 'koala/api'
|
|
8
|
+
require 'koala/api/graph_batch_api'
|
|
8
9
|
require 'koala/oauth'
|
|
9
10
|
require 'koala/realtime_updates'
|
|
10
11
|
require 'koala/test_users'
|
|
@@ -13,6 +14,7 @@ require 'koala/test_users'
|
|
|
13
14
|
require 'koala/http_service'
|
|
14
15
|
|
|
15
16
|
# miscellaneous
|
|
17
|
+
require 'koala/configuration'
|
|
16
18
|
require 'koala/utils'
|
|
17
19
|
require 'koala/version'
|
|
18
20
|
require 'ostruct'
|
|
@@ -36,14 +38,10 @@ module Koala
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
# Allows you to control various Koala configuration options.
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
# (see HTTPService::DEFAULT_SERVERS) if you want to run requests through
|
|
42
|
-
# other servers.
|
|
43
|
-
# * api_version: controls which Facebook API version to use (v1.0, v2.0,
|
|
44
|
-
# etc)
|
|
41
|
+
# NOTE: this is not currently threadsafe.
|
|
42
|
+
# See Koala::Configuration.
|
|
45
43
|
def config
|
|
46
|
-
@config ||=
|
|
44
|
+
@config ||= Configuration.new
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
# Used for testing.
|
|
@@ -61,7 +59,7 @@ module Koala
|
|
|
61
59
|
|
|
62
60
|
# An convenenient alias to Koala.http_service.make_request.
|
|
63
61
|
def self.make_request(path, args, verb, options = {})
|
|
64
|
-
http_service.make_request(path, args, verb, options)
|
|
62
|
+
http_service.make_request(HTTPService::Request.new(path: path, args: args, verb: verb, options: options))
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
# we use Faraday as our main service, with mock as the other main one
|
data/readme.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Koala [](https://rubygems.org/gems/koala) [](https://gemnasium.com/arsduo/koala) [](http://travis-ci.org/arsduo/koala) [](https://codeclimate.com/github/arsduo/koala) [](https://codeclimate.com/github/arsduo/koala)
|
|
2
2
|
====
|
|
3
|
-
[Koala](http://github.com/arsduo/koala) is a Facebook library for Ruby, supporting the Graph API (including the batch requests and photo uploads),
|
|
3
|
+
[Koala](http://github.com/arsduo/koala) is a Facebook library for Ruby, supporting the Graph API (including the batch requests and photo uploads), realtime updates, test users, and OAuth validation. We wrote Koala with four goals:
|
|
4
4
|
|
|
5
5
|
* Lightweight: Koala should be as light and simple as Facebook’s own libraries, providing API accessors and returning simple JSON.
|
|
6
6
|
* Fast: Koala should, out of the box, be quick. Out of the box, we use Facebook's faster read-only servers when possible and if available, the Typhoeus gem to make snappy Facebook requests. Of course, that brings us to our next topic:
|
|
7
|
-
* Flexible: Koala should be useful to everyone, regardless of their current configuration. We support
|
|
7
|
+
* Flexible: Koala should be useful to everyone, regardless of their current configuration. We support all currently-supported Ruby versions (MRI 2.1-2.4) and Koala should work on JRuby and Rubinius.
|
|
8
8
|
* Tested: Koala should have complete test coverage, so you can rely on it. Our test coverage is complete and can be run against either mocked responses or the live Facebook servers; we're also on [Travis CI](http://travis-ci.org/arsduo/koala/).
|
|
9
9
|
|
|
10
10
|
**Found a bug? Interested in contributing?** Check out the Maintenance section below!
|
|
@@ -12,9 +12,12 @@ Koala [](https://rubygems.org/
|
|
|
12
12
|
Installation
|
|
13
13
|
------------
|
|
14
14
|
|
|
15
|
+
**Koala 3.0 is out! There should be no significant changes** for most users. If you encounter any
|
|
16
|
+
problems, please file an issue and I'll take a look.
|
|
17
|
+
|
|
15
18
|
In Bundler:
|
|
16
19
|
```ruby
|
|
17
|
-
gem "koala"
|
|
20
|
+
gem "koala"
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
Otherwise:
|
|
@@ -22,25 +25,41 @@ Otherwise:
|
|
|
22
25
|
[sudo|rvm] gem install koala
|
|
23
26
|
```
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
Configuration
|
|
29
|
+
-------------
|
|
30
|
+
|
|
31
|
+
Most applications will only use one application configuration. Rather than having to provide that
|
|
32
|
+
value every time, you can configure Koala to use global settings:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
# In Rails, you could put this in config/initializers/koala.rb
|
|
36
|
+
Koala.configure do |config|
|
|
37
|
+
config.access_token = MY_TOKEN
|
|
38
|
+
config.app_access_token = MY_APP_ACCESS_TOKEN
|
|
39
|
+
config.app_id = MY_APP_ID
|
|
40
|
+
config.app_secret = MY_APP_SECRET
|
|
41
|
+
# See Koala::Configuration for more options, including details on how to send requests through
|
|
42
|
+
# your own proxy servers.
|
|
43
|
+
end
|
|
44
|
+
```
|
|
27
45
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
details.
|
|
46
|
+
**Note**: this is not currently threadsafe. (PRs welcome as long as they support both threaded and
|
|
47
|
+
non-threaded configuration.)
|
|
31
48
|
|
|
32
49
|
Graph API
|
|
33
50
|
---------
|
|
34
51
|
|
|
35
|
-
The Graph API is the
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
The Graph API is the interface to Facebook's data. Using it with Koala is quite straightforward.
|
|
53
|
+
First, you'll need an access token, which you can get through Facebook's [Graph API
|
|
54
|
+
Explorer](https://developers.facebook.com/tools/explorer) (click on 'Get Access Token').
|
|
55
|
+
|
|
38
56
|
Then, go exploring:
|
|
39
57
|
|
|
40
58
|
```ruby
|
|
41
59
|
require 'koala'
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
|
|
61
|
+
# access_token and other values aren't required if you set the defaults as described above
|
|
62
|
+
@graph = Koala::Facebook::API.new(access_token)
|
|
44
63
|
|
|
45
64
|
profile = @graph.get_object("me")
|
|
46
65
|
friends = @graph.get_connections("me", "friends")
|
|
@@ -56,14 +75,14 @@ friends = @graph.get_connections("me", "friends")
|
|
|
56
75
|
# For extra security (recommended), you can provide an appsecret parameter,
|
|
57
76
|
# tying your access tokens to your app secret.
|
|
58
77
|
# (See https://developers.facebook.com/docs/reference/api/securing-graph-api/
|
|
59
|
-
|
|
78
|
+
|
|
79
|
+
# You may need to turn on 'Require proof on all calls' in the advanced section
|
|
60
80
|
# of your app's settings when doing this.
|
|
61
|
-
@graph = Koala::Facebook::API.new(
|
|
81
|
+
@graph = Koala::Facebook::API.new(access_token, app_secret)
|
|
62
82
|
|
|
63
83
|
# Facebook is now versioning their API. # If you don't specify a version, Facebook
|
|
64
|
-
# will default to the oldest version your app is allowed to use.
|
|
65
|
-
#
|
|
66
|
-
# https://developers.facebook.com/docs/apps/versions for more information.
|
|
84
|
+
# will default to the oldest version your app is allowed to use.
|
|
85
|
+
# See https://developers.facebook.com/docs/apps/versions for more information.
|
|
67
86
|
#
|
|
68
87
|
# You can specify version either globally:
|
|
69
88
|
Koala.config.api_version = "v2.0"
|
|
@@ -115,85 +134,20 @@ the results apart from a long list of array entries:
|
|
|
115
134
|
|
|
116
135
|
Check out the wiki for more details and examples.
|
|
117
136
|
|
|
118
|
-
|
|
119
|
-
------------
|
|
120
|
-
|
|
121
|
-
Where the Graph API and the old REST API overlap, you should choose the Graph API. Unfortunately, that overlap is far from complete, and there are many important API calls that can't yet be done via the Graph.
|
|
122
|
-
|
|
123
|
-
Fortunately, Koala supports the REST API using the very same interface; to use this, instantiate an API:
|
|
124
|
-
```ruby
|
|
125
|
-
@rest = Koala::Facebook::API.new(oauth_access_token)
|
|
126
|
-
|
|
127
|
-
@rest.fql_query(my_fql_query) # convenience method
|
|
128
|
-
@rest.fql_multiquery(fql_query_hash) # convenience method
|
|
129
|
-
@rest.rest_call("stream.publish", arguments_hash) # generic version
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Of course, you can use the Graph API methods on the same object -- the power of two APIs right in the palm of your hand.
|
|
133
|
-
```ruby
|
|
134
|
-
@api = Koala::Facebook::API.new(oauth_access_token)
|
|
135
|
-
fql = @api.fql_query(my_fql_query)
|
|
136
|
-
@api.put_wall_post(process_result(fql))
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Configuration
|
|
140
|
-
-------------
|
|
141
|
-
|
|
142
|
-
You can change the host that koala makes requests to (point to a mock server, apigee, runscope etc..)
|
|
143
|
-
```ruby
|
|
144
|
-
# config/initializers/koala.rb
|
|
145
|
-
require 'koala'
|
|
146
|
-
|
|
147
|
-
Koala.configure do |config|
|
|
148
|
-
config.graph_server = 'my-graph-mock.mysite.com'
|
|
149
|
-
# other common options are `rest_server` and `dialog_host`
|
|
150
|
-
# see lib/koala/http_service.rb
|
|
151
|
-
end
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Of course the defaults are the facebook endpoints and you can additionally configure the beta
|
|
155
|
-
tier and video upload matching and replacement strings.
|
|
156
|
-
|
|
157
|
-
OAuth
|
|
137
|
+
App Access Tokens
|
|
158
138
|
-----
|
|
159
139
|
|
|
160
|
-
You
|
|
140
|
+
You get your application's own access token, which can be used without a user session for subscriptions and certain other requests:
|
|
161
141
|
```ruby
|
|
162
142
|
@oauth = Koala::Facebook::OAuth.new(app_id, app_secret, callback_url)
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
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:
|
|
166
|
-
```ruby
|
|
167
|
-
# parses and returns a hash including the token and the user id
|
|
168
|
-
# NOTE: this method can only be called once per session, as the OAuth code
|
|
169
|
-
# Facebook supplies can only be redeemed once. Your application must handle
|
|
170
|
-
# cross-request storage of this information; you can no longer call this method
|
|
171
|
-
# multiple times.
|
|
172
|
-
@oauth.get_user_info_from_cookies(cookies)
|
|
173
|
-
```
|
|
174
|
-
And if you have to use the more complicated [redirect-based OAuth process](http://developers.facebook.com/docs/authentication/), Koala helps out there, too:
|
|
175
|
-
|
|
176
|
-
```ruby
|
|
177
|
-
# generate authenticating URL
|
|
178
|
-
@oauth.url_for_oauth_code
|
|
179
|
-
# fetch the access token once you have the code
|
|
180
|
-
@oauth.get_access_token(code)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
You can also get your application's own access token, which can be used without a user session for subscriptions and certain other requests:
|
|
184
|
-
```ruby
|
|
185
143
|
@oauth.get_app_access_token
|
|
186
144
|
```
|
|
187
145
|
For those building apps on Facebook, parsing signed requests is simple:
|
|
188
146
|
```ruby
|
|
189
147
|
@oauth.parse_signed_request(signed_request_string)
|
|
190
148
|
```
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
@oauth.get_token_from_session_key(session_key)
|
|
194
|
-
@oauth.get_tokens_from_session_keys(array_of_session_keys)
|
|
195
|
-
```
|
|
196
|
-
That's it! It's pretty simple once you get the hang of it. If you're new to OAuth, though, check out the wiki and the OAuth Playground example site (see below).
|
|
149
|
+
|
|
150
|
+
The OAuth class has additional methods that may occasionally be useful.
|
|
197
151
|
|
|
198
152
|
Real-time Updates
|
|
199
153
|
-----------------
|
|
@@ -202,6 +156,7 @@ Sometimes, reaching out to Facebook is a pain -- let it reach out to you instead
|
|
|
202
156
|
|
|
203
157
|
Koala makes it easy to interact with your applications using the RealtimeUpdates class:
|
|
204
158
|
```ruby
|
|
159
|
+
# This class also supports the defaults as described above
|
|
205
160
|
@updates = Koala::Facebook::RealtimeUpdates.new(app_id: app_id, secret: secret)
|
|
206
161
|
```
|
|
207
162
|
You can do just about anything with your real-time update subscriptions using the RealtimeUpdates class:
|
|
@@ -225,14 +180,16 @@ For more information about meet_challenge and the RealtimeUpdates class, check o
|
|
|
225
180
|
Test Users
|
|
226
181
|
----------
|
|
227
182
|
|
|
228
|
-
We also support the test users API, allowing you to conjure up fake users and command them to do your bidding using the Graph
|
|
183
|
+
We also support the test users API, allowing you to conjure up fake users and command them to do your bidding using the Graph API:
|
|
229
184
|
```ruby
|
|
185
|
+
# This class also supports the defaults as described above
|
|
230
186
|
@test_users = Koala::Facebook::TestUsers.new(app_id: id, secret: secret)
|
|
231
187
|
user = @test_users.create(is_app_installed, desired_permissions)
|
|
232
188
|
user_graph_api = Koala::Facebook::API.new(user["access_token"])
|
|
233
189
|
# or, if you want to make a whole community:
|
|
234
190
|
@test_users.create_network(network_size, is_app_installed, common_permissions)
|
|
235
191
|
```
|
|
192
|
+
|
|
236
193
|
Talking to Facebook
|
|
237
194
|
-------------------
|
|
238
195
|
|
|
@@ -255,14 +212,6 @@ Some resources to help you as you play with Koala and the Graph API:
|
|
|
255
212
|
* Complete Koala documentation <a href="https://github.com/arsduo/koala/wiki">on the wiki</a>
|
|
256
213
|
* Facebook's <a href="http://facebook.stackoverflow.com/">Stack Overflow site</a> is a stupendous place to ask questions, filled with people who will help you figure out what's up with the Facebook API.
|
|
257
214
|
* Facebook's <a href="http://developers.facebook.com/tools/explorer/">Graph API Explorer</a>, where you can play with the Graph API in your browser
|
|
258
|
-
* The Koala-powered <a href="http://oauth.twoalex.com" target="_blank">OAuth Playground</a>, where you can easily generate OAuth access tokens and any other data needed to test out the APIs or OAuth
|
|
259
|
-
* Follow Koala on <a href="http://www.facebook.com/pages/Koala/315368291823667">Facebook</a> and <a href="https://twitter.com/#!/koala_fb">Twitter</a> for SDK updates and occasional news about Facebook API changes.
|
|
260
|
-
|
|
261
|
-
*Note*: I use the Koala issues tracker on Github to triage and address issues
|
|
262
|
-
with the gem itself; if you need help using the Facebook API, the above
|
|
263
|
-
resources will be far more effective. Depending on how much time I have, Github
|
|
264
|
-
issues filed about how to use the Facebook API may be closed with a reference
|
|
265
|
-
to the Facebook Stack Overflow page.
|
|
266
215
|
|
|
267
216
|
Testing
|
|
268
217
|
-------
|
|
@@ -280,26 +229,18 @@ LIVE=true bundle exec rake spec
|
|
|
280
229
|
# you can also test against Facebook's beta tier
|
|
281
230
|
LIVE=true BETA=true bundle exec rake spec
|
|
282
231
|
```
|
|
232
|
+
|
|
283
233
|
By default, the live tests are run against test users, so you can run them as frequently as you want. If you want to run them against a real user, however, you can fill in the OAuth token, code, and access\_token values in spec/fixtures/facebook_data.yml. See the wiki for more details.
|
|
284
234
|
|
|
285
235
|
Maintenance
|
|
286
236
|
-----------
|
|
287
237
|
|
|
288
238
|
_Pull requests_: Koala exists as it does thanks to the amazing support and work of community members of all
|
|
289
|
-
backgrounds and levels of experience. Pull requests are very welcome!
|
|
290
|
-
|
|
239
|
+
backgrounds and levels of experience. Pull requests are very welcome!
|
|
240
|
+
|
|
241
|
+
_Issues_: If you have any questions about the gem, found an issue in the Ruby code or
|
|
242
|
+
documentation, or have another question that isn't right for StackOverflow, just open an issue and fill out the template.
|
|
291
243
|
|
|
292
244
|
Please note that this project is released with a Contributor Code of Conduct. By participating in
|
|
293
245
|
this project you agree to abide by its terms. See
|
|
294
246
|
[code_of_conduct.md](https://github.com/arsduo/koala/blob/master/code_of_conduct.md) for more information.
|
|
295
|
-
|
|
296
|
-
_Schedule_: In order to keep Koala moving forward on a regular and predictable schedule, I will
|
|
297
|
-
address issues and pull requests at least three times a year: late July/early August, late
|
|
298
|
-
December/early January, and late March/early April. I may respond to issues in between maintenance
|
|
299
|
-
periods, but it'll depend on other life/work goings-on.
|
|
300
|
-
|
|
301
|
-
Breaking/new Facebook changes and other urgent issues obviously will get addressed much more
|
|
302
|
-
quickly. (We've never had a security issue, but obviously that would be priority 0.)
|
|
303
|
-
|
|
304
|
-
Have questions? Found a breaking bug or urgent issue? [Tweet at me](http://twitter.com/arsduo) --
|
|
305
|
-
I'm always happy to respond.
|