facebooker 1.0.31 → 1.0.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/Manifest.txt +5 -0
  3. data/README.rdoc +9 -0
  4. data/facebooker.gemspec +8 -9
  5. data/generators/facebook/templates/public/javascripts/facebooker.js +10 -16
  6. data/init.rb +4 -1
  7. data/install.rb +1 -1
  8. data/lib/facebooker.rb +75 -20
  9. data/lib/facebooker/adapters/bebo_adapter.rb +9 -9
  10. data/lib/facebooker/data.rb +14 -14
  11. data/lib/facebooker/models/page.rb +16 -0
  12. data/lib/facebooker/models/photo.rb +7 -0
  13. data/lib/facebooker/models/user.rb +75 -28
  14. data/lib/facebooker/parser.rb +187 -127
  15. data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
  16. data/lib/facebooker/rails/controller.rb +30 -7
  17. data/lib/facebooker/rails/extensions/rack_setup.rb +5 -1
  18. data/lib/facebooker/rails/facebook_request_fix.rb +5 -5
  19. data/lib/facebooker/rails/facebook_request_fix_2-3.rb +31 -0
  20. data/lib/facebooker/rails/facebook_url_rewriting.rb +7 -2
  21. data/lib/facebooker/rails/helpers.rb +29 -5
  22. data/lib/facebooker/rails/helpers/fb_connect.rb +14 -5
  23. data/lib/facebooker/rails/publisher.rb +26 -12
  24. data/lib/facebooker/service.rb +64 -56
  25. data/lib/facebooker/session.rb +56 -22
  26. data/lib/facebooker/version.rb +1 -1
  27. data/lib/rack/facebook.rb +26 -14
  28. data/lib/tasks/tunnel.rake +1 -1
  29. data/test/facebooker/adapters_test.rb +78 -0
  30. data/test/facebooker/data_test.rb +14 -14
  31. data/test/facebooker/models/page_test.rb +46 -0
  32. data/test/facebooker/models/photo_test.rb +16 -0
  33. data/test/facebooker/models/user_test.rb +83 -48
  34. data/test/facebooker/rails/facebook_request_fix_2-3_test.rb +25 -0
  35. data/test/facebooker/rails/facebook_url_rewriting_test.rb +39 -0
  36. data/test/facebooker/rails/publisher_test.rb +5 -1
  37. data/test/facebooker/rails_integration_test.rb +52 -8
  38. data/test/facebooker/service_test.rb +58 -0
  39. data/test/facebooker/session_test.rb +106 -92
  40. data/test/facebooker_test.rb +2 -2
  41. data/test/rack/facebook_test.rb +4 -4
  42. data/test/test_helper.rb +10 -3
  43. metadata +14 -4
@@ -8,5 +8,12 @@ module Facebooker
8
8
  :story_fbid
9
9
 
10
10
  id_is :pid
11
+
12
+ #override the generated method for id_is to use a string
13
+ def pid=(val)
14
+ @pid = val
15
+ end
16
+
17
+ alias :id= :pid=
11
18
  end
12
19
  end
@@ -10,7 +10,7 @@ module Facebooker
10
10
  include Model
11
11
  attr_accessor :message, :time, :status_id
12
12
  end
13
- FIELDS = [: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, :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]
13
+ FIELDS = [: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, :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]
14
14
  STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :pic_square]
15
15
  populating_attr_accessor(*FIELDS)
16
16
  attr_reader :affiliations
@@ -69,47 +69,88 @@ module Facebooker
69
69
  # Set the list of friends, given an array of User objects. If the list has been retrieved previously, will not set
70
70
  def friends=(list_of_friends,flid=nil)
71
71
  @friends_hash ||= {}
72
- flid=cast_to_friend_list_id(flid)
73
- #use __blank instead of nil so that this is cached
74
- cache_key = flid||"__blank"
75
-
72
+ flid=cast_to_friend_list_id(flid)
73
+ #use __blank instead of nil so that this is cached
74
+ cache_key = flid||"__blank"
75
+
76
76
  @friends_hash[cache_key] ||= list_of_friends
