Soutenance module: convert to V3.2

This commit is contained in:
Némunaire 2012-10-15 01:52:32 +02:00
commit 28dee24b5a
3 changed files with 196 additions and 201 deletions

View file

@ -1,4 +1,5 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<nemubotmodule name="soutenance"> <nemubotmodule name="soutenance">
<server ip="intra.acu.epita.fr" url="/intra/sout_liste.html" /> <server ip="www.acu.epita.fr" url="/intra/sout_liste.html" />
<message type="cmd" name="soutenance" call="ask_soutenance" />
</nemubotmodule> </nemubotmodule>

View file

@ -2,17 +2,37 @@
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
import http.client
import re import re
import threading
import time import time
from response import Response
from .Soutenance import Soutenance from .Soutenance import Soutenance
class SiteSoutenances: class SiteSoutenances(threading.Thread):
def __init__(self, page): def __init__(self, datas):
save = False
self.souts = list() self.souts = list()
self.updated = datetime.now() self.updated = datetime.now()
last = None self.datas = datas
threading.Thread.__init__(self)
def getPage(self):
conn = http.client.HTTPSConnection(CONF.getNode("server")["ip"], timeout=10)
try:
conn.request("GET", CONF.getNode("server")["url"])
res = conn.getresponse()
page = res.read()
except:
print ("[%s] impossible de récupérer la page %s."%(s, p))
return ""
conn.close()
return page
def parsePage(self, page):
save = False
for line in page.split("\n"): for line in page.split("\n"):
if re.match("</tr>", line) is not None: if re.match("</tr>", line) is not None:
save = False save = False
@ -46,22 +66,93 @@ class SiteSoutenances:
except ValueError: except ValueError:
last.end = None last.end = None
def update(self): def gen_response(self, req, msg):
if self.findLast() is not None and datetime.now () - self.updated > timedelta(minutes=2): """Generate a text response on right server and channel"""
return None return Response(req["sender"], msg, req["channel"], server=req["server"])
elif datetime.now () - self.updated < timedelta(hours=1):
return self def res_next(self, req):
soutenance = self.findLast()
if soutenance is None:
return self.gen_response(req, "Il ne semble pas y avoir de soutenance pour le moment.")
else: else:
return None if soutenance.start > soutenance.hour:
avre = "%s de *retard*"%msg.just_countdown(soutenance.start - soutenance.hour, 4)
else:
avre = "%s *d'avance*"%msg.just_countdown(soutenance.hour - soutenance.start, 4)
self.gen_response(req, "Actuellement à la soutenance numéro %d, commencée il y a %s avec %s."%(soutenance.rank, msg.just_countdown(datetime.now () - soutenance.start, 4), avre))
def res_assistants(self, req):
assistants = self.findAssistants()
if len(assistants) > 0:
return self.gen_response(req, "Les %d assistants faisant passer les soutenances sont : %s." % (len(assistants), ', '.join(assistants.keys())))
else:
return self.gen_response(req, "Il ne semble pas y avoir de soutenance pour le moment.")
def res_soutenance(self, req):
name = req["user"]
if name == "acu" or name == "yaka" or name == "acus" or name == "yakas" or name == "assistant" or name == "assistants":
return self.res_assistants(req)
elif name == "next":
return self.res_next(req)
soutenance = self.findClose(name)
if soutenance is None:
return self.gen_response(req, "Pas d'horaire de soutenance pour %s."%name)
else:
if soutenance.state == "En cours":
return self.gen_response(req, "%s est actuellement en soutenance avec %s. Elle était prévue à %s, position %d."%(name, soutenance.assistant, soutenance.hour, soutenance.rank))
elif soutenance.state == "Effectue":
return self.gen_response(req, "%s a passé sa soutenance avec %s. Elle a duré %s."%(name, soutenance.assistant, msg.just_countdown(soutenance.end - soutenance.start, 4)))
elif soutenance.state == "Retard":
return self.gen_response(req, "%s était en retard à sa soutenance de %s."%(name, soutenance.hour))
else:
last = self.findLast()
if last is not None:
if soutenance.hour + (last.start - last.hour) > datetime.now ():
return self.gen_response(req, "Soutenance de %s : %s, position %d ; estimation du passage : dans %s."%(name, soutenance.hour, soutenance.rank, msg.just_countdown((soutenance.hour - datetime.now ()) + (last.start - last.hour))))
else:
return self.gen_response(req, "Soutenance de %s : %s, position %d ; passage imminent."%(name, soutenance.hour, soutenance.rank))
else:
return self.gen_response(req, "Soutenance de %s : %s, position %d."%(name, soutenance.hour, soutenance.rank))
def res_list(self, req):
name = req["user"]
souts = self.findAll(name)
if souts is None:
self.gen_response(req, "Pas de soutenance prévues pour %s."%name)
else:
first = True
for s in souts:
if first:
self.gen_response(req, "Soutenance(s) de %s : - %s (position %d) ;"%(name, s.hour, s.rank))
first = False
else:
self.gen_response(req, " %s - %s (position %d) ;"%(len(name)*' ', s.hour, s.rank))
def run(self):
self.parsePage(self.getPage().decode())
res = list()
for u in self.datas.getNodes("request"):
res.append(self.res_soutenance(u))
return res
def needUpdate(self):
if self.findLast() is not None and datetime.now () - self.updated > timedelta(minutes=2):
return True
elif datetime.now () - self.updated < timedelta(hours=1):
return False
else:
return True
def findAssistants(self): def findAssistants(self):
h = {} h = dict()
for s in self.souts: for s in self.souts:
if s.assistant is not None and s.assistant != "": if s.assistant is not None and s.assistant != "":
h[s.assistant] = (s.start, s.end) h[s.assistant] = (s.start, s.end)
return h return h
def findLast(self): def findLast(self):
close = None close = None
for s in self.souts: for s in self.souts:

