Module_state done: global datas management
newnemubot replaces old one
This commit is contained in:
parent
684cecd137
commit
25b2634ea3
152
birthday.py
152
birthday.py
@ -1,152 +0,0 @@
|
||||
# coding=utf-8
|
||||
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from datetime import date
|
||||
from xml.dom.minidom import parse
|
||||
from xml.dom.minidom import parseString
|
||||
from xml.dom.minidom import getDOMImplementation
|
||||
|
||||
filename = ""
|
||||
BIRTHDAYS = {}
|
||||
|
||||
def xmlparse(node):
|
||||
"""Parse the given node and add birthdays to the global list."""
|
||||
for item in node.getElementsByTagName("birthday"):
|
||||
if (item.hasAttribute("year")):
|
||||
year = int(item.getAttribute("year"))
|
||||
else:
|
||||
year = 0
|
||||
if (item.hasAttribute("month")):
|
||||
month = int(item.getAttribute("month"))
|
||||
else:
|
||||
month = 0
|
||||
if (item.hasAttribute("day")):
|
||||
day = int(item.getAttribute("day"))
|
||||
else:
|
||||
day = 0
|
||||
if (item.hasAttribute("hour")):
|
||||
hour = int(item.getAttribute("hour"))
|
||||
else:
|
||||
hour = 0
|
||||
if (item.hasAttribute("minute")):
|
||||
minute = int(item.getAttribute("minute"))
|
||||
else:
|
||||
minute = 0
|
||||
second = 1
|
||||
|
||||
BIRTHDAYS[item.getAttribute("name")] = datetime(year, month, day, hour, minute, second)
|
||||
|
||||
|
||||
def load_module(datas_path):
|
||||
"""Load this module"""
|
||||
global BIRTHDAYS, filename
|
||||
BIRTHDAYS = {}
|
||||
filename = datas_path + "/birthdays.xml"
|
||||
|
||||
sys.stdout.write ("Loading birthdays ... ")
|
||||
dom = parse(filename)
|
||||
xmlparse (dom.getElementsByTagName('birthdays')[0])
|
||||
print ("done (%d loaded)" % len(BIRTHDAYS))
|
||||
|
||||
|
||||
def save_module():
|
||||
"""Save the dates"""
|
||||
global filename
|
||||
sys.stdout.write ("Saving birthdays ... ")
|
||||
|
||||
impl = getDOMImplementation()
|
||||
newdoc = impl.createDocument(None, 'birthdays', None)
|
||||
top = newdoc.documentElement
|
||||
|
||||
for name in BIRTHDAYS.keys():
|
||||
day = BIRTHDAYS[name]
|
||||
bonus=""
|
||||
if day.hour != 0:
|
||||
bonus += 'hour="%s" ' % day.hour
|
||||
if day.minute != 0:
|
||||
bonus += 'minute="%s" ' % day.minute
|
||||
item = parseString ('<birthday name="%s" year="%d" month="%d" day="%d" %s />' % (name, day.year, day.month, day.day, bonus)).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 "People birthdays and ages"
|
||||
|
||||
|
||||
def help_full ():
|
||||
return "!anniv /who/: gives the remaining time before the anniversary of /who/\n!age /who/: gives the age of /who/\nIf /who/ is not given, gives the remaining time before your anniversary.\n\n To set yout birthday, say it to nemubot :)"
|
||||
|
||||
|
||||
def findName(msg):
|
||||
if len(msg.cmd) < 2 or msg.cmd[1].lower() == "moi" or msg.cmd[1].lower() == "me":
|
||||
name = msg.sender.lower()
|
||||
else:
|
||||
name = msg.cmd[1].lower()
|
||||
|
||||
matches = []
|
||||
|
||||
if name in BIRTHDAYS:
|
||||
matches.append(name)
|
||||
else:
|
||||
for k in BIRTHDAYS.keys ():
|
||||
if k.find (name) == 0:
|
||||
matches.append (k)
|
||||
return (matches, name)
|
||||
|
||||
|
||||
def parseanswer(msg):
|
||||
if msg.cmd[0] == "anniv":
|
||||
(matches, name) = findName(msg)
|
||||
if len(matches) == 1:
|
||||
(n, d) = (matches[0], BIRTHDAYS[matches[0]])
|
||||
tyd = d
|
||||
tyd = datetime(date.today().year, tyd.month, tyd.day)
|
||||
|
||||
if tyd.day == datetime.today().day and tyd.month == datetime.today().month:
|
||||
msg.send_chn (msg.countdown_format (d, "", "C'est aujourd'hui l'anniversaire de %s ! Il a%s. Joyeux anniversaire :)" % (n, "%s")))
|
||||
else:
|
||||
if tyd < datetime.today():
|
||||
tyd = datetime(date.today().year + 1, tyd.month, tyd.day)
|
||||
|
||||
msg.send_chn (msg.countdown_format (tyd, "Il reste %s avant l'anniversaire de %s !" % ("%s", n), ""))
|
||||
else:
|
||||
msg.send_chn ("%s: désolé, je ne connais pas la date d'anniversaire de %s. Quand est-il né ?"%(msg.sender, name))
|
||||
return True
|
||||
elif msg.cmd[0] == "age":
|
||||
(matches, name) = findName(msg)
|
||||
if len(matches) == 1:
|
||||
(n, d) = (matches[0], BIRTHDAYS[matches[0]])
|
||||
|
||||
msg.send_chn (msg.countdown_format (d, "", "%s a %s." % (n, "%s")))
|
||||
else:
|
||||
msg.send_chn ("%s: désolé, je ne connais pas l'âge de %s. Quand est-il né ?"%(msg.sender, name))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def parseask(msg):
|
||||
msgl = msg.content.lower ()
|
||||
if re.match("^.*(date de naissance|birthday|geburtstag|née? |nee? le|born on).*$", msgl) is not None:
|
||||
try:
|
||||
extDate = msg.extractDate ()
|
||||
if extDate is None:
|
||||
msg.send_chn ("%s: ta date de naissance ne paraît pas valide..." % (msg.sender))
|
||||
else:
|
||||
BIRTHDAYS[msg.sender.lower()] = extDate
|
||||
msg.send_chn ("%s: ok, c'est noté, ta date de naissance est le %s" % (msg.sender, extDate.strftime("%A %d %B %Y à %H:%M")))
|
||||
save_module ()
|
||||
except:
|
||||
msg.send_chn ("%s: ta date de naissance ne paraît pas valide..." % (msg.sender))
|
||||
return True
|
||||
return False
|
||||
|
||||
def parselisten (msg):
|
||||
return False
|
0
datas/datas
Normal file
0
datas/datas
Normal file
97
imodule.py
97
imodule.py
@ -1,97 +0,0 @@
|
||||
# coding=utf-8
|
||||
|
||||
class ModuleException(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
|
||||
class ModuleState:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.attributes = dict()
|
||||
self.childs = list()
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getAttribute(self, name):
|
||||
if name in self.attributes:
|
||||
return self.attributes[name]
|
||||
else:
|
||||
return None
|
||||
|
||||
def setAttribute(self, name, value):
|
||||
self.attributes[name] = value
|
||||
|
||||
def getChilds(self):
|
||||
return self.childs
|
||||
|
||||
def addChild(self, child):
|
||||
self.childs.append(child)
|
||||
|
||||
|
||||
class ModuleStateFile:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
|
||||
if not os.access(self.filename, os.R_OK):
|
||||
with open(self.filename) as f:
|
||||
for line in f:
|
||||
print line
|
||||
|
||||
|
||||
class ModuleBase:
|
||||
def __init__(self, datas_path):
|
||||
self.datas_path = datas_path
|
||||
|
||||
if self.module_name is None:
|
||||
raise ModuleException("module_name not defined")
|
||||
|
||||
if self.conf is not None:
|
||||
self.conf = self.datas_path + self.conf
|
||||
if not os.access(self.conf, os.R_OK):
|
||||
|
||||
|
||||
|
||||
def print(self, message):
|
||||
print ("[%s] %s" % (self.module_name, message))
|
||||
|
||||
|
||||
def load(self):
|
||||
return True
|
||||
|
||||
def reload(self):
|
||||
return self.save() and self.load()
|
||||
|
||||
def save(self):
|
||||
return True
|
||||
|
||||
|
||||
def launch(self, servers):
|
||||
return True
|
||||
|
||||
def stop(self):
|
||||
return True
|
||||
|
||||
|
||||
def help_tiny(self):
|
||||
return None
|
||||
|
||||
def help_full(self):
|
||||
return None
|
||||
|
||||
|
||||
def parseanswer(self, msg):
|
||||
return False
|
||||
|
||||
def parseask(self, msg):
|
||||
return False
|
||||
|
||||
def parselisten(self, msg):
|
||||
return False
|
||||
|
||||
def parseadmin(self, msg):
|
||||
return False
|
11
message.py
11
message.py
@ -223,9 +223,14 @@ class Message:
|
||||
|
||||
#Try modules
|
||||
else:
|
||||
for im in mods.keys():
|
||||
if mods[im].parseask(self):
|
||||
return
|
||||
for im in mods:
|
||||
#try:
|
||||
if im.parseask(self):
|
||||
return
|
||||
#except AttributeError:
|
||||
#print ("Warning: in module `%s', no function parseask defined." % im.name)
|
||||
#im.parseask = lambda x: False
|
||||
#continue
|
||||
|
||||
#Owner commands
|
||||
elif self.content[0] == '`' and self.sender == self.srv.owner:
|
||||
|
103
module_state.py
Normal file
103
module_state.py
Normal file
@ -0,0 +1,103 @@
|
||||
# coding=utf-8
|
||||
|
||||
import xml.sax
|
||||
from datetime import datetime
|
||||
from datetime import date
|
||||
import time
|
||||
|
||||
class ModuleState:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.attributes = dict()
|
||||
self.childs = list()
|
||||
self.index = dict()
|
||||
self.index_fieldname = None
|
||||
self.index_tagname = None
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.getAttribute(i)
|
||||
|
||||
def __contains__(self, i):
|
||||
return i in self.index
|
||||
|
||||
def getAttribute(self, name):
|
||||
if name in self.attributes:
|
||||
return self.attributes[name]
|
||||
else:
|
||||
return None
|
||||
|
||||
def getDate(self, name):
|
||||
if name in self.attributes.keys():
|
||||
if isinstance(self.attributes[name], datetime):
|
||||
return self.attributes[name]
|
||||
else:
|
||||
return date.fromtimestamp(float(self.attributes[name]))
|
||||
else:
|
||||
return None
|
||||
|
||||
def getInt(self, name):
|
||||
if name in self.attributes.keys():
|
||||
return int(self.attributes[name])
|
||||
else:
|
||||
return None
|
||||
|
||||
def setIndex(self, fieldname = "name", tagname = None):
|
||||
self.index_fieldname = fieldname
|
||||
self.index_tagname = tagname
|
||||
for child in self.childs:
|
||||
if (tagname is None or tagname == child.name) and child.hasAttribute(fieldname):
|
||||
self.index[child[fieldname]] = child
|
||||
|
||||
def hasAttribute(self, name):
|
||||
return (name in self.attributes)
|
||||
|
||||
def setAttribute(self, name, value):
|
||||
self.attributes[name] = value
|
||||
|
||||
def getChilds(self):
|
||||
return self.childs
|
||||
|
||||
def getNode(self, tagname):
|
||||
ret = None
|
||||
for child in self.childs:
|
||||
if tagname is None or tagname == child.name:
|
||||
ret = child
|
||||
return ret
|
||||
|
||||
def getNodes(self, tagname):
|
||||
ret = list()
|
||||
for child in self.childs:
|
||||
if tagname is None or tagname == child.name:
|
||||
ret.append(child)
|
||||
return ret
|
||||
|
||||
def addChild(self, child):
|
||||
self.childs.append(child)
|
||||
if self.index_fieldname is not None:
|
||||
self.setIndex(self.index_fieldname, self.index_tagname)
|
||||
|
||||
def save_node(self, gen):
|
||||
attribs = {}
|
||||
for att in self.attributes.keys():
|
||||
if isinstance(self.attributes[att], datetime):
|
||||
attribs[att] = str(time.mktime(self.attributes[att].timetuple()))
|
||||
else:
|
||||
attribs[att] = str(self.attributes[att])
|
||||
attrs = xml.sax.xmlreader.AttributesImpl(attribs)
|
||||
|
||||
gen.startElement(self.name, attrs)
|
||||
|
||||
for child in self.childs:
|
||||
child.save_node(gen)
|
||||
|
||||
gen.endElement(self.name)
|
||||
|
||||
def save(self, filename):
|
||||
with open(filename,"w") as f:
|
||||
gen = xml.sax.saxutils.XMLGenerator(f, "utf-8")
|
||||
gen.startDocument()
|
||||
self.save_node(gen)
|
||||
gen.endDocument()
|
39
module_states_file.py
Normal file
39
module_states_file.py
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/python3
|
||||
# coding=utf-8
|
||||
|
||||
import os
|
||||
import xml.sax
|
||||
|
||||
from module_exception import ModuleException
|
||||
from module_state import ModuleState
|
||||
|
||||
class ModuleStatesFile(xml.sax.ContentHandler):
|
||||
def startDocument(self):
|
||||
self.root = None
|
||||
self.stack = list()
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
cur = ModuleState(name)
|
||||
|
||||
for name in attrs.keys():
|
||||
cur.setAttribute(name, attrs.getValue(name))
|
||||
|
||||
self.stack.append(cur)
|
||||
|
||||
def endElement(self, name):
|
||||
child = self.stack.pop()
|
||||
size = len(self.stack)
|
||||
if size > 0:
|
||||
self.stack[size - 1].addChild(child)
|
||||
else:
|
||||
self.root = child
|
||||
|
||||
def parse_file(filename):
|
||||
parser = xml.sax.make_parser()
|
||||
mod = ModuleStatesFile()
|
||||
parser.setContentHandler(mod)
|
||||
try:
|
||||
parser.parse(open(filename, "r"))
|
||||
return mod.root
|
||||
except:
|
||||
return ModuleState("nemubotstate")
|
97
modules/birthday.py
Normal file
97
modules/birthday.py
Normal file
@ -0,0 +1,97 @@
|
||||
# coding=utf-8
|
||||
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from datetime import date
|
||||
|
||||
from module_state import ModuleState
|
||||
|
||||
nemubotversion = 3.0
|
||||
|
||||
def load():
|
||||
global DATAS
|
||||
DATAS.setIndex("name", "birthday")
|
||||
|
||||
|
||||
def help_tiny ():
|
||||
"""Line inserted in the response to the command !help"""
|
||||
return "People birthdays and ages"
|
||||
|
||||
|
||||
def help_full ():
|
||||
return "!anniv /who/: gives the remaining time before the anniversary of /who/\n!age /who/: gives the age of /who/\nIf /who/ is not given, gives the remaining time before your anniversary.\n\n To set yout birthday, say it to nemubot :)"
|
||||
|
||||
|
||||
def findName(msg):
|
||||
if len(msg.cmd) < 2 or msg.cmd[1].lower() == "moi" or msg.cmd[1].lower() == "me":
|
||||
name = msg.sender.lower()
|
||||
else:
|
||||
name = msg.cmd[1].lower()
|
||||
|
||||
matches = []
|
||||
|
||||
if name in DATAS.index:
|
||||
matches.append(name)
|
||||
else:
|
||||
for k in DATAS.index.keys ():
|
||||
if k.find (name) == 0:
|
||||
matches.append (k)
|
||||
return (matches, name)
|
||||
|
||||
|
||||
def parseanswer(msg):
|
||||
if msg.cmd[0] == "anniv":
|
||||
(matches, name) = findName(msg)
|
||||
if len(matches) == 1:
|
||||
name = matches[0]
|
||||
tyd = DATAS.index[name].getDate("born")
|
||||
tyd = datetime(date.today().year, tyd.month, tyd.day)
|
||||
|
||||
if tyd.day == datetime.today().day and tyd.month == datetime.today().month:
|
||||
msg.send_chn (msg.countdown_format (DATAS.index[name].getDate("born"), "", "C'est aujourd'hui l'anniversaire de %s ! Il a%s. Joyeux anniversaire :)" % (name, "%s")))
|
||||
else:
|
||||
if tyd < datetime.today():
|
||||
tyd = datetime(date.today().year + 1, tyd.month, tyd.day)
|
||||
|
||||
msg.send_chn (msg.countdown_format (tyd, "Il reste %s avant l'anniversaire de %s !" % ("%s", name), ""))
|
||||
else:
|
||||
msg.send_chn ("%s: désolé, je ne connais pas la date d'anniversaire de %s. Quand est-il né ?"%(msg.sender, name))
|
||||
return True
|
||||
elif msg.cmd[0] == "age":
|
||||
(matches, name) = findName(msg)
|
||||
if len(matches) == 1:
|
||||
name = matches[0]
|
||||
d = DATAS.index[name].getDate("born")
|
||||
|
||||
msg.send_chn (msg.countdown_format (d, "", "%s a %s." % (n, "%s")))
|
||||
else:
|
||||
msg.send_chn ("%s: désolé, je ne connais pas l'âge de %s. Quand est-il né ?"%(msg.sender, name))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def parseask(msg):
|
||||
msgl = msg.content.lower ()
|
||||
if re.match("^.*(date de naissance|birthday|geburtstag|née? |nee? le|born on).*$", msgl) is not None:
|
||||
try:
|
||||
extDate = msg.extractDate ()
|
||||
if extDate is None:
|
||||
msg.send_chn ("%s: ta date de naissance ne paraît pas valide..." % (msg.sender))
|
||||
else:
|
||||
if msg.sender.lower() in DATAS.index:
|
||||
DATAS.index[msg.sender.lower()] = extDate
|
||||
else:
|
||||
ms = ModuleState("birthday")
|
||||
ms.setAttribute("name", msg.sender.lower())
|
||||
ms.setAttribute("born", extDate)
|
||||
DATAS.addChild(ms)
|
||||
msg.send_chn ("%s: ok, c'est noté, ta date de naissance est le %s" % (msg.sender, extDate.strftime("%A %d %B %Y à %H:%M")))
|
||||
save()
|
||||
except:
|
||||
msg.send_chn ("%s: ta date de naissance ne paraît pas valide..." % (msg.sender))
|
||||
return True
|
||||
return False
|
||||
|
||||
def parselisten (msg):
|
||||
return False
|
2
modules/birthday.xml
Normal file
2
modules/birthday.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" ?>
|
||||
<nemubotmodule name="birthday" />
|
@ -8,18 +8,60 @@ import threading
|
||||
from datetime import timedelta
|
||||
from datetime import datetime
|
||||
from datetime import date
|
||||
from xml.dom.minidom import parse
|
||||
from xml.dom.minidom import parseString
|
||||
from xml.dom.minidom import getDOMImplementation
|
||||
|
||||
filename = ""
|
||||
from module_state import ModuleState
|
||||
|
||||
nemubotversion = 3.0
|
||||
|
||||
channels = "#nemutest #42sh #ykar #epitagueule"
|
||||
MANCHE = None
|
||||
QUESTIONS = list()
|
||||
SCORES = dict ()
|
||||
LASTSEEN = dict ()
|
||||
temps = dict ()
|
||||
|
||||
class Wrapper:
|
||||
def __init__(self):
|
||||
self.cache = dict()
|
||||
|
||||
def items(self):
|
||||
global DATAS
|
||||
ret = list()
|
||||
for k in DATAS.index.keys():
|
||||
ret.append((k, self[k]))
|
||||
return ret
|
||||
|
||||
def __contains__(self, i):
|
||||
global DATAS
|
||||
return i in DATAS.index
|
||||
|
||||
def __getitem__(self, i):
|
||||
global DATAS
|
||||
if i in self.cache:
|
||||
return self.cache[i]
|
||||
else:
|
||||
sc = Score()
|
||||
sc.parse(DATAS.index[i])
|
||||
self.cache[i] = sc
|
||||
return sc
|
||||
|
||||
def __setitem__(self, i, j):
|
||||
global DATAS
|
||||
ms = ModuleState("player")
|
||||
ms.setAttribute("name", i)
|
||||
j.save(ms)
|
||||
DATAS.addChild(ms)
|
||||
DATAS.setIndex("name", "player")
|
||||
|
||||
def __delitem__(self, i):
|
||||
global DATAS
|
||||
del DATAS.index[i]
|
||||
|
||||
def save(self, i):
|
||||
if i in self.cache:
|
||||
self.cache[i].save(DATAS.index[i])
|
||||
del self.cache[i]
|
||||
|
||||
|
||||
SCORES = Wrapper()
|
||||
|
||||
class Score:
|
||||
def __init__(self):
|
||||
#FourtyTwo
|
||||
@ -37,15 +79,26 @@ class Score:
|
||||
self.changed = False
|
||||
|
||||
def parse(self, item):
|
||||
self.ftt = int(item.getAttribute("fourtytwo"))
|
||||
self.twt = int(item.getAttribute("twentythree"))
|
||||
self.pi = int(item.getAttribute("pi"))
|
||||
self.notfound = int(item.getAttribute("notfound"))
|
||||
self.tententen = int(item.getAttribute("tententen"))
|
||||
self.leet = int(item.getAttribute("leet"))
|
||||
self.great = int(item.getAttribute("great"))
|
||||
self.bad = int(item.getAttribute("bad"))
|
||||
self.triche = int(item.getAttribute("triche"))
|
||||
self.ftt = item.getInt("fourtytwo")
|
||||
self.twt = item.getInt("twentythree")
|
||||
self.pi = item.getInt("pi")
|
||||
self.notfound = item.getInt("notfound")
|
||||
self.tententen = item.getInt("tententen")
|
||||
self.leet = item.getInt("leet")
|
||||
self.great = item.getInt("great")
|
||||
self.bad = item.getInt("bad")
|
||||
self.triche = item.getInt("triche")
|
||||
|
||||
def save(self, state):
|
||||
state.setAttribute("fourtytwo", self.ftt)
|
||||
state.setAttribute("twentythree", self.twt)
|
||||
state.setAttribute("pi", self.pi)
|
||||
state.setAttribute("notfound", self.notfound)
|
||||
state.setAttribute("tententen", self.tententen)
|
||||
state.setAttribute("leet", self.leet)
|
||||
state.setAttribute("great", self.great)
|
||||
state.setAttribute("bad", self.bad)
|
||||
state.setAttribute("triche", self.triche)
|
||||
|
||||
def merge(self, other):
|
||||
self.ftt += other.ftt
|
||||
@ -100,6 +153,7 @@ class Score:
|
||||
def playBad(self):
|
||||
if self.canPlay():
|
||||
self.bad += 1
|
||||
self.great += 1
|
||||
def playTriche(self):
|
||||
self.triche += 1
|
||||
def oupsTriche(self):
|
||||
@ -130,58 +184,9 @@ class Score:
|
||||
return "42: %d, 23: %d, leet: %d, pi: %d, 404: %d, 10: %d, great: %d, bad: %d, triche: %d = %d."%(self.ftt, self.twt, self.leet, self.pi, self.notfound, self.tententen, self.great, self.bad, self.triche, self.score())
|
||||
|
||||
|
||||
def xmlparse(node):
|
||||
"""Parse the given node and add scores to the global list."""
|
||||
global SCORES, MANCHE
|
||||
for item in node.getElementsByTagName("score"):
|
||||
SCORES[item.getAttribute("name")] = Score ()
|
||||
SCORES[item.getAttribute("name")].parse(item)
|
||||
|
||||
for item in node.getElementsByTagName("question"):
|
||||
QUESTIONS.append((item.getAttribute("question"),item.getAttribute("regexp"),item.getAttribute("great")))
|
||||
|
||||
manche = node.getElementsByTagName("manche")[0]
|
||||
MANCHE = (int(manche.getAttribute("number")),
|
||||
manche.getAttribute("winner"),
|
||||
int(manche.getAttribute("winner_score")),
|
||||
manche.getAttribute("who"),
|
||||
# datetime.now ())
|
||||
datetime.fromtimestamp (time.mktime (time.strptime (manche.getAttribute("date")[:19], "%Y-%m-%d %H:%M:%S"))))
|
||||
|
||||
def load_module(datas_path):
|
||||
"""Load this module"""
|
||||
global MANCHE, SCORES, filename
|
||||
MANCHE = None
|
||||
SCORES = dict ()
|
||||
filename = datas_path + "/42.xml"
|
||||
|
||||
sys.stdout.write ("Loading 42scores ... ")
|
||||
dom = parse(filename)
|
||||
xmlparse (dom.documentElement)
|
||||
print ("done (%d loaded, %d questions, currently in round %d)" % (len(SCORES), len(QUESTIONS), -42))
|
||||
|
||||
def save_module():
|
||||
"""Save the scores"""
|
||||
global filename
|
||||
sys.stdout.write ("Saving 42scores ... ")
|
||||
|
||||
impl = getDOMImplementation()
|
||||
newdoc = impl.createDocument(None, 'game', None)
|
||||
top = newdoc.documentElement
|
||||
|
||||
for name in SCORES.keys():
|
||||
scr = 'fourtytwo="%d" twentythree="%d" pi="%d" notfound="%d" tententen="%d" leet="%d" great="%d" bad="%d" triche="%d"'% SCORES[name].toTuple()
|
||||
item = parseString ('<score name="%s" %s />' % (name, scr)).documentElement
|
||||
top.appendChild(item);
|
||||
|
||||
top.appendChild(parseString ('<manche number="%d" winner="%s" winner_score="%d" who="%s" date="%s" />' % MANCHE).documentElement)
|
||||
|
||||
for q in QUESTIONS:
|
||||
top.appendChild(parseString ('<question question="%s" regexp="%s" great="%s" />' % q).documentElement)
|
||||
|
||||
with open(filename, "w") as f:
|
||||
newdoc.writexml (f)
|
||||
print ("done")
|
||||
def load():
|
||||
global DATAS
|
||||
DATAS.setIndex("name", "player")
|
||||
|
||||
|
||||
def help_tiny ():
|
||||
@ -198,7 +203,7 @@ def rev (tupl):
|
||||
|
||||
def parseanswer (msg):
|
||||
if msg.cmd[0] == "42" or msg.cmd[0] == "score" or msg.cmd[0] == "scores":
|
||||
global SCORES, MANCHE
|
||||
global SCORES
|
||||
if len(msg.cmd) > 2 and msg.is_owner and ((msg.cmd[1] == "merge" and len(msg.cmd) > 3) or msg.cmd[1] == "oupstriche"):
|
||||
if msg.cmd[2] in SCORES and (len(msg.cmd) <= 3 or msg.cmd[3] in SCORES):
|
||||
if msg.cmd[1] == "merge":
|
||||
@ -215,7 +220,8 @@ def parseanswer (msg):
|
||||
elif len(msg.cmd) > 1 and (msg.cmd[1] == "help" or msg.cmd[1] == "aide"):
|
||||
msg.send_chn ("Formule : \"42\" * 2 + great * 5 + leet * 13.37 + (pi + 1) * 3.1415 * (not_found + 1) + tententen * 10 + \"23\" - (bad + 1) * 10 * (triche * 5 + 1) + 7")
|
||||
elif len(msg.cmd) > 1 and (msg.cmd[1] == "manche" or msg.cmd[1] == "round"):
|
||||
msg.send_chn ("Nous sommes dans la %de manche, gagnée par %s avec %d points et commencée par %s le %s"%MANCHE)
|
||||
manche = DATAS.getNode("manche")
|
||||
msg.send_chn ("Nous sommes dans la %de manche, gagnée par %s avec %d points et commencée par %s le %s." % (manche.getInt("number"), manche["winner"], manche.getInt("winner_score"), manche["who"], manche.getDate("date")))
|
||||
#elif msg.channel == "#nemutest":
|
||||
else:
|
||||
phrase = ""
|
||||
@ -241,15 +247,15 @@ def parseanswer (msg):
|
||||
|
||||
|
||||
def win(msg):
|
||||
global SCORES, MANCHE
|
||||
global SCORES
|
||||
who = msg.sender
|
||||
|
||||
(num_manche, winner, nb_points, whosef, dayte) = MANCHE
|
||||
manche = DATAS.getNode("manche")
|
||||
|
||||
maxi_scor = 0
|
||||
maxi_name = None
|
||||
|
||||
for player in SCORES.keys():
|
||||
for player in DATAS.index.keys():
|
||||
scr = SCORES[player].score()
|
||||
if scr > maxi_scor:
|
||||
maxi_scor = scr
|
||||
@ -267,10 +273,14 @@ def win(msg):
|
||||
else:
|
||||
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 ())
|
||||
manche.setAttribute("number", manche.getInt("number") + 1)
|
||||
manche.setAttribute("winner", maxi_name)
|
||||
manche.setAttribute("winner_score", maxi_scor)
|
||||
manche.setAttribute("who", who)
|
||||
manche.setAttribute("date", datetime.now())
|
||||
|
||||
print ("Nouvelle manche :", MANCHE)
|
||||
save_module ()
|
||||
print ("Nouvelle manche !")
|
||||
save()
|
||||
|
||||
|
||||
def parseask (msg):
|
||||
@ -298,8 +308,8 @@ def parselisten (msg):
|
||||
bfrseen = LASTSEEN[msg.realname]
|
||||
LASTSEEN[msg.realname] = datetime.now()
|
||||
|
||||
# if msg.channel == "#nemutest" and msg.sender not in DELAYED:
|
||||
if msg.channel != "#nemutest" and msg.sender not in DELAYED:
|
||||
if msg.channel == "#nemutest" and msg.sender not in DELAYED:
|
||||
# if msg.channel != "#nemutest" and msg.sender not in DELAYED:
|
||||
|
||||
if re.match("^(42|quarante[- ]?deux).{,2}$", msg.content.strip().lower()):
|
||||
if msg.time.minute == 10 and msg.time.second == 10 and msg.time.hour == 10:
|
||||
@ -389,9 +399,6 @@ class DelayedTuple:
|
||||
else:
|
||||
return False
|
||||
|
||||
#<question question=" ?" regexp="microprocesseur"/>
|
||||
#<question question=" ?" regexp=""/>
|
||||
|
||||
def wait(self, timeout):
|
||||
self.delayEvnt.wait(timeout)
|
||||
|
||||
@ -404,12 +411,17 @@ class GameUpdater(threading.Thread):
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
global DELAYED, QUESTIONS, LASTQUESTION
|
||||
global DELAYED, LASTQUESTION
|
||||
|
||||
seen = datetime.now() - self.bfrseen
|
||||
if self.bfrseen is not None:
|
||||
seen = datetime.now() - self.bfrseen
|
||||
rnd = random.randint(0, int(seen.seconds/90))
|
||||
else:
|
||||
rnd = 1
|
||||
|
||||
rnd = random.randint(0, seen.seconds/90)
|
||||
if rnd != 0:
|
||||
QUESTIONS = CONF.getNodes("question")
|
||||
|
||||
if self.msg.channel == "#nemutest":
|
||||
quest = 9
|
||||
else:
|
||||
@ -419,7 +431,9 @@ class GameUpdater(threading.Thread):
|
||||
quest = LASTQUESTION
|
||||
LASTQUESTION += 1
|
||||
|
||||
(question, regexp, great) = QUESTIONS[quest]
|
||||
question = QUESTIONS[quest]["question"]
|
||||
regexp = QUESTIONS[quest]["regexp"]
|
||||
great = QUESTIONS[quest]["great"]
|
||||
self.msg.send_chn("%s: %s" % (self.msg.sender, question))
|
||||
|
||||
DELAYED[self.msg.sender] = DelayedTuple(regexp, great)
|
||||
@ -436,4 +450,5 @@ class GameUpdater(threading.Thread):
|
||||
else:
|
||||
self.msg.send_chn("%s: J'accepte" % self.msg.sender)
|
||||
del DELAYED[self.msg.sender]
|
||||
save_module ()
|
||||
SCORES.save(self.msg.sender)
|
||||
save()
|
71
nemubot.py
71
nemubot.py
@ -2,72 +2,21 @@
|
||||
# coding=utf-8
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import os
|
||||
import re
|
||||
import imp
|
||||
from datetime import date
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
if len(sys.argv) != 2 and len(sys.argv) != 3:
|
||||
print ("This script takes exactly 1 arg: a XML config file")
|
||||
sys.exit(1)
|
||||
|
||||
imports = ["birthday", "qd", "events", "youtube", "watchWebsite", "soutenance", "whereis", "alias"]
|
||||
imports_launch = ["watchWebsite", "events"]
|
||||
mods = {}
|
||||
|
||||
def onClose():
|
||||
"""Call when the bot quit; saving all modules"""
|
||||
for imp in mods.keys():
|
||||
mods[imp].save_module ()
|
||||
|
||||
for imp in imports_launch:
|
||||
mods[imp].stop ()
|
||||
|
||||
#Save banlist before quit
|
||||
message.save_module ()
|
||||
|
||||
sys.exit (0)
|
||||
|
||||
def onSignal(signum, frame):
|
||||
print ("\nSIGINT receive, saving states and close")
|
||||
onClose()
|
||||
signal.signal(signal.SIGINT, onSignal)
|
||||
|
||||
#Define working directory
|
||||
if len(sys.argv) == 3:
|
||||
basedir = sys.argv[2]
|
||||
else:
|
||||
basedir = "./"
|
||||
|
||||
#Load base modules
|
||||
server = __import__ ("server")
|
||||
message = __import__ ("message")
|
||||
message.load (basedir + "/datas/")
|
||||
|
||||
#Read configuration XML file
|
||||
dom = parse(sys.argv[1])
|
||||
config = dom.getElementsByTagName('config')[0]
|
||||
servers = dict ()
|
||||
|
||||
#Load modules
|
||||
for imp in imports:
|
||||
mod = __import__ (imp)
|
||||
mods[imp] = mod
|
||||
|
||||
for serveur in config.getElementsByTagName('server'):
|
||||
srv = server.Server(serveur, config.getAttribute('nick'), config.getAttribute('owner'), config.getAttribute('realname'))
|
||||
srv.launch(mods, basedir + "/datas/")
|
||||
servers[srv.id] = srv
|
||||
import traceback
|
||||
|
||||
servers = dict()
|
||||
|
||||
print ("Nemubot ready, my PID is %i!" % (os.getpid()))
|
||||
|
||||
prompt = __import__ ("prompt")
|
||||
while prompt.launch(servers):
|
||||
imp.reload(prompt)
|
||||
try:
|
||||
imp.reload(prompt)
|
||||
except:
|
||||
print ("Unable to reload the prompt due to errors. Fix them before trying to reload the prompt.")
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
sys.stdout.write (traceback.format_exception_only(exc_type, exc_value)[0])
|
||||
|
||||
onClose()
|
||||
print ("Bye")
|
||||
sys.exit(0)
|
||||
|
103
prompt.py
103
prompt.py
@ -2,12 +2,17 @@ import sys
|
||||
import shlex
|
||||
import traceback
|
||||
import imp
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
server = __import__("server")
|
||||
imp.reload(server)
|
||||
|
||||
xmlparser = __import__("module_states_file")
|
||||
imp.reload(xmlparser)
|
||||
|
||||
selectedServer = None
|
||||
modules_path = "./modules/"
|
||||
datas_path = "./datas/"
|
||||
|
||||
MODS = list()
|
||||
|
||||
def parsecmd(msg):
|
||||
@ -39,13 +44,17 @@ def getPS1():
|
||||
|
||||
def launch(servers):
|
||||
"""Launch the prompt"""
|
||||
for srv in servers:
|
||||
servers[srv].update_mods(MODS)
|
||||
|
||||
ret = ""
|
||||
cmds = list()
|
||||
while ret != "quit" and ret != "reset":
|
||||
sys.stdout.write("\033[0;33m%s§\033[0m " % getPS1())
|
||||
sys.stdout.flush()
|
||||
sys.stdout.write("\033[0;33m%s§\033[0m " % getPS1())
|
||||
sys.stdout.flush()
|
||||
for k in sys.stdin.readline().strip().split(";"):
|
||||
try:
|
||||
cmds = parsecmd(sys.stdin.readline().strip())
|
||||
cmds = parsecmd(k)
|
||||
except KeyboardInterrupt:
|
||||
cmds = parsecmd("quit")
|
||||
except:
|
||||
@ -66,23 +75,77 @@ def launch(servers):
|
||||
# #
|
||||
##########################
|
||||
|
||||
def load_module(config, servers):
|
||||
global MODS
|
||||
if config.hasAttribute("name"):
|
||||
try:
|
||||
#Import the module code
|
||||
mod = imp.load_source(config["name"], modules_path + "/" + config["name"] + ".py")
|
||||
try:
|
||||
if mod.nemubotversion < 3.0:
|
||||
print (" Module `%s' is not compatible with this version." % config["name"])
|
||||
return
|
||||
|
||||
#Set module common functions and datas
|
||||
mod.name = config["name"]
|
||||
mod.print = lambda msg: print("[%s] %s"%(mod.name, msg))
|
||||
mod.DATAS = xmlparser.parse_file(datas_path + "/" + config["name"] + ".xml")
|
||||
mod.CONF = config
|
||||
mod.save = lambda: mod.DATAS.save(datas_path + "/" + config["name"] + ".xml")
|
||||
|
||||
try:
|
||||
mod.load()
|
||||
print (" Module `%s' successfully loaded." % config["name"])
|
||||
except AttributeError:
|
||||
print (" Module `%s' successfully added." % config["name"])
|
||||
MODS.append(mod)
|
||||
except AttributeError:
|
||||
print (" Module `%s' is not a nemubot module." % config["name"])
|
||||
for srv in servers:
|
||||
servers[srv].update_mods(MODS)
|
||||
except IOError:
|
||||
print (" Module `%s' not loaded: unable to find module implementation." % config["name"])
|
||||
|
||||
|
||||
def load(cmds, servers):
|
||||
"""Load an XML configuration file"""
|
||||
if len(cmds) > 1:
|
||||
for f in cmds[1:]:
|
||||
dom = parse(f)
|
||||
config = dom.getElementsByTagName('config')[0]
|
||||
for serveur in config.getElementsByTagName('server'):
|
||||
srv = server.Server(serveur, config.getAttribute('nick'), config.getAttribute('owner'), config.getAttribute('realname'))
|
||||
if srv.id not in servers:
|
||||
servers[srv.id] = srv
|
||||
print (" Server `%s' successfully added." % srv.id)
|
||||
else:
|
||||
print (" Server `%s' already added, skiped." % srv.id)
|
||||
config = xmlparser.parse_file(f)
|
||||
if config.getName() == "nemubotconfig" or config.getName() == "config":
|
||||
#Preset each server in this file
|
||||
for serveur in config.getChilds():
|
||||
srv = server.Server(serveur, config.getAttribute('nick'), config.getAttribute('owner'), config.getAttribute('realname'))
|
||||
if srv.id not in servers:
|
||||
servers[srv.id] = srv
|
||||
print (" Server `%s' successfully added." % srv.id)
|
||||
else:
|
||||
print (" Server `%s' already added, skiped." % srv.id)
|
||||
|
||||
elif config.getName() == "nemubotmodule":
|
||||
load_module(config, servers)
|
||||
else:
|
||||
print (" Can't load `%s'; this is not a valid nemubot configuration file." % f)
|
||||
else:
|
||||
print ("Not enough arguments. `load' takes an filename.")
|
||||
return
|
||||
|
||||
def unload(cmds, servers):
|
||||
"""Unload a module"""
|
||||
global MODS
|
||||
if len(cmds) == 2 and cmds[1] == "all":
|
||||
for mod in MODS:
|
||||
try:
|
||||
mod.unload()
|
||||
except AttributeError:
|
||||
continue
|
||||
while len(MODS) > 0:
|
||||
MODS.pop()
|
||||
elif len(cmds) > 1:
|
||||
print("Ok")
|
||||
|
||||
def close(cmds, servers):
|
||||
"""Disconnect and forget (remove from the servers list) the server"""
|
||||
global selectedServer
|
||||
if len(cmds) > 1:
|
||||
for s in cmds[1:]:
|
||||
@ -98,6 +161,7 @@ def close(cmds, servers):
|
||||
return
|
||||
|
||||
def select(cmds, servers):
|
||||
"""Select the current server"""
|
||||
global selectedServer
|
||||
if len(cmds) == 2 and cmds[1] != "None" and cmds[1] != "nemubot" and cmds[1] != "none":
|
||||
if cmds[1] in servers:
|
||||
@ -109,12 +173,16 @@ def select(cmds, servers):
|
||||
return
|
||||
|
||||
def liste(cmds, servers):
|
||||
"""Show some lists"""
|
||||
if len(cmds) > 1:
|
||||
for l in cmds[1:]:
|
||||
l = l.lower()
|
||||
if l == "server" or l == "servers":
|
||||
for srv in servers.keys():
|
||||
print (" - %s ;" % srv)
|
||||
elif l == "mod" or l == "mods" or l == "module" or l == "modules":
|
||||
for mod in MODS:
|
||||
print (" - %s ;" % mod.name)
|
||||
elif l == "chan" or l == "channel" or l == "channels":
|
||||
if selectedServer is not None:
|
||||
for chn in selectedServer.channels:
|
||||
@ -127,6 +195,7 @@ def liste(cmds, servers):
|
||||
print (" Please give a list to show: servers, ...")
|
||||
|
||||
def connect(cmds, servers):
|
||||
"""Make the connexion to a server"""
|
||||
if len(cmds) > 1:
|
||||
for s in cmds[1:]:
|
||||
if s in servers:
|
||||
@ -140,6 +209,7 @@ def connect(cmds, servers):
|
||||
print (" Please SELECT a server or give its name in argument.")
|
||||
|
||||
def join(cmds, servers):
|
||||
"""Join or leave a channel"""
|
||||
rd = 1
|
||||
if len(cmds) <= rd:
|
||||
print ("%s: not enough arguments." % cmds[0])
|
||||
@ -164,6 +234,7 @@ def join(cmds, servers):
|
||||
srv.leave(cmds[rd])
|
||||
|
||||
def send(cmds, servers):
|
||||
"""Built-on that send a message on a channel"""
|
||||
rd = 1
|
||||
if len(cmds) <= rd:
|
||||
print ("send: not enough arguments.")
|
||||
@ -202,6 +273,7 @@ def send(cmds, servers):
|
||||
return "done"
|
||||
|
||||
def disconnect(cmds, servers):
|
||||
"""Close the connection to a server"""
|
||||
if len(cmds) > 1:
|
||||
for s in cmds[1:]:
|
||||
if s in servers:
|
||||
@ -216,6 +288,7 @@ def disconnect(cmds, servers):
|
||||
print (" Please SELECT a server or give its name in argument.")
|
||||
|
||||
def zap(cmds, servers):
|
||||
"""Hard change connexion state"""
|
||||
if len(cmds) > 1:
|
||||
for s in cmds[1:]:
|
||||
if s in servers:
|
||||
@ -228,6 +301,7 @@ def zap(cmds, servers):
|
||||
print (" Please SELECT a server or give its name in argument.")
|
||||
|
||||
def end(cmds, servers):
|
||||
"""Quit the prompt for reload or exit"""
|
||||
if cmds[0] == "reset":
|
||||
return "reset"
|
||||
else:
|
||||
@ -240,8 +314,9 @@ CAPS = {
|
||||
'quit': end, #Disconnect all server and quit
|
||||
'exit': end, #Alias for quit
|
||||
'reset': end, #Reload the prompt
|
||||
'load': load, #Load a servers configuration file
|
||||
'load': load, #Load a servers or module configuration file
|
||||
'close': close, #Disconnect and remove a server from the list
|
||||
'unload': unload, #Unload a module and remove it from the list
|
||||
'select': select, #Select a server
|
||||
'list': liste, #Show lists
|
||||
'connect': connect, #Connect to a server
|
||||
|
@ -34,7 +34,7 @@ class Server(threading.Thread):
|
||||
self.partner = "nbr23"
|
||||
|
||||
self.channels = list()
|
||||
for channel in server.getElementsByTagName('channel'):
|
||||
for channel in server.getChilds():
|
||||
self.channels.append(channel.getAttribute("name"))
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
@ -102,6 +102,9 @@ class Server(threading.Thread):
|
||||
else:
|
||||
return False
|
||||
|
||||
def update_mods(self, mods):
|
||||
self.mods = mods
|
||||
|
||||
def launch(self, mods):
|
||||
if not self.connected:
|
||||
self.stop = False
|
||||
|
Loading…
x
Reference in New Issue
Block a user