X-Git-Url: http://gitweb.pimeys.fr/?a=blobdiff_plain;f=today_server.py;h=8c251db13ad34dee94f63cec00ab1b913f2e0c32;hb=6ead3f80d35afb337e30ab8cb0eeb30f272f65e3;hp=98e484481a65bf5ae894bed1693ad3351dd19758;hpb=18dc797478ece73aaf30c5322303d05006474d28;p=today.git diff --git a/today_server.py b/today_server.py index 98e4844..8c251db 100755 --- a/today_server.py +++ b/today_server.py @@ -10,50 +10,22 @@ et répondre à un check. """ -import time, datetime -import locale import re import BeautifulSoup +from lxml import etree import os import sys import urllib import json import traceback +import inspect +import pprint os.chdir('/home/vincent/scripts/today/') sys.path.append("/home/vincent/scripts/dtc/") import dtc -#: Fichier où sont stockés les derniers IDs des trucs -store_published_file = "lasts_published" - -#: Fichier où est stockée une copie de la liste des derniers IDs *lus* -store_seen_file = "lasts_sync" - -def get_now(): - """Obtenir la date actuelle sous le bon format""" - timestamp = time.time() - now = datetime.datetime(*time.localtime(timestamp)[:7]) - return now - -def parse_date(s, french=True): - """Essaye d'obtenir une date à partir du string fourni""" - s = s.lower() - if isinstance(s, unicode): - s = s.encode("utf-8") - if s.startswith("le "): - s = s[3:] - # Y U PARKINSON ? - s = re.sub(" +", " ", s) - # Pour avoir les noms de dates en Français - if french: - locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') - for format in ["%d %B %Y"]: - try: - struct = time.strptime(s, format) - return datetime.datetime(*struct[:7]) - except ValueError: - pass - raise ValueError("%r : Didn't manage to convert as date, sorry." % (s,)) +# Config server +import serverconfig def last_dtc(): """Vérifie si il y a des quotes DTC non lues""" @@ -85,50 +57,104 @@ def last_visiteur(): nepisodes = len(episodes) return nsaisons * 100 + nepisodes +def parse_youtube(username): + """Récupère les vidéos d'une chaîne Youtube""" + link = "https://gdata.youtube.com/feeds/api/users/%s/uploads?start-index=1&max-results=50" % (username,) + entries = [] + while link: + p = urllib.urlopen(link) + t = p.read() + x = etree.fromstring(t) + # lxml ne supporte pas les namespaces vides dans les requêtes XPath + ns = x.nsmap + ns["default"] = ns[None] + ns.pop(None) + # Il y a potentiellement une suite + nextlinks = x.xpath("//default:link[@rel='next']", namespaces=ns) + if nextlinks: + link = nextlinks[0].attrib["href"] + else: + link = False + localentries = x.xpath("//default:entry", namespaces=ns) + entries.extend(localentries) + titles = [e.xpath(".//default:title", namespaces=ns)[0].text for e in entries] + return titles + +def get_season_episode(title): + """Récupère les numéros de la saison et de l'épisode. Crash si ne trouve pas.""" + ep = int(re.findall("ep([0-9]*)", title)[0]) + saison = int(re.findall("s([0-9]*)", title)[0]) + return saison, ep + def last_noob_warpzone(): - p = urllib.urlopen("http://noob-tv.com/agenda01.html") - t = p.read() - # On parse - soup = BeautifulSoup.BeautifulSoup(t) - # On récupère tous les évènements - garbage = soup.findAll("strong") - events = [] - for o in garbage: - l = o.findAll("span", attrs={"class":"Style31"}) - if l: - events.append([o.text[:o.text.index(":")].strip(), l[0].string.lower().strip()]) # la date, l'event - # On garde que les "sorties" - events = [o for o in events if "sortie" in o[1]] - # Fucking HTML - events = [[o[0].replace(u"û", u"û").replace(u"é", u"é"), o[1]] for o in events] - # Parsing des dates - eventss = [] - for i in range(len(events)): - raw_date, event = events[i] - try: - eventss.append([parse_date(raw_date), event]) - except ValueError: - pass - events = eventss - del eventss - noobs = [ev for ev in events if "noob" in ev[1]] - warpzones = [ev for ev in events if "warpzone" in ev[1]] - # On prend en considération le dernier évènement qui a eu lieu - now = get_now() - ###### - ###### RHÂ, shit, y'a des fuckings trucs du genre "1er" dans les dates… :/ - return noobs, warpzones - + global last_nw + # GRUIK + if "last_nw" in globals().keys(): + return last_nw + titles = parse_youtube("Funglisoft") + noobs = [t.lower().strip() for t in titles if t.lower().strip().startswith("noob")] + warpzones = [t.lower().strip() for t in titles if t.lower().strip().startswith("warpzone project")] + lasts = [] + for serie in [noobs, warpzones]: + # Les titres sont dans l'ordre antichronologique, on s'arrête donc au premier qu'on comprend + for titre in serie: + if "noob le film" in titre or "making of" in titre or "noob versus rct" == titre or "extraits ost" in titre: + continue + try: + if DEBUG: + print titre + saison, ep = get_season_episode(titre) + except (ValueError, IndexError) as e: + print "%s sur un season_episode warpzone : %s\n" % (e, titre) + continue + lasts.append([saison, ep]) + del saison, ep + break + last_noob = lasts[0][0]*100 + lasts[0][1] + last_warp = lasts[1][0]*100 + lasts[1][1] + last_nw = [last_noob, last_warp] + return last_nw + +def last_noob(): + return last_noob_warpzone()[0] +def last_warpzone(): + return last_noob_warpzone()[1] + +def last_hugo(): + titles = parse_youtube("HugoToutSeul") + return len(titles) + +def last_norman(): + titles = parse_youtube("NormanFaitDesVideos") + return len(titles) + +def last_cyprien(): + titles = parse_youtube("MonsieurDream") + return len(titles) + +def last_grenier(): + titles = parse_youtube("joueurdugrenier") + return len(titles) + +def last_jl8(): + rss = urllib.urlopen("http://limbero.org/jl8/rss/") + t = rss.read() + x = etree.fromstring(t) + links = x.xpath("//link") + maxnum = links[1].text.split("/")[-1] + maxnum = int(maxnum) + return maxnum + def get_file(): - """Récupère la liste des derniers ids de chaque truc, stockée dans le fichiers.""" - f = open(store_published_file) + """Récupère la liste des derniers ids de chaque truc, stockée dans le fichier.""" + f = open(serverconfig.store_published_file) news = json.load(f) f.close() return news def update_file(news): """Met à jour la liste des derniers ids dans le fichier.""" - f = open(store_published_file, 'w') + f = open(serverconfig.store_published_file, 'w') json.dump(news, f) f.close() @@ -137,6 +163,13 @@ FETCHS = { "dtc" : last_dtc, "xantah" : last_xantah, "visiteur" : last_visiteur, + "noob" : last_noob, + "warpzone" : last_warpzone, + "hugo" : last_hugo, + "norman" : last_norman, + "cyprien" : last_cyprien, + "grenier" : last_grenier, + "dc" : last_jl8, } def fetch_all(): @@ -146,8 +179,18 @@ def fetch_all(): try: news[k] = f() except Exception as e: - print "Erreur à la récupération de %s :" % k - traceback.print_exc() + errmsg = "Erreur à la récupération de %s :\n" % k + errmsg += traceback.format_exc() + # On dumpe le contenu local de la mémoire au moment de l'exception + fobj = inspect.trace()[-1][0] + # On fait un peu de ménage + d = {k:v for (k,v) in fobj.f_locals.iteritems() if not k.startswith("_")} + # On évite d'envoyer truckLoadsOfShit + d = {k: (v if len(str(v)) < 800 + else str(v)[:400] + "*" * 40 + "TRUNCATED OBJECT" + "*" * 40 + str(v)[-400:]) + for (k,v) in d.iteritems()} + errmsg += "\nContexte : %s\n\n" % (pprint.pformat(d)) + print errmsg return news def sync(): @@ -156,23 +199,27 @@ def sync(): t = sys.stdin.read() on_client = json.loads(t) # On récupère où en est le serveur dans le fichier idoine - if os.path.isfile(store_seen_file): - on_server = json.load(open(store_seen_file)) + if os.path.isfile(serverconfig.store_seen_file): + on_server = json.load(open(serverconfig.store_seen_file)) else: on_server = {} # On garde le maximum for k in set(on_client.keys() + on_server.keys()): on_server[k] = max(on_client.get(k, 0), on_server.get(k, 0)) # On enregistre ce nouveau dico - json.dump(on_server, open(store_seen_file, "w")) + json.dump(on_server, open(serverconfig.store_seen_file, "w")) # On envoie au client ce nouveau dico print json.dumps(on_server) if __name__ == "__main__": + DEBUG = ("--debug" in sys.argv) or ("--verbose" in sys.argv) or serverconfig.DEBUG if sys.argv[1] == "check": news = fetch_all() - olds = get_file() - olds.update(news) + if "--init" in sys.argv: + olds = news + else: + olds = get_file() + olds.update(news) update_file(olds) elif sys.argv[1] == "whatsup": news = get_file()