mini_fb 0.1.1

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 (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