77
77
  end
78
78
 
79
79
  def cast_to_friend_list_id(flid)
80
80
  case flid
81
- when String
82
- list=friend_lists.detect {|f| f.name==flid}
83
- raise Facebooker::Session::InvalidFriendList unless list
84
- list.flid
85
- when FriendList
86
- flid.flid
87
- else
88
- flid
89
- end
90
- end
81
+ when String
82
+ list=friend_lists.detect {|f| f.name==flid}
83
+ raise Facebooker::Session::InvalidFriendList unless list
84
+ list.flid
85
+ when FriendList
86
+ flid.flid
87
+ else
88
+ flid
89
+ end
90
+ end
91
91
  ##
92
92
  # Retrieve friends
93
93
  def friends(flid = nil)
94
- @friends_hash ||= {}
95
- flid=cast_to_friend_list_id(flid)
96
-
97
- #use __blank instead of nil so that this is cached
98
- cache_key = flid||"__blank"
99
- options = {:uid=>self.id}
100
- options[:flid] = flid unless flid.nil?
101
- @friends_hash[cache_key] ||= @session.post('facebook.friends.get', options,false).map do |uid|
94
+ @friends_hash ||= {}
95
+ flid=cast_to_friend_list_id(flid)
96
+
97
+ #use __blank instead of nil so that this is cached
98
+ cache_key = flid||"__blank"
99
+ options = {:uid=>self.id}
100
+ options[:flid] = flid unless flid.nil?
101
+ @friends_hash[cache_key] ||= @session.post('facebook.friends.get', options,false).map do |uid|
102
102
  User.new(uid, @session)
103
103
  end
104
104
  @friends_hash[cache_key]
105
105
  end
106
+
107
+ ###
108
+ # Publish a post into the stream on the user's Wall and News Feed. This
109
+ # post also appears in the user's friend's streams. The +publish_stream+
110
+ # extended permission must be granted in order to use this method.
111
+ #
112
+ # See: http://wiki.developers.facebook.com/index.php/Stream.publish
113
+ #
114
+ # +target+ can be the current user or some other user.
115
+ #
116
+ # Example:
117
+ # # Publish a message to my own wall:
118
+ # me.publish_to(me, :message => 'hello world')
119
+ #
120
+ # # Publish to a friend's wall with an action link:
121
+ # me.publish_to(my_friend, :message => 'how are you?', :action_links => [
122
+ # :text => 'my website',
123
+ # :href => 'http://tenderlovemaking.com/'
124
+ # ])
125
+ def publish_to target, options = {}
126
+ @session.post('facebook.stream.publish',
127
+ :uid => self.id,
128
+ :target_id => target.id,
129
+ :message => options[:message],
130
+ :attachment => Facebooker.json_encode(options[:attachment]),
131
+ :action_links => Facebooker.json_encode(options[:action_links])
132
+ )
133
+ end
106
134
 
107
- def friend_lists
135
+
136
+ ###
137
+ # Publish a comment on a post
138
+ #
139
+ # See: http://wiki.developers.facebook.com/index.php/Stream.addComment
140
+ #
141
+ # +post_id+ the post_id for the post that is being commented on
142
+ # +comment+ the text of the comment
143
+ def comment_on(post_id, comment)
144
+ @session.post('facebook.stream.addComment', {:post_id=>post_id, :comment=>comment})
145
+ end
146
+
147
+
148
+ def friend_lists
108
149
  @friend_lists ||= @session.post('facebook.friends.getLists').map do |hash|
109
- friend_list = FriendList.from_hash(hash)
110
- friend_list.session = session
111
- friend_list
112
- end
150
+ friend_list = FriendList.from_hash(hash)
151
+ friend_list.session = session
152
+ friend_list
153
+ end
113
154
  end
114
155
  ###
115
156
  # Retrieve friends with user info populated
@@ -323,6 +364,12 @@ module Facebooker
323
364
  session.post('facebook.users.hasAppPermission',:ext_perm=>ext_perm) == "1"
324
365
  end
325
366
 
