RkTaggy - przykładowy robot Google Wave

Tworzenie robotów nie jest obecnie zbyt łatwe. Z jednej strony niewiele jest robotów z opublikowanym kodem... a większość z tych publicznych napisana jest w Javie :( Naszym przyjacielem przy tworzeniu robota będzie:
  • API Documentation
  • logging.debug() w Google App Engine. Jako że nie można testować robotów lokalnie, ani nie ma zbyt ładnej dokumentacji i przykładów na każdym etapie rozwoju robota należy wszystko logować by sprawdzić jakie dane i obiekty otrzymujemy:
    wavemybot1

RkTaggy - przykładowy robot

Poniżej kod wstępnej wersji mojego robota rktaggy@appspot.com (dodaj go do swojej fali ;)):
# -*- coding: utf-8 -*-
from waveapi import events
from waveapi import model
from waveapi import robot
from waveapi import document
import logging

from barcharts import make_barcharts

def OnRobotAdded(properties, context):
	"""
	Robot dodany
	"""
	root_wavelet = context.GetRootWavelet()
	root_wavelet.CreateBlip().GetDocument().SetText("""I'm a BBCode like BBCode ;) robot that has some nifty tags that you can use...
	[barchart]Chart Title
	label1,value1
	label2,value2
	label3,value3
	...,...
	[/barchart]
	""")

def OnBlipSubmitted(properties, context):
	"""
	Nowy blip dodany
	"""
	#logging.debug('properties')
	#logging.debug(properties)
	blipId = properties['blipId']
	logging.debug('blipId %s' % blipId)
	blip = context.GetBlipById(blipId) #OpBasedBlip
	if blip:
		doc = blip.GetDocument() # OpBasedDocument
		#elems = blip.GetElements()
		#logging.debug('elements')
		#logging.debug(elems)
		#logging.debug('doc')
		#logging.debug(doc)
		text = doc.GetText()
		#logging.debug('text')
		#logging.debug(text)
		
		urls = make_barcharts(text)
		if len(urls) > 0:
			for i in urls:
				img = document.Image(url=i)
				doc.AppendElement(img)
		
		#doc.SetText(text)


if __name__ == '__main__':
	myRobot = robot.Robot('rktaggy',
		image_url='http://rktaggy.appspot.com/site_media/logo.png',
		version='23',
		profile_url='http://rktaggy.appspot.com/')
	myRobot.RegisterHandler(events.BLIP_SUBMITTED, OnBlipSubmitted)
	myRobot.RegisterHandler(events.WAVELET_SELF_ADDED, OnRobotAdded)
	myRobot.Run()
Jest to dość prosty robot, który obrabia nowo dodaną wiadomość. Służy do tego zdarzenie BLIP_SUBMITTED. Obsługuje go funkcja OnBlipSubmitted, która w argumencie properties posiada ID nowego blipa (co zostało "odkryte" po zalogowaniu tego argumentu przez moduł logging.). Mając ID blipa możemy pobrać sam obiekt Blipa za pomocą context.GetBlipById(ID) (patrz też waveapi/model.py, klasa Context). Dostajemy obiekt OpBasedBlip (patrz dokumentacja), dla którego możemy pobrać dokument OpBasedDocument za pomocą metody GetDocument. Obiekt ten zawiera całą treść blipa - tekst jak i załączniki. Za pomocą metody GetText pobieramy tekst blipa, którą obrabiamy metodą make_barcharts, która wyszukuje dane do wykresu słupkowego i zwraca listę URLi do wykresów Google Charts (kod za chwilę). Każdego URLa do wykresu (grafiki) wstawiamy do Blipa jako element (~załącznik) za pomocą obiekty document.Image przyjmującego jako argument adres URL do pliku. Grafika zostanie dostawiona do końca wiadomości.
Funkcja make_barcharts wygląda tak:
# -*- coding: utf-8 -*-
from re import findall
from pygooglechart import GroupedVerticalBarChart
from pygooglechart import Axis
import logging

def make_barcharts(text):
	urls = []
	barcharts = findall( r'(?xs)\[barchart\](.*?)\[/barchart\]''', text)
	
	for i in barcharts:
		try:
			values = []
			labels = []
			maxvalue = 0
			title = ''
			data = i.split('
')
			if len(data) > 0:
				title = data[0]
				del data[0]
				for d in data:
					d = d.strip()
					if len(d) > 0:
						elem = d.split(',')
						labels.append(elem[0])
						values.append(int(elem[1]))
						if int(elem[1]) > maxvalue:
							maxvalue = int(elem[1])
				chart = GroupedVerticalBarChart(300, 300, y_range=(0, maxvalue))
				chart.set_bar_width(10)
				chart.set_colours(['00ff00'])
				chart.set_bar_spacing(15)
				chart.set_group_spacing(50)
				chart.add_data(values)
				labs = chart.set_axis_labels(Axis.BOTTOM, labels)
				chart.set_axis_style(labs, '202020', font_size=12, alignment=0)
				vlabs = chart.set_axis_labels(Axis.LEFT, values)
				chart.set_axis_style(vlabs, '202020', font_size=12, alignment=0)
				index = chart.set_axis_labels(Axis.TOP, [title])
				chart.set_axis_style(index, '202020', font_size=14, alignment=0)
				chart.set_axis_positions(index, [50])
				
				urls.append(chart.get_url())
		except:
			logging.error('EXCEPTION FOR')
			logging.error(i)
			pass
	return urls
Wyszukuje ona dane w formacie:
[barchart]Tytuł Wykresu
etykieta,wartość liczbowa
etykieta,wartość liczbowa
etykieta,wartość liczbowa
[/barchart]
A następnie wydobywa wszystkie dane i konstruuje prosty wykres za pomocą pygooglechart.
Obecnie nie można w łatwy sposób wstawiać treści blipa zawierającej kod HTML. Jest to znany brak, nad którym zespół Google Wave pracuje. Obecnie można to obejść wstawiając gadżet, czy stosując SetAnnotation - dlatego nasz przykładowy robot wstawia grafiki :))

Kod źródłowy

Jeżeli chcesz wykorzystać tego robota musisz w app.yaml zmienić mu identyfikator na własny, ID zarejestrowanej aplikacji na GAE (podobnie w kodzie robota)
RkBlog

Google Wave, 18 October 2009

Comment article
Comment article RkBlog main page Search RSS Contact