Class: Koala::Facebook::RealtimeUpdates

Inherits:
Object
  • Object
show all
Defined in:
lib/koala/realtime_updates.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ RealtimeUpdates

Create a new RealtimeUpdates instance. If you don’t have your app’s access token, provide the app’s secret and Koala will make a request to Facebook for the appropriate token.

Options Hash (options):

  • :app_id (Object)

    the application’s ID.

  • :app_access_token (Object)

    an application access token, if known.

  • :secret (Object)

    the application’s secret.

Raises:

  • ArgumentError if the application ID and one of the app access token or the secret are not provided.



22
23
24
25
26
27
28
29
# File 'lib/koala/realtime_updates.rb', line 22

def initialize(options = {})
  @app_id = options[:app_id] || Koala.config.app_id
  @app_access_token = options[:app_access_token] || Koala.config.app_access_token
  @secret = options[:secret] || Koala.config.app_secret
  unless @app_id && (@app_access_token || @secret) # make sure we have what we need
    raise ArgumentError, "Initialize must receive a hash with :app_id and either :app_access_token or :secret! (received #{options.inspect})"
  end
end

Instance Attribute Details

#app_access_tokenObject (readonly)

The app access token, either provided on initialization or fetched from Facebook using the app_id and secret.



10
11
12
# File 'lib/koala/realtime_updates.rb', line 10

def app_access_token
  @app_access_token
end

#app_idObject (readonly)

Manage realtime callbacks for changes to users’ information. See developers.facebook.com/docs/reference/api/realtime.

@note: to subscribe to real-time updates, you must have an application access token

or provide the app secret when initializing your RealtimeUpdates object.


10
11
12
# File 'lib/koala/realtime_updates.rb', line 10

def app_id
  @app_id
end

#secretObject (readonly)

Manage realtime callbacks for changes to users’ information. See developers.facebook.com/docs/reference/api/realtime.

@note: to subscribe to real-time updates, you must have an application access token

or provide the app secret when initializing your RealtimeUpdates object.


10
11
12
# File 'lib/koala/realtime_updates.rb', line 10

def secret
  @secret
end

Class Method Details

.meet_challenge(params, verify_token = nil) { ... } ⇒ Object

As a security measure (to prevent DDoS attacks), Facebook sends a verification request to your server after you request a subscription. This method parses the challenge params and makes sure the call is legitimate.

Yields:

  • verify_token if you need to compute the verification token (for instance, if your callback URL includes a record ID, which you look up and use to calculate a hash), you can pass meet_challenge a block, which will receive the verify_token received back from Facebook.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/koala/realtime_updates.rb', line 103

def self.meet_challenge(params, verify_token = nil, &verification_block)
  if params["hub.mode"] == "subscribe" &&
      # you can make sure this is legitimate through two ways
      # if your store the token across the calls, you can pass in the token value
      # and we'll make sure it matches
      ((verify_token && params["hub.verify_token"] == verify_token) ||
      # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
      # you can pass in a block, which we'll call with the verify_token sent by Facebook
      # if it's legit, return anything that evaluates to true; otherwise, return nil or false
      (verification_block && yield(params["hub.verify_token"])))
    params["hub.challenge"]
  else
    false
  end
end

Instance Method Details

#apiKoala::Facebook::API

The application API interface used to communicate with Facebook.



40
41
42
43
44
# File 'lib/koala/realtime_updates.rb', line 40

def api
  # Only instantiate the API if needed. validate_update doesn't require it, so we shouldn't
  # make an unnecessary request to get the app_access_token.
  @api ||= API.new(app_access_token)
end

#list_subscriptions(options = {}) ⇒ Array

List all active subscriptions for this application.



86
87
88
# File 'lib/koala/realtime_updates.rb', line 86

def list_subscriptions(options = {})
  api.graph_call(subscription_path, {}, "get", options)
end

#subscribe(object, fields, callback_url, verify_token, options = {}) ⇒ Object

Note:

Your callback_url must be set up to handle the verification request or the subscription will not be set up.

Subscribe to realtime updates for certain fields on a given object (user, page, etc.). See the realtime updates documentation for more information on what objects and fields you can register for.

Raises:

  • A subclass of Koala::Facebook::APIError if the subscription request failed.



60
61
62
63
64
65
66
67
68
# File 'lib/koala/realtime_updates.rb', line 60

def subscribe(object, fields, callback_url, verify_token, options = {})
  args = {
    :object => object,
    :fields => fields,
    :callback_url => callback_url,
  }.merge(verify_token ? {:verify_token => verify_token} : {})
  # a subscription is a success if Facebook returns a 200 (after hitting your server for verification)
  api.graph_call(subscription_path, args, 'post', options)
end

#subscription_pathObject

The Facebook subscription management URL for your application.



146
147
148
# File 'lib/koala/realtime_updates.rb', line 146

def subscription_path
  @subscription_path ||= "#{@app_id}/subscriptions"
end

#unsubscribe(object = nil, options = {}) ⇒ Object

Unsubscribe from updates for a particular object or from updates.

Raises:

  • A subclass of Koala::Facebook::APIError if the subscription request failed.



77
78
79
# File 'lib/koala/realtime_updates.rb', line 77

def unsubscribe(object = nil, options = {})
  api.graph_call(subscription_path, object ? {:object => object} : {}, "delete", options)
end

#validate_update(body, headers) ⇒ Object

Public: As a security measure, all updates from facebook are signed using X-Hub-Signature: sha1=XXXX where XXX is the sha1 of the json payload using your application secret as the key.

Example:

# in Rails controller
# @oauth being a previously defined Koala::Facebook::OAuth instance
def receive_update
  if @oauth.validate_update(request.body, headers)
    ...
  end
end


131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/koala/realtime_updates.rb', line 131

def validate_update(body, headers)
  unless @secret
    raise AppSecretNotDefinedError, "You must init RealtimeUpdates with your app secret in order to validate updates"
  end

  request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE']
  return unless request_signature

  signature_parts = request_signature.split("sha1=")
  request_signature = signature_parts[1]
  calculated_signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body)
  calculated_signature == request_signature
end