367
+ ##
368
+ # Convenience method to check multiple permissions at once
369
+ def has_permissions?(ext_perms)
370
+ ext_perms.all?{|p| has_permission?(p)}
371
+ end
372
+
326
373
  ##
327
374
  # Convenience method to send email to the current user
328
375
  def send_email(subject, text=nil, fbml=nil)
@@ -2,34 +2,50 @@ require 'rexml/document'
2
2
  require 'facebooker/session'
3
3
  module Facebooker
4
4
  class Parser
5
-
6
- module REXMLElementExtensions
7
- def text_value
8
- self.children.first.to_s.strip
5
+
6
+ module REXMLElementExtensions # :nodoc:
7
+ def content
8
+ self.text || ''
9
+ end
10
+
11
+ def [] key
12
+ attributes[key]
13
+ end
14
+
15
+ def text?
16
+ false
17
+ end
18
+ end
19
+
20
+ module REXMLTextExtensions # :nodoc:
21
+ def text?
22
+ true
9
23
  end
10
24
  end
11
-
25
+
12
26
  ::REXML::Element.__send__(:include, REXMLElementExtensions)
13
-
27
+ ::REXML::Text.__send__(:include, REXMLTextExtensions)
28
+
14
29
  def self.parse(method, data)
15
30
  Errors.process(data)
16
31
  parser = Parser::PARSERS[method]
17
- parser.process(
18
- data
19
- )
32
+ raise "Can't find a parser for '#{method}'" unless parser
33
+ parser.process(data)
20
34
  end
21
-
35
+
22
36
  def self.array_of(response_element, element_name)
23
37
  values_to_return = []
24
- response_element.elements.each(element_name) do |element|
38
+ response_element.children.each do |element|
39
+ next if element.text?
40
+ next unless element.name == element_name
25
41
  values_to_return << yield(element)
26
42
  end
27
43
  values_to_return
28
44
  end
29
-
45
+
30
46
  def self.array_of_text_values(response_element, element_name)
31
47
  array_of(response_element, element_name) do |element|
32
- element.text_value
48
+ element.content.strip
33
49
  end
34
50
  end
35
51
 
@@ -38,75 +54,85 @@ module Facebooker
38
54
  hashinate(element)
39
55
  end
40
56
  end
41
-
57
+
42
58
  def self.element(name, data)
43
59
  data = data.body rescue data # either data or an HTTP response
44
- doc = REXML::Document.new(data)
45
- doc.elements.each(name) do |element|
46
- return element
60
+ begin
61
+ xml = Nokogiri::XML(data.strip).at(name)
62
+ if node = xml.at(name)
63
+ return node
64
+ end
65
+ if xml.root.name == name
66
+ return xml.root
67
+ end
68
+ rescue # Can't parse with Nokogiri
69
+ doc = REXML::Document.new(data)
70
+ doc.elements.each(name) do |element|
71
+ return element
72
+ end
47
73
  end
48
74
  raise "Element #{name} not found in #{data}"
49
75
  end
50
-
76
+
51
77
  def self.hash_or_value_for(element)
52
- if element.children.size == 1 && element.children.first.kind_of?(REXML::Text)
53
- element.text_value
78
+ if element.children.size == 1 && element.children.first.text?
79
+ element.content.strip
54
80
  else
55
81
  hashinate(element)
56
82
  end
57
83
  end
58
-
84
+
59
85
  def self.hashinate(response_element)
60
- response_element.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |hash, child|
86
+ response_element.children.reject{|c| c.text? }.inject({}) do |hash, child|
61
87
  # If the node hasn't any child, and is not a list, we want empty strings, not empty hashes,
62
88
  # except if attributes['nil'] == true
