djanowski-facebooker 1.0.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 (111) hide show
  1. data/CHANGELOG.txt +0 -0
  2. data/COPYING +19 -0
  3. data/History.txt +16 -0
  4. data/Manifest.txt +110 -0
  5. data/README +46 -0
  6. data/README.txt +81 -0
  7. data/Rakefile +76 -0
  8. data/TODO.txt +10 -0
  9. data/generators/facebook/facebook_generator.rb +14 -0
  10. data/generators/facebook/templates/config/facebooker.yml +41 -0
  11. data/generators/facebook/templates/public/javascripts/facebooker.js +106 -0
  12. data/generators/facebook_controller/USAGE +33 -0
  13. data/generators/facebook_controller/facebook_controller_generator.rb +40 -0
  14. data/generators/facebook_controller/templates/controller.rb +7 -0
  15. data/generators/facebook_controller/templates/functional_test.rb +11 -0
  16. data/generators/facebook_controller/templates/helper.rb +2 -0
  17. data/generators/facebook_controller/templates/view.fbml.erb +2 -0
  18. data/generators/facebook_controller/templates/view.html.erb +2 -0
  19. data/generators/facebook_publisher/facebook_publisher_generator.rb +14 -0
  20. data/generators/facebook_publisher/templates/create_facebook_templates.rb +15 -0
  21. data/generators/facebook_publisher/templates/publisher.rb +3 -0
  22. data/generators/facebook_scaffold/USAGE +27 -0
  23. data/generators/facebook_scaffold/facebook_scaffold_generator.rb +118 -0
  24. data/generators/facebook_scaffold/templates/controller.rb +93 -0
  25. data/generators/facebook_scaffold/templates/facebook_style.css +2579 -0
  26. data/generators/facebook_scaffold/templates/functional_test.rb +89 -0
  27. data/generators/facebook_scaffold/templates/helper.rb +2 -0
  28. data/generators/facebook_scaffold/templates/layout.fbml.erb +6 -0
  29. data/generators/facebook_scaffold/templates/layout.html.erb +17 -0
  30. data/generators/facebook_scaffold/templates/style.css +74 -0
  31. data/generators/facebook_scaffold/templates/view_edit.fbml.erb +13 -0
  32. data/generators/facebook_scaffold/templates/view_edit.html.erb +18 -0
  33. data/generators/facebook_scaffold/templates/view_index.fbml.erb +24 -0
  34. data/generators/facebook_scaffold/templates/view_index.html.erb +24 -0
  35. data/generators/facebook_scaffold/templates/view_new.fbml.erb +12 -0
  36. data/generators/facebook_scaffold/templates/view_new.html.erb +17 -0
  37. data/generators/facebook_scaffold/templates/view_show.fbml.erb +10 -0
  38. data/generators/facebook_scaffold/templates/view_show.html.erb +10 -0
  39. data/generators/publisher/publisher_generator.rb +14 -0
  40. data/init.rb +54 -0
  41. data/install.rb +12 -0
  42. data/lib/facebooker/adapters/adapter_base.rb +87 -0
  43. data/lib/facebooker/adapters/bebo_adapter.rb +73 -0
  44. data/lib/facebooker/adapters/facebook_adapter.rb +48 -0
  45. data/lib/facebooker/admin.rb +28 -0
  46. data/lib/facebooker/batch_request.rb +44 -0
  47. data/lib/facebooker/data.rb +57 -0
  48. data/lib/facebooker/feed.rb +78 -0
  49. data/lib/facebooker/logging.rb +51 -0
  50. data/lib/facebooker/model.rb +123 -0
  51. data/lib/facebooker/models/affiliation.rb +10 -0
  52. data/lib/facebooker/models/album.rb +11 -0
  53. data/lib/facebooker/models/applicationproperties.rb +39 -0
  54. data/lib/facebooker/models/cookie.rb +10 -0
  55. data/lib/facebooker/models/education_info.rb +11 -0
  56. data/lib/facebooker/models/event.rb +26 -0
  57. data/lib/facebooker/models/friend_list.rb +14 -0
  58. data/lib/facebooker/models/group.rb +35 -0
  59. data/lib/facebooker/models/info_item.rb +10 -0
  60. data/lib/facebooker/models/info_section.rb +10 -0
  61. data/lib/facebooker/models/location.rb +8 -0
  62. data/lib/facebooker/models/notifications.rb +17 -0
  63. data/lib/facebooker/models/page.rb +27 -0
  64. data/lib/facebooker/models/photo.rb +10 -0
  65. data/lib/facebooker/models/tag.rb +12 -0
  66. data/lib/facebooker/models/user.rb +352 -0
  67. data/lib/facebooker/models/work_info.rb +9 -0
  68. data/lib/facebooker/parser.rb +540 -0
  69. data/lib/facebooker/rails/controller.rb +246 -0
  70. data/lib/facebooker/rails/facebook_asset_path.rb +18 -0
  71. data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
  72. data/lib/facebooker/rails/facebook_pretty_errors.rb +14 -0
  73. data/lib/facebooker/rails/facebook_request_fix.rb +24 -0
  74. data/lib/facebooker/rails/facebook_session_handling.rb +69 -0
  75. data/lib/facebooker/rails/facebook_url_rewriting.rb +39 -0
  76. data/lib/facebooker/rails/helpers.rb +615 -0
  77. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  78. data/lib/facebooker/rails/publisher.rb +492 -0
  79. data/lib/facebooker/rails/routing.rb +49 -0
  80. data/lib/facebooker/rails/test_helpers.rb +88 -0
  81. data/lib/facebooker/rails/utilities.rb +22 -0
  82. data/lib/facebooker/server_cache.rb +24 -0
  83. data/lib/facebooker/service.rb +31 -0
  84. data/lib/facebooker/session.rb +564 -0
  85. data/lib/facebooker/version.rb +9 -0
  86. data/lib/facebooker.rb +143 -0
  87. data/lib/net/http_multipart_post.rb +123 -0
  88. data/lib/tasks/facebooker.rake +18 -0
  89. data/lib/tasks/tunnel.rake +46 -0
  90. data/rails/init.rb +1 -0
  91. data/setup.rb +1585 -0
  92. data/templates/layout.erb +24 -0
  93. data/test/adapters_test.rb +98 -0
  94. data/test/batch_request_test.rb +82 -0
  95. data/test/event_test.rb +15 -0
  96. data/test/facebook_admin_test.rb +75 -0
  97. data/test/facebook_cache_test.rb +43 -0
  98. data/test/facebook_data_test.rb +84 -0
  99. data/test/facebooker_test.rb +855 -0
  100. data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
  101. data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
  102. data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
  103. data/test/http_multipart_post_test.rb +54 -0
  104. data/test/logging_test.rb +43 -0
  105. data/test/model_test.rb +91 -0
  106. data/test/publisher_test.rb +436 -0
  107. data/test/rails_integration_test.rb +1126 -0
  108. data/test/session_test.rb +587 -0
  109. data/test/test_helper.rb +60 -0
  110. data/test/user_test.rb +229 -0
  111. metadata +181 -0
