simianarmy-facebooker 1.0.40

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 (135) hide show
  1. data/.autotest +15 -0
  2. data/CHANGELOG.rdoc +24 -0
  3. data/COPYING.rdoc +19 -0
  4. data/Manifest.txt +133 -0
  5. data/README.rdoc +113 -0
  6. data/Rakefile +85 -0
  7. data/TODO.rdoc +4 -0
  8. data/examples/desktop_login.rb +14 -0
  9. data/facebooker.gemspec +38 -0
  10. data/generators/facebook/facebook_generator.rb +14 -0
  11. data/generators/facebook/templates/config/facebooker.yml +49 -0
  12. data/generators/facebook/templates/public/javascripts/facebooker.js +93 -0
  13. data/generators/facebook_controller/USAGE +33 -0
  14. data/generators/facebook_controller/facebook_controller_generator.rb +40 -0
  15. data/generators/facebook_controller/templates/controller.rb +7 -0
  16. data/generators/facebook_controller/templates/functional_test.rb +11 -0
  17. data/generators/facebook_controller/templates/helper.rb +2 -0
  18. data/generators/facebook_controller/templates/view.fbml.erb +2 -0
  19. data/generators/facebook_controller/templates/view.html.erb +2 -0
  20. data/generators/facebook_publisher/facebook_publisher_generator.rb +14 -0
  21. data/generators/facebook_publisher/templates/create_facebook_templates.rb +15 -0
  22. data/generators/facebook_publisher/templates/publisher.rb +3 -0
  23. data/generators/facebook_scaffold/USAGE +27 -0
  24. data/generators/facebook_scaffold/facebook_scaffold_generator.rb +118 -0
  25. data/generators/facebook_scaffold/templates/controller.rb +93 -0
  26. data/generators/facebook_scaffold/templates/facebook_style.css +2579 -0
  27. data/generators/facebook_scaffold/templates/functional_test.rb +89 -0
  28. data/generators/facebook_scaffold/templates/helper.rb +2 -0
  29. data/generators/facebook_scaffold/templates/layout.fbml.erb +6 -0
  30. data/generators/facebook_scaffold/templates/layout.html.erb +17 -0
  31. data/generators/facebook_scaffold/templates/style.css +74 -0
  32. data/generators/facebook_scaffold/templates/view_edit.fbml.erb +13 -0
  33. data/generators/facebook_scaffold/templates/view_edit.html.erb +18 -0
  34. data/generators/facebook_scaffold/templates/view_index.fbml.erb +24 -0
  35. data/generators/facebook_scaffold/templates/view_index.html.erb +24 -0
  36. data/generators/facebook_scaffold/templates/view_new.fbml.erb +12 -0
  37. data/generators/facebook_scaffold/templates/view_new.html.erb +17 -0
  38. data/generators/facebook_scaffold/templates/view_show.fbml.erb +10 -0
  39. data/generators/facebook_scaffold/templates/view_show.html.erb +10 -0
  40. data/generators/publisher/publisher_generator.rb +14 -0
  41. data/generators/xd_receiver/templates/xd_receiver.html +10 -0
  42. data/generators/xd_receiver/xd_receiver_generator.rb +10 -0
  43. data/init.rb +26 -0
  44. data/install.rb +12 -0
  45. data/lib/facebooker/adapters/adapter_base.rb +91 -0
  46. data/lib/facebooker/adapters/bebo_adapter.rb +77 -0
  47. data/lib/facebooker/adapters/facebook_adapter.rb +52 -0
  48. data/lib/facebooker/admin.rb +42 -0
  49. data/lib/facebooker/batch_request.rb +45 -0
  50. data/lib/facebooker/data.rb +57 -0
  51. data/lib/facebooker/feed.rb +78 -0
  52. data/lib/facebooker/logging.rb +44 -0
  53. data/lib/facebooker/mobile.rb +20 -0
  54. data/lib/facebooker/mock/service.rb +50 -0
  55. data/lib/facebooker/mock/session.rb +18 -0
  56. data/lib/facebooker/model.rb +139 -0
  57. data/lib/facebooker/models/affiliation.rb +10 -0
  58. data/lib/facebooker/models/album.rb +11 -0
  59. data/lib/facebooker/models/applicationproperties.rb +39 -0
  60. data/lib/facebooker/models/applicationrestrictions.rb +10 -0
  61. data/lib/facebooker/models/cookie.rb +10 -0
  62. data/lib/facebooker/models/education_info.rb +11 -0
  63. data/lib/facebooker/models/event.rb +28 -0
  64. data/lib/facebooker/models/friend_list.rb +16 -0
  65. data/lib/facebooker/models/group.rb +36 -0
  66. data/lib/facebooker/models/info_item.rb +10 -0
  67. data/lib/facebooker/models/info_section.rb +10 -0
  68. data/lib/facebooker/models/location.rb +8 -0
  69. data/lib/facebooker/models/notifications.rb +17 -0
  70. data/lib/facebooker/models/page.rb +28 -0
  71. data/lib/facebooker/models/photo.rb +19 -0
  72. data/lib/facebooker/models/tag.rb +12 -0
  73. data/lib/facebooker/models/user.rb +469 -0
  74. data/lib/facebooker/models/video.rb +9 -0
  75. data/lib/facebooker/models/work_info.rb +10 -0
  76. data/lib/facebooker/parser.rb +650 -0
  77. data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
  78. data/lib/facebooker/rails/controller.rb +356 -0
  79. data/lib/facebooker/rails/cucumber/world.rb +46 -0
  80. data/lib/facebooker/rails/cucumber.rb +28 -0
  81. data/lib/facebooker/rails/extensions/action_controller.rb +48 -0
  82. data/lib/facebooker/rails/extensions/rack_setup.rb +6 -0
  83. data/lib/facebooker/rails/extensions/routing.rb +15 -0
  84. data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
  85. data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
  86. data/lib/facebooker/rails/facebook_request_fix.rb +28 -0
  87. data/lib/facebooker/rails/facebook_request_fix_2-3.rb +31 -0
  88. data/lib/facebooker/rails/facebook_session_handling.rb +68 -0
  89. data/lib/facebooker/rails/facebook_url_helper.rb +192 -0
  90. data/lib/facebooker/rails/facebook_url_rewriting.rb +60 -0
  91. data/lib/facebooker/rails/helpers/fb_connect.rb +118 -0
  92. data/lib/facebooker/rails/helpers.rb +804 -0
  93. data/lib/facebooker/rails/integration_session.rb +38 -0
  94. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  95. data/lib/facebooker/rails/publisher.rb +550 -0
  96. data/lib/facebooker/rails/routing.rb +49 -0
  97. data/lib/facebooker/rails/test_helpers.rb +68 -0
  98. data/lib/facebooker/rails/utilities.rb +22 -0
  99. data/lib/facebooker/server_cache.rb +24 -0
  100. data/lib/facebooker/service.rb +102 -0
  101. data/lib/facebooker/session.rb +635 -0
  102. data/lib/facebooker/version.rb +9 -0
  103. data/lib/facebooker.rb +179 -0
  104. data/lib/net/http_multipart_post.rb +123 -0
  105. data/lib/rack/facebook.rb +82 -0
  106. data/lib/tasks/facebooker.rake +18 -0
  107. data/lib/tasks/tunnel.rake +46 -0
  108. data/rails/init.rb +1 -0
  109. data/setup.rb +1585 -0
  110. data/templates/layout.erb +24 -0
  111. data/test/facebooker/adapters_test.rb +174 -0
  112. data/test/facebooker/admin_test.rb +102 -0
  113. data/test/facebooker/batch_request_test.rb +83 -0
  114. data/test/facebooker/data_test.rb +86 -0
  115. data/test/facebooker/logging_test.rb +43 -0
  116. data/test/facebooker/mobile_test.rb +45 -0
  117. data/test/facebooker/model_test.rb +133 -0
  118. data/test/facebooker/models/event_test.rb +15 -0
  119. data/test/facebooker/models/photo_test.rb +16 -0
  120. data/test/facebooker/models/user_test.rb +361 -0
  121. data/test/facebooker/rails/facebook_request_fix_2-3_test.rb +25 -0
  122. data/test/facebooker/rails/facebook_url_rewriting_test.rb +39 -0
  123. data/test/facebooker/rails/publisher_test.rb +481 -0
  124. data/test/facebooker/rails_integration_test.rb +1434 -0
  125. data/test/facebooker/server_cache_test.rb +44 -0
  126. data/test/facebooker/session_test.rb +652 -0
  127. data/test/facebooker_test.rb +951 -0
  128. data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
  129. data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
  130. data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
  131. data/test/net/http_multipart_post_test.rb +52 -0
  132. data/test/rack/facebook_test.rb +61 -0
  133. data/test/rails_test_helper.rb +27 -0
  134. data/test/test_helper.rb +74 -0
  135. metadata +222 -0
