1
0
Fork 0

Module_state done: global datas management

newnemubot replaces old one
This commit is contained in:
Némunaire 2012-05-30 11:58:27 +02:00
parent 684cecd137
commit 25b2634ea3
12 changed files with 453 additions and 414 deletions

View File

@ -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
View File

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
<?xml version="1.0" ?>
<nemubotmodule name="birthday" />

View File

@ -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()

View File

@ -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
View File

@ -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

View File

@ -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