joelind-koala 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,88 @@
1
+ v0.8.0
2
+ -- Breaking interface changes
3
+ -- Removed string overloading for the methods, per 0.7.3, which caused Marshaling issues
4
+ -- Removed ability to provide a string as the second argument to url_for_access_token, per 0.5.0
5
+
6
+ v0.7.4
7
+ -- Fixed bug with get_user_from_cookies
8
+
9
+ v0.7.3
10
+ -- Added support for picture sizes -- thanks thhermansen for the patch!
11
+ -- Adjusted the return values for several methods (get_access_token, get_app_access_token, get_token_from_session_key, get_tokens_from_session_keys, get_user_from_cookies)
12
+ -- These methods now return strings, rather than hashes, which makes more sense
13
+ -- The strings are overloaded with an [] method for backwards compatibility (Ruby is truly amazing)
14
+ -- Using those methods triggers a deprecation warning
15
+ -- This will be removed by 1.0
16
+ -- 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
17
+ -- Responses with HTTP status 500+ now properly throw errors under Net::HTTP
18
+ -- Updated changelog
19
+ -- Added license
20
+
21
+ v0.7.2
22
+ -- 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)
23
+ -- Moved Koala files into a koala/ subdirectory to minimize risk of name collisions
24
+ -- Added OAuth Playground git submodule as an example
25
+ -- Updated tests, readme, and changelog
26
+
27
+ v0.7.1
28
+ -- Updated RealtimeUpdates#list_subscriptions and GraphAPI#get_connections to now return an
29
+ array of results directly (rather than a hash with one key)
30
+ -- Fixed a bug with Net::HTTP-based HTTP service in which the headers hash was improperly formatted
31
+ -- Updated readme
32
+
33
+ v0.7.0
34
+ -- Added RealtimeUpdates class, which can be used to manage subscriptions for user updates (see http://developers.facebook.com/docs/api/realtime)
35
+ -- Added picture method to graph API, which fetches an object's picture from the redirect headers.
36
+ -- Added _greatly_ improved testing with result mocking, which is now the default set of tests
37
+ -- Renamed live testing spec to koala_spec_without_mocks.rb
38
+ -- Added Koala::Response class, which encapsulates HTTP results since Facebook sometimes sends data in the status or headers
39
+ -- Much internal refactoring
40
+ -- Updated readme, changelog, etc.
41
+
42
+
43
+ v0.6.0
44
+ -- Added support for the old REST API thanks to cbaclig's great work
45
+ -- Updated tests to conform to RSpec standards
46
+ -- Updated changelog, readme, etc.
47
+
48
+ v0.5.1
49
+ -- Documentation is now on the wiki, updated readme accordingly.
50
+
51
+ v0.5.0
52
+ -- Added several new OAuth methods for making and parsing access token requests
53
+ -- Added test suite for the OAuth class
54
+ -- Made second argument to url_for_access_token a hash (strings still work but trigger a deprecation warning)
55
+ -- Added fields to facebook_data.yml
56
+ -- Updated readme
57
+
58
+ v0.4.1
59
+ -- Encapsulated GraphAPI and OAuth classes in the Koala::Facebook module for clarity (and to avoid claiming the global Facebook class)
60
+ -- Moved make_request method to Koala class from GraphAPI instance (for use by future OAuth class functionality)
61
+ -- Renamed request method to api for consistancy with Javascript library
62
+ -- Updated tests and readme
63
+
64
+ v0.4.0
65
+ -- Adopted the Koala name
66
+ -- Updated readme and tests
67
+ -- Fixed cookie verification bug for non-expiring OAuth tokens
68
+
69
+ v0.3.1
70
+ -- Bug fixes.
71
+
72
+ v0.3
73
+ -- Renamed Graph API class from Facebook::GraphAPI to FacebookGraph::API
74
+ -- Created FacebookGraph::OAuth class for tokens and OAuth URLs
75
+ -- Updated method for including HTTP service (think we've got it this time)
76
+ -- Updated tests
77
+ -- Added CHANGELOG and gemspec
78
+
79
+ v0.2
80
+ -- Gemified the project
81
+ -- Split out HTTP services into their own file, and adjusted inclusion method
82
+
83
+ v0.1
84
+ -- Added modular support for Typhoeus
85
+ -- Added tests
86
+
87
+ v0.0
88
+ -- Hi from F8! Basic read/write from the graph is working
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 Alex Koppel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,29 @@
1
+ CHANGELOG
2
+ LICENSE
3
+ Manifest
4
+ Rakefile
5
+ init.rb
6
+ koala.gemspec
7
+ lib/koala.rb
8
+ lib/koala/graph_api.rb
9
+ lib/koala/http_services.rb
10
+ lib/koala/realtime_updates.rb
11
+ lib/koala/rest_api.rb
12
+ readme.md
13
+ spec/facebook_data.yml
14
+ spec/koala/api_base_tests.rb
15
+ spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb
16
+ spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb
17
+ spec/koala/graph_api/graph_api_no_access_token_tests.rb
18
+ spec/koala/graph_api/graph_api_with_access_token_tests.rb
19
+ spec/koala/live_testing_data_helper.rb
20
+ spec/koala/net_http_service_tests.rb
21
+ spec/koala/oauth/oauth_tests.rb
22
+ spec/koala/realtime_updates/realtime_updates_tests.rb
23
+ spec/koala/rest_api/rest_api_no_access_token_tests.rb
24
+ spec/koala/rest_api/rest_api_with_access_token_tests.rb
25
+ spec/koala_spec.rb
26
+ spec/koala_spec_helper.rb
27
+ spec/koala_spec_without_mocks.rb
28
+ spec/mock_facebook_responses.yml
29
+ spec/mock_http_service.rb
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # Rakefile
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'echoe'
5
+
6
+ # gem management
7
+ Echoe.new('joelind-koala', '0.8.1') 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. Build of 0.8.1 for testing compatibility."
10
+ p.url = "http://github.com/joelind/koala"
11
+ p.author = ["Alex Koppel", "Chris Baclig", "Rafi Jacoby", "Context Optional", "Joe Lind"]
12
+ p.email = "joelind@gmail.com"
13
+ p.ignore_pattern = ["tmp/*", "script/*", "pkg/*"]
14
+ p.development_dependencies = []
15
+ p.retain_gemspec = true
16
+ p.project = "joelind-koala"
17
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # init.rb
2
+ require 'koala'
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{joelind-koala}
5
+ s.version = "0.8.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional, Joe Lind"]
9
+ s.date = %q{2010-08-15}
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. Build of 0.8.1 for testing compatibility.}
11
+ s.email = %q{joelind@gmail.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", "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", "readme.md", "spec/facebook_data.yml", "spec/koala/api_base_tests.rb", "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_with_access_token_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_with_access_token_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", "joelind-koala.gemspec"]
14
+ s.homepage = %q{http://github.com/joelind/koala}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Joelind-koala", "--main", "readme.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{joelind-koala}
18
+ s.rubygems_version = %q{1.3.6}
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
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
data/koala.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{koala}
5
+ s.version = "0.8.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional, Joe Lind"]
9
+ s.date = %q{2010-08-15}
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. Build of 0.8.1 for testing compatibility.}
11
+ s.email = %q{joelind@gmail.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", "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", "readme.md", "spec/facebook_data.yml", "spec/koala/api_base_tests.rb", "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_with_access_token_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_with_access_token_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
+ s.homepage = %q{http://github.com/joelind/koala}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala", "--main", "readme.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{joelind-koala}
18
+ s.rubygems_version = %q{1.3.6}
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
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,131 @@
1
+ module Koala
2
+ module Facebook
3
+ GRAPH_SERVER = "graph.facebook.com"
4
+
5
+ module GraphAPIMethods
6
+ # A client for the Facebook Graph API.
7
+ #
8
+ # See http://developers.facebook.com/docs/api for complete documentation
9
+ # for the API.
10
+ #
11
+ # The Graph API is made up of the objects in Facebook (e.g., people, pages,
12
+ # events, photos) and the connections between them (e.g., friends,
13
+ # photo tags, and event RSVPs). This client provides access to those
14
+ # primitive types in a generic way. For example, given an OAuth access
15
+ # token, this will fetch the profile of the active user and the list
16
+ # of the user's friends:
17
+ #
18
+ # graph = Koala::Facebook::GraphAPI.new(access_token)
19
+ # user = graph.get_object("me")
20
+ # friends = graph.get_connections(user["id"], "friends")
21
+ #
22
+ # You can see a list of all of the objects and connections supported
23
+ # by the API at http://developers.facebook.com/docs/reference/api/.
24
+ #
25
+ # You can obtain an access token via OAuth or by using the Facebook
26
+ # JavaScript SDK. See http://developers.facebook.com/docs/authentication/
27
+ # for details.
28
+ #
29
+ # If you are using the JavaScript SDK, you can use the
30
+ # Koala::Facebook::OAuth.get_user_from_cookie() method below to get the OAuth access token
31
+ # for the active user from the cookie saved by the SDK.
32
+
33
+ def get_object(id, args = {})
34
+ # Fetchs the given object from the graph.
35
+ graph_call(id, args)
36
+ end
37
+
38
+ def get_objects(ids, args = {})
39
+ # Fetchs all of the given object from the graph.
40
+ # We return a map from ID to object. If any of the IDs are invalid,
41
+ # we raise an exception.
42
+ graph_call("", args.merge("ids" => ids.join(",")))
43
+ end
44
+
45
+ def get_connections(id, connection_name, args = {})
46
+ # Fetchs the connections for given object.
47
+ graph_call("#{id}/#{connection_name}", args)["data"]
48
+ end
49
+
50
+ def get_picture(object, args = {})
51
+ result = graph_call("#{object}/picture", args, "get", :http_component => :headers)
52
+ result["Location"]
53
+ end
54
+
55
+ def put_object(parent_object, connection_name, args = {})
56
+ # Writes the given object to the graph, connected to the given parent.
57
+ #
58
+ # For example,
59
+ #
60
+ # graph.put_object("me", "feed", :message => "Hello, world")
61
+ #
62
+ # writes "Hello, world" to the active user's wall. Likewise, this
63
+ # will comment on a the first post of the active user's feed:
64
+ #
65
+ # feed = graph.get_connections("me", "feed")
66
+ # post = feed["data"][0]
67
+ # graph.put_object(post["id"], "comments", :message => "First!")
68
+ #
69
+ # See http://developers.facebook.com/docs/api#publishing for all of
70
+ # the supported writeable objects.
71
+ #
72
+ # Most write operations require extended permissions. For example,
73
+ # publishing wall posts requires the "publish_stream" permission. See
74
+ # http://developers.facebook.com/docs/authentication/ for details about
75
+ # extended permissions.
76
+
77
+ raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token
78
+ graph_call("#{parent_object}/#{connection_name}", args, "post")
79
+ end
80
+
81
+ def put_wall_post(message, attachment = {}, profile_id = "me")
82
+ # Writes a wall post to the given profile's wall.
83
+ #
84
+ # We default to writing to the authenticated user's wall if no
85
+ # profile_id is specified.
86
+ #
87
+ # attachment adds a structured attachment to the status message being
88
+ # posted to the Wall. It should be a dictionary of the form:
89
+ #
90
+ # {"name": "Link name"
91
+ # "link": "http://www.example.com/",
92
+ # "caption": "{*actor*} posted a new review",
93
+ # "description": "This is a longer description of the attachment",
94
+ # "picture": "http://www.example.com/thumbnail.jpg"}
95
+
96
+ self.put_object(profile_id, "feed", attachment.merge({:message => message}))
97
+ end
98
+
99
+ def put_comment(object_id, message)
100
+ # Writes the given comment on the given post.
101
+ self.put_object(object_id, "comments", {:message => message})
102
+ end
103
+
104
+ def put_like(object_id)
105
+ # Likes the given post.
106
+ self.put_object(object_id, "likes")
107
+ end
108
+
109
+ def delete_object(id)
110
+ # Deletes the object with the given ID from the graph.
111
+ graph_call(id, {}, "delete")
112
+ end
113
+
114
+ def search(search_terms, args = {})
115
+ # Searches for a given term
116
+ graph_call("search", args.merge({:q => search_terms}))
117
+ end
118
+
119
+ def graph_call(*args)
120
+ response = api(*args) do |response|
121
+ # check for Graph API-specific errors
122
+ if response.is_a?(Hash) && error_details = response["error"]
123
+ raise APIError.new(error_details)
124
+ end
125
+ end
126
+
127
+ response
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,70 @@
1
+ module Koala
2
+ class Response
3
+ attr_reader :status, :body, :headers
4
+ def initialize(status, body, headers)
5
+ @status = status
6
+ @body = body
7
+ @headers = headers
8
+ end
9
+ end
10
+
11
+ module NetHTTPService
12
+ # this service uses Net::HTTP to send requests to the graph
13
+ def self.included(base)
14
+ base.class_eval do
15
+ require 'net/http' unless defined?(Net::HTTP)
16
+ require 'net/https'
17
+
18
+ def self.make_request(path, args, verb, options = {})
19
+ # We translate args to a valid query string. If post is specified,
20
+ # we send a POST request to the given path with the given arguments.
21
+
22
+ # if the verb isn't get or post, send it as a post argument
23
+ args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
24
+
25
+ server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
26
+ http = Net::HTTP.new(server, 443)
27
+ http.use_ssl = true
28
+ # we turn off certificate validation to avoid the
29
+ # "warning: peer certificate won't be verified in this SSL session" warning
30
+ # not sure if this is the right way to handle it
31
+ # see http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
32
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
33
+
34
+ result = http.start { |http|
35
+ response, body = (verb == "post" ? http.post(path, encode_params(args)) : http.get("#{path}?#{encode_params(args)}"))
36
+ Koala::Response.new(response.code.to_i, body, response)
37
+ }
38
+ end
39
+
40
+ protected
41
+ def self.encode_params(param_hash)
42
+ # TODO investigating whether a built-in method handles this
43
+ # if no hash (e.g. no auth token) return empty string
44
+ ((param_hash || {}).collect do |key_and_value|
45
+ key_and_value[1] = key_and_value[1].to_json if key_and_value[1].class != String
46
+ "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
47
+ end).join("&")
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ module TyphoeusService
54
+ # this service uses Typhoeus to send requests to the graph
55
+ def self.included(base)
56
+ base.class_eval do
57
+ require 'typhoeus' unless defined?(Typhoeus)
58
+ include Typhoeus
59
+
60
+ def self.make_request(path, args, verb, options = {})
61
+ # if the verb isn't get or post, send it as a post argument
62
+ args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
63
+ server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
64
+ response = self.send(verb, "https://#{server}/#{path}", :params => args)
65
+ Koala::Response.new(response.code, response.body, response.headers_hash)
66
+ end
67
+ end # class_eval
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,95 @@
1
+ require 'koala'
2
+
3
+ module Koala
4
+ module Facebook
5
+ module RealtimeUpdateMethods
6
+ # note: to subscribe to real-time updates, you must have an application access token
7
+
8
+ def self.included(base)
9
+ # make the attributes readable
10
+ base.class_eval do
11
+ attr_reader :app_id, :app_access_token, :secret
12
+
13
+ # parses the challenge params and makes sure the call is legitimate
14
+ # returns the challenge string to be sent back to facebook if true
15
+ # returns false otherwise
16
+ # this is a class method, since you don't need to know anything about the app
17
+ # saves a potential trip fetching the app access token
18
+ def self.meet_challenge(params, verify_token = nil, &verification_block)
19
+ if params["hub.mode"] == "subscribe" &&
20
+ # you can make sure this is legitimate through two ways
21
+ # if your store the token across the calls, you can pass in the token value
22
+ # and we'll make sure it matches
23
+ (verify_token && params["hub.verify_token"] == verify_token) ||
24
+ # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
25
+ # you can pass in a block, which we'll call with the verify_token sent by Facebook
26
+ # if it's legit, return anything that evaluates to true; otherwise, return nil or false
27
+ (verification_block && yield(params["hub.verify_token"]))
28
+ params["hub.challenge"]
29
+ else
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def initialize(options = {})
37
+ @app_id = options[:app_id]
38
+ @app_access_token = options[:app_access_token]
39
+ @secret = options[:secret]
40
+ unless @app_id && (@app_access_token || @secret) # make sure we have what we need
41
+ raise ArgumentError, "Initialize must receive a hash with :app_id and either :app_access_token or :secret! (received #{options.inspect})"
42
+ end
43
+
44
+ # fetch the access token if we're provided a secret
45
+ if @secret && !@app_access_token
46
+ oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
47
+ @app_access_token = oauth.get_app_access_token
48
+ end
49
+ end
50
+
51
+ # subscribes for realtime updates
52
+ # your callback_url must be set up to handle the verification request or the subscription will not be set up
53
+ # http://developers.facebook.com/docs/api/realtime
54
+ def subscribe(object, fields, callback_url, verify_token)
55
+ args = {
56
+ :object => object,
57
+ :fields => fields,
58
+ :callback_url => callback_url,
59
+ :verify_token => verify_token
60
+ }
61
+ # a subscription is a success if Facebook returns a 200 (after hitting your server for verification)
62
+ api(subscription_path, args, 'post', :http_component => :status) == 200
63
+ end
64
+
65
+ # removes subscription for object
66
+ # if object is nil, it will remove all subscriptions
67
+ def unsubscribe(object = nil)
68
+ args = {}
69
+ args[:object] = object if object
70
+ api(subscription_path, args, 'delete', :http_component => :status) == 200
71
+ end
72
+
73
+ def list_subscriptions
74
+ api(subscription_path)["data"]
75
+ end
76
+
77
+ def api(*args) # same as GraphAPI
78
+ response = super(*args) do |response|
79
+ # check for subscription errors
80
+ if response.is_a?(Hash) && error_details = response["error"]
81
+ raise APIError.new(error_details)
82
+ end
83
+ end
84
+
85
+ response
86
+ end
87
+
88
+ protected
89
+
90
+ def subscription_path
91
+ @subscription_path ||= "#{@app_id}/subscriptions"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,23 @@
1
+ module Koala
2
+ module Facebook
3
+ REST_SERVER = "api.facebook.com"
4
+
5
+ module RestAPIMethods
6
+ def fql_query(fql)
7
+ rest_call('fql.query', 'query' => fql)
8
+ end
9
+
10
+ def rest_call(method, args = {})
11
+ response = api("method/#{method}", args.merge('format' => 'json'), 'get', :rest_api => true) do |response|
12
+ # check for REST API-specific errors
13
+ if response.is_a?(Hash) && response["error_code"]
14
+ raise APIError.new("type" => response["error_code"], "message" => response["error_msg"])
15
+ end
16
+ end
17
+
18
+ response
19
+ end
20
+ end
21
+
22
+ end # module Facebook
23
+ end # module Koala