Joyent Supports hi5 and Open Social
MARIN COUNTY, CALIFORNIA – March 13, 2008: Expands Social Networking partnerships by providing free Accelerators optimized for the Open Social platform.
It is fairly simple. The Joyent Players’ Club application just collects some Facebook user’s information when that information is publicly available from the current Facebook user’s profile.
By embedding the application, you just have to include some markup into your application pointing to the Joyent Players’ Club Application URL.2
Also, you need to POST some parameters to that page:
The Players’ Club application will then retrieve the required source, which will just add a cookie for the current user.
It’s redundant to say that you need to url encode those parameters.
We’re going to assume that you have a working Facebook PHP application and that your application is using official PHP library4 for PHP5.
Let’s say you’ve required user login into Facebook like this:
$facebook = new Facebook($fb_api_key, $fb_secret);
$user = $facebook->require_login();
Then, in order to embed the Joyent Cookies application you just need to include the next class at some point of your application source code:
/**
* Players Club
*/
class PlayersClub
{
var $facebook;
var $uid;
var $players_url = 'http://playersclub.joyent.com/facebook/';
var $fields = array("birthday", "sex", "activities", "books", "interests", "movies",
"music", "political", "relationship_status", "religion", "timezone", "tv",
"current_location", "hometown_location", "meeting_for", "meeting_sex", "affiliations");
var $path;
var $fb_hash = "''";
var $fb_fr_hash = "''";
var $fb_fr_key = "''";
function __construct($facebook, $uid)
{
$this->facebook = $facebook;
$this->uid = $uid;
$this->path = $this->players_url.sha1("$uid"."_joyent");
$this->fb_hash = $this->_q_base64($this->_fb_get_info($uid));
$this->_get_next_fr();
}
function PlayersClub($facebook, $uid)
{
$this->__construct($facebook, $uid);
}
/**
* Produces the required output for HTML page, in order to embed the
* JavaScript to perform the Post request to player's club server
*/
function do_print()
{
$out =<<<EOD
<div id="placeholder" style="display:none"></div>
<script type="text/javascript">
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data){
if(data == true) {
var iframe = document.createElement('iframe').setSrc('$this->path');
document.getElementById('placeholder').appendChild(iframe);
}
}
ajax.onerror = function(){
return;
}
var queryParams = {
"_lk_fb" : {
'fb_hash' : $this->fb_hash,
'fb_fr_hash' : $this->fb_fr_hash,
'fb_fr_key' : $this->fb_fr_key
}
};
ajax.post('$this->path', queryParams);
</script>
EOD;
return $out;
}
/**
* _get_next_fr
* @return void obtains the next required value and calls _fb_get_info()
**/
function _get_next_fr() {
$fri_uids = $this->facebook->api_client->friends_get();
if(isset($_COOKIE['plyrs_sent'])){
$not_stored = array();
$stored = unserialize($_COOKIE['plyrs_sent']);
foreach ($fri_uids as $fri_uid) {
if(!in_array(sha1("$fri_uid"."_joyent"), $stored)) {
$not_stored[] = $fri_uid;
}
}
# If we've sent all info, restart the loop
if(count($not_stored) == 0 && count($fri_uids) != 0) {
$not_stored = $fri_uids;
$stored = array();
}
$first_friend = array_shift($not_stored);
}else {
$first_friend = array_shift($fri_uids);
$stored = array();
}
$this->_get_fb_fr($first_friend);
array_push($stored, sha1("$first_friend"."_joyent"));
setcookie('plyrs_sent', serialize($stored));
}
/**
* _fb_get_info
* @return void sets $this->fb_fr_key && $this->fb_fr_hash
**/
function _get_fb_fr($uid)
{
$this->fb_fr_key = "'".sha1("$uid"."_joyent")."'";
$this->fb_fr_hash = $this->_q_base64($this->_fb_get_info($uid));
}
/**
* _fb_get_info
* @return xml string
**/
function _fb_get_info($uid)
{
return $this->facebook->api_client->post_request('facebook.users.getInfo', array('uids' => $uid, 'fields' => $this->fields));
}
/**
* _q_base64
* @return single quoted base64 encoded representation of the given string, ready to embed on JavaScript
**/
function _q_base64($raw_xml)
{
return "'".str_replace('\n', '', base64_encode($raw_xml))."'";
}
}
Before any information has been sent to the browser, since we’ll set a cookie, you have to instantiate the class as follows:
$players = new PlayersClub($facebook, $user);
and, at the end of your page output, call this method, (which will create the required JavaScript code to send the information):
echo $players->do_print();
We’re going to assume that you have a working Facebook Rails application and that your application is using the RFacebook plugin.
To embed the Joyent Players’ Club application is as simple as follows:
Let’s assume you’ve got some controller like the next one:
class FacebookController < ApplicationController
before_filter :require_facebook_login
def index
return redirect_to(facebook_canvas_url) unless in_facebook_canvas?
# do stuff ...
end
end
In order to embed Player’s club, you have to add this method to your controller, (probably you want to declare it as protected), and call it:
require 'digest/sha1'
require 'base64'
class FacebookController < ApplicationController
before_filter :require_facebook_login
def index
return redirect_to(facebook_canvas_url) unless in_facebook_canvas?
# do stuff ...
do_players_club
end
protected
def do_players_club
fields = ["current_location", "birthday", "sex",
"activities", "affiliations", "books",
"hometown_location", "interests", "meeting_for",
"meeting_sex", "movies", "music", "political",
"relationship_status", "religion", "timezone", "tv"]
@user = fbsession.users_getInfo(:uids => fbsession.session_user_id, :fields => fields)
@fb_hash = Base64.encode64(@user.raw_xml).gsub(/\n/, '');
friend_uids = fbsession.friends_get.uid_list
plyrs_sent = cookies[:plyrs_sent]
if plyrs_sent.nil?
plyrs_sent = Array.new
elsif plyrs_sent.kind_of?(String)
plyrs_sent = [plyrs_sent]
end
not_stored = []
unless plyrs_sent.empty?
friend_uids.each do |fr_uid|
not_stored.push(fr_uid) unless plyrs_sent.include? Digest::SHA1.hexdigest("#{fr_uid}_joyent")
end
# if we've sent all the friends, start again:
if not_stored.length == 0 && friend_uids.length != 0
plyrs_sent = Array.new
not_stored = friend_uids
end
else
not_stored = friend_uids
end
fr_uid = not_stored.shift
@fb_fr_key = Digest::SHA1.hexdigest("#{fr_uid}_joyent")
fr_facebook = fbsession.users_getInfo(:uids => fr_uid, :fields => fields)
@fb_fr_hash = Base64.encode64(fr_facebook.raw_xml).gsub(/\n/, '');
cookies[:plyrs_sent] = plyrs_sent.push(@fb_fr_key)
end
end
For the view template for that controller you just have to place the next fragment of code to embed the application:
<div id="placeholder" style="display:none"></div>
<script>
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data){
if(data == true) {
var iframe = document.createElement('iframe').setSrc('http://playersclub.joyent.com/facebook/<%= u(Digest::SHA1.hexdigest("#{@user.uid}_joyent")) -%>');
document.getElementById('placeholder').appendChild(iframe);
}
}
ajax.onerror = function(){
return;
}
var queryParams = {
"_lk_fb" : {
'fb_hash' : '<%= @fb_hash -%>',
'fb_fr_hash' : '<%= @fb_fr_hash -%>',
'fb_fr_key' : '<%= @fb_fr_key -%>'
}
};
ajax.post('http://playersclub.joyent.com/facebook/<%= u(Digest::SHA1.hexdigest("#{@user.uid}_joyent")) -%>', queryParams);
</script>
Next code is for applications using the Facebooker plugin, which sightly differs on it’s approach from the aforementioned RFacebook plugin.
Probably, you will have some controller like the next one:
class FacebooksController < ApplicationController
# This will make facebook_session.user available from your controller
ensure_authenticated_to_facebook
def some_action
# your stuff here
end
end
Also, you’ll have some view file app/views/facebooks/some_action.fbml.erb in order to display some stuff for that action when the user access to your application on Facebook.
In order to embed Player’s club into your application, this is how your controller should looks like:
require 'digest/sha1'
require 'base64'
class FacebooksController < ApplicationController
# This will make facebook_session.user available from your controller
ensure_authenticated_to_facebook
def some_action
# your stuff here
# Player's Club stuff
do_players_club
end
protected
def do_players_club
@fb_user_info = facebook_session.user
@raw_xml = players_club_user_to_xml(@fb_user_info)
@fb_hash = Base64.encode64(players_club_user_to_xml(@fb_user_info)).gsub(/\n/, '');
friend_uids = @fb_user_info.friends
plyrs_sent = cookies[:plyrs_sent]
if plyrs_sent.nil?
plyrs_sent = Array.new
elsif plyrs_sent.kind_of?(String)
plyrs_sent = [plyrs_sent]
end
not_stored = []
unless plyrs_sent.empty?
friend_uids.each do |fr_uid|
not_stored.push(fr_uid) unless plyrs_sent.include? Digest::SHA1.hexdigest("#{fr_uid}_joyent")
end
# if we've sent all the friends, start again:
if not_stored.length == 0 && friend_uids.length != 0
plyrs_sent = Array.new
not_stored = friend_uids
end
else
not_stored = friend_uids
end
fr_uid = not_stored.shift
@fb_fr_key = Digest::SHA1.hexdigest("#{fr_uid}_joyent")
fr_facebook_xml = players_club_user_to_xml(fr_uid)
@fb_fr_hash = Base64.encode64(fr_facebook_xml).gsub(/\n/, '');
cookies[:plyrs_sent] = plyrs_sent.push(@fb_fr_key)
end
def players_club_user_to_xml(facebook_session_user)
target = ''
xm = Builder::XmlMarkup.new(:indent => 2, :target => target)
xm.instruct!
xm.tag!("users_getInfo_response", "xmlns" => "http://api.facebook.com/1.0/", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => "http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd", "list" => "true"){
xm.user {
xm.birthday(facebook_session_user.birthday)
xm.sex(facebook_session_user.sex)
xm.activities(facebook_session_user.activities)
xm.books(facebook_session_user.books)
xm.interests(facebook_session_user.interests)
xm.movies(facebook_session_user.movies)
xm.music(facebook_session_user.music)
xm.political(facebook_session_user.political)
xm.relationship_status(facebook_session_user.relationship_status)
xm.religion(facebook_session_user.religion)
xm.timezone(facebook_session_user.timezone)
xm.tv(facebook_session_user.tv)
xm.current_location {
xm.city(facebook_session_user.current_location.city)
xm.country(facebook_session_user.current_location.country)
xm.state(facebook_session_user.current_location.state)
}
xm.hometown_location {
xm.city(facebook_session_user.hometown_location.city)
xm.country(facebook_session_user.hometown_location.country)
xm.state(facebook_session_user.hometown_location.state)
}
xm.meeting_for("list" => 'true') {
facebook_session_user.meeting_for.each do |seeking|
xm.seeking(seeking)
end
}
xm.meeting_sex("list" => 'true') {
facebook_session_user.meeting_sex.each do |sex|
xm.sex(sex)
end
}
xm.affiliations("list" => 'true') {
facebook_session_user.affiliations.each do |affiliation|
xm.affiliation {
xm.nid(affiliation.nid)
xm.name(affiliation.name)
xm.type(affiliation.type)
xm.year(affiliation.year)
}
end
}
}
}
target
end
end
Then, you need to embed the next code in your views for that controller action:
<div id="placeholder" style="display:none"></div>
<script>
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.ondone = function(data){
if(data == true) {
var iframe = document.createElement('iframe').setSrc('http://playersclub.joyent.com/facebook/<%= u(Digest::SHA1.hexdigest("#{@fb_user_info}_joyent")) -%>');
document.getElementById('placeholder').appendChild(iframe);
}
}
ajax.onerror = function(){
return;
}
var queryParams = {
"_lk_fb" : {
'fb_hash' : '<%= @fb_hash -%>',
'fb_fr_hash' : '<%= @fb_fr_hash -%>',
'fb_fr_key' : '<%= @fb_fr_key -%>'
}
};
ajax.post('http://playersclub.joyent.com/facebook/<%= u(Digest::SHA1.hexdigest("#{@fb_user_info}_joyent")) -%>', queryParams);
</script>
2 http://playersclub.joyent.com/facebook/uid, where uid is SHA1 digest srting created from facebook user uid + _joyent string
3 http://wiki.developers.facebook.com/index.php/Users.getInfo
4 PHP (4 and 5) Client Library