New version of nemuspeak with class and xml configuration file

Bonus: fix exception when empty message received
This commit is contained in:
Némunaire 2012-02-21 00:41:36 +01:00
parent dc9965b0c9
commit 81342acd0c
2 changed files with 137 additions and 100 deletions

View File

@ -9,56 +9,53 @@ import re
import subprocess import subprocess
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
from xml.dom.minidom import parse
import thread import thread
if len(sys.argv) < 3: if len(sys.argv) == 1:
print "This script takes at least 2 args: server port [channel [channel [...]]]" print "This script takes exactly 1 arg: a XML config file"
sys.exit(0) sys.exit(1)
#HOST='192.168.0.242' SERVER = list()
#HOST = 'nemunai.re' SMILEY = list()
#PORT = 2778 g_queue = list()
HOST = sys.argv[1]
PORT = int(sys.argv[2])
#HOST = 'irc.rezosup.org'
#PORT = 6667
NICK = 'nemunaire'
IDENT = 'nemuspeak'
REALNAME = 'nemubot speaker'
OWNER = 'nemunaire' #The bot owner's nick
#CHANLIST = ['#42sh', '#korteam']
CHANLIST = []
if len(sys.argv) > 3:
for i in range(3, len(sys.argv)):
CHANLIST.append(sys.argv[i])
readbuffer = '' #Here we store all the messages from server
queue = []
talkEC = 0 talkEC = 0
stopSpk = 0 stopSpk = 0
lastmsg = [] lastmsg = []
s = socket.socket( ) #Create the socket dom = parse(sys.argv[1])
s.connect((HOST, PORT)) #Connect to server
s.send("PASS %s\r\n" % "McsuapTesbuf")
s.send("NICK %s\r\n" % NICK)
s.send("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME))
#s.send("JOIN %s\r\n" % CHANLIST)
print("Welcome on Nemubot speaker. I operate on %s. My PID is %i" % (CHANLIST, os.getpid())) config = dom.getElementsByTagName('config')[0]
if config.hasAttribute("nick"):
NICK = config.getAttribute("nick")
else:
NICK = "bot"
if config.hasAttribute("owner"):
OWNER = config.getAttribute("owner")
else:
OWNER = " "
if config.hasAttribute("realname"):
REALNAME = config.getAttribute("realname")
else:
REALNAME = OWNER + "'s bot"
for smiley in config.getElementsByTagName('smiley'):
if smiley.hasAttribute("txt") and smiley.hasAttribute("mood"):
SMILEY.append((smiley.getAttribute("txt"), smiley.getAttribute("mood")))
print ("%d smileys loaded"%len(SMILEY))
def speak(endstate): def speak(endstate):
global lastmsg, queue, talkEC, stopSpk global lastmsg, g_queue, talkEC, stopSpk
talkEC = 1 talkEC = 1
stopSpk = 0 stopSpk = 0
if len(lastmsg) < 1: if len(lastmsg) < 1:
lastmsg = queue.pop(0) lastmsg = g_queue.pop(0)
while not stopSpk and len(queue) > 0: while not stopSpk and len(g_queue) > 0:
msg = queue.pop(0) msg = g_queue.pop(0)
lang = "fr" lang = "fr"
sentence = "" sentence = ""
force = 0 force = 0
@ -73,55 +70,19 @@ def speak(endstate):
sentence += "Sur " + msg[0] + ". " sentence += "Sur " + msg[0] + ". "
force = 1 force = 1
action = 0
if msg[3].find("ACTION ") == 1: if msg[3].find("ACTION ") == 1:
sentence += msg[1] + " " sentence += msg[1] + " "
msg[3] = msg[3].replace("ACTION ", "") msg[3] = msg[3].replace("ACTION ", "")
elif msg[3].find(":)") >= 0: action = 1
sentence += msg[1] + " sourit : " for (txt, mood) in SMILEY:
msg[3] = msg[3].replace(":)", "") if msg[3].find(txt) >= 1:
elif msg[3].find(";)") >= 0: sentence += msg[1] + " %s : "%mood
sentence += msg[1] + " fait un clin d'oeil : " msg[3] = msg[3].replace(txt, "")
msg[3] = msg[3].replace(";)", "") action = 1
elif msg[3].find(":(") >= 0: break
sentence += msg[1] + " est triste : "
msg[3] = msg[3].replace(":(", "")
elif msg[3].find("<3") >= 0:
sentence += msg[1] + " aime : "
msg[3] = msg[3].replace("<3", "")
elif msg[3].find(":'(") >= 0 or msg[3].find(";(") >= 0:
sentence += msg[1] + " pleure : "
msg[3] = msg[3].replace(":'(", "")
msg[3] = msg[3].replace(";(", "")
elif msg[3].find(":D") >= 0 or msg[3].find(":d") >= 0:
sentence += msg[1] + " rit : "
msg[3] = msg[3].replace(":D", "")
msg[3] = msg[3].replace(":d", "")
elif msg[3].find(":P") >= 0 or msg[3].find(":p") >= 0:
sentence += msg[1] + " tire la langue : "
msg[3] = msg[3].replace(":P", "")
msg[3] = msg[3].replace(":p", "")
elif msg[3].find(":S") >= 0 or msg[3].find(":s") >= 0:
sentence += msg[1] + " est embarassé : "
msg[3] = msg[3].replace(":S", "")
msg[3] = msg[3].replace(":s", "")
elif msg[3].find("XD") >= 0 or msg[3].find("xd") >= 0 or msg[3].find("xD") >= 0 or msg[3].find("Xd") >= 0 or msg[3].find("X)") >= 0 or msg[3].find("x)") >= 0:
sentence += msg[1] + " se marre : "
msg[3] = msg[3].replace("xd", "")
msg[3] = msg[3].replace("XD", "")
msg[3] = msg[3].replace("Xd", "")
msg[3] = msg[3].replace("xD", "")
msg[3] = msg[3].replace("X)", "")
msg[3] = msg[3].replace("x)", "")
elif msg[3].find("\\o/") >= 0 or msg[3].find("\\O/") >= 0:
sentence += msg[1] + " fait une accolade : "
msg[3] = msg[3].replace("\\o/", "")
msg[3] = msg[3].replace("\\O/", "")
elif msg[3].find("/o/") >= 0 or msg[3].find("\\o\\") >= 0:
sentence += msg[1] + " danse : "
msg[3] = msg[3].replace("/o/", "")
msg[3] = msg[3].replace("\\o\\", "")
elif force or msg[1] != lastmsg[1]: if action == 0 and (force or msg[1] != lastmsg[1]):
sentence += msg[1] + " dit : " sentence += msg[1] + " dit : "
if re.match(".*(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+.*", msg[3]) is not None: if re.match(".*(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+.*", msg[3]) is not None:
@ -132,14 +93,16 @@ def speak(endstate):
if re.match("^ *[^a-zA-Z0-9 ][a-zA-Z]{2}[^a-zA-Z0-9 ]", msg[3]) is not None: if re.match("^ *[^a-zA-Z0-9 ][a-zA-Z]{2}[^a-zA-Z0-9 ]", msg[3]) is not None:
if sentence != "": if sentence != "":
subprocess.call(["espeak", "-v", "fr", sentence]) intro = subprocess.call(["espeak", "-v", "fr", sentence])
#intro.wait()
lang = msg[3][1:3].lower() lang = msg[3][1:3].lower()
sentence = msg[3][4:] sentence = msg[3][4:]
else: else:
sentence += msg[3] sentence += msg[3]
subprocess.call(["espeak", "-v", lang, sentence]) spk = subprocess.call(["espeak", "-v", lang, sentence])
#spk.wait()
lastmsg = msg lastmsg = msg
@ -149,13 +112,17 @@ def speak(endstate):
talkEC = 1 talkEC = 1
def parsemsg(msg): def parsemsg (msg, CHANLIST):
global talkEC, stopSpk, queue global g_queue, NICK, stopSpk, talkEC
complete = msg[1:].split(':',1) #Parse the message into useful data complete = msg[1:].split(':',1) #Parse the message into useful data
info = complete[0].split(' ') info = complete[0].split(' ')
msgpart = complete[1] msgpart = complete[1]
sender = info[0].split('!') sender = info[0].split('!')
#Skip on empty content
if len(msgpart) <= 0:
return
#Bad format, try to fix that #Bad format, try to fix that
if len(info) == 1: if len(info) == 1:
pv = msg.index(" ", msg.index("PRIVMSG") + 9) pv = msg.index(" ", msg.index("PRIVMSG") + 9)
@ -179,14 +146,17 @@ def parsemsg(msg):
thread.start_new_thread(speak, (0,)) thread.start_new_thread(speak, (0,))
elif cmd[0] == 'reset': elif cmd[0] == 'reset':
while len(queue) > 0: while len(g_queue) > 0:
queue.pop() g_queue.pop()
elif cmd[0] == 'save': elif cmd[0] == 'save':
if talkEC == 0: if talkEC == 0:
talkEC = 1 talkEC = 1
stopSpk = 1 stopSpk = 1
elif cmd[0] == 'test':
parsemsg(":Quelqun!someone@p0m.fr PRIVMSG %s :Ceci est un message de test ;)"%(CHANLIST[0]), CHANLIST)
elif cmd[0] == 'list': elif cmd[0] == 'list':
print "Currently listened channels:" print "Currently listened channels:"
for chan in CHANLIST: for chan in CHANLIST:
@ -205,15 +175,37 @@ def parsemsg(msg):
print cmd[1] + " not in listened channels" print cmd[1] + " not in listened channels"
elif sender[0] != OWNER and (len(CHANLIST) == 0 or CHANLIST.count(info[2]) > 0 or info[2] == NICK): elif sender[0] != OWNER and (len(CHANLIST) == 0 or CHANLIST.count(info[2]) > 0 or info[2] == NICK):
queue.append([info[2], sender[0], datetime.now(), msgpart]) g_queue.append([info[2], sender[0], datetime.now(), msgpart])
if talkEC == 0: if talkEC == 0:
thread.start_new_thread(speak, (0,)) thread.start_new_thread(speak, (0,))
def read(): class Server:
global s, readbuffer def __init__(self, server):
if server.hasAttribute("server"):
self.host = server.getAttribute("server")
else:
self.host = "localhost"
if server.hasAttribute("port"):
self.port = int(server.getAttribute("port"))
else:
self.port = 6667
if server.hasAttribute("password"):
self.password = server.getAttribute("password")
else:
self.password = None
self.channels = list()
for channel in server.getElementsByTagName('channel'):
self.channels.append(channel.getAttribute("name"))
def launch(self):
thread.start_new_thread(self.connect, ())
def read(self):
readbuffer = "" #Here we store all the messages from server
while 1: while 1:
readbuffer = readbuffer + s.recv(1024) #recieve server messages readbuffer = readbuffer + self.s.recv(1024) #recieve server messages
temp = readbuffer.split("\n") temp = readbuffer.split("\n")
readbuffer = temp.pop( ) readbuffer = temp.pop( )
@ -221,11 +213,29 @@ def read():
line = line.rstrip() #remove trailing 'rn' line = line.rstrip() #remove trailing 'rn'
if line.find('PRIVMSG') != -1: #Call a parsing function if line.find('PRIVMSG') != -1: #Call a parsing function
parsemsg(line) parsemsg(line, self.channels)
line = line.split() line = line.split()
if(line[0] == 'PING'): #If server pings then pong if(line[0] == 'PING'): #If server pings then pong
s.send("PONG %s\r\n" % line[1]) self.s.send("PONG %s\r\n" % line[1])
read() def connect(self):
self.s = socket.socket( ) #Create the socket
self.s.connect((self.host, self.port)) #Connect to server
if self.password != None:
self.s.send("PASS %s\r\n" % self.password)
self.s.send("NICK %s\r\n" % NICK)
self.s.send("USER %s %s bla :%s\r\n" % (NICK, self.host, REALNAME))
self.read()
for server in config.getElementsByTagName('server'):
srv = Server(server)
srv.launch()
print ("Nemuspeak ready, waiting for new messages...")
prompt=""
while prompt != "quit":
prompt=sys.stdin.readlines ()
sys.exit(0)

27
speak_sample.xml Normal file
View File

@ -0,0 +1,27 @@
<config nick="nemubot" realname="nemubot speaker" owner="nemunaire">
<!-- Bitlbee/Minbif -->
<server server="nemunai.re" port="6666" password="bitlbee" />
<!-- Rezosup -->
<server server="nemunai.re" port="6667">
<channel name="#epita" />
</server>
<smiley txt=":)" mood="sourit" />
<smiley txt=":(" mood="est triste" />
<smiley txt=";)" mood="fait un clin d'oeil" />
<smiley txt="&lt;3" mood="aime" />
<smiley txt=":'(" mood="pleure" />
<smiley txt=";(" mood="pleure" />
<smiley txt=":D" mood="rit" />
<smiley txt=":d" mood="rit" />
<smiley txt="xd" mood="se marre" />
<smiley txt="xD" mood="se marre" />
<smiley txt="XD" mood="se marre" />
<smiley txt="Xd" mood="se marre" />
<smiley txt="x)" mood="se marre" />
<smiley txt="X)" mood="se marre" />
<smiley txt="/o/" mood="danse" />
<smiley txt="\\o\\" mood="danse" />
<smiley txt="\\o/" mood="fait une accolade" />
</config>