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.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/koala/realtime_updates.rb', line 25

def initialize(options = {})
  @app_id = options[:app_id]
  @app_access_token = options[:app_access_token]
  @secret = options[: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

  # fetch the access token if we're provided a secret
  if @secret && !@app_access_token
    oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
    @app_access_token = oauth.get_app_access_token
  end

  @api = API.new(@app_access_token)
end

Instance Attribute Details

#apiKoala::Facebook::API (readonly)

The application API interface used to communicate with Facebook.



12
13
14
# File 'lib/koala/realtime_updates.rb', line 12

def api
  @api
end

#app_access_tokenObject (readonly)

Returns the value of attribute app_access_token.



13
14
15
# File 'lib/koala/realtime_updates.rb', line 13

def app_access_token
  @app_access_token
end

#app_idObject (readonly)

Returns the value of attribute app_id.



13
14
15
# File 'lib/koala/realtime_updates.rb', line 13

def app_id
  @app_id
end

#secretObject (readonly)

Returns the value of attribute secret.



13
14
15
# File 'lib/koala/realtime_updates.rb', line 13

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.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/koala/realtime_updates.rb', line 99

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

#list_subscriptions(options = {}) ⇒ Array

List all active subscriptions for this application.

Parameters:

Returns:

  • (Array)

    a list of active subscriptions



82
83
84
# File 'lib/koala/realtime_updates.rb', line 82

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)

  • options (defaults to: {})

    request-related options for Koala and Faraday. See github.com/arsduo/koala/wiki/HTTP-Services for additional options.

Raises:

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



56
57
58
59
60
61
62
63
64
# File 'lib/koala/realtime_updates.rb', line 56

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.



141
142
143
# File 'lib/koala/realtime_updates.rb', line 141

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.

  • options (defaults to: {})

    request-related options for Koala and Faraday. See github.com/arsduo/koala/wiki/HTTP-Services for additional options.

Raises:

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



73
74
75
# File 'lib/koala/realtime_updates.rb', line 73

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


127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/koala/realtime_updates.rb', line 127

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

  if request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE'] and
     signature_parts = request_signature.split("sha1=")
    request_signature = signature_parts[1]
    calculated_signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body)
    calculated_signature == request_signature
  end
end