XMPPボット-ボット雛形の作成

Last-modified: 2014-08-16 (土) 12:41:50 (2013d)

[ 前のページ : XMPPボット-Python実行環境の準備 | ]

testbot.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import xmpp

account = {
	'JID'     : 'test-bot@example.com',
	'Password': 'PASSWORD',
	'Server'  : '127.0.0.1',
	'Port'    : 5222,
}

def parseMessage(conn,mess):
	
	text=mess.getBody()
	user=mess.getFrom()
	
	if text is None:
		#print "Null message catched."
		return
	
	reply = u'Reply: '+text;
	
	print "##### text =",text.encode('utf-8','ignore')
	print "##### reply = ",reply.encode('utf-8','ignore')
	
	conn.send(xmpp.Message(user,reply))

class ConnectionError: pass
class AuthorizationError: pass

class Bot:
	def __init__(self, JID, Password,Server,Port):
		jid = xmpp.JID(JID)
		self.connection = xmpp.Client(jid.getDomain(), debug=[])
		
		result = self.connection.connect(server=(Server,Port))
		if result is None: raise ConnectionError
		result = self.connection.auth(jid.getNode(), Password)
		if result is None: raise AuthorizationError
		
		self.connection.RegisterHandler('message',parseMessage)
		self.connection.sendInitPresence()
		
	def loop(self):
		try:
			while self.connection.Process(1):
				pass
		except KeyboardInterrupt:
			pass

bot = Bot(**account)
bot.loop()

testbot.py というファイル名で保存し、実行します。ejabberdが起動しているサーバ上で実行されることを想定しています。

実行すると、IMクライアント上で、先ほどのアカウントがアクティブになり、

testbot-contactlist.png

なにか発言すると、文頭に Reply: をつけて返答します。

testbot-chat.png

実行環境のコンソールには

$ ./testbot.py 
An error occurred while looking up _xmpp-client._tcp.127.0.0.1
##### text = Hello.
##### reply =  Reply: Hello.
##### text = こんにちは。
##### reply =  Reply: こんにちは。

というログが表示されます。

コード説明

account (ディクショナリ)

Jabberアカウントの設定項目です。外部ファイルにするのが正しいのかもしれませんが、それほど長いコードでもないので中に書きました。
'Server':'127.0.0.1' となっていますが、ejabberdが動作するサーバ上で動かすために自分のアドレスを指定しています。ejabberdが動作するサーバとボットが動作するサーバが異なる場合は、'192.168.0.4' とかでいいかと思います。

参考までに、GoogleTalk?で動作させる場合は

account = {
	'JID'     : 'example@gmail.com',
	'Password': 'foobarfoobar',
	'Server'  : 'talk.google.com',
	'Port'    : 5223,
}

このようになります。

parseMessage (関数)

受信したメッセージに対して、処理を行う関数です。 一応、イベントドリブンのコールバック関数的に動作し、Botクラス内で登録されています。

メッセージの受信だけでなく、他のユーザーが文字を入力しようとしている時などにも呼び出されるため、実際にメッセージを受信した時のみ動くよう、

	if text is None:
		#print "Null message catched."
		return

というコードで振り分けを行っています。…が、もっとスマートな方法があるのかも…。

また、このtext(mess.getBody())ですが、unicode型となりますので、printする場合はutf-8かなんかでencodeして、str型にした方が無難です。

       print "##### text =",text.encode('utf-8','ignore')
       print "##### reply = ",reply.encode('utf-8','ignore')

がそれにあたります。

encodeしないでprintすると、標準出力をファイルにリダイレクトした時とかにエラーが発生することがあります。'ignore'オプションは一応つけてますが、特に必要ないかもしれません。

Bot (クラス)

XMPPボットの基本クラスです。 サーバへの接続やイベントハンドラの登録などを行います。

基本的に、あまり編集しません。