tenderlove-facebooker 1.0.16.20090319151701

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 (124) hide show
  1. data/CHANGELOG.rdoc +17 -0
  2. data/COPYING.rdoc +19 -0
  3. data/Manifest.txt +123 -0
  4. data/README.rdoc +103 -0
  5. data/Rakefile +86 -0
  6. data/TODO.rdoc +4 -0
  7. data/examples/desktop_login.rb +14 -0
  8. data/facebooker.gemspec +38 -0
  9. data/generators/facebook/facebook_generator.rb +14 -0
  10. data/generators/facebook/templates/config/facebooker.yml +46 -0
  11. data/generators/facebook/templates/public/javascripts/facebooker.js +99 -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/generators/xd_receiver/templates/xd_receiver.html +10 -0
  41. data/generators/xd_receiver/xd_receiver_generator.rb +9 -0
  42. data/init.rb +72 -0
  43. data/install.rb +12 -0
  44. data/lib/facebooker/adapters/adapter_base.rb +87 -0
  45. data/lib/facebooker/adapters/bebo_adapter.rb +75 -0
  46. data/lib/facebooker/adapters/facebook_adapter.rb +52 -0
  47. data/lib/facebooker/admin.rb +42 -0
  48. data/lib/facebooker/batch_request.rb +44 -0
  49. data/lib/facebooker/data.rb +57 -0
  50. data/lib/facebooker/feed.rb +78 -0
  51. data/lib/facebooker/logging.rb +51 -0
  52. data/lib/facebooker/mobile.rb +20 -0
  53. data/lib/facebooker/mock/service.rb +50 -0
  54. data/lib/facebooker/mock/session.rb +18 -0
  55. data/lib/facebooker/model.rb +135 -0
  56. data/lib/facebooker/models/affiliation.rb +10 -0
  57. data/lib/facebooker/models/album.rb +11 -0
  58. data/lib/facebooker/models/applicationproperties.rb +39 -0
  59. data/lib/facebooker/models/applicationrestrictions.rb +10 -0
  60. data/lib/facebooker/models/cookie.rb +10 -0
  61. data/lib/facebooker/models/education_info.rb +11 -0
  62. data/lib/facebooker/models/event.rb +28 -0
  63. data/lib/facebooker/models/friend_list.rb +16 -0
  64. data/lib/facebooker/models/group.rb +36 -0
  65. data/lib/facebooker/models/info_item.rb +10 -0
  66. data/lib/facebooker/models/info_section.rb +10 -0
  67. data/lib/facebooker/models/location.rb +8 -0
  68. data/lib/facebooker/models/notifications.rb +17 -0
  69. data/lib/facebooker/models/page.rb +27 -0
  70. data/lib/facebooker/models/photo.rb +12 -0
  71. data/lib/facebooker/models/tag.rb +12 -0
  72. data/lib/facebooker/models/user.rb +426 -0
  73. data/lib/facebooker/models/video.rb +9 -0
  74. data/lib/facebooker/models/work_info.rb +9 -0
  75. data/lib/facebooker/parser.rb +589 -0
  76. data/lib/facebooker/rails/controller.rb +304 -0
  77. data/lib/facebooker/rails/cucumber/world.rb +46 -0
  78. data/lib/facebooker/rails/cucumber.rb +28 -0
  79. data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
  80. data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
  81. data/lib/facebooker/rails/facebook_request_fix.rb +24 -0
  82. data/lib/facebooker/rails/facebook_session_handling.rb +69 -0
  83. data/lib/facebooker/rails/facebook_url_helper.rb +192 -0
  84. data/lib/facebooker/rails/facebook_url_rewriting.rb +39 -0
  85. data/lib/facebooker/rails/helpers/fb_connect.rb +89 -0
  86. data/lib/facebooker/rails/helpers.rb +762 -0
  87. data/lib/facebooker/rails/integration_session.rb +38 -0
  88. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  89. data/lib/facebooker/rails/publisher.rb +526 -0
  90. data/lib/facebooker/rails/routing.rb +49 -0
  91. data/lib/facebooker/rails/test_helpers.rb +68 -0
  92. data/lib/facebooker/rails/utilities.rb +22 -0
  93. data/lib/facebooker/server_cache.rb +24 -0
  94. data/lib/facebooker/service.rb +94 -0
  95. data/lib/facebooker/session.rb +584 -0
  96. data/lib/facebooker/version.rb +9 -0
  97. data/lib/facebooker.rb +174 -0
  98. data/lib/net/http_multipart_post.rb +123 -0
  99. data/lib/tasks/facebooker.rake +18 -0
  100. data/lib/tasks/tunnel.rake +46 -0
  101. data/rails/init.rb +1 -0
  102. data/setup.rb +1585 -0
  103. data/templates/layout.erb +24 -0
  104. data/test/facebooker/adapters_test.rb +96 -0
  105. data/test/facebooker/admin_test.rb +102 -0
  106. data/test/facebooker/batch_request_test.rb +83 -0
  107. data/test/facebooker/data_test.rb +86 -0
  108. data/test/facebooker/logging_test.rb +43 -0
  109. data/test/facebooker/mobile_test.rb +45 -0
  110. data/test/facebooker/model_test.rb +123 -0
  111. data/test/facebooker/models/event_test.rb +15 -0
  112. data/test/facebooker/models/user_test.rb +295 -0
  113. data/test/facebooker/rails/publisher_test.rb +452 -0
  114. data/test/facebooker/rails_integration_test.rb +1312 -0
  115. data/test/facebooker/server_cache_test.rb +44 -0
  116. data/test/facebooker/session_test.rb +614 -0
  117. data/test/facebooker_test.rb +925 -0
  118. data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
  119. data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
  120. data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
  121. data/test/net/http_multipart_post_test.rb +52 -0
  122. data/test/rails_test_helper.rb +11 -0
  123. data/test/test_helper.rb +66 -0
  124. metadata +217 -0
