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.
- data/lib/mini_fb.rb +277 -276
- data/test/mini_fb_tests.rb +1 -1
- metadata +3 -2
data/lib/mini_fb.rb
CHANGED
@@ -1,276 +1,277 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@
|
34
|
-
@
|
35
|
-
@
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@user
|
42
|
-
@user
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
@
|
71
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
#
|
115
|
-
#
|
116
|
-
# The '
|
117
|
-
# The '
|
118
|
-
#
|
119
|
-
|
120
|
-
|
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
|
-
kwargs
|
148
|
-
kwargs["
|
149
|
-
kwargs["
|
150
|
-
kwargs["
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
kwargs[
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
# - :
|
217
|
-
|
218
|
-
|
219
|
-
login_url
|
220
|
-
login_url << "&
|
221
|
-
login_url
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
|
233
|
-
#
|
234
|
-
#
|
235
|
-
|
236
|
-
#
|
237
|
-
#
|
238
|
-
|
239
|
-
#
|
240
|
-
#
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
#
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
data/test/mini_fb_tests.rb
CHANGED
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.
|
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-
|
13
|
+
date: 2009-12-03 00:00:00 -08:00
|
13
14
|
default_executable:
|
14
15
|
dependencies: []
|
15
16
|
|