63
- hash[child.name] =
64
- if (child.attributes['nil'] == 'true')
65
- nil
66
- elsif (child.children.size == 1 && child.children.first.kind_of?(REXML::Text)) || (child.children.size == 0 && child.attributes['list'] != 'true')
67
- anonymous_field_from(child, hash) || child.text_value
68
- elsif child.attributes['list'] == 'true'
69
- child.children.reject{|c| c.kind_of? REXML::Text}.map { |subchild| hash_or_value_for(subchild)}
89
+ hash[child.name] =
90
+ if (child['nil'] == 'true')
91
+ nil
92
+ elsif (child.children.size == 1 && child.children.first.text?) || (child.children.size == 0 && child['list'] != 'true')
93
+ anonymous_field_from(child, hash) || child.content.strip
94
+ elsif child['list'] == 'true'
95
+ child.children.reject{|c| c.text? }.map { |subchild| hash_or_value_for(subchild)}
70
96
  else
71
- child.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |subhash, subchild|
97
+ child.children.reject{|c| c.text? }.inject({}) do |subhash, subchild|
72
98
  subhash[subchild.name] = hash_or_value_for(subchild)
73
99
  subhash
74
100
  end
75
101
  end #if (child.attributes)
76
102
  hash
77
- end #do |hash, child|
103
+ end #do |hash, child|
78
104
  end
79
-
105
+
80
106
  def self.booleanize(response)
81
107
  response == "1" ? true : false
82
108
  end
83
-
109
+
84
110
  def self.anonymous_field_from(child, hash)
85
111
  if child.name == 'anon'
86
- (hash[child.name] || []) << child.text_value
112
+ (hash[child.name] || []) << child.content.strip
87
113
  end
88
114
  end
89
-
90
- end
91
-
115
+
116
+ end
117
+
92
118
  class RevokeAuthorization < Parser#:nodoc:
93
119
  def self.process(data)
94
120
  booleanize(data)
95
121
  end
96
122
  end
97
-
123
+
98
124
  class CreateToken < Parser#:nodoc:
99
125
  def self.process(data)
100
- element('auth_createToken_response', data).text_value
126
+ element('auth_createToken_response', data).content.strip
101
127
  end
102
128
  end
103
-
129
+
104
130
  class RegisterUsers < Parser
105
131
  def self.process(data)
106
132
  array_of_text_values(element("connect_registerUsers_response", data), "connect_registerUsers_response_elt")
107
133
  end
108
134
  end
109
-
135
+
110
136
  class UnregisterUsers < Parser
111
137
  def self.process(data)
112
138
  array_of_text_values(element("connect_unregisterUsers_response", data), "connect_unregisterUsers_response_elt")
@@ -115,49 +141,49 @@ module Facebooker
115
141
 
116
142
  class GetUnconnectedFriendsCount < Parser
117
143
  def self.process(data)
118
- hash_or_value_for(element("connect_getUnconnectedFriendsCount_response",data)).to_i
144
+ hash_or_value_for(element("connect_getUnconnectedFriendsCount_response",data)).to_i
119
145
  end
120
146
  end
121
147
 
122
148
  class GetSession < Parser#:nodoc:
123
- def self.process(data)
149
+ def self.process(data)
124
150
  hashinate(element('auth_getSession_response', data))
125
151
  end
126
152
  end
127
-
153
+
128
154
  class GetFriends < Parser#:nodoc:
129
155
  def self.process(data)
130
156
  array_of_text_values(element('friends_get_response', data), 'uid')
131
157
  end
132
158
  end
133
-
159
+
134
160
  class FriendListsGet < Parser#:nodoc:
135
161
  def self.process(data)
136
162
  array_of_hashes(element('friends_getLists_response', data), 'friendlist')
137
163
  end
138
164
  end
139
-
165
+
140
166
  class UserInfo < Parser#:nodoc:
141
167
  def self.process(data)
142
168
  array_of_hashes(element('users_getInfo_response', data), 'user')
143
169
  end
144
170
  end
145
-
171
+
146
172
  class UserStandardInfo < Parser#:nodoc:
147
173
  def self.process(data)
148
174
  array_of_hashes(element('users_getStandardInfo_response', data), 'standard_user_info')
149
175
  end
150
176
  end
151
-
177
+
152
178
  class GetLoggedInUser < Parser#:nodoc:
153
179
  def self.process(data)
154
- Integer(element('users_getLoggedInUser_response', data).text_value)
180
+ Integer(element('users_getLoggedInUser_response', data).content.strip)
155
181
  end
156
182
  end
