XMPPボット-メモボットの作成

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

[ 前のページ : XMPPボット-グループチャットボットの作成 | ]

入力内容をDB(Sqlite3)に保存するボットです。

このようなアプリケーションは、特にIM上で実現せずとも、Webアプリとして用意した方が使いやすいものができると思います。

ただ、使ってみてわかったのですが、IM上で動作するアプリの方がレスポンスが圧倒的に速く、思い立ってからメモを開始するまでの時間も短くできます。少量のメモをたくさんする方は、こういった形も検討する価値はあるのではないでしょうか。

xmpp-memobot.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# XMPPメモボット
# 入力されたデータをとりあえず記録する。
#

import xmpp
import sqlite3
import time
import config as CONFIG

# DB設計
# 
# [memodata] テーブル
# 
# seq_id   (integer) ID,オートインクリメント
# user     (text)    登録ユーザー
# textdata (text)    文字情報
# ctime    (integer) 登録日時タイムスタンプ


db=sqlite3.connect(CONFIG.dbFileName)

# Table check
c = db.cursor()
c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='memodata'")
if c.fetchone()[0] == 0 :
	# テーブルが存在しない(=初回起動)。作成する。
	
	sql="""CREATE TABLE memodata (
	 seq_id INTEGER NOT NULL PRIMARY KEY ,
	 user TEXT,
	 textdata TEXT,
	 ctime INTEGER
	 )"""
	c = db.cursor()
	c.execute(sql)
	db.commit()
	#print "##### DB create."
	
c.close()


def parseMessage(conn,mess):
	
	text=mess.getBody()
	
	userFull = unicode(mess.getFrom())
	if userFull.find('/')+1: user,userResource=userFull.split('/',1)
	else: user,userResource=userFull,''
	
	if text is None: return
	
	if text.find(' ')+1: command,args=text.split(' ',1)
	else: command,args=text,''
	command=command.lower()
	
	if command == "stat":
		# 状態を表示。総レコード数
		reply = u"[stat]\n"
		c = db.cursor()
		recordCount = c.execute("SELECT count(*) FROM memodata").fetchone()[0]
		c.close()
		reply = u"総レコード数 : "+str(recordCount)
	
	elif command == "all":
		# 対象ユーザーの登録レコードすべてを表示
		reply = u"[all]\n"
		c = db.cursor()
		c.execute("SELECT seq_id,textdata,ctime FROM memodata WHERE user = ? ORDER BY ctime",(user,))
		for record in c:
			#print "####",record
			strTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(record[2]))
			reply += "[ "+str(record[0])+" ] ("+strTime+")\n"
			reply += record[1]+"\n"
		c.close()
		
	elif command == "new":
		# 対象ユーザーの最新レコードを表示
		reply = u"[new]\n"
		if args.isdigit():
			num = int(args)
		else:
			num = 5
		c = db.cursor()
		sql="SELECT seq_id,textdata,ctime FROM (SELECT seq_id,textdata,ctime FROM memodata WHERE user = ? ORDER BY ctime desc LIMIT ?) ORDER BY ctime"
		c.execute(sql,(user,num,))
		for record in c:
			#print "####",record
			strTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(record[2]))
			reply += "[ "+str(record[0])+" ] ("+strTime+")\n"
			reply += record[1]+"\n"
		c.close()
		
	elif command == "old":
		# 対象ユーザーの古いレコードを表示
		reply = u"[old]\n"
		if args.isdigit():
			num = int(args)
		else:
			num = 5
		#print "#### num =",num
		sql="SELECT seq_id,textdata,ctime FROM memodata WHERE user = ? ORDER BY ctime LIMIT ?"
		c = db.cursor()
		c.execute(sql,(user,num,))
		for record in c:
			#print "####",record
			strTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(record[2]))
			reply += "[ "+str(record[0])+" ] ("+strTime+")\n"
			reply += record[1]+"\n"
		c.close()
		
	elif command == "del":
		# レコードを削除
		reply = u"[del]\n"
		if args.isdigit():
			num = int(args)
			sql="SELECT seq_id,textdata,ctime FROM memodata WHERE seq_id = ? and user = ?"
			c = db.cursor()
			c.execute(sql,(num,user,))
			record = c.fetchone()
			c.close()
			
			#print "#### record = ",record
			if record == None:
				reply += u"削除対象が存在しません。"
			else:
				strTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(record[2]))
				reply += "[ "+str(record[0])+" ] ("+strTime+")\n"
				reply += record[1]+"\n"
				
				sql="DELETE FROM memodata WHERE seq_id = ? and user = ?"
				c = db.cursor()
				c.execute(sql,(num,user,))
				c.close()
				db.commit()
				reply += u"削除しました。"
			
		else:
			reply += u"文法: del 削除するID"
	
	else:
		#入力された文字を登録
		timeStamp = time.mktime(time.localtime())
		#print "##### text =",text
		#print "##### timeStamp =",timeStamp
		
		sql="INSERT INTO memodata (user,textdata,ctime) VALUES (?,?,?)"
		c = db.cursor()
		c.execute(sql,(user,text,timeStamp))
		c.close()
		db.commit()
		reply = u"登録しました"
		
	
	conn.send(xmpp.Message(mess.getFrom(),reply))
	

class ConnectionError: pass
class AuthorizationError: pass

#
# XMPPボット基本クラス
#
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(**CONFIG.account)
bot.loop()

config.py

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

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

dbFileName="memodata.db"

ユーザーは自分の登録内容しか見れません。