mini_fb 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.markdown +38 -0
  2. data/lib/mini_fb.rb +204 -0
  3. data/test/mini_fb_tests.rb +22 -0
  4. metadata +56 -0
data/README.markdown ADDED
@@ -0,0 +1,38 @@
1
+ MiniFB - the simple miniature facebook library
2
+ ==============================================
3
+
4
+ MiniFB is a small, lightweight Ruby library for interacting with the [Facebook API](http://wiki.developers.facebook.com/index.php/API).
5
+
6
+ General Usage
7
+ -------------
8
+
9
+ The most general case is to use MiniFB.call method:
10
+
11
+ user_hash = MiniFB.call(FB_API_KEY, FB_SECRET, "Users.getInfo", "session_key"=>@session_key, "uids"=>@uid, "fields"=>User.all_fields)
12
+
13
+ Which simply returns the parsed json response from Facebook.
14
+
15
+ Some Higher Level Objects for Common Uses
16
+ ----------------------
17
+
18
+ Get a MiniFB::Session:
19
+
20
+ @fb = MiniFB::Session.new(FB_API_KEY, FB_SECRET, @fb_session, @fb_uid)
21
+
22
+ With the session, you can then get the user information for the session/uid.
23
+
24
+ user = @fb.user
25
+
26
+ Then get info from the user:
27
+
28
+ first_name = user["first_name"]
29
+
30
+ Or profile photos:
31
+
32
+ photos = user.profile_photos
33
+
34
+ Or if you want other photos, try:
35
+
36
+ photos = @fb.photos("pids"=>[12343243,920382343,9208348])
37
+
38
+
data/lib/mini_fb.rb ADDED
@@ -0,0 +1,204 @@
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
+ class FaceBookError < StandardError
11
+ # Error that happens during a facebook call.
12
+ def initialize( error_code, error_msg )
13
+ raise StandardError.new( "Facebook error #{error_code}: #{error_msg}" )
14
+ end
15
+ end
16
+
17
+ class Session
18
+ attr_accessor :api_key, :secret_key, :session_key, :uid
19
+
20
+
21
+ def initialize(api_key, secret_key, session_key, uid)
22
+ @api_key = api_key
23
+ @secret_key = FaceBookSecret.new secret_key
24
+ @session_key = session_key
25
+ @uid = uid
26
+ end
27
+
28
+ # returns current user
29
+ def user
30
+ return @user unless @user.nil?
31
+ @user = User.new(MiniFB.call(@api_key, @secret_key, "Users.getInfo", "session_key"=>@session_key, "uids"=>@uid, "fields"=>User.all_fields)[0], self)
32
+ @user
33
+ end
34
+
35
+ def photos
36
+ Photos.new(self)
37
+ end
38
+
39
+
40
+ end
41
+ class User
42
+ 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]
43
+ STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :proxied_email]
44
+
45
+ def self.all_fields
46
+ FIELDS.join(",")
47
+ end
48
+
49
+ def initialize(fb_hash, session)
50
+ @fb_hash = fb_hash
51
+ @session = session
52
+ end
53
+
54
+ def [](key)
55
+ @fb_hash[key]
56
+ end
57
+
58
+ def uid
59
+ return self["uid"]
60
+ end
61
+
62
+ def profile_photos
63
+ @session.photos.get("uid"=>uid, "aid"=>profile_pic_album_id)
64
+ end
65
+
66
+ def profile_pic_album_id
67
+ merge_aid(-3, uid)
68
+ end
69
+
70
+ def merge_aid(aid, uid)
71
+ uid = uid.to_i
72
+ ret = (uid << 32) + (aid & 0xFFFFFFFF)
73
+ # puts 'merge_aid=' + ret.inspect
74
+ return ret
75
+ end
76
+ end
77
+
78
+ class Photos
79
+
80
+ def initialize(session)
81
+ @session = session
82
+ end
83
+
84
+ def get(params)
85
+ pids = params["pids"]
86
+ if !pids.nil? && pids.is_a?(Array)
87
+ pids = pids.join(",")
88
+ params["pids"] = pids
89
+ end
90
+ MiniFB.call(@session.api_key, @session.secret_key, "photos.get", params.update("session_key"=>@session.session_key))
91
+ end
92
+ end
93
+
94
+ # Call facebook server with a method request. Most keyword arguments
95
+ # are passed directly to the server with a few exceptions.
96
+ # The 'sig' value will always be computed automatically.
97
+ # The 'v' version will be supplied automatically if needed.
98
+ # The 'call_id' defaults to True, which will generate a valid
99
+ # number. Otherwise it should be a valid number or False to disable.
100
+
101
+ # The default return is a parsed json object.
102
+ # Unless the 'format' and/or 'callback' arguments are given,
103
+ # in which case the raw text of the reply is returned. The string
104
+ # will always be returned, even during errors.
105
+
106
+ # If an error occurs, a FacebookError exception will be raised
107
+ # with the proper code and message.
108
+
109
+ # The secret argument should be an instance of FacebookSecret
110
+ # to hide value from simple introspection.
111
+ def MiniFB.call( api_key, secret, method, kwargs )
112
+
113
+ puts 'kwargs=' + kwargs.inspect
114
+
115
+ # Prepare arguments for call
116
+ call_id = kwargs.fetch("call_id", true)
117
+ if call_id == true then
118
+ kwargs["call_id"] = Time.now.tv_sec.to_s
119
+ else
120
+ kwargs.delete("call_id")
121
+ end
122
+
123
+ custom_format = kwargs.include?("format") or kwargs.include?("callback")
124
+ kwargs["format"] ||= "JSON"
125
+ kwargs["v"] ||= FB_API_VERSION
126
+ kwargs["api_key"]||= api_key
127
+ kwargs["method"] ||= method
128
+
129
+ # Hash with secret
130
+ arg_string = String.new
131
+ kwargs.sort.each { |kv| arg_string << kv[0] << "=" << kv[1].to_s }
132
+ kwargs["sig"] = Digest::MD5.hexdigest( arg_string + secret.value.call )
133
+
134
+ # Call website with POST request
135
+ begin
136
+ response = Net::HTTP.post_form( URI.parse(FB_URL), kwargs )
137
+ rescue SocketError => err
138
+ raise IOError.new( "Cannot connect to the facebook server: " + err )
139
+ end
140
+
141
+ # Handle response
142
+ return response.body if custom_format
143
+
144
+ data = JSON.parse( response.body )
145
+ puts 'response=' + data.inspect
146
+ if data.include?( "error_msg" ) then
147
+ raise FaceBookError.new( data["error_code"] || 1, data["error_msg"] )
148
+ end
149
+ return data
150
+ end
151
+
152
+
153
+ # This function expects arguments as a hash, so
154
+ # it is agnostic to different POST handling variants in ruby.
155
+ #
156
+ # Validate the arguments received from facebook. This is usually
157
+ # sent for the iframe in Facebook's canvas. It is not necessary
158
+ # to use this on the auth_token and uid passed to callbacks like
159
+ # post-add and post-remove.
160
+ #
161
+ # The arguments must be a mapping of to string keys and values
162
+ # or a string of http request data.
163
+ #
164
+ # If the data is invalid or not signed properly, and empty
165
+ # dictionary is returned.
166
+ #
167
+ # The secret argument should be an instance of FacebookSecret
168
+ # to hide value from simple introspection.
169
+ #
170
+ def MiniFB.validate( secret, arguments )
171
+
172
+ signature = arguments.delete( "fb_sig" )
173
+ return arguments if signature.nil?
174
+
175
+ unsigned = Hash.new
176
+ signed = Hash.new
177
+
178
+ arguments.each do |k, v|
179
+ if k =~ /^fb_sig_(.*)/ then
180
+ signed[$1] = v
181
+ else
182
+ unsigned[k] = v
183
+ end
184
+ end
185
+
186
+ arg_string = String.new
187
+ signed.sort.each { |kv| arg_string << kv[0] << "=" << kv[1] }
188
+ if Digest::MD5.hexdigest( arg_string + secret ) != signature then
189
+ unsigned # Hash is incorrect, return only unsigned fields.
190
+ else
191
+ unsigned.merge signed
192
+ end
193
+ end
194
+
195
+ class FaceBookSecret
196
+ # Simple container that stores a secret value.
197
+ # Proc cannot be dumped or introspected by normal tools.
198
+ attr_reader :value
199
+
200
+ def initialize( value )
201
+ @value = Proc.new { value }
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+ class MiniFBTests < Test::Unit::TestCase
3
+
4
+ def setup
5
+
6
+ end
7
+ def teardown
8
+
9
+ end
10
+
11
+ def test_basic_calls
12
+
13
+ end
14
+
15
+ def test_session
16
+
17
+ end
18
+
19
+ def test_photos
20
+
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_fb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Travis Reeder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-11 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Tiny facebook library
17
+ email: travis@appoxy.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - lib/mini_fb.rb
26
+ - README.markdown
27
+ has_rdoc: true
28
+ homepage: http://github.com/appoxy/mini_fb
29
+ licenses: []
30
+
31
+ post_install_message:
32
+ rdoc_options:
33
+ - --charset=UTF-8
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ requirements: []
49
+
50
+ rubyforge_project:
51
+ rubygems_version: 1.3.5
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Tiny facebook library
55
+ test_files:
56
+ - test/mini_fb_tests.rb