diff --git a/modules/soutenance.xml b/modules/soutenance.xml
index ed5da4d..957423b 100644
--- a/modules/soutenance.xml
+++ b/modules/soutenance.xml
@@ -1,4 +1,5 @@
-
-
\ No newline at end of file
+
+
+
diff --git a/modules/soutenance/SiteSoutenances.py b/modules/soutenance/SiteSoutenances.py
index ffbc30e..63833b7 100644
--- a/modules/soutenance/SiteSoutenances.py
+++ b/modules/soutenance/SiteSoutenances.py
@@ -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("", 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("
", line) is not None:
- save = True
- last = Soutenance()
- self.souts.append(last)
- elif save:
- result = re.match("]+>(.*) | ", 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("", line) is not None:
+ save = False
+ elif re.match("", line) is not None:
+ save = True
+ last = Soutenance()
+ self.souts.append(last)
+ elif save:
+ result = re.match("]+>(.*) | ", 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
diff --git a/modules/soutenance/__init__.py b/modules/soutenance/__init__.py
index 6ff8e10..28b981e 100644
--- a/modules/soutenance/__init__.py
+++ b/modules/soutenance/__init__.py
@@ -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 : gives the date of the next defense of /who/.\n!soutenances : 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)