@@ -0,0 +1,352 @@
1
+ require 'facebooker/model'
2
+ require 'facebooker/models/affiliation'
3
+ require 'facebooker/models/work_info'
4
+ require 'active_support'
5
+ module Facebooker
6
+ #
7
+ # Holds attributes and behavior for a Facebook User
8
+ class User
9
+ include Model
10
+ class Status
11
+ include Model
12
+ attr_accessor :message, :time, :status_id
13
+ end
14
+ 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, :uid, :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]
15
+ STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url]
16
+ attr_accessor :id, :session
17
+ populating_attr_accessor *FIELDS
18
+ attr_reader :affiliations
19
+ populating_hash_settable_accessor :current_location, Location
20
+ populating_hash_settable_accessor :hometown_location, Location
21
+ populating_hash_settable_accessor :hs_info, EducationInfo::HighschoolInfo
22
+ populating_hash_settable_accessor :status, Status
23
+ populating_hash_settable_list_accessor :affiliations, Affiliation
24
+ populating_hash_settable_list_accessor :education_history, EducationInfo
25
+ populating_hash_settable_list_accessor :work_history, WorkInfo
26
+
27
+ # Can pass in these two forms:
28
+ # id, session, (optional) attribute_hash
29
+ # attribute_hash
30
+ def initialize(*args)
31
+ if (args.first.kind_of?(String) || args.first.kind_of?(Integer)) && args.size==1
32
+ @id=Integer(args.shift)
33
+ @session = Session.current
34
+ elsif (args.first.kind_of?(String) || args.first.kind_of?(Integer)) && args[1].kind_of?(Session)
35
+ @id = Integer(args.shift)
36
+ @session = args.shift
37
+ end
38
+ if args.last.kind_of?(Hash)
39
+ populate_from_hash!(args.pop)
40
+ end
41
+ end
42
+
43
+ # Returns a user's events, params correspond to API call parameters (except UID):
44
+ # http://wiki.developers.facebook.com/index.php/Events.get
45
+ # E.g:
46
+ # @user.events(:start_time => Time.now.to_i, :end_time => 1.month.from_now.to_i)
47
+ # # => Returns events betwen now and a month from now
48
+ def events(params={})
49
+ @events ||= @session.post('facebook.events.get', {:uid => self.id}.merge(params)).map do |event|
50
+ Event.from_hash(event)
51
+ end
52
+ end
53
+
54
+ #
55
+ # Set the list of friends, given an array of User objects. If the list has been retrieved previously, will not set
56
+ def friends=(list_of_friends,flid=nil)
57
+ @friends_hash ||= {}
58
+ flid=cast_to_friend_list_id(flid)
59
+ #use __blank instead of nil so that this is cached
60
+ cache_key = flid||"__blank"
61
+
62
+ @friends_hash[cache_key] ||= list_of_friends
63
+ end
64
+
65
+ def cast_to_friend_list_id(flid)
66
+ case flid
67
+ when String
68
+ list=friend_lists.detect {|f| f.name==flid}
69
+ raise Facebooker::Session::InvalidFriendList unless list
70
+ list.flid
71
+ when FriendList
72
+ flid.flid
73
+ else
74
+ flid
75
+ end
76
+ end
77
+ ##
78
+ # Retrieve friends
79
+ def friends(flid = nil)
80
+ @friends_hash ||= {}
81
+ flid=cast_to_friend_list_id(flid)
82
+
83
+ #use __blank instead of nil so that this is cached
84
+ cache_key = flid||"__blank"
85
+ @friends_hash[cache_key] ||= @session.post('facebook.friends.get', (flid.nil? ? {} : {:flid => flid})).map do |uid|
86
+ User.new(uid, @session)
87
+ end
88
+ @friends_hash[cache_key]
89
+ end
90
+
91
+ def friend_lists
92
+ @friend_lists ||= @session.post('facebook.friends.getLists').map do |hash|
93
+ friend_list = FriendList.from_hash(hash)
94
+ friend_list.session = session
95
+ friend_list
96
+ end
97
+ end
98
+ ###
99
+ # Retrieve friends with user info populated
100
+ # Subsequent calls will be retrieved from memory.
101
+ # Optional: list of fields to retrieve as symbols
102
+ def friends!(*fields)
103
+ @friends ||= session.post('facebook.users.getInfo', :fields => collect(fields), :uids => friends.map{|f| f.id}.join(',')).map do |hash|
104
+ User.new(hash['uid'], session, hash)
105
+ end
106
+ end
107
+
108
+ ###
109
+ # Retrieve profile data for logged in user
110
+ # Optional: list of fields to retrieve as symbols
111
+ def populate(*fields)
112
+ session.post('facebook.users.getInfo', :fields => collect(fields), :uids => id) do |response|
113
+ populate_from_hash!(response.first)
114
+ end
115
+ end
116
+
117
+ def friends_with?(user_or_id)
118
+ friends.map{|f| f.to_i}.include?(user_or_id.to_i)
119
+ end
120
+
121
+ def friends_with_this_app
122
+ @friends_with_this_app ||= session.post('facebook.friends.getAppUsers').map do |uid|
123
+ User.new(uid, session)
124
+ end
125
+ end
126
+
127
+ def groups(gids = [])
128
+ args = gids.empty? ? {} : {:gids => gids}
129
+ @groups ||= session.post('facebook.groups.get', args).map do |hash|
130
+ group = Group.from_hash(hash)
131
+ group.session = session
132
+ group
133
+ end
134
+ end
135
+
136
+ def notifications
137
+ @notifications ||= Notifications.from_hash(session.post('facebook.notifications.get'))
138
+ end
139
+
140
+ def publish_story(story)
141
+ publish(story)
142
+ end
143
+
144
+ def publish_action(action)
145
+ publish(action)
146
+ end
147
+
148
+ def publish_templatized_action(action)
149
+ publish(action)
150
+ end
151
+
152
+ def albums
153
+ @albums ||= session.post('facebook.photos.getAlbums', :uid => self.id) do |response|
154
+ response.map do |hash|
155
+ Album.from_hash(hash)
156
+ end
157
+ end
158
+ end
159
+
160
+ def create_album(params)
161
+ @album = session.post('facebook.photos.createAlbum', params) {|response| Album.from_hash(response)}
162
+ end
163
+
164
+ def profile_photos
165
+ session.get_photos(nil, nil, profile_pic_album_id)
166
+ end
167
+
168
+ def upload_photo(multipart_post_file)
169
+ Photo.from_hash(session.post_file('facebook.photos.upload', {nil => multipart_post_file}))
170
+ end
171
+
172
+ def profile_fbml
173
+ session.post('facebook.profile.getFBML', :uid => @id)
174
+ end
175
+
176
+ ##
177
+ # Set the profile FBML for this user
178
+ #
179
+ # This does not set profile actions, that should be done with profile_action=
180
+ def profile_fbml=(markup)
181
+ set_profile_fbml(markup, nil, nil)
182
+ end
183
+
184
+ ##
185
+ # Set the mobile profile FBML
186
+ def mobile_fbml=(markup)
187
+ set_profile_fbml(nil, markup, nil)
188
+ end
189
+
190
+ def profile_action=(markup)
191
+ set_profile_fbml(nil, nil, markup)
192
+ end
193
+
194
+ def profile_main=(markup)
195
+ set_profile_fbml(nil,nil,nil,markup)
196
+ end
197
+
198
+ def set_profile_fbml(profile_fbml, mobile_fbml, profile_action_fbml, profile_main = nil)
199
+ parameters = {:uid => @id}
200
+ parameters[:profile] = profile_fbml if profile_fbml
201
+ parameters[:profile_action] = profile_action_fbml if profile_action_fbml
202
+ parameters[:mobile_profile] = mobile_fbml if mobile_fbml
203
+ parameters[:profile_main] = profile_main if profile_main
204
+ session.post('facebook.profile.setFBML', parameters,false)
205
+ end
206
+
207
+ ## ** NEW PROFILE DESIGN ***
208
+ # Set a info section for this user
209
+ #
210
+ # Note: using set_profile_info as I feel using user.set_info could be confused with the user.getInfo facebook method.
211
+ # Also, I feel it fits in line with user.set_profile_fbml.
212
+ def set_profile_info(title, info_fields, format = :text)
213
+ session.post('facebook.profile.setInfo', :title => title, :uid => @id,
214
+ :type => format.to_s == "text" ? 1 : 5, :info_fields => info_fields.to_json)
215
+ end
216
+
217
+ def get_profile_info
218
+ session.post('facebook.profile.getInfo', :uid => @id)
219
+ end
220
+
221
+ ##
222
+ # Set the status of the user
223
+ #
224
+ # DOES NOT prepend "is" to the message
225
+ #
226
+ # requires extended permission.
227
+ def status=(message)
228
+ case message
229
+ when String
230
+ session.post('facebook.users.setStatus',:status=>message,:status_includes_verb=>1) do |ret|
231
+ ret
232
+ end
233
+ when Status
234
+ @status = message
235
+ when Hash
236
+ @status = Status.from_hash(message)
237
+ end
238
+ end
239
+
240
+ ##
241
+ # Convenience method to send email to the current user
242
+ def send_email(subject, text=nil, fbml=nil)
243
+ session.send_email([@id], subject, text, fbml)
244
+ end
245
+
246
+ ##
247
+ # Convenience method to set cookie for the current user
248
+ def set_cookie(name, value, expires=nil, path=nil)
249
+ session.data.set_cookie(@id, name, value, expires, path)
250
+ end
251
+
252
+ ##
253
+ # Convenience method to get cookies for the current user
254
+ def get_cookies(name=nil)
255
+ session.data.get_cookies(@id, name)
256
+ end
257
+
258
+ ##
259
+ # Returns the user's id as an integer
260
+ def to_i
261
+ id
262
+ end
263
+
264
+ def to_s
265
+ id.to_s
266
+ end
267
+
268
+ ##
269
+ # Two Facebooker::User objects should be considered equal if their Facebook ids are equal
270
+ def ==(other_user)
271
+ id == other_user.id
272
+ end
273
+
274
+
275
+ # register a user with Facebook
276
+ # users should be a hast with at least an :email field
277
+ # you can optionally provide an :account_id field as well
278
+
279
+ def self.register(users)
280
+ user_map={}
281
+ users=users.map do |h|
282
+ returning h.dup do |d|
283
+ if email=d.delete(:email)
284
+ hash = hash_email(email)
285
+ user_map[hash]=h
286
+ d[:email_hash]=hash
287
+ end
288
+ end
289
+ end
290
+ Facebooker::Session.create.post("facebook.connect.registerUsers",:accounts=>users.to_json) do |ret|
291
+ ret.each do |hash|
292
+ user_map.delete(hash)
293
+ end
294
+ unless user_map.blank?
295
+ e=Facebooker::Session::UserRegistrationFailed.new
296
+ e.failed_users = user_map.values
297
+ raise e
298
+ end
299
+ ret
300
+ end
301
+ end
302
+
303
+ def self.hash_email(email)
304
+ email = email.downcase.strip
305
+ crc=Zlib.crc32(email)
306
+ md5=Digest::MD5.hexdigest(email)
307
+ "#{crc}_#{md5}"
308
+ end
309
+
310
+ def self.cast_to_facebook_id(object)
311
+ if object.respond_to?(:facebook_id)
312
+ object.facebook_id
313
+ else
314
+ object
315
+ end
316
+ end
317
+
318
+ def facebook_id
319
+ @id
320
+ end
321
+
322
+ def self.user_fields(fields = [])
323
+ valid_fields(fields)
324
+ end
325
+
326
+ def self.standard_fields(fields = [])
327
+ valid_fields(fields,STANDARD_FIELDS)
328
+ end
329
+
330
+ private
331
+ def publish(feed_story_or_action)
332
+ session.post(Facebooker::Feed::METHODS[feed_story_or_action.class.name.split(/::/).last], feed_story_or_action.to_params) == "1" ? true : false
333
+ end
334
+
335
+ def self.valid_fields(fields, allowable=FIELDS)
336
+ allowable.reject{|field_name| !fields.empty? && !fields.include?(field_name)}.join(',')
337
+ end
338
+
339
+ def collect(fields, allowable=FIELDS)
340
+ allowable.reject{|field_name| !fields.empty? && !fields.include?(field_name)}.join(',')
341
+ end
342
+
343
+ def profile_pic_album_id
344
+ merge_aid(-3, @id)
345
+ end
346
+
347
+ def merge_aid(aid, uid)
348
+ (uid << 32) + (aid & 0xFFFFFFFF)
349
+ end
350
+
351
+ end
352
+ end
@@ -0,0 +1,9 @@
1
+ module Facebooker
2
+ class WorkInfo
3
+ include Model
4
+ attr_accessor :end_date, :start_date, :company_name, :description, :position, :location
5
+ def location=(location)
6
+ @location = location.kind_of?(Hash) ? Location.from_hash(location) : location
7
+ end
8
+ end
9
+ end