1
0
Fork 0

Merge branch 'master' of /home/nemunaire/git/nemubot

Conflicts:
	nemubot.py
	watchWebsite.py
This commit is contained in:
Némunaire 2012-04-30 18:22:10 +02:00
commit f676ce11c6
10 changed files with 457 additions and 285 deletions

113
alias.py Normal file
View File

@ -0,0 +1,113 @@
# coding=utf-8
import re
import sys
from datetime import datetime
from xml.dom.minidom import parse
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
filename = ""
ALIAS = {}
variables = {}
def load_module(datas_path):
"""Load this module"""
global ALIAS, filename
SCORES = dict ()
filename = datas_path + "/alias.xml"
sys.stdout.write ("Loading aliaslist ... ")
dom = parse(filename)
for item in dom.documentElement.getElementsByTagName("alias"):
ALIAS[item.getAttribute("alias")] = item.getAttribute("origin")
for item in dom.documentElement.getElementsByTagName("variable"):
variables[item.getAttribute("name")] = item.getAttribute("value")
print ("done (%d aliases and %d vars)" % (len(ALIAS), len (variables)))
def save_module():
"""Save the aliases"""
global ALIAS, variables, filename
sys.stdout.write ("Saving aliases ... ")
impl = getDOMImplementation()
newdoc = impl.createDocument(None, 'aliaslist', None)
top = newdoc.documentElement
for name in ALIAS.keys():
item = parseString ('<alias alias="%s" origin="%s" />' % (name, ALIAS[name])).documentElement
top.appendChild(item);
for name in variables.keys():
item = parseString ('<variable name="%s" value="%s" />' % (name, variables[name])).documentElement
top.appendChild(item);
with open(filename, "w") as f:
newdoc.writexml (f)
print ("done")
def help_tiny ():
"""Line inserted in the response to the command !help"""
return "alias module"
def help_full ():
return "TODO"
def parseanswer (msg):
global ALIAS, variables
if msg.cmd[0] == "set":
if len (msg.cmd) > 2:
variables[msg.cmd[1]] = " ".join(msg.cmd[2:])
msg.send_snd("Variable $%s définie." % msg.cmd[1])
else:
msg.send_snd("!set prend au minimum deux arguments : le nom de la variable et sa valeur.")
return True
elif msg.cmd[0] in ALIAS:
msg.content = msg.content.replace("!" + msg.cmd[0], ALIAS[msg.cmd[0]], 1)
cnt = msg.content.split(' ')
for i in range(0,len(cnt)):
if len (cnt[i]) and cnt[i][0] == '$':
if cnt[i][1] == '$' and len(cnt[i]) == 2:
cnt[i] = "$"
elif cnt[i] == "$sender":
cnt[i] = msg.sender
elif cnt[i] == "$chan" or cnt[i] == "$channel":
cnt[i] = msg.channel
elif cnt[i] == "$date":
now = datetime.now()
cnt[i] = ("%d/%d/%d %d:%d:%d"%(now.day, now.month, now.year, now.hour, now.minute, now.second))
elif cnt[i] == "$date,":
now = datetime.now()
cnt[i] = ("%d/%d/%d %d:%d:%d,"%(now.day, now.month, now.year, now.hour, now.minute, now.second))
elif cnt[i] == "$date.":
now = datetime.now()
cnt[i] = ("%d/%d/%d %d:%d:%d."%(now.day, now.month, now.year, now.hour, now.minute, now.second))
elif cnt[i][1:] in variables:
cnt[i] = variables[cnt[i][1:]]
else:
cnt[i] = ""
msg.content = " ".join(cnt)
msg.reparsemsg()
return True
else:
return False
def parseask (msg):
global ALIAS
if re.match(".*(set|cr[ée]{2}|nouvel(le)?) alias.*", msg.content) is not None:
result = re.match(".*alias !?([a-zA-Z0-9_-]+) (pour|=|:) (.+)$", msg.content)
if result.group(1) in ALIAS or result.group(3).find("alias") >= 0:
msg.send_snd("Cet alias est déjà défini.")
else:
ALIAS[result.group(1)] = result.group(3)
msg.send_snd("Nouvel alias %s défini avec succès." % result.group(1))
return True
return False
def parselisten (msg):
return False

View File

@ -26,7 +26,7 @@ class AtomEntry:
self.link = node.getElementsByTagName("link")[0].getAttribute ("href")
else:
self.link = None
if len (node.getElementsByTagName("category")) > 1:
if len (node.getElementsByTagName("category")) >= 1:
self.category = node.getElementsByTagName("category")[0].getAttribute ("term")
else:
self.category = None

View File

