Tải bản đầy đủ (.pdf) (50 trang)

Tài liệu Building OpenSocial Apps- P5 pdf

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (317.78 KB, 50 trang )

ptg
Summary
Being able to communicate securely with an external server has some huge advantages.
You can write custom Web services and host large databases.The possibilities are nearly
limitless.
There are many options out there for hosting providers.We chose Google App Engine
mainly because it is free for sites with small amounts of traffic, and free is nice.Amazon
Web Service (AWS) is a competing “cloud-computing” service that behaves differently
from GAE.With GAE you’re forced to use their Web servers and database back end, write
your code in Python or Java, and upload it all to their servers.With AWS you can pick
and choose which of their services to use and in what language you write your code.
There’s also Microsoft’s Azure, not to mention traditional Web hosting companies
from which you can rent physical servers sitting in physical racks.There’s also that spare
174 Chapter 8 OAuth and Phoning Home
Figure 8.3 Example of Canvas surface link on a user’s Profile
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
computer you have sitting in your closet, but that probably can’t handle too many
concurrent users (see Chapter 13, Performance, Scaling, and Security, to learn how to
scale your app).
Before deciding on a service, it’s best to shop around and do some research. See
what’s easiest, and possibly cheapest, for your new app.Whatever you choose, use the
basic principles outlined in this chapter to safely communicate between MySpace and
your hosting service.
Note
Code listings and/or code examples for this chapter can be found on our Google Code
page under .
Summary 175
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.


ptg
This page intentionally left blank
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
9
External Iframe Apps
This chapter is essentially an extension of the preceding one. In Chapter 8 we discussed
several elements of OAuth that are relevant to this chapter and to writing external
iframe apps on the MySpace platform. We recommend that if you skipped Chapter 8,
go back now and read the sections that describe OAuth.
Moving forward in this chapter, we’ll assume you’re familiar with OAuth and with
setting up and publishing Web services using Python on Google App Engine (GAE).
In this chapter we’ll take our existing on-site app and port it over to an external
iframe, or off-site, app. Be prepared, because there’s a pretty large paradigm shift from an
on-site JavaScript app to an off-site app.
With on-site apps, you supply some markup and possibly a few Web services, and the
MySpace platform takes care of the rest.Your markup is wrapped in some headers and
footers (mostly script tags that pull in the OpenSocial container) so it can be correctly
rendered. When a user accesses the page, the MySpace infrastructure takes care of the
actual rendering of the page.
When the app starts running, it has very little knowledge of the user; it really knows
only the IDs of both the Viewer and the Owner.That means that the app has to send
out requests for data when it loads—maybe it requires a friend list, or some details from
your servers.These asynchronous requests are sent out while the app idles, perhaps with
a loading message and one of those “spinner” graphics twirling away to give the illusion
of activity.When the requests come back, the app leaps into action, as it should now
have all the data it needs to fully load.
That’s the typical flow of an on-site app, but off-site apps have a very different
pattern. For an off-site app, MySpace simply renders an iframe onto the page with the

src attribute set to the URL of your choice. Since you control the contents of the
URL, you have full control over the app. But this control comes at a cost; you are now
responsible for the rendering of the app.
Off-site apps behave much more like traditional Web pages. A request comes in, then
it’s picked up by your Web server and passed off for processing to your scripting
language of choice, such as PHP,ASP.NET, or Python. The request is then processed.
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Let’s say we send off a REST request to the MySpace API for a friend list and also
pull some data out of our local database. The friend list and the data are then pushed
down onto the page used as the iframe app. In this case, the app has all the data it needs
to fully load at render time. The trade-off here is that on-site apps render immediately,
then idle while waiting for data. Off-site apps, by contrast, do their waiting for data up
front and then completely load.
The other big difference is that with on on-site apps you really have only one page.
In our Tic-Tac-Toe app we hide and show various HTML elements to give the illusion
of multiple pages. Off-site apps can have multiple actual pages, so markup and JavaScript
code can be separated a little more cleanly.Well-known techniques like clicking a button
that posts back a form can be used.
As you can see, there are some pros and cons to using an off-site app.The biggest
reason for using one would be that you have an existing app somewhere on the Web
that you could wrap an iframe around and there you go—you now have an instant
MySpace app. So, let’s dig a little deeper into what it would take to accomplish that.
REST APIs
What exactly is a “REST API”? Well, REST stands for REpresentational State Transfer,
which isn’t overly helpful as an actual definition. It essentially comes down to how
resources are accessed. The underlying assumption with REST is that objects and
records exist in one place, their universal resource identifier (URI), on the Internet and
stay there.The address is used to state the “who” of the object we wish to work with.

