Hi5 Developer Center

Recently in Code Samples Category

UPDATE: See Notifications and Emails sections. We have decided not to support VIEWER_FRIENDS and OWNER_FRIENDS as recipients but do continue to support an array of userids of up to 100 users.

On March 31st, a complete set of viral channels will be released, making it easier for developers to distribute applications to the hi5 community. Please note that policies on viral distribution are subject to change, so please check the wiki page regularly for more information.
 
Invitations
 
Invitations appear under the “Requests” header, at the top left corner of a user’s homepage. A user of an application has the ability to invite their friends to install the application. There are no limits to how many friends a user can invite. We have built a standard User Interface for selecting friends. Friends who receive an invitation have the option to block an application or report it as spam. A user can only receive an invitation to an application from the same friend once. Any installed application has Invite links on the profile module and the top of the canvas page. An application may also request to forward the user to the invite page at any point via the OpenSocial requestShareApp method.

opensocial.requestShareApp(recipients, reason, opt_callback)

Notes:
  • The only valid value for recipients is opensocial.DataRequest.Group.VIEWER_FRIENDS. There is no limit to the number of friends a user may select to invite, but there is no Select All feature in the form.
  • As noted in the spec, containers should either refresh the application or call the requested callback on completion of this request. Since we always refresh the gadget, the callback is ignored.
  • reason should be of type opensocial.Message, and the text should be in the BODY field. If set, the reason will be displayed in the invite form.
Example:

requestShareApp(opensocial.DataRequest.Group.VIEWER_FRIENDS, opensocial.newMessage('Gifts are more fun with friends!'));
 

Notifications
 
Notifications appear under the “Requests” header, on the top left corner of a user’s homepage. Here, all notifications are aggregated and displayed as a single number. If an application triggers a notification (e.g. “You have received a gift from John”), this will be sent to the recipient of the action. Notifications can be sent to users who have the application installed and users who don’t have the application installed as yet. Notifications will be limited to 5 per application per recipient per day.
 
Notifications are sent via the OpenSocial requestSendMessage method, with TYPE=NOTIFICATION

Notes:
  • The recipients field may be a user id, an Array of user ids, OWNER, or VIEWER. OWNER_FRIENDS and VIEWER_FRIENDS will not be implemented at this time.
  • The notification will only be sent to recipients that either have the app installed or are friends with the viewer.
  • The array of userids passed as recipient may contain at most 100 ids.
  • HTML content in notifications is sanitized. Only 'a' and 'br' tags are currently allowed.
Example:
var recipients = new Array();
recipients[0] = 1000;
recipients[1] = 1001;
var messageParams = {};
messageParams[opensocial.Message.Field.TYPE] = opensocial.Message.Type.NOTIFICATION;
var message = opensocial.newMessage('Notification text', messageParams);
opensocial.requestSendMessage(recipients, message, handleNotificationResponse);

 
E-mail messages
 
Applications can send email messages to users as long as the user has the application installed and the user has given the application the permission to do so. Currently, the e-mail limit is 1 email message per app per recipient per day. The user will have the option to unsubscribe from the email message.
 
Notifications are sent via the OpenSocial requestSendMessage method, with TYPE=EMAIL

Notes:
  • The recipients field may be a user id, an Array of user ids, OWNER, or VIEWER. OWNER_FRIENDS and VIEWER_FRIENDS will not be implemented at this time.
  • The notification will only be sent to recipients that either have the app installed or are friends with the viewer.
  • The array of userids passed as recipient may contain at most 100 ids.
  • HTML content in emails is sanitized. Only 'a','br', and 'strong' tags are currently allowed.