@ -5,15 +5,30 @@ import sys
from datetime import timedelta
from datetime import datetime
from datetime import date
import time
from xml.dom.minidom import parse
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
filename = ""
EVENTS = {}
STREND = {}
class Strend:
def __init__(self, item):
if item is not None:
self.name = item.getAttribute("name")
self.start = datetime.fromtimestamp (time.mktime (time.strptime (item.getAttribute("start")[:19], "%Y-%m-%d %H:%M:%S")))
self.proprio = item.getAttribute("proprio")
else:
self.start = datetime.now()
def xmlparse(node):
"""Parse the given node and add events to the global list."""
for item in node.getElementsByTagName("strend"):
STREND[item.getAttribute("name")] = Strend(item)
for item in node.getElementsByTagName("event"):
if (item.hasAttribute("year")):
year = int(item.getAttribute("year"))
@ -48,8 +63,9 @@ def xmlparse(node):
def load_module(datas_path):
"""Load this module"""
global EVENTS, filename
global EVENTS, STREND, filename
EVENTS = {}
STREND = {}
filename = datas_path + "/events.xml"
sys.stdout.write ("Loading events ... ")
@ -67,6 +83,10 @@ def save_module():
newdoc = impl.createDocument(None, 'events', None)
top = newdoc.documentElement
for name in STREND.keys():
item = parseString ('<strend name="%s" start="%s" proprio="%s" />' % (name, STREND[name].start, STREND[name].proprio)).documentElement
top.appendChild(item);
for name in EVENTS.keys():
(day, msg_before, msg_after) = EVENTS[name]
bonus=""
@ -96,6 +116,7 @@ def help_full ():
def parseanswer(msg):
global STREND
if msg.cmd[0] == "we" or msg.cmd[0] == "week-end" or msg.cmd[0] == "weekend":
ndate = datetime.today() + timedelta(5 - datetime.today().weekday())
ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1)
@ -116,6 +137,30 @@ def parseanswer(msg):
"Il reste %s avant les vacances :)",
"Profitons, c'est les vacances depuis %s."))
return True
elif msg.cmd[0] == "start" and len(msg.cmd) > 1:
if msg.cmd[1] not in STREND:
STREND[msg.cmd[1]] = Strend(None)
STREND[msg.cmd[1]].proprio = msg.sender
STREND[msg.cmd[1]].name = msg.cmd[1]
msg.send_snd ("%s commencé le %s"% (msg.cmd[1], datetime.now()))
else:
msg.send_snd ("%s existe déjà."% (msg.cmd[1]))
elif msg.cmd[0] == "end" and len(msg.cmd) > 1:
if msg.cmd[1] in STREND:
msg.send_chn ("%s a duré %s." % (msg.cmd[1], msg.just_countdown(datetime.now () - STREND[msg.cmd[1]].start)))
if STREND[msg.cmd[1]].proprio == msg.sender:
del STREND[msg.cmd[1]]
else:
msg.send_snd ("Vous ne pouvez pas terminer le compteur %s, créé par %s."% (msg.cmd[1], STREND[msg.cmd[1]].proprio))
else:
msg.send_snd ("%s n'est pas un compteur connu."% (msg.cmd[1]))
elif msg.cmd[0] == "eventslist" or msg.cmd[0] == "eventlist" or msg.cmd[0] == "eventsliste" or msg.cmd[0] == "eventliste":
msg.send_snd ("Compteurs connus : %s." % ", ".join(STREND.keys()))
elif msg.cmd[0] in STREND:
msg.send_chn ("%s commencé il y a %s." % (msg.cmd[0], msg.just_countdown(datetime.now () - STREND[msg.cmd[0]].start)))
elif msg.cmd[0] in EVENTS:
(day, msg_before, msg_after) = EVENTS[msg.cmd[0]]
if day is None:

View File

