Module events now working

This commit is contained in:
Némunaire 2012-06-20 16:24:19 +02:00
parent 61ac7b11f5
commit d9eab146e6
3 changed files with 116 additions and 204 deletions

View File

@ -41,7 +41,10 @@ class ModuleState:
if isinstance(self.attributes[name], datetime): if isinstance(self.attributes[name], datetime):
return self.attributes[name] return self.attributes[name]
else: else:
return date.fromtimestamp(float(self.attributes[name])) try:
return datetime.fromtimestamp(float(self.attributes[name]))
except ValueError:
return datetime.fromtimestamp(time.mktime(time.strptime(self.attributes[name][:19], "%Y-%m-%d %H:%M:%S")))
else: else:
return None return None

View File

@ -7,194 +7,84 @@ from datetime import datetime
from datetime import date from datetime import date
import time import time
import threading import threading
from xml.dom.minidom import parse
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
import imodule from module_state import ModuleState
class Manager(threading.Thread):
def __init__(self, servers):
self.servers = servers
self.stop = False
threading.Thread.__init__(self)
def run(self):
global STREND
while not self.stop:
newStrendEvt.clear()
closer = None
#Gets the closer event
for evt in STREND.keys():
if ((closer is None or closer.end is None) or (STREND[evt].end is not None and STREND[evt].end < closer.end)) and STREND[evt].end is not None and STREND[evt].end > datetime.now():
closer = STREND[evt]
if closer is not None and closer.end is not None:
#print ("Closer: %s à %s"%(closer.name, closer.end))
timeleft = (closer.end - datetime.now()).seconds
timer = threading.Timer(timeleft, closer.alertEnd, (self.servers,))
timer.start()
#print ("Start timer (%ds)"%timeleft)
newStrendEvt.wait()
if closer is not None and closer.end is not None and closer.end > datetime.now():
timer.cancel()
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")
self.server = item.getAttribute("server")
self.channel = item.getAttribute("channel")
if item.getAttribute("end") is not None and item.getAttribute("end") != "":
try:
self.end = datetime.fromtimestamp (time.mktime (time.strptime (item.getAttribute("end")[:19], "%Y-%m-%d %H:%M:%S")))
except:
self.end = None
else:
self.end = None
else:
self.start = datetime.now()
self.end = None
def alertEnd(self, SRVS):
for server in SRVS.keys():
if server == self.server:
if self.channel == SRVS[server].nick:
SRVS[server].send_msg_usr(self.proprio, "%s: %s arrivé à échéance."%(self.proprio, self.name))
else:
SRVS[server].send_msg(self.channel, "%s: %s arrivé à échéance."%(self.proprio, self.name))
del STREND[self.name]
newStrendEvt.set()
class Nemodule(imodule.ModuleBase):
filename = ""
events = dict()
strend = dict()
threadManager = None
newStrendEvt = threading.Event()
def launch (self, servers):
self.stop()
self.threadManager = Manager(servers)
self.threadManager.start()
def stop (self):
if self.threadManager is not None:
self.threadManager.stop = True
self.newStrendEvt.set()
def xmlparse(self, 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"))
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
if (item.hasAttribute("second")):
second = int(item.getAttribute("second"))
else:
second = 0
if year == month == day == hour == minute == second == 0:
events[item.getAttribute("name")] = (None, item.getAttribute("before_after"), None)
else:
events[item.getAttribute("name")] = (datetime(year, month, day, hour, minute, second),item.getAttribute("msg_before"), item.getAttribute("msg_after"))
def load_module(datas_path):
"""Load this module"""
global EVENTS, STREND, filename
EVENTS = {}
STREND = {}
filename = datas_path + "/events.xml"
sys.stdout.write ("Loading events ... ")
dom = parse(filename)
xmlparse (dom.getElementsByTagName('events')[0])
print ("done (%d loaded)" % len(EVENTS))
def save_module():
"""Save the dates"""
global filename
sys.stdout.write ("Saving events ... ")
impl = getDOMImplementation()
newdoc = impl.createDocument(None, 'events', None)
top = newdoc.documentElement
for name in STREND.keys():
iend = ""
if STREND[name].end is not None:
iend = ' end="%s"'%STREND[name].end
item = parseString ('<strend name="%s" start="%s" proprio="%s" server="%s" channel="%s"%s />' % (name, STREND[name].start, STREND[name].proprio, STREND[name].server, STREND[name].channel, iend)).documentElement
top.appendChild(item);
for name in EVENTS.keys():
(day, msg_before, msg_after) = EVENTS[name]
bonus=""
if day is None:
item = parseString ('<event name="%s" msg_before="%s" />' % (name, msg_before)).documentElement
else:
if day.hour != 0:
bonus += 'hour="%s" ' % day.hour
if day.minute != 0:
bonus += 'minute="%s" ' % day.minute
if day.second != 1:
bonus += 'second="%s" ' % day.second
item = parseString ('<event name="%s" year="%d" month="%d" day="%d" %s msg_after="%s" msg_before="%s" />' % (name, day.year, day.month, day.day, bonus, msg_after, msg_before)).documentElement
top.appendChild(item);
with open(filename, "w") as f:
newdoc.writexml (f)
print ("done")
nemubotversion = 3.0
def help_tiny (): def help_tiny ():
"""Line inserted in the response to the command !help""" """Line inserted in the response to the command !help"""
return "events manager" return "events manager"
def help_full (): def help_full ():
return "This module store a lot of events: ny, we, vacs, " + (", ".join(EVENTS.keys())) + "\n!eventslist: gets list of timer\n!start /something/: launch a timer" return "This module store a lot of events: ny, we, vacs, " + (", ".join(DATAS.index.keys())) + "\n!eventslist: gets list of timer\n!start /something/: launch a timer"
class Manager(threading.Thread):
def __init__(self):
self.stop = False
threading.Thread.__init__(self)
def alertEnd(self, evt):
global newStrendEvt, SRVS, DATAS
#Send the message on each matched servers
for server in SRVS.keys():
if not evt.hasAttribute("server") or server == evt["server"]:
if evt["channel"] == SRVS[server].nick:
SRVS[server].send_msg_usr(evt["proprio"], "%s: %s arrivé à échéance." % (evt["proprio"], evt["name"]))
else:
SRVS[server].send_msg(evt["channel"], "%s: %s arrivé à échéance." % (evt["proprio"], evt["name"]))
DATAS.delChild(DATAS.index[evt["name"]])
save()
newStrendEvt.set()
def run(self):
global DATAS
while not self.stop:
newStrendEvt.clear()
closer = None
#Gets the closer event
for evt in DATAS.index.keys():
if DATAS.index[evt].hasAttribute("end") and (closer is None or DATAS.index[evt].getDate("end") < closer.getDate("end")) and DATAS.index[evt].getDate("end") > datetime.now():
closer = DATAS.index[evt]
if closer is not None and closer.hasAttribute("end"):
#print ("Closer: %s à %s"%(closer.name, closer["end"]))
timeleft = (closer.getDate("end") - datetime.now()).seconds
timer = threading.Timer(timeleft, self.alertEnd, (closer,))
timer.start()
#print ("Start timer (%ds)"%timeleft)
newStrendEvt.wait()
if closer is not None and closer.hasAttribute("end") and closer.getDate("end") > datetime.now():
timer.cancel()
self.threadManager = None
threadManager = None
newStrendEvt = threading.Event()
def load():
global DATAS
#Define the index
DATAS.setIndex("name")
#Load the manager
threadManager = Manager()
threadManager.start()
def close():
if self.threadManager is not None:
self.threadManager.stop = True
self.newStrendEvt.set()
def parseanswer(msg): def parseanswer(msg):
global STREND global DATAS
if msg.cmd[0] == "we" or msg.cmd[0] == "week-end" or msg.cmd[0] == "weekend": 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.today() + timedelta(5 - datetime.today().weekday())
ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1)
msg.send_chn ( msg.send_chn (
msg.countdown_format (ndate, msg.countdown_format (ndate,
"Il reste %s avant le week-end, courrage ;)", "Il reste %s avant le week-end, courage ;)",
"Youhou, on est en week-end depuis %s.")) "Youhou, on est en week-end depuis %s."))
return True return True
elif msg.cmd[0] == "new-year" or msg.cmd[0] == "newyear" or msg.cmd[0] == "ny": elif msg.cmd[0] == "new-year" or msg.cmd[0] == "newyear" or msg.cmd[0] == "ny":
@ -210,55 +100,58 @@ def parseanswer(msg):
"Profitons, c'est les vacances depuis %s.")) "Profitons, c'est les vacances depuis %s."))
return True return True
elif msg.cmd[0] == "start" and len(msg.cmd) > 1: elif msg.cmd[0] == "start" and len(msg.cmd) > 1:
if msg.cmd[1] not in STREND: if msg.cmd[1] not in DATAS:
STREND[msg.cmd[1]] = Strend(None) strnd = ModuleState("strend")
STREND[msg.cmd[1]].server = msg.srv.id strnd["server"] = msg.srv.id
STREND[msg.cmd[1]].channel = msg.channel strnd["channel"] = msg.channel
STREND[msg.cmd[1]].proprio = msg.sender strnd["proprio"] = msg.sender
STREND[msg.cmd[1]].name = msg.cmd[1] strnd["start"] = datetime.now()
strnd["name"] = msg.cmd[1]
DATAS.addChild(strnd)
if len(msg.cmd) > 2: if len(msg.cmd) > 2:
result = re.match("([0-9]+)([smhdjSMHDJ])?", msg.cmd[2]) result = re.match("([0-9]+)([smhdjSMHDJ])?", msg.cmd[2])
if result is not None: if result is not None:
try: try:
if result.group(2) is not None and (result.group(2) == "m" or result.group(2) == "M"): if result.group(2) is not None and (result.group(2) == "m" or result.group(2) == "M"):
STREND[msg.cmd[1]].end = datetime.now() + timedelta(minutes=int(result.group(1))) strnd["end"] = datetime.now() + timedelta(minutes=int(result.group(1)))
elif result.group(2) is not None and (result.group(2) == "h" or result.group(2) == "H"): elif result.group(2) is not None and (result.group(2) == "h" or result.group(2) == "H"):
STREND[msg.cmd[1]].end = datetime.now() + timedelta(hours=int(result.group(1))) strnd["end"] = datetime.now() + timedelta(hours=int(result.group(1)))
elif result.group(2) is not None and (result.group(2) == "d" or result.group(2) == "D" or result.group(2) == "j" or result.group(2) == "J"): elif result.group(2) is not None and (result.group(2) == "d" or result.group(2) == "D" or result.group(2) == "j" or result.group(2) == "J"):
STREND[msg.cmd[1]].end = datetime.now() + timedelta(days=int(result.group(1))) strnd["end"] = datetime.now() + timedelta(days=int(result.group(1)))
else: else:
STREND[msg.cmd[1]].end = datetime.now() + timedelta(seconds=int(result.group(1))) strnd["end"] = datetime.now() + timedelta(seconds=int(result.group(1)))
newStrendEvt.set() newStrendEvt.set()
msg.send_snd ("%s commencé le %s et se terminera le %s."% (msg.cmd[1], datetime.now(), STREND[msg.cmd[1]].end)) msg.send_snd ("%s commencé le %s et se terminera le %s."% (msg.cmd[1], datetime.now(), strnd.getDate("end")))
except: except:
msg.send_snd ("Impossible de définir la fin de %s."% (msg.cmd[1])) msg.send_snd ("Impossible de définir la fin de %s."% (msg.cmd[1]))
msg.send_snd ("%s commencé le %s."% (msg.cmd[1], datetime.now())) msg.send_snd ("%s commencé le %s."% (msg.cmd[1], datetime.now()))
else: else:
msg.send_snd ("%s commencé le %s"% (msg.cmd[1], datetime.now())) msg.send_snd ("%s commencé le %s"% (msg.cmd[1], datetime.now()))
save()
else: else:
msg.send_snd ("%s existe déjà."% (msg.cmd[1])) msg.send_snd ("%s existe déjà."% (msg.cmd[1]))
return True
elif (msg.cmd[0] == "end" or msg.cmd[0] == "forceend") and len(msg.cmd) > 1: elif (msg.cmd[0] == "end" or msg.cmd[0] == "forceend") and len(msg.cmd) > 1:
if msg.cmd[1] in STREND: if msg.cmd[1] in DATAS.index and DATAS.index[msg.cmd[1]].hasAttribute("end"):
msg.send_chn ("%s a duré %s." % (msg.cmd[1], msg.just_countdown(datetime.now () - STREND[msg.cmd[1]].start))) msg.send_chn ("%s a duré %s." % (msg.cmd[1], msg.just_countdown(datetime.now () - DATAS.index[msg.cmd[1]].getDate("start"))))
if STREND[msg.cmd[1]].proprio == msg.sender or (msg.cmd[0] == "forceend" and msg.sender == msg.srv.owner): if DATAS.index[msg.cmd[1]]["proprio"] == msg.sender or (msg.cmd[0] == "forceend" and msg.sender == msg.srv.owner):
del STREND[msg.cmd[1]] DATAS.delChild(DATAS.index[msg.cmd[1]])
newStrendEvt.set() newStrendEvt.set()
save()
else: else:
msg.send_snd ("Vous ne pouvez pas terminer le compteur %s, créé par %s."% (msg.cmd[1], STREND[msg.cmd[1]].proprio)) msg.send_snd ("Vous ne pouvez pas terminer le compteur %s, créé par %s."% (msg.cmd[1], DATAS.index[msg.cmd[1]]["proprio"]))
else: else:
msg.send_snd ("%s n'est pas un compteur connu."% (msg.cmd[1])) msg.send_snd ("%s n'est pas un compteur connu."% (msg.cmd[1]))
return True
elif msg.cmd[0] == "eventslist" or msg.cmd[0] == "eventlist" or msg.cmd[0] == "eventsliste" or msg.cmd[0] == "eventliste": 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())) msg.send_snd ("Compteurs connus : %s." % ", ".join(DATAS.index.keys()))
elif msg.cmd[0] in STREND: elif msg.cmd[0] in DATAS.index:
msg.send_chn ("%s commencé il y a %s." % (msg.cmd[0], msg.just_countdown(datetime.now () - STREND[msg.cmd[0]].start))) if DATAS.index[msg.cmd[0]].name == "strend":
elif msg.cmd[0] in EVENTS: msg.send_chn ("%s commencé il y a %s." % (msg.cmd[0], msg.just_countdown(datetime.now () - DATAS.index[msg.cmd[0]].getDate("start"))))
(day, msg_before, msg_after) = EVENTS[msg.cmd[0]]
if day is None:
msg.send_chn (msg_before)
else: else:
msg.send_chn (msg.countdown_format (day, msg_before, msg_after)) msg.send_chn (msg.countdown_format (DATAS.index[msg.cmd[0]].getDate("start"), DATAS.index[msg.cmd[0]]["msg_before"], DATAS.index[msg.cmd[0]]["msg_after"]))
save()
return True return True
else: else:
return False return False
@ -268,7 +161,7 @@ def parseask(msg):
msgl = msg.content.lower () msgl = msg.content.lower ()
if re.match("^.*((create|new) +(a|an|a +new|an *other)? *(events?|commande?)|(nouvel(le)?|ajoute|cr[ée]{1,3}) +(un)? *([eé]v[ée]nements?|commande?)).*$", msgl) is not None: if re.match("^.*((create|new) +(a|an|a +new|an *other)? *(events?|commande?)|(nouvel(le)?|ajoute|cr[ée]{1,3}) +(un)? *([eé]v[ée]nements?|commande?)).*$", msgl) is not None:
name = re.match("^.*!([^ \"'@!]+).*$", msg.content) name = re.match("^.*!([^ \"'@!]+).*$", msg.content)
if name is not None and name.group (1) not in EVENTS: if name is not None and name.group (1) not in DATAS.index:
texts = re.match("^[^\"]*(avant|après|apres|before|after)?[^\"]*\"([^\"]+)\"[^\"]*((avant|après|apres|before|after)?.*\"([^\"]+)\".*)?$", msg.content) texts = re.match("^[^\"]*(avant|après|apres|before|after)?[^\"]*\"([^\"]+)\"[^\"]*((avant|après|apres|before|after)?.*\"([^\"]+)\".*)?$", msg.content)
if texts is not None and texts.group (3) is not None: if texts is not None and texts.group (3) is not None:
extDate = msg.extractDate () extDate = msg.extractDate ()
@ -283,14 +176,28 @@ def parseask(msg):
msg_after = texts.group (5) msg_after = texts.group (5)
if msg_before.find ("%s") != -1 and msg_after.find ("%s") != -1: if msg_before.find ("%s") != -1 and msg_after.find ("%s") != -1:
EVENTS[name.group (1)] = (extDate, msg_before, msg_after) evt = ModuleState("event")
save_module () evt["server"] = msg.srv.id
evt["channel"] = msg.channel
evt["proprio"] = msg.sender
evt["name"] = name.group(1)
evt["start"] = extDate
evt["msg_after"] = msg_after
evt["msg_before"] = msg_before
DATAS.addChild(evt)
save()
msg.send_snd ("Nouvel événement !%s ajouté avec succès."%name.group (1)) msg.send_snd ("Nouvel événement !%s ajouté avec succès."%name.group (1))
else: else:
msg.send_snd ("Pour que l'événement soit valide, ajouter %s à l'endroit où vous voulez que soit ajouté le compte à rebours.") msg.send_snd ("Pour que l'événement soit valide, ajouter %s à l'endroit où vous voulez que soit ajouté le compte à rebours.")
elif texts is not None and texts.group (2) is not None: elif texts is not None and texts.group (2) is not None:
EVENTS[name.group (1)] = (None, texts.group (2), None) evt = ModuleState("event")
save_module () evt["server"] = msg.srv.id
evt["channel"] = msg.channel
evt["proprio"] = msg.sender
evt["name"] = name.group(1)
evt["msg_before"] = texts.group (2)
DATAS.addChild(evt)
save()
msg.send_snd ("Nouvelle commande !%s ajoutée avec succès."%name.group (1)) msg.send_snd ("Nouvelle commande !%s ajoutée avec succès."%name.group (1))
else: else:
msg.send_snd ("Veuillez indiquez les messages d'attente et d'après événement entre guillemets.") msg.send_snd ("Veuillez indiquez les messages d'attente et d'après événement entre guillemets.")

2
modules/events.xml Normal file
View File

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