Class: FacebookRb::Client
- Inherits:
-
Object
- Object
- FacebookRb::Client
- Defined in:
- lib/facebookrb.rb
Defined Under Namespace
Classes: APIProxy
Constant Summary collapse
- FB_URL =
"http://api.facebook.com/restserver.php"
- FB_API_VERSION =
"1.0"
- USER_FIELDS =
[:uid, :status, :political, :pic_small, :name, :quotes, :is_app_user, :tv, :profile_update_time, :meeting_sex, :hs_info, :timezone, :relationship_status, :hometown_location, :about_me, :wall_count, :significant_other_id, :pic_big, :music, :work_history, :sex, :religion, :notes_count, :activities, :pic_square, :movies, :has_added_app, :education_history, :birthday, :birthday_date, :first_name, :meeting_for, :last_name, :interests, :current_location, :pic, :books, :affiliations, :locale, :profile_url, :proxied_email, :email_hashes, :allowed_restrictions, :pic_with_logo, :pic_big_with_logo, :pic_small_with_logo, :pic_square_with_logo]
- USER_FIELDS_STANDARD =
[:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :proxied_email]
Instance Attribute Summary collapse
-
#api_key ⇒ Object
Returns the value of attribute api_key.
-
#batch_queue ⇒ Object
Returns the value of attribute batch_queue.
-
#canvas_url ⇒ Object
Returns the value of attribute canvas_url.
-
#format ⇒ Object
Returns the value of attribute format.
-
#last_response ⇒ Object
Returns the value of attribute last_response.
-
#pending_batch ⇒ Object
Returns the value of attribute pending_batch.
-
#secret ⇒ Object
Returns the value of attribute secret.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #add_special_params(method, params) ⇒ Object
- #addurl ⇒ Object
-
#batch(options = {}) {|_self| ... } ⇒ Object
Performs a batch API operation (batch.run).
-
#call(method, params = {}) ⇒ Object
Call facebook server with a method request.
-
#convert_incoming_params(params) ⇒ Object
Converts some parameter values into more useful forms: * 0 or 1 into true/false * Time values into Time objects * Comma separated lists into arrays.
-
#convert_outgoing_params(params) ⇒ Object
Converts parameters being sent to Facebook from ruby objects to the appropriate text representation.
-
#extract_params(env) ⇒ Object
Extracts and validates any Facebook parameters from the request, and stores them in the client.
-
#generate_signature(fb_params, secret) ⇒ Object
Generate a signature using the application secret key.
-
#get_params_from(params, namespace = 'fb_sig') ⇒ Object
Get the signed parameters that were sent from Facebook.
-
#initialize(options = {}) ⇒ Client
constructor
A new instance of Client.
- #params ⇒ Object
- #url(path = nil) ⇒ Object
- #valid? ⇒ Boolean
Constructor Details
#initialize(options = {}) ⇒ Client
Returns a new instance of Client.
36 37 38 39 40 41 |
# File 'lib/facebookrb.rb', line 36 def initialize( = {}) self.api_key = [:api_key] || ['api_key'] self.secret = [:secret] || ['secret'] self.canvas_url = [:canvas_url] || ['canvas_url'] self.format = [:format] || ['format'] || 'JSON' end |
Instance Attribute Details
#api_key ⇒ Object
Returns the value of attribute api_key.
33 34 35 |
# File 'lib/facebookrb.rb', line 33 def api_key @api_key end |
#batch_queue ⇒ Object
Returns the value of attribute batch_queue.
34 35 36 |
# File 'lib/facebookrb.rb', line 34 def batch_queue @batch_queue end |
#canvas_url ⇒ Object
Returns the value of attribute canvas_url.
33 34 35 |
# File 'lib/facebookrb.rb', line 33 def canvas_url @canvas_url end |
#format ⇒ Object
Returns the value of attribute format.
33 34 35 |
# File 'lib/facebookrb.rb', line 33 def format @format end |
#last_response ⇒ Object
Returns the value of attribute last_response.
34 35 36 |
# File 'lib/facebookrb.rb', line 34 def last_response @last_response end |
#pending_batch ⇒ Object
Returns the value of attribute pending_batch.
34 35 36 |
# File 'lib/facebookrb.rb', line 34 def pending_batch @pending_batch end |
#secret ⇒ Object
Returns the value of attribute secret.
33 34 35 |
# File 'lib/facebookrb.rb', line 33 def secret @secret end |
Instance Method Details
#[](key) ⇒ Object
47 48 49 |
# File 'lib/facebookrb.rb', line 47 def [](key) params[key] end |
#add_special_params(method, params) ⇒ Object
150 151 152 153 154 |
# File 'lib/facebookrb.rb', line 150 def add_special_params(method, params) #call_as_apikey for Permissions API #ss Session secret #use_ssl_resources end |
#addurl ⇒ Object
59 60 61 |
# File 'lib/facebookrb.rb', line 59 def addurl "http://apps.facebook.com/add.php?api_key=#{self.api_key}" end |
#batch(options = {}) {|_self| ... } ⇒ Object
Performs a batch API operation (batch.run)
Example:
results = fb.batch do
fb.application.getPublicInfo(...)
fb.users.getInfo(...)
end
Options:
* :raise_errors (default true) - since a batch returns results for
multiple calls, some may return errors while others do not, by default
an exception will be raised if any errors are found. Set to
false to disable this and handle errors yourself
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/facebookrb.rb', line 121 def batch( = {}) return unless block_given? #TODO: real error code/message raise FacebookError.new('error_code', 'error_msg') if pending_batch self.batch_queue = [] self.pending_batch = true [:raise_errors] = true if [:raise_errors].nil? yield self self.pending_batch = false results = call('batch.run', :method_feed => self.batch_queue, :serial_only => true) self.batch_queue = nil #Batch results are an array of JSON strings, parse each results.map! { |json| Yajl::Parser.parse(json) } results.each do |data| if data.is_a?(Hash) && data['error_msg'] raise FacebookError.new(data['error_code'], data['error_msg']) end end if [:raise_errors] results end |
#call(method, params = {}) ⇒ Object
Call facebook server with a method request. Most keyword arguments are passed directly to the server with a few exceptions.
Returns a parsed json object.
If an error occurs, a FacebookError exception will be raised with the proper code and message.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/facebookrb.rb', line 72 def call(method, params={}) api_params = params.dup # Prepare standard arguments for call api_params['method'] ||= method api_params['api_key'] ||= self.api_key api_params['format'] ||= self.format api_params['session_key'] ||= self.params['session_key'] api_params['call_id'] ||= Time.now.to_f.to_s api_params['v'] ||= FB_API_VERSION convert_outgoing_params(api_params) api_params['sig'] = generate_signature(api_params, self.secret) #If in a batch, stash the params in the queue and bail if pending_batch batch_queue << api_params.map { |k,v| "#{k}=#{v}" }.join('&') return end # Call Facebook with POST request response = Net::HTTP.post_form( URI.parse(FB_URL), api_params ) # Handle response self.last_response = response.body data = Yajl::Parser.parse(response.body) if data.is_a?(Hash) && data['error_msg'] raise FacebookError.new(data['error_code'], data['error_msg']) end return data end |
#convert_incoming_params(params) ⇒ Object
Converts some parameter values into more useful forms:
* 0 or 1 into true/false
* Time values into Time objects
* Comma separated lists into arrays
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/facebookrb.rb', line 201 def convert_incoming_params(params) return nil unless params params.each do |key, value| case key when 'friends', 'linked_account_ids' params[key] = value.split(',') when /(time|expires)$/ if value == '0' params[key] = nil else params[key] = Time.at(value.to_f) end when /^(logged_out|position_|in_|is_)/, /added$/ params[key] = (value == '1') else params[key] = value end end params end |
#convert_outgoing_params(params) ⇒ Object
Converts parameters being sent to Facebook from ruby objects to the appropriate text representation
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/facebookrb.rb', line 228 def convert_outgoing_params(params) json_encoder = Yajl::Encoder.new params.each do |key, value| params.delete(key) if value.nil? case value when Array, Hash params[key] = json_encoder.encode(value) when Time params[key] = value.to_i.to_s when TrueClass params[key] = '1' when FalseClass params[key] = '0' end end params end |
#extract_params(env) ⇒ Object
Extracts and validates any Facebook parameters from the request, and stores them in the client. We look for parameters from POST, GET, then cookies, in that order. POST and GET are always more up-to-date than cookies, so we prefer those if they are available.
Parameters:
env the Rack environment, or a Rack request
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/facebookrb.rb', line 166 def extract_params(env) #Accept a Request object or the env if env.is_a?(Rack::Request) request = env else request = Rack::Request.new(env) end #Fetch from POST fb_params = get_params_from(request.POST, 'fb_sig') #Fetch from GET unless fb_params # note that with preload FQL, it's possible to receive POST params in # addition to GET, and a different prefix is used for each fb_get_params = get_params_from(request.GET, 'fb_sig') || {} fb_post_params = get_params_from(request.POST, 'fb_post_sig') || {} fb_get_params.merge!(fb_post_params) fb_params = fb_get_params unless fb_get_params.empty? end #Fetch from cookies unless fb_params fb_params = get_params_from(request., self.api_key) end @params = convert_incoming_params(fb_params) end |
#generate_signature(fb_params, secret) ⇒ Object
Generate a signature using the application secret key.
The only two entities that know your secret key are you and Facebook, according to the Terms of Service. Since nobody else can generate the signature, you can rely on it to verify that the information came from Facebook.
Parameters:
fb_params an array of all Facebook-sent parameters, NOT INCLUDING
the signature itself
secret your app's secret key
Returns:
a md5 hash to be checked against the signature provided by Facebook
297 298 299 300 |
# File 'lib/facebookrb.rb', line 297 def generate_signature(fb_params, secret) str = fb_params.map { |k,v| "#{k}=#{v}" }.sort.join Digest::MD5.hexdigest("#{str}#{secret}") end |
#get_params_from(params, namespace = 'fb_sig') ⇒ Object
Get the signed parameters that were sent from Facebook. Validates the set of parameters against the included signature.
Since Facebook sends data to your callback URL via unsecured means, the signature is the only way to make sure that the data actually came from Facebook. So if an app receives a request at the callback URL, it should always verify the signature that comes with against your own secret key. Otherwise, it’s possible for someone to spoof a request by pretending to be someone else, i.e.:
www.your-callback-url.com/?fb_user=10101
Parameters:
params A hash of parameters, i.e., from a HTTP request, or cookies
namespace prefix string for the set of parameters we want to verify.
i.e., fb_sig or fb_post_sig
Returns:
the subset of parameters containing the given prefix, and also matching
the signature associated with them, or nil if the params do not validate
267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/facebookrb.rb', line 267 def get_params_from(params, namespace='fb_sig') prefix = "#{namespace}_" fb_params = Hash.new params.each do |key, value| if key =~ /^#{prefix}(.*)$/ fb_params[$1] = value end end param_sig = params[namespace] gen_sig = generate_signature(fb_params, self.secret) return fb_params if param_sig == gen_sig nil end |
#params ⇒ Object
43 44 45 |
# File 'lib/facebookrb.rb', line 43 def params @params ||= {} end |
#url(path = nil) ⇒ Object
55 56 57 |
# File 'lib/facebookrb.rb', line 55 def url(path = nil) path ? "#{canvas_url}#{path}" : canvas_url end |
#valid? ⇒ Boolean
51 52 53 |
# File 'lib/facebookrb.rb', line 51 def valid? !params.empty? end |