157
183
 
158
184
  class PagesIsAdmin < Parser#:nodoc:
159
185
  def self.process(data)
160
- element('pages_isAdmin_response', data).text_value == '1'
186
+ element('pages_isAdmin_response', data).content.strip == '1'
161
187
  end
162
188
  end
163
189
 
@@ -166,22 +192,34 @@ module Facebooker
166
192
  array_of_hashes(element('pages_getInfo_response', data), 'page')
167
193
  end
168
194
  end
169
-
195
+
170
196
  class PagesIsFan < Parser#:nodoc:
171
197
  def self.process(data)
172
- element('pages_isFan_response', data).text_value == '1'
198
+ element('pages_isFan_response', data).content.strip == '1'
173
199
  end
174
- end
200
+ end
175
201
 
176
202
  class PublishStoryToUser < Parser#:nodoc:
177
203
  def self.process(data)
178
- element('feed_publishStoryToUser_response', data).text_value
204
+ element('feed_publishStoryToUser_response', data).content.strip
179
205
  end
180
206
  end
181
207
 
208
+ class StreamPublish < Parser#:nodoc:
209
+ def self.process(data)
210
+ element('stream_publish_response', data).content.strip
211
+ end
212
+ end
213
+
214
+ class StreamAddComment < Parser#:nodoc:
215
+ def self.process(data)
216
+ element('stream_addComment_response', data).content.strip
217
+ end
218
+ end
219
+
182
220
  class RegisterTemplateBundle < Parser#:nodoc:
183
221
  def self.process(data)
184
- element('feed_registerTemplateBundle_response', data).text_value.to_i
222
+ element('feed_registerTemplateBundle_response', data).content.to_i
185
223
  end
186
224
  end
187
225
 
@@ -193,58 +231,58 @@ module Facebooker
193
231
 
194
232
  class DeactivateTemplateBundleByID < Parser#:nodoc:
195
233
  def self.process(data)
196
- element('feed_deactivateTemplateBundleByID_response', data).text_value == '1'
234
+ element('feed_deactivateTemplateBundleByID_response', data).content.strip == '1'
197
235
  end
198
236
  end
199
237
 
200
238
  class PublishUserAction < Parser#:nodoc:
201
239
  def self.process(data)
202
- element('feed_publishUserAction_response', data).children[1].text_value == "1"
240
+ element('feed_publishUserAction_response', data).children[1].content.strip == "1"
203
241
  end
204
242
  end
205
-
243
+
206
244
  class PublishActionOfUser < Parser#:nodoc:
207
245
  def self.process(data)
208
- element('feed_publishActionOfUser_response', data).text_value
246
+ element('feed_publishActionOfUser_response', data).content.strip
209
247
  end
210
248
  end
211
-
249
+
212
250
  class PublishTemplatizedAction < Parser#:nodoc:
213
251
  def self.process(data)
214
- element('feed_publishTemplatizedAction_response', data).children[1].text_value
252
+ element('feed_publishTemplatizedAction_response', data).children[1].content.strip
215
253
  end
216
254
  end
217
-
255
+
218
256
  class SetAppProperties < Parser#:nodoc:
219
257
  def self.process(data)
220
- element('admin_setAppProperties_response', data).text_value
258
+ element('admin_setAppProperties_response', data).content.strip
221
259
  end
222
- end
223
-
260
+ end
261
+
224
262
  class GetAppProperties < Parser#:nodoc:
225
263
  def self.process(data)
226
- element('admin_getAppProperties_response', data).text_value
264
+ element('admin_getAppProperties_response', data).content.strip
227
265
  end
228
266
  end
229
-
267
+
230
268
  class SetRestrictionInfo < Parser#:nodoc:
231
269
  def self.process(data)
232
- element('admin_setRestrictionInfo_response', data).text_value
270
+ element('admin_setRestrictionInfo_response', data).content.strip
233
271
  end
234
- end
235
-
272
+ end
273
+
236
274
  class GetRestrictionInfo < Parser#:nodoc:
237
275
  def self.process(data)