@@ -0,0 +1,10 @@
1
+ module Facebooker
2
+ class InfoItem
3
+ include Model
4
+ attr_accessor :label, :image, :description, :link, :sublabel
5
+
6
+ def to_json
7
+ {:label => label, :image => image, :description => description, :link => link, :sublabel => sublabel}.to_json
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Facebooker
2
+ class InfoSection
3
+ include Model
4
+ attr_accessor :field, :items
5
+
6
+ def to_json
7
+ {:field => field, :items => items}.to_json
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Facebooker
2
+ ##
3
+ # Representation of Location used in all places where a Location is specified.
4
+ class Location
5
+ include Model
6
+ attr_accessor :city, :zip, :country, :state
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Facebooker
2
+ class Notifications
3
+ include Model
4
+ attr_accessor :messages, :group_invites, :pokes, :friend_requests, :event_invites, :shares
5
+
6
+ [:Messages, :Pokes, :Shares].each do |notification_type|
7
+ const_set(notification_type, Class.new do
8
+ include Model
9
+ attr_accessor :unread, :most_recent
10
+ end)
11
+ attribute_name = "#{notification_type.to_s.downcase}"
12
+ define_method("#{attribute_name}=") do |value|
13
+ instance_variable_set("@#{attribute_name}", value.kind_of?(Hash) ? Notifications.const_get(notification_type).from_hash(value) : value)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'facebooker/model'
2
+ module Facebooker
3
+ class Page
4
+
5
+ class Genre
6
+ include Model
7
+ FIELDS = [ :dance, :party, :relax, :talk, :think, :workout, :sing, :intimate, :raunchy, :headphones ]
8
+ attr_accessor *FIELDS
9
+
10
+ def initialize(*args)
11
+ super
12
+
13
+ # convert '1'/'0' to true/false
14
+ FIELDS.each do |field|
15
+ self.send("#{field}=", self.send(field) == '1')
16
+ end
17
+ end
18
+ end
19
+
20
+ include Model
21
+ attr_accessor :page_id, :name, :pic_small, :pic_big, :pic_square, :pic_large, :type, :type, :website, :location, :hours, :band_members, :bio, :hometown, :genre, :record_label, :influences, :has_added_app, :founded, :company_overview, :mission, :products, :release_date, :starring, :written_by, :directed_by, :produced_by, :studio, :awards, :plot_outline, :network, :season, :schedule
22
+
23
+ def genre=(value)
24
+ @genre = value.kind_of?(Hash) ? Genre.from_hash(value) : value
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ require 'facebooker/model'
2
+ module Facebooker
3
+ class Photo
4
+ include Model
5
+ attr_accessor :pid, :aid, :owner, :title,
6
+ :link, :caption, :created,
7
+ :src, :src_big, :src_small,
8
+ :story_fbid
9
+
10
+ id_is :pid
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'facebooker/model'
2
+ module Facebooker
3
+ class Tag
4
+ include Model
5
+ attr_accessor :pid, :subject, :xcoord, :ycoord
6
+
7
+ def coordinates
8
+ [xcoord, ycoord]
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,426 @@
1
+ require 'facebooker/model'
2
+ require 'facebooker/models/affiliation'
3
+ require 'facebooker/models/work_info'
4
+ module Facebooker
5
+ #
6
+ # Holds attributes and behavior for a Facebook User
7
+ class User
8
+ include Model
9
+ class Status
10
+ include Model
11
+ attr_accessor :message, :time, :status_id
12
+ end
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, :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, :locale, :profile_url, :proxied_email, :email_hashes, :allowed_restrictions]
14
+ STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url, :pic_square]
15
+ populating_attr_accessor *FIELDS
16
+ attr_reader :affiliations
17
+ populating_hash_settable_accessor :current_location, Location
18
+ populating_hash_settable_accessor :hometown_location, Location
19
+ populating_hash_settable_accessor :hs_info, EducationInfo::HighschoolInfo
20
+ populating_hash_settable_accessor :status, Status
21
+ populating_hash_settable_list_accessor :affiliations, Affiliation
22
+ populating_hash_settable_list_accessor :education_history, EducationInfo
23
+ populating_hash_settable_list_accessor :work_history, WorkInfo
24
+
25
+ # Can pass in these two forms:
26
+ # id, session, (optional) attribute_hash
27
+ # attribute_hash
28
+ def initialize(*args)
29
+ if (args.first.kind_of?(String) || args.first.kind_of?(Integer)) && args.size==1
30
+ self.uid = args.shift
31
+ @session = Session.current
32
+ elsif (args.first.kind_of?(String) || args.first.kind_of?(Integer)) && args[1].kind_of?(Session)
33
+ self.uid = args.shift
34
+ @session = args.shift
35
+ end
36
+ if args.last.kind_of?(Hash)
37
+ populate_from_hash!(args.pop)
38
+ end
39
+ end
40
+
41
+ id_is :uid
42
+ alias :facebook_id :id
43
+
44
+ # Returns a user's events, params correspond to API call parameters (except UID):
45
+ # http://wiki.developers.facebook.com/index.php/Events.get
46
+ # E.g:
47
+ # @user.events(:start_time => Time.now, :end_time => 1.month.from_now)
48
+ # # => Returns events betwen now and a month from now
49
+ def events(params={})
50
+ @events ||= {}
51
+ [:start_time,:end_time].compact.each do |key|
52
+ params[key] = params[key].to_i
53
+ end
54
+ # puts @events[params.to_s].nil?
55
+ @events[params.to_s] ||= @session.post('facebook.events.get', {:uid => self.id}.merge(params)).map do |event|
56
+ Event.from_hash(event)
57
+ end
58
+ end
59
+
60
+ #
61
+ # Set the list of friends, given an array of User objects. If the list has been retrieved previously, will not set
62
+ def friends=(list_of_friends,flid=nil)
63
+ @friends_hash ||= {}
64
+ flid=cast_to_friend_list_id(flid)
65
+ #use __blank instead of nil so that this is cached
66
+ cache_key = flid||"__blank"
67
+
68
+ @friends_hash[cache_key] ||= list_of_friends
69
+ end
70
+
71
+ def cast_to_friend_list_id(flid)
72
+ case flid
73
+ when String
74
+ list=friend_lists.detect {|f| f.name==flid}
75
+ raise Facebooker::Session::InvalidFriendList unless list
76
+ list.flid
77
+ when FriendList
78
+ flid.flid
79
+ else
80
+ flid
81
+ end
82
+ end
83
+ ##
84
+ # Retrieve friends
85
+ def friends(flid = nil)
86
+ @friends_hash ||= {}
87
+ flid=cast_to_friend_list_id(flid)
88
+
89
+ #use __blank instead of nil so that this is cached
90
+ cache_key = flid||"__blank"
91
+ options = {:uid=>self.id}
92
+ options[:flid] = flid unless flid.nil?
93
+ @friends_hash[cache_key] ||= @session.post('facebook.friends.get', options,false).map do |uid|
94
+ User.new(uid, @session)
95
+ end
96
+ @friends_hash[cache_key]
97
+ end
98
+
99
+ def friend_lists
100
+ @friend_lists ||= @session.post('facebook.friends.getLists').map do |hash|
101
+ friend_list = FriendList.from_hash(hash)
102
+ friend_list.session = session
103
+ friend_list
104
+ end
105
+ end
106
+ ###
107
+ # Retrieve friends with user info populated
108
+ # Subsequent calls will be retrieved from memory.
109
+ # Optional: list of fields to retrieve as symbols
110
+ def friends!(*fields)
111
+ @friends ||= session.post('facebook.users.getInfo', :fields => collect(fields), :uids => friends.map{|f| f.id}.join(',')).map do |hash|
112
+ User.new(hash['uid'], session, hash)
113
+ end
114
+ end
115
+
116
+ ###
117
+ # Retrieve profile data for logged in user
118
+ # Optional: list of fields to retrieve as symbols
119
+ def populate(*fields)
120
+ session.post('facebook.users.getInfo', :fields => collect(fields), :uids => id) do |response|
121
+ populate_from_hash!(response.first)
122
+ end
123
+ end
124
+
125
+ def friends_with?(user_or_id)
126
+ friends.map{|f| f.to_i}.include?(user_or_id.to_i)
127
+ end
128
+
129
+ def friends_with_this_app
130
+ @friends_with_this_app ||= session.post('facebook.friends.getAppUsers').map do |uid|
131
+ User.new(uid, session)
132
+ end
133
+ end
134
+
135
+ def groups(gids = [])
136
+ args = gids.empty? ? {} : {:gids => gids}
137
+ @groups ||= session.post('facebook.groups.get', args).map do |hash|
138
+ group = Group.from_hash(hash)
139
+ group.session = session
140
+ group
141
+ end
142
+ end
143
+
144
+ def notifications
145
+ @notifications ||= Notifications.from_hash(session.post('facebook.notifications.get'))
146
+ end
147
+
148
+ def publish_story(story)
149
+ publish(story)
150
+ end
151
+
152
+ def publish_action(action)
153
+ publish(action)
154
+ end
155
+
156
+ def publish_templatized_action(action)
157
+ publish(action)
158
+ end
159
+
160
+ def albums
161
+ @albums ||= session.post('facebook.photos.getAlbums', :uid => self.id) do |response|
162
+ response.map do |hash|
163
+ Album.from_hash(hash)
164
+ end
165
+ end
166
+ end
167
+
168
+ def create_album(params)
169
+ @album = session.post('facebook.photos.createAlbum', params) {|response| Album.from_hash(response)}
170
+ end
171
+
172
+ def profile_photos
173
+ session.get_photos(nil, nil, profile_pic_album_id)
174
+ end
175
+
176
+ # Upload a photo to the user's profile.
177
+ #
178
+ # In your view, create a multipart form that posts directly to your application (not through canvas):
179
+ #
180
+ # <% form_tag photos_url(:canvas => false), :html => {:multipart => true, :promptpermission => 'photo_upload'} do %>
181
+ # Photo: <%= file_field_tag 'photo' %>
182
+ # Caption: <%= text_area_tag 'caption' %>
183
+ # <%= submit_tag 'Upload Photo', :class => 'inputsubmit' %>
184
+ # <% end %>
185
+ #
186
+ # And in your controller:
187
+ #
188
+ # class PhotosController < ApplicationController
189
+ # def create
190
+ # file = Net::HTTP::MultipartPostFile.new(
191
+ # params[:photo].original_filename,
192
+ # params[:photo].content_type,
193
+ # params[:photo].read
194
+ # )
195
+ #
196
+ # @photo = facebook_session.user.upload_photo(file, :caption => params[:caption])
197
+ # redirect_to photos_url(:canvas => true)
198
+ # end
199
+ # end
200
+ #
201
+ # Options correspond to http://wiki.developers.facebook.com/index.php/Photos.upload
202
+ def upload_photo(multipart_post_file, options = {})
203
+ Photo.from_hash(session.post_file('facebook.photos.upload',
204
+ options.merge(nil => multipart_post_file)))
205
+ end
206
+
207
+ # Upload a video to the user's profile.
208
+ #
209
+ # In your view, create a multipart form that posts directly to your application (not through canvas):
210
+ #
211
+ # <% form_tag videos_url(:canvas => false), :html => {:multipart => true, :promptpermission => 'video_upload'} do %>
212
+ # Video: <%= file_field_tag 'video' %>
213
+ # Title: <%= text_area_tag 'title' %>
214
+ # Description: <%= text_area_tag 'description' %>
215
+ # <%= submit_tag 'Upload Video', :class => 'inputsubmit' %>
216
+ # <% end %>
217
+ #
218
+ # And in your controller:
219
+ #
220
+ # class VideosController < ApplicationController
221
+ # def create
222
+ # file = Net::HTTP::MultipartPostFile.new(
223
+ # params[:photo].original_filename,
224
+ # params[:photo].content_type,
225
+ # params[:photo].read
226
+ # )
227
+ #
228
+ # @video = facebook_session.user.upload_video(file, :description => params[:description])
229
+ # redirect_to videos_url(:canvas => true)
230
+ # end
231
+ # end
232
+ #
233
+ # Options correspond to http://wiki.developers.facebook.com/index.php/Video.upload
234
+ def upload_video(multipart_post_file, options = {})
235
+ Video.from_hash(session.post_file('facebook.video.upload',
236
+ options.merge(nil => multipart_post_file, :base => Facebooker.video_server_base)))
237
+ end
238
+
239
+ def profile_fbml
240
+ session.post('facebook.profile.getFBML', :uid => id)
241
+ end
242
+
243
+ ##
244
+ # Set the profile FBML for this user
245
+ #
246
+ # This does not set profile actions, that should be done with profile_action=
247
+ def profile_fbml=(markup)
248
+ set_profile_fbml(markup, nil, nil)
249
+ end
250
+
251
+ ##
252
+ # Set the mobile profile FBML
253
+ def mobile_fbml=(markup)
254
+ set_profile_fbml(nil, markup, nil)
255
+ end
256
+
257
+ def profile_action=(markup)
258
+ set_profile_fbml(nil, nil, markup)
259
+ end
260
+
261
+ def profile_main=(markup)
262
+ set_profile_fbml(nil,nil,nil,markup)
263
+ end
264
+
265
+ def set_profile_fbml(profile_fbml, mobile_fbml, profile_action_fbml, profile_main = nil)
266
+ parameters = {:uid => id}
267
+ parameters[:profile] = profile_fbml if profile_fbml
268
+ parameters[:profile_action] = profile_action_fbml if profile_action_fbml
269
+ parameters[:mobile_profile] = mobile_fbml if mobile_fbml
270
+ parameters[:profile_main] = profile_main if profile_main
271
+ session.post('facebook.profile.setFBML', parameters,false)
272
+ end
273
+
274
+ ## ** NEW PROFILE DESIGN ***
275
+ # Set a info section for this user
276
+ #
277
+ # Note: using set_profile_info as I feel using user.set_info could be confused with the user.getInfo facebook method.
278
+ # Also, I feel it fits in line with user.set_profile_fbml.
279
+ def set_profile_info(title, info_fields, format = :text)
280
+ session.post('facebook.profile.setInfo', :title => title, :uid => id,
281
+ :type => format.to_s == "text" ? 1 : 5, :info_fields => info_fields.to_json)
282
+ end
283
+
284
+ def get_profile_info
285
+ session.post('facebook.profile.getInfo', :uid => id)
286
+ end
287
+
288
+ ##
289
+ # This DOES NOT set the status of a user on Facebook
290
+ # Use the set_status method instead
291
+ def status=(message)
292
+ case message
293
+ when String,Status
294
+ @status = message
295
+ when Hash
296
+ @status = Status.from_hash(message)
297
+ end
298
+ end
299
+
300
+ ##
301
+ # Set the status for a user
302
+ # DOES NOT prepend "is" to the message
303
+ #
304
+ # requires extended permission.
305
+ def set_status(message)
306
+ self.status=message
307
+ session.post('facebook.users.setStatus',{:status=>message,:status_includes_verb=>1,:uid => uid}, false) do |ret|
308
+ ret
309
+ end
310
+ end
311
+
312
+ ##
313
+ # Checks to see if the user has enabled the given extended permission
314
+ def has_permission?(ext_perm) # ext_perm = email, offline_access, status_update, photo_upload, create_listing, create_event, rsvp_event, sms
315
+ session.post('facebook.users.hasAppPermission',:ext_perm=>ext_perm) == "1"
316
+ end
317
+
318
+ ##
319
+ # Convenience method to send email to the current user
320
+ def send_email(subject, text=nil, fbml=nil)
321
+ session.send_email([id], subject, text, fbml)
322
+ end
323
+
324
+ ##
325
+ # Convenience method to set cookie for the current user
326
+ def set_cookie(name, value, expires=nil, path=nil)
327
+ session.data.set_cookie(id, name, value, expires, path)
328
+ end
329
+
330
+ ##
331
+ # Convenience method to get cookies for the current user
332
+ def get_cookies(name=nil)
333
+ session.data.get_cookies(id, name)
334
+ end
335
+
336
+ ##
337
+ # Returns the user's id as an integer
338
+ def to_i
339
+ id
340
+ end
341
+
342
+ def to_s
343
+ id.to_s
344
+ end
345
+
346
+ ##
347
+ # Two Facebooker::User objects should be considered equal if their Facebook ids are equal
348
+ def ==(other_user)
349
+ other_user.is_a?(User) && id == other_user.id
350
+ end
351
+
352
+
353
+ # register a user with Facebook
354
+ # users should be a hast with at least an :email field
355
+ # you can optionally provide an :account_id field as well
356
+
357
+ def self.register(users)
358
+ user_map={}
359
+ users=users.map do |h|
360
+ returning h.dup do |d|
361
+ if email=d.delete(:email)
362
+ hash = hash_email(email)
363
+ user_map[hash]=h
364
+ d[:email_hash]=hash
365
+ end
366
+ end
367
+ end
368
+ Facebooker::Session.create.post("facebook.connect.registerUsers",:accounts=>users.to_json) do |ret|
369
+ ret.each do |hash|
370
+ user_map.delete(hash)
371
+ end
372
+ unless user_map.empty?
373
+ e=Facebooker::Session::UserRegistrationFailed.new
374
+ e.failed_users = user_map.values
375
+ raise e
376
+ end
377
+ ret
378
+ end
379
+ end
380
+
381
+ def self.hash_email(email)
382
+ email = email.downcase.strip
383
+ crc=Zlib.crc32(email)
384
+ md5=Digest::MD5.hexdigest(email)
385
+ "#{crc}_#{md5}"
386
+ end
387
+
388
+ def self.cast_to_facebook_id(object)
389
+ if object.respond_to?(:facebook_id)
390
+ object.facebook_id
391
+ else
392
+ object
393
+ end
394
+ end
395
+
396
+ def self.user_fields(fields = [])
397
+ valid_fields(fields)
398
+ end
399
+
400
+ def self.standard_fields(fields = [])
401
+ valid_fields(fields,STANDARD_FIELDS)
402
+ end
403
+
404
+ private
405
+ def publish(feed_story_or_action)
406
+ session.post(Facebooker::Feed::METHODS[feed_story_or_action.class.name.split(/::/).last], feed_story_or_action.to_params) == "1" ? true : false
407
+ end
408
+
409
+ def self.valid_fields(fields, allowable=FIELDS)
410
+ allowable.reject{|field_name| !fields.empty? && !fields.include?(field_name)}.join(',')
411
+ end
412
+
413
+ def collect(fields, allowable=FIELDS)
414
+ allowable.reject{|field_name| !fields.empty? && !fields.include?(field_name)}.join(',')
415
+ end
416
+
417
+ def profile_pic_album_id
418
+ merge_aid(-3, id)
419
+ end
420
+
421
+ def merge_aid(aid, uid)
422
+ (uid << 32) + (aid & 0xFFFFFFFF)
423
+ end
424
+
425
+ end
426
+ end
@@ -0,0 +1,9 @@
1
+ require 'facebooker/model'
2
+ module Facebooker
3
+ class Video
4
+ include Model
5
+ attr_accessor :vid, :owner, :title,
6
+ :link, :description, :created,
7
+ :story_fbid
8
+ end
9
+ 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