Oups, add a lot of missing files
This commit is contained in:
parent
d234d83df8
commit
061e73722f
48
modules/events/Manager.py
Normal file
48
modules/events/Manager.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import threading
|
||||||
|
|
||||||
|
newStrendEvt = threading.Event()
|
||||||
|
|
||||||
|
class Manager(threading.Thread):
|
||||||
|
def __init__(self, datas, srvs):
|
||||||
|
self.stop = False
|
||||||
|
self.DATAS = datas
|
||||||
|
self.SRVS = srvs
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
def alertEnd(self, evt):
|
||||||
|
global newStrendEvt
|
||||||
|
#Send the message on each matched servers
|
||||||
|
for server in self.SRVS.keys():
|
||||||
|
if not evt.hasAttribute("server") or server == evt["server"]:
|
||||||
|
if evt["channel"] == self.SRVS[server].nick:
|
||||||
|
self.SRVS[server].send_msg_usr(evt["proprio"], "%s: %s arrivé à échéance." % (evt["proprio"], evt["name"]))
|
||||||
|
else:
|
||||||
|
self.SRVS[server].send_msg(evt["channel"], "%s: %s arrivé à échéance." % (evt["proprio"], evt["name"]))
|
||||||
|
self.DATAS.delChild(self.DATAS.index[evt["name"]])
|
||||||
|
save()
|
||||||
|
newStrendEvt.set()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
global newStrendEvt
|
||||||
|
while not self.stop:
|
||||||
|
newStrendEvt.clear()
|
||||||
|
closer = None
|
||||||
|
#Gets the closer event
|
||||||
|
for evt in self.DATAS.index.keys():
|
||||||
|
if self.DATAS.index[evt].hasAttribute("end") and (closer is None or self.DATAS.index[evt].getDate("end") < closer.getDate("end")) and self.DATAS.index[evt].getDate("end") > datetime.now():
|
||||||
|
closer = self.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
|
31
modules/qcm/Course.py
Normal file
31
modules/qcm/Course.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
COURSES = None
|
||||||
|
|
||||||
|
class Course:
|
||||||
|
def __init__(self, iden):
|
||||||
|
global COURSES
|
||||||
|
if iden in COURSES.index:
|
||||||
|
self.node = COURSES.index[iden]
|
||||||
|
else:
|
||||||
|
self.node = { "code":"N/A", "name":"N/A", "branch":"N/A" }
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self.node["xml:id"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def code(self):
|
||||||
|
return self.node["code"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.node["name"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def branch(self):
|
||||||
|
return self.node["branch"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def validated(self):
|
||||||
|
return int(self.node["validated"]) > 0
|
93
modules/qcm/Question.py
Normal file
93
modules/qcm/Question.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import hashlib
|
||||||
|
import http.client
|
||||||
|
import socket
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
from .Course import Course
|
||||||
|
from .User import User
|
||||||
|
|
||||||
|
QUESTIONS = None
|
||||||
|
|
||||||
|
class Question:
|
||||||
|
def __init__(self, node):
|
||||||
|
self.node = node
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ident(self):
|
||||||
|
return self.node["xml:id"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self.node["xml:id"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def question(self):
|
||||||
|
return self.node["question"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def course(self):
|
||||||
|
return Course(self.node["course"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def answers(self):
|
||||||
|
return self.node.getNodes("answer")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def validator(self):
|
||||||
|
return User(self.node["validator"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def writer(self):
|
||||||
|
return User(self.node["writer"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def validated(self):
|
||||||
|
return self.node["validated"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def addedtime(self):
|
||||||
|
return datetime.fromtimestamp(float(self.node["addedtime"]))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def author(self):
|
||||||
|
return User(self.node["writer"])
|
||||||
|
|
||||||
|
def report(self, raison="Sans raison"):
|
||||||
|
conn = http.client.HTTPConnection(CONF.getNode("server")["url"])
|
||||||
|
try:
|
||||||
|
conn.request("GET", "report.php?id=" + hashlib.md5(self.id.encode()).hexdigest() + "&raison=" + quote(raison))
|
||||||
|
except socket.gaierror:
|
||||||
|
print ("[%s] impossible de récupérer la page %s."%(s, p))
|
||||||
|
return False
|
||||||
|
res = conn.getresponse()
|
||||||
|
conn.close()
|
||||||
|
return (res.status == http.client.OK)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tupleInfo(self):
|
||||||
|
return (self.author.username, self.validator.username, self.addedtime)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bestAnswer(self):
|
||||||
|
best = self.answers[0]
|
||||||
|
for answer in self.answers:
|
||||||
|
if best.getInt("score") < answer.getInt("score"):
|
||||||
|
best = answer
|
||||||
|
return best["answer"]
|
||||||
|
|
||||||
|
def isCorrect(self, msg):
|
||||||
|
msg = msg.lower().replace(" ", "")
|
||||||
|
for answer in self.answers:
|
||||||
|
if msg == answer["answer"].lower().replace(" ", ""):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getScore(self, msg):
|
||||||
|
msg = msg.lower().replace(" ", "")
|
||||||
|
for answer in self.answers:
|
||||||
|
if msg == answer["answer"].lower().replace(" ", ""):
|
||||||
|
return answer.getInt("score")
|
||||||
|
return 0
|
16
modules/qcm/QuestionFile.py
Normal file
16
modules/qcm/QuestionFile.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import module_states_file as xmlparser
|
||||||
|
|
||||||
|
from .Question import Question
|
||||||
|
|
||||||
|
class QuestionFile:
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.questions = xmlparser.parse_file(filename)
|
||||||
|
self.questions.setIndex("xml:id")
|
||||||
|
|
||||||
|
def getQuestion(self, ident):
|
||||||
|
if ident in self.questions.index:
|
||||||
|
return Question(self.questions.index[ident])
|
||||||
|
else:
|
||||||
|
return None
|
68
modules/qcm/Session.py
Normal file
68
modules/qcm/Session.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
|
SESSIONS = dict()
|
||||||
|
|
||||||
|
from . import Question
|
||||||
|
|
||||||
|
class Session:
|
||||||
|
def __init__(self, srv, chan, sender):
|
||||||
|
self.questions = list()
|
||||||
|
self.current = -1
|
||||||
|
self.score = 0
|
||||||
|
self.good = 0
|
||||||
|
self.bad = 0
|
||||||
|
self.trys = 0
|
||||||
|
self.timer = None
|
||||||
|
self.server = srv
|
||||||
|
self.channel = chan
|
||||||
|
self.sender = sender
|
||||||
|
|
||||||
|
def addQuestion(self, ident):
|
||||||
|
if ident not in self.questions:
|
||||||
|
self.questions.append(ident)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def next_question(self):
|
||||||
|
self.trys = 0
|
||||||
|
self.current += 1
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
@property
|
||||||
|
def question(self):
|
||||||
|
if self.current >= 0 and self.current < len(self.questions):
|
||||||
|
return Question.Question(Question.QUESTIONS.index[self.questions[self.current]])
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def askNext(self, bfr = ""):
|
||||||
|
global SESSIONS
|
||||||
|
self.timer = None
|
||||||
|
nextQ = self.next_question()
|
||||||
|
if nextQ is not None:
|
||||||
|
if self.channel == self.server.nick:
|
||||||
|
self.server.send_msg_final(self.sender, "%s%s" % (bfr, nextQ.question))
|
||||||
|
elif self.sender != self.channel:
|
||||||
|
self.server.send_msg_final(self.channel, "%s: %s%s" % (self.sender, bfr, nextQ.question))
|
||||||
|
else:
|
||||||
|
self.server.send_msg_final(self.channel, "%s%s" % (bfr, nextQ.question))
|
||||||
|
else:
|
||||||
|
if self.good > 1:
|
||||||
|
goodS = "s"
|
||||||
|
else:
|
||||||
|
goodS = ""
|
||||||
|
if self.channel == self.server.nick:
|
||||||
|
self.server.send_msg_final(self.sender, "%sFini, tu as donné %d bonne%s réponse%s sur %d questions." % (self.sender, bfr, self.good, goodS, goodS, len(self.questions)))
|
||||||
|
elif self.sender != self.channel:
|
||||||
|
self.server.send_msg_final(self.channel, "%s: %sFini, tu as donné %d bonne%s réponse%s sur %d questions." % (self.sender, bfr, self.good, goodS, goodS, len(self.questions)))
|
||||||
|
else:
|
||||||
|
self.server.send_msg_final(self.channel, "%sFini, vous avez donné %d bonne%s réponse%s sur %d questions." % (bfr, self.good, goodS, goodS, len(self.questions)))
|
||||||
|
del SESSIONS[self.sender]
|
||||||
|
|
||||||
|
def prepareNext(self, lag = 3):
|
||||||
|
if self.timer is None:
|
||||||
|
self.timer = threading.Timer(lag, self.askNext)
|
||||||
|
self.timer.start()
|
||||||
|
|
27
modules/qcm/User.py
Normal file
27
modules/qcm/User.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
USERS = None
|
||||||
|
|
||||||
|
class User:
|
||||||
|
def __init__(self, iden):
|
||||||
|
global USERS
|
||||||
|
if iden in USERS.index:
|
||||||
|
self.node = USERS.index[iden]
|
||||||
|
else:
|
||||||
|
self.node = { "username":"N/A", "email":"N/A" }
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self.node["xml:id"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def username(self):
|
||||||
|
return self.node["username"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def email(self):
|
||||||
|
return self.node["email"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def validated(self):
|
||||||
|
return int(self.node["validated"]) > 0
|
26
modules/qd/DelayedTuple.py
Normal file
26
modules/qd/DelayedTuple.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import re
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class DelayedTuple:
|
||||||
|
def __init__(self, regexp, great):
|
||||||
|
self.delayEvnt = threading.Event()
|
||||||
|
self.msg = None
|
||||||
|
self.regexp = regexp
|
||||||
|
self.great = great
|
||||||
|
|
||||||
|
def triche(self, res):
|
||||||
|
if res is not None:
|
||||||
|
return re.match(".*" + self.regexp + ".*", res.lower() + " ") is None
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def perfect(self, res):
|
||||||
|
if res is not None:
|
||||||
|
return re.match(".*" + self.great + ".*", res.lower() + " ") is not None
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def wait(self, timeout):
|
||||||
|
self.delayEvnt.wait(timeout)
|
59
modules/qd/GameUpdater.py
Normal file
59
modules/qd/GameUpdater.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import random
|
||||||
|
import threading
|
||||||
|
from .DelayedTuple import DelayedTuple
|
||||||
|
|
||||||
|
DELAYED = dict()
|
||||||
|
|
||||||
|
LASTQUESTION = 99999
|
||||||
|
|
||||||
|
class GameUpdater(threading.Thread):
|
||||||
|
def __init__(self, msg, bfrseen):
|
||||||
|
self.msg = msg
|
||||||
|
self.bfrseen = bfrseen
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
global DELAYED, LASTQUESTION
|
||||||
|
|
||||||
|
if self.bfrseen is not None:
|
||||||
|
seen = datetime.now() - self.bfrseen
|
||||||
|
rnd = random.randint(0, int(seen.seconds/90))
|
||||||
|
else:
|
||||||
|
rnd = 1
|
||||||
|
|
||||||
|
if rnd != 0:
|
||||||
|
QUESTIONS = CONF.getNodes("question")
|
||||||
|
|
||||||
|
if self.msg.channel == "#nemutest":
|
||||||
|
quest = 9
|
||||||
|
else:
|
||||||
|
if LASTQUESTION >= len(QUESTIONS):
|
||||||
|
random.shuffle(QUESTIONS)
|
||||||
|
LASTQUESTION = 0
|
||||||
|
quest = LASTQUESTION
|
||||||
|
LASTQUESTION += 1
|
||||||
|
|
||||||
|
question = QUESTIONS[quest]["question"]
|
||||||
|
regexp = QUESTIONS[quest]["regexp"]
|
||||||
|
great = QUESTIONS[quest]["great"]
|
||||||
|
self.msg.send_chn("%s: %s" % (self.msg.sender, question))
|
||||||
|
|
||||||
|
DELAYED[self.msg.sender] = DelayedTuple(regexp, great)
|
||||||
|
|
||||||
|
DELAYED[self.msg.sender].wait(20)
|
||||||
|
|
||||||
|
if DELAYED[self.msg.sender].triche(DELAYED[self.msg.sender].msg):
|
||||||
|
getUser(self.msg.sender).playTriche()
|
||||||
|
self.msg.send_chn("%s: Tricheur !" % self.msg.sender)
|
||||||
|
elif DELAYED[self.msg.sender].perfect(DELAYED[self.msg.sender].msg):
|
||||||
|
if random.randint(0, 10) == 1:
|
||||||
|
getUser(self.msg.sender).bonusQuestion()
|
||||||
|
self.msg.send_chn("%s: Correct !" % self.msg.sender)
|
||||||
|
else:
|
||||||
|
self.msg.send_chn("%s: J'accepte" % self.msg.sender)
|
||||||
|
del DELAYED[self.msg.sender]
|
||||||
|
SCORES.save(self.msg.sender)
|
||||||
|
save()
|
20
modules/qd/QDWrapper.py
Normal file
20
modules/qd/QDWrapper.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from wrapper import Wrapper
|
||||||
|
from .Score import Score
|
||||||
|
|
||||||
|
class QDWrapper(Wrapper):
|
||||||
|
def __init__(self, datas):
|
||||||
|
Wrapper.__init__(self)
|
||||||
|
self.DATAS = datas
|
||||||
|
self.stateName = "player"
|
||||||
|
self.attName = "name"
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
if i in self.cache:
|
||||||
|
return self.cache[i]
|
||||||
|
else:
|
||||||
|
sc = Score()
|
||||||
|
sc.parse(Wrapper.__getitem__(self, i))
|
||||||
|
self.cache[i] = sc
|
||||||
|
return sc
|
126
modules/qd/Score.py
Normal file
126
modules/qd/Score.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class Score:
|
||||||
|
"""Manage the user's scores"""
|
||||||
|
def __init__(self):
|
||||||
|
#FourtyTwo
|
||||||
|
self.ftt = 0
|
||||||
|
#TwentyThree
|
||||||
|
self.twt = 0
|
||||||
|
self.pi = 0
|
||||||
|
self.notfound = 0
|
||||||
|
self.tententen = 0
|
||||||
|
self.leet = 0
|
||||||
|
self.great = 0
|
||||||
|
self.bad = 0
|
||||||
|
self.triche = 0
|
||||||
|
self.last = None
|
||||||
|
self.changed = False
|
||||||
|
|
||||||
|
def parse(self, item):
|
||||||
|
self.ftt = item.getInt("fourtytwo")
|
||||||
|
self.twt = item.getInt("twentythree")
|
||||||
|
self.pi = item.getInt("pi")
|
||||||
|
self.notfound = item.getInt("notfound")
|
||||||
|
self.tententen = item.getInt("tententen")
|
||||||
|
self.leet = item.getInt("leet")
|
||||||
|
self.great = item.getInt("great")
|
||||||
|
self.bad = item.getInt("bad")
|
||||||
|
self.triche = item.getInt("triche")
|
||||||
|
|
||||||
|
def save(self, state):
|
||||||
|
state.setAttribute("fourtytwo", self.ftt)
|
||||||
|
state.setAttribute("twentythree", self.twt)
|
||||||
|
state.setAttribute("pi", self.pi)
|
||||||
|
state.setAttribute("notfound", self.notfound)
|
||||||
|
state.setAttribute("tententen", self.tententen)
|
||||||
|
state.setAttribute("leet", self.leet)
|
||||||
|
state.setAttribute("great", self.great)
|
||||||
|
state.setAttribute("bad", self.bad)
|
||||||
|
state.setAttribute("triche", self.triche)
|
||||||
|
|
||||||
|
def merge(self, other):
|
||||||
|
self.ftt += other.ftt
|
||||||
|
self.twt += other.twt
|
||||||
|
self.pi += other.pi
|
||||||
|
self.notfound += other.notfound
|
||||||
|
self.tententen += other.tententen
|
||||||
|
self.leet += other.leet
|
||||||
|
self.great += other.great
|
||||||
|
self.bad += other.bad
|
||||||
|
self.triche += other.triche
|
||||||
|
|
||||||
|
def newWinner(self):
|
||||||
|
self.ftt = 0
|
||||||
|
self.twt = 0
|
||||||
|
self.pi = 1
|
||||||
|
self.notfound = 1
|
||||||
|
self.tententen = 0
|
||||||
|
self.leet = 1
|
||||||
|
self.great = -1
|
||||||
|
self.bad = -4
|
||||||
|
self.triche = 0
|
||||||
|
|
||||||
|
def isWinner(self):
|
||||||
|
return self.great >= 42
|
||||||
|
|
||||||
|
def playFtt(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.ftt += 1
|
||||||
|
def playTwt(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.twt += 1
|
||||||
|
def playSuite(self):
|
||||||
|
self.canPlay()
|
||||||
|
self.twt += 1
|
||||||
|
self.great += 1
|
||||||
|
def playPi(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.pi += 1
|
||||||
|
def playNotfound(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.notfound += 1
|
||||||
|
def playTen(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.tententen += 1
|
||||||
|
def playLeet(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.leet += 1
|
||||||
|
def playGreat(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.great += 1
|
||||||
|
def playBad(self):
|
||||||
|
if self.canPlay():
|
||||||
|
self.bad += 1
|
||||||
|
self.great += 1
|
||||||
|
def playTriche(self):
|
||||||
|
self.triche += 1
|
||||||
|
def oupsTriche(self):
|
||||||
|
self.triche -= 1
|
||||||
|
def bonusQuestion(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def toTuple(self):
|
||||||
|
return (self.ftt, self.twt, self.pi, self.notfound, self.tententen, self.leet, self.great, self.bad, self.triche)
|
||||||
|
|
||||||
|
def canPlay(self):
|
||||||
|
now = datetime.now()
|
||||||
|
ret = self.last == None or self.last.minute != now.minute or self.last.hour != now.hour or self.last.day != now.day
|
||||||
|
self.changed = self.changed or ret
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def hasChanged(self):
|
||||||
|
if self.changed:
|
||||||
|
self.changed = False
|
||||||
|
self.last = datetime.now()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def score(self):
|
||||||
|
return (self.ftt * 2 + self.great * 5 + self.leet * 13.37 + (self.pi + 1) * 3.1415 * (self.notfound + 1) + self.tententen * 10 + self.twt - (self.bad + 1) * 10 * (self.triche * 5 + 1) + 7)
|
||||||
|
|
||||||
|
def details(self):
|
||||||
|
return "42: %d, 23: %d, leet: %d, pi: %d, 404: %d, 10: %d, great: %d, bad: %d, triche: %d = %d."%(self.ftt, self.twt, self.leet, self.pi, self.notfound, self.tententen, self.great, self.bad, self.triche, self.score())
|
@ -6,6 +6,7 @@ from datetime import datetime
|
|||||||
nemubotversion = 3.0
|
nemubotversion = 3.0
|
||||||
|
|
||||||
from . import GameUpdater
|
from . import GameUpdater
|
||||||
|
from .QDWrapper import QDWrapper
|
||||||
|
|
||||||
channels = "#nemutest #42sh #ykar #epitagueule"
|
channels = "#nemutest #42sh #ykar #epitagueule"
|
||||||
LASTSEEN = dict ()
|
LASTSEEN = dict ()
|
||||||
@ -210,7 +211,7 @@ def parselisten (msg):
|
|||||||
win(msg)
|
win(msg)
|
||||||
return True
|
return True
|
||||||
elif getUser(msg.sender).hasChanged():
|
elif getUser(msg.sender).hasChanged():
|
||||||
gu = GameUpdater(msg, bfrseen)
|
gu = GameUpdater.GameUpdater(msg, bfrseen)
|
||||||
gu.start()
|
gu.start()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
13
modules/soutenance/Delayed.py
Normal file
13
modules/soutenance/Delayed.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class Delayed:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.res = None
|
||||||
|
self.evt = threading.Event()
|
||||||
|
|
||||||
|
def wait(self, timeout):
|
||||||
|
self.evt.clear()
|
||||||
|
self.evt.wait(timeout)
|
88
modules/soutenance/SiteSoutenances.py
Normal file
88
modules/soutenance/SiteSoutenances.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
|
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:
|
||||||
|
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
|
||||||
|
|
||||||
|
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 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
|
11
modules/soutenance/Soutenance.py
Normal file
11
modules/soutenance/Soutenance.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
class Soutenance:
|
||||||
|
def __init__(self):
|
||||||
|
self.hour = None
|
||||||
|
self.rank = 0
|
||||||
|
self.login = None
|
||||||
|
self.state = None
|
||||||
|
self.assistant = None
|
||||||
|
self.start = None
|
||||||
|
self.end = None
|
130
modules/watchWebsite/Site.py
Normal file
130
modules/watchWebsite/Site.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
import http.client
|
||||||
|
import hashlib
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
|
from .atom import Atom
|
||||||
|
|
||||||
|
class Site:
|
||||||
|
def __init__(self, item):
|
||||||
|
self.server = item.getAttribute("server")
|
||||||
|
self.page = item.getAttribute("page")
|
||||||
|
if len(self.page) <= 0 or self.page[0] != "/":
|
||||||
|
self.page = "/" + self.page
|
||||||
|
if item.hasAttribute("type"):
|
||||||
|
self.type = item.getAttribute("type")
|
||||||
|
else:
|
||||||
|
self.type = "hash"
|
||||||
|
self.message = item.getAttribute("message")
|
||||||
|
|
||||||
|
if item.hasAttribute("time"):
|
||||||
|
self.updateTime = item.getInt("time")
|
||||||
|
else:
|
||||||
|
self.updateTime = 60
|
||||||
|
self.lastChange = datetime.now()
|
||||||
|
self.lastpage = None
|
||||||
|
|
||||||
|
self.channels = list()
|
||||||
|
for channel in item.getNodes('channel'):
|
||||||
|
self.channels.append(channel.getAttribute("name"))
|
||||||
|
|
||||||
|
self.categories = dict()
|
||||||
|
for category in item.getNodes('category'):
|
||||||
|
self.categories[category.getAttribute("term")] = category.getAttribute("part")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update(self):
|
||||||
|
if self.lastpage is None:
|
||||||
|
return self.lastChange
|
||||||
|
else:
|
||||||
|
return self.lastChange + timedelta(seconds=self.updateTime)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url(self):
|
||||||
|
return self.server + self.page
|
||||||
|
|
||||||
|
def send_message (self, msg):
|
||||||
|
global SRVS
|
||||||
|
if len(self.channels) > 0:
|
||||||
|
for server in SRVS.keys():
|
||||||
|
for chan in self.channels:
|
||||||
|
SRVS[server].send_msg (chan, msg)
|
||||||
|
else:
|
||||||
|
for server in SRVS.keys():
|
||||||
|
SRVS[server].send_global (msg)
|
||||||
|
|
||||||
|
def treat_atom (self, content):
|
||||||
|
change=False
|
||||||
|
f = Atom(content)
|
||||||
|
if self.lastpage is not None:
|
||||||
|
diff = self.lastpage.diff (f)
|
||||||
|
if len(diff) > 0:
|
||||||
|
print ("[%s] Page differ!"%self.server)
|
||||||
|
diff.reverse()
|
||||||
|
for d in diff:
|
||||||
|
if self.message.count("%s") == 2 and len(self.categories) > 0:
|
||||||
|
if d.category is None or d.category not in self.categories:
|
||||||
|
messageI = self.message % (self.categories[""], "%s")
|
||||||
|
else:
|
||||||
|
messageI = self.message % (self.categories[d.category], "%s")
|
||||||
|
self.send_message (messageI % unquote (d.link))
|
||||||
|
elif self.message.count("%s") == 2:
|
||||||
|
if f.id == youtube.idAtom:
|
||||||
|
youtube.send_global (d.link2, self.message % (d.title, unquote (d.link)))
|
||||||
|
else:
|
||||||
|
self.send_message (self.message % (d.title, unquote (d.link)))
|
||||||
|
elif self.message.count("%s") == 1:
|
||||||
|
self.send_message(self.message % unquote (d.title))
|
||||||
|
else:
|
||||||
|
self.send_message(self.message)
|
||||||
|
change=True
|
||||||
|
return (f, change)
|
||||||
|
|
||||||
|
def check (self):
|
||||||
|
try:
|
||||||
|
#print ("Check %s"%(self.url))
|
||||||
|
(status, content) = getPage(self.server, self.page)
|
||||||
|
if content is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.type == "atom":
|
||||||
|
(self.lastpage, change) = self.treat_atom(content)
|
||||||
|
else:
|
||||||
|
hash = hashlib.sha224(content).hexdigest()
|
||||||
|
if hash != self.lastpage:
|
||||||
|
if self.lastpage is not None:
|
||||||
|
self.send_message (self.message)
|
||||||
|
self.lastpage = hash
|
||||||
|
|
||||||
|
self.lastChange = datetime.now()
|
||||||
|
|
||||||
|
# if self.updateTime < 10:
|
||||||
|
# self.updateTime = 10
|
||||||
|
# if self.updateTime > 400:
|
||||||
|
# self.updateTime = 400
|
||||||
|
except:
|
||||||
|
print ("Une erreur est survenue lors de la récupération de la page " + self.server + "/" + self.page)
|
||||||
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
|
traceback.print_exception(exc_type, exc_value, exc_traceback)
|
||||||
|
self.updateTime *= 2
|
||||||
|
|
||||||
|
|
||||||
|
def getPage(s, p):
|
||||||
|
conn = http.client.HTTPConnection(s)
|
||||||
|
try:
|
||||||
|
conn.request("GET", p)
|
||||||
|
|
||||||
|
res = conn.getresponse()
|
||||||
|
data = res.read()
|
||||||
|
except:
|
||||||
|
print ("[%s] impossible de récupérer la page %s."%(s, p))
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
return (res.status, data)
|
46
modules/watchWebsite/Watcher.py
Normal file
46
modules/watchWebsite/Watcher.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class Watcher(threading.Thread):
|
||||||
|
def __init__(self):
|
||||||
|
self.servers = list()
|
||||||
|
self.stop = False
|
||||||
|
self.newSrv = threading.Event()
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
def addServer(self, server):
|
||||||
|
self.servers.append(server)
|
||||||
|
self.newSrv.set()
|
||||||
|
|
||||||
|
def check(self, closer):
|
||||||
|
closer.check()
|
||||||
|
self.newSrv.set()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while not self.stop:
|
||||||
|
self.newSrv.clear()
|
||||||
|
closer = None
|
||||||
|
#Gets the closer server update
|
||||||
|
for server in self.servers:
|
||||||
|
if server.update < datetime.now():
|
||||||
|
#print ("Closer now: %s à %s"%(server.url, server.update))
|
||||||
|
self.check(server)
|
||||||
|
elif closer is None or server.update < closer.update:
|
||||||
|
closer = server
|
||||||
|
if closer is not None:
|
||||||
|
#print ("Closer: %s à %s"%(closer.url, closer.update))
|
||||||
|
timeleft = (closer.update - datetime.now()).seconds
|
||||||
|
timer = threading.Timer(timeleft, self.check, (closer,))
|
||||||
|
timer.start()
|
||||||
|
#print ("Start timer (%ds)"%timeleft)
|
||||||
|
|
||||||
|
self.newSrv.wait()
|
||||||
|
|
||||||
|
if closer is not None and closer.update is not None and closer.update > datetime.now():
|
||||||
|
timer.cancel()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stop = True
|
||||||
|
self.newSrv.set()
|
5
modules/whereis/Delayed.py
Normal file
5
modules/whereis/Delayed.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
class Delayed:
|
||||||
|
def __init__(self):
|
||||||
|
self.names = dict()
|
57
modules/whereis/UpdatedStorage.py
Normal file
57
modules/whereis/UpdatedStorage.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import socket
|
||||||
|
from datetime import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from .User import User
|
||||||
|
|
||||||
|
class UpdatedStorage:
|
||||||
|
def __init__(self, url, port):
|
||||||
|
sock = connect_to_ns(url, port)
|
||||||
|
self.users = dict()
|
||||||
|
if sock != None:
|
||||||
|
users = list_users(sock)
|
||||||
|
if users is not None:
|
||||||
|
for l in users:
|
||||||
|
u = User(l)
|
||||||
|
if u.login not in self.users:
|
||||||
|
self.users[u.login] = list()
|
||||||
|
self.users[u.login].append(u)
|
||||||
|
self.lastUpdate = datetime.now ()
|
||||||
|
else:
|
||||||
|
self.users = None
|
||||||
|
sock.close()
|
||||||
|
else:
|
||||||
|
self.users = None
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if datetime.now () - self.lastUpdate < timedelta(minutes=10):
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def connect_to_ns(server, port):
|
||||||
|
try:
|
||||||
|
s = socket.socket()
|
||||||
|
s.settimeout(3)
|
||||||
|
s.connect((server, port))
|
||||||
|
except socket.error:
|
||||||
|
return None
|
||||||
|
s.recv(8192)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def list_users(sock):
|
||||||
|
try:
|
||||||
|
sock.send('list_users\n'.encode())
|
||||||
|
buf = ''
|
||||||
|
while True:
|
||||||
|
tmp = sock.recv(8192).decode()
|
||||||
|
buf += tmp
|
||||||
|
if '\nrep 002' in tmp or tmp == '':
|
||||||
|
break
|
||||||
|
return buf.split('\n')[:-2]
|
||||||
|
except socket.error:
|
||||||
|
return None
|
35
modules/whereis/User.py
Normal file
35
modules/whereis/User.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
class User(object):
|
||||||
|
def __init__(self, line):
|
||||||
|
fields = line.split()
|
||||||
|
self.login = fields[1]
|
||||||
|
self.ip = fields[2]
|
||||||
|
self.location = fields[8]
|
||||||
|
self.promo = fields[9]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sm(self):
|
||||||
|
for sm in CONF.getNodes("sm"):
|
||||||
|
if self.ip.startswith(sm["ip"]):
|
||||||
|
return sm["name"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def poste(self):
|
||||||
|
if self.sm is None:
|
||||||
|
if self.ip.startswith('10.'):
|
||||||
|
return 'quelque part sur le PIE (%s)'%self.ip
|
||||||
|
else:
|
||||||
|
return "chez lui"
|
||||||
|
else:
|
||||||
|
if self.ip.startswith('10.247') or self.ip.startswith('10.248') or self.ip.startswith('10.249') or self.ip.startswith('10.250'):
|
||||||
|
return "en " + self.sm + " rangée " + self.ip.split('.')[2] + " poste " + self.ip.split('.')[3]
|
||||||
|
else:
|
||||||
|
return "en " + self.sm
|
||||||
|
|
||||||
|
def __cmp__(self, other):
|
||||||
|
return cmp(self.login, other.login)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.login)
|
35
modules/ycc/Tinyfier.py
Normal file
35
modules/ycc/Tinyfier.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class Tinyfier(threading.Thread):
|
||||||
|
def __init__(self, url, msg):
|
||||||
|
self.url = url
|
||||||
|
self.msg = msg
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
(status, page) = getPage("ycc.fr", "/redirection/create/" + self.url)
|
||||||
|
if status == http.client.OK and len(page) < 100:
|
||||||
|
srv = re.match(".*((ht|f)tps?://|www.)([^/ ]+).*", self.url)
|
||||||
|
if srv is None:
|
||||||
|
self.msg.send_chn("Mauvaise URL : %s" % (self.url))
|
||||||
|
else:
|
||||||
|
self.msg.send_chn("URL pour %s : %s" % (srv.group(3), page.decode()))
|
||||||
|
else:
|
||||||
|
print ("ERROR: ycc.fr seem down?")
|
||||||
|
self.msg.send_chn("La situation est embarassante, il semblerait que YCC soit down :(")
|
||||||
|
|
||||||
|
def getPage(s, p):
|
||||||
|
conn = http.client.HTTPConnection(s)
|
||||||
|
try:
|
||||||
|
conn.request("GET", p)
|
||||||
|
except socket.gaierror:
|
||||||
|
print ("[%s] impossible de récupérer la page %s."%(s, p))
|
||||||
|
return None
|
||||||
|
|
||||||
|
res = conn.getresponse()
|
||||||
|
data = res.read()
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
return (res.status, data)
|
@ -99,7 +99,7 @@ def mod_save(mod, datas_path):
|
|||||||
|
|
||||||
def mod_has_access(mod, config, msg):
|
def mod_has_access(mod, config, msg):
|
||||||
if config is not None and config.hasNode("channel"):
|
if config is not None and config.hasNode("channel"):
|
||||||
for chan in config.getChilds("channel"):
|
for chan in config.getNodes("channel"):
|
||||||
if (chan["server"] is None or chan["server"] == msg.srv.id) and (chan["channel"] is None or chan["channel"] == msg.channel):
|
if (chan["server"] is None or chan["server"] == msg.srv.id) and (chan["channel"] is None or chan["channel"] == msg.channel):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
Loading…
Reference in New Issue
Block a user