Not Drowning, Waving

I spent some time with the good folks at Google Sydney and a heap of fun Australian developers exploring¬†Googles new “wave” technology.

In short is pretty cool, an already neat GUI wrapping some serious back-end firepower to creat a collaborative environment that merges Realtime Publishing, Chat and Email. After a morning briefing on the tech, I Spent my afternoon with fellow Python lover Carlo Piva (http://www.linkedin.com/pub/carlo-piva/7/260/33b) creating a robot that objected to foul language and censored it. For those on Wave, try it by adding invectivedeleted@appspot.com to any wave (aka conversation) and just try to be rude or racist ūüôā

The code to do this is short and sweet –¬†we decided in the name of expediency to use an existing site noswearing.com for the swearing correction.

This example shows off a couple of cool things :

  1. how to make a basic bot that communicate with an external¬†“web service” for its functionality
  2. how to do POST requests
  3. how to screen scrape the results
  4. how to update existing blips (posts)

Here is the Python me and my coding buddy came up with:

from waveapi import events
from waveapi import model
from waveapi import robot
from google.appengine.api import urlfetch
from google.appengine.ext.webapp.util import run_wsgi_app
import urllib

def OnParticipantsChanged(properties, context):
¬† “””Invoked when any participants have been added/removed.”””
¬† added = properties[‘participantsAdded’]
  for p in added:

def OnRobotAdded(properties, context):
¬† “””Invoked when the robot has been added.”””
  root_wavelet = context.GetRootWavelet()
¬† root_wavelet.CreateBlip().GetDocument().SetText(“I’m alive!”)

def Notify(context):
  root_wavelet = context.GetRootWavelet()
¬† root_wavelet.CreateBlip().GetDocument().SetText(“Hi everybody!”)

def OnBlip(properties, context):
¬† “””Invoked when the robot sees a blip”””
¬† blip = context.GetBlipById(properties[‘blipId’])
  contents = blip.GetDocument().GetText()
  good = unswear(contents)
  if (good!=contents):

def unswear(bad):
¬† url = “

  form_fields = {
¬†¬†¬† “action”: “translate”,
¬†¬†¬† “p”: bad,
¬†¬†¬† “racial”: “on”,
¬†¬†¬† “submit”: “Filter”

  form_data = urllib.urlencode(form_fields)
  result = urlfetch.fetch(url=url,
¬†¬†¬† headers={‘Content-Type’: ‘application/x-www-form-urlencoded’})
  html = result.content
¬† key_start = ‘<span style=”font-family: arial; font-size:12px;”>’
¬† key_end = ‘</span></div><br>’
  return html[html.find(key_start)+len(key_start):html.find(key_end)]

if __name__ == ‘__main__’:
¬† myRobot = robot.Robot(‘invectivedeleted’,
¬†¬†¬†¬†¬† image_url=’http://s44.photobucket.com/albums/f39/philonikes/aim%20icons/th_fuck.gif&#8217;,
¬†¬†¬†¬†¬† version=’9′,
¬†¬†¬†¬†¬† profile_url=’http://invectivedeleted.appspot.com/&#8217;)
  myRobot.RegisterHandler(events.WAVELET_PARTICIPANTS_CHANGED, OnParticipantsChanged)
  myRobot.RegisterHandler(events.WAVELET_SELF_ADDED, OnRobotAdded)
  myRobot.RegisterHandler(events.BLIP_SUBMITTED, OnBlip)

Have fun!


1 Response to “Not Drowning, Waving”

  1. 1 Dave White
    November 4, 2009 at 7:17 pm

    I was just playing with your bot. It works quite well. I’m thinking about playing around with development for wave, so i thought i’d check it out.

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: