Wednesday, November 28, 2007

OpenSocial Activity Posting

NOTE: This code and post was written for an older version of Opensocial. I make no guarantees as to it's validity in later versions.

There are four APIs to opensocial: Javascript, Activities, People, and Persistence. The last three haven't been released yet, but the Javascript one already implements some of the features that they will support. For example. the People API will let you retrieve a specific person, or a specific person's friends. That can already be done (mostly, you can't get a person by ID yet) in the Javascript API. I ran through what could be done with people pretty quickly, and was able to get a demo up using persistence as well, but activities have been puzzling me.


The Activities Data API describes how you will be able to create, retrive, update, and delete activities. That sounds sweet. Except for the fact that right now, with the Javascript API, the only thing you can do is create activities. Even doing that is kind of confusing, so I'm going to go through what I've learned so far.

Before you can even think about creating an event, you have to create a stream. You do this with opensocial.newStream. The first parameter, folder, has apparently already been deprecated, so I've just been putting "null" for it. Title, the second parameter, is apparently the title of the stream (real big surprise.) I've done some tests, and if you use newStream with the title of an already existing stream, it still creates a new stream. I'm not sure what it does to the old stream, but activities that have already been posted to a person's update feed aren't removed. The tests were part of a demo app I'm working on, so they're not in their own test apps. Once I get them seperated, I'll post a link to them. Finally, you can post a map of optional parameters. Right now, the only two fields that interest me are USER_ID, and FAVICON_URL. I haven't tested FAVICON_URL yet, to see how well it works, but USER_ID got me really excited. When I was first working with the activities, I thought that I could only post updates to my own update feed (which is sort of redundant, but it is the default if no USER_ID is specified.) All you have to do is specify the USER_ID, and any activities posted to that stream will go on that user's update feed. SO, here's the line of code that I use to create my stream.


var activitystream = opensocial.newStream(null, title, { "USER_ID": friendId });
"title" is a variable containing whatever I want the stream to be titled. "friendId" contains the id of the friend whose feed the activities will be posted to.


Alright then, the stream is set up. Now you get to create the event. That's accomplished with opensocial.newActivity. It has three parameters as well. The first one, stream, is the stream variable you just set up. The second, title, is the most important. It is what will show up on the update feed. Also, since the optional parameters don't seem to be doing jack at the moment, it's ALL the person who recieves this activity will see. Here's how you set up the activity.


var activity = opensocial.newActivity(activitystream, text_to_display, null)

I just leave opt_params as null, since they're pretty useless now.


Almost done! You've set up the stream and the activity, and even told the activity what stream it's going to be posted to. Now, all you have to do is let it loose. This is done using the opensocial.requestCreateActivity method. It has, beleive it or not, THREE PARAMETERS. The first is the activty variable, which has the stream variable, which swallowed the fly...etc. The second is the "priority" of the posting. There are only two options (at least at the moment), opensocial.CreateActivityPriority.HIGH, and opensocial.CreateActivityPriority.LOW. HIGH means that if the stream you wrote to doesn't exist, the activity will still be posted. If you choose LOW, and the stream doesn't exist, the activity will not be posted. Supposedly, there is a chance that using HIGH will navigate away from the current page (your opensocial gadget,) but I've never had that happen to me, and I've only been using HIGH. The third parameter is a function to be called when the activity has been posted. It's optional, but I've been using it to verify that the operation completed. Here's the last line of code you need.


opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH, callbackFunction);


There you have it, the longest explanation of three lines of code ever. ;-P At least now you can post updates to your friend's update feeds. One other little caveat I should mention, if the title of the activity is identical to another activity in the same stream, it will not be re-posted. My guess is that changing the opt_params might allow this to happen, but I haven't tested it yet.

As far as programmatically accessing streams/activities, I'm totally scoobied at the moment. After I post this, I'm going to check the DataRequest methods, and see how much I can/can't do with them, but for now, I'll leave you with being able to post activities. Catch youse later.

Monday, November 26, 2007

OpenSocial Browser Incompatability

NOTE: This code and post was written for an older version of Opensocial. I make no guarantees as to it's validity in later versions.

Just a quick note: I'm going to set a goal for myself to do at least one blog post per week. It will be of a decent length, and not filler in any way, shape, or form. One of my biggest dislikes of the blogosphere is that people post the most useless stuff. I'm going to do my best to avoid it, but if I start sliding, someone let me know, please.


Back to the topic at hand...


