diff --git a/atom.py b/atom.py index a06f54a..4b87c50 100755 --- a/atom.py +++ b/atom.py @@ -53,7 +53,7 @@ class Atom: differ = list () for k in other.entries.keys (): if self.updated is None and k not in self.entries: - self.updated = entry.updated + self.updated = other.entries[k].updated if k not in self.entries and other.entries[k].updated >= self.updated: differ.append (other.entries[k]) return differ @@ -61,11 +61,11 @@ class Atom: if __name__ == "__main__": content1 = "" - with open("rss.php", "r") as f: + with open("rss.php.1", "r") as f: for line in f: content1 += line content2 = "" - with open("rss.php.1", "r") as f: + with open("rss.php", "r") as f: for line in f: content2 += line a = Atom (content1) diff --git a/birthday.py b/birthday.py index 2f73e2c..1a2d79d 100644 --- a/birthday.py +++ b/birthday.py @@ -77,11 +77,11 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return "!anniv /who/: gives the remaining time before the anniversary of /who/" + return "People birthdays and ages" def help_full (): - return "!anniv /who/: gives the remaining time before the anniversary of /who/\nIf /who/ is not given, gives the remaining time before your anniversary.\n\n To set yout birthday, say it to nemubot :)" + return "!anniv /who/: gives the remaining time before the anniversary of /who/\n!age /who/: gives the age of /who/\nIf /who/ is not given, gives the remaining time before your anniversary.\n\n To set yout birthday, say it to nemubot :)" def findName(msg): diff --git a/events.py b/events.py index 3d9aa91..6d96dfa 100644 --- a/events.py +++ b/events.py @@ -89,11 +89,10 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return "!events FIXME" - + return "events manager" def help_full (): - return "FIXME" + return "This module store a lot of events: ny, we, vacs, " + (", ".join(EVENTS.keys())) def parseanswer(msg): diff --git a/message.py b/message.py index a264293..d6a06fe 100644 --- a/message.py +++ b/message.py @@ -83,6 +83,106 @@ class Message: self.srv.send_msg (self.sender, msg) + + + def treat (self, mods): + if self.cmd == "PING": + self.pong () + elif self.cmd == "PRIVMSG" and self.srv.accepted_channel(self.channel): + self.parsemsg (mods) + elif self.cmd == "NICK": + print ("%s change de nom pour %s" % (self.sender, self.content)) + elif self.cmd == "PART": + print ("%s vient de quitter %s" % (self.sender, self.channel)) + elif self.cmd == "JOIN": + print ("%s arrive sur %s" % (self.sender, self.channel)) + + + def pong (self): + self.srv.s.send(("PONG %s\r\n" % self.content).encode ()) + + + def parsemsg (self, mods): + #Treat all messages starting with 'nemubot:' as distinct commands + if self.content.find("%s:"%self.srv.nick) == 0: + messagel = self.content.lower() + + #Is it a simple response? + if re.match(".*(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)", messagel) is not None: + self.send_chn ("%s: pong"%(self.sender)) + + elif re.match(".*(quel(le)? heure est[ -]il|what time is it)", messagel) is not None: + now = datetime.now() + self.send_chn ("%s: j'envoie ce message à %s:%d:%d."%(self.sender, now.hour, now.minute, now.second)) + + elif re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (.+)$", messagel) is not None: + result = re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (qu(e |'))?(.+)$", self.content) + self.send_chn ("%s: %s"%(result.group(2), result.group(5))) + elif re.match(".*di[st] (.+) (a|à) ([a-zA-Z0-9_]+)$", messagel) is not None: + result = re.match(".*di[st] (.+) (à|a) ([a-zA-Z0-9_]+)$", self.content) + self.send_chn ("%s: %s"%(result.group(3), result.group(1))) + + elif re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content) is not None: + result = re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content) + if self.srv.channels.count(result.group(1)): + self.send_msg(result.group(1), result.group(2)) + elif re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content) is not None: + result = re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content) + if self.srv.channels.count(result.group(2)): + self.send_msg(result.group(2), result.group(1)) + + #Try modules + else: + for im in mods.keys(): + if mods[im].parseask(self): + return + + #Owner commands + elif self.content[0] == '`' and self.sender == self.srv.owner: + self.cmd = self.content[1:].split(' ') + if self.cmd[0] == "reload": + if len(self.cmd) > 1: + if self.cmd[1] in mods: + mods[self.cmd[1]].save_module () + imp.reload(mods[self.cmd[1]]) + mods[self.cmd[1]].load_module (self.srv.datas_dir) + self.send_snd ("Module %s rechargé avec succès."%self.cmd[1]) + else: + self.send_snd ("Module inconnu %s."%self.cmd[1]) + else: + self.send_snd ("Usage: `reload /module/.") + self.send_snd ("Loaded modules: " + ', '.join(mods.keys()) + ".") + + #Messages stating with ! + elif self.content[0] == '!': + self.cmd = self.content[1:].split(' ') + if self.cmd[0] == "help": + if len (self.cmd) > 1: + if self.cmd[1] in mods: + self.send_snd(mods[self.cmd[1]].help_full ()) + else: + self.send_snd("No help for command %s" % self.cmd[1]) + else: + self.send_snd("Pour me demander quelque chose, commencez votre message par mon nom ; je réagis à certain messages commençant par !, consulter l'aide de chaque module :") + for im in mods.keys(): + self.send_snd(" - !help %s: %s" % (im, mods[im].help_tiny ())) + + for im in mods.keys(): + if mods[im].parseanswer(self): + return + + else: + for im in mods.keys(): + if mods[im].parselisten(self): + return + + +############################## +# # +# Extraction/Format text # +# # +############################## + def just_countdown (self, delta, resolution = 5): sec = delta.seconds hours, remainder = divmod(sec, 3600) @@ -142,6 +242,7 @@ class Message: def countdown_format (self, date, msg_before, msg_after, timezone = None): + """Replace in a text %s by a sentence incidated the remaining time before/after an event""" if timezone != None: os.environ['TZ'] = timezone time.tzset() @@ -160,95 +261,8 @@ class Message: return sentence_c % self.just_countdown(delta) - def treat (self, mods): - if self.cmd == "PING": - self.pong () - elif self.cmd == "PRIVMSG": - self.parsemsg (mods) - elif self.cmd == "NICK": - print ("%s change de nom pour %s" % (self.sender, self.content)) - elif self.cmd == "PART": - print ("%s vient de quitter %s" % (self.sender, self.channel)) - elif self.cmd == "JOIN": - print ("%s arrive sur %s" % (self.sender, self.channel)) - - - def pong (self): - self.srv.s.send(("PONG %s\r\n" % self.content).encode ()) - - - def parsemsg (self, mods): - #Treat all messages starting with 'nemubot:' as distinct commands - if self.content.find("%s:"%self.srv.nick) == 0: - messagel = self.content.lower() - - #Is it a simple response? - if re.match(".*(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)", messagel) is not None: - self.send_chn ("%s: pong"%(self.sender)) - - elif re.match(".*(quel(le)? heure est[ -]il|what time is it)", messagel) is not None: - now = datetime.now() - self.send_chn ("%s: j'envoie ce message à %s:%d:%d."%(self.sender, now.hour, now.minute, now.second)) - - elif re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (.+)$", messagel) is not None: - result = re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (qu(e |'))?(.+)$", self.content) - self.send_chn ("%s: %s"%(result.group(2), result.group(5))) - elif re.match(".*di[st] (.+) (a|à) ([a-zA-Z0-9_]+)$", messagel) is not None: - result = re.match(".*di[st] (.+) (à|a) ([a-zA-Z0-9_]+)$", self.content) - self.send_chn ("%s: %s"%(result.group(3), result.group(1))) - - elif re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content) is not None: - result = re.match(".*di[st] sur (#[a-zA-Z0-9]+) (.+)$", self.content) - if self.srv.channels.count(result.group(1)): - self.send_msg(result.group(1), result.group(2)) - elif re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content) is not None: - result = re.match(".*di[st] (.+) sur (#[a-zA-Z0-9]+)$", self.content) - if self.srv.channels.count(result.group(2)): - self.send_msg(result.group(2), result.group(1)) - - else: - for im in mods.keys(): - if mods[im].parseask(self): - return - - elif self.content[0] == '`' and self.sender == self.srv.owner: - self.cmd = self.content[1:].split(' ') - if self.cmd[0] == "reload": - if len(self.cmd) > 1: - if self.cmd[1] in mods: - mods[self.cmd[1]].save_module () - imp.reload(mods[self.cmd[1]]) - mods[self.cmd[1]].load_module (self.srv.datas_dir) - self.send_snd ("Module %s rechargé avec succès."%self.cmd[1]) - else: - self.send_snd ("Module inconnu %s."%self.cmd[1]) - else: - self.send_snd ("Usage: `reload /module/.") - self.send_snd ("Loaded modules: " + ', '.join(mods.keys()) + ".") - - elif self.content[0] == '!': - self.cmd = self.content[1:].split(' ') - if self.cmd[0] == "help": - if len (self.cmd) > 1: - if self.cmd[1] in mods: - self.send_snd(mods[self.cmd[1]].help_full ()) - else: - self.send_snd("No help for command %s" % self.cmd[1]) - else: - self.send_snd("Pour me demander quelque chose, commencez votre message par mon nom ou par l'une des commandes suivantes :") - for im in mods: - self.send_snd(" - %s" % im.help_tiny ()) - - for im in mods.keys(): - if mods[im].parseanswer(self): - return - - else: - for im in mods.keys(): - if mods[im].parselisten(self): - return - def extractDate (self): + """Parse a message to extract a time and date""" msgl = self.content.lower () result = re.match("^[^0-9]+(([0-9]{1,4})[^0-9]+([0-9]{1,2}|janvier|january|fevrier|février|february|mars|march|avril|april|mai|maï|may|juin|juni|juillet|july|jully|august|aout|août|septembre|september|october|octobre|oktober|novembre|november|decembre|décembre|december)([^0-9]+([0-9]{1,4}))?)[^0-9]+(([0-9]{1,2})[^0-9]*[h':]([^0-9]*([0-9]{1,2})([^0-9]*[m\":][^0-9]*([0-9]{1,2}))?)?)?.*$", msgl + " TXT") if result is not None: diff --git a/nemubot.py b/nemubot.py index 47c6bb8..a5a830f 100755 --- a/nemubot.py +++ b/nemubot.py @@ -10,7 +10,7 @@ from datetime import datetime from datetime import timedelta from xml.dom.minidom import parse -imports = ["birthday", "qd", "events", "youtube", "watchWebsite", "soutenance"] +imports = ["birthday", "qd", "events", "youtube", "watchWebsite", "soutenance", "whereis"] imports_launch = ["watchWebsite"] mods = {} import server diff --git a/qd.py b/qd.py index b0c67b0..00b4cb1 100644 --- a/qd.py +++ b/qd.py @@ -158,10 +158,10 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return "!42: display scores\n!42 help: display the performed calculate\n!42 manche: display information about current round\n!42 /who/: show the /who/'s scores" + return "42 game!" def help_full (): - return "Help for 42 todo" + return "!42: display scores\n!42 help: display the performed calculate\n!42 manche: display information about current round\n!42 /who/: show the /who/'s scores" def rev (tupl): diff --git a/server.py b/server.py index d3fead1..6352acd 100644 --- a/server.py +++ b/server.py @@ -28,13 +28,14 @@ class Server: self.channels.append(channel.getAttribute("name")) def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"): - for line in msg.split("\n"): - if line != "" and self.accepted_channel(channel): - self.s.send (("%s %s :%s%s" % (cmd, channel, line, endl)).encode ()) + if msg is not None and channel is not None: + for line in msg.split("\n"): + if line != "" and self.accepted_channel(channel): + self.s.send (("%s %s :%s%s" % (cmd, channel, line, endl)).encode ()) def send_global (self, msg, cmd = "PRIVMSG", endl = "\r\n"): - for channel in self.channels: - self.send_msg (channel, msg, cmd, endl) + for channel in self.channels: + self.send_msg (channel, msg, cmd, endl) def launch(self, mods, datas_dir): @@ -57,10 +58,10 @@ class Server: for line in temp: msg = message.Message (self, line) - try: - msg.treat (mods) - except: - print ("Une erreur est survenue lors du traitement du message : %s"%line) + #try: + msg.treat (mods) + #except: + #print ("Une erreur est survenue lors du traitement du message : %s"%line) def connect(self, mods): diff --git a/soutenance.py b/soutenance.py index 0f9d2ed..321eab9 100644 --- a/soutenance.py +++ b/soutenance.py @@ -7,8 +7,6 @@ from datetime import date from datetime import datetime from datetime import timedelta -stack = list() - def getPage (): conn = http.client.HTTPSConnection("intra.acu.epita.fr") conn.request("GET", "/intra/sout_liste.html") @@ -87,7 +85,7 @@ class SiteSoutenances: 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): + 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=1499)): close = s return close @@ -120,10 +118,10 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return None + return "EPITA ING1 defenses module" def help_full (): - return None + 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 diff --git a/watchWebsite.py b/watchWebsite.py index a07a5cc..a07a52d 100644 --- a/watchWebsite.py +++ b/watchWebsite.py @@ -3,7 +3,10 @@ import http.client import hashlib import sys +import traceback import time +import pickle +import base64 import _thread from urllib.parse import unquote from xml.dom.minidom import parse @@ -33,7 +36,14 @@ class Site: else: self.updateTime = 60 self.lastChange = 0 - self.lastpage = None + if len(item.childNodes) > 0 and item.childNodes[0].nodeValue is not None: + self.lastpage = pickle.loads(base64.b64decode(item.childNodes[0].nodeValue.encode())) + elif item.nodeValue is not None: + self.lastpage = pickle.loads(base64.b64decode(item.nodeValue.encode())) + else: + self.lastpage = None + print (self.server, self.lastpage) + self.run = True self.channels = list() @@ -126,8 +136,10 @@ class Site: time.sleep(self.updateTime) except: - print ("Une erreur est survenue lors de la récupération de la page " + self.server + "/" + self.page) - time.sleep(self.updateTime * 3) + 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_tb(exc_traceback) + time.sleep(self.updateTime * 3) @@ -163,6 +175,9 @@ def save_module(): if len(site.channels) > 0: for chan in site.channels: item.appendChild(parseString ('' % (chan)).documentElement); + b64 = base64.b64encode(pickle.dumps(site.lastpage)).decode() + item.appendChild(newdoc.createTextNode(b64)); + print (site.server) top.appendChild(item); with open(filename, "w") as f: @@ -172,10 +187,10 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return None + return "Alert on changes on websites" def help_full (): - return None + return "This module is autonomous you can't interract with it." def parseanswer (msg): if msg.cmd[0] == "watch": diff --git a/whereis.py b/whereis.py new file mode 100644 index 0000000..69332af --- /dev/null +++ b/whereis.py @@ -0,0 +1,146 @@ +# coding=utf-8 + +import re +import sys +import socket +import time +from datetime import datetime +from datetime import date +from datetime import timedelta +from urllib.parse import unquote +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation + +NS_SERVER = 'ns-server.epita.fr' +NS_PORT = 4242 + +class UpdatedStorage: + def __init__(self): + sock = connect_to_ns(NS_SERVER, NS_PORT) + self.users = dict() + for l in list_users(sock): + u = User(l) + self.users[u.login] = u + sock.close() + self.lastUpdate = datetime.now () + + def update(self): + if datetime.now () - self.lastUpdate < timedelta(minutes=10): + return self + else: + return None + + +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): + if self.ip.startswith('10.200'): + return 'en SM' + self.ip.split('.')[2] + elif self.ip.startswith('10.247'): + return 'en pasteur' + elif self.ip.startswith('10.248'): + return 'en srlab' + elif self.ip.startswith('10.249'): + return 'en midlab' + elif self.ip.startswith('10.250'): + return 'en cisco' + elif self.ip.startswith('10'): + return 'quelque part sur le PIE (%s)'%self.ip + else: + return "chez lui" + + @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: + return self.sm + " rangée " + self.ip.split('.')[2] + " poste " + self.ip.split('.')[3] + + def __cmp__(self, other): + return cmp(self.login, other.login) + + def __hash__(self): + return hash(self.login) + +def connect_to_ns(server, port): + s = socket.socket() + s.connect((server, port)) + s.recv(8192) # salut ... + return s + +def list_users(sock): + 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] + + +def load_module(datas_path): + """Load this module""" + return + +def save_module(): + """Save the module state""" + return + +def help_tiny (): + """Line inserted in the response to the command !help""" + return "Find a user on the PIE" + +def help_full (): + return "!whereis /who/: gives the position of /who/." + +datas = None + +def parseanswer (msg): + global datas + if msg.cmd[0] == "whereis" or msg.cmd[0] == "ouest": + if datas is not None: + datas = datas.update () + if datas is None: + datas = UpdatedStorage() + + if len(msg.cmd) >= 2: + name = msg.cmd[1] + else: + name = msg.sender + + if name in datas.users: + msg.send_chn ("%s est %s (%s)." %(name, datas.users[name].poste, unquote(datas.users[name].location))) + else: + msg.send_chn ("%s n'est pas connecté sur le PIE." % name) + + return True + elif msg.cmd[0] == "ip": + if len(msg.cmd) >= 2: + name = msg.cmd[1] + else: + name = msg.sender + + if name in datas.users: + msg.send_chn ("L'ip de %s est %s." %(name, datas.users[name].ip)) + else: + msg.send_chn ("%s n'est pas connecté à netsoul." % name) + return True + return False + +def parseask (msg): + return False + +def parselisten (msg): + return False diff --git a/youtube.py b/youtube.py index ba7acf6..2455ebb 100644 --- a/youtube.py +++ b/youtube.py @@ -16,10 +16,10 @@ def save_module(): def help_tiny (): """Line inserted in the response to the command !help""" - return + return "music extractor" def help_full (): - return + return "To launch a convertion task, juste paste a youtube link (or compatible service) and wait for nemubot answer!" def parseanswer(msg): return False