This is coupled with an action verb (for example, GET or POST) in the request to state
the “what” of what we wish to do.
How a REST Web Service Is Addressed
A REST Web service is addressed via URIs. Say we have a REST Web service that
returns data on fruit.To get a list of all the fruit available, we might access a URI like
this with a GET request:
/>Let’s say that Web service returns a list of available fruit, and one of the fruits listed is
apple. We might make a call like this to get a list of the types of apples available:
/>Specifically, we might want to know which local producers grow Granny Smith
apples:
/>And even more specifically, there’s an orchard down the street that we want data on.
Each producer would have a unique identifier; this one’s is 12345. We might access the
price list for that producer’s Granny Smiths via the following URI:
/>178 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
REST APIs 179
This is an example of a REST API; we access the actual data we want by addressing
the URI in a specific way and use a globally unique identifier (GUID) to drill down to
specific entities. MySpace’s APIs follow a similar pattern but replace fruit with MySpace
users, GUIDs with MySpace IDs, and price lists with friend lists.
If you are not used to using REST, this may seem a little strange and low-level, but
MySpace provides several SDKs to help you out.The beauty of having an SDK is that
just about all of this is abstracted away. You’ll see shortly how easy it is to make requests
to the MySpace APIs using an SDK.
Setting Up an External Iframe App
Now that we understand what the REST APIs are, let’s take a look at how to set up an
app on MySpace that will make use of them. Up until now, our Tic-Tac-Toe app has
used MySpace’s OpenSocial container to make requests to the API, has lived on

MySpace servers, and has been written entirely in JavaScript.
What if we had an app already written and running on a Web site and wanted to
make it a MySpace app? Would we have to completely rewrite the app in JavaScript?
And convert all of our server communication to makeRequest? That’s one possibility,
but another is to simply “iframe your app.”
What that means is that MySpace provides the ability to load in an external iframe
on the Canvas surface instead of loading in the usual MySpace-hosted iframe. Let’s
walk through what it might take to convert parts of our Tic-Tac-Toe app to an
iframe app.
First we’ll need to create a new app by following the instructions found in Chapter 1,
Your First MySpace App. Once it’s created, navigate to Edit App Source and click on the
Canvas Surface tab (it’s the default tab). Instead of selecting HTML/Javascript Source
from the radio buttons at the top, we’ll select External Iframe.
Then, inside the External IFrame URL field, enter the starting point for your app. In
our case, and as shown in Figure 9.1, it’s http://opensocial—tic-tac-toe.appspot.com/play.
When the Canvas surface for this app loads, it will load the page you entered into the
External Iframe URL field instead of loading a MySpace-hosted page. In addition, it will
append several parameters to the source of the iframe in order to pass values to your app.
An example of this would be the following:
http://opensocial—tic-tac-toe.appspot.com/play?
appid=131583&
country=us&
installState=1&
lang=en&
oauth_consumer_key=http%3A%2F%2Fwww.myspace.com%2F461572677&
oauth_nonce=633738729982017828&
oauth_signature=11LDA8y%2FTsE36vg%2BKXKfSxJrkok%3D&
oauth_signature_method=HMAC-SHA1&
oauth_timestamp=1238276198&
oauth_version=1.0&

From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
opensocial_owner_id=183399670&
opensocial_surface=canvas&
opensocial_token=H1YEBkwWjVWJLEo7n%2FVFM%2FDl1uvHTAVVfubkLWHNF1a4k9h1D6PCyLaNzTkFJ
➥AOCaxGIlluygnH2d4tuLcfbQnxbgNMN2%2FnPqp2sCZDCXt0%3D&
opensocial_viewer_id=183399670&
perm=%5B%22UT%22%2C%22UF%22%2C%22RN%22%2C%22PB%22%2C%22SN%22%2C%22%22%2C%22BI%22%
➥5D&
ptoString=COMMENTS%2CBLOG%2CBULLETINS%2CPROFILE%2CSEND_MESSAGE%2CSHARE_APP%2C
➥ACTIVITY
As you can see, our base URL, http://opensocial—tic-tac-toe.appspot.com/play, has
several query string parameters appended to it. There are some session-specific values,
such as the language and country of the current user, the user ID, and whether the user
has the app installed.The app’s ID and OAuth parameters are also passed down.This
allows you to verify the request in the same way we verified a signed makeRequest in
Chapter 8, Oauth and Phoning Home; essentially the iframe URL becomes an authenti-
cated OAuth request. We’ll discuss the opensocial_token, perm, and ptoString
parameters later in the chapter when we discuss cross-domain communication and
sending messages.
When our initial page loads, we’ll be able to determine the user’s ID, use the
MySpace SDK to fetch any data we might need from the MySpace APIs, and push the
data onto the page when it renders. Let’s implement the Play and Invite tabs of our
current Tic-Tac-Toe app.The Play tab requires the user’s Profile data, and the Invite tab
requires the user’s friend list.
180 Chapter 9 External Iframe Apps
Figure 9.1 Screen shot of the external iframe URL setup process.
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

ptg
REST APIs 181
The Server Code
Let’s go back to our code from Chapter 8 and update our app.yaml again. For reference,
you can find the Chapter 8 code in this folder:
/>application: opensocial—tic-tac-toe
version: 1
runtime: python
api_version: 1
handlers:
- url: /ws
script: ws/ws.py
- url: /play
script: play/play.py
- url: /invite
script: invite/invite.py
As you can see, we’re going to use two separate pages for the two tabs.The handlers
for each (play.py and invite.py) are very similar. Let’s take a look at invite.py in detail and
then take a quick look at play.py.
import os
import ckeynsecret
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from myspace.myspaceapi import MySpace, MySpaceError
from oauthlib import oauth
from entities import WinLoss
class Invite(webapp.RequestHandler):
def get(

self
):
id =
self
.request.get(
‘opensocial_viewer_id’
)
appid =
self
.request.get(
‘appid’
)
opensocial_token =
self
.request.get(
‘opensocial_token’
)
error = False
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
182 Chapter 9 External Iframe Apps
try:
int(id)
int(appid)
except:
error = True
ms = MySpace(ckeynsecret.CONSUMER_KEY, ckeynsecret.CONSUMER_SECRET)
ms.token = oauth.OAuthToken(
‘’

,
‘’
)
try:
friends = ms.get_friends(id)
except MySpaceError, mse:
error = True
if error:
msg =
‘Oops, there was an error, try refreshing the page!’
self
.response.out.write(msg)
return
json = simplejson.dumps(friends)
if json is None:
json =
‘{}’
template_values = {
‘friends_obj’
: json,
‘appid’
: appid,
‘ownerId’
: id,
‘opensocial_token’
: opensocial_token
}
path = os.path.join(os.path.dirname(__file__),
‘invite.html’
)

self
.response.out.write(template.render(path, template_values))
application = webapp.WSGIApplication(
[(
‘/invite’
, Invite)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ ==
“__main__”
:
main()
import ckeynsecret includes our consumer key and secret from an external file,
and we import the official MySpace SDK using from myspace.myspaceapi import
MySpace, MySpaceError
. For the request handler itself, we define only a GET
handler. Just as in our Chapter 8 code, it starts by checking the incoming user ID and
app ID to make sure they’re integers.
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
To make use of the MySpace SDK (you can download it at
and pick the language of your choice), we
need to instantiate a MySpace object. All of the API functionality will be done through
this object. To initialize the MySpace object, you need to always do the following two
things:
ms = MySpace(ckeynsecret.CONSUMER_KEY, ckeynsecret.CONSUMER_SECRET)
ms.token = oauth.OAuthToken('', '')
The first line creates the MySpace object given the consumer key and secret.The

second creates an OAuth token; the two parameters are always empty strings when
accessing the MySpace API with an OpenSocial app.
Fetching a friend list is as simple as this:
friends = ms.get_friends(id)
That’s all there is to it; the SDK should take care of the rest. Assuming no exception
was thrown, we now have the user’s friend list.The circumstances for throwing an
exception are mostly permission-related—the user might not have the app installed,
might be blocking the app, and so on.
We then get the friend list ready to be pushed down onto the page by using
simplejson.dumps(friends). We pass a total of four items down to the page: the
friend list, the app ID, the owner ID, and the OpenSocial token.
REST API List
Now that we’ve seen one of the APIs in action, let’s take a look at what other
functionality the SDKs support. Table 9.1 describes all of the endpoints supported
by the MySpace SDK as of this writing. Some of the data has been truncated for
readability, but these are mostly just long URLs. The most important part, the schema
of the data, is intact. MySpace also maintains documentation for the APIs (not the
SDKs themselves, just the bare endpoints) at />php?title=MySpace_REST_Resources.
REST APIs 183
Table 9.1 Overview of Endpoints Supported by the MySpace SDK
Function name
get_albums
Description Fetches a list of albums
Parameters <integer>user_id—the ID of the user
Sample response {
"count": 1,
"albums":
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg

Table 9.1 Continued
[{
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"photoCount": 1,
"photosUri": "http:\/\/uri_to_photos",
"privacy": "Everyone",
"defaultImage": "http:\/\/path_to_img.jpg",
"title": "My Photos",
"location": "",
"id": 542074,
"albumUri": "http:\/\/uri_to_album"
}],
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",

"userType": "RegularUser"}
}
Function name get_album
Description Fetches data for a particular album
Parameters <integer>user_id—the ID of the user
<integer>album_id—the ID of the album
Sample response {
"count": 1,
"photos":
[{
"photoUri": "http:\/\/uri_to_photo",
184 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
"smallImageUri": "http:\/\/path_to_img.jpg",
"caption": "",
"uploadDate": "4\/25\/2007 12:56:26 PM",
"lastUpdatedDate": "",
"imageUri": "http:\/\/path_to_img.jpg",
"id": 1982932,
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",

"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
}],
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
}
Function name get_friends
Description Fetches a list of friends
Parameters <integer>user_id—the ID of the user
<integer>page—the page number
<integer>page_size—the number of records to fetch
<string>list—defines how to filter the friend list; one of the
following values can be provided:
top—only the top friends
online—only friends who are currently online
app—only friends who have the app installed
<string>show—what extra data to provide for each friend; any
combination of the following values is allowed:
mood—each friend’s mood
REST APIs 185
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

ptg
Table 9.1 Continued
status—each friend’s status
online—whether or not each friend is online
Sample response {
"count": 2,
"Friends":
[
{"name": "Tom",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 6221,
"uri": "http:\/\/api.myspace.com\/v1\/users\/6221",
"webUri": "http:\/\/www.myspace.com\/tom",
"userType": "RegularUser"},
{"name": "Chris Cole",
"largeImage": "http:\/\/path_to_img.png",
"image": "http:\/\/path_to_img.png",
"userId": 45070236,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/45070236",
"webUri": "http:\/\/www.myspace.com\/ccole_myspace",
"userType": "RegularUser"}
],
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,

"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"topFriends": "http:\/\/uri_to_topfriends",
"next": "http:\/\/uri_to_next"
}
Notes The "next" URI is to aid in paging; it returns the URI to use to
retrieve the next page of friends. But since we’re using the SDK and
not manually sending out these requests, we’ll have to maintain the
186
Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
paging state the same way we did for the on-site app. An example URI
is
/>page=3&page_size=50.
Function name get_friendship
Description Given a user ID and a list of friend IDs, returns true for each ID in
the list that is a friend of the user,
false otherwise
Parameters <integer>user_id—the ID of the user
<string>friend_ids—a semicolon-delimited list of integer IDs
Sample response {
"friendship":
[{
"friendId": 6221,

"areFriends": true
}],
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
}
Notes Either the MySpace SDK or the API has a bug with this endpoint.
A semicolon-delimited list of friend IDs is required for the
friend_ids parameter. The endpoint correctly returns data if you
use just one ID, such as
6221. However, if you supply more than
one ID, such as
6221;123456;876543, the API returns a 401 error.
The error provided is “Invalid digital signature for base string.”
Luckily, this endpoint isn’t the most useful.
Function name get_mood
Description Fetches the user’s mood data
Parameters <integer>user_id—the ID of the user
Sample response {
"moodLastUpdated": "4\/12\/2009 8:32:10 PM",
REST APIs 187
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

ptg
Table 9.1 Continued
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"moodId": 56,
"mood": "curious",
"moodImageUrl":
"http:\/\/x.myspacecdn.com\/images\/blog\/moods\/

iBrads\/curious.gif"
}
Function name get_moods
Description Fetches the entire list of moods currently supported by MySpace for
the particular user
Parameters <integer>user_id—the ID of the user
Sample response {
"moods":
[
{
"moodName": "accomplished",
"moodPictureUrl": "http:\/\/path_to_img.gif",
"moodId": 90,

"moodPictureName": "chipper.gif"
},
{
"moodName": "adored",
"moodPictureUrl": "http:\/\/path_to_img.gif",
"moodId": 135,
"moodPictureName": "adored.gif"
}
]
}
Function name get_photos
Description Fetches a list of photos
188
Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
Parameters
<integer>user_id—the ID of the user
<integer>page—the page number
<integer>page_size—the number of records to fetch
Sample response {
"count": 2,
"photos":
[
{"photoUri": "http:\/\/uri_to_photo",
"smallImageUri": "http:\/\/path_to_img.jpg",
"caption": "",
"uploadDate": "4\/25\/2007 12:56:26 PM",

"lastUpdatedDate": "",
"imageUri": "http:\/\/path_to_img.jpg",
"id": 1982932,
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
},
{"photoUri": "http:\/\/uri_to_photo",
"smallImageUri": "http:\/\/path_to_img.jpg",
"caption": "",
"uploadDate": "9\/11\/2008 4:25:22 PM",
"lastUpdatedDate": "",
"imageUri": "http:\/\/path_to_img.jpg",
"id": 26834127,
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
REST APIs 189

From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
},
],
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
}
Function name get_photo
Description Fetches data on a particular photo
Parameters <integer>user_id—the ID of the user
<integer>photo_id—the ID of the photo
Sample response {
"photoUri": "http:\/\/uri_to_photo",
"smallImageUri": "http:\/\/path_to_img.jpg",
"caption": "",
"uploadDate": "4\/25\/2007 12:56:26 PM",
"lastUpdatedDate": "",
"imageUri": "http:\/\/path_to_img.jpg",

"id": 1982932,
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"}
}
Function name get_profile
Description Fetches Profile data
190
Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
Parameters
<integer>user_id—the ID of the user
<string>type—the level of detail to fetch for the Profile data;
valid values are
basic, full, and extended
Sample response {
"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,

"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"lastUpdatedDate": "1\/1\/2009 2:11:28 PM",
"type": "basic"
}
Notes Later in the chapter we’ll discuss the differences among the three
levels of detail. The sample response here is for a basic Profile;
we’ll make use of an extended Profile a little later.
Function name get_status
Description Fetches the user’s status and mood
Parameters <integer>user_id—the ID of the user
Sample response {
"status": "is testing",
"mood": "curious",
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"moodLastUpdated": "4\/12\/2009 8:32:10 PM",
"moodId": 56,
"moodImageUrl":
"http:\/\/x.myspacecdn.com\/images\/blog\/moods\


/iBrads\/curious.gif"
}
REST APIs 191
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
Function name
get_videos
Description Fetches a list of videos
Parameters <integer>user_id—the ID of the user
Sample response {
"count": 1,
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"videos":
[{
"mediastatus": "ProcessingSuccessful",
"description": "Not a whole lot ",
"language": "en",
"privacy": "Public",

"country": "US",
"totalviews": "0",
"title": "Test Video",
"totalrating": "0",
"mediatype": "4",
"datecreated": "1\/1\/2009 2:30:48 PM",
"resourceuserid": "183399670",
"thumbnail": "http:\/\/path_to_img.jpg",
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"totalcomments": "0",
192 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
"totalvotes": "0",
"dateupdated": "1\/1\/2009 2:30:22 PM",
"runtime": "0",
"id": 55701156,
"videoUri": "http:\/\/uri_to_video"
}]

}
Function name get_video
Description Fetches data for a particular video
Parameters <integer>user_id—the ID of the user
<integer>video_id—the ID of the video
Sample response {
"mediastatus": "ProcessingSuccessful",
"description": "Not a whole lot ",
"language": "en",
"privacy": "Public",
"country": "US",
"totalviews": "0",
"title": "Test Video",
"totalrating": "0",
"mediatype": "4",
"datecreated": "1\/1\/2009 2:30:48 PM",
"resourceuserid": "183399670",
"thumbnail": "http:\/\/path_to_img.jpg",
"user":
{"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"uri":

"http:\/\/api.myspace.com\/v1\/users\/183399670",
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"},
"totalcomments": "0",
"totalvotes": "0",

"dateupdated": "1\/1\/2009 2:30:22 PM",
"runtime": "0",
"id": 55701156,
REST APIs 193
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
"videoUri": "http:\/\/uri_to_video"
}
Function name get_activities_atom
Description Fetches the list of app activities that the user has raised
Parameters <integer>user_id—the ID of the user
Sample response "<feed xml:lang=\"en-US\" >
<title type=\"text\">
Recent activities from Chad Russell at MySpace
<\/title>
<subtitle type=\"text\">
This feed contains all of the activities for a

single MySpace user
<\/subtitle>
<id>tag:myspace.com,2009:user\/183399670\

/activities<\/id>
<rights type=\"text\">Copyright (c) 2003-2009,

MySpace.com<\/rights>
<updated>2009-06-27T04:32:55Z<\/updated>
<author>

<name>Chad Russell<\/name>
<uri>http:\/\/www.myspace.com\/cdsrussell<\/uri>
<\/author>
<generator>PersonalActivitiesSyndicationFeed

Factory.1.1<\/generator>
<link rel=\"self\" href=\"http:\/\/path_to.atom\"\/>
<entry>
<id>tag:myspace.com,2009:\/ <\/id>
<title type=\"text\">Chad Russell is

thing\n<\/title>
<published>2009-06-23T12:44:35Z<\/published>
<updated>2009-06-23T12:44:35Z<\/updated>
<author>
<name>Chad Russell<\/name>
<uri>http:\/\/www.myspace.com\/cdsrussell<\/uri>
<\/author>
<link rel=\"icon\" \/>
<link rel=\"alternate\" \/>
<category term=\"ApplicationInnerActivity\" \/>
194 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
<content type=\"xhtml\">
<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">
various markup here
</div>

<\/content>
<activity:object>
<activity:object-

type>http:\/\/path_to_schema<\/activity:

object-type>
<id>tag:myspace.com,2009:\/Application\-

/114612<\/id>
<title>Friends Navigator<\/title>
<link rel=\"alternate\" \/>
<link rel=\"preview\" \/>
<\/activity:object>
<activity:verb>http:\/\/path_to_schema

<\/activity:verb>
<\/entry>
<\/feed>"
Function name get_friends_activities_atom
Description Fetches the list of app activities that the user’s friends have raised
Parameters <integer>user_id—the ID of the user
Sample response Very similar to the schema outlined for the response of the
get_activities_atom endpoint
Function name set_status
Description Sets the status for the particular user ID
Parameters <integer>user_id—the ID of the user
<string>status—the new status, as an arbitrary string
Sample response ""
Function name set_mood

Description Sets the mood for the particular user ID
Parameters <integer>user_id—the ID of the user
<integer>mood—the new mood; must correspond to one of the
valid mood IDs, which can be fetched using the
get_moods API
Sample response ""
Function name create_album
Description Creates a new media album
REST APIs 195
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Table 9.1 Continued
Parameters
<integer>user_id—the ID of the user
<string>title—the new title for the album, as an arbitrary string
<string>location—the geographic location where the album
media takes place, as an arbitrary string
<string>privacy—the album’s privacy setting; valid values are Me
(a private album), FriendsOnly (just the user’s friends can see it),
and
Everyone (a public album)
Sample response {"id": 2098891, "title": "family photos"}
Function name get_indicators
Description Fetches the indicators that are currently raised; can indicate a new
friend request, message, app invite, or comment approval
Parameters <integer>user_id—the ID of the user
Sample response {
"countnewmail": 1,
"user": {

"name": "Chad Russell",
"largeImage": "http:\/\/path_to_img.jpg",
"image": "http:\/\/path_to_img.jpg",
"userId": 183399670,
"webUri": "http:\/\/www.myspace.com\/cdsrussell",
"userType": "RegularUser"
},
"countpendingim": 1,
"mailurl":
"http:\/\/messaging.myspace.com\/index.cfm? "
}
Notes In the sample response, the user has one new mail message
pending and one IM message that has yet to be read.
Function name send_notification
Description Sends a notification from the app to the specified user; see
Chapter 5, Communication and Viral Features, for details
Parameters <integer>app_id—the app ID that will raise the notification
<string>recipients—a comma-delimited list of integer recipient
IDs, such as
"6221,12345"
<string>content—the main body of the message
<string>btn0_label—optional; the label for the first button
<string>btn0_surface—optional; which surface the first button
will navigate to; can be
canvas or appProfile
196 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
REST APIs 197

Note
In the course of researching all of the available endpoints, we created a test page. If you’re
having trouble accessing any of the APIs, this test page might come in handy. The test
page comes in two parts. The first is a client-side HTML page, which can be downloaded at
/>toe/index.html.
This page has a series of buttons on it, each corresponding to an endpoint (there are
some additional buttons that were used in Chapter 8). Clicking a button causes a Web
service request to some Python code, which can be downloaded at
/>tic-tac-toe/test.py. This file determines which endpoint you want to hit and uses the
MySpace SDK to make the request. The response is then pushed down onto the client.
If you’re having trouble, try it out for yourself. You may need to change the user ID found in
the
getter function in index.html to one of your own, along with some of the parameters
passed into the
getter function. For example, the album ID hard-coded into the file
corresponds to the user ID. If you change the user ID, the album will be different.
We hope you’ll find this page useful!
The Client Code
To create the markup and JavaScript for our off-site app, we modified the Canvas surface
code from our on-site app. Because it’s mostly the same, we won’t repeat it here.The
main difference is that instead of Ajax requests being sent to the API when the app
loads, the data is already there.The template object we push down from the Python
script has four members: friends_obj, appid, ownerId, and opensocial_token.In
our client-side markup, we can use these four template parameters by enclosing the
member names in double braces: {{ some_name }}.The space between the braces, and
including the braces, will be replaced by actual data at render time.
So the typical flow becomes the following:
1. A user loads our Canvas surface.
2. MySpace creates an iframe with the src attribute pointing to our URL.
Table 9.1 Continued

<string>btn1_label—optional; the label for the second button
<string>btn1_surface—optional; which surface the second
button will navigate to; can be
canvas or appProfile
<string>mediaitems—optional; must be in the format
where 6221 is a
user ID; posts that user’s thumbnail image along with the
notification
Sample response ""
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
3. The iframe loads and the request hits our servers.
4. We interrogate the query string of the request to determine the Viewer’s ID.
5. Using that ID, we make requests against the MySpace API for data.
6. The data comes back (or it doesn’t) and we put that data into a template object.
7. When the page renders, it looks for the double braces; if any are found, and the
label matches the name of one of the template members, the template is replaced
by actual data.
Our friends_obj parameter contained a JSON object of our user’s friend list. We
can access this on the client by doing the following:
var friends = {{ friends_obj }};
The friend list has now made its way from the MySpace API into our server scripts and
down to the client in the form of a JavaScript object. It’s now ready to be used on the page.
We also want to pass along pertinent data between pages. Each page in our app is
expecting certain data to exist on the query string.These query string parameters are
initially set by MySpace. But if a user clicks a link to go to another page, those query
string parameters are lost. So when we construct the link that will take the user to the
Play page, we add the other template values manually.The Play page has a similar link
pointing back to the Invite page:

<a id="tab0" class="left tab"
href="/play?opensocial_viewer_id={{ ownerId }}&
appid={{ appid }}&
opensocial_token={{ opensocial_token }}">Play</a>
When a user clicks this link, we pass the three parameters ownerId, appid, and
opensocial_token to the receiving page.This is just one of many ways to maintain
session state in your app.
Now that we have all of our data pushed down onto the page, we need to make a few
more changes in order to get everything working correctly.These modifications are
necessary because the friend data isn’t in the same format as it was for an on-site app. We
will no longer need to use the getField function to access data; the fields are instead
accessed directly from the object.Table 9.1 can be a great help with figuring out where
all the data should be.Tools like Firebug and Fiddler (see the Introduction for what these
tools are and where to get them) are also invaluable for understanding the data responses.
We first make the body execute a function after it has loaded:
<body onload="runOnLoad()">
The runOnLoad function then initializes a number of things, including saving the
friend data:
function runOnLoad(){
TTT.Lists.setCurrentList(TTT.ListTypes.ALL_FRIENDS);
TTT.Lists.getCurrentList().list = friends.Friends;
198 Chapter 9 External Iframe Apps
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

×