diff --git a/atom.py b/atom.py new file mode 100755 index 0000000..ebbdccd --- /dev/null +++ b/atom.py @@ -0,0 +1,53 @@ +#!/usr/bin/python3 +# coding=utf-8 + +import time +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation + +class AtomEntry: + def __init__ (self, node): + self.id = node.getElementsByTagName("id")[0].firstChild.nodeValue + self.title = node.getElementsByTagName("title")[0].firstChild.nodeValue + self.updated = time.strptime(node.getElementsByTagName("updated")[0].firstChild.nodeValue[:19], "%Y-%m-%dT%H:%M:%S") + self.summary = node.getElementsByTagName("summary")[0].firstChild.nodeValue + self.link = node.getElementsByTagName("link")[0].getAttribute ("href") + +class Atom: + def __init__ (self, string): + self.feed = parseString (string).documentElement + self.id = self.feed.getElementsByTagName("id")[0].firstChild.nodeValue + self.title = self.feed.getElementsByTagName("title")[0].firstChild.nodeValue + + self.updated = None + self.entries = dict () + for item in self.feed.getElementsByTagName("entry"): + entry = AtomEntry (item) + self.entries[entry.id] = entry + if self.updated is None or self.updated < entry.updated: + self.updated = entry.updated + + def diff (self, other): + differ = list () + for k in other.entries.keys (): + if k not in self.entries and other.entries[k].updated >= self.updated: + differ.append (other.entries[k]) + return differ + + +if __name__ == "__main__": + content1 = "" + with open("rss.php", "r") as f: + for line in f: + content1 += line + content2 = "" + with open("rss.php.1", "r") as f: + for line in f: + content2 += line + a = Atom (content1) + print (a.updated) + b = Atom (content2) + print (b.updated) + + diff = a.diff (b) diff --git a/birthday.py b/birthday.py index f44d97f..926c896 100644 --- a/birthday.py +++ b/birthday.py @@ -1,12 +1,18 @@ # coding=utf-8 -import counter +import re from datetime import datetime +from datetime import date +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation -BIRTHDAYS = list() +filename = "" +BIRTHDAYS = {} def xmlparse(node): - for item in node.getElementsByTagName("item"): + """Parse the given node and add birthdays to the global list.""" + for item in node.getElementsByTagName("birthday"): if (item.hasAttribute("year")): year = int(item.getAttribute("year")) else: @@ -29,102 +35,101 @@ def xmlparse(node): minute = 0 second = 1 - BIRTHDAYS.append((item.getAttribute("name"), datetime(year, month, day, hour, minute, second))) + BIRTHDAYS[item.getAttribute("name")] = datetime(year, month, day, hour, minute, second) -def xmlsave(doc): - top = doc.createTextNode("birthday") - for brth in BIRTHDAYS: - item = doc.createTextNode("item") - item.setAttribute("", "") + +def load_module(datas_path): + """Load this module""" + global BIRTHDAYS, filename + BIRTHDAYS = {} + filename = datas_path + "/birthdays.xml" + + print ("Loading birthdays ...",) + dom = parse(filename) + xmlparse (dom.getElementsByTagName('birthdays')[0]) + print ("done (%d loaded)" % len(BIRTHDAYS)) + + +def save_module(): + """Save the dates""" + global filename + print ("Saving birthdays ...",) + + impl = getDOMImplementation() + newdoc = impl.createDocument(None, 'birthdays', None) + top = newdoc.documentElement + + for name in BIRTHDAYS.keys(): + day = BIRTHDAYS[name] + bonus="" + if day.hour != 0: + bonus += 'hour="%s" ' % day.hour + if day.minute != 0: + bonus += 'minute="%s" ' % day.minute + item = parseString ('' % (name, day.year, day.month, day.day, bonus)).documentElement top.appendChild(item); - -def parseanswer(s, channel, sender, cmd): - if len(cmd) < 2 or cmd[1].lower() == "moi": - name = sender.lower() - else: - name = cmd[1].lower() - matches = [] + with open(filename, "w") as f: + newdoc.writexml (f) + print ("done") - if name in birthdays: - matches.append(name) - else: - for k in birthdays.keys(): - if k.find(name) == 0: - matches.append(k) - if len(matches) == 1: - (n, d) = (matches[0], birthdays[matches[0]]) - tyd = d - tyd = datetime(date.today().year, tyd.month, tyd.day) +def help_tiny (): + """Line inserted in the response to the command !help""" + return "!anniv /who/: gives the remaining time before the anniversary of /who/" - if tyd.day == datetime.today().day and tyd.month == datetime.today().month: - newyear.launch (s, info[2], d, ["", "C'est aujourd'hui l'anniversaire de %s ! Il a%s. Joyeux anniversaire :)" % (n, "%s")], cmd) + +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 :)" + + +def parseanswer(msg): + if msg.cmd[0] == "anniv": + if len(msg.cmd) < 2 or msg.cmd[1].lower() == "moi" or msg.cmd[1].lower() == "me": + name = msg.sender.lower() else: - if tyd < datetime.today(): - tyd = datetime(date.today().year + 1, tyd.month, tyd.day) + name = msg.cmd[1].lower() - newyear.launch (s, info[2], tyd, ["Il reste%s avant l'anniversaire de %s !" % ("%s", n), ""], cmd) - else: - s.send("PRIVMSG %s :%s: désolé, je ne connais pas la date d'anniversaire de %s. Quand est-il né ?\r\n"%(info[2], sender[0], name)) + matches = [] - -def parseask(s, channel, sender, msgl): - if re.match(".*(date de naissance|birthday|geburtstag|née?|nee? le|born on).*", msgl) is not None: - 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|obtobre|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}))?.*", msgl) - if result is None: - s.send("PRIVMSG %s :%s: je ne reconnais pas le format de ta date de naissance :(\r\n"%(channel, sender)) + if name in BIRTHDAYS: + matches.append(name) else: - day = result.group(2) - if len(day) == 4: - year = day - day = 0 - month = result.group(3) - if month == "janvier" or month == "january" or month == "januar": - month = 1 - elif month == "fevrier" or month == "février" or month == "february": - month = 2 - elif month == "mars" or month == "march": - month = 3 - elif month == "avril" or month == "april": - month = 4 - elif month == "mai" or month == "may" or month == "maï": - month = 5 - elif month == "juin" or month == "juni" or month == "junni": - month = 6 - elif month == "juillet" or month == "jully" or month == "july": - month = 7 - elif month == "aout" or month == "août" or month == "august": - month = 8 - elif month == "september" or month == "septembre": - month = 9 - elif month == "october" or month == "october" or month == "oktober": - month = 10 - elif month == "november" or month == "novembre": - month = 11 - elif month == "december" or month == "decembre" or month == "décembre": - month = 12 - if day == 0: - day = result.group(5) - else: - year = result.group(5) + for k in BIRTHDAYS.keys (): + if k.find (name) == 0: + matches.append (k) - hour = result.group(7) - minute = result.group(8) + if len(matches) == 1: + (n, d) = (matches[0], BIRTHDAYS[matches[0]]) + tyd = d + tyd = datetime(date.today().year, tyd.month, tyd.day) - print "Chaîne reconnue : %s/%s/%s %s:%s"%(day, month, year, hour, minute) - if year == None: - year = date.today().year - if hour == None: - hour = 0 - if minute == None: - minute = 0 + if tyd.day == datetime.today().day and tyd.month == datetime.today().month: + msg.send_chn (msg.countdown_format (d, "", "C'est aujourd'hui l'anniversaire de %s ! Il a%s. Joyeux anniversaire :)" % (n, "%s"))) + else: + if tyd < datetime.today(): + tyd = datetime(date.today().year + 1, tyd.month, tyd.day) - try: - newdate = datetime(int(year), int(month), int(day), int(hour), int(minute)) - birthdays[sender[0].lower()] = newdate - s.send("PRIVMSG %s :%s: ok, c'est noté, ta date de naissance est le %s\r\n"%(channel, sender, newdate.strftime("%A %d %B %Y à %H:%M"))) - except ValueError: - s.send("PRIVMSG %s :%s: ta date de naissance me paraît peu probable...\r\n"%(channel, sender)) + msg.send_chn (msg.countdown_format (tyd, "Il reste%s avant l'anniversaire de %s !" % ("%s", n), "")) + else: + msg.send_chn ("%s: désolé, je ne connais pas la date d'anniversaire de %s. Quand est-il né ?"%(msg.sender, name)) + return True + else: + return False + + +def parseask(msg): + msgl = msg.content.lower () + if re.match("^.*(date de naissance|birthday|geburtstag|née?|nee? le|born on).*$", msgl) is not None: + extDate = msg.extractDate () + if extDate is None: + msg.send_chn ("%s: ta date de naissance ne paraît pas valide..." % (msg.sender)) + else: + BIRTHDAYS[msg.sender.lower()] = extDate + msg.send_chn ("%s: ok, c'est noté, ta date de naissance est le %s" % (msg.sender, extDate.strftime("%A %d %B %Y à %H:%M"))) + save_module () return True return False + +def parselisten (msg): + return False diff --git a/events.py b/events.py new file mode 100644 index 0000000..850ea7e --- /dev/null +++ b/events.py @@ -0,0 +1,167 @@ +# coding=utf-8 + +import re +from datetime import timedelta +from datetime import datetime +from datetime import date +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation + +filename = "" +EVENTS = {} + +def xmlparse(node): + """Parse the given node and add events to the global list.""" + for item in node.getElementsByTagName("event"): + if (item.hasAttribute("year")): + year = int(item.getAttribute("year")) + else: + year = 0 + if (item.hasAttribute("month")): + month = int(item.getAttribute("month")) + else: + month = 0 + if (item.hasAttribute("day")): + day = int(item.getAttribute("day")) + else: + day = 0 + if (item.hasAttribute("hour")): + hour = int(item.getAttribute("hour")) + else: + hour = 0 + if (item.hasAttribute("minute")): + minute = int(item.getAttribute("minute")) + else: + minute = 0 + if (item.hasAttribute("second")): + second = int(item.getAttribute("second")) + else: + second = 0 + + if year == month == day == hour == minute == second == 0: + EVENTS[item.getAttribute("name")] = (None, item.getAttribute("before_after"), None) + else: + EVENTS[item.getAttribute("name")] = (datetime(year, month, day, hour, minute, second),item.getAttribute("msg_before"), item.getAttribute("msg_after")) + + +def load_module(datas_path): + """Load this module""" + global EVENTS, filename + EVENTS = {} + filename = datas_path + "/events.xml" + + print ("Loading events ...",) + dom = parse(filename) + xmlparse (dom.getElementsByTagName('events')[0]) + print ("done (%d loaded)" % len(EVENTS)) + + +def save_module(): + """Save the dates""" + global filename + print ("Saving events ...",) + + impl = getDOMImplementation() + newdoc = impl.createDocument(None, 'events', None) + top = newdoc.documentElement + + for name in EVENTS.keys(): + (day, msg_before, msg_after) = EVENTS[name] + bonus="" + if day is None: + item = parseString ('' % (name, msg_before)).documentElement + else: + if day.hour != 0: + bonus += 'hour="%s" ' % day.hour + if day.minute != 0: + bonus += 'minute="%s" ' % day.minute + if day.second != 1: + bonus += 'second="%s" ' % day.second + item = parseString ('' % (name, day.year, day.month, day.day, bonus, msg_after, msg_before)).documentElement + top.appendChild(item); + + with open(filename, "w") as f: + newdoc.writexml (f) + print ("done") + + +def help_tiny (): + """Line inserted in the response to the command !help""" + return "!events FIXME" + + +def help_full (): + return "FIXME" + + +def parseanswer(msg): + if msg.cmd[0] == "we" or msg.cmd[0] == "week-end" or msg.cmd[0] == "weekend": + ndate = datetime.today() + timedelta(5 - datetime.today().weekday()) + ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) + msg.send_chn ( + msg.countdown_format (ndate, + "Il reste %s avant le week-end, courrage ;)", + "Youhou, on est en week-end depuis %s.")) + return True + elif msg.cmd[0] == "new-year" or msg.cmd[0] == "newyear" or msg.cmd[0] == "ny": + msg.send_chn ( + msg.countdown_format (datetime(datetime.today().year + 1, 1, 1, 0, 0, 1), + "Il reste %s avant la nouvelle année.", + "Nous faisons déjà la fête depuis %s !")) + return True + elif msg.cmd[0] == "vacances" or msg.cmd[0] == "vacs" or msg.cmd[0] == "holiday" or msg.cmd[0] == "holidays": + msg.send_chn ( + msg.countdown_format (datetime(2012, 7, 30, 18, 0, 1), + "Il reste %s avant les vacances :)", + "Profitons, c'est les vacances depuis %s.")) + return True + elif msg.cmd[0] in EVENTS: + (day, msg_before, msg_after) = EVENTS[msg.cmd[0]] + if day is None: + msg.send_chn (msg_before) + else: + msg.send_chn (msg.countdown_format (day, msg_before, msg_after)) + return True + else: + return False + + +def parseask(msg): + msgl = msg.content.lower () + if re.match("^.*((create|new) +(a|an|a +new|an *other)? *(events?|commande?)|(nouvel(le)?|ajoute|cr[ée]{1,3}) +(un)? *([eé]v[ée]nements?|commande?)).*$", msgl) is not None: + name = re.match("^.*!([^ \"'@!]+).*$", msg.content) + if name is not None and name.group (1) not in EVENTS: + texts = re.match("^[^\"]*(avant|après|apres|before|after)?[^\"]*\"([^\"]+)\"[^\"]*((avant|après|apres|before|after)?.*\"([^\"]+)\".*)?$", msg.content) + if texts is not None and texts.group (3) is not None: + extDate = msg.extractDate () + if extDate is None or extDate == "": + msg.send_snd ("La date de l'événement est invalide...") + else: + if texts.group (1) is not None and (texts.group (1) == "après" or texts.group (1) == "apres" or texts.group (1) == "after"): + msg_after = texts.group (2) + msg_before = texts.group (5) + if (texts.group (4) is not None and (texts.group (4) == "après" or texts.group (4) == "apres" or texts.group (4) == "after")) or texts.group (1) is None: + msg_before = texts.group (2) + msg_after = texts.group (5) + + if msg_before.find ("%s") != -1 and msg_after.find ("%s") != -1: + EVENTS[name.group (1)] = (extDate, msg_before, msg_after) + save_module () + msg.send_snd ("Nouvel événement !%s ajouté avec succès."%name.group (1)) + else: + msg.send_snd ("Pour que l'événement soit valide, ajouter %s à l'endroit où vous voulez que soit ajouté le compte à rebours.") + elif texts is not None and texts.group (2) is not None: + EVENTS[name.group (1)] = (None, texts.group (2), None) + save_module () + msg.send_snd ("Nouvelle commande !%s ajoutée avec succès."%name.group (1)) + else: + msg.send_snd ("Veuillez indiquez les messages d'attente et d'après événement entre guillemets.") + elif name is None: + msg.send_snd ("Veuillez attribuer une commande à l'événement.") + else: + msg.send_snd ("Un événement portant ce nom existe déjà.") + return False + +def parselisten (msg): + return False diff --git a/message.py b/message.py new file mode 100755 index 0000000..b233f66 --- /dev/null +++ b/message.py @@ -0,0 +1,271 @@ +#!/usr/bin/python2.7 +# coding=utf-8 + +from datetime import datetime +import re +import socket +import string +import time + +class Message: + def __init__ (self, srv, line): + self.srv = srv + self.time = datetime.now () + line = line.rstrip() #remove trailing 'rn' + + if line.find(' PRIVMSG ') != -1: #Call a parsing function + complete = line[1:].split(':',1) #Parse the message into useful data + info = complete[0].split(' ') + + self.cmd = "PRIVMSG" + self.sender = (info[0].split('!'))[0] + self.channel = info[2] + self.content = complete[1] + + elif line.find(' NICK ') != -1: + complete = line[1:].split(':',1) #Parse the message into useful data + if len(complete) > 1: + info = complete[0].split(' ') + + self.cmd = "NICK" + self.sender = (info[0].split('!'))[0] + self.content = complete[1] + else: + self.cmd = "NONE" + + elif line.find(' JOIN ') != -1: + complete = line[1:].split(':',1) #Parse the message into useful data + if len(complete) > 1: + info = complete[0].split(' ') + + self.cmd = "JOIN" + self.sender = (info[0].split('!'))[0] + self.channel = complete[1] + else: + self.cmd = "NONE" + + elif line.find(' PART ') != -1: + complete = line[1:].split(':',1) #Parse the message into useful data + info = complete[0].split(' ') + + self.cmd = "PART" + self.sender = (info[0].split('!'))[0] + self.channel = info[2] + if len (complete) > 1: + self.content = complete[1] + else: + self.content = "" + + elif line.find(' PING ') != -1: #If server pings then pong + line = line.split() + + self.cmd = "PING" + self.content = line[1] + + else: + self.cmd = "UNKNOWN" + print (line) + + + def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"): + self.srv.send_msg (channel, msg, cmd, endl) + + def send_global (self, msg, cmd = "PRIVMSG", endl = "\r\n"): + self.srv.send_global (msg, cmd, endl) + + def send_chn (self, msg): + """Send msg on the same channel as receive message""" + self.srv.send_msg (self.channel, msg) + + def send_snd (self, msg): + """Send msg to the sender who send the original message""" + self.srv.send_msg (self.sender, msg) + + + def countdown_format (self, date, msg_before, msg_after, timezone = None): + if timezone != None: + os.environ['TZ'] = timezone + time.tzset() + + #Calculate time before the date + if datetime.now() > date: + sentence_c = msg_after + delta = datetime.now() - date + else: + sentence_c = msg_before + delta = date - datetime.now() + + sec = delta.seconds + hours, remainder = divmod(sec, 3600) + minutes, seconds = divmod(remainder, 60) + + sentence = "" + force = 0 + + if force or delta.days > 0: + force = 1 + sentence += " %i jour"%(delta.days) + + if delta.days > 1: + sentence += "s" + sentence += "," + + if force or hours > 0: + force = 1 + sentence += " %i heure"%(hours) + if hours > 1: + sentence += "s" + sentence += "," + + if force or minutes > 0: + force = 1 + sentence += " %i minute"%(minutes) + if minutes > 1: + sentence += "s" + sentence += " et" + + if force or seconds > 0: + force = 1 + sentence += " %i seconde"%(seconds) + if seconds > 1: + sentence += "s" + + return sentence_c % sentence[1:] + + if timezone != None: + os.environ['TZ'] = "Europe/Paris" + + + 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): + if re.match(".*(norme|coding style).*", self.content) is not None and re.match(".*(please|give|obtenir|now|plz|stp|svp|s'il (te|vous) pla.t|check).*", self.content) is not None: + norme.launch (self.srv.s, self.sender, self.content) + + #Treat all messages starting with 'nemubot:' as distinct commands + elif 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(".*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 imp in mods: + if imp.parseask(self): + return + + 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 imp in mods: + self.send_snd(" - %s" % imp.help_tiny ()) + + for imp in mods: + if imp.parseanswer(self): + return + + else: + for imp in mods: + if imp.parselisten(self): + return + + def extractDate (self): + 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: + day = result.group(2) + if len(day) == 4: + year = day + day = 0 + month = result.group(3) + if month == "janvier" or month == "january" or month == "januar": + month = 1 + elif month == "fevrier" or month == "février" or month == "february": + month = 2 + elif month == "mars" or month == "march": + month = 3 + elif month == "avril" or month == "april": + month = 4 + elif month == "mai" or month == "may" or month == "maï": + month = 5 + elif month == "juin" or month == "juni" or month == "junni": + month = 6 + elif month == "juillet" or month == "jully" or month == "july": + month = 7 + elif month == "aout" or month == "août" or month == "august": + month = 8 + elif month == "september" or month == "septembre": + month = 9 + elif month == "october" or month == "october" or month == "oktober": + month = 10 + elif month == "november" or month == "novembre": + month = 11 + elif month == "december" or month == "decembre" or month == "décembre": + month = 12 + + if day == 0: + day = result.group(5) + else: + year = result.group(5) + + hour = result.group(7) + minute = result.group(9) + second = result.group(11) + + print ("Chaîne reconnue : %s/%s/%s %s:%s:%s"%(day, month, year, hour, minute, second)) + if year == None: + year = date.today().year + if hour == None: + hour = 0 + if minute == None: + minute = 0 + if second == None: + second = 1 + else: + second = int (second) + 1 + if second > 59: + minute = int (minute) + 1 + second = 0 + + return datetime(int(year), int(month), int(day), int(hour), int(minute), int(second)) + else: + return None diff --git a/nemubot.py b/nemubot.py index aa3c47b..dc60dd6 100755 --- a/nemubot.py +++ b/nemubot.py @@ -1,113 +1,55 @@ -#!/usr/bin/python2.7 +#!/usr/bin/python3 # coding=utf-8 import sys -import socket -import string +import signal import os import re -import thread from datetime import date from datetime import datetime from datetime import timedelta from xml.dom.minidom import parse -import birthday -import norme -import newyear -import ontime -import watchWebsite -import qd +imports = ["birthday", "qd", "events"] +imports_launch = ["watchWebsite"] +mods = list () +import server if len(sys.argv) == 1: - print "This script takes exactly 1 arg: a XML config file" + print ("This script takes exactly 1 arg: a XML config file") sys.exit(1) +def onSignal(signum, frame): + print ("\nSIGINT receive, saving states and close") -class Server: - def __init__(self, server): - if server.hasAttribute("server"): - self.host = server.getAttribute("server") - else: - self.host = "localhost" - if server.hasAttribute("port"): - self.port = int(server.getAttribute("port")) - else: - self.port = 6667 - if server.hasAttribute("password"): - self.password = server.getAttribute("password") - else: - self.password = None + for imp in mods: + imp.save_module () - self.channels = list() - for channel in server.getElementsByTagName('channel'): - self.channels.append(channel.getAttribute("name")) - - def launch(self): - thread.start_new_thread(self.connect, ()) - - def accepted_channel(self, channel): - return (self.channels.find(channel) != -1) - - def read(self): - readbuffer = "" #Here we store all the messages from server - while 1: - readbuffer = readbuffer + self.s.recv(1024) #recieve server messages - temp = readbuffer.split("\n") - readbuffer = temp.pop( ) - - for line in temp: - line = line.rstrip() #remove trailing 'rn' - - if line.find('PRIVMSG') != -1: #Call a parsing function - complete = line[1:].split(':',1) #Parse the message into useful data - info = complete[0].split(' ') - msgpart = complete[1] - sender = info[0].split('!') - if len(msgpart) > 0 and self.accepted_channel(info[2]): - parsemsg(info[2], sender[0], msgpart) - - line = line.split() - - if(line[0] == 'PING'): #If server pings then pong - self.s.send("PONG %s\r\n" % line[1]) - - def parsemsg(self, channel, sender, msg): - if re.match(".*(norme|coding style).*", msg) is not None and re.match(".*(please|give|obtenir|now|plz|stp|svp|s'il (te|vous) pla.t|check).*", msg) is not None: - norme.launch (self.s, sender, msg) - - elif msg.find("%s:"%NICK) == 0: #Treat all messages starting with 'nemubot:' as distinct commands - msgl = msg.lower() - if re.match(".*(m[' ]?entends?[ -]+tu|h?ear me|ping).*", msgl) is not None: - self.s.send("PRIVMSG %s :%s: pong\r\n"%(channel, sender)) - elif re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (.+)$", msgl) is not None: - result = re.match(".*di[st] (a|à) ([a-zA-Z0-9_]+) (qu(e |'))?(.+)$", msg) - self.s.send("PRIVMSG %s :%s: %s\r\n"%(channel, result.group(2), result.group(5))) - elif re.match(".*di[st] (.+) (a|à) ([a-zA-Z0-9_]+)$", msgl) is not None: - result = re.match(".*di[st] (.+) (à|a) ([a-zA-Z0-9_]+)$", msg) - self.s.send("PRIVMSG %s :%s: %s\r\n"%(channel, result.group(3), result.group(1))) - else: - if not birthday.parseask(self.s, channel, sender, msgl): - return + sys.exit (0) +signal.signal(signal.SIGINT, onSignal) +dom = parse(sys.argv[1]) +config = dom.getElementsByTagName('config')[0] +servers = list () - def connect(self): - self.s = socket.socket( ) #Create the socket - self.s.connect((self.host, self.port)) #Connect to server - if self.password != None: - self.s.send("PASS %s\r\n" % self.password) - self.s.send("NICK %s\r\n" % NICK) - self.s.send("USER %s %s bla :%s\r\n" % (NICK, self.host, REALNAME)) - #s.send("JOIN %s\r\n" % CHANLIST) - self.read() +for imp in imports: + mod = __import__ (imp) + mods.append (mod) + mod.load_module ("datas/") -for server in config.getElementsByTagName('server'): - srv = Server(server) - srv.launch() +for serveur in config.getElementsByTagName('server'): + srv = server.Server(serveur, config.getAttribute('nick'), config.getAttribute('owner'), config.getAttribute('realname')) + srv.launch(mods) + servers.append (srv) -print ("Nemubot ready, I operate on %s. My PID is %i" % (CHANLIST, os.getpid())) +for imp in imports_launch: + mod = __import__ (imp) + mod.load_module ("datas/") + mod.launch (servers) + +print ("Nemubot ready, my PID is %i!" % (os.getpid())) prompt="" while prompt != "quit": prompt=sys.stdin.readlines () @@ -147,70 +89,6 @@ def parsemsg(msg): if cmd[0] == 'chronos' or cmd[0] == 'edt' or cmd[0] == 'cours': s.send("PRIVMSG %s :chronos\r\n"%(info[2])) - if cmd[0] == 'new-year' or cmd[0] == 'newyear' or cmd[0] == 'ny': - #What is the next year? - nyear = datetime.today().year + 1 - ndate = datetime(nyear, 1, 1, 0, 0, 1) - newyear.launch (s, info[2], ndate, ["Il reste%s avant la nouvelle année", "Nous faisons déjà la fête depuis%s"], cmd) - if cmd[0] == 'end-of-world' or cmd[0] == 'endofworld' or cmd[0] == 'worldend' or cmd[0] == 'eow': - ndate = datetime(2012, 12, 12, 12, 12, 13) - newyear.launch (s, info[2], ndate, ["Il reste%s avant la fin du monde", "Non, cela ne peut pas arriver, la fin du monde s'est produite il y a maintenant %s. Vous n'êtes vraiment pas mort ? :("], cmd) - if cmd[0] == 'weekend' or cmd[0] == 'week-end' or cmd[0] == 'we': - ndate = datetime.today() + timedelta(5 - datetime.today().weekday()) - ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) - newyear.launch (s, info[2], ndate, ["Il reste%s avant le week-end, courrage ;)", "Youhou, on est en week-end depuis%s"], cmd) - if cmd[0] == 'google' or cmd[0] == 'eog': - ndate = datetime(2012, 3, 1, 0, 0, 1) - newyear.launch (s, info[2], ndate, ["Il reste%s pour fermer tous ces comptes Google, hop hop hop, il y a du boulot !", "Nous ne pouvons plus utiliser les services de Google depuis%s"], cmd) - if cmd[0] == 'endweekend' or cmd[0] == 'end-week-end' or cmd[0] == 'endwe' or cmd[0] == 'eowe': - ndate = datetime.today() + timedelta(7 - datetime.today().weekday()) - ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) - if datetime.today().weekday() >= 5: - newyear.launch (s, info[2], ndate, ["Plus que%s avant la fin du week-end :(", ""], cmd) - else: - newyear.launch (s, info[2], ndate, ["Encore%s avant la prochaine semaine", ""], cmd) - if cmd[0] == 'partiels' or cmd[0] == 'partiel': - ndate = datetime(2012, 3, 26, 9, 0, 1) - #ndate = datetime(2012, 1, 23, 9, 0, 1) - newyear.launch (s, info[2], ndate, ["Il reste%s avant les partiels :-o", "Les partiels ont commencés depuis maintenant%s"], cmd) - if cmd[0] == 'vacs' or cmd[0] == 'vacances' or cmd[0] == 'holiday' or cmd[0] == 'holidays' or cmd[0] == 'free-time': - ndate = datetime(2012, 3, 30, 18, 0, 1) - newyear.launch (s, info[2], ndate, ["Il reste%s avant les vacances :)", "Profitons, c'est les vacances depuis%s"], cmd) - if cmd[0] == 'katy' or cmd[0] == 'album': - ndate = datetime(2012, 3, 26, 8, 0, 0) - newyear.launch (s, info[2], ndate, ["Il reste%s avant la sortie du prochain album de Katy Perry :)", "Vite, courrons s'acheter le nouvel album de Katy Perry, il est sorti depuis%s"], cmd) - if cmd[0] == 'anniv' or cmd[0] == 'age': - if len(cmd) < 2 or cmd[1].lower() == "moi": - name = sender[0].lower() - else: - name = cmd[1].lower() - - matches = [] - - if name in birthdays: - matches.append(name) - else: - for k in birthdays.keys(): - if k.find(name) == 0: - matches.append(k) - - if len(matches) == 1: - (n, d) = (matches[0], birthdays[matches[0]]) - tyd = d - tyd = datetime(date.today().year, tyd.month, tyd.day) - - if tyd.day == datetime.today().day and tyd.month == datetime.today().month: - newyear.launch (s, info[2], d, ["", "C'est aujourd'hui l'anniversaire de %s ! Il a%s. Joyeux anniversaire :)" % (n, "%s")], cmd) - else: - if tyd < datetime.today(): - tyd = datetime(date.today().year + 1, tyd.month, tyd.day) - - if cmd[0] == 'age': - newyear.launch (s, info[2], d, ["", "%s a%s aujourd'hui !" % (n, "%s")], cmd) - else: - newyear.launch (s, info[2], tyd, ["Il reste%s avant l'anniversaire de %s !" % ("%s", n), ""], cmd) - else: - s.send("PRIVMSG %s :%s: désolé, je ne connais pas la date d'anniversaire de %s. Quand est-il né ?\r\n"%(info[2], sender[0], name)) if cmd[0] == 'jpo' or cmd[0] == 'JPO' or cmd[0] == 'next-jpo': #ndate = datetime(2012, 5, 12, 8, 30, 1) @@ -234,10 +112,10 @@ def parsemsg(msg): if cmd[0]=='devoice': s.send('MODE '+info[2]+' -v '+cmd[1]+'n') if cmd[0]=='restart': - print "Restarting thread" + print ("Restarting thread") launch(s) if cmd[0]=='stop': - print "Bye!" + print ("Bye!") s.send("PRIVMSG %s :Bye!\r\n"%(info[2])) sys.exit (0) if cmd[0]=='sys': @@ -246,7 +124,7 @@ def parsemsg(msg): if msgpart[0]=='-' and sender[0]==OWNER : #Treat msgs with - as explicit command to send to server cmd=msgpart[1:] #s.send(cmd+'n') - print 'cmd='+cmd + print ('cmd='+cmd) def read(): global s, readbuffer @@ -257,6 +135,7 @@ def read(): #signal.signal(signal.SIGHUP, onSignal) for line in temp: + print (line) line = line.rstrip() #remove trailing 'rn' if line.find('PRIVMSG') != -1: #Call a parsing function @@ -272,7 +151,7 @@ def launch(s): # thread.start_new_thread(ontime.startThread, (s,datetime(2012, 2, 23, 0, 0, 1),[],CHANLIST)) thread.start_new_thread(watchWebsite.startThread, (s, "you.p0m.fr", "", "#42sh #epitaguele", "Oh, quelle est cette nouvelle image sur http://you.p0m.fr/ ? :p")) thread.start_new_thread(watchWebsite.startThread, (s, "intra.nbr23.com", "", "#42sh", "Oh, quel est ce nouveau film sur http://intra.nbr23.com/ ? :p")) - print "Launched successfuly" + print ("Launched successfuly") launch(s) read() diff --git a/newyear.py b/newyear.py deleted file mode 100644 index fb73b75..0000000 --- a/newyear.py +++ /dev/null @@ -1,78 +0,0 @@ -# coding=utf-8 -import re -import os -from datetime import datetime -import time - -def launch(s, chan, ndate, sentences, msgpart): - -# if msgpart != 0 and len(msgpart) > 1: -# os.environ['TZ'] = msgpart[1] -# time.tzset() - - sentence_c = "PRIVMSG " + chan + " :" - - #Calculate time before new year - if datetime.now() > ndate: - sentence_c += sentences[1] - delta = datetime.now() - ndate - - else: - sentence_c += sentences[0] - delta = ndate - datetime.now() - - sec = delta.seconds - hours, remainder = divmod(sec, 3600) - minutes, seconds = divmod(remainder, 60) - - sentence = "" - force = 0 - - if force or delta.days > 0: - if delta.days > 366: - year = delta.days / 365 - days = delta.days % 365 - year / 4 - sentence += " %i an"%(year) - if year > 1: - sentence += "s" - sentence += "," - sentence += " %i jour"%(days) - if days > 1: - sentence += "s" - else: - sentence += " %i jour"%(delta.days) - if delta.days > 1: - sentence += "s" - - force = 1 - sentence += "," - - if force or hours > 0: - force = 1 - sentence += " %i heure"%(hours) - if hours > 1: - sentence += "s" - sentence += "," - - if force or minutes > 0: - force = 1 - sentence += " %i minute"%(minutes) - if minutes > 1: - sentence += "s" - sentence += " et" - - if force or seconds > 0: - force = 1 - sentence += " %i seconde"%(seconds) - if seconds > 1: - sentence += "s" - - s.send(sentence_c%(sentence) + "\r\n") - - if msgpart != 0 and len(msgpart) > 1: - os.environ['TZ'] = "Europe/Paris" - -def special(s, chan): -# s.send("PRIVMSG %s :Bonne année %i !\r\n"%(chan, datetime.today().year)) -# s.send("PRIVMSG %s :Wikipédia vient de sombrer :(\r\n"%(chan)) - s.send("PRIVMSG %s :Joyeux anniversaire Xetal !\r\n"%(chan)) diff --git a/qd.py b/qd.py index 8f5dba5..89aa2fa 100644 --- a/qd.py +++ b/qd.py @@ -1,103 +1,165 @@ # coding=utf-8 -from datetime import date -from datetime import datetime + +import re +import time from datetime import timedelta +from datetime import datetime +from datetime import date +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation +filename = "" channels = "#nemutest #42sh #epitagueule" +MANCHE = None +SCORES = dict () +temps = dict () -manche = (2, 'maxence23', datetime(2012, 3, 7, 22, 23, 0, 0), "colona", 193) +def xmlparse(node): + """Parse the given node and add scores to the global list.""" + global SCORES, MANCHE + for item in node.getElementsByTagName("score"): + SCORES[item.getAttribute("name")] = (int(item.getAttribute("fourtytwo")), + int(item.getAttribute("twentythree")), + int(item.getAttribute("pi")), + int(item.getAttribute("notfound")), + int(item.getAttribute("tententen")), + int(item.getAttribute("leet")), + int(item.getAttribute("great")), + int(item.getAttribute("bad"))) + manche = node.getElementsByTagName("manche")[0] + MANCHE = (int(manche.getAttribute("number")), + manche.getAttribute("winner"), + int(manche.getAttribute("winner_score")), + manche.getAttribute("who"), + datetime.now ()) +# time.strptime (manche.getAttribute("date"))) -#score42 = {'nemunaire': (46, 5, 19, 1, 1, 27), 'cocacompany': (1, 0, 0, 0, 0, 0), 'nelson': (5, 5, 0, 0, 0, 1), 'xetal': (10, 2, 0, 0, 0, 2), 'colona': (31, 4, 32, 0, 1, 13), 'bob': (47, 4, 19, 0, 1, 27), 'benf': (12, 8, 0, 0, 1, 2), 'maxence23': (46, 18, 42, 1, 1, 45)} -score42 = {'nemunaire': (49, 1, 40, 2, 2, 42, 2), 'xetal': (1, 0, 0, 0, 0, 0, 0), 'benf': (3, 0, 0, 0, 0, 0, 0), 'colona': (23, 0, 9, 0, 1, 18, 0), 'nelson': (7, 0, 0, 0, 0, 3, 0), 'maxence23': (43, -4, 25, 1, 1, 37, 0), 'bob': (39, 1, 14, 1, 0, 26, 0), 'cccompany': (1, 0, 0, 0, 0, 1, 0)} +def load_module(datas_path): + """Load this module""" + global MANCHE, SCORES, filename + MANCHE = None + SCORES = dict () + filename = datas_path + "/42.xml" -temps = dict() + print ("Loading 42scores ...",) + dom = parse(filename) + xmlparse (dom.documentElement) + print ("done (%d loaded, currently in round %d)" % (len(SCORES), -42)) -def scores(s, cmd, where): - global score42 - if len(cmd) > 1 and (cmd[1] == "help" or cmd[1] == "aide"): - s.send("PRIVMSG %s :Formule : normal * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + not_found * 4.04\r\n"%(where)) - elif len(cmd) > 1 and (cmd[1] == "manche"): - txt = "Nous sommes dans la %de manche, commencée par %s le %s et gagnée par %s avec %d points"%manche - s.send("PRIVMSG %s :%s\r\n"%(where, txt)) +def save_module(): + """Save the dates""" + global filename + print ("Saving birthdays ...",) + + impl = getDOMImplementation() + newdoc = impl.createDocument(None, 'game', None) + top = newdoc.documentElement + + for name in SCORES.keys(): + scr = 'fourtytwo="%d" twentythree="%d" pi="%d" notfound="%d" tententen="%d" leet="%d" great="%d" bad="%d"'% SCORES[name] + item = parseString ('' % (name, scr)).documentElement + top.appendChild(item); + + top.appendChild(parseString ('' % MANCHE).documentElement) + + with open(filename, "w") as f: + newdoc.writexml (f) + print ("done") + + +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" + +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 :)" + + +def rev (tupl): + (k, v) = tupl + return (v, k) + +def parseanswer (msg): + if msg.cmd[0] == "42" or msg.cmd[0] == "score" or msg.cmd[0] == "scores": + global SCORES, MANCHE + if len(msg.cmd) > 1 and (msg.cmd[1] == "help" or msg.cmd[1] == "aide"): + msg.send_chn ("Formule : normal * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + not_found * 4.04") + elif len(msg.cmd) > 1 and (msg.cmd[1] == "manche" or msg.cmd[1] == "round"): + msg.send_chn ("Nous sommes dans la %de manche, gagnée par %s avec %d points et commencée par %s le %s"%MANCHE) #elif where == "#nemutest": - else: - phrase = "" - if where == "#42sh": - players = ["Bob", "colona", "maxence23", "nemunaire", "Xetal"] - elif where == "#tc": - players = ["benf", "Bob", "maxence23", "nemunaire", "Xetal"] - elif where == "#epitagueule": - players = ["benf", "Bob", "colona", "cccompany", "maxence23", "nelson", "nemunaire", "Xetal"] else: - players = score42.keys() + phrase = "" - if len(cmd) > 1: - if cmd[1].lower() in score42: - (normal, bad, great, leet, pi, dt, nf) = user(cmd[1]) - phrase += " %s: 42: %d, 23: %d, bad: %d, great: %d, leet: %d, pi: %d, 404: %d = %d."%(cmd[1], normal, dt, bad, great, leet, pi, nf, normal * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + nf * 4.04) - else: - phrase = " %s n'a encore jamais joué,"%(cmd[1]) - else: - joueurs = dict() -# for player in players: - for player in score42.keys(): - if player in score42: - joueurs[player] = score(player) - - for nom, scr in sorted(joueurs.iteritems(), key=lambda (k,v): (v,k), reverse=True): - if phrase == "": - phrase = " *%s: %d*,"%(nom, scr) + if len(msg.cmd) > 1: + if msg.cmd[1].lower() in SCORES: + (normal, bad, great, leet, pi, dt, nf) = user(msg.cmd[1]) + phrase += " %s: 42: %d, 23: %d, bad: %d, great: %d, leet: %d, pi: %d, 404: %d = %d."%(msg.cmd[1], normal, dt, bad, great, leet, pi, nf, normal * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + nf * 4.04) else: - phrase += " %s: %d,"%(nom, scr) + phrase = " %s n'a encore jamais joué,"%(msg.cmd[1]) + else: + joueurs = dict() +# for player in players: + for player in SCORES.keys(): + if player in SCORES: + joueurs[player] = score(player) - s.send("PRIVMSG %s :Scores :%s\r\n"%(where, phrase[0:len(phrase)-1])) + for nom, scr in sorted(joueurs.items(), key=rev, reverse=True): + if phrase == "": + phrase = " *%s: %d*,"%(nom, scr) + else: + phrase += " %s: %d,"%(nom, scr) + + msg.send_chn ("Scores :%s" % (phrase[0:len(phrase)-1])) + return True + else: + return False def score(who): - (normal, bad, great, leet, pi, dt, nf) = user(who) + (qd, dt, pi, nf, ttt, leet, great, bad) = user(who) # return (normal * 2 + leet * 3 + pi * 3.1415 + dt + nf * 4.04) * (10000 * great / (1 + bad * 2.5)) - return (normal * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + nf * 4.04) - + return (qd * 2 - bad * 10 + great * 5 + leet * 3 + pi * 3.1415 + dt + nf * 4.04) + def win(s, who): - global score42, manche + global SCORES, MANCHE who = who.lower() - (num_manche, whosef, dayte, winner, nb_points) = manche + (num_manche, winner, nb_points, whosef, dayte) = MANCHE maxi_scor = 0 maxi_name = None - for player in score42.keys(): + for player in SCORES.keys(): scr = score(player) if scr > maxi_scor: maxi_scor = scr maxi_name = player #Reset ! - score42 = dict() -# score42[maxi_name] = (-10, 0, -4, 0, 0, -2, 0) - score42[maxi_name] = (0, 0, 0, 0, 0, 0, 0) - score42[who] = (0, -4, -1, 1, 1, 1, 0) + SCORES = dict() +# SCORES[maxi_name] = (-10, 0, -4, 0, 0, -2, 0) +# SCORES[maxi_name] = (0, 0, 0, 0, 0, 0, 0) + SCORES[who] = (0, 0, 1, 1, 0, 1, -1, -4) - for chan in channels.split(' '): - if who != maxi_name: - s.send("PRIVMSG %s :Félicitations %s, tu remportes cette manche terminée par %s, avec un score de %d !\r\n"%(chan, maxi_name, who, maxi_scor)) - else: - s.send("PRIVMSG %s :Félicitations %s, tu remportes cette manche avec %d points !\r\n"%(chan, maxi_name, maxi_scor)) + if who != maxi_name: + msg.send_global ("Félicitations %s, tu remportes cette manche terminée par %s, avec un score de %d !"%(maxi_name, who, maxi_scor)) + else: + msg.send_global ("Félicitations %s, tu remportes cette manche avec %d points !"%(maxi_name, maxi_scor)) - manche = (num_manche + 1, who, datetime.now(), maxi_name, maxi_scor) + MANCHE = (num_manche + 1, maxi_name, maxi_scor, who, datetime.now ()) + + print ("Nouvelle manche :", MANCHE) + save_module () - print "Nouvelle manche :", manche - print datetime.now(), score42 - def user(who): who = who.lower() - if who in score42: - return score42[who] + if who in SCORES: + return SCORES[who] else: - return (0, 0, 0, 0, 0, 0, 0) + return (0, 0, 0, 0, 0, 0, 0, 0) def canPlay(who): @@ -109,70 +171,78 @@ def canPlay(who): return False -def go(s, sender, msgpart, where): - if where != "#nemutest": - great = 0 +def parseask (msg): + return False - if (msgpart.strip().startswith("42") and len (msgpart) < 5) or ((msgpart.strip().lower().startswith("quarante-deux") or msgpart.strip().lower().startswith("quarante deux")) and len (msgpart) < 17): - (normal, bad, great, leet, pi, dt, nf) = user(sender[0]) - if canPlay(sender[0]): - if datetime.now().minute == 42: - if datetime.now().second == 0: - great += 1 - normal += 1 - else: - bad += 1 - score42[sender[0].lower()] = (normal, bad, great, leet, pi, dt, nf) - print datetime.now(), score42 +def parselisten (msg): +# if msg.channel == "#nemutest": + if msg.channel != "#nemutest": + (qd, dt, pi, nf, ttt, leet, great, bad) = user(msg.sender) + sum = qd + dt + pi + nf + ttt + leet + great + bad - if (msgpart.strip().startswith("23") and len (msgpart) < 5) or ((msgpart.strip().lower().startswith("vingt-trois") or msgpart.strip().lower().startswith("vingt trois")) and len (msgpart) < 14): - (normal, bad, great, leet, pi, dt, nf) = user(sender[0]) - if canPlay(sender[0]): - if datetime.now().minute == 23: - if datetime.now().second == 0: - great += 1 - dt += 1 - else: - bad += 1 - score42[sender[0].lower()] = (normal, bad, great, leet, pi, dt, nf) - print datetime.now(), score42 + if (msg.content.strip().startswith("42") and len (msg.content) < 5) or ((msg.content.strip().lower().startswith("quarante-deux") or msg.content.strip().lower().startswith("quarante deux")) and len (msg.content) < 17): + if datetime.now().minute == 10 and datetime.now().second == 10 and datetime.now().hour == 10: + ttt += 1 + great += 1 + elif datetime.now().minute == 42: + if datetime.now().second == 0: + great += 1 + qd += 1 + else: + bad += 1 - if len (msgpart) < 12 and (msgpart.strip().lower().startswith("leet time") or msgpart.strip().lower().startswith("leettime") or msgpart.strip().lower().startswith("l33t time") or msgpart.strip().lower().startswith("1337")): - (normal, bad, great, leet, pi, dt, nf) = user(sender[0]) - if canPlay(sender[0]): - if datetime.now().hour == 13 and datetime.now().minute == 37: - if datetime.now().second == 0: - great += 1 - leet += 1 - else: - bad += 1 - score42[sender[0].lower()] = (normal, bad, great, leet, pi, dt, nf) - print datetime.now(), score42 + if (msg.content.strip().startswith("23") and len (msg.content) < 5) or ((msg.content.strip().lower().startswith("vingt-trois") or msg.content.strip().lower().startswith("vingt trois")) and len (msg.content) < 14): + if datetime.now().minute == 23: + if datetime.now().second == 0: + great += 1 + dt += 1 + else: + bad += 1 - if len (msgpart) < 11 and (msgpart.strip().lower().startswith("pi time") or msgpart.strip().lower().startswith("pitime") or msgpart.strip().lower().startswith("3.14 time")): - (normal, bad, great, leet, pi, dt, nf) = user(sender[0]) - if canPlay(sender[0]): - if datetime.now().hour == 3 and datetime.now().minute == 14: - if datetime.now().second == 15 or datetime.now().second == 16: - great += 1 - pi += 1 - else: - bad += 1 - score42[sender[0].lower()] = (normal, bad, great, leet, pi, dt, nf) - print datetime.now(), score42 + if (msg.content.strip().startswith("101010") and len (msg.content) < 9): + if datetime.now().minute == 10 and datetime.now().hour == 10: + if datetime.now().second == 10: + great += 1 + ttt += 1 + else: + bad += 1 - if len (msgpart) < 16 and (msgpart.strip().lower().startswith("time not found") or msgpart.strip().lower().startswith("timenotfound") or msgpart.strip().lower().startswith("404 time")) or (len (msgpart) < 6 and msgpart.strip().lower().startswith("404")): - (normal, bad, great, leet, pi, dt, nf) = user(sender[0]) - if canPlay(sender[0]): - if datetime.now().hour == 4 and datetime.now().minute == 04: - if datetime.now().second == 0 or datetime.now().second == 4: - great += 1 - nf += 1 - else: - bad += 1 - score42[sender[0].lower()] = (normal, bad, great, leet, pi, dt, nf) - print datetime.now(), score42 + if (msg.content.strip().startswith("12345") and len (msg.content) < 8) or (msg.content.strip().startswith("012345") and len (msg.content) < 9): + if datetime.now().hour == 1 and datetime.now().minute == 23 and datetime.now().second == 45: + great += 1 + dt += 1 + else: + bad += 1 - if great >= 42: - print "Nous avons un vainqueur ! Nouvelle manche :p" - win(s, sender[0]) + if len (msg.content) < 12 and (msg.content.strip().lower().startswith("leet time") or msg.content.strip().lower().startswith("leettime") or msg.content.strip().lower().startswith("l33t time") or msg.content.strip().lower().startswith("1337")): + if datetime.now().hour == 13 and datetime.now().minute == 37: + if datetime.now().second == 0: + great += 1 + leet += 1 + else: + bad += 1 + + if len (msg.content) < 11 and (msg.content.strip().lower().startswith("pi time") or msg.content.strip().lower().startswith("pitime") or msg.content.strip().lower().startswith("3.14 time")): + if datetime.now().hour == 3 and datetime.now().minute == 14: + if datetime.now().second == 15 or datetime.now().second == 16: + great += 1 + pi += 1 + else: + bad += 1 + + if len (msg.content) < 16 and (msg.content.strip().lower().startswith("time not found") or msg.content.strip().lower().startswith("timenotfound") or msg.content.strip().lower().startswith("404 time")) or (len (msg.content) < 6 and msg.content.strip().lower().startswith("404")): + if datetime.now().hour == 4 and datetime.now().minute == 4: + if datetime.now().second == 0 or datetime.now().second == 4: + great += 1 + nf += 1 + else: + bad += 1 + + if sum != qd + dt + pi + nf + ttt + leet + great + bad and (canPlay (msg.sender) or (datetime.now().second == 45 and datetime.now().minute == 23 and datetime.now().hour == 1)): + SCORES[msg.sender.lower()] = (qd, dt, pi, nf, ttt, leet, great, bad) + if great >= 42: + print ("Nous avons un vainqueur ! Nouvelle manche :p") + win(s, msg.sender) + else: + save_module () + return False diff --git a/server.py b/server.py new file mode 100755 index 0000000..ff54b0c --- /dev/null +++ b/server.py @@ -0,0 +1,71 @@ +import socket +import _thread +import time + +import message + +class Server: + def __init__(self, server, nick, owner, realname): + self.nick = nick + self.owner = owner + self.realname = realname + + if server.hasAttribute("server"): + self.host = server.getAttribute("server") + else: + self.host = "localhost" + if server.hasAttribute("port"): + self.port = int(server.getAttribute("port")) + else: + self.port = 6667 + if server.hasAttribute("password"): + self.password = server.getAttribute("password") + else: + self.password = None + + self.channels = list() + for channel in server.getElementsByTagName('channel'): + 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 != "": + 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) + + + def launch(self, mods): + _thread.start_new_thread(self.connect, (mods,)) + + def accepted_channel(self, channel): + return (self.channels.find(channel) != -1) + + def read(self, mods): + self.readbuffer = "" #Here we store all the messages from server + while 1: + self.readbuffer = self.readbuffer + self.s.recv(1024).decode() #recieve server messages + temp = self.readbuffer.split("\n") + self.readbuffer = temp.pop( ) + + for line in temp: + msg = message.Message (self, line) + msg.treat (mods) + + + def connect(self, mods): + self.s = socket.socket( ) #Create the socket + self.s.connect((self.host, self.port)) #Connect to server + + if self.password != None: + self.s.send(b"PASS " + self.password.encode () + b"\r\n") + self.s.send(("NICK %s\r\n" % self.nick).encode ()) + self.s.send(("USER %s %s bla :%s\r\n" % (self.nick, self.host, self.realname)).encode ()) + print ("Connection to %s:%d completed" % (self.host, self.port)) + + self.s.send(("JOIN %s\r\n" % ' '.join (self.channels)).encode ()) + print ("Listen to channels: %s" % ' '.join (self.channels)) + + self.read(mods) diff --git a/watchWebsite.py b/watchWebsite.py index 1702450..378f7a4 100644 --- a/watchWebsite.py +++ b/watchWebsite.py @@ -1,10 +1,82 @@ # coding=utf-8 -import httplib + +import http.client import hashlib import time +import _thread +from urllib.parse import unquote +from xml.dom.minidom import parse +from xml.dom.minidom import parseString +from xml.dom.minidom import getDOMImplementation -def getPage(s, p): - conn = httplib.HTTPConnection(s) +import atom + +filename = "" +SITES = [] +SRVS = None + +def xmlparse(node): + """Parse the given node and add events to the global list.""" + for item in node.getElementsByTagName("watch"): + if item.getAttribute("type"): + type = item.getAttribute("type") + else: + type = "hash" + + SITES.append ((item.getAttribute("server"), item.getAttribute("page"), type, item.getAttribute("message"), None, 40)) + + +def load_module(datas_path): + """Load this module""" + global SITES, filename + SITES = [] + filename = datas_path + "/watch.xml" + + print ("Loading watchsites ...",) + dom = parse(filename) + xmlparse (dom.documentElement) + print ("done (%d loaded)" % len(SITES)) + + +def launch (servers): + global SRVS + SRVS = servers + for site in SITES: + _thread.start_new_thread (startThread, (site,)) + +def send_global (msg): + for server in SRVS: + server.send_global (msg) + +def treat_atom (lastpage, content, message): + change=False + f = atom.Atom (content) + if lastpage is not None: + diff = lastpage.diff (f) + if len(diff) > 0: + if f.id == "http://public.nbr23.com/rss.php": + for d in diff: + if d.summary == "Music": + messageI = message % ("quelles sont ces nouvelles musiques", "%s") + elif d.summary == "TV_Shows": + messageI = message % ("quelle est cette nouvelle série", "%s") + elif d.summary == "Movies": + messageI = message % ("quel est ce nouveau film", "%s") + elif d.summary == "Books": + messageI = message % ("quel est ce nouveau livre", "%s") + else: + messageI = message % ("quel est ce nouveau fichier", "%s") + send_global (messageI % unquote (d.link)) + elif message.find ("%s") >= 0: + for d in diff: + send_global (message % unquote (d.link)) + else: + send_global (message) + change=True + return (f,change) + +def getPage (s, p): + conn = http.client.HTTPConnection(s) conn.request("GET", "/%s"%(p)) res = conn.getresponse() @@ -13,16 +85,55 @@ def getPage(s, p): conn.close() return data -def startThread(s, a, p, CHANLIST, message): - lastpage = hashlib.sha224(getPage(a, p)).hexdigest() - time.sleep(2) +def startThread(site): + (srv, page, type, message, lastpage, updateTime) = site + + lastChange = 0 + while 1: - page = hashlib.sha224(getPage(a, p)).hexdigest() + content = getPage(srv, page) - if page != lastpage: - print("Page differ!") - for chan in CHANLIST.split(): - s.send("PRIVMSG %s :%s\r\n" % (chan, message)) - lastpage = page + if type == "atom": + (lastpage, change) = treat_atom (lastpage, content, message) + if change: + if lastChange <= 0: + lastChange -= 1 + else: + lastChange = 0 + else: + lastChange += 1 + else: + hash = hashlib.sha224(content).hexdigest() + if hash != lastpage: + if lastpage is not None: + send_global (message) + lastpage = hash + if lastChange <= 0: + lastChange -= 1 + else: + lastChange = 0 + else: + lastChange += 1 - time.sleep(60) + #Update check time intervalle + if lastChange >= 1 and updateTime < 60: + updateTime *= 2 + elif lastChange >= 10 and updateTime < 200: + updateTime *= 1.25 + elif lastChange >= 50 and updateTime < 500: + updateTime *= 1.1 + elif lastChange < 0 and updateTime < 60: + updateTime /= 2 + elif lastChange <= 0 and updateTime < 200: + updateTime /= 3 + elif lastChange <= 0 and updateTime > 350: + updateTime /= 7 + elif lastChange <= 0: + updateTime /= 4.5 + + if updateTime < 10: + updateTime = 10 + if updateTime > 500: + updateTime = 500 + + time.sleep(updateTime)