1
0
Fork 0

events: Use the new data parser, knodes based

This commit is contained in:
nemunaire 2017-09-01 20:47:38 +02:00
parent ce4140ade8
commit 26f301d6b4
1 changed files with 110 additions and 62 deletions

View File

@ -1,7 +1,9 @@
"""Create countdowns and reminders""" """Create countdowns and reminders"""
import re import calendar
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from functools import partial
import re
from nemubot import context from nemubot import context
from nemubot.exception import IMException from nemubot.exception import IMException
@ -10,29 +12,84 @@ from nemubot.hooks import hook
from nemubot.message import Command from nemubot.message import Command
from nemubot.tools.countdown import countdown_format, countdown from nemubot.tools.countdown import countdown_format, countdown
from nemubot.tools.date import extractDate from nemubot.tools.date import extractDate
from nemubot.tools.xmlparser.node import ModuleState from nemubot.tools.xmlparser.basic import DictNode
from nemubot.module.more import Response from nemubot.module.more import Response
class Event:
def __init__(self, server, channel, creator, start_time, end_time=None):
self._server = server
self._channel = channel
self._creator = creator
self._start = datetime.utcfromtimestamp(float(start_time)).replace(tzinfo=timezone.utc) if not isinstance(start_time, datetime) else start_time
self._end = datetime.utcfromtimestamp(float(end_time)).replace(tzinfo=timezone.utc) if end_time else None
self._evt = None
def __del__(self):
if self._evt is not None:
context.del_event(self._evt)
self._evt = None
def saveElement(self, store, tag="event"):
attrs = {
"server": str(self._server),
"channel": str(self._channel),
"creator": str(self._creator),
"start_time": str(calendar.timegm(self._start.timetuple())),
}
if self._end:
attrs["end_time"] = str(calendar.timegm(self._end.timetuple()))
store.startElement(tag, attrs)
store.endElement(tag)
@property
def creator(self):
return self._creator
@property
def start(self):
return self._start
@property
def end(self):
return self._end
@end.setter
def end(self, c):
self._end = c
@end.deleter
def end(self):
self._end = None
def help_full (): def help_full ():
return "This module store a lot of events: ny, we, " + (", ".join(context.datas.index.keys() if hasattr(context, "datas") else [])) + "\n!eventslist: gets list of timer\n!start /something/: launch a timer" return "This module store a lot of events: ny, we, " + (", ".join(context.datas.keys()) if hasattr(context, "datas") else "") + "\n!eventslist: gets list of timer\n!start /something/: launch a timer"
def load(context): def load(context):
#Define the index context.set_knodes({
context.data.setIndex("name") "dict": DictNode,
"event": Event,
})
for evt in context.data.index.keys(): if context.data is None:
if context.data.index[evt].hasAttribute("end"): context.data = DictNode()
event = ModuleEvent(call=fini, call_data=dict(strend=context.data.index[evt]))
event.schedule(context.data.index[evt].getDate("end")) # Relaunch all timers
context.add_event(event) for kevt in context.data:
if context.data[kevt].end:
context.data[kevt]._evt = context.call_at(context.data[kevt].end, partial(fini, kevt, context.data[kevt]))
def fini(d, strend): def fini(name, evt):
context.send_response(strend["server"], Response("%s arrivé à échéance." % strend["name"], channel=strend["channel"], nick=strend["proprio"])) context.send_response(evt._server, Response("%s arrivé à échéance." % name, channel=evt._channel, nick=evt.creator))
context.data.delChild(context.data.index[strend["name"]]) evt._evt = None
del context.data[name]
context.save() context.save()
@ -61,18 +118,10 @@ def start_countdown(msg):
"""!start /something/: launch a timer""" """!start /something/: launch a timer"""
if len(msg.args) < 1: if len(msg.args) < 1:
raise IMException("indique le nom d'un événement à chronométrer") raise IMException("indique le nom d'un événement à chronométrer")
if msg.args[0] in context.data.index: if msg.args[0] in context.data:
raise IMException("%s existe déjà." % msg.args[0]) raise IMException("%s existe déjà." % msg.args[0])
strnd = ModuleState("strend") evt = Event(server=msg.server, channel=msg.channel, creator=msg.frm, start_time=msg.date)
strnd["server"] = msg.server
strnd["channel"] = msg.channel
strnd["proprio"] = msg.frm
strnd["start"] = msg.date
strnd["name"] = msg.args[0]
context.data.addChild(strnd)
evt = ModuleEvent(call=fini, call_data=dict(strend=strnd))
if len(msg.args) > 1: if len(msg.args) > 1:
result1 = re.findall("([0-9]+)([smhdjwyaSMHDJWYA])?", msg.args[1]) result1 = re.findall("([0-9]+)([smhdjwyaSMHDJWYA])?", msg.args[1])
@ -90,48 +139,48 @@ def start_countdown(msg):
if result2 is None or result2.group(4) is None: yea = now.year if result2 is None or result2.group(4) is None: yea = now.year
else: yea = int(result2.group(4)) else: yea = int(result2.group(4))
if result2 is not None and result3 is not None: if result2 is not None and result3 is not None:
strnd["end"] = datetime(yea, int(result2.group(3)), int(result2.group(2)), hou, minu, sec, timezone.utc) evt.end = datetime(yea, int(result2.group(3)), int(result2.group(2)), hou, minu, sec, timezone.utc)
elif result2 is not None: elif result2 is not None:
strnd["end"] = datetime(int(result2.group(4)), int(result2.group(3)), int(result2.group(2)), 0, 0, 0, timezone.utc) evt.end = datetime(int(result2.group(4)), int(result2.group(3)), int(result2.group(2)), 0, 0, 0, timezone.utc)
elif result3 is not None: elif result3 is not None:
if hou * 3600 + minu * 60 + sec > now.hour * 3600 + now.minute * 60 + now.second: if hou * 3600 + minu * 60 + sec > now.hour * 3600 + now.minute * 60 + now.second:
strnd["end"] = datetime(now.year, now.month, now.day, hou, minu, sec, timezone.utc) evt.end = datetime(now.year, now.month, now.day, hou, minu, sec, timezone.utc)
else: else:
strnd["end"] = datetime(now.year, now.month, now.day + 1, hou, minu, sec, timezone.utc) evt.end = datetime(now.year, now.month, now.day + 1, hou, minu, sec, timezone.utc)
evt.schedule(strnd.getDate("end"))
context.add_event(evt)
except: except:
context.data.delChild(strnd)
raise IMException("Mauvais format de date pour l'événement %s. Il n'a pas été créé." % msg.args[0]) raise IMException("Mauvais format de date pour l'événement %s. Il n'a pas été créé." % msg.args[0])
elif result1 is not None and len(result1) > 0: elif result1 is not None and len(result1) > 0:
strnd["end"] = msg.date evt.end = msg.date
for (t, g) in result1: for (t, g) in result1:
if g is None or g == "" or g == "m" or g == "M": if g is None or g == "" or g == "m" or g == "M":
strnd["end"] += timedelta(minutes=int(t)) evt.end += timedelta(minutes=int(t))
elif g == "h" or g == "H": elif g == "h" or g == "H":
strnd["end"] += timedelta(hours=int(t)) evt.end += timedelta(hours=int(t))
elif g == "d" or g == "D" or g == "j" or g == "J": elif g == "d" or g == "D" or g == "j" or g == "J":
strnd["end"] += timedelta(days=int(t)) evt.end += timedelta(days=int(t))
elif g == "w" or g == "W": elif g == "w" or g == "W":
strnd["end"] += timedelta(days=int(t)*7) evt.end += timedelta(days=int(t)*7)
elif g == "y" or g == "Y" or g == "a" or g == "A": elif g == "y" or g == "Y" or g == "a" or g == "A":
strnd["end"] += timedelta(days=int(t)*365) evt.end += timedelta(days=int(t)*365)
else: else:
strnd["end"] += timedelta(seconds=int(t)) evt.end += timedelta(seconds=int(t))
evt.schedule(strnd.getDate("end"))
context.add_event(evt)
context.data[msg.args[0]] = evt
context.save() context.save()
if "end" in strnd:
if evt.end is not None:
context.add_event(ModuleEvent(partial(fini, msg.args[0], evt),
offset=evt.end - datetime.now(timezone.utc),
interval=0))
return Response("%s commencé le %s et se terminera le %s." % return Response("%s commencé le %s et se terminera le %s." %
(msg.args[0], msg.date.strftime("%A %d %B %Y à %H:%M:%S"), (msg.args[0], msg.date.strftime("%A %d %B %Y à %H:%M:%S"),
strnd.getDate("end").strftime("%A %d %B %Y à %H:%M:%S")), evt.end.strftime("%A %d %B %Y à %H:%M:%S")),
nick=msg.frm) channel=msg.channel)
else: else:
return Response("%s commencé le %s"% (msg.args[0], return Response("%s commencé le %s"% (msg.args[0],
msg.date.strftime("%A %d %B %Y à %H:%M:%S")), msg.date.strftime("%A %d %B %Y à %H:%M:%S")),
nick=msg.frm) channel=msg.channel)
@hook.command("end") @hook.command("end")
@ -140,16 +189,15 @@ def end_countdown(msg):
if len(msg.args) < 1: if len(msg.args) < 1:
raise IMException("quel événement terminer ?") raise IMException("quel événement terminer ?")
if msg.args[0] in context.data.index: if msg.args[0] in context.data:
if context.data.index[msg.args[0]]["proprio"] == msg.frm or (msg.cmd == "forceend" and msg.frm_owner): if context.data[msg.args[0]].creator == msg.frm or (msg.cmd == "forceend" and msg.frm_owner):
duration = countdown(msg.date - context.data.index[msg.args[0]].getDate("start")) duration = countdown(msg.date - context.data[msg.args[0]].start)
context.del_event(context.data.index[msg.args[0]]) del context.data[msg.args[0]]
context.data.delChild(context.data.index[msg.args[0]])
context.save() context.save()
return Response("%s a duré %s." % (msg.args[0], duration), return Response("%s a duré %s." % (msg.args[0], duration),
channel=msg.channel, nick=msg.frm) channel=msg.channel, nick=msg.frm)
else: else:
raise IMException("Vous ne pouvez pas terminer le compteur %s, créé par %s." % (msg.args[0], context.data.index[msg.args[0]]["proprio"])) raise IMException("Vous ne pouvez pas terminer le compteur %s, créé par %s." % (msg.args[0], context.data[msg.args[0]].creator))
else: else:
return Response("%s n'est pas un compteur connu."% (msg.args[0]), channel=msg.channel, nick=msg.frm) return Response("%s n'est pas un compteur connu."% (msg.args[0]), channel=msg.channel, nick=msg.frm)
@ -158,19 +206,19 @@ def end_countdown(msg):
def liste(msg): def liste(msg):
"""!eventslist: gets list of timer""" """!eventslist: gets list of timer"""
if len(msg.args): if len(msg.args):
res = list() res = Response(channel=msg.channel)
for user in msg.args: for user in msg.args:
cmptr = [x["name"] for x in context.data.index.values() if x["proprio"] == user] cmptr = [k for k in context.data if context.data[k].creator == user]
if len(cmptr) > 0: if len(cmptr) > 0:
res.append("Compteurs créés par %s : %s" % (user, ", ".join(cmptr))) res.append_message(cmptr, title="Events created by %s" % user)
else: else:
res.append("%s n'a pas créé de compteur" % user) res.append_message("%s doesn't have any counting events" % user)
return Response(" ; ".join(res), channel=msg.channel) return res
else: else:
return Response("Compteurs connus : %s." % ", ".join(context.data.index.keys()), channel=msg.channel) return Response(list(context.data.keys()), channel=msg.channel, title="Known events")
@hook.command(match=lambda msg: isinstance(msg, Command) and msg.cmd in context.data.index) @hook.command(match=lambda msg: isinstance(msg, Command) and msg.cmd in context.data)
def parseanswer(msg): def parseanswer(msg):
res = Response(channel=msg.channel) res = Response(channel=msg.channel)
@ -178,13 +226,13 @@ def parseanswer(msg):
if msg.cmd[0] == "!": if msg.cmd[0] == "!":
res.nick = msg.frm res.nick = msg.frm
if context.data.index[msg.cmd].name == "strend": if msg.cmd in context.data:
if context.data.index[msg.cmd].hasAttribute("end"): if context.data[msg.cmd].end:
res.append_message("%s commencé il y a %s et se terminera dans %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start")), countdown(context.data.index[msg.cmd].getDate("end") - msg.date))) res.append_message("%s commencé il y a %s et se terminera dans %s." % (msg.cmd, countdown(msg.date - context.data[msg.cmd].start), countdown(context.data[msg.cmd].end - msg.date)))
else: else:
res.append_message("%s commencé il y a %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start")))) res.append_message("%s commencé il y a %s." % (msg.cmd, countdown(msg.date - context.data[msg.cmd].start)))
else: else:
res.append_message(countdown_format(context.data.index[msg.cmd].getDate("start"), context.data.index[msg.cmd]["msg_before"], context.data.index[msg.cmd]["msg_after"])) res.append_message(countdown_format(context.data[msg.cmd].start, context.data[msg.cmd]["msg_before"], context.data[msg.cmd]["msg_after"]))
return res return res
@ -195,7 +243,7 @@ def parseask(msg):
name = re.match("^.*!([^ \"'@!]+).*$", msg.message) name = re.match("^.*!([^ \"'@!]+).*$", msg.message)
if name is None: if name is None:
raise IMException("il faut que tu attribues une commande à l'événement.") raise IMException("il faut que tu attribues une commande à l'événement.")
if name.group(1) in context.data.index: if name.group(1) in context.data:
raise IMException("un événement portant ce nom existe déjà.") raise IMException("un événement portant ce nom existe déjà.")
texts = re.match("^[^\"]*(avant|après|apres|before|after)?[^\"]*\"([^\"]+)\"[^\"]*((avant|après|apres|before|after)?.*\"([^\"]+)\".*)?$", msg.message, re.I) texts = re.match("^[^\"]*(avant|après|apres|before|after)?[^\"]*\"([^\"]+)\"[^\"]*((avant|après|apres|before|after)?.*\"([^\"]+)\".*)?$", msg.message, re.I)