@@ -0,0 +1,650 @@
1
+ require 'rexml/document'
2
+ require 'facebooker/session'
3
+ module Facebooker
4
+ class Parser
5
+
6
+ module REXMLElementExtensions
7
+ def text_value
8
+ self.children.first.to_s.strip
9
+ end
10
+ end
11
+
12
+ ::REXML::Element.__send__(:include, REXMLElementExtensions)
13
+
14
+ def self.parse(method, data)
15
+ Errors.process(data)
16
+ parser = Parser::PARSERS[method]
17
+ parser.process(
18
+ data
19
+ )
20
+ end
21
+
22
+ def self.array_of(response_element, element_name)
23
+ values_to_return = []
24
+ response_element.elements.each(element_name) do |element|
25
+ values_to_return << yield(element)
26
+ end
27
+ values_to_return
28
+ end
29
+
30
+ def self.array_of_text_values(response_element, element_name)
31
+ array_of(response_element, element_name) do |element|
32
+ element.text_value
33
+ end
34
+ end
35
+
36
+ def self.array_of_hashes(response_element, element_name)
37
+ array_of(response_element, element_name) do |element|
38
+ hashinate(element)
39
+ end
40
+ end
41
+
42
+ def self.element(name, data)
43
+ 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
47
+ end
48
+ raise "Element #{name} not found in #{data}"
49
+ end
50
+
51
+ def self.hash_or_value_for(element)
52
+ if element.children.size == 1 && element.children.first.kind_of?(REXML::Text)
53
+ element.text_value
54
+ else
55
+ hashinate(element)
56
+ end
57
+ end
58
+
59
+ def self.hashinate(response_element)
60
+ response_element.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |hash, child|
61
+ # puts "hash => "
62
+ # puts hash.inspect
63
+ # puts "child => "
64
+ # puts child.inspect
65
+ # If the node hasn't any child, and is not a list, we want empty strings, not empty hashes,
66
+ # except if attributes['nil'] == true
67
+ hash[child.name] =
68
+ if (child.attributes['nil'] == 'true')
69
+ nil
70
+ elsif (child.children.size == 1 && child.children.first.kind_of?(REXML::Text)) || (child.children.size == 0 && child.attributes['list'] != 'true')
71
+ anonymous_field_from(child, hash) || child.text_value
72
+ elsif child.attributes['list'] == 'true'
73
+ child.children.reject{|c| c.kind_of? REXML::Text}.map { |subchild| hash_or_value_for(subchild)}
74
+ else
75
+ child.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |subhash, subchild|
76
+ subhash[subchild.name] = hash_or_value_for(subchild)
77
+ subhash
78
+ end
79
+ end #if (child.attributes)
80
+ hash
81
+ end #do |hash, child|
82
+ end
83
+
84
+ def self.booleanize(response)
85
+ response == "1" ? true : false
86
+ end
87
+
88
+ def self.anonymous_field_from(child, hash)
89
+ if child.name == 'anon'
90
+ (hash[child.name] || []) << child.text_value
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ class RevokeAuthorization < Parser#:nodoc:
97
+ def self.process(data)
98
+ booleanize(data)
99
+ end
100
+ end
101
+
102
+ class CreateToken < Parser#:nodoc:
103
+ def self.process(data)
104
+ element('auth_createToken_response', data).text_value
105
+ end
106
+ end
107
+
108
+ class RegisterUsers < Parser
109
+ def self.process(data)
110
+ array_of_text_values(element("connect_registerUsers_response", data), "connect_registerUsers_response_elt")
111
+ end
112
+ end
113
+
114
+ class UnregisterUsers < Parser
115
+ def self.process(data)
116
+ array_of_text_values(element("connect_unregisterUsers_response", data), "connect_unregisterUsers_response_elt")
117
+ end
118
+ end
119
+
120
+ class GetUnconnectedFriendsCount < Parser
121
+ def self.process(data)
122
+ hash_or_value_for(element("connect_getUnconnectedFriendsCount_response",data)).to_i
123
+ end
124
+ end
125
+
126
+ class GetSession < Parser#:nodoc:
127
+ def self.process(data)
128
+ hashinate(element('auth_getSession_response', data))
129
+ end
130
+ end
131
+
132
+ class GetFriends < Parser#:nodoc:
133
+ def self.process(data)
134
+ array_of_text_values(element('friends_get_response', data), 'uid')
135
+ end
136
+ end
137
+
138
+ class FriendListsGet < Parser#:nodoc:
139
+ def self.process(data)
140
+ array_of_hashes(element('friends_getLists_response', data), 'friendlist')
141
+ end
142
+ end
143
+
144
+ class UserInfo < Parser#:nodoc:
145
+ def self.process(data)
146
+ array_of_hashes(element('users_getInfo_response', data), 'user')
147
+ end
148
+ end
149
+
150
+ class UserStandardInfo < Parser#:nodoc:
151
+ def self.process(data)
152
+ array_of_hashes(element('users_getStandardInfo_response', data), 'standard_user_info')
153
+ end
154
+ end
155
+
156
+ class GetLoggedInUser < Parser#:nodoc:
157
+ def self.process(data)
158
+ Integer(element('users_getLoggedInUser_response', data).text_value)
159
+ end
160
+ end
161
+
162
+ class PagesIsAdmin < Parser#:nodoc:
163
+ def self.process(data)
164
+ element('pages_isAdmin_response', data).text_value == '1'
165
+ end
166
+ end
167
+
168
+ class PagesGetInfo < Parser#:nodoc:
169
+ def self.process(data)
170
+ array_of_hashes(element('pages_getInfo_response', data), 'page')
171
+ end
172
+ end
173
+
174
+ class PagesIsFan < Parser#:nodoc:
175
+ def self.process(data)
176
+ element('pages_isFan_response', data).text_value == '1'
177
+ end
178
+ end
179
+
180
+ class PublishStoryToUser < Parser#:nodoc:
181
+ def self.process(data)
182
+ element('feed_publishStoryToUser_response', data).text_value
183
+ end
184
+ end
185
+
186
+ class RegisterTemplateBundle < Parser#:nodoc:
187
+ def self.process(data)
188
+ element('feed_registerTemplateBundle_response', data).text_value.to_i
189
+ end
190
+ end
191
+
192
+ class GetRegisteredTemplateBundles < Parser
193
+ def self.process(data)
194
+ array_of_hashes(element('feed_getRegisteredTemplateBundles_response',data), 'template_bundle')
195
+ end
196
+ end
197
+
198
+ class DeactivateTemplateBundleByID < Parser#:nodoc:
199
+ def self.process(data)
200
+ element('feed_deactivateTemplateBundleByID_response', data).text_value == '1'
201
+ end
202
+ end
203
+
204
+ class PublishUserAction < Parser#:nodoc:
205
+ def self.process(data)
206
+ element('feed_publishUserAction_response', data).children[1].text_value == "1"
207
+ end
208
+ end
209
+
210
+ class PublishActionOfUser < Parser#:nodoc:
211
+ def self.process(data)
212
+ element('feed_publishActionOfUser_response', data).text_value
213
+ end
214
+ end
215
+
216
+ class PublishTemplatizedAction < Parser#:nodoc:
217
+ def self.process(data)
218
+ element('feed_publishTemplatizedAction_response', data).children[1].text_value
219
+ end
220
+ end
221
+
222
+ class SetAppProperties < Parser#:nodoc:
223
+ def self.process(data)
224
+ element('admin_setAppProperties_response', data).text_value
225
+ end
226
+ end
227
+
228
+ class GetAppProperties < Parser#:nodoc:
229
+ def self.process(data)
230
+ element('admin_getAppProperties_response', data).text_value
231
+ end
232
+ end
233
+
234
+ class SetRestrictionInfo < Parser#:nodoc:
235
+ def self.process(data)
236
+ element('admin_setRestrictionInfo_response', data).text_value
237
+ end
238
+ end
239
+
240
+ class GetRestrictionInfo < Parser#:nodoc:
241
+ def self.process(data)
242
+ element('admin_getRestrictionInfo_response', data).text_value
243
+ end
244
+ end
245
+
246
+ class GetAllocation < Parser#:nodoc:
247
+ def self.process(data)
248
+ element('admin_getAllocation_response', data).text_value
249
+ end
250
+ end
251
+
252
+ class BatchRun < Parser #:nodoc:
253
+ class << self
254
+ def current_batch=(current_batch)
255
+ Thread.current[:facebooker_current_batch]=current_batch
256
+ end
257
+ def current_batch
258
+ Thread.current[:facebooker_current_batch]
259
+ end
260
+ end
261
+ def self.process(data)
262
+ array_of_text_values(element('batch_run_response',data),"batch_run_response_elt").each_with_index do |response,i|
263
+ batch_request=current_batch[i]
264
+ body=Struct.new(:body).new
265
+ body.body=CGI.unescapeHTML(response)
266
+ begin
267
+ batch_request.result=Parser.parse(batch_request.method,body)
268
+ rescue Exception=>ex
269
+ batch_request.exception_raised=ex
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ class GetAppUsers < Parser#:nodoc:
276
+ def self.process(data)
277
+ array_of_text_values(element('friends_getAppUsers_response', data), 'uid')
278
+ end
279
+ end
280
+
281
+ class NotificationsGet < Parser#:nodoc:
282
+ def self.process(data)
283
+ hashinate(element('notifications_get_response', data))
284
+ end
285
+ end
286
+
287
+ class NotificationsSend < Parser#:nodoc:
288
+ def self.process(data)
289
+ element('notifications_send_response', data).text_value
290
+ end
291
+ end
292
+
293
+ class NotificationsSendEmail < Parser#:nodoc:
294
+ def self.process(data)
295
+ element('notifications_sendEmail_response', data).text_value
296
+ end
297
+ end
298
+
299
+ class GetTags < Parser#nodoc:
300
+ def self.process(data)
301
+ array_of_hashes(element('photos_getTags_response', data), 'photo_tag')
302
+ end
303
+ end
304
+
305
+ class AddTags < Parser#nodoc:
306
+ def self.process(data)
307
+ element('photos_addTag_response', data)
308
+ end
309
+ end
310
+
311
+ class GetPhotos < Parser#nodoc:
312
+ def self.process(data)
313
+ array_of_hashes(element('photos_get_response', data), 'photo')
314
+ end
315
+ end
316
+
317
+ class GetAlbums < Parser#nodoc:
318
+ def self.process(data)
319
+ array_of_hashes(element('photos_getAlbums_response', data), 'album')
320
+ end
321
+ end
322
+
323
+ class CreateAlbum < Parser#:nodoc:
324
+ def self.process(data)
325
+ hashinate(element('photos_createAlbum_response', data))
326
+ end
327
+ end
328
+
329
+ class UploadPhoto < Parser#:nodoc:
330
+ def self.process(data)
331
+ hashinate(element('photos_upload_response', data))
332
+ end
333
+ end
334
+
335
+ class UploadVideo < Parser#:nodoc:
336
+ def self.process(data)
337
+ hashinate(element('video_upload_response', data))
338
+ end
339
+ end
340
+
341
+ class SendRequest < Parser#:nodoc:
342
+ def self.process(data)
343
+ element('notifications_sendRequest_response', data).text_value
344
+ end
345
+ end
346
+
347
+ class ProfileFBML < Parser#:nodoc:
348
+ def self.process(data)
349
+ element('profile_getFBML_response', data).text_value
350
+ end
351
+ end
352
+
353
+ class ProfileFBMLSet < Parser#:nodoc:
354
+ def self.process(data)
355
+ element('profile_setFBML_response', data).text_value
356
+ end
357
+ end
358
+
359
+ class ProfileInfo < Parser#:nodoc:
360
+ def self.process(data)
361
+ hashinate(element('profile_getInfo_response info_fields', data))
362
+ end
363
+ end
364
+
365
+ class ProfileInfoSet < Parser#:nodoc:
366
+ def self.process(data)
367
+ element('profile_setInfo_response', data).text_value
368
+ end
369
+ end
370
+
371
+ class FqlQuery < Parser#nodoc
372
+ def self.process(data)
373
+ root = element('fql_query_response', data)
374
+ first_child = root.children.reject{|c| c.kind_of?(REXML::Text)}.first
375
+ first_child.nil? ? [] : [first_child.name, array_of_hashes(root, first_child.name)]
376
+ end
377
+ end
378
+
379
+ class FqlMultiquery < Parser#nodoc
380
+ def self.process(data)
381
+ root = element('fql_multiquery_response', data)
382
+ root.elements.collect do |elm|
383
+ [
384
+ elm.elements[1].text,
385
+ if elm.elements[2].elements[1].nil?
386
+ []
387
+ else
388
+ [
389
+ elm.elements[2].elements[1].name,
390
+ array_of_hashes(elm.elements[2], elm.elements[2].elements[1].name)
391
+ ]
392
+ end
393
+ ]
394
+ end
395
+ end
396
+ end
397
+
398
+ class SetRefHandle < Parser#:nodoc:
399
+ def self.process(data)
400
+ element('fbml_setRefHandle_response', data).text_value
401
+ end
402
+ end
403
+
404
+ class RefreshRefURL < Parser#:nodoc:
405
+ def self.process(data)
406
+ element('fbml_refreshRefUrl_response', data).text_value
407
+ end
408
+ end
409
+
410
+ class RefreshImgSrc < Parser#:nodoc:
411
+ def self.process(data)
412
+ element('fbml_refreshImgSrc_response', data).text_value
413
+ end
414
+ end
415
+
416
+ class SetCookie < Parser#:nodoc:
417
+ def self.process(data)
418
+ element('data_setCookie_response', data).text_value
419
+ end
420
+ end
421
+
422
+ class GetCookies < Parser#:nodoc:
423
+ def self.process(data)
424
+ array_of_hashes(element('data_getCookie_response', data), 'cookies')
425
+ end
426
+ end
427
+
428
+ class EventsGet < Parser#:nodoc:
429
+ def self.process(data)
430
+ array_of_hashes(element('events_get_response', data), 'event')
431
+ end
432
+ end
433
+
434
+ class GroupGetMembers < Parser#:nodoc:
435
+ def self.process(data)
436
+ root = element('groups_getMembers_response', data)
437
+ result = ['members', 'admins', 'officers', 'not_replied'].map do |position|
438
+ array_of(root, position) {|element| element}.map do |element|
439
+ array_of_text_values(element, 'uid').map do |uid|
440
+ {:position => position}.merge(:uid => uid)
441
+ end
442
+ end
443
+ end.flatten
444
+ end
445
+ end
446
+
447
+ class EventMembersGet < Parser#:nodoc:
448
+ def self.process(data)
449
+ root = element('events_getMembers_response', data)
450
+ result = ['attending', 'declined', 'unsure', 'not_replied'].map do |rsvp_status|
451
+ array_of(root, rsvp_status) {|element| element}.map do |element|
452
+ array_of_text_values(element, 'uid').map do |uid|
453
+ {:rsvp_status => rsvp_status}.merge(:uid => uid)
454
+ end
455
+ end
456
+ end.flatten
457
+ end
458
+ end
459
+
460
+ class GroupsGet < Parser#:nodoc:
461
+ def self.process(data)
462
+ array_of_hashes(element('groups_get_response', data), 'group')
463
+ end
464
+ end
465
+
466
+ class AreFriends < Parser#:nodoc:
467
+ def self.process(data)
468
+ array_of_hashes(element('friends_areFriends_response', data), 'friend_info').inject({}) do |memo, hash|
469
+ memo[[Integer(hash['uid1']), Integer(hash['uid2'])].sort] = are_friends?(hash['are_friends'])
470
+ memo
471
+ end
472
+ end
473
+
474
+ private
475
+ def self.are_friends?(raw_value)
476
+ if raw_value == '1'
477
+ true
478
+ elsif raw_value == '0'
479
+ false
480
+ else
481
+ nil
482
+ end
483
+ end
484
+ end
485
+
486
+ class SetStatus < Parser
487
+ def self.process(data)
488
+ element('users_setStatus_response',data).text_value == '1'
489
+ end
490
+ end
491
+
492
+ class GetPreference < Parser#:nodoc:
493
+ def self.process(data)
494
+ element('data_getUserPreference_response', data).text_value
495
+ end
496
+ end
497
+
498
+ class SetPreference < Parser#:nodoc:
499
+ def self.process(data)
500
+ element('data_setUserPreference_response', data).text_value
501
+ end
502
+ end
503
+
504
+ class UserHasPermission < Parser
505
+ def self.process(data)
506
+ element('users_hasAppPermission_response', data).text_value
507
+ end
508
+ end
509
+
510
+ class SmsSend < Parser#:nodoc:
511
+ def self.process(data)
512
+ element('sms_send_response', data).text_value == '0'
513
+ end
514
+ end
515
+
516
+ class SmsCanSend < Parser#:nodoc:
517
+ def self.process(data)
518
+ element('sms_canSend_response', data).text_value
519
+ end
520
+ end
521
+
522
+ class StreamGet < Parser
523
+ def self.process(data)
524
+ res = hashinate(element('stream_get_response', data))
525
+ res.each do |key, val|
526
+ puts "#{key} => #{val.inspect}"
527
+ 5.times { puts }
528
+ end
529
+ end
530
+ end
531
+
532
+ class Errors < Parser#:nodoc:
533
+ EXCEPTIONS = {
534
+ 1 => Facebooker::Session::UnknownError,
535
+ 2 => Facebooker::Session::ServiceUnavailable,
536
+ 4 => Facebooker::Session::MaxRequestsDepleted,
537
+ 5 => Facebooker::Session::HostNotAllowed,
538
+ 100 => Facebooker::Session::MissingOrInvalidParameter,
539
+ 101 => Facebooker::Session::InvalidAPIKey,
540
+ 102 => Facebooker::Session::SessionExpired,
541
+ 103 => Facebooker::Session::CallOutOfOrder,
542
+ 104 => Facebooker::Session::IncorrectSignature,
543
+ 120 => Facebooker::Session::InvalidAlbumId,
544
+ 250 => Facebooker::Session::ExtendedPermissionRequired,
545
+ 321 => Facebooker::Session::AlbumIsFull,
546
+ 324 => Facebooker::Session::MissingOrInvalidImageFile,
547
+ 325 => Facebooker::Session::TooManyUnapprovedPhotosPending,
548
+ 330 => Facebooker::Session::TemplateDataMissingRequiredTokens,
549
+ 340 => Facebooker::Session::TooManyUserCalls,
550
+ 341 => Facebooker::Session::TooManyUserActionCalls,
551
+ 342 => Facebooker::Session::InvalidFeedTitleLink,
552
+ 343 => Facebooker::Session::InvalidFeedTitleLength,
553
+ 344 => Facebooker::Session::InvalidFeedTitleName,
554
+ 345 => Facebooker::Session::BlankFeedTitle,
555
+ 346 => Facebooker::Session::FeedBodyLengthTooLong,
556
+ 347 => Facebooker::Session::InvalidFeedPhotoSource,
557
+ 348 => Facebooker::Session::InvalidFeedPhotoLink,
558
+ 330 => Facebooker::Session::FeedMarkupInvalid,
559
+ 360 => Facebooker::Session::FeedTitleDataInvalid,
560
+ 361 => Facebooker::Session::FeedTitleTemplateInvalid,
561
+ 362 => Facebooker::Session::FeedBodyDataInvalid,
562
+ 363 => Facebooker::Session::FeedBodyTemplateInvalid,
563
+ 364 => Facebooker::Session::FeedPhotosNotRetrieved,
564
+ 366 => Facebooker::Session::FeedTargetIdsInvalid,
565
+ 601 => Facebooker::Session::FQLParseError,
566
+ 602 => Facebooker::Session::FQLFieldDoesNotExist,
567
+ 603 => Facebooker::Session::FQLTableDoesNotExist,
568
+ 604 => Facebooker::Session::FQLStatementNotIndexable,
569
+ 605 => Facebooker::Session::FQLFunctionDoesNotExist,
570
+ 606 => Facebooker::Session::FQLWrongNumberArgumentsPassedToFunction,
571
+ 807 => Facebooker::Session::TemplateBundleInvalid
572
+ }
573
+ def self.process(data)
574
+ response_element = element('error_response', data) rescue nil
575
+ if response_element
576
+ hash = hashinate(response_element)
577
+ exception = EXCEPTIONS[Integer(hash['error_code'])] || StandardError
578
+ raise exception, hash['error_msg']
579
+ end
580
+ end
581
+ end
582
+
583
+ class Parser
584
+ PARSERS = {
585
+ 'facebook.auth.revokeAuthorization' => RevokeAuthorization,
586
+ 'facebook.auth.createToken' => CreateToken,
587
+ 'facebook.auth.getSession' => GetSession,
588
+ 'facebook.connect.registerUsers' => RegisterUsers,
589
+ 'facebook.connect.unregisterUsers' => UnregisterUsers,
590
+ 'facebook.connect.getUnconnectedFriendsCount' => GetUnconnectedFriendsCount,
591
+ 'facebook.users.getInfo' => UserInfo,
592
+ 'facebook.users.getStandardInfo' => UserStandardInfo,
593
+ 'facebook.users.setStatus' => SetStatus,
594
+ 'facebook.users.getLoggedInUser' => GetLoggedInUser,
595
+ 'facebook.users.hasAppPermission' => UserHasPermission,
596
+ 'facebook.pages.isAdmin' => PagesIsAdmin,
597
+ 'facebook.pages.getInfo' => PagesGetInfo,
598
+ 'facebook.pages.isFan' => PagesIsFan,
599
+ 'facebook.friends.get' => GetFriends,
600
+ 'facebook.friends.getLists' => FriendListsGet,
601
+ 'facebook.friends.areFriends' => AreFriends,
602
+ 'facebook.friends.getAppUsers' => GetAppUsers,
603
+ 'facebook.feed.publishStoryToUser' => PublishStoryToUser,
604
+ 'facebook.feed.publishActionOfUser' => PublishActionOfUser,
605
+ 'facebook.feed.publishTemplatizedAction' => PublishTemplatizedAction,
606
+ 'facebook.feed.registerTemplateBundle' => RegisterTemplateBundle,
607
+ 'facebook.feed.deactivateTemplateBundleByID' => DeactivateTemplateBundleByID,
608
+ 'facebook.feed.getRegisteredTemplateBundles' => GetRegisteredTemplateBundles,
609
+ 'facebook.feed.publishUserAction' => PublishUserAction,
610
+ 'facebook.notifications.get' => NotificationsGet,
611
+ 'facebook.notifications.send' => NotificationsSend,
612
+ 'facebook.notifications.sendRequest' => SendRequest,
613
+ 'facebook.profile.getFBML' => ProfileFBML,
614
+ 'facebook.profile.setFBML' => ProfileFBMLSet,
615
+ 'facebook.profile.getInfo' => ProfileInfo,
616
+ 'facebook.profile.setInfo' => ProfileInfoSet,
617
+ 'facebook.fbml.setRefHandle' => SetRefHandle,
618
+ 'facebook.fbml.refreshRefUrl' => RefreshRefURL,
619
+ 'facebook.fbml.refreshImgSrc' => RefreshImgSrc,
620
+ 'facebook.data.setCookie' => SetCookie,
621
+ 'facebook.data.getCookies' => GetCookies,
622
+ 'facebook.admin.setAppProperties' => SetAppProperties,
623
+ 'facebook.admin.getAppProperties' => GetAppProperties,
624
+ 'facebook.admin.setRestrictionInfo' => SetRestrictionInfo,
625
+ 'facebook.admin.getRestrictionInfo' => GetRestrictionInfo,
626
+ 'facebook.admin.getAllocation' => GetAllocation,
627
+ 'facebook.batch.run' => BatchRun,
628
+ 'facebook.fql.query' => FqlQuery,
629
+ 'facebook.fql.multiquery' => FqlMultiquery,
630
+ 'facebook.photos.get' => GetPhotos,
631
+ 'facebook.photos.getAlbums' => GetAlbums,
632
+ 'facebook.photos.createAlbum' => CreateAlbum,
633
+ 'facebook.photos.getTags' => GetTags,
634
+ 'facebook.photos.addTag' => AddTags,
635
+ 'facebook.photos.upload' => UploadPhoto,
636
+ 'facebook.events.get' => EventsGet,
637
+ 'facebook.groups.get' => GroupsGet,
638
+ 'facebook.events.getMembers' => EventMembersGet,
639
+ 'facebook.groups.getMembers' => GroupGetMembers,
640
+ 'facebook.notifications.sendEmail' => NotificationsSendEmail,
641
+ 'facebook.data.getUserPreference' => GetPreference,
642
+ 'facebook.data.setUserPreference' => SetPreference,
643
+ 'facebook.video.upload' => UploadVideo,
644
+ 'facebook.sms.send' => SmsSend,
645
+ 'facebook.sms.canSend' => SmsCanSend,
646
+ # $Author$ added code for stream fetching
647
+ 'facebook.stream.get' => StreamGet
648
+ }
649
+ end
650
+ end
@@ -0,0 +1,31 @@
1
+ module Facebooker::Rails::BackwardsCompatibleParamChecks
2
+
3
+ def one_or_true( value )
4
+ case value
5
+ when String then
6
+ value == "1"
7
+ when Numeric then
8
+ value.to_f == 1.0
9
+ when TrueClass then
10
+ true
11
+ else
12
+ false
13
+ end
14
+ end
15
+
16
+ def zero_or_false( value )
17
+ case value
18
+ when String then
19
+ value == "0"
20
+ when Numeric then
21
+ value.to_f == 0.0
22
+ when FalseClass then
23
+ true
24
+ when NilClass then
25
+ true
26
+ else
27
+ false
28
+ end
29
+ end
30
+
31
+ end