@ -1,17 +1,95 @@
#!/usr/bin/python2.7
# coding=utf-8
from datetime import datetime
from datetime import timedelta
import re
import socket
import sys
import string
import time
import imp
import random
from xml.dom.minidom import parse
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
BANLIST = []
CREDITS = {}
filename = ""
def load_module(datas_path):
global BANLIST, CREDITS, filename
CREDITS = dict ()
BANLIST = list ()
filename = datas_path + "/general.xml"
sys.stdout.write ("Loading banlist ... ")
dom = parse(filename)
for item in dom.documentElement.getElementsByTagName("ban"):
BANLIST.append(item.getAttribute("name"))
print ("done (%d users banned)" % (len(BANLIST)))
def save_module():
global BANLIST, ALIAS, filename
sys.stdout.write ("Saving banlist ... ")
impl = getDOMImplementation()
newdoc = impl.createDocument(None, 'global', None)
top = newdoc.documentElement
for name in BANLIST:
item = parseString ('<ban name="%s" />' % (name)).documentElement
top.appendChild(item);
with open(filename, "w") as f:
newdoc.writexml (f)
print ("done")
class Credits:
def __init__ (self, name):
self.name = name
self.credits = 5
self.randsec = timedelta(seconds=random.randint(0, 55))
self.lastmessage = datetime.now() + self.randsec
self.iask = True
def ask(self):
if self.name in BANLIST:
return False
now = datetime.now() + self.randsec
if self.lastmessage.minute == now.minute and (self.lastmessage.second == now.second or self.lastmessage.second == now.second - 1):
print("AUTOBAN %s: too low time between messages" % self.name)
BANLIST.append(self.name)
#self.credits -= self.credits / 2 #Une alternative
return False
self.iask = True
return self.credits > 0 or self.lastmessage.minute != now.minute
def speak(self):
if self.iask:
self.iask = False
now = datetime.now() + self.randsec
if self.lastmessage.minute != now.minute:
self.credits = min (15, self.credits + 5)
self.lastmessage = now
self.credits -= 1
return self.credits > -3
def to_string(self):
print ("%s: %d ; reset: %d" % (self.name, self.credits, self.randsec.seconds))
class Message:
def __init__ (self, srv, line):
self.srv = srv
self.time = datetime.now ()
self.channel = ""
self.content = ""
line = line.rstrip() #remove trailing 'rn'
if line.find(' PRIVMSG ') != -1: #Call a parsing function
@ -20,9 +98,20 @@ class Message:
self.cmd = "PRIVMSG"
self.sender = (info[0].split('!'))[0]
self.realname = (info[0].split('!'))[1]
self.channel = info[2]
self.content = complete[1]
elif line.find(' ACTION ') != -1:
complete = line[1:].split(':',1) #Parse the message into useful data
info = complete[0].split(' ')
self.cmd = "ACTION"
self.sender = (info[0].split('!'))[0]
self.realname = (info[0].split('!'))[1]
self.channel = info[2]
self.content = complete[1]
elif line.find(' NICK ') != -1:
complete = line[1:].split(':',1) #Parse the message into useful data
if len(complete) > 1:
@ -30,6 +119,7 @@ class Message:
self.cmd = "NICK"
self.sender = (info[0].split('!'))[0]
self.realname = (info[0].split('!'))[1]
self.content = complete[1]
else:
self.cmd = "NONE"
@ -41,6 +131,7 @@ class Message:
self.cmd = "JOIN"
self.sender = (info[0].split('!'))[0]
self.realname = (info[0].split('!'))[1]
self.channel = complete[1]
else:
self.cmd = "NONE"
@ -51,12 +142,23 @@ class Message:
self.cmd = "PART"
self.sender = (info[0].split('!'))[0]
self.realname = (info[0].split('!'))[1]
self.channel = info[2]
if len (complete) > 1:
self.content = complete[1]
else:
self.content = ""
elif line.find(' MODE ') != -1:
complete = line[1:].split(' ')
if len(complete) >= 5:
self.cmd = "MODE"
self.channel = complete[2]
self.mode = complete[3]
self.sender = complete[4]
else:
self.cmd = "NONE"
elif line.find(' PING ') != -1: #If server pings then pong
line = line.split()
@ -69,26 +171,41 @@ class Message:
def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
self.srv.send_msg (channel, msg, cmd, endl)
if CREDITS[self.realname].speak():
self.srv.send_msg (channel, msg, cmd, endl)
def send_global (self, msg, cmd = "PRIVMSG", endl = "\r\n"):
self.srv.send_global (msg, cmd, endl)
if CREDITS[self.realname].speak():
self.srv.send_global (msg, cmd, endl)
def send_chn (self, msg):
"""Send msg on the same channel as receive message"""
self.srv.send_msg (self.channel, msg)
if CREDITS[self.realname].speak():
if self.channel == self.srv.nick:
self.send_snd (msg)
else:
self.srv.send_msg (self.channel, msg)
def send_snd (self, msg):
"""Send msg to the sender who send the original message"""
self.srv.send_msg (self.sender, msg)
if CREDITS[self.realname].speak():
self.srv.send_msg_usr (self.sender, msg)
def authorize (self):
if self.realname not in CREDITS:
CREDITS[self.realname] = Credits(self.realname)
elif self.content[0] == '`':
return True
elif not CREDITS[self.realname].ask():
return False
return self.srv.accepted_channel(self.channel)
def treat (self, mods):
if self.cmd == "PING":
self.pong ()
elif self.cmd == "PRIVMSG" and self.srv.accepted_channel(self.channel):
elif self.cmd == "PRIVMSG" and self.authorize():
self.parsemsg (mods)
elif self.cmd == "NICK":
print ("%s change de nom pour %s" % (self.sender, self.content))
@ -102,6 +219,12 @@ class Message:
self.srv.s.send(("PONG %s\r\n" % self.content).encode ())
def reparsemsg(self):
if self.mods is not None:
self.parsemsg(self.mods)
else:
print ("Can't reparse message")
def parsemsg (self, mods):
#Treat all messages starting with 'nemubot:' as distinct commands
if self.content.find("%s:"%self.srv.nick) == 0:
@ -124,12 +247,10 @@ class Message:
elif re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content) is not None:
result = re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content)
if self.srv.channels.count(result.group(1)):
self.send_msg(result.group(1), result.group(2))
self.send_msg(result.group(1), result.group(2))
elif re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content) is not None:
result = re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content)
if self.srv.channels.count(result.group(2)):
self.send_msg(result.group(2), result.group(1))
self.send_msg(result.group(2), result.group(1))
#Try modules
else:
@ -153,8 +274,27 @@ class Message:
self.send_snd ("Usage: `reload /module/.")
self.send_snd ("Loaded modules: " + ', '.join(mods.keys()) + ".")
elif self.cmd[0] == "ban":
if len(self.cmd) > 1:
BANLIST.append(self.cmd[1])
else:
print (BANLIST)
elif self.cmd[0] == "banlist":
print (BANLIST)
elif self.cmd[0] == "unban":
if len(self.cmd) > 1:
BANLIST.remove(self.cmd[1])
elif self.cmd[0] == "credits":
if len(self.cmd) > 1 and self.cmd[1] in CREDITS:
self.send_chn ("%s a %d crédits." % (self.cmd[1], CREDITS[self.cmd[1]]))
else:
for c in CREDITS.keys():
print (CREDITS[c].to_string())
#Messages stating with !
elif self.content[0] == '!':
self.mods = mods
self.cmd = self.content[1:].split(' ')
if self.cmd[0] == "help":
if len (self.cmd) > 1:

View File

