The Google Buzz API and You

Arizona State University – January 13, 2011

Hello
Timothy Jordan Developer Advocate, Google timothyjordan.com buzz.timothyjordan.com timothyjordan

Hello
Will Norris Developer Programs Engineer, Google http://willnorris.com

#buzzathon

Today

• This Talk • Answers & Questions • Hack Time • Demos & Prizes

This Talk

• The Conversational Web • Open Standards • Google Buzz • Examples

The Conversational Web

Open Standards
...are a really good thing

Why?

Open Source

Open Source

Open Standards

Password Anti-Pattern

OAuth

Your Application

Request a token (with scope)

Service Provider

OAuth

Your Application

Get unauthorized request token

Service Provider

OAuth

Your Application
Send user to SP with token

Service Provider

OAuth

Your Application
User returns with verification code

Service Provider

OAuth

Your Application

Exchange request for access token

Service Provider

OAuth

Your Application

Use access token to get data

Service Provider

Atom

<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?> <?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemconte <feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/ feedburner/ext/1.0" gd:etag="W/&quot;CkUGRHk8fyp7ImA9Wx5WEU0.&quot;"> <id>tag:blogger.com,1999:blog-3188762512334365442</id> <updated>2010-09-21T13:17:05.777-07:00</updated> <title>Social Web Blog</title> <subtitle type="html" /> <link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://googles <link rel="alternate" type="text/html" href="http://googlesocialweb.blogspot.com/" /> <link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/318876251233436 <author> <name>A Googler</name> <email>noreply@blogger.com</email> </author> <generator version="7.00" uri="http://www.blogger.com">Blogger</generator> <openSearch:totalResults>45</openSearch:totalResults> <openSearch:startIndex>1</openSearch:startIndex> <openSearch:itemsPerPage>25</openSearch:itemsPerPage> <link rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/SocialWebBlog" /> <feedburner:info uri="socialwebblog" /> <link rel="hub" href="http://pubsubhubbub.appspot.com/" /> <entry gd:etag="W/&quot;D0YASX89cCp7ImA9WxFaFUo.&quot;">

Atom

<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <id>tag:blogger.com,1999:blog-3188762512334365442</id> <updated>2010-09-21T13:17:05.777-07:00</updated> <title>Social Web Blog</title> <author> <name>A Googler</name> <email>noreply@blogger.com</email> </author> <generator version="7.00" uri="http://www.blogger.com">Blogger</generator> <link rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/SocialWebBlog" /> <entry> <id>tag:blogger.com,1999:blog-3188762512334365442.post-8190772326434476744</id> <published>2010-07-19T14:14:00.001-07:00</published> <updated>2010-07-19T14:32:28.168-07:00</updated> <title>Announcing New Google Buzz API features</title> <content type="html"> ... </content> <link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/31887625123343 <author> <name>Timothy Jordan</name> <uri>http://www.blogger.com/profile/14618592793335366108</uri> <email>noreply@blogger.com</email> </author> <thr:total>7</thr:total>

Atom
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom">

<id>tag:blogger.com,1999:blog-3188762512334365442</id> <updated>2010-09-21T13:17:05.777-07:00</updated> <title>Social Web Blog</title>

<author> <name>A Googler</name> <email>noreply@blogger.com</email> </author> <generator version="7.00" uri="http://www.blogger.com">Blogger</generator> <link rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/SocialWebBlog" /> <entry> <id>tag:blogger.com,1999:blog-3188762512334365442.post-8190772326434476744</id> <published>2010-07-19T14:14:00.001-07:00</published> <updated>2010-07-19T14:32:28.168-07:00</updated> <title>Announcing New Google Buzz API features</title> <content type="html"> ... </content> <link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/31887625123343 <author> <name>Timothy Jordan</name> <uri>http://www.blogger.com/profile/14618592793335366108</uri> <email>noreply@blogger.com</email> </author>

Atom
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <id>tag:blogger.com,1999:blog-3188762512334365442</id> <updated>2010-09-21T13:17:05.777-07:00</updated> <title>Social Web Blog</title>

<author> <name>A Googler</name> <email>noreply@blogger.com</email> </author>
<generator version="7.00" uri="http://www.blogger.com">Blogger</generator>

<link rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/SocialWebBlog" />

<entry> <id>tag:blogger.com,1999:blog-3188762512334365442.post-8190772326434476744</id> <published>2010-07-19T14:14:00.001-07:00</published> <updated>2010-07-19T14:32:28.168-07:00</updated> <title>Announcing New Google Buzz API features</title> <content type="html"> ... </content> <link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/31887625123343 <author> <name>Timothy Jordan</name> <uri>http://www.blogger.com/profile/14618592793335366108</uri>

PubSubHubbub

Publisher

Hub

Subscriber

PubSubHubbub

Give me your latest content for feed X, please.

Publisher

Subscriber

PubSubHubbub

I've delegated distribution of that content to this Hub.

Publisher

Subscriber

PubSubHubbub

I want to subscribe to feed X. Send updates to this URL

Publisher

Hub

Subscriber

PubSubHubbub

Hey there! Did you really send this request?

Publisher

Hub

Subscriber

PubSubHubbub

Yup, that was really me, not a DoS attacker.

Publisher

Hub

Subscriber

PubSubHubbub

Here’s some new content for feed X!

Publisher

Hub

Subscriber

PubSubHubbub

New update to feed X! Here you go.

Publisher

Hub

Subscriber

PubSubHubbub

New update to feed X! Here you go.

Publisher

Hub

Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber

PubSubHubbub

code.google.com/p/pubsubhubbub

salmon-protocol.org

Salmon

I have a new entry

Source

PubSubHubbub

Aggregator

Salmon

A new entry? I will re-publish it right away.

Source

PubSubHubbub

Aggregator

Salmon

I have a new comment on that entry from you!

Source

Salmon

Aggregator

Salmon

A new comment? I will publish it in the thread right away [*].

Source

Salmon

Aggregator

[*] After using magic security pixie dust to verify provenance.

Salmon

I have a new comment.

Source

PubSubHubbub

Aggregator Aggregator Aggregator Aggregator Aggregator Aggregator Aggregator

Salmon

Thanks, we'll re-publish this right away.

Source

PubSubHubbub

Aggregator Aggregator Aggregator Aggregator Aggregator Aggregator Aggregator

salmon-protocol.org

activitystrea.ms

Activity Streams

Actor

Activity Streams

Actor Verb

Activity Streams

Actor Verb Object

Activity Streams

Timothy Shared A Link

Activity Streams

Barack Obama Started Following Timothy Jordan

Activity Streams

Timothy Jordan Started Following Barack Obama

Activity Streams

Timothy Jordan Has Tea With Bella Swan

Activity Streams

Timothy Jordan Has Tea With Bella Swan

activitystrea.ms

Google Buzz API

Warning!

Buzz API Documentation

https://code.google.com/apis/buzz/docs/

OACurl

http://code.google.com/p/oacurl/

https://www.googleapis.com/buzz/v1/

http://code.google.com/p/google-api-python-client/ http://code.google.com/p/google-api-java-client/ http://code.google.com/p/google-api-ruby-client/ http://code.google.com/p/google-api-php-client/

https://www.googleapis.com/buzz/v1/

Common Parameters
alt • alt=atom returns an Atom representation of the data. • alt=json returns a JSON representation of the data. prettyprint • If prettyprint=true, the results returned by the server will be human readable • Default: prettyprint=false
https://www.googleapis.com/buzz/v1/activities/@me/@self?alt=json&prettyprint=true

Common Parameters
• • • • • preview=true max-results=N max-liked=N max-comments=N c={token} preview the operation. maximum number of results. maximum number of likes maximum number of comments continuation token

https://www.googleapis.com/buzz/v1/activities/@me/@self?max-results=20&c={token}

Search Parameters
• q={query} search. • lat, lon, radius geo location. • bbox bounding box.

https://www.googleapis.com/buzz/v1/activities/search?q={q}&lat={l}&lon={l}&radius={r}

Activity Streams

Actor Verb Object

Ted Taco Posts A Note

2010:buzz:z13ispojgwqsinyij04chlupum2ytbspsa4?alt\u003djson",      "type": "json"     }    ],    "replies": [     {      "href": "{url}/{userId}/@self/{commentId}/@comments?alt=json",      "type": "application/json",      "count": 2,      "updated": "2010-05-09T02:53:13.730Z"     }    ]   },

  "actor": {    "id": "{id}",    "name": "Ted Taco",    "profileUrl": "{url}/ted",    "thumbnailUrl": "{url}/ted/thumb.jpg"   },
  "verbs": [    "post"   ],   "object": {    "type": "note",    "content": "content goes here",    "links": {     "alternate": [      {       "href": "http://www.google.com/buzz/a/google.com",       "type": "text/html"      }     ]    }   },

   ],    "replies": [     {      "href": "{url}/{userId}/@self/{commentId}/@comments?alt=json",      "type": "application/json",      "count": 2,      "updated": "2010-05-09T02:53:13.730Z"     }    ]   },   "actor": {    "id": "{id}",    "name": "Timothy Jordan",    "profileUrl": "{url}/captaintimothy",    "thumbnailUrl": "{url}/captaintimothy/thumb.jpg"   },

  "verbs": [    "post"   ],
  "object": {    "type": "note",    "content": "content goes here",    "links": {     "alternate": [      {       "href": "http://www.google.com/buzz/a/google.com",       "type": "text/html"      }     ]    }   },   "source": {    "title": "Buzz"   },   "visibility": {    "entries": [

    }    ],    "replies": [     {      "href": "{url}/{userId}/@self/{commentId}/@comments?alt=json",      "type": "application/json",      "count": 2,      "updated": "2010-05-09T02:53:13.730Z"     }    ]   },   "actor": {    "id": "{id}",    "name": "Timothy Jordan",    "profileUrl": "{url}/captaintimothy",    "thumbnailUrl": "{url}/captaintimothy/thumb.jpg"   },   "verbs": [    "post"   ],

  "object": {    "type": "note",    "content": "content goes here"   },
  "source": {    "title": "Buzz"   },   "visibility": {    "entries": [     {      "id": "https://www.googleapis.com/buzz/v1/people/@me/@groups/@public?alt\u003djson",      "title": "Public"     }    ]   }  }

{   "kind": "buzz#activity",

  "title": "note to self",   "published": "2010-05-09T02:53:13.000Z",   "updated": "2010-05-09T02:53:13.730Z",    "id": "tag:google.com,2010:buzz:foo",
  "links": {    "liked": [     {      "href": "https://www.googleapis.com/buzz/v1/activities/110242419133439594545/@self/tag:google.com, 2010:buzz:z13ispojgwqsinyij04chlupum2ytbspsa4/@liked?alt\u003djson",      "type": "application/json",      "count": 0     }    ],    "alternate": [     {      "href": "http://www.google.com/buzz/a/google.com",      "type": "text/html"     }    ],    "self": [     {      "href": "https://www.googleapis.com/buzz/v1/activities/110242419133439594545/@self/tag:google.com, 2010:buzz:z13ispojgwqsinyij04chlupum2ytbspsa4?alt\u003djson",

{   "kind": "buzz#activity",   "title": "note to self",   "published": "2010-05-09T02:53:13.000Z",   "updated": "2010-05-09T02:53:13.730Z",    "id": "tag:google.com,2010:buzz:foo",   "links": {

   "liked": [     {      "href": "{url}/{userid}/@self/{commentId}/@liked?alt=json",      "type": "application/json",      "count": 4, "updated": "2010-05-09T02:53:13.730Z"     }
   ],    "alternate": [     {      "href": "http://www.google.com/buzz/a/google.com",      "type": "text/html"     }    ],    "self": [     {      "href": "https://www.googleapis.com/buzz/v1/activities/110242419133439594545/@self/tag:google.com, 2010:buzz:z13ispojgwqsinyij04chlupum2ytbspsa4?alt\u003djson",      "type": "json"

   "alternate": [     {      "href": "http://www.google.com/buzz/a/google.com",      "type": "text/html"     }    ],    "self": [     {      "href": "https://www.googleapis.com/buzz/v1/activities/110242419133439594545/@self/tag:google.com, 2010:buzz:z13ispojgwqsinyij04chlupum2ytbspsa4?alt\u003djson",      "type": "json"     }    ],

"replies": [     {      "href": "{url}/{userId}/@self/{commentId}/@comments?alt=json",      "type": "application/json",      "count": 2,      "updated": "2010-05-09T02:53:13.730Z"     }    ]
      },   "actor": {    "id": "110242419133439594545",    "name": "Timothy Jordan",    "profileUrl": "{url}/captaintimothy",    "thumbnailUrl": "{url}/captaintimothy/thumb.jpg"   },   "verbs": [    "post"   ],   "object": {

  },   "verbs": [    "post"   ],   "object": {    "type": "note",    "content": "content goes here",    "links": {     "alternate": [      {       "href": "http://www.google.com/buzz/a/google.com",       "type": "text/html"      }     ]    }   },

  "source": {    "title": "Buzz"   },
  "visibility": {    "entries": [     {      "id": "https://www.googleapis.com/buzz/v1/people/@me/@groups/@public?alt\u003djson",      "title": "Public"     }    ]   }  }

  },   "verbs": [    "post"   ],   "object": {    "type": "note",    "content": "content goes here",    "links": {     "alternate": [      {       "href": "http://www.google.com/buzz/a/google.com",       "type": "text/html"      }     ]    }   },   "source": {    "title": "Buzz"   },

"visibility": {    "entries": [     {      "id": "{url}/people/@me/@groups/@public?alt=json",      "title": "Public"     }    ]   }
    }

    "alternate": [      {       "href": "http://www.google.com/buzz/a/google.com",       "type": "text/html"      }     ]    }   },   "source": {    "title": "Buzz"   },   "visibility": {    "entries": [     {      "id": "{url}/people/@me/@groups/@public?alt=json",      "title": "Public"     }    ] },

"geocode": "37.422194 -122.084547", "address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA", "placeName": "Googleplex"
}  }

  "object": {    "type": "note",    "content": "content goes here",

"attachments": [ { "type": "article", "title": "Name of the link", "links": { "alternate": [ { "href": "{url}/to/article.html", "type": "text/html" } ]
} } ]

  }

  "object": {    "type": "note",    "content": "content goes here",

"attachments": [      {       "type": "photo",       "links": {        "preview": [         {          "href": "{url}/image_thumb.jpg",          "type": "image/jpeg"         }        ],        "enclosure": [         {          "href": "{url}/image.jpg",          "type": "image/jpeg",          "height": 190,          "width": 260         }        ]

   

     }     }    ]   }

   "object": {     "type": "note",     "content": "content goes here", "attachments": [ {

"type": "video", "title": "video description goes here", "links": { "alternate": [ { "href": "http://www.youtube.com/watch?v=abcdef", "type": "text/html" } ], "preview": [ { "href": "{url}/default.jpg", "type": "image/jpeg" }, { "href": "{url}/proxy?thumbnail_default.jpg", "type": "image/jpeg" }
] }

Verbs
Favorite Follow Friend Join Play Post Save Share Tag Update

Objects
Article Audio Bookmark Comment File Folder Group List Note Person Photo Photo Album Place Playlist Product Review Service Status Video

Verbs
Favorite Follow Friend Join Play Post Save Share Tag Update

Objects
Article Audio Bookmark Comment File Folder Group List Note Person Photo Photo Album Place Playlist Product Review Service Status Video

OAuth

Auth url: https://www.google.com/buzz/api/auth/OAuthAuthorizeToken https://www.google.com/buzz/api/auth/OAuthAuthorizeToken scope: https://www.googleapis.com/auth/buzz ?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fbuzz &domain=www.example.org domain: www.example.org &oauth_token= iconUrl: http://www.example.org/icon.png

PubSubHubbub

Firehose

Photo credit: Nandhp, used under the Creative Commons Attribution-Share Alike 3.0 Unported license.

Gardenhose

Track

Examples

buzz-bingo.appspot.com

Buzz Bingo

Sign-In & Auth for Buzz client = buzz.Client() client.build_oauth_consumer(   OAUTH_CONSUMER_KEY,   OAUTH_CONSUMER_SECRET ) client.oauth_scopes.append(   buzz.FULL_ACCESS_SCOPE )

Sign-In & Auth for Buzz request_token = \   client.fetch_oauth_request_token(     'http://example.com/oauth/callback/'   ) # Save request token to the data store authorization_url = \   client.build_oauth_authorization_url(     request_token   )

Sign-In & Auth for Buzz # User visits the authorization_url

Sign-In & Auth for Buzz verifier = request.get('oauth_verifier') # Lookup request_token in data store client.oauth_request_token = request_token access_token = \   client.fetch_oauth_access_token(verifier) # Save access token to the data store

Buzz Bingo is open source! code.google.com/p/buzz-bingo buzz-bingo.appspot.com

buzz-mood.appspot.com

Buzz Mood

Some Constants

FIREHOSE = "https://www.googleapis.com/buzz/v1/activities/@all/@public" HUB = "http://pubsubhubbub.appspot.com/" CALLBACK = "http://buzz-mood.appspot.com/pshb/callback"

Subscribe class PubsubhubbubSubscribeHandler (webapp.RequestHandler):   def post(self):     parameters = {       "hub.callback": CALLBACK,       "hub.mode": "subscribe",       "hub.topic": FIREHOSE,       "hub.verify": "async"     }     fetch(       HUB,       method='POST',       payload=urllib.urlencode(parameters),       follow_redirects=False     )

Verify Subscription
class PubsubhubbubCallbackHandler(webapp.RequestHandler):   def get(self):     hub_mode = self.request.get('hub.mode')     hub_topic = self.request.get('hub.topic')     hub_challenge = self.request.get('hub.challenge')     if hub_mode == "subscribe" and hub_topic == FIREHOSE:       logging.info('Subscription verified.')       self.response.set_status(202)       self.response.out.write(hub_challenge)     else:       # We're only interested in the firehose       # And we don't really ever unsubscribe       self.response.set_status(403)       self.response.out.write('')

Incoming Post   # PubsubhubbubCallbackHandler continued...   def post(self):     feed_data = self.request.body     feed = feedparser.parse(feed_data)     for entry in feed.entries:       if hasattr(entry, 'content'):         content = entry.content[0].value       elif hasattr(entry, 'summary'):         content = entry.summary       elif hasattr(entry, 'title'):         content = entry.title       else:         logging.info('Skipping, could not find content.')         continue       if mood.PATTERN.search(content):         mood.assign(content)

Process Post
def assign(summary, content):   lower = content.lower()   for bucket in BUCKETS:     if lower.find(bucket) != -1:       logging.info('Entry assigned to \'%s\' bucket.' % bucket)       query = Mood.all()       query.filter('name =', bucket)       mood = query.fetch(1)       if not mood:         mood = Mood(name=bucket)       elif type(mood) == list:         mood = mood[0]       else:         raise TypeError('Expected a list.')       mood.counter += 1       mood.last_summary = summary       mood.last_content = content       mood.put()

buzzsearchengine.appspot.com

Buzz Search Engine

buzzchatbot.appspot.com

Buzz Chat Bot

Questions

Questions and Answers
Timothy Jordan Developer Advocate, Google timothyjordan.com buzz.timothyjordan.com timothyjordan Will Norris Developer Programs Engineer, Google http://willnorris.com

Links

https://code.google.com/apis/buzz/docs/ http://code.google.com/apis/buzz/docs/libraries.html code.google.com/p/buzz-codelabs code.google.com/p/buzz-mood github.com/adewale/buzzsearchengine

Sign up to vote on this title
UsefulNot useful