Updating Facebook Profiles and Feeds with RFacebook
June 18th, 2007
One of the things I found difficult to understand when it comes to writing a Facebook application is how to add a “dynamic” panel to a users’ profile page, and how to auto-add entries to their mini-feed. A couple of examples include:
- Putting “Nathan has added 5 photos to Flickr” or “Nathan is listening to Computer Camp Love by Datarock” on my mini-feed
- Adding a dynamic panel to my profile which shows the last 10 patches I have submitted to Ruby on Rails
It turns out this is a fairly trivial exercise with Matt Pizzimenti’s RFacebook gem. The following is a quick run-down of what’s required for adding content to the profiles of users who have installed your (Rails based) Facebook application via a push strategy. I’ve done a gem unpack of hpricot-0.5, json-1.1.0 and rfacebook-0.6.2 to RAILS_ROOT/vendor/plugins.
The “Infinite Session”
In order for you to be able to add content independently of a Facebook user being logged in, you need to have a way of authenticating yourself. When a user is browsing your application through the Facebook interface, the RFacebook library gives you access to thefbsession variable which represents the user who is currently logged into Facebook. The problem is, this session will expire. You can find out when a session will expire by checking the value of fbsession.session_expires.
But surely we don’t want to force a user to log in to Facebook every time we want to update their profile with notifications / new content from our third-party application? So how do we get a session that doesn’t expire? The trick is providing a link to the following URL:
http://www.facebook.com/code_gen.php?v=1.0&api_key=YOUR_API_KEY
Once the user clicks the “Generate” button on that page, every time you call auth.getSession, you’ll get an identical session ID which has a fbsession.session_expires value of 0. While the user is interacting with your Facebook application, you should serialise this to some kind of storage such as the ActiveRecord model of your user so you can use it later:
1 2 3 4 5 6 7 8 9 10 11 |
class FacebookUser < ActiveRecord::Migration def self.up create_table :facebook_users do |t| t.column :user_id, :string, :null => false t.column :infinite_session, :null => false end end def self.down drop_table :facebook_users end end |
And the sample controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
require 'facebook_rails_controller_extensions' class FacebookController < ApplicationController include RFacebook::RailsControllerExtensions FB_APP_URL = 'http://apps.facebook.com/my-app-name' before_filter :require_facebook_login before_filter :require_configuration, :except => :configure def facebook_api_key() 'YOUR_API_KEY'; end def facebook_api_secret() 'YOUR_API_SECRET'; end def finish_facebook_login() redirect_to FB_APP_URL; end def require_configuration @user = FacebookUser.find_by_user_id(fbsession.session_user_id) redirect_to :action => :configure unless @user end def configure @user = FacebookUser.find_or_initialize_by_user_id(fbsession.session_user_id) unless fbsession.session_expires @user.infinite_session = fbsession.session_key @user.save! end end end |
This means we can now run a little script (via cron, if you wish):
1 2 3 4 5 6 7 8 9 10 |
#!/usr/bin/env /path/to/application/script/runner require 'facebook_rails_controller_extensions' session = RFacebook::FacebookWebSession.new('YOUR_API_KEY', 'YOUR_API_SECRET') FacebookUser.find(:all).each do |user| session.activate_with_previous_session(user.infinite_session, user.user_id) session.profile_setFBML(:uid => user.user_id, :markup => 'My really dynamic content') session.feed_publishActionOfUser(:title => 'added some really dynamic content') end |
You could run this script every 5 minutes, or perhaps even directly call session.feed_publishActionOfUser and session.profile_setFBML from your application when the user does something (such as creating a resource).
If you’ve got any examples of where you’ve used this technique, or have any suggestions as to how it could be done better, I’d love to see them. Please comment below :).
June 22nd, 2007 at 04:16 PM
This was unclear to me, too. Thanks for the straightforward explanation.
June 27th, 2007 at 09:23 AM
We’re not requiring users to click that “Generate” link. Instead we’re just storing their session key and re-using it in our background process. Turns out that most of the sessions we get are infinite anyway.
June 27th, 2007 at 06:39 PM
@Scott: You’ll only get an infinite session if the user clicks on the “keep me logged in” checkbox when adding the application (which I agree, is most of the time).
It’s handy to prompt users within the canvas to click the ‘Generate’ link if they haven’t done so, or they’ll wonder why things aren’t working properly.
August 3rd, 2007 at 03:38 AM
I tested the code with some revisions to mainly test out feed_publishActionOfUser. The code got executed smoothly with no error, however, what I posted does not show up in the minifeed of myself, nor in that of my friend.
Any suggestions on how I could identify and fix the problem?
- Zesko
October 5th, 2007 at 06:30 PM
The developer wiki now has the ‘proper’ solution, which is to use your own key since you know that you will have checked off “keep me logged in”. Check it out: http://wiki.developers.facebook.com/index.php/Infinite_session_keys
October 26th, 2007 at 10:57 PM
Great post. I was doing the same thing. Have you started using handles at all? Makes updating profile a lot simpler and cleaner. Either way, solid post.
moe
October 27th, 2007 at 04:11 PM
@moe: To be honest, I haven’t had much time to work on anything Facebook recently. I’ve grown tired of going the hard yards to integrate with what’s essentially a closed system sitting behind a public, proprietary API – much akin to Microsoft’s Blackbird or AOL’s RAINMAN.
November 17th, 2007 at 10:02 PM
Just a quick note to say that the infinite session key generation method given in this article is unnecessary for internal Facebook applications.
With internal apps, if a user has added your app, the seesion key they have will be infinite. If they haven’t added your app, you won’t need to update their profile anyway!
The method may apply to external apps, but I wouldn’t know about that.
Oh – and great article by the way, it helped me understand how the whole profile and feed thing worked.
March 11th, 2008 at 08:06 PM
I cannot make it work, dunt know what happen to the cron that I made. When I tru execute the cron, error occurs: ../config/../vendor/rails/railties/lib/commands/runner.rb:45: undefined local variable or method `status’ for main:Object (NameError) from (eval):6:in `each’ from (eval):6 from /home/admin/myapp/script/runner:4:in `eval’ from /home/admin/myapp/script/../config/../vendor/rails/railties/lib/commands/runner.rb:45 from /home/admin/myapp/script/runner:4:in `require’ from /home/admin/myapp/script/runner:4
Please help me to figure this out. Thanks a lot
March 21st, 2008 at 02:42 PM
Please help…i am running a very similar script that Nathan is running above (from script/runner). When i run this script from the terminal command line, it executes successfully. However, when the script is run from the cron (using the exact same command) I get the following error:
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’: no such file to load—facebook_web_session (MissingSourceFile)
April 13th, 2008 at 02:33 AM
i m also facing this problem in wondows os and still not resolved. guide me for solution.
July 29th, 2008 at 10:16 AM
Anyone know how to do this with the new profile updates for Facebook?