@ -10,10 +10,10 @@ from datetime import datetime
from datetime import timedelta
from xml.dom.minidom import parse
imports = ["birthday", "qd", "events", "youtube", "watchWebsite", "soutenance", "whereis"]
imports = ["birthday", "qd", "events", "youtube", "watchWebsite", "soutenance", "whereis", "alias"]
imports_launch = ["watchWebsite"]
mods = {}
import server
import server, message
if len(sys.argv) != 2 and len(sys.argv) != 3:
print ("This script takes exactly 1 arg: a XML config file")
@ -26,6 +26,9 @@ def onSignal(signum, frame):
for imp in mods.keys():
mods[imp].save_module ()
#Save banlist before quit
message.save_module ()
sys.exit (0)
signal.signal(signal.SIGINT, onSignal)
@ -33,12 +36,13 @@ if len(sys.argv) == 3:
basedir = sys.argv[2]
else:
basedir = "./"
print (basedir, len(sys.argv))
dom = parse(sys.argv[1])
config = dom.getElementsByTagName('config')[0]
servers = list ()
message.load_module (basedir + "/datas/")
for imp in imports:
mod = __import__ (imp)
mods[imp] = mod
@ -59,103 +63,3 @@ while prompt != "quit":
prompt=sys.stdin.readlines ()
sys.exit(0)
def parsemsg(msg):
global birthdays, score42
complete = msg[1:].split(':',1) #Parse the message into useful data
info = complete[0].split(' ')
msgpart = complete[1]
sender = info[0].split('!')
if len(msgpart) <= 0:
return
qd.go (s, sender, msgpart, info[2])
if CHANLIST.find(info[2]) != -1 and re.match(".*(norme|coding style).*", msgpart) is not None and re.match(".*(please|give|obtenir|now|plz|stp|svp|s'il (te|vous) pla.t|check).*", msgpart) is not None:
norme.launch (s, sender, msgpart)
elif CHANLIST.find(info[2]) != -1 and msgpart[0] == '!': #Treat all messages starting with '!' as command
cmd = msgpart[1:].split(' ')
if cmd[0] == 'help' or cmd[0] == 'h':
s.send("PRIVMSG %s :Pour me demander quelque chose, commencer votre message par !.\nVoici ce dont je suis capable :\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !new-year !newyear !ny : Affiche le temps restant avant la nouvelle année\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !end-of-world !worldend !eow : Temps restant avant la fin du monde\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !weekend !week-end !we : Affiche le temps restant avant le prochain week-end\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !partiels : Affiche le temps restant avant les prochains partiels\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !vacs !vacances !holidays !free-time : Affiche le temps restant avant les prochaines vacances\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !jpo !next-jpo : Affiche le temps restant avant la prochaine JPO\r\n"%(sender[0]))
s.send("PRIVMSG %s : - !42 !scores : Affiche les scores des gens\r\n"%(sender[0]))
if cmd[0] == 'score' or cmd[0] == 'scores' or cmd[0] == '42':
qd.scores(s, cmd, info[2])
if cmd[0] == 'chronos' or cmd[0] == 'edt' or cmd[0] == 'cours':
s.send("PRIVMSG %s :chronos\r\n"%(info[2]))
if cmd[0] == 'jpo' or cmd[0] == 'JPO' or cmd[0] == 'next-jpo':
#ndate = datetime(2012, 5, 12, 8, 30, 1)
#ndate = datetime(2012, 3, 31, 8, 30, 1)
ndate = datetime(2012, 3, 17, 8, 30, 1)
#ndate = datetime(2012, 2, 4, 8, 30, 1)
newyear.launch (s, info[2], ndate, ["Il reste%s avant la prochaine JPO... We want you!", "Nous somme en pleine JPO depuis%s"], cmd)
if cmd[0] == 'professional-project' or cmd[0] == 'project-professionnel' or cmd[0] == 'projet-professionnel' or cmd[0] == 'project-professionel' or cmd[0] == 'tc' or cmd[0] == 'next-rendu' or cmd[0] == 'rendu':
ndate = datetime(2012, 3, 18, 23, 42, 1)
newyear.launch (s, info[2], ndate, ["Il reste%s avant la fermeture du rendu de TC-5 et de corewar, vite au boulot !", "À %s près, il aurait encore été possible de rendre"], cmd)
elif msgpart[0] == '`' and sender[0] == OWNER and CHANLIST.find(info[2]) != -1: #Treat all messages starting with '`' as command
cmd=msgpart[1:].split(' ')
if cmd[0]=='op':
s.send("MODE %s +o %s\r\n" % (info[2], cmd[1]))
if cmd[0]=='deop':
s.send("MODE %s -o %s\r\n" % (info[2], cmd[1]))
if cmd[0]=='voice':
s.send('MODE '+info[2]+' +v '+cmd[1]+'n')
if cmd[0]=='devoice':
s.send('MODE '+info[2]+' -v '+cmd[1]+'n')
if cmd[0]=='restart':
print ("Restarting thread")
launch(s)
if cmd[0]=='stop':
print ("Bye!")
s.send("PRIVMSG %s :Bye!\r\n"%(info[2]))
sys.exit (0)
if cmd[0]=='sys':
syscmd(msgpart[1:],info[2])
if msgpart[0]=='-' and sender[0]==OWNER : #Treat msgs with - as explicit command to send to server
cmd=msgpart[1:]
#s.send(cmd+'n')
print ('cmd='+cmd)
def read():
global s, readbuffer
while 1:
readbuffer = readbuffer + s.recv(1024) #recieve server messages
temp = readbuffer.split("\n")
readbuffer = temp.pop( )
#signal.signal(signal.SIGHUP, onSignal)
for line in temp:
print (line)
line = line.rstrip() #remove trailing 'rn'
if line.find('PRIVMSG') != -1: #Call a parsing function
parsemsg(line)
line = line.split()
if(line[0] == 'PING'): #If server pings then pong
s.send("PONG %s\r\n" % line[1])
def launch(s):
# thread.start_new_thread(ontime.startThread, (s,datetime(2012, 1, 18, 6, 0, 1),["Il reste%s avant la fin de Wikipédia", "C'est fini, Wikipédia a sombrée depuis%s"],CHANLIST))
# thread.start_new_thread(ontime.startThread, (s,datetime(2012, 2, 23, 0, 0, 1),[],CHANLIST))
thread.start_new_thread(watchWebsite.startThread, (s, "you.p0m.fr", "", "#42sh #epitaguele", "Oh, quelle est cette nouvelle image sur http://you.p0m.fr/ ? :p"))
thread.start_new_thread(watchWebsite.startThread, (s, "intra.nbr23.com", "", "#42sh", "Oh, quel est ce nouveau film sur http://intra.nbr23.com/ ? :p"))
print ("Launched successfuly")
launch(s)
read()

