koala 0.9.0 → 1.0.0.beta
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 +33 -7
- data/Manifest +6 -14
- data/Rakefile +4 -3
- data/koala.gemspec +13 -8
- data/lib/koala/graph_api.rb +16 -3
- data/lib/koala/http_services.rb +100 -16
- data/lib/koala/rest_api.rb +73 -6
- data/lib/koala/test_users.rb +72 -0
- data/lib/koala.rb +101 -71
- data/readme.md +14 -13
- data/spec/facebook_data.yml +14 -8
- data/spec/koala/api_base_tests.rb +7 -0
- data/spec/koala/assets/beach.jpg +0 -0
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +5 -1
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +9 -4
- data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +10 -61
- data/spec/koala/graph_api/graph_api_tests.rb +86 -0
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +130 -126
- data/spec/koala/graph_api/graph_collection_tests.rb +2 -2
- data/spec/koala/live_testing_data_helper.rb +40 -12
- data/spec/koala/net_http_service_tests.rb +401 -152
- data/spec/koala/oauth/oauth_tests.rb +41 -72
- data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +7 -76
- data/spec/koala/rest_api/rest_api_tests.rb +118 -0
- data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +6 -4
- data/spec/koala/test_users/test_users_tests.rb +208 -0
- data/spec/koala/typhoeus_service_tests.rb +156 -0
- data/spec/koala_spec_helper.rb +43 -4
- data/spec/koala_spec_without_mocks.rb +4 -4
- data/spec/mock_facebook_responses.yml +69 -3
- data/spec/mock_http_service.rb +16 -1
- metadata +49 -23
- data/examples/oauth_playground/Capfile +0 -2
- data/examples/oauth_playground/LICENSE +0 -22
- data/examples/oauth_playground/Rakefile +0 -4
- data/examples/oauth_playground/config/deploy.rb +0 -39
- data/examples/oauth_playground/config/facebook.yml +0 -13
- data/examples/oauth_playground/config.ru +0 -27
- data/examples/oauth_playground/lib/load_facebook.rb +0 -3
- data/examples/oauth_playground/lib/oauth_playground.rb +0 -187
- data/examples/oauth_playground/readme.md +0 -8
- data/examples/oauth_playground/spec/oauth_playground_spec.rb +0 -35
- data/examples/oauth_playground/spec/spec_helper.rb +0 -36
- data/examples/oauth_playground/tmp/restart.txt +0 -0
- data/examples/oauth_playground/views/index.erb +0 -206
- data/examples/oauth_playground/views/layout.erb +0 -39
data/CHANGELOG
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
|
+
v1.0
|
|
2
|
+
New methods:
|
|
3
|
+
-- Photo and file upload now supported through #put_picture and general support for file hashes (see documentation)
|
|
4
|
+
-- Added a delete_like method (thanks to wassem)
|
|
5
|
+
Internal improvements:
|
|
6
|
+
-- For public requests, Koala now uses http by default (instead of https) to improve speed
|
|
7
|
+
-- This can be overridden through Koala.always_use_ssl= or by passing :use_ssl => true in the options hash for an api call
|
|
8
|
+
-- Read-only REST API requests now go through the faster api-read server
|
|
9
|
+
-- Replaced parse_signed_request with a version from Facebook that also supports the new signed params proposal
|
|
10
|
+
-- Note: invalid requests will now raise exceptions rather than return nil, in keeping with other SDKs
|
|
11
|
+
-- delete_object will now raise an error if there's no access token (like put_object and delete_like)
|
|
12
|
+
Test improvements:
|
|
13
|
+
-- Expanded HTTP service tests (added Typhoeus test suite and additional Net::HTTP test cases)
|
|
14
|
+
-- Live tests now verify that the access token has the necessary permissions before starting
|
|
15
|
+
-- Replaced the 50-person network test, which often took 15+ minutes to run live, with a 5-person test
|
|
16
|
+
|
|
17
|
+
v0.10.0
|
|
18
|
+
-- Added test user module
|
|
19
|
+
-- Fixed bug when raising APIError after Facebook fails to exchange session keys
|
|
20
|
+
-- Made access_token accessible via the readonly access_token property on all our API classes
|
|
21
|
+
|
|
22
|
+
v0.9.1
|
|
23
|
+
-- Tests are now compatible with Ruby 1.9.2
|
|
24
|
+
-- Added JSON to runtime dependencies
|
|
25
|
+
-- Removed examples directory (referenced from github instead)
|
|
26
|
+
|
|
1
27
|
v0.9.0
|
|
2
28
|
-- Added parse_signed_request to handle Facebook's new authentication scheme
|
|
3
29
|
-- note: creates dependency on OpenSSL (OpenSSL::HMAC) for decryption
|
|
4
|
-
-- Added GraphCollection class to provide paging support for GraphAPI get_connections and search methods (thanks to jagthedrummer)
|
|
30
|
+
-- Added GraphCollection class to provide paging support for GraphAPI get_connections and search methods (thanks to jagthedrummer)
|
|
5
31
|
-- Added get_page method to easily fetch pages of results from GraphCollections
|
|
6
32
|
-- Exchanging sessions for tokens now works properly when provided invalid/expired session keys
|
|
7
|
-
-- You can now include a :typhoeus_options key in TyphoeusService#make_request's options hash to control the Typhoeus call (for example, to set :disable_ssl_peer_verification => true)
|
|
33
|
+
-- You can now include a :typhoeus_options key in TyphoeusService#make_request's options hash to control the Typhoeus call (for example, to set :disable_ssl_peer_verification => true)
|
|
8
34
|
-- All paths provided to HTTP services start with leading / to improve compatibility with stubbing libraries
|
|
9
35
|
-- If Facebook returns nil for search or get_connections requests, Koala now returns nil rather than throwing an exception
|
|
10
36
|
|
|
@@ -13,7 +39,7 @@ v0.8.0
|
|
|
13
39
|
-- Removed string overloading for the methods, per 0.7.3, which caused Marshaling issues
|
|
14
40
|
-- Removed ability to provide a string as the second argument to url_for_access_token, per 0.5.0
|
|
15
41
|
|
|
16
|
-
v0.7.4
|
|
42
|
+
v0.7.4
|
|
17
43
|
-- Fixed bug with get_user_from_cookies
|
|
18
44
|
|
|
19
45
|
v0.7.3
|
|
@@ -24,18 +50,18 @@ v0.7.3
|
|
|
24
50
|
-- Using those methods triggers a deprecation warning
|
|
25
51
|
-- This will be removed by 1.0
|
|
26
52
|
-- There are new info methods (get_access_token_info, get_app_access_token_info, get_token_info_from_session_keys, and get_user_info_from_cookies) that natively return hashes, for when you want the expiration date
|
|
27
|
-
-- Responses with HTTP status 500+ now properly throw errors under Net::HTTP
|
|
53
|
+
-- Responses with HTTP status 500+ now properly throw errors under Net::HTTP
|
|
28
54
|
-- Updated changelog
|
|
29
55
|
-- Added license
|
|
30
56
|
|
|
31
57
|
v0.7.2
|
|
32
58
|
-- Added support for exchanging session keys for OAuth access tokens (get_token_from_session_key for single keys, get_tokens_from_session_keys for multiple)
|
|
33
59
|
-- Moved Koala files into a koala/ subdirectory to minimize risk of name collisions
|
|
34
|
-
-- Added OAuth Playground git submodule as an example
|
|
60
|
+
-- Added OAuth Playground git submodule as an example
|
|
35
61
|
-- Updated tests, readme, and changelog
|
|
36
62
|
|
|
37
63
|
v0.7.1
|
|
38
|
-
-- Updated RealtimeUpdates#list_subscriptions and GraphAPI#get_connections to now return an
|
|
64
|
+
-- Updated RealtimeUpdates#list_subscriptions and GraphAPI#get_connections to now return an
|
|
39
65
|
array of results directly (rather than a hash with one key)
|
|
40
66
|
-- Fixed a bug with Net::HTTP-based HTTP service in which the headers hash was improperly formatted
|
|
41
67
|
-- Updated readme
|
|
@@ -82,7 +108,7 @@ v0.3.1
|
|
|
82
108
|
v0.3
|
|
83
109
|
-- Renamed Graph API class from Facebook::GraphAPI to FacebookGraph::API
|
|
84
110
|
-- Created FacebookGraph::OAuth class for tokens and OAuth URLs
|
|
85
|
-
-- Updated method for including HTTP service (think we've got it this time)
|
|
111
|
+
-- Updated method for including HTTP service (think we've got it this time)
|
|
86
112
|
-- Updated tests
|
|
87
113
|
-- Added CHANGELOG and gemspec
|
|
88
114
|
|
data/Manifest
CHANGED
|
@@ -2,20 +2,6 @@ CHANGELOG
|
|
|
2
2
|
LICENSE
|
|
3
3
|
Manifest
|
|
4
4
|
Rakefile
|
|
5
|
-
examples/oauth_playground/Capfile
|
|
6
|
-
examples/oauth_playground/LICENSE
|
|
7
|
-
examples/oauth_playground/Rakefile
|
|
8
|
-
examples/oauth_playground/config.ru
|
|
9
|
-
examples/oauth_playground/config/deploy.rb
|
|
10
|
-
examples/oauth_playground/config/facebook.yml
|
|
11
|
-
examples/oauth_playground/lib/load_facebook.rb
|
|
12
|
-
examples/oauth_playground/lib/oauth_playground.rb
|
|
13
|
-
examples/oauth_playground/readme.md
|
|
14
|
-
examples/oauth_playground/spec/oauth_playground_spec.rb
|
|
15
|
-
examples/oauth_playground/spec/spec_helper.rb
|
|
16
|
-
examples/oauth_playground/tmp/restart.txt
|
|
17
|
-
examples/oauth_playground/views/index.erb
|
|
18
|
-
examples/oauth_playground/views/layout.erb
|
|
19
5
|
init.rb
|
|
20
6
|
koala.gemspec
|
|
21
7
|
lib/koala.rb
|
|
@@ -23,12 +9,15 @@ lib/koala/graph_api.rb
|
|
|
23
9
|
lib/koala/http_services.rb
|
|
24
10
|
lib/koala/realtime_updates.rb
|
|
25
11
|
lib/koala/rest_api.rb
|
|
12
|
+
lib/koala/test_users.rb
|
|
26
13
|
readme.md
|
|
27
14
|
spec/facebook_data.yml
|
|
28
15
|
spec/koala/api_base_tests.rb
|
|
16
|
+
spec/koala/assets/beach.jpg
|
|
29
17
|
spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb
|
|
30
18
|
spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb
|
|
31
19
|
spec/koala/graph_api/graph_api_no_access_token_tests.rb
|
|
20
|
+
spec/koala/graph_api/graph_api_tests.rb
|
|
32
21
|
spec/koala/graph_api/graph_api_with_access_token_tests.rb
|
|
33
22
|
spec/koala/graph_api/graph_collection_tests.rb
|
|
34
23
|
spec/koala/live_testing_data_helper.rb
|
|
@@ -36,7 +25,10 @@ spec/koala/net_http_service_tests.rb
|
|
|
36
25
|
spec/koala/oauth/oauth_tests.rb
|
|
37
26
|
spec/koala/realtime_updates/realtime_updates_tests.rb
|
|
38
27
|
spec/koala/rest_api/rest_api_no_access_token_tests.rb
|
|
28
|
+
spec/koala/rest_api/rest_api_tests.rb
|
|
39
29
|
spec/koala/rest_api/rest_api_with_access_token_tests.rb
|
|
30
|
+
spec/koala/test_users/test_users_tests.rb
|
|
31
|
+
spec/koala/typhoeus_service_tests.rb
|
|
40
32
|
spec/koala_spec.rb
|
|
41
33
|
spec/koala_spec_helper.rb
|
|
42
34
|
spec/koala_spec_without_mocks.rb
|
data/Rakefile
CHANGED
|
@@ -4,13 +4,14 @@ require 'rake'
|
|
|
4
4
|
require 'echoe'
|
|
5
5
|
|
|
6
6
|
# gem management
|
|
7
|
-
Echoe.new('koala', '0.
|
|
8
|
-
p.summary
|
|
9
|
-
p.description
|
|
7
|
+
Echoe.new('koala', '1.0.0.beta') do |p|
|
|
8
|
+
p.summary = "A lightweight, flexible library for Facebook with support for the Graph API, the old REST API, realtime updates, and OAuth validation."
|
|
9
|
+
p.description = "Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, 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."
|
|
10
10
|
p.url = "http://github.com/arsduo/koala"
|
|
11
11
|
p.author = ["Alex Koppel", "Chris Baclig", "Rafi Jacoby", "Context Optional"]
|
|
12
12
|
p.email = "alex@alexkoppel.com"
|
|
13
13
|
p.ignore_pattern = ["tmp/*", "script/*", "pkg/*"]
|
|
14
|
+
p.runtime_dependencies = ["json >=1.0", "multipart-post >=1.0"]
|
|
14
15
|
p.development_dependencies = []
|
|
15
16
|
p.retain_gemspec = true
|
|
16
17
|
end
|
data/koala.gemspec
CHANGED
|
@@ -2,29 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{koala}
|
|
5
|
-
s.version = "0.
|
|
5
|
+
s.version = "1.0.0.beta"
|
|
6
6
|
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
8
8
|
s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional"]
|
|
9
|
-
s.date = %q{
|
|
9
|
+
s.date = %q{2011-01-26}
|
|
10
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 API and the older REST API, 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
11
|
s.email = %q{alex@alexkoppel.com}
|
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb"]
|
|
13
|
-
s.files = ["CHANGELOG", "LICENSE", "Manifest", "Rakefile", "
|
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb", "lib/koala/test_users.rb"]
|
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "Rakefile", "init.rb", "koala.gemspec", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb", "lib/koala/test_users.rb", "readme.md", "spec/facebook_data.yml", "spec/koala/api_base_tests.rb", "spec/koala/assets/beach.jpg", "spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb", "spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb", "spec/koala/graph_api/graph_api_no_access_token_tests.rb", "spec/koala/graph_api/graph_api_tests.rb", "spec/koala/graph_api/graph_api_with_access_token_tests.rb", "spec/koala/graph_api/graph_collection_tests.rb", "spec/koala/live_testing_data_helper.rb", "spec/koala/net_http_service_tests.rb", "spec/koala/oauth/oauth_tests.rb", "spec/koala/realtime_updates/realtime_updates_tests.rb", "spec/koala/rest_api/rest_api_no_access_token_tests.rb", "spec/koala/rest_api/rest_api_tests.rb", "spec/koala/rest_api/rest_api_with_access_token_tests.rb", "spec/koala/test_users/test_users_tests.rb", "spec/koala/typhoeus_service_tests.rb", "spec/koala_spec.rb", "spec/koala_spec_helper.rb", "spec/koala_spec_without_mocks.rb", "spec/mock_facebook_responses.yml", "spec/mock_http_service.rb"]
|
|
14
14
|
s.homepage = %q{http://github.com/arsduo/koala}
|
|
15
|
-
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"
|
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
|
|
16
16
|
s.require_paths = ["lib"]
|
|
17
17
|
s.rubyforge_project = %q{koala}
|
|
18
|
-
s.rubygems_version = %q{1.
|
|
18
|
+
s.rubygems_version = %q{1.4.2}
|
|
19
19
|
s.summary = %q{A lightweight, flexible library for Facebook with support for the Graph API, the old REST API, realtime updates, and OAuth validation.}
|
|
20
20
|
|
|
21
21
|
if s.respond_to? :specification_version then
|
|
22
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
23
22
|
s.specification_version = 3
|
|
24
23
|
|
|
25
|
-
if Gem::Version.new(Gem::
|
|
24
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
25
|
+
s.add_runtime_dependency(%q<json>, [">= 1.0"])
|
|
26
|
+
s.add_runtime_dependency(%q<multipart-post>, [">= 1.0"])
|
|
26
27
|
else
|
|
28
|
+
s.add_dependency(%q<json>, [">= 1.0"])
|
|
29
|
+
s.add_dependency(%q<multipart-post>, [">= 1.0"])
|
|
27
30
|
end
|
|
28
31
|
else
|
|
32
|
+
s.add_dependency(%q<json>, [">= 1.0"])
|
|
33
|
+
s.add_dependency(%q<multipart-post>, [">= 1.0"])
|
|
29
34
|
end
|
|
30
35
|
end
|
data/lib/koala/graph_api.rb
CHANGED
|
@@ -142,7 +142,7 @@ module Koala
|
|
|
142
142
|
# Writes a wall post to the given profile's wall.
|
|
143
143
|
#
|
|
144
144
|
# We default to writing to the authenticated user's wall if no
|
|
145
|
-
# profile_id is specified.
|
|
145
|
+
# profile_id is specified.
|
|
146
146
|
#
|
|
147
147
|
# attachment adds a structured attachment to the status message being
|
|
148
148
|
# posted to the Wall. It should be a dictionary of the form:
|
|
@@ -155,7 +155,14 @@ module Koala
|
|
|
155
155
|
|
|
156
156
|
self.put_object(profile_id, "feed", attachment.merge({:message => message}))
|
|
157
157
|
end
|
|
158
|
-
|
|
158
|
+
|
|
159
|
+
def put_picture(file_hash, args = {}, target_id = "me")
|
|
160
|
+
raise APIError.new("type" => "KoalaInvaliFileFormat", "message" => "put_picture requires a hash describing the File to upload (see HTTPService::is_valid_file_hash?") unless file_hash.kind_of?(Hash)
|
|
161
|
+
|
|
162
|
+
args["source"] = file_hash
|
|
163
|
+
self.put_object(target_id, "photos", args)
|
|
164
|
+
end
|
|
165
|
+
|
|
159
166
|
def put_comment(object_id, message)
|
|
160
167
|
# Writes the given comment on the given post.
|
|
161
168
|
self.put_object(object_id, "comments", {:message => message})
|
|
@@ -165,9 +172,15 @@ module Koala
|
|
|
165
172
|
# Likes the given post.
|
|
166
173
|
self.put_object(object_id, "likes")
|
|
167
174
|
end
|
|
175
|
+
|
|
176
|
+
def delete_like(object_id)
|
|
177
|
+
raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Unliking requires an access token"}) unless @access_token
|
|
178
|
+
graph_call("#{object_id}/likes", {}, "delete")
|
|
179
|
+
end
|
|
168
180
|
|
|
169
181
|
def delete_object(id)
|
|
170
182
|
# Deletes the object with the given ID from the graph.
|
|
183
|
+
raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Unliking requires an access token"}) unless @access_token
|
|
171
184
|
graph_call(id, {}, "delete")
|
|
172
185
|
end
|
|
173
186
|
|
|
@@ -189,4 +202,4 @@ module Koala
|
|
|
189
202
|
end
|
|
190
203
|
end
|
|
191
204
|
end
|
|
192
|
-
end
|
|
205
|
+
end
|
data/lib/koala/http_services.rb
CHANGED
|
@@ -8,62 +8,146 @@ module Koala
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
module HTTPService
|
|
12
|
+
# common functionality for all HTTP services
|
|
13
|
+
def self.included(base)
|
|
14
|
+
base.class_eval do
|
|
15
|
+
class << self
|
|
16
|
+
attr_accessor :always_use_ssl
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
def self.params_require_multipart?(param_hash)
|
|
21
|
+
param_hash.any? { |key, value| is_valid_file_hash?(value) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# A file hash can take two forms:
|
|
25
|
+
# - A hash with "content_type" and "path" keys where "path" is the local path
|
|
26
|
+
# to the file to be uploaded.
|
|
27
|
+
# - A hash with the "file" key containing an already-opened IO that responds to "read"
|
|
28
|
+
# as well as "content_type" and the "path" key to the original file
|
|
29
|
+
# ("path"" is required by multipart-post even for opened files)
|
|
30
|
+
#
|
|
31
|
+
# Valid inputs for a file to be posted via multipart/form-data
|
|
32
|
+
# are based on the criteria for an UploadIO to be created
|
|
33
|
+
# See : https://github.com/nicksieger/multipart-post/blob/master/lib/composite_io.rb
|
|
34
|
+
def self.is_valid_file_hash?(value)
|
|
35
|
+
value.kind_of?(Hash) and value.key?("content_type") and value.key?("path") and (
|
|
36
|
+
!value.key?("file") or value["file"].respond_to?(:read)
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
11
43
|
module NetHTTPService
|
|
12
44
|
# this service uses Net::HTTP to send requests to the graph
|
|
13
45
|
def self.included(base)
|
|
14
46
|
base.class_eval do
|
|
15
|
-
require
|
|
16
|
-
require
|
|
47
|
+
require "net/http" unless defined?(Net::HTTP)
|
|
48
|
+
require "net/https"
|
|
49
|
+
require "net/http/post/multipart"
|
|
50
|
+
|
|
51
|
+
include Koala::HTTPService
|
|
17
52
|
|
|
18
53
|
def self.make_request(path, args, verb, options = {})
|
|
19
54
|
# We translate args to a valid query string. If post is specified,
|
|
20
55
|
# we send a POST request to the given path with the given arguments.
|
|
21
56
|
|
|
57
|
+
# by default, we use SSL only for private requests
|
|
58
|
+
# this makes public requests faster
|
|
59
|
+
private_request = args["access_token"] || @always_use_ssl || options[:use_ssl]
|
|
60
|
+
|
|
22
61
|
# if the verb isn't get or post, send it as a post argument
|
|
23
62
|
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
24
63
|
|
|
25
64
|
server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
|
|
26
|
-
http = Net::HTTP.new(server, 443)
|
|
27
|
-
http.use_ssl = true
|
|
28
|
-
|
|
65
|
+
http = Net::HTTP.new(server, private_request ? 443 : nil)
|
|
66
|
+
http.use_ssl = true if private_request
|
|
67
|
+
|
|
68
|
+
# we turn off certificate validation to avoid the
|
|
29
69
|
# "warning: peer certificate won't be verified in this SSL session" warning
|
|
30
70
|
# not sure if this is the right way to handle it
|
|
31
71
|
# see http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
|
|
32
72
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
33
73
|
|
|
34
|
-
result = http.start
|
|
35
|
-
response, body =
|
|
74
|
+
result = http.start do |http|
|
|
75
|
+
response, body = if verb == "post"
|
|
76
|
+
if params_require_multipart? args
|
|
77
|
+
http.request Net::HTTP::Post::Multipart.new path, encode_multipart_params(args)
|
|
78
|
+
else
|
|
79
|
+
http.post(path, encode_params(args))
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
http.get("#{path}?#{encode_params(args)}")
|
|
83
|
+
end
|
|
84
|
+
|
|
36
85
|
Koala::Response.new(response.code.to_i, body, response)
|
|
37
|
-
|
|
86
|
+
end
|
|
38
87
|
end
|
|
39
88
|
|
|
40
89
|
protected
|
|
41
90
|
def self.encode_params(param_hash)
|
|
42
91
|
# unfortunately, we can't use to_query because that's Rails, not Ruby
|
|
43
92
|
# if no hash (e.g. no auth token) return empty string
|
|
44
|
-
((param_hash || {}).collect do |key_and_value|
|
|
93
|
+
((param_hash || {}).collect do |key_and_value|
|
|
45
94
|
key_and_value[1] = key_and_value[1].to_json if key_and_value[1].class != String
|
|
46
95
|
"#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
|
|
47
96
|
end).join("&")
|
|
48
97
|
end
|
|
98
|
+
|
|
99
|
+
def self.encode_multipart_params(param_hash)
|
|
100
|
+
Hash[*param_hash.collect do |key, value|
|
|
101
|
+
if is_valid_file_hash?(value)
|
|
102
|
+
if value.key?("file")
|
|
103
|
+
value = UploadIO.new(value["file"], value["content_type"], value["path"])
|
|
104
|
+
else
|
|
105
|
+
value = UploadIO.new(value["path"], value['content_type'])
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
[key, value]
|
|
110
|
+
end.flatten]
|
|
111
|
+
end
|
|
49
112
|
end
|
|
50
113
|
end
|
|
51
114
|
end
|
|
52
115
|
|
|
53
116
|
module TyphoeusService
|
|
54
117
|
# this service uses Typhoeus to send requests to the graph
|
|
118
|
+
|
|
119
|
+
# used for multipart file uploads (see below)
|
|
120
|
+
class NetHTTPInterface
|
|
121
|
+
include NetHTTPService
|
|
122
|
+
end
|
|
123
|
+
|
|
55
124
|
def self.included(base)
|
|
56
125
|
base.class_eval do
|
|
57
|
-
require
|
|
126
|
+
require "typhoeus" unless defined?(Typhoeus)
|
|
58
127
|
include Typhoeus
|
|
128
|
+
|
|
129
|
+
include Koala::HTTPService
|
|
59
130
|
|
|
60
131
|
def self.make_request(path, args, verb, options = {})
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
132
|
+
unless params_require_multipart?(args)
|
|
133
|
+
# if the verb isn't get or post, send it as a post argument
|
|
134
|
+
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
135
|
+
server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
|
|
136
|
+
|
|
137
|
+
# you can pass arguments directly to Typhoeus using the :typhoeus_options key
|
|
138
|
+
typhoeus_options = {:params => args}.merge(options[:typhoeus_options] || {})
|
|
139
|
+
|
|
140
|
+
# by default, we use SSL only for private requests (e.g. with access token)
|
|
141
|
+
# this makes public requests faster
|
|
142
|
+
prefix = (args["access_token"] || @always_use_ssl || options[:use_ssl]) ? "https" : "http"
|
|
143
|
+
|
|
144
|
+
response = self.send(verb, "#{prefix}://#{server}#{path}", typhoeus_options)
|
|
145
|
+
Koala::Response.new(response.code, response.body, response.headers_hash)
|
|
146
|
+
else
|
|
147
|
+
# we have to use NetHTTPService for multipart for file uploads
|
|
148
|
+
# until Typhoeus integrates support
|
|
149
|
+
Koala::TyphoeusService::NetHTTPInterface.make_request(path, args, verb, options)
|
|
150
|
+
end
|
|
67
151
|
end
|
|
68
152
|
end # class_eval
|
|
69
153
|
end
|
data/lib/koala/rest_api.rb
CHANGED
|
@@ -1,23 +1,90 @@
|
|
|
1
1
|
module Koala
|
|
2
2
|
module Facebook
|
|
3
3
|
REST_SERVER = "api.facebook.com"
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
module RestAPIMethods
|
|
6
6
|
def fql_query(fql)
|
|
7
7
|
rest_call('fql.query', 'query' => fql)
|
|
8
8
|
end
|
|
9
|
-
|
|
10
|
-
def rest_call(method, args = {})
|
|
11
|
-
|
|
9
|
+
|
|
10
|
+
def rest_call(method, args = {}, options = {})
|
|
11
|
+
options = options.merge!(:rest_api => true, :read_only => READ_ONLY_METHODS.include?(method))
|
|
12
|
+
|
|
13
|
+
response = api("method/#{method}", args.merge('format' => 'json'), 'get', options) do |response|
|
|
12
14
|
# check for REST API-specific errors
|
|
13
15
|
if response.is_a?(Hash) && response["error_code"]
|
|
14
16
|
raise APIError.new("type" => response["error_code"], "message" => response["error_msg"])
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
|
-
|
|
19
|
+
|
|
18
20
|
response
|
|
19
21
|
end
|
|
22
|
+
|
|
23
|
+
# read-only methods for which we can use API-read
|
|
24
|
+
# taken directly from the FB PHP library (https://github.com/facebook/php-sdk/blob/master/src/facebook.php)
|
|
25
|
+
READ_ONLY_METHODS = [
|
|
26
|
+
'admin.getallocation',
|
|
27
|
+
'admin.getappproperties',
|
|
28
|
+
'admin.getbannedusers',
|
|
29
|
+
'admin.getlivestreamvialink',
|
|
30
|
+
'admin.getmetrics',
|
|
31
|
+
'admin.getrestrictioninfo',
|
|
32
|
+
'application.getpublicinfo',
|
|
33
|
+
'auth.getapppublickey',
|
|
34
|
+
'auth.getsession',
|
|
35
|
+
'auth.getsignedpublicsessiondata',
|
|
36
|
+
'comments.get',
|
|
37
|
+
'connect.getunconnectedfriendscount',
|
|
38
|
+
'dashboard.getactivity',
|
|
39
|
+
'dashboard.getcount',
|
|
40
|
+
'dashboard.getglobalnews',
|
|
41
|
+
'dashboard.getnews',
|
|
42
|
+
'dashboard.multigetcount',
|
|
43
|
+
'dashboard.multigetnews',
|
|
44
|
+
'data.getcookies',
|
|
45
|
+
'events.get',
|
|
46
|
+
'events.getmembers',
|
|
47
|
+
'fbml.getcustomtags',
|
|
48
|
+
'feed.getappfriendstories',
|
|
49
|
+
'feed.getregisteredtemplatebundlebyid',
|
|
50
|
+
'feed.getregisteredtemplatebundles',
|
|
51
|
+
'fql.multiquery',
|
|
52
|
+
'fql.query',
|
|
53
|
+
'friends.arefriends',
|
|
54
|
+
'friends.get',
|
|
55
|
+
'friends.getappusers',
|
|
56
|
+
'friends.getlists',
|
|
57
|
+
'friends.getmutualfriends',
|
|
58
|
+
'gifts.get',
|
|
59
|
+
'groups.get',
|
|
60
|
+
'groups.getmembers',
|
|
61
|
+
'intl.gettranslations',
|
|
62
|
+
'links.get',
|
|
63
|
+
'notes.get',
|
|
64
|
+
'notifications.get',
|
|
65
|
+
'pages.getinfo',
|
|
66
|
+
'pages.isadmin',
|
|
67
|
+
'pages.isappadded',
|
|
68
|
+
'pages.isfan',
|
|
69
|
+
'permissions.checkavailableapiaccess',
|
|
70
|
+
'permissions.checkgrantedapiaccess',
|
|
71
|
+
'photos.get',
|
|
72
|
+
'photos.getalbums',
|
|
73
|
+
'photos.gettags',
|
|
74
|
+
'profile.getinfo',
|
|
75
|
+
'profile.getinfooptions',
|
|
76
|
+
'stream.get',
|
|
77
|
+
'stream.getcomments',
|
|
78
|
+
'stream.getfilters',
|
|
79
|
+
'users.getinfo',
|
|
80
|
+
'users.getloggedinuser',
|
|
81
|
+
'users.getstandardinfo',
|
|
82
|
+
'users.hasapppermission',
|
|
83
|
+
'users.isappuser',
|
|
84
|
+
'users.isverified',
|
|
85
|
+
'video.getuploadlimits'
|
|
86
|
+
]
|
|
20
87
|
end
|
|
21
|
-
|
|
88
|
+
|
|
22
89
|
end # module Facebook
|
|
23
90
|
end # module Koala
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'koala'
|
|
2
|
+
|
|
3
|
+
module Koala
|
|
4
|
+
module Facebook
|
|
5
|
+
module TestUserMethods
|
|
6
|
+
|
|
7
|
+
def initialize(options = {})
|
|
8
|
+
@app_id = options[:app_id]
|
|
9
|
+
@app_access_token = options[:app_access_token]
|
|
10
|
+
@secret = options[:secret]
|
|
11
|
+
unless @app_id && (@app_access_token || @secret) # make sure we have what we need
|
|
12
|
+
raise ArgumentError, "Initialize must receive a hash with :app_id and either :app_access_token or :secret! (received #{options.inspect})"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# fetch the access token if we're provided a secret
|
|
16
|
+
if @secret && !@app_access_token
|
|
17
|
+
oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
|
|
18
|
+
@app_access_token = oauth.get_app_access_token
|
|
19
|
+
end
|
|
20
|
+
@graph_api = GraphAPI.new(@app_access_token)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create(installed, permissions = nil)
|
|
24
|
+
# Creates and returns a test user
|
|
25
|
+
args = {'installed' => installed}
|
|
26
|
+
args['permissions'] = (permissions.is_a?(Array) ? permissions.join(",") : permissions) if installed
|
|
27
|
+
result = @graph_api.graph_call(accounts_path, args, "post")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def list
|
|
31
|
+
@graph_api.graph_call(accounts_path)["data"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def delete(test_user)
|
|
35
|
+
test_user = test_user["id"] if test_user.is_a?(Hash)
|
|
36
|
+
@graph_api.delete_object(test_user)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete_all
|
|
40
|
+
list.each {|u| delete u }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def befriend(user1, user2)
|
|
44
|
+
user1 = user1["id"] if user1.is_a?(Hash)
|
|
45
|
+
user2 = user2["id"] if user2.is_a?(Hash)
|
|
46
|
+
@graph_api.graph_call("/#{user1}/friends/#{user2}") && @graph_api.graph_call("/#{user2}/friends/#{user1}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def create_network(network_size, installed = true, permissions = '')
|
|
50
|
+
network_size = 50 if network_size > 50 # FB's max is 50
|
|
51
|
+
users = (0...network_size).collect { create(installed, permissions) }
|
|
52
|
+
friends = users.clone
|
|
53
|
+
users.each do |user|
|
|
54
|
+
# Remove this user from list of friends
|
|
55
|
+
friends.delete_at(0)
|
|
56
|
+
# befriend all the others
|
|
57
|
+
friends.each do |friend|
|
|
58
|
+
befriend(user, friend)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
return users
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
protected
|
|
65
|
+
|
|
66
|
+
def accounts_path
|
|
67
|
+
@accounts_path ||= "/#{@app_id}/accounts/test-users"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end # TestUserMethods
|
|
71
|
+
end # Facebook
|
|
72
|
+
end # Koala
|