mini_fb 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/lib/mini_fb.rb +277 -276
  2. data/test/mini_fb_tests.rb +1 -1
  3. metadata +3 -2
data/lib/mini_fb.rb CHANGED
@@ -1,276 +1,277 @@
1
- module MiniFB
2
- require 'digest/md5'
3
- require 'erb'
4
- require 'json/pure'
5
-
6
- # Global constants
7
- FB_URL = "http://api.facebook.com/restserver.php"
8
- FB_API_VERSION = "1.0"
9
-
10
- @@logging = false
11
-
12
- def enable_logging
13
- @@logging = true
14
- end
15
-
16
- def disable_logging
17
- @@logging = false
18
- end
19
-
20
- class FaceBookError < StandardError
21
- # Error that happens during a facebook call.
22
- def initialize( error_code, error_msg )
23
- super("Facebook error #{error_code}: #{error_msg}" )
24
- end
25
- end
26
-
27
- class Session
28
- attr_accessor :api_key, :secret_key, :session_key, :uid
29
-
30
-
31
- def initialize(api_key, secret_key, session_key, uid)
32
- @api_key = api_key
33
- @secret_key = FaceBookSecret.new secret_key
34
- @session_key = session_key
35
- @uid = uid
36
- end
37
-
38
- # returns current user
39
- def user
40
- return @user unless @user.nil?
41
- @user = User.new(MiniFB.call(@api_key, @secret_key, "Users.getInfo", "session_key"=>@session_key, "uids"=>@uid, "fields"=>User.all_fields)[0], self)
42
- @user
43
- end
44
-
45
- def photos
46
- Photos.new(self)
47
- end
48
-
49
-
50
- def call(method, params={})
51
- return MiniFB.call(api_key, secret_key, method, params.update("session_key"=>session_key))
52
- end
53
-
54
-
55
- end
56
- class User
57
- 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]
58
- STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :proxied_email]
59
-
60
- def self.all_fields
61
- FIELDS.join(",")
62
- end
63
-
64
- def self.standard_fields
65
- STANDARD_FIELDS.join(",")
66
- end
67
-
68
- def initialize(fb_hash, session)
69
- @fb_hash = fb_hash
70
- @session = session
71
- end
72
-
73
- def [](key)
74
- @fb_hash[key]
75
- end
76
-
77
- def uid
78
- return self["uid"]
79
- end
80
-
81
- def profile_photos
82
- @session.photos.get("uid"=>uid, "aid"=>profile_pic_album_id)
83
- end
84
-
85
- def profile_pic_album_id
86
- merge_aid(-3, uid)
87
- end
88
-
89
- def merge_aid(aid, uid)
90
- uid = uid.to_i
91
- ret = (uid << 32) + (aid & 0xFFFFFFFF)
92
- # puts 'merge_aid=' + ret.inspect
93
- return ret
94
- end
95
- end
96
-
97
- class Photos
98
-
99
- def initialize(session)
100
- @session = session
101
- end
102
-
103
- def get(params)
104
- pids = params["pids"]
105
- if !pids.nil? && pids.is_a?(Array)
106
- pids = pids.join(",")
107
- params["pids"] = pids
108
- end
109
- @session.call("photos.get", params)
110
- end
111
- end
112
-
113
- # Call facebook server with a method request. Most keyword arguments
114
- # are passed directly to the server with a few exceptions.
115
- # The 'sig' value will always be computed automatically.
116
- # The 'v' version will be supplied automatically if needed.
117
- # The 'call_id' defaults to True, which will generate a valid
118
- # number. Otherwise it should be a valid number or False to disable.
119
-
120
- # The default return is a parsed json object.
121
- # Unless the 'format' and/or 'callback' arguments are given,
122
- # in which case the raw text of the reply is returned. The string
123
- # will always be returned, even during errors.
124
-
125
- # If an error occurs, a FacebookError exception will be raised
126
- # with the proper code and message.
127
-
128
- # The secret argument should be an instance of FacebookSecret
129
- # to hide value from simple introspection.
130
- def MiniFB.call( api_key, secret, method, kwargs )
131
-
132
- puts 'kwargs=' + kwargs.inspect
133
-
134
- if secret.is_a? String
135
- secret = FaceBookSecret.new(secret)
136
- end
137
-
138
- # Prepare arguments for call
139
- call_id = kwargs.fetch("call_id", true)
140
- if call_id == true then
141
- kwargs["call_id"] = Time.now.tv_sec.to_s
142
- else
143
- kwargs.delete("call_id")
144
- end
145
-
146
- custom_format = kwargs.include?("format") or kwargs.include?("callback")
147
- kwargs["format"] ||= "JSON"
148
- kwargs["v"] ||= FB_API_VERSION
149
- kwargs["api_key"]||= api_key
150
- kwargs["method"] ||= method
151
-
152
- # Hash with secret
153
- arg_string = String.new
154
- # todo: convert symbols to strings, symbols break the next line
155
- kwargs.sort.each { |kv| arg_string << kv[0] << "=" << kv[1].to_s }
156
- kwargs["sig"] = Digest::MD5.hexdigest( arg_string + secret.value.call )
157
-
158
- # Call website with POST request
159
- begin
160
- response = Net::HTTP.post_form( URI.parse(FB_URL), kwargs )
161
- rescue SocketError => err
162
- raise IOError.new( "Cannot connect to the facebook server: " + err )
163
- end
164
-
165
- # Handle response
166
- return response.body if custom_format
167
-
168
- fb_method = kwargs["method"]
169
- body = response.body
170
-
171
- begin
172
- data = JSON.parse( body )
173
- puts 'response=' + data.inspect if @@logging
174
- if data.include?( "error_msg" ) then
175
- raise FaceBookError.new( data["error_code"] || 1, data["error_msg"] )
176
- end
177
-
178
- rescue JSON::ParserError => ex
179
- if fb_method == "users.getLoggedInUser" # Little hack because this response isn't valid JSON
180
- return body
181
- else
182
- raise ex
183
- end
184
- end
185
- return data
186
- end
187
-
188
- # Returns true is signature is valid, false otherwise.
189
- def MiniFB.verify_signature( secret, arguments )
190
- signature = arguments.delete( "fb_sig" )
191
- return false if signature.nil?
192
-
193
- unsigned = Hash.new
194
- signed = Hash.new
195
-
196
- arguments.each do |k, v|
197
- if k =~ /^fb_sig_(.*)/ then
198
- signed[$1] = v
199
- else
200
- unsigned[k] = v
201
- end
202
- end
203
-
204
- arg_string = String.new
205
- signed.sort.each { |kv| arg_string << kv[0] << "=" << kv[1] }
206
- if Digest::MD5.hexdigest( arg_string + secret ) == signature
207
- return true
208
- end
209
- return false
210
- end
211
-
212
- # Returns the login/add app url for your application.
213
- #
214
- # options:
215
- # - :next => a relative next page to go to. relative to your facebook connect url or if :canvas is true, then relative to facebook app url
216
- # - :canvas => true/false - to say whether this is a canvas app or not
217
- def self.login_url(api_key, options={})
218
- login_url = "http://api.facebook.com/login.php?api_key=#{api_key}"
219
- login_url << "&next=#{options[:next]}" if options[:next]
220
- login_url << "&canvas" if options[:canvas]
221
- login_url
222
- end
223
-
224
- # This function expects arguments as a hash, so
225
- # it is agnostic to different POST handling variants in ruby.
226
- #
227
- # Validate the arguments received from facebook. This is usually
228
- # sent for the iframe in Facebook's canvas. It is not necessary
229
- # to use this on the auth_token and uid passed to callbacks like
230
- # post-add and post-remove.
231
- #
232
- # The arguments must be a mapping of to string keys and values
233
- # or a string of http request data.
234
- #
235
- # If the data is invalid or not signed properly, an empty
236
- # dictionary is returned.
237
- #
238
- # The secret argument should be an instance of FacebookSecret
239
- # to hide value from simple introspection.
240
- #
241
- # DEPRECATED, use verify_signature instead
242
- def MiniFB.validate( secret, arguments )
243
-
244
- signature = arguments.delete( "fb_sig" )
245
- return arguments if signature.nil?
246
-
247
- unsigned = Hash.new
248
- signed = Hash.new
249
-
250
- arguments.each do |k, v|
251
- if k =~ /^fb_sig_(.*)/ then
252
- signed[$1] = v
253
- else
254
- unsigned[k] = v
255
- end
256
- end
257
-
258
- arg_string = String.new
259
- signed.sort.each { |kv| arg_string << kv[0] << "=" << kv[1] }
260
- if Digest::MD5.hexdigest( arg_string + secret ) != signature
261
- unsigned # Hash is incorrect, return only unsigned fields.
262
- else
263
- unsigned.merge signed
264
- end
265
- end
266
-
267
- class FaceBookSecret
268
- # Simple container that stores a secret value.
269
- # Proc cannot be dumped or introspected by normal tools.
270
- attr_reader :value
271
-
272
- def initialize( value )
273
- @value = Proc.new { value }
274
- end
275
- end
276
- end
1
+ require 'digest/md5'
2
+ require 'erb'
3
+ require 'json' unless defined? JSON
4
+
5
+ module MiniFB
6
+
7
+ # Global constants
8
+ FB_URL = "http://api.facebook.com/restserver.php"
9
+ FB_API_VERSION = "1.0"
10
+
11
+ @@logging = false
12
+
13
+ def enable_logging
14
+ @@logging = true
15
+ end
16
+
17
+ def disable_logging
18
+ @@logging = false
19
+ end
20
+
21
+ class FaceBookError < StandardError
22
+ # Error that happens during a facebook call.
23
+ def initialize( error_code, error_msg )
24
+ super("Facebook error #{error_code}: #{error_msg}" )
25
+ end
26
+ end
27
+
28
+ class Session
29
+ attr_accessor :api_key, :secret_key, :session_key, :uid
30
+
31
+
32
+ def initialize(api_key, secret_key, session_key, uid)
33
+ @api_key = api_key
34
+ @secret_key = FaceBookSecret.new secret_key
35
+ @session_key = session_key
36
+ @uid = uid
37
+ end
38
+
39
+ # returns current user
40
+ def user
41
+ return @user unless @user.nil?
42
+ @user = User.new(MiniFB.call(@api_key, @secret_key, "Users.getInfo", "session_key"=>@session_key, "uids"=>@uid, "fields"=>User.all_fields)[0], self)
43
+ @user
44
+ end
45
+
46
+ def photos
47
+ Photos.new(self)
48
+ end
49
+
50
+
51
+ def call(method, params={})
52
+ return MiniFB.call(api_key, secret_key, method, params.update("session_key"=>session_key))
53
+ end
54
+
55
+
56
+ end
57
+ class User
58
+ 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]
59
+ STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :proxied_email]
60
+
61
+ def self.all_fields
62
+ FIELDS.join(",")
63
+ end
64
+
65
+ def self.standard_fields
66
+ STANDARD_FIELDS.join(",")
67
+ end
68
+
69
+ def initialize(fb_hash, session)
70
+ @fb_hash = fb_hash
71
+ @session = session
72
+ end
73
+
74
+ def [](key)
75
+ @fb_hash[key]
76
+ end
77
+
78
+ def uid
79
+ return self["uid"]
80
+ end
81
+
82
+ def profile_photos
83
+ @session.photos.get("uid"=>uid, "aid"=>profile_pic_album_id)
84
+ end
85
+
86
+ def profile_pic_album_id
87
+ merge_aid(-3, uid)
88
+ end
89
+
90
+ def merge_aid(aid, uid)
91
+ uid = uid.to_i
92
+ ret = (uid << 32) + (aid & 0xFFFFFFFF)
93
+ # puts 'merge_aid=' + ret.inspect
94
+ return ret
95
+ end
96
+ end
97
+
98
+ class Photos
99
+
100
+ def initialize(session)
101
+ @session = session
102
+ end
103
+
104
+ def get(params)
105
+ pids = params["pids"]
106
+ if !pids.nil? && pids.is_a?(Array)
107
+ pids = pids.join(",")
108
+ params["pids"] = pids
109
+ end
110
+ @session.call("photos.get", params)
111
+ end
112
+ end
113
+
114
+ # Call facebook server with a method request. Most keyword arguments
115
+ # are passed directly to the server with a few exceptions.
116
+ # The 'sig' value will always be computed automatically.
117
+ # The 'v' version will be supplied automatically if needed.
118
+ # The 'call_id' defaults to True, which will generate a valid
119
+ # number. Otherwise it should be a valid number or False to disable.
120
+
121
+ # The default return is a parsed json object.
122
+ # Unless the 'format' and/or 'callback' arguments are given,
123
+ # in which case the raw text of the reply is returned. The string
124
+ # will always be returned, even during errors.
125
+
126
+ # If an error occurs, a FacebookError exception will be raised
127
+ # with the proper code and message.
128
+
129
+ # The secret argument should be an instance of FacebookSecret
130
+ # to hide value from simple introspection.
131
+ def MiniFB.call( api_key, secret, method, kwargs )
132
+
133
+ puts 'kwargs=' + kwargs.inspect
134
+
135
+ if secret.is_a? String
136
+ secret = FaceBookSecret.new(secret)
137
+ end
138
+
139
+ # Prepare arguments for call
140
+ call_id = kwargs.fetch("call_id", true)
141
+ if call_id == true then
142
+ kwargs["call_id"] = Time.now.tv_sec.to_s
143
+ else
144
+ kwargs.delete("call_id")
145
+ end
146
+
147
+ custom_format = kwargs.include?("format") or kwargs.include?("callback")
148
+ kwargs["format"] ||= "JSON"
149
+ kwargs["v"] ||= FB_API_VERSION
150
+ kwargs["api_key"]||= api_key
151
+ kwargs["method"] ||= method
152
+
153
+ # Hash with secret
154
+ arg_string = String.new
155
+ # todo: convert symbols to strings, symbols break the next line
156
+ kwargs.sort.each { |kv| arg_string << kv[0] << "=" << kv[1].to_s }
157
+ kwargs["sig"] = Digest::MD5.hexdigest( arg_string + secret.value.call )
158
+
159
+ # Call website with POST request
160
+ begin
161
+ response = Net::HTTP.post_form( URI.parse(FB_URL), kwargs )
162
+ rescue SocketError => err
163
+ raise IOError.new( "Cannot connect to the facebook server: " + err )
164
+ end
165
+
166
+ # Handle response
167
+ return response.body if custom_format
168
+
169
+ fb_method = kwargs["method"]
170
+ body = response.body
171
+
172
+ begin
173
+ data = JSON.parse( body )
174
+ puts 'response=' + data.inspect if @@logging
175
+ if data.include?( "error_msg" ) then
176
+ raise FaceBookError.new( data["error_code"] || 1, data["error_msg"] )
177
+ end
178
+
179
+ rescue JSON::ParserError => ex
180
+ if fb_method == "users.getLoggedInUser" # Little hack because this response isn't valid JSON
181
+ return body
182
+ else
183
+ raise ex
184
+ end
185
+ end
186
+ return data
187
+ end
188
+
189
+ # Returns true is signature is valid, false otherwise.
190
+ def MiniFB.verify_signature( secret, arguments )
191
+ signature = arguments.delete( "fb_sig" )
192
+ return false if signature.nil?
193
+
194
+ unsigned = Hash.new
195
+ signed = Hash.new
196
+
197
+ arguments.each do |k, v|
198
+ if k =~ /^fb_sig_(.*)/ then
199
+ signed[$1] = v
200
+ else
201
+ unsigned[k] = v
202
+ end
203
+ end
204
+
205
+ arg_string = String.new
206
+ signed.sort.each { |kv| arg_string << kv[0] << "=" << kv[1] }
207
+ if Digest::MD5.hexdigest( arg_string + secret ) == signature
208
+ return true
209
+ end
210
+ return false
211
+ end
212
+
213
+ # Returns the login/add app url for your application.
214
+ #
215
+ # options:
216
+ # - :next => a relative next page to go to. relative to your facebook connect url or if :canvas is true, then relative to facebook app url
217
+ # - :canvas => true/false - to say whether this is a canvas app or not
218
+ def self.login_url(api_key, options={})
219
+ login_url = "http://api.facebook.com/login.php?api_key=#{api_key}"
220
+ login_url << "&next=#{options[:next]}" if options[:next]
221
+ login_url << "&canvas" if options[:canvas]
222
+ login_url
223
+ end
224
+
225
+ # This function expects arguments as a hash, so
226
+ # it is agnostic to different POST handling variants in ruby.
227
+ #
228
+ # Validate the arguments received from facebook. This is usually
229
+ # sent for the iframe in Facebook's canvas. It is not necessary
230
+ # to use this on the auth_token and uid passed to callbacks like
231
+ # post-add and post-remove.
232
+ #
233
+ # The arguments must be a mapping of to string keys and values
234
+ # or a string of http request data.
235
+ #
236
+ # If the data is invalid or not signed properly, an empty
237
+ # dictionary is returned.
238
+ #
239
+ # The secret argument should be an instance of FacebookSecret
240
+ # to hide value from simple introspection.
241
+ #
242
+ # DEPRECATED, use verify_signature instead
243
+ def MiniFB.validate( secret, arguments )
244
+
245
+ signature = arguments.delete( "fb_sig" )
246
+ return arguments if signature.nil?
247
+
248
+ unsigned = Hash.new
249
+ signed = Hash.new
250
+
251
+ arguments.each do |k, v|
252
+ if k =~ /^fb_sig_(.*)/ then
253
+ signed[$1] = v
254
+ else
255
+ unsigned[k] = v
256
+ end
257
+ end
258
+
259
+ arg_string = String.new
260
+ signed.sort.each { |kv| arg_string << kv[0] << "=" << kv[1] }
261
+ if Digest::MD5.hexdigest( arg_string + secret ) != signature
262
+ unsigned # Hash is incorrect, return only unsigned fields.
263
+ else
264
+ unsigned.merge signed
265
+ end
266
+ end
267
+
268
+ class FaceBookSecret
269
+ # Simple container that stores a secret value.
270
+ # Proc cannot be dumped or introspected by normal tools.
271
+ attr_reader :value
272
+
273
+ def initialize( value )
274
+ @value = Proc.new { value }
275
+ end
276
+ end
277
+ end
@@ -1,8 +1,8 @@
1
1
  require 'test/unit'
2
2
  class MiniFBTests < Test::Unit::TestCase
3
3
 
4
- def setup
5
4
 
5
+ def setup
6
6
  end
7
7
 
8
8
  def teardown
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_fb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Reeder
8
+ - Aaron Hurley
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-11-13 00:00:00 -08:00
13
+ date: 2009-12-03 00:00:00 -08:00
13
14
  default_executable:
14
15
  dependencies: []
15
16