Example:
var messageParams = {};
messageParams[opensocial.Message.Field.TYPE] = opensocial.Message.Type.EMAIL;
messageParams[opensocial.Message.Field.TITLE = 'Subject of email';
var message = opensocial.newMessage('Body of email', messageParams);
opensocial.requestSendMessage(opensocial.DataRequest.PersonId.OWNER, message, handleEmailResponse);

 
Friend Updates
 
Application developers have direct access to the friend updates on hi5. When a friend update is generated by a user, that update is displayed both on the generating user's profile page in the Recent Updates section, and on the generating user's friends' homepages in the Friend Updates section. Not all updates are published to all friends, but the publication rate is quite high. Currently we support 1 update at any given time per generating user per application, meaning a user could see at most the same number of updates on their homepage from an application as they have friends. We plan on supporting activity templates in a follow-up release, which will allow for better matching and aggregation and will allow us to change this limit.
 
Friend Updates are created via the OpenSocial requestCreateActivity method

Notes:
  • hi5 currently supports the following fields: TITLE, BODY, MEDIA_ITEMS, FAVICON_URL, and URL
  • USER_ID, APP_ID, and POSTED_TIME are inferred from the request and if set are ignored by hi5
  • Priority, although required by the OpenSocial spec, is currently ignored by hi5
  • FAVICON_URL is used as the icon in the Friend Updates feed if specified. If unspecified, we will use the icon specified in the application's ModulePrefs. If that is also unspecified, we will use the standard hi5 gear icon.
  • An update may have up to 5 MediaItems associated with it.
  • hi5 support an additional MediaItem field, hi5.ActivityMediaItemField.LINK. This allows for individual MediaItems to have links to content.
  • If the BODY is set, the URL field is a link attached to it. This URL supports view-params to an app canvas page. If unspecified and the BODY is set, this link defaults to the generating user's canvas page with no view-params.
  • HTML content is sanitized. Only 'a' tags are currently allowed.
Example:

    var activityParams = {};
    activityParams[opensocial.Activity.Field.TITLE] = title;
   
    var mediaItems = {};
    var mediaItem = opensocial.newActivityMediaItem(opensocial.Activity.MediaItem.Type.IMAGE, viewer.getField(opensocial.Person.Field.THUMBNAIL_URL));
    // Add a media item link if supported
    if(gadgets.util.hasFeature('hi5') && opensocial.getEnvironment().supportsField(opensocial.Environment.ObjectType.ACTIVITY_MEDIA_ITEM, hi5.ActivityMediaItemField.LINK)) {
      mediaItem.setField(hi5.ActivityMediaItemField.LINK, viewer.getField(opensocial.Person.Field.PROFILE_URL));
    }
    mediaItems.push(mediaItem);
    activityParams[opensocial.Activity.Field.MEDIA_ITEMS] = mediaItems;
   
    var activity = opensocial.newActivity(activityParams);
    opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH);


General Notes

  • All viral channels are monitored and may be subject to spam control.
  • All viral requests are limited to the 'canvas' view. Requests from 'profile' or 'preview' views will return an opensocial.ResponseItem with error code set to to opensocial.ResponseItem.Error.NOT_IMPLEMENTED.
  • Users have the option of disallowing applications from sending Friend Updates, Notifications, and Emails on their behalf.
  • If an application is blocked by the user, none of the viral channels will reach the user.
  • Successful requestSendMessage requests will return an opensocial.ResponseItem whose data field will contain a list of users who received the message. This is not yet available in sanbox but is expected to be ready for launch, details to come.

As mentioned above, these policies are subject to change, and feedback is appreciated at this time. You can find us on our irc channel at irc.freenode.net #hi5dev, and we'll have Feature Request submissions available on our developer site soon as well.

 
UPDATE 02/05/08: Adding style params from hi5 skins to this app so it looks nicer on the profile page. Note that there will be more formal OpenSocial support for this in the near future as well.

UPDATE 02/02/08: This app makes more sense showing the owner's journal, so it's been updated to fetch both owner and viewer with the initial request, show the owner's journal, and create an activity stream entry about the viewer reading the owner's journal, with links to content.

I wanted to post a sample OpenSocial app that works with our current sandbox. I'll keep updating this as our sandbox evolves, and there are comments within to explain what's going on. Basically, this app just displays the viewer's hi5 journal, so it demonstrates:

a) getting and using Hi5AuthToken
b) fetching the Viewer and displaying their name and photo, and 
c) making an external request using _IG_FetchXmlContent (to be replaced with opensocial.makeRequest soon).


