Soutenance module: convert to V3.2
This commit is contained in:
parent
afcb104ed9
commit
28dee24b5a
3 changed files with 196 additions and 201 deletions
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" ?>
|
||||
<nemubotmodule name="soutenance">
|
||||
<server ip="intra.acu.epita.fr" url="/intra/sout_liste.html" />
|
||||
</nemubotmodule>
|
||||
<server ip="www.acu.epita.fr" url="/intra/sout_liste.html" />
|
||||
<message type="cmd" name="soutenance" call="ask_soutenance" />
|
||||
</nemubotmodule>
|
||||
|
|
|
|||
|
|
@ -2,87 +2,178 @@
|
|||
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
import http.client
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
|
||||
from response import Response
|
||||
|
||||
from .Soutenance import Soutenance
|
||||
|
||||
class SiteSoutenances:
|
||||
def __init__(self, page):
|
||||
save = False
|
||||
self.souts = list()
|
||||
self.updated = datetime.now()
|
||||
last = None
|
||||
for line in page.split("\n"):
|
||||
if re.match("</tr>", line) is not None:
|
||||
class SiteSoutenances(threading.Thread):
|
||||
def __init__(self, datas):
|
||||
self.souts = list()
|
||||
self.updated = datetime.now()
|
||||
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
|
||||
elif re.match("<tr.*>", line) is not None:
|
||||
save = True
|
||||
last = Soutenance()
|
||||
self.souts.append(last)
|
||||
elif save:
|
||||
result = re.match("<td[^>]+>(.*)</td>", line)
|
||||
if last.hour is None:
|
||||
try:
|
||||
last.hour = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
continue
|
||||
elif last.rank == 0:
|
||||
last.rank = int (result.group(1))
|
||||
elif last.login == None:
|
||||
last.login = result.group(1)
|
||||
elif last.state == None:
|
||||
last.state = result.group(1)
|
||||
elif last.assistant == None:
|
||||
last.assistant = result.group(1)
|
||||
elif last.start == None:
|
||||
try:
|
||||
last.start = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
last.start = None
|
||||
elif last.end == None:
|
||||
try:
|
||||
last.end = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
last.end = None
|
||||
|
||||
def update(self):
|
||||
if self.findLast() is not None and datetime.now () - self.updated > timedelta(minutes=2):
|
||||
return None
|
||||
elif datetime.now () - self.updated < timedelta(hours=1):
|
||||
return self
|
||||
else:
|
||||
return None
|
||||
for line in page.split("\n"):
|
||||
if re.match("</tr>", line) is not None:
|
||||
save = False
|
||||
elif re.match("<tr.*>", line) is not None:
|
||||
save = True
|
||||
last = Soutenance()
|
||||
self.souts.append(last)
|
||||
elif save:
|
||||
result = re.match("<td[^>]+>(.*)</td>", line)
|
||||
if last.hour is None:
|
||||
try:
|
||||
last.hour = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
continue
|
||||
elif last.rank == 0:
|
||||
last.rank = int (result.group(1))
|
||||
elif last.login == None:
|
||||
last.login = result.group(1)
|
||||
elif last.state == None:
|
||||
last.state = result.group(1)
|
||||
elif last.assistant == None:
|
||||
last.assistant = result.group(1)
|
||||
elif last.start == None:
|
||||
try:
|
||||
last.start = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
last.start = None
|
||||
elif last.end == None:
|
||||
try:
|
||||
last.end = datetime.fromtimestamp(time.mktime(time.strptime(result.group(1), "%Y-%m-%d %H:%M")))
|
||||
except ValueError:
|
||||
last.end = None
|
||||
|
||||
def findAssistants(self):
|
||||
h = {}
|
||||
for s in self.souts:
|
||||
if s.assistant is not None and s.assistant != "":
|
||||
h[s.assistant] = (s.start, s.end)
|
||||
return h
|
||||
|
||||
def gen_response(self, req, msg):
|
||||
"""Generate a text response on right server and channel"""
|
||||
return Response(req["sender"], msg, req["channel"], server=req["server"])
|
||||
|
||||
def findLast(self):
|
||||
close = None
|
||||
for s in self.souts:
|
||||
if (s.state != "En attente" and s.start is not None and (close is None or close.rank < s.rank or close.hour.day > s.hour.day)) and (close is None or s.hour - close.hour < timedelta(seconds=2499)):
|
||||
close = s
|
||||
return close
|
||||
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:
|
||||
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 findAll(self, login):
|
||||
ss = list()
|
||||
for s in self.souts:
|
||||
if s.login == login:
|
||||
ss.append(s)
|
||||
return ss
|
||||
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 findClose(self, login):
|
||||
ss = self.findAll(login)
|
||||
close = None
|
||||
for s in ss:
|
||||
if close is not None:
|
||||
print (close.hour)
|
||||
print (s.hour)
|
||||
if close is None or (close.hour < s.hour and close.hour.day >= datetime.datetime().day):
|
||||
close = s
|
||||
return close
|
||||
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):
|
||||
h = dict()
|
||||
for s in self.souts:
|
||||
if s.assistant is not None and s.assistant != "":
|
||||
h[s.assistant] = (s.start, s.end)
|
||||
return h
|
||||
|
||||
def findLast(self):
|
||||
close = None
|
||||
for s in self.souts:
|
||||
if (s.state != "En attente" and s.start is not None and (close is None or close.rank < s.rank or close.hour.day > s.hour.day)) and (close is None or s.hour - close.hour < timedelta(seconds=2499)):
|
||||
close = s
|
||||
return close
|
||||
|
||||
def findAll(self, login):
|
||||
ss = list()
|
||||
for s in self.souts:
|
||||
if s.login == login:
|
||||
ss.append(s)
|
||||
return ss
|
||||
|
||||
def findClose(self, login):
|
||||
ss = self.findAll(login)
|
||||
close = None
|
||||
for s in ss:
|
||||
if close is not None:
|
||||
print (close.hour)
|
||||
print (s.hour)
|
||||
if close is None or (close.hour < s.hour and close.hour.day >= datetime.datetime().day):
|
||||
close = s
|
||||
return close
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
# coding=utf-8
|
||||
|
||||
import http.client
|
||||
import time
|
||||
import re
|
||||
import _thread
|
||||
import threading
|
||||
from datetime import date
|
||||
from datetime import datetime
|
||||
|
||||
from module_state import ModuleState
|
||||
|
||||
from .SiteSoutenances import SiteSoutenances
|
||||
from . import SiteSoutenances
|
||||
from .Delayed import Delayed
|
||||
|
||||
nemubotversion = 3.0
|
||||
|
||||
DELAYED = dict()
|
||||
nemubotversion = 3.2
|
||||
|
||||
def help_tiny():
|
||||
"""Line inserted in the response to the command !help"""
|
||||
|
|
@ -24,123 +18,32 @@ def help_tiny():
|
|||
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/"
|
||||
|
||||
datas = None
|
||||
THREAD = None
|
||||
wait = list()
|
||||
def load(context):
|
||||
global CONF
|
||||
SiteSoutenances.CONF = CONF
|
||||
|
||||
def parseanswer(msg):
|
||||
global THREAD, wait
|
||||
if msg.cmd[0] == "soutenance" or msg.cmd[0] == "soutenances":
|
||||
if THREAD is None:
|
||||
THREAD = _thread.start_new_thread (startSoutenance, (msg,))
|
||||
def ask_soutenance(msg):
|
||||
req = ModuleState("request")
|
||||
if len(msg.cmd) > 1:
|
||||
req.setAttribute("user", msg.cmd[1])
|
||||
else:
|
||||
wait.append(msg)
|
||||
return True
|
||||
return False
|
||||
req.setAttribute("user", "next")
|
||||
req.setAttribute("server", msg.srv.id)
|
||||
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):
|
||||
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
|
||||
res = site.run()
|
||||
|
||||
for n in DATAS.getNodes("request"):
|
||||
DATAS.delChild(n)
|
||||
|
||||
def startSoutenance (msg):
|
||||
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.")
|
||||
return res
|
||||
else:
|
||||
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)
|
||||
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
|
||||
site = DATAS["_running"]
|
||||
return site.res_soutenance(req)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue