Jump to content

Reacting to Wave Conversations and Inserting Wave Gadgets with a Wave Robot

+ 3
  tmo9d's Photo
Posted Oct 05 2009 08:43 AM

If you want to create a Google Wave Robot that listens for changes to a Wave and inserts a Google Gadget, this post is an attempt to share that knowledge. At the moment, Wave Robots must reside on Google's AppEngine. You can write them in either Python or Java. The following example uses Java, and if you are interested in implementing a similar robot, you'll need access to Google Wave and an account on Google AppEngine.

These steps assume that you know how to install Eclipse and that you have already installed the Google Eclipse plugin. If you are looking for detailed instructions about these startup steps, see the Java Tutorial for creating a Google Wave Robot. While this tutorial is helpful, the sample application you end up with is a novelty, all it does is allow you to create a robot that announces itself and welcomes participants on a Wave.

Creating an Intelligent, Gadget-wielding Robot

I wanted to create a Wave Robot that watches an ongoing conversation and inserts a Wave Gadget in response to activity. To do this, you'll need to do the following in your Robot code:

1. Modify the capabilities.xml to include the following events:

<?xml version="1.0" encoding="utf-8"?>
<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">
  <w:capabilities>
    <w:capability name="WAVELET_PARTICIPANTS_CHANGED" content="true" />
    <w:capability name="BLIP_SUBMITTED" content="true" />
    <w:capability name="BLIP_VERSION_CHANGED" content="true" />
    <w:capability name="FORM_BUTTON_CLICKED" content="true" />
  </w:capabilities>
  <w:version>1</w:version>
</w:robot>


2. Create a Google Wave Gadget and publish that gadget to a web server that is accessible to the public. While Google Wave Robots must be served from Google AppEngine, there is no restriction on where a Google Wave Gadgets can be served from. In this example, we're using the ISBN Lookup gadget from: http://mars.discursi...bn-lookup-4.xml

3. Here is the Java code for our Robot (This is all it takes to participate in a conversation, match an ISBN, and insert a gadget.):

package com.discursive.sample.isbnreplacer;

import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.wave.api.AbstractRobotServlet;
import com.google.wave.api.Blip;
import com.google.wave.api.Event;
import com.google.wave.api.EventType;
import com.google.wave.api.Gadget;
import com.google.wave.api.Range;
import com.google.wave.api.RobotMessageBundle;
import com.google.wave.api.TextView;
import com.google.wave.api.Wavelet;

public class IsbnReplacerRobot extends AbstractRobotServlet {

  private static final Logger log = 
    Logger.getLogger( IsbnReplacerRobot.class.getName() );
	
  public static String ISBN_GADGET_XML = 
    "http://mars.discursive.com/isbn-lookup-4.xml";
	
  @Override
  public void processEvents(RobotMessageBundle events) {
    log.info( "EVENTS: " + events );
		
    Wavelet wavelet = events.getWavelet();

    if (events.wasSelfAdded()) {
      Blip blip = wavelet.appendBlip();
      TextView textView = blip.getDocument();
      textView.append("BookMarker is here.");
    }

    List<Event> submittedEvents = events.getBlipSubmittedEvents();
    for (Event e : submittedEvents) {
      Blip blip = e.getBlip();
      TextView textView = blip.getDocument();
      replaceIsbns(textView);
    }
  }

  void replaceIsbns(TextView textView) {
    String text = textView.getText();
    log.info( "TEXT: " + text );
		
    Pattern isbn = Pattern.compile("\\d{13}");
    Matcher matcher = isbn.matcher(text);

    while (matcher.find()) {
      log.info( " Found a match" );
      textView.replace(new Range(matcher.start(), 
                       matcher.start() + 13), "");
      String isbnNum = text.substring( matcher.start(),
                                       matcher.start() + 13);
      Gadget gadget = new Gadget( ISBN_GADGET_XML );
      gadget.setField( "isbn", isbnNum );
      textView.insertElement( matcher.start(), gadget );
    }
  }
}


This code simply scans a TextView's text document for 13-digits, assumes it is an ISBN, and replaces it with a Gadget. You can see how easy it is to create a gadget and update the state of the Gadget from the API.

4. Publish your application to Google AppEngine, making sure that you have the appropriate capabilities.xml and configuring in your web.xml (see the Java Tutorial for creating a Google Wave Robot)

Demonstration of this Google Wave Robot

Here is the result, to use this robot:

1. Add a demorobot124@appspot.com as a contact... (You can try it yourself...)

2. Start a new wave with the robot (or add the robot to an existing Wave)

3. Then add a new blip that contains an ISBN.

The Robot will then scan your document for 13-digits, and replace that ISBN with the ISBN Lookup Gadget and set the ISBN. This will have the effect of replacing your ISBN with a thumbnail of the book cover.



The promise of Wave is the idea of intelligent agents observing and reacting to real-time conversation and collaboration. While this is a very simple example, a more complex example would involve a Google Wave Robot watching/participating in a conversation, instatiating multiple gadgets in response to activity, and (this is key) coordinating Wave state across multiple gadgets.

I've heard a rumor that one of Larry Page's ultimate goals is the idea of an intelligent agent that can sit in a room, taking note of an ongoing conversation, and providing data in response to the conversation. I can see how this plays into this idea of bridging conversation, collaboration, and intelligence. It will be interesting to see how people start to use robots to bridge the non-wave portion of the web with Google Wave.

1 Reply

 : Dec 09 2009 01:27 PM
Couldn't get the desired result.

Steps to recreate:

1. Create new wave
2. Add Text:
Java Cookbook 9780596007010

3. Add participant: demorobot124@appspot.com
4. Close wave

What happens is the ISB-13 number disappears and no icon appears.

I am behind a firewall, though port 80 is open.