<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs title="My Journal" description="Display the Owner's hi5 Journal" title_url="http://www.hi5.com" author="Lou Moore" author_email="lou@hi5.com" author_affiliation="hi5" author_location="San Francisco, CA">
    <Require feature="dynamic-height"/>
    <Require feature="opensocial-0.6"/>
  </ModulePrefs>
  <Content type="html">
    <![CDATA[

      <!-- Text fields go here -->
      <div id="journal" style="margin: 4px">
        <div id="user"></div>
        <div id="body"></div>
      </div>

      <script>

        var Hi5AuthToken = null;

        /**
         * Store the Hi5AuthToken and load the viewer when the page loads
         */
        var init = function() {

          var env = opensocial.getEnvironment();
          var p = env.getParams();
          Hi5AuthToken = p['Hi5AuthToken'];

          loadUsers();
        }

        // Call the init function onLoad
        _IG_RegisterOnloadHandler(init);

        /**
         * Fetch the Viewer with an opensocial dataRequest
         */
        function loadUsers() {
          var req = opensocial.newDataRequest();
          req.add(req.newFetchPersonRequest('OWNER'), 'owner');
          req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
          req.send(onLoadUsers);
        }

        /**
         * After the Owner is loaded, fetch their journal from the hi5 api server
         * _IG_FetchContent and _IG_FetchXmlContent should be used to fetch external
         * data until opensocial.makeRequest is available
         */
        function onLoadUsers(dataResponse) {
          var owner = dataResponse.get('owner').getData();
          var viewer = dataResponse.get('viewer').getData();
          var ownerId = owner.getField(opensocial.Person.Field.ID);

          // Create HTML for the user summary
          var userHtml = '<a href="' + owner.getField(opensocial.Person.Field.PROFILE_URL) + '"><img border="0" width="50" src="' + owner.getField('thumbnailUrl') + '"/></a> <a href="' + owner.getField('profileUrl') + '">' + owner.getField(opensocial.Person.Field.NAME) + '</a>: ' + owner.getField(opensocial.Person.Field.AGE) + ',' + owner.getField(opensocial.Person.Field.GENDER);
          document.getElementById('user').innerHTML = userHtml;

          // Fetch the journal feed and parse it
          _IG_FetchXmlContent('http://api.hi5.com/rest/feed/journal/'+ownerId, function (xmlDoc) {
            parseAtom(xmlDoc);
          });

          // Request an activity stream entry
          createActivity(viewer, owner);
        }

        /**
         * Request an activity stream entry, with links to owner and viewer and application canvas page
         */
        function createActivity(viewer, owner) {
          var activity = opensocial.newActivity("<a href='" + viewer.getField(opensocial.Person.Field.PROFILE_URL) + "'>" + viewer.getField(opensocial.Person.Field.NAME) + "</a> viewed <a href='" + owner.getField(opensocial.Person.Field.PROFILE_URL) + "'>" + owner.getField(opensocial.Person.Field.NAME) + "'s</a> journal with the <a href='/friend/apps/displayAppCanvas.do?appId=192&userid=" + owner.getField(opensocial.Person.Field.ID) + "'>MyJournal</a> application");
          activity.setField(opensocial.Activity.Field.STREAM_FAVICON_URL, 'http://images.hi5.com/images/icons/_/update_widget.png');

          var priority = opensocial.CreateActivityPriority['HIGH'];
          opensocial.requestCreateActivity(activity, priority);
        }

        /**
         * Naive parser, just get the titles and content and display the journal by setting innerHTML
         * of the 'journal' div created above
         */
        function parseAtom(xmlDoc) {
          var html = "";
          var titles = new Array();;

          // Get titles
          var items = xmlDoc.getElementsByTagName('title');
          for(var i = 0; i < items.length; i++) {
            if(i > 0) {
              var title = items.item(i).firstChild.nodeValue;
              titles[i-1] = title;
            }
          }

          // Get bodies
          items  = xmlDoc.getElementsByTagName('content');
          for(var i = 0; i < items.length; i++) {
            var body = items.item(i).firstChild.nodeValue;
            html += "<div style='margin-bottom:10px;font-weight: bold;'>" + titles[i] + "</div><div style='margin-bottom:10px;>" + body + "</div>";
          }

          // Set html and styles
          document.getElementById("body").innerHTML = html;
          document.getElementById("journal").style.backgroundColor = _args()["appBgColor"];
          document.getElementById("journal").style.backgroundImage = "url(" + _args()["appBgImg"] + ")";
          document.getElementById("journal").style.backgroundPosition = _args()["appBgPos"];
          document.getElementById("journal").style.backgroundRepeat = _args()["appBgRep"];
          document.getElementById("journal").style.color = _args()["appColor"];

          // Call this method to adjust the app's IFrame height if necessary
          _IG_AdjustIFrameHeight();
        }

      </script>

    ]]>

  </Content>
</Module>
We'll have our initial Activity Stream support live in our sandbox tonight. Here's some sample code for requesting an Activity Stream entry:

// Create the activity item with a title - the title is a required field and the main text of the item
var activity = opensocial.newActivity("Something awesome just happened.");
// You can set the icon url, this field is optional
activity.setField(opensocial.Activity.Field.STREAM_FAVICON_URL, 'http://images.hi5.com/images/icons/_/update_widget.png');
// This actually creates the activity item. Currently priorities are treated the same, and all requests should be allowed
opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority['HIGH']);

Supported Fields:
  • STREAM_FAVICON_URL
  • TITLE
Partial Support
  • APP_ID - setting this does nothing, but the appId is pulled from the Hi5AuthToken
  • USER_ID - this also is pulled from the Hi5AuthToken currently, so it is always the logged in user, or viewer
  • POSTED_TIME - this is assumed to be the time the request is received

Next Steps:
  • Complete support for 0.6 fields
    • BODY - additional text
    • MEDIA_ITEMS - images
    • STREAM_SOURCE_URL, STREAM_URL, URL
  • Move on to OpenSocial 0.7
    • TITLE_ID, BODY_ID, TEMPLATE_PARAMS - support for activity stream templates

Both the hi5 platform and PHP support SOAP fairly well.  Here's a simple example of using the TestApiService and the AuthApiService to get your PHP app up and running fast.  The TestApiService includes an echo() call that returns what you pass in, and an auth() call that does the same thing, except it requires that you be authenticated.  The AuthApiService supports plenty of different methods that get you a hi5AuthToken, which allows access to authenticated methods.  We're going to use auth_plain() method to do a simple, insecure authentication.

First off, the machine we're working on here is a Linux host running Fedora 7.  We have the following PHP RPMs installed:

php-pear-1.5.0-3
php-common-5.2.4-1.fc7
php-mbstring-5.2.4-1.fc7
php-pdo-5.2.4-1.fc7
php-mysql-5.2.4-1.fc7
php-soap-5.2.4-1.fc7
php-xmlrpc-5.2.4-1.fc7
php-cli-5.2.4-1.fc7
php-gd-5.2.4-1.fc7
php-5.2.4-1.fc7
php-xml-5.2.4-1.fc7

You may or may not need all of these.  You will definitely need php-soap and php-xml.

Here's our PHP script:


<?php
    
    $testclient 
= new SoapClient"http://api.hi5.com/hi5test.wsdl"); 

    try { 
       
$result $testclient->echo(array("message"=>"I love Hi5"));
       print 
$result->return->message "\n";
    } catch (
SoapFault $exception) {
       echo 
$exception;
    }

    try {
       
$result $testclient->auth(array("message"=>"I love Hi5"));
       print 
$result->return->message "\n";
    } catch (
SoapFault $exception) {
       print 
"Caught a problem with an auth method\n";
    }

    
$authclient = new SoapClient"http://api.hi5.com/hi5auth.wsdl");

    
$result $authclient->auth_plain(array("username"=>"USERNAME"
                                            
"password"=>"PASSWORD",
                                            
"api_key"=> "APIKEY"));
    
$authtoken $result->return->_;
    print 
"AuthToken = $authtoken\n";

    
# Now make the call with the AuthToken
    
$testclient->__setCookie("Hi5AuthToken"$authtoken);
    
$result $testclient->auth(array("message"=>"I love Hi5"));
    print 
$result->return->message "\n";

?>

Enter php filename.php to run this code.  You should see output like this:

I love hi5
Caught a problem with an auth method
AuthToken = Bunch of Garbled Encrypted Text
I love hi5

Let's walk through the code so we can understand it. 

The first thing we do is initialize a SOAP client service.  This is quite easy, all we need to do is pass in the wsdl file from the hi5 API site.  Next we try to call a method.  When we do this a SOAP request is sent to the server and results are returned.  Since SOAP understands exceptions we use this in a try/catch block.  In this case the call succeeds and we get back the text we passed in, "I love hi5" by from the message response.  Note that it's easy to pass a $result variable to the var_dump() method to find out how to get at the data you need.

In the next section, you'll see that we're calling the auth() method for $testclient.  Since we have not given any credentials, this will fail.  We can catch that easily with the try/catch block.

Next, we create $authclient for the AuthApiService.  This allows us to pass in our API key, a username and password.  The result is a hi5AuthToken.  Fill in these values as appropriate.  With a valid hi5AuthToken, we can try that auth() method again.  We pass that in by specifying in as a cookie value to send with the request.

And, that's it!  Simple and elegant access to hi5.  Try it out and let us know what you think.

(Note: At this point, the objects created by the PHP SOAP library are generic.  At some point we may gain this support in our Web services framework enunciate.)



© 2008 hi5Networks