New version of nemuspeak with class and xml configuration file
Bonus: fix exception when empty message received
This commit is contained in:
parent
dc9965b0c9
commit
81342acd0c
194
nemuspeak.py
194
nemuspeak.py
@ -9,56 +9,53 @@ import re
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from xml.dom.minidom import parse
|
||||
import thread
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print "This script takes at least 2 args: server port [channel [channel [...]]]"
|
||||
sys.exit(0)
|
||||
if len(sys.argv) == 1:
|
||||
print "This script takes exactly 1 arg: a XML config file"
|
||||
sys.exit(1)
|
||||
|
||||
#HOST='192.168.0.242'
|
||||
#HOST = 'nemunai.re'
|
||||
#PORT = 2778
|
||||
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 = []
|
||||
SERVER = list()
|
||||
SMILEY = list()
|
||||
g_queue = list()
|
||||
talkEC = 0
|
||||
stopSpk = 0
|
||||
lastmsg = []
|
||||
|
||||
s = socket.socket( ) #Create the socket
|
||||
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)
|
||||
dom = parse(sys.argv[1])
|
||||
|
||||
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):
|
||||
global lastmsg, queue, talkEC, stopSpk
|
||||
global lastmsg, g_queue, talkEC, stopSpk
|
||||
talkEC = 1
|
||||
stopSpk = 0
|
||||
|
||||
if len(lastmsg) < 1:
|
||||
lastmsg = queue.pop(0)
|
||||
lastmsg = g_queue.pop(0)
|
||||
|
||||
while not stopSpk and len(queue) > 0:
|
||||
msg = queue.pop(0)
|
||||
while not stopSpk and len(g_queue) > 0:
|
||||
msg = g_queue.pop(0)
|
||||
lang = "fr"
|
||||
|
||||
sentence = ""
|
||||
force = 0
|
||||
|
||||
@ -73,55 +70,19 @@ def speak(endstate):
|
||||
sentence += "Sur " + msg[0] + ". "
|
||||
force = 1
|
||||
|
||||
action = 0
|
||||
if msg[3].find("ACTION ") == 1:
|
||||
sentence += msg[1] + " "
|
||||
msg[3] = msg[3].replace("ACTION ", "")
|
||||
elif msg[3].find(":)") >= 0:
|
||||
sentence += msg[1] + " sourit : "
|
||||
msg[3] = msg[3].replace(":)", "")
|
||||
elif msg[3].find(";)") >= 0:
|
||||
sentence += msg[1] + " fait un clin d'oeil : "
|
||||
msg[3] = msg[3].replace(";)", "")
|
||||
elif msg[3].find(":(") >= 0:
|
||||
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\\", "")
|
||||
action = 1
|
||||
for (txt, mood) in SMILEY:
|
||||
if msg[3].find(txt) >= 1:
|
||||
sentence += msg[1] + " %s : "%mood
|
||||
msg[3] = msg[3].replace(txt, "")
|
||||
action = 1
|
||||
break
|
||||
|
||||
elif force or msg[1] != lastmsg[1]:
|
||||
if action == 0 and (force or msg[1] != lastmsg[1]):
|
||||
sentence += msg[1] + " dit : "
|
||||
|
||||
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 sentence != "":
|
||||
subprocess.call(["espeak", "-v", "fr", sentence])
|
||||
intro = subprocess.call(["espeak", "-v", "fr", sentence])
|
||||
#intro.wait()
|
||||
|
||||
lang = msg[3][1:3].lower()
|
||||
sentence = msg[3][4:]
|
||||
else:
|
||||
sentence += msg[3]
|
||||
|
||||
subprocess.call(["espeak", "-v", lang, sentence])
|
||||
spk = subprocess.call(["espeak", "-v", lang, sentence])
|
||||
#spk.wait()
|
||||
|
||||
lastmsg = msg
|
||||
|
||||
@ -149,13 +112,17 @@ def speak(endstate):
|
||||
talkEC = 1
|
||||
|
||||
|
||||
def parsemsg(msg):
|
||||
global talkEC, stopSpk, queue
|
||||
def parsemsg (msg, CHANLIST):
|
||||
global g_queue, NICK, stopSpk, talkEC
|
||||
complete = msg[1:].split(':',1) #Parse the message into useful data
|
||||
info = complete[0].split(' ')
|
||||
msgpart = complete[1]
|
||||
sender = info[0].split('!')
|
||||
|
||||
#Skip on empty content
|
||||
if len(msgpart) <= 0:
|
||||
return
|
||||
|
||||
#Bad format, try to fix that
|
||||
if len(info) == 1:
|
||||
pv = msg.index(" ", msg.index("PRIVMSG") + 9)
|
||||
@ -179,14 +146,17 @@ def parsemsg(msg):
|
||||
thread.start_new_thread(speak, (0,))
|
||||
|
||||
elif cmd[0] == 'reset':
|
||||
while len(queue) > 0:
|
||||
queue.pop()
|
||||
while len(g_queue) > 0:
|
||||
g_queue.pop()
|
||||
|
||||
elif cmd[0] == 'save':
|
||||
if talkEC == 0:
|
||||
talkEC = 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':
|
||||
print "Currently listened channels:"
|
||||
for chan in CHANLIST:
|
||||
@ -205,15 +175,37 @@ def parsemsg(msg):
|
||||
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):
|
||||
queue.append([info[2], sender[0], datetime.now(), msgpart])
|
||||
g_queue.append([info[2], sender[0], datetime.now(), msgpart])
|
||||
if talkEC == 0:
|
||||
thread.start_new_thread(speak, (0,))
|
||||
|
||||
|
||||
def read():
|
||||
global s, readbuffer
|
||||
class Server:
|
||||
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:
|
||||
readbuffer = readbuffer + s.recv(1024) #recieve server messages
|
||||
readbuffer = readbuffer + self.s.recv(1024) #recieve server messages
|
||||
temp = readbuffer.split("\n")
|
||||
readbuffer = temp.pop( )
|
||||
|
||||
@ -221,11 +213,29 @@ def read():
|
||||
line = line.rstrip() #remove trailing 'rn'
|
||||
|
||||
if line.find('PRIVMSG') != -1: #Call a parsing function
|
||||
parsemsg(line)
|
||||
parsemsg(line, self.channels)
|
||||
|
||||
line = line.split()
|
||||
|
||||
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
27
speak_sample.xml
Normal 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="<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>
|
Loading…
x
Reference in New Issue
Block a user