View file

@ -1,21 +1,15 @@
# coding=utf-8 # coding=utf-8
import http.client
import time import time
import re import re
import _thread
import threading import threading
from datetime import date from datetime import date
from datetime import datetime from datetime import datetime
from module_state import ModuleState from . import SiteSoutenances
from .SiteSoutenances import SiteSoutenances
from .Delayed import Delayed from .Delayed import Delayed
nemubotversion = 3.0 nemubotversion = 3.2
DELAYED = dict()
def help_tiny(): def help_tiny():
"""Line inserted in the response to the command !help""" """Line inserted in the response to the command !help"""
@ -24,123 +18,32 @@ def help_tiny():
def help_full(): def help_full():
return "!soutenance: gives information about current defenses state\n!soutenance <who>: gives the date of the next defense of /who/.\n!soutenances <who>: gives all defense dates of /who/" return "!soutenance: gives information about current defenses state\n!soutenance <who>: gives the date of the next defense of /who/.\n!soutenances <who>: gives all defense dates of /who/"
datas = None def load(context):
THREAD = None global CONF
wait = list() SiteSoutenances.CONF = CONF
def parseanswer(msg): def ask_soutenance(msg):
global THREAD, wait req = ModuleState("request")
if msg.cmd[0] == "soutenance" or msg.cmd[0] == "soutenances": if len(msg.cmd) > 1:
if THREAD is None: req.setAttribute("user", msg.cmd[1])
THREAD = _thread.start_new_thread (startSoutenance, (msg,))
else: else:
wait.append(msg) req.setAttribute("user", "next")
return True req.setAttribute("server", msg.srv.id)
return False req.setAttribute("channel", msg.channel)
req.setAttribute("sender", msg.sender)
#An instance of this module is already running?
if not DATAS.hasAttribute("_running") or DATAS["_running"].needUpdate():
DATAS.addChild(req)
site = SiteSoutenances.SiteSoutenances(DATAS)
DATAS.setAttribute("_running", site)
def parseask(msg): res = site.run()
if len(DELAYED) > 0 and msg.nick == msg.srv.partner:
treat = False
for part in msg.content.split(';'):
if part is None:
continue
for d in DELAYED.keys():
if DELAYED[d].res is None and part.find(DELAYED[d].name) >= 0:
result = re.match(".* est (.*[^.])\.?", part)
if result is not None:
DELAYED[d].res = result.group(1)
DELAYED[d].evt.set()
return treat
return False
for n in DATAS.getNodes("request"):
DATAS.delChild(n)
def startSoutenance (msg): return res
global datas, THREAD, wait
#Starts by updating datas
if datas is not None:
datas = datas.update ()
if datas is None:
datas = SiteSoutenances(getPage().decode())
if len(msg.cmd) == 1 or msg.cmd[1] == "next":
soutenance = datas.findLast()
if soutenance is None:
msg.send_chn ("Il ne semble pas y avoir de soutenance pour le moment.")
else: else:
if soutenance.start > soutenance.hour: site = DATAS["_running"]
avre = "%s de *retard*"%msg.just_countdown(soutenance.start - soutenance.hour, 4) return site.res_soutenance(req)
else:
avre = "%s *d'avance*"%msg.just_countdown(soutenance.hour - soutenance.start, 4)
msg.send_chn ("Actuellement à la soutenance numéro %d, commencée il y a %s avec %s."%(soutenance.rank, msg.just_countdown(datetime.now () - soutenance.start, 4), avre))
elif msg.cmd[1] == "assistants" or msg.cmd[1] == "assistant" or msg.cmd[1] == "yaka" or msg.cmd[1] == "yakas" or msg.cmd[1] == "acu" or msg.cmd[1] == "acus":
assistants = datas.findAssistants()
if len(assistants) > 0:
msg.send_chn ("Les %d assistants faisant passer les soutenances sont : %s." % (len(assistants), ', '.join(assistants.keys())))
else:
msg.send_chn ("Il ne semble pas y avoir de soutenance pour le moment.")
else:
name = msg.cmd[1]
if msg.cmd[0] == "soutenance":
soutenance = datas.findClose(name)
if soutenance is None:
global DELAYED
DELAYED[msg] = Delayed(name)
msg.srv.send_msg_prtn ("~whois %s" % name)
DELAYED[msg].wait(5)
if DELAYED[msg].res is not None:
name = DELAYED[msg].res
soutenance = datas.findClose(name)
if soutenance is None:
msg.send_chn ("Pas d'horaire de soutenance pour %s."%name)
else:
if soutenance.state == "En cours":
msg.send_chn ("%s est actuellement en soutenance avec %s. Elle était prévue à %s, position %d."%(name, soutenance.assistant, soutenance.hour, soutenance.rank))
elif soutenance.state == "Effectue":
msg.send_chn ("%s a passé sa soutenance avec %s. Elle a duré %s."%(name, soutenance.assistant, msg.just_countdown(soutenance.end - soutenance.start, 4)))
elif soutenance.state == "Retard":
msg.send_chn ("%s était en retard à sa soutenance de %s."%(name, soutenance.hour))
else:
last = datas.findLast()
if last is not None:
if soutenance.hour + (last.start - last.hour) > datetime.now ():
msg.send_chn ("Soutenance de %s : %s, position %d ; estimation du passage : dans %s."%(name, soutenance.hour, soutenance.rank, msg.just_countdown((soutenance.hour - datetime.now ()) + (last.start - last.hour))))
else:
msg.send_chn ("Soutenance de %s : %s, position %d ; passage imminent."%(name, soutenance.hour, soutenance.rank))
else:
msg.send_chn ("Soutenance de %s : %s, position %d."%(name, soutenance.hour, soutenance.rank))
elif msg.cmd[0] == "soutenances":
souts = datas.findAll(name)
if souts is None:
msg.send_snd ("Pas de soutenance prévues pour %s."%name)
else:
first = True
for s in souts:
if first:
msg.send_snd ("Soutenance(s) de %s : - %s (position %d) ;"%(name, s.hour, s.rank))
first = False
else:
msg.send_snd (" %s - %s (position %d) ;"%(len(name)*' ', s.hour, s.rank))
THREAD = None
if len(wait) > 0:
startSoutenance(wait.pop())
def getPage():
conn = http.client.HTTPConnection(CONF.getNode("server")["ip"], timeout=10)
try:
conn.request("GET", CONF.getNode("server")["url"])
res = conn.getresponse()
data = res.read()
except:
print ("[%s] impossible de récupérer la page %s."%(s, p))
return ""
conn.close()
return data