View File

@ -1,9 +1,8 @@
#!/usr/bin/python2.7
#!/usr/bin/python3
# coding=utf-8
import sys
import socket
import string
import signal
import os
import re
@ -11,10 +10,10 @@ import subprocess
from datetime import datetime
from datetime import timedelta
from xml.dom.minidom import parse
import thread
import _thread
if len(sys.argv) <= 1:
print "This script takes exactly 1 arg: a XML config file"
print ("This script takes exactly 1 arg: a XML config file")
sys.exit(1)
def onSignal(signum, frame):
@ -22,13 +21,19 @@ def onSignal(signum, frame):
sys.exit (0)
signal.signal(signal.SIGINT, onSignal)
if len(sys.argv) == 3:
basedir = sys.argv[2]
else:
basedir = "./"
import message
SMILEY = list()
CORRECTIONS = list()
g_queue = list()
talkEC = 0
stopSpk = 0
lastmsg = []
lastmsg = None
dom = parse(sys.argv[1])
@ -57,13 +62,14 @@ for correct in config.getElementsByTagName('correction'):
CORRECTIONS.append((" " + (correct.getAttribute("bad") + " "), (" " + correct.getAttribute("good") + " ")))
print ("%d corrections loaded"%len(CORRECTIONS))
def speak(endstate):
global lastmsg, g_queue, talkEC, stopSpk
talkEC = 1
stopSpk = 0
if len(lastmsg) < 1:
lastmsg = g_queue.pop(0)
if lastmsg is None:
lastmsg = message.Message(None, "")
while not stopSpk and len(g_queue) > 0:
msg = g_queue.pop(0)
@ -71,51 +77,55 @@ def speak(endstate):
sentence = ""
force = 0
if force or msg[2] - lastmsg[2] > timedelta(0, 500):
sentence += "A {0} heure {1} : ".format(msg[2].hour, msg[2].minute)
#Skip identic body
if msg.content == lastmsg.content:
continue
if force or msg.time - lastmsg.time > timedelta(0, 500):
sentence += "A {0} heure {1} : ".format(msg.time.hour, msg.time.minute)
force = 1
if force or msg[0] != lastmsg[0]:
if msg[0] == OWNER:
if force or msg.channel != lastmsg.channel:
if msg.channel == OWNER:
sentence += "En message priver. " #Just to avoid é :p
else:
sentence += "Sur " + msg[0] + ". "
sentence += "Sur " + msg.channel + ". "
force = 1
action = 0
if msg[3].find("ACTION ") == 1:
sentence += msg[1] + " "
msg[3] = msg[3].replace("ACTION ", "")
if msg.content.find("ACTION ") == 1:
sentence += msg.sender + " "
msg.content = msg.content.replace("ACTION ", "")
action = 1
for (txt, mood) in SMILEY:
if msg[3].find(txt) >= 0:
sentence += msg[1] + (" %s : "%mood)
msg[3] = msg[3].replace(txt, "")
if msg.content.find(txt) >= 0:
sentence += msg.sender + (" %s : "%mood)
msg.content = msg.content.replace(txt, "")
action = 1
break
for (bad, good) in CORRECTIONS:
if msg[3].find(bad) >= 0:
msg[3] = (" " + msg[3] + " ").replace(bad, good)
if msg.content.find(bad) >= 0:
msg.content = (" " + msg.content + " ").replace(bad, good)
if action == 0 and (force or msg[1] != lastmsg[1]):
sentence += msg[1] + " dit : "
if action == 0 and (force or msg.sender != lastmsg.sender):
sentence += msg.sender + " dit : "
if re.match(".*(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+.*", msg[3]) is not None:
msg[3] = re.sub("(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+", " U.R.L Y.C.C ", msg[3])
if re.match(".*(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+.*", msg.content) is not None:
msg.content = re.sub("(https?://)?(www\\.)?ycc.fr/[a-z0-9A-Z]+", " U.R.L Y.C.C ", msg.content)
if re.match(".*https?://.*", msg[3]) is not None:
msg[3] = re.sub(r'https?://[^ ]+', " U.R.L ", msg[3])
if re.match(".*https?://.*", msg.content) is not None:
msg.content = re.sub(r'https?://[^ ]+', " U.R.L ", msg.content)
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.content) is not None:
if sentence != "":
intro = subprocess.call(["espeak", "-v", "fr", sentence])
#intro.wait()
lang = msg[3][1:3].lower()
sentence = msg[3][4:]
lang = msg.content[1:3].lower()
sentence = msg.content[4:]
else:
sentence += msg[3]
sentence += msg.content
spk = subprocess.call(["espeak", "-v", lang, sentence])
#spk.wait()
@ -128,74 +138,6 @@ def speak(endstate):
talkEC = 1
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)
complete = [ msg[1:pv], msg[pv:] ]
info = complete[0].split(' ')
msgpart = complete[1].strip()
if msgpart[0] == ":":
msgpart = msgpart[1:]
sender = info[0].split('!')
if len(CHANLIST) == 0 or CHANLIST.count(info[2]) >= 0 or info[2] == NICK:
#Treat all messages starting with '`' as command
if msgpart[0] == '`' and sender[0] == OWNER:
cmd=msgpart[1:].split(' ')
if cmd[0] == 'stop':
print "Bye!"
sys.exit (0)
elif cmd[0] == 'speak':
thread.start_new_thread(speak, (0,))
elif cmd[0] == 'reset':
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:
print chan
print "-- "
elif cmd[0] == 'add' and len(cmd) > 1:
CHANLIST.append(cmd[1])
print cmd[1] + " added to listened channels"
elif cmd[0] == 'del' and len(cmd) > 1:
if CHANLIST.count(cmd[1]) > 0:
CHANLIST.remove(cmd[1])
print cmd[1] + " removed from listened channels"
else:
print cmd[1] + " not in listened channels"
elif sender[0] != OWNER and (len(CHANLIST) == 0 or CHANLIST.count(info[2]) > 0 or info[2] == OWNER):
g_queue.append([info[2], sender[0], datetime.now(), msgpart])
if talkEC == 0:
thread.start_new_thread(speak, (0,))
class Server:
def __init__(self, server):
if server.hasAttribute("server"):
@ -216,33 +158,38 @@ class Server:
self.channels.append(channel.getAttribute("name"))
def launch(self):
thread.start_new_thread(self.connect, ())
_thread.start_new_thread(self.connect, ())
def authorize(self, msg):
return msg.sender != OWNER and (msg.channel == OWNER or msg.channel in self.channels)
def read(self):
readbuffer = "" #Here we store all the messages from server
while 1:
readbuffer = readbuffer + self.s.recv(1024) #recieve server messages
try:
readbuffer = readbuffer + self.s.recv(1024).decode() #recieve server messages
except UnicodeDecodeError:
print ("ERREUR de décodage unicode")
continue
temp = readbuffer.split("\n")
readbuffer = temp.pop( )
for line in temp:
line = line.rstrip() #remove trailing 'rn'
if line.find('PRIVMSG') != -1: #Call a parsing function
parsemsg(unicode(line, encoding='utf-8', errors='ignore'), self.channels)
line = line.split()
if(line[0] == 'PING'): #If server pings then pong
self.s.send("PONG %s\r\n" % line[1])
msg = message.Message(self, line)
if msg.cmd == "PING":
self.s.send(("PONG %s\r\n" % msg.content).encode ())
elif msg.cmd == "PRIVMSG" and self.authorize(msg):
g_queue.append(msg)
if talkEC == 0:
_thread.start_new_thread(speak, (0,))
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.s.send(("PASS %s\r\n" % self.password).encode())
self.s.send(("NICK %s\r\n" % NICK).encode())
self.s.send(("USER %s %s bla :%s\r\n" % (NICK, self.host, REALNAME)).encode())
self.read()
for server in config.getElementsByTagName('server'):
@ -250,7 +197,7 @@ for server in config.getElementsByTagName('server'):
srv.launch()
def sighup_h(signum, frame):
print "Signal reçu..."
print ("Signal reçu...")
if os.path.exists("/tmp/isPresent"):
thread.start_new_thread(speak, (0,))
else:

61
qd.py
View File

@ -57,35 +57,27 @@ class Score:
def playFtt(self):
if self.canPlay():
self.ftt += 1
self.last = datetime.now()
def playTwt(self):
if self.canPlay():
self.twt += 1
self.last = datetime.now()
def playPi(self):
if self.canPlay():
self.pi += 1
self.last = datetime.now()
def playNoutfound(self):
if self.canPlay():
self.notfound += 1
self.last = datetime.now()
def playTen(self):
if self.canPlay():
self.tententen += 1
self.last = datetime.now()
def playLeet(self):
if self.canPlay():
self.leet += 1
self.last = datetime.now()
def playGreat(self):
if self.canPlay():
self.great += 1
self.last = datetime.now()
def playBad(self):
if self.canPlay():
self.bad += 1
self.last = datetime.now()
def toTuple(self):
return (self.ftt, self.twt, self.pi, self.notfound, self.tententen, self.leet, self.great, self.bad)
@ -97,6 +89,7 @@ class Score:
def hasChanged(self):
if self.changed:
self.changed = False
self.last = datetime.now()
return True
else:
return False
@ -186,10 +179,12 @@ def parseanswer (msg):
phrase = " %s n'a encore jamais joué,"%(msg.cmd[1])
else:
for nom, scr in sorted(SCORES.items(), key=rev, reverse=True):
if phrase == "":
phrase = " *%s: %d*,"%(nom, scr.score())
else:
phrase += " %s: %d,"%(nom, scr.score())
score = scr.score()
if score != 0:
if phrase == "":
phrase = " *%s: %d*,"%(nom, score)
else:
phrase += " %s: %d,"%(nom, score)
msg.send_chn ("Scores :%s" % (phrase[0:len(phrase)-1]))
return True
@ -197,9 +192,9 @@ def parseanswer (msg):
return False
def win(s, who):
def win(msg):
global SCORES, MANCHE
who = who.lower()
who = msg.sender.lower()
(num_manche, winner, nb_points, whosef, dayte) = MANCHE
@ -207,7 +202,7 @@ def win(s, who):
maxi_name = None
for player in SCORES.keys():
scr = score(player)
scr = SCORES[player].score()
if scr > maxi_scor:
maxi_scor = scr
maxi_name = player
@ -216,12 +211,12 @@ def win(s, who):
SCORES = dict()
# SCORES[maxi_name] = (-10, 0, -4, 0, 0, -2, 0)
# SCORES[maxi_name] = (0, 0, 0, 0, 0, 0, 0)
SCORES[who].newWinner
SCORES[who].newWinner()
if who != maxi_name:
msg.send_global ("Félicitations %s, tu remportes cette manche terminée par %s, avec un score de %d !"%(maxi_name, who, maxi_scor))
msg.send_chn ("Félicitations %s, tu remportes cette manche terminée par %s, avec un score de %d !"%(maxi_name, who, maxi_scor))
else:
msg.send_global ("Félicitations %s, tu remportes cette manche avec %d points !"%(maxi_name, maxi_scor))
msg.send_chn ("Félicitations %s, tu remportes cette manche avec %d points !"%(maxi_name, maxi_scor))
MANCHE = (num_manche + 1, maxi_name, maxi_scor, who, datetime.now ())
@ -244,58 +239,58 @@ def parselisten (msg):
# if msg.channel == "#nemutest":
if msg.channel != "#nemutest":
if (msg.content.strip().startswith("42") and len (msg.content) < 5) or ((msg.content.strip().lower().startswith("quarante-deux") or msg.content.strip().lower().startswith("quarante deux")) and len (msg.content) < 17):
if datetime.now().minute == 10 and datetime.now().second == 10 and datetime.now().hour == 10:
if msg.time.minute == 10 and msg.time.second == 10 and msg.time.hour == 10:
getUser(msg.sender).playTen()
getUser(msg.sender).playGreat()
elif datetime.now().minute == 42:
if datetime.now().second == 0:
elif msg.time.minute == 42:
if msg.time.second == 0:
getUser(msg.sender).playGreat()
getUser(msg.sender).playFtt()
else:
getUser(msg.sender).playBad()
if (msg.content.strip().startswith("23") and len (msg.content) < 5) or ((msg.content.strip().lower().startswith("vingt-trois") or msg.content.strip().lower().startswith("vingt trois")) and len (msg.content) < 14):
if datetime.now().minute == 23:
if datetime.now().second == 0:
if msg.time.minute == 23:
if msg.time.second == 0:
getUser(msg.sender).playGreat()
getUser(msg.sender).playTwt()
else:
getUser(msg.sender).playBad()
if (msg.content.strip().startswith("101010") and len (msg.content) < 9):
if datetime.now().minute == 10 and datetime.now().hour == 10:
if datetime.now().second == 10:
if msg.time.minute == 10 and msg.time.hour == 10:
if msg.time.second == 10:
getUser(msg.sender).playGreat()
getUser(msg.sender).playTen()
else:
getUser(msg.sender).playBad()
if (msg.content.strip().startswith("12345") and len (msg.content) < 8) or (msg.content.strip().startswith("012345") and len (msg.content) < 9):
if datetime.now().hour == 1 and datetime.now().minute == 23 and datetime.now().second == 45:
if msg.time.hour == 1 and msg.time.minute == 23 and msg.time.second == 45:
getUser(msg.sender).playGreat()
getUser(msg.sender).playTwt()
else:
getUser(msg.sender).playBad()
if len (msg.content) < 12 and (msg.content.strip().lower().startswith("leet time") or msg.content.strip().lower().startswith("leettime") or msg.content.strip().lower().startswith("leetime") or msg.content.strip().lower().startswith("l33t time") or msg.content.strip().lower().startswith("1337")):
if datetime.now().hour == 13 and datetime.now().minute == 37:
if datetime.now().second == 0:
if msg.time.hour == 13 and msg.time.minute == 37:
if msg.time.second == 0:
getUser(msg.sender).playGreat()
getUser(msg.sender).playLeet()
else:
getUser(msg.sender).playBad()
if len (msg.content) < 11 and (msg.content.strip().lower().startswith("pi time") or msg.content.strip().lower().startswith("pitime") or msg.content.strip().lower().startswith("3.14 time")):
if datetime.now().hour == 3 and datetime.now().minute == 14:
if datetime.now().second == 15 or datetime.now().second == 16:
if msg.time.hour == 3 and msg.time.minute == 14:
if msg.time.second == 15 or msg.time.second == 16:
getUser(msg.sender).playGreat()
getUser(msg.sender).playPi()
else:
getUser(msg.sender).playBad()
if len (msg.content) < 16 and (msg.content.strip().lower().startswith("time not found") or msg.content.strip().lower().startswith("timenotfound") or msg.content.strip().lower().startswith("404 time")) or (len (msg.content) < 6 and msg.content.strip().lower().startswith("404")):
if datetime.now().hour == 4 and datetime.now().minute == 4:
if datetime.now().second == 0 or datetime.now().second == 4:
if msg.time.hour == 4 and msg.time.minute == 4:
if msg.time.second == 0 or msg.time.second == 4:
getUser(msg.sender).playGreat()
getUser(msg.sender).playNotfound()
else:
@ -303,7 +298,7 @@ def parselisten (msg):
if getUser(msg.sender).isWinner():
print ("Nous avons un vainqueur ! Nouvelle manche :p")
win(s, msg.sender)
win(msg)
elif getUser(msg.sender).hasChanged():
save_module ()
return False

View File

@ -1,3 +1,5 @@
import sys
import traceback
import socket
import _thread
import time
@ -23,16 +25,26 @@ class Server:
else:
self.password = None
self.listen_nick = True
self.channels = list()
for channel in server.getElementsByTagName('channel'):
self.channels.append(channel.getAttribute("name"))
def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
def send_msg_final(self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
if msg is not None and channel is not None:
for line in msg.split("\n"):
if line != "" and self.accepted_channel(channel):
if line != "":
self.s.send (("%s %s :%s%s" % (cmd, channel, line, endl)).encode ())
def send_msg_usr (self, user, msg):
if user is not None and user[0] != "#":
self.send_msg_final(user, msg)
def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
if self.accepted_channel(channel):
self.send_msg_final(channel, msg, cmd, endl)
def send_global (self, msg, cmd = "PRIVMSG", endl = "\r\n"):
for channel in self.channels:
self.send_msg (channel, msg, cmd, endl)
@ -43,7 +55,10 @@ class Server:
_thread.start_new_thread(self.connect, (mods,))
def accepted_channel(self, channel):
return (self.channels.count(channel) != -1)
if self.listen_nick:
return self.channels.count(channel) or channel == self.nick
else:
return self.channels.count(channel)
def read(self, mods):
self.readbuffer = "" #Here we store all the messages from server
@ -58,10 +73,12 @@ class Server:
for line in temp:
msg = message.Message (self, line)
#try:
msg.treat (mods)
#except:
#print ("Une erreur est survenue lors du traitement du message : %s"%line)
try:
msg.treat (mods)
except:
print ("Une erreur est survenue lors du traitement du message : %s"%line)
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback)
def connect(self, mods):

View File

@ -117,7 +117,7 @@ class Site:
hash = hashlib.sha224(content).hexdigest()
if hash != self.lastpage:
if self.lastpage is not None:
self.send_message ()
self.send_message (self.message)
self.lastpage = hash
if self.lastChange <= 0:
self.lastChange -= 1
@ -138,7 +138,7 @@ class Site:
except:
print ("Une erreur est survenue lors de la récupération de la page " + self.server + "/" + self.page)
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback)
traceback.print_exception(exc_type, exc_value, exc_traceback)
time.sleep(self.updateTime * 3)
@ -177,7 +177,7 @@ def save_module():
item.appendChild(parseString ('<channel name="%s" />' % (chan)).documentElement);
b64 = base64.b64encode(pickle.dumps(site.lastpage)).decode()
item.appendChild(newdoc.createTextNode(b64));
print (site.server)
#print (site.server)
top.appendChild(item);
with open(filename, "w") as f:

View File

@ -52,10 +52,8 @@ class User(object):
return 'en midlab'
elif self.ip.startswith('10.250'):
return 'en cisco'
elif self.ip.startswith('10'):
return 'quelque part sur le PIE (%s)'%self.ip
else:
return "chez lui"
return None
@property
def poste(self):
@ -103,27 +101,40 @@ def help_tiny ():
return "Find a user on the PIE"
def help_full ():
return "!whereis /who/: gives the position of /who/."
return "!whereis /who/: gives the position of /who/.\n!whereare /who/ [/other who/ ...]: gives the position of /who/."
datas = None
def parseanswer (msg):
global datas
if msg.cmd[0] == "whereis" or msg.cmd[0] == "ouest":
if msg.cmd[0] == "whereis" or msg.cmd[0] == "whereare" or msg.cmd[0] == "ouest" or msg.cmd[0] == "ousont":
if datas is not None:
datas = datas.update ()
if datas is None:
datas = UpdatedStorage()
if len(msg.cmd) >= 2:
name = msg.cmd[1]
else:
name = msg.sender
if len(msg.cmd) > 10:
msg.send_snd ("Demande moi moins de personnes à la fois dans ton !%s" % msg.cmd[0])
return True
if name in datas.users:
msg.send_chn ("%s est %s (%s)." %(name, datas.users[name].poste, unquote(datas.users[name].location)))
else:
msg.send_chn ("%s n'est pas connecté sur le PIE." % name)
pasla = list()
for name in msg.cmd:
if name == "whereis" or name == "whereare" or name == "ouest" or name == "ousont":
if len(msg.cmd) >= 2:
continue
else:
name = msg.sender
if name in datas.users:
msg.send_chn ("%s est %s (%s)." %(name, datas.users[name].poste, unquote(datas.users[name].location)))
else:
pasla.append(name)
if len(pasla) == 1:
msg.send_chn ("%s n'est pas connecté sur le PIE." % pasla[0])
elif len(pasla) > 1:
msg.send_chn ("%s ne sont pas connectés sur le PIE." % ", ".join(pasla))
return True
elif msg.cmd[0] == "ip":