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.

Parameters:

  • options (defaults to: {})

    initialization options.

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.

Parameters:

  • params

    the request parameters sent by Facebook. (You can pass in a Rails params hash.)

  • verify_token (defaults to: nil)

    the verify token sent in the subscription request, if you provided one

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.

Returns:

  • the challenge string to be sent back to Facebook, or false if the request is invalid.


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.

Returns:

  • (Array)

    a list of active subscriptions


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.

Parameters:

  • object

    a Facebook ID (name or number)

  • fields

    the fields you want your app to be updated about

  • callback_url

    the URL Facebook should ping when an update is available

  • verify_token

    a token included in the verification request, allowing you to ensure the call is genuine (see the docs for more information)

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.

Parameters:

  • object (defaults to: nil)

    the object whose subscriptions to delete. If no object is provided, all subscriptions will be removed.

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