先日、Google WaveのRobots APIバージョン2がリリースされた。更新内容の概要は「Google Wave Robot API v2のリリースエントリを翻訳しました」が分かりやすい。そこで、以前に作成した「てめーはおれを怒らせた」ボットをバージョン2のAPIで書き直してみることにした。しかし、すぐに修正できるだろうとナメていたら意外と時間が掛かってしまった。
初っ端でいきなり動かない。ほとんどチュートリアルと同じ程度に削っても動かない。エラーを頼りにAPIのソースコードなどを読んだりしているうちに、自分のプログラムの問題ではないんじゃないかと思い、動作確認していた環境をSandboxからPreviewに変更してみたら、問題なく動くようになった。ここでかなりの時間ロス。さらに、インターフェースも大きく変わっていて、新しいAPIでどのように実装するのか調べるだけでも結構時間を取られた。
書き直したソースコードは以下の通り。本当にこれで良いのか自信はないが、ちゃんと動作するようだ。因みに、ボットのアカウントはbillowlet@appspot.comだ。Google WaveのContactsパネルから登録すれば使うことができる。
慣れていないので手こずってしまったが、以前のバージョンに比べて、できることは増えているし、APIの構成も分かりやすくなっている。それに、ちゃんとGoogle Wave Robot Python API v2のドキュメントが整備されているのが嬉しいところ。何か面白いボットを作ってみたいな。
追記(2010/3/15):
Sandboxでも正常に動作するようになったみたい。
billowlet.py
#!/usr/bin/env python # -*- coding: utf-8 -*- """billowlet.py by nox, 2010.3.6""" import re, urllib, urllib2, random from google.appengine.ext import db from waveapi import events from waveapi import robot from waveapi import blip from waveapi import appengine_robot_runner from waveapi import simplejson HIRAGANA = u"あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん" KATAKANA = u"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン" class UserData(db.Model): user = db.StringProperty(multiline=False) status = db.StringProperty(multiline=False) def OnWaveletParticipantsChanged(event, wavelet): participants = event.participants_added for participant in participants: if participant != "billowlet@appspot.com": wavelet.reply(u"%s、おれを怒らせるなよ。" % participant.split("@")[0]) def OnWaveletSelfAdded(event, wavelet): wavelet.reply(u"おれはbillowlet。よろしくな。") def Translate(text, from_lang, to_lang): url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s%%7C%s" % (urllib.quote(text.encode("utf-8")), from_lang, to_lang) data = simplejson.loads(urllib2.urlopen(url).read()) return data["responseData"]["translatedText"] def BeCat(text): text = re.sub(u"。", u"にゃ。", text) text = re.sub(u"?|\?", u"にゃぁ?", text) text = re.sub(u"!|\!", u"にゃっ!", text) text = re.sub(u"な", u"にゃ", text) if text[-1] not in (u"。", u"?", u"?", u"!", u"!"): text += u"にゃ" return text def DotMarks(text): from_kana = u"かきくけこさしすせそたちつてとはひふへほカキクケコサシスセソタチツテトハヒフヘホ" to_kana = u"がぎぐげござじずぜぞだぢづでどばびぶべぼガギグゲゴザジズゼゾダヂヅデドバビブベボ" for f, t in zip(from_kana, to_kana): text = text.replace(f, t) return text def Laugh(text, ch): for i in range(len(text), 0, -1): text = text[:i] + ch + text[i:] return text.replace(u"。", u"").replace(u"、", u"") + ch * random.randint(3, 10) def Kana(idx): return HIRAGANA[idx] + u"|" + KATAKANA[idx] def OnBlipSubmitted(event, wavelet): blp = event.blip user = blp.creator opq = wavelet.get_operation_queue() data = UserData.all().filter("user =", user).get() if data: status = data.status else: status = None text = blp.text.strip() if status and re.match(u"ごめんなさい|ゆるして", text): json = opq.blip_create_child(blp.wave_id, blp.wavelet_id, blp.blip_id) child_blp = blip.Blip(json, wavelet.blips, opq) child_blp.append(u"ゆるしてやる。やれやれだぜ。".encode("utf-8")) if data: data.delete() st = (u"ネコになれ。", # 0 u"英国紳士になれ。", # 1 u"台湾に住め。", # 2 u"インチキ日本人になれ。", # 3 u"大事なことは2回言え。", # 4 u"笑え。", # 5 u"濁れ。", # 6 u"逆さまになれ。", # 7 u"どもれ。", # 8 u"うざくなれ。") # 9 fn = {st[0]: BeCat, st[1]: lambda (text): Translate(text, "ja", "en"), st[2]: lambda (text): Translate(text, "ja", "zh-TW"), st[3]: lambda (text): Translate(Translate(text, "ja", "en"), "en", "ja"), st[4]: lambda (text): text + text + u"\n大事なことなので2回言いました。", st[5]: lambda (text): Laugh(text, u"w"), st[6]: DotMarks, st[7]: lambda (text): text[::-1], st[8]: lambda (text): (text[0] + u"、") * 3 + text, st[9]: lambda (text): Laugh(text, u"っ")} angry = range(len(HIRAGANA)) random.shuffle(angry) if status: text = fn[status](text) blp.range(1, len(blp.text)).replace(text.encode("utf-8")) else: userdata = UserData() for i in range(len(st)): if re.search(Kana(angry[i]), text): status = st[i] break if status: json = opq.blip_create_child(blp.wave_id, blp.wavelet_id, blp.blip_id) child_blp = blip.Blip(json, wavelet.blips, opq) text = u"てめーはおれを怒らせた。%s" % status child_blp.append(text.encode("utf-8")) userdata.user = user userdata.status = status userdata.put() def main(): myRobot = robot.Robot("billowlet", image_url="http://billowlet.appspot.com/assets/icon.png", profile_url="http://billowlet.appspot.com/") myRobot.register_handler(events.WaveletParticipantsChanged, OnWaveletParticipantsChanged) myRobot.register_handler(events.BlipSubmitted, OnBlipSubmitted) myRobot.register_handler(events.WaveletSelfAdded, OnWaveletSelfAdded) appengine_robot_runner.run(myRobot) if __name__ == "__main__": main()
初っ端でいきなり動かない。ほとんどチュートリアルと同じ程度に削っても動かない。エラーを頼りにAPIのソースコードなどを読んだりしているうちに、自分のプログラムの問題ではないんじゃないかと思い、動作確認していた環境をSandboxからPreviewに変更してみたら、問題なく動くようになった。ここでかなりの時間ロス。さらに、インターフェースも大きく変わっていて、新しいAPIでどのように実装するのか調べるだけでも結構時間を取られた。
書き直したソースコードは以下の通り。本当にこれで良いのか自信はないが、ちゃんと動作するようだ。因みに、ボットのアカウントはbillowlet@appspot.comだ。Google WaveのContactsパネルから登録すれば使うことができる。
慣れていないので手こずってしまったが、以前のバージョンに比べて、できることは増えているし、APIの構成も分かりやすくなっている。それに、ちゃんとGoogle Wave Robot Python API v2のドキュメントが整備されているのが嬉しいところ。何か面白いボットを作ってみたいな。
追記(2010/3/15):
Sandboxでも正常に動作するようになったみたい。
billowlet.py
#!/usr/bin/env python # -*- coding: utf-8 -*- """billowlet.py by nox, 2010.3.6""" import re, urllib, urllib2, random from google.appengine.ext import db from waveapi import events from waveapi import robot from waveapi import blip from waveapi import appengine_robot_runner from waveapi import simplejson HIRAGANA = u"あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん" KATAKANA = u"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン" class UserData(db.Model): user = db.StringProperty(multiline=False) status = db.StringProperty(multiline=False) def OnWaveletParticipantsChanged(event, wavelet): participants = event.participants_added for participant in participants: if participant != "billowlet@appspot.com": wavelet.reply(u"%s、おれを怒らせるなよ。" % participant.split("@")[0]) def OnWaveletSelfAdded(event, wavelet): wavelet.reply(u"おれはbillowlet。よろしくな。") def Translate(text, from_lang, to_lang): url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s%%7C%s" % (urllib.quote(text.encode("utf-8")), from_lang, to_lang) data = simplejson.loads(urllib2.urlopen(url).read()) return data["responseData"]["translatedText"] def BeCat(text): text = re.sub(u"。", u"にゃ。", text) text = re.sub(u"?|\?", u"にゃぁ?", text) text = re.sub(u"!|\!", u"にゃっ!", text) text = re.sub(u"な", u"にゃ", text) if text[-1] not in (u"。", u"?", u"?", u"!", u"!"): text += u"にゃ" return text def DotMarks(text): from_kana = u"かきくけこさしすせそたちつてとはひふへほカキクケコサシスセソタチツテトハヒフヘホ" to_kana = u"がぎぐげござじずぜぞだぢづでどばびぶべぼガギグゲゴザジズゼゾダヂヅデドバビブベボ" for f, t in zip(from_kana, to_kana): text = text.replace(f, t) return text def Laugh(text, ch): for i in range(len(text), 0, -1): text = text[:i] + ch + text[i:] return text.replace(u"。", u"").replace(u"、", u"") + ch * random.randint(3, 10) def Kana(idx): return HIRAGANA[idx] + u"|" + KATAKANA[idx] def OnBlipSubmitted(event, wavelet): blp = event.blip user = blp.creator opq = wavelet.get_operation_queue() data = UserData.all().filter("user =", user).get() if data: status = data.status else: status = None text = blp.text.strip() if status and re.match(u"ごめんなさい|ゆるして", text): json = opq.blip_create_child(blp.wave_id, blp.wavelet_id, blp.blip_id) child_blp = blip.Blip(json, wavelet.blips, opq) child_blp.append(u"ゆるしてやる。やれやれだぜ。".encode("utf-8")) if data: data.delete() st = (u"ネコになれ。", # 0 u"英国紳士になれ。", # 1 u"台湾に住め。", # 2 u"インチキ日本人になれ。", # 3 u"大事なことは2回言え。", # 4 u"笑え。", # 5 u"濁れ。", # 6 u"逆さまになれ。", # 7 u"どもれ。", # 8 u"うざくなれ。") # 9 fn = {st[0]: BeCat, st[1]: lambda (text): Translate(text, "ja", "en"), st[2]: lambda (text): Translate(text, "ja", "zh-TW"), st[3]: lambda (text): Translate(Translate(text, "ja", "en"), "en", "ja"), st[4]: lambda (text): text + text + u"\n大事なことなので2回言いました。", st[5]: lambda (text): Laugh(text, u"w"), st[6]: DotMarks, st[7]: lambda (text): text[::-1], st[8]: lambda (text): (text[0] + u"、") * 3 + text, st[9]: lambda (text): Laugh(text, u"っ")} angry = range(len(HIRAGANA)) random.shuffle(angry) if status: text = fn[status](text) blp.range(1, len(blp.text)).replace(text.encode("utf-8")) else: userdata = UserData() for i in range(len(st)): if re.search(Kana(angry[i]), text): status = st[i] break if status: json = opq.blip_create_child(blp.wave_id, blp.wavelet_id, blp.blip_id) child_blp = blip.Blip(json, wavelet.blips, opq) text = u"てめーはおれを怒らせた。%s" % status child_blp.append(text.encode("utf-8")) userdata.user = user userdata.status = status userdata.put() def main(): myRobot = robot.Robot("billowlet", image_url="http://billowlet.appspot.com/assets/icon.png", profile_url="http://billowlet.appspot.com/") myRobot.register_handler(events.WaveletParticipantsChanged, OnWaveletParticipantsChanged) myRobot.register_handler(events.BlipSubmitted, OnBlipSubmitted) myRobot.register_handler(events.WaveletSelfAdded, OnWaveletSelfAdded) appengine_robot_runner.run(myRobot) if __name__ == "__main__": main()
コメント