238
- element('admin_getRestrictionInfo_response', data).text_value
276
+ element('admin_getRestrictionInfo_response', data).content.strip
239
277
  end
240
278
  end
241
-
279
+
242
280
  class GetAllocation < Parser#:nodoc:
243
281
  def self.process(data)
244
- element('admin_getAllocation_response', data).text_value
282
+ element('admin_getAllocation_response', data).content.strip
245
283
  end
246
284
  end
247
-
285
+
248
286
  class BatchRun < Parser #:nodoc:
249
287
  class << self
250
288
  def current_batch=(current_batch)
@@ -267,28 +305,28 @@ module Facebooker
267
305
  end
268
306
  end
269
307
  end
270
-
308
+
271
309
  class GetAppUsers < Parser#:nodoc:
272
310
  def self.process(data)
273
311
  array_of_text_values(element('friends_getAppUsers_response', data), 'uid')
274
312
  end
275
313
  end
276
-
314
+
277
315
  class NotificationsGet < Parser#:nodoc:
278
316
  def self.process(data)
279
317
  hashinate(element('notifications_get_response', data))
280
318
  end
281
319
  end
282
-
320
+
283
321
  class NotificationsSend < Parser#:nodoc:
284
322
  def self.process(data)
285
- element('notifications_send_response', data).text_value
323
+ element('notifications_send_response', data).content.strip
286
324
  end
287
- end
325
+ end
288
326
 
289
327
  class NotificationsSendEmail < Parser#:nodoc:
290
- def self.process(data)
291
- element('notifications_sendEmail_response', data).text_value
328
+ def self.process(data)
329
+ element('notifications_sendEmail_response', data).content.strip
292
330
  end
293
331
  end
294
332
 
@@ -297,7 +335,7 @@ module Facebooker
297
335
  array_of_hashes(element('photos_getTags_response', data), 'photo_tag')
298
336
  end
299
337
  end
300
-
338
+
301
339
  class AddTags < Parser#nodoc:
302
340
  def self.process(data)
303
341
  element('photos_addTag_response', data)
@@ -309,19 +347,19 @@ module Facebooker
309
347
  array_of_hashes(element('photos_get_response', data), 'photo')
310
348
  end
311
349
  end
312
-
350
+
313
351
  class GetAlbums < Parser#nodoc:
314
352
  def self.process(data)
315
353
  array_of_hashes(element('photos_getAlbums_response', data), 'album')
316
354
  end
317
355
  end
318
-
356
+
319
357
  class CreateAlbum < Parser#:nodoc:
320
358
  def self.process(data)
321
359
  hashinate(element('photos_createAlbum_response', data))
322
360
  end
323
- end
324
-
361
+ end
362
+
325
363
  class UploadPhoto < Parser#:nodoc:
326
364
  def self.process(data)
327
365
  hashinate(element('photos_upload_response', data))
@@ -333,81 +371,100 @@ module Facebooker
333
371
  hashinate(element('video_upload_response', data))
334
372
  end
335
373
  end
336
-
374
+
337
375
  class SendRequest < Parser#:nodoc:
338
376
  def self.process(data)
339
- element('notifications_sendRequest_response', data).text_value
377
+ element('notifications_sendRequest_response', data).content.strip
340
378
  end
341
379
  end
342
-
380
+
343
381
  class ProfileFBML < Parser#:nodoc:
344
382
  def self.process(data)
345
- element('profile_getFBML_response', data).text_value
383
+ element('profile_getFBML_response', data).content.strip
346
384
  end
347
385
  end
348
-
386
+
349
387
  class ProfileFBMLSet < Parser#:nodoc:
350
388
  def self.process(data)
351
- element('profile_setFBML_response', data).text_value
389
+ element('profile_setFBML_response', data).content.strip
352
390
  end
353
391
  end
354
-
392
+
355
393
  class ProfileInfo < Parser#:nodoc:
356
394
  def self.process(data)
357
395
  hashinate(element('profile_getInfo_response info_fields', data))
358
396
  end
359
397
  end
360
-
398
+
361
399
  class ProfileInfoSet < Parser#:nodoc:
362
400
  def self.process(data)
363
- element('profile_setInfo_response', data).text_value
401
+ element('profile_setInfo_response', data).content.strip
364
402
  end
365
403
  end
366
-
404
+
367
405
  class FqlQuery < Parser#nodoc
368
406
  def self.process(data)
369
407
  root = element('fql_query_response', data)
370
- first_child = root.children.reject{|c| c.kind_of?(REXML::Text)}.first
408
+ first_child = root.children.reject{|c| c.text? }.first
371
409
  first_child.nil? ? [] : [first_child.name, array_of_hashes(root, first_child.name)]
372
410
  end
373
411
  end
374
-
412
+
413
+ class FqlMultiquery < Parser#nodoc
414
+ def self.process(data)
415
+ root = element('fql_multiquery_response', data)
416
+ root.elements.collect do |elm|
417
+ [
418
+ elm.elements[1].text,
419
+ if elm.elements[2].elements[1].nil?
420
+ []
421
+ else
422
+ [
423
+ elm.elements[2].elements[1].name,
424
+ array_of_hashes(elm.elements[2], elm.elements[2].elements[1].name)
425
+ ]
426
+ end
427
+ ]
428
+ end
429
+ end
430
+ end
431
+
375
432
  class SetRefHandle < Parser#:nodoc:
376
433
  def self.process(data)
377
- element('fbml_setRefHandle_response', data).text_value
434
+ element('fbml_setRefHandle_response', data).content.strip
378
435
  end
379
436
  end
380
-
437
+
381
438
  class RefreshRefURL < Parser#:nodoc:
382
439
  def self.process(data)
383
- element('fbml_refreshRefUrl_response', data).text_value
440
+ element('fbml_refreshRefUrl_response', data).content.strip
384
441
  end
385
442
  end
386
-
443
+
387
444
  class RefreshImgSrc < Parser#:nodoc:
388
445
  def self.process(data)
389
- element('fbml_refreshImgSrc_response', data).text_value
446
+ element('fbml_refreshImgSrc_response', data).content.strip
390
447
  end
391
448
  end
392
-
449
+
393
450
  class SetCookie < Parser#:nodoc:
394
451
  def self.process(data)
395
- element('data_setCookie_response', data).text_value
452
+ element('data_setCookie_response', data).content.strip
396
453
  end
397
454
  end
398
-
455
+
399
456
  class GetCookies < Parser#:nodoc:
400
457
  def self.process(data)
401
458
  array_of_hashes(element('data_getCookie_response', data), 'cookies')
402
459
  end
403
460
  end
404
-
461
+
405
462
  class EventsGet < Parser#:nodoc:
406
463
  def self.process(data)
407
464
  array_of_hashes(element('events_get_response', data), 'event')
408
465
  end
409
466
  end
410
-
467
+
411
468
  class GroupGetMembers < Parser#:nodoc:
412
469
  def self.process(data)
413
470
  root = element('groups_getMembers_response', data)
@@ -417,10 +474,10 @@ module Facebooker
417
474
  {:position => position}.merge(:uid => uid)
418
475
  end
419
476
  end
420
- end.flatten
477
+ end.flatten
421
478
  end
422
479
  end
423
-
480
+
424
481
  class EventMembersGet < Parser#:nodoc:
425
482
  def self.process(data)
426
483
  root = element('events_getMembers_response', data)
@@ -433,13 +490,13 @@ module Facebooker
433
490
  end.flatten
434
491
  end
435
492
  end
436
-
493
+
437
494
  class GroupsGet < Parser#:nodoc:
438
495
  def self.process(data)
439
496
  array_of_hashes(element('groups_get_response', data), 'group')
440
497
  end
441
498
  end
442
-
499
+
443
500
  class AreFriends < Parser#:nodoc:
444
501
  def self.process(data)
445
502
  array_of_hashes(element('friends_areFriends_response', data), 'friend_info').inject({}) do |memo, hash|
@@ -459,40 +516,40 @@ module Facebooker
459
516
  end
460
517
  end
461
518
  end
462
-
519
+
463
520
  class SetStatus < Parser
464
521
  def self.process(data)