I've been working with Google's new OpenSocial Framework recently (
more info), which is a social networking framework that can be impelemented by social networking sites to provide cross-platform support for developers, making things a lot easier for third-party social app developers. There's one big glitch, though. It doesn't work on all browsers. I did some initial research on the topic, and was asked by Google to open a group dedicated to finding and documenting these differences (look here). The basic jist is this: Firefox and Opera work fine, IE and Safari don't. Safari asks for access to something in google's domain (which users/developers don't have access too,) and IE has something going on with it's requests.


In all the attempts that I made, any data request made from IE came back with a 401 Unauthorized Error. So I looked at the request made (using
Fiddler, which is a great piece of software). So here's what I found in a request for the information about the viewer of a page.


IE Request:

POST /46/o/api/json HTTP/1.1
Accept: */*
Accept-Language: en-us
Referer:
http://64b409ht-a.gmodules.com/ig/ifr?url=http://www.cs.drexel.edu/~asc38/Google/Test6.xml&parent=http://sandbox.orkut.com&lang=en-US&country=US&synd=orkut&mode=canvas&nocache=2147483647&mid=0&h=200#st=AFinprSFNk0cx-EYLjFu4KnGC8ErtahjWjnpbuHHWFEYTpx2pp2zBPW-N1gC-xtto2aB3gq7RW_B4wcDS1GzSkXNRoJrD0ScvjxAEhcmWl0_LvGe1TyJDm0&gadgetId=06080089800194424967&gadgetViewer=09795457263253596479&gadgetOwner=09795457263253596479&nocache=2147483647
Content-Type: application/x-www-form-urlencoded;charset=utf-8
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.5.20706; .NET CLR 3.0.590)
Host: 64b409ht-a.gmodules.com
Content-Length: 190
Proxy-Connection: Keep-Alive
Pragma: no-cache
req=%5B%7B%22key%22%3A%22viewer%22%2C%22request%22%3A%7B%22type%22%3A%22FETCH_PERSON%22%2C%22parameters%22%3A%7B%22id%22%3A%22VIEWER%22%2C%22profileDetail%22%3A%22basic%22%7D%7D%7D%5D&out=js


Looks pretty standard, huh? The body has a value named req, which appears to have some of the request data. There's also a decent bit in the referrer header as well. For some reason, however, this gets the 401 error. Let's check out the Firefox request, and see what the difference might be.


Firefox Request:
POST /46/o/api/json HTTP/1.1
Host: 64b409ht-a.gmodules.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Referer: http://64b409ht-a.gmodules.com/ig/ifr?url=http://www.cs.drexel.edu/~asc38/Google/Test6.xml&parent=http://sandbox.orkut.com&lang=en-US&country=US&synd=orkut&mode=canvas&nocache=2147483647&mid=0&h=200
Content-Length: 313
Pragma: no-cache
Cache-Control: no-cache
req=%5B%7B%22key%22%3A%22viewer%22%2C%22request%22%3A%7B%22type%22%3A%22FETCH_PERSON%22%2C%22parameters%22%3A%7B%22id%22%3A%22VIEWER%22%2C%22profileDetail%22%3A%22basic%22%7D%7D%7D%5D&st=AFinprR418rXG6TALrKsP6Ad_U1xE3E7z2_F22lrqaGoNvFN2NpWE7zB6-nqW69Zy9W-sgP8QNvSu7aTXe_ZfeSe-vBNjAvJa_BUohr6C3_l89naEvApO9s&out=js


Notice a difference? The Firefox has a lot more detail in the req value, and a bit less in the Referer. Here's a little summary of what's in where.


As far as the referers go, both browsers have the same address, url, parent, lang, country, synd, mode, nocache, and mid parameters. In fact, after mid, the firefox referer value stops. IE just keeps going, with a "#" seperator, instead of a "&". Usually, "#"s are used as an anchor to a link on the page, but that doesn't make sense on two accounts. First, this is a referer to a page, and second, because the anchor apparently has a value too. Other than the "#" sign, it appears to be assigning some sort of key value to the variable "st". Then, it even goes on to declare the value of gadgetId, gadgetViewer, gadgetOwner, and another nocache.


The req value is also a very similar story. IE and Firefox have an identical value, except that IE doesn't include the st parameter, which Firefox does. The st values are different, but I'm guessing that st stands for "state", which one would expect to change. Would the state cause a 401 error? Maybe, only Google knows.


One other interesting thing to note. In the accept header, IE just has "*/*" listed, which I assume means that it accepts all formats. That's nice, but Firefox has the following listed in the accept header "text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, image/png" (spaces added after commas by me).


I don't have any solid answers, but here's my hypothesis: the "anchor" value in the referer header of the IE request is what's doing it in. Somehow, that adds something to the request that is a no-go for OpenSocial, causing it to error out.

Tuesday, November 20, 2007

Introduction

Greetings, Blogosphere.

This is the quasi-professional blog of Aaron Chapin.

The title is taken from a quote I found on the internet.

"A computer lets you make more mistakes faster than any invention in human history - with the possible exceptions of handguns and tequila." - Mitch Radcliffe

I do not advocate violence, drinking, or either of the two in conjunction to computing, but this blog is going to be quasi-dedicated to chronicling my numerous programming mistakes, and how I fix them, so I feel the title is appropriate. I can only hope that it will be enjoyed.

-A. Chapin