465
- element('users_setStatus_response',data).text_value == '1'
522
+ element('users_setStatus_response',data).content.strip == '1'
466
523
  end
467
524
  end
468
-
525
+
469
526
  class GetPreference < Parser#:nodoc:
470
527
  def self.process(data)
471
- element('data_getUserPreference_response', data).text_value
528
+ element('data_getUserPreference_response', data).content.strip
472
529
  end
473
530
  end
474
-
531
+
475
532
  class SetPreference < Parser#:nodoc:
476
533
  def self.process(data)
477
- element('data_setUserPreference_response', data).text_value
534
+ element('data_setUserPreference_response', data).content.strip
478
535
  end
479
536
  end
480
-
537
+
481
538
  class UserHasPermission < Parser
482
539
  def self.process(data)
483
- element('users_hasAppPermission_response', data).text_value
540
+ element('users_hasAppPermission_response', data).content.strip
484
541
  end
485
- end
542
+ end
486
543
 
487
544
  class SmsSend < Parser#:nodoc:
488
545
  def self.process(data)
489
- element('sms_send_response', data).text_value == '0'
546
+ element('sms_send_response', data).content.strip == '0'
490
547
  end
491
548
  end
492
-
549
+
493
550
  class SmsCanSend < Parser#:nodoc:
494
551
  def self.process(data)
495
- element('sms_canSend_response', data).text_value
552
+ element('sms_canSend_response', data).content.strip
496
553
  end
497
554
  end
498
555
 
@@ -521,7 +578,7 @@ module Facebooker
521
578
  345 => Facebooker::Session::BlankFeedTitle,
522
579
  346 => Facebooker::Session::FeedBodyLengthTooLong,
523
580
  347 => Facebooker::Session::InvalidFeedPhotoSource,
524
- 348 => Facebooker::Session::InvalidFeedPhotoLink,
581
+ 348 => Facebooker::Session::InvalidFeedPhotoLink,
525
582
  330 => Facebooker::Session::FeedMarkupInvalid,
526
583
  360 => Facebooker::Session::FeedTitleDataInvalid,
527
584
  361 => Facebooker::Session::FeedTitleTemplateInvalid,
@@ -546,7 +603,7 @@ module Facebooker
546
603
  end
547
604
  end
548
605
  end
549
-
606
+
550
607
  class Parser
551
608
  PARSERS = {
552
609
  'facebook.auth.revokeAuthorization' => RevokeAuthorization,
@@ -562,7 +619,7 @@ module Facebooker
562
619
  'facebook.users.hasAppPermission' => UserHasPermission,
563
620
  'facebook.pages.isAdmin' => PagesIsAdmin,
564
621
  'facebook.pages.getInfo' => PagesGetInfo,
565
- 'facebook.pages.isFan' => PagesIsFan,
622
+ 'facebook.pages.isFan' => PagesIsFan,
566
623
  'facebook.friends.get' => GetFriends,
567
624
  'facebook.friends.getLists' => FriendListsGet,
568
625
  'facebook.friends.areFriends' => AreFriends,
@@ -593,12 +650,15 @@ module Facebooker
593
650
  'facebook.admin.getAllocation' => GetAllocation,
594
651
  'facebook.batch.run' => BatchRun,
595
652
  'facebook.fql.query' => FqlQuery,
653
+ 'facebook.fql.multiquery' => FqlMultiquery,
596
654
  'facebook.photos.get' => GetPhotos,
597
655
  'facebook.photos.getAlbums' => GetAlbums,
598
656
  'facebook.photos.createAlbum' => CreateAlbum,
599
657
  'facebook.photos.getTags' => GetTags,
600
658
  'facebook.photos.addTag' => AddTags,
601
659
  'facebook.photos.upload' => UploadPhoto,
660
+ 'facebook.stream.publish' => StreamPublish,
661
+ 'facebook.stream.addComment' => StreamAddComment,
602
662
  'facebook.events.get' => EventsGet,
603
663
  'facebook.groups.get' => GroupsGet,
604
664
  'facebook.events.getMembers' => EventMembersGet,