]> gitweb.pimeys.fr Git - today.git/blob - today_server.py
On peut récupérer les vidéos des chaînes Youtube grâce à l'API Youtube
[today.git] / today_server.py
1 #!/usr/bin/python
2 # -*- encoding: utf-8 -*-
3
4 """ Codé par 20-100
5 script qui affiche des trucs à penser, des J-n des conneries
6 or that kind of stuff.
7
8 Partie serveur, prévue pour chercher périodiquement les trucs non lus
9 et répondre à un check.
10
11 """
12
13 import time, datetime
14 import locale
15 import re
16 import BeautifulSoup
17 from lxml import etree
18 import os
19 import sys
20 import urllib
21 import json
22 import traceback
23 os.chdir('/home/vincent/scripts/today/')
24 sys.path.append("/home/vincent/scripts/dtc/")
25 import dtc
26
27 #: Fichier où sont stockés les derniers IDs des trucs
28 store_published_file = "lasts_published"
29
30 #: Fichier où est stockée une copie de la liste des derniers IDs *lus*
31 store_seen_file = "lasts_sync"
32
33 def get_now():
34 """Obtenir la date actuelle sous le bon format"""
35 timestamp = time.time()
36 now = datetime.datetime(*time.localtime(timestamp)[:7])
37 return now
38
39 def parse_date(s, french=True):
40 """Essaye d'obtenir une date à partir du string fourni"""
41 s = s.lower()
42 if isinstance(s, unicode):
43 s = s.encode("utf-8")
44 if s.startswith("le "):
45 s = s[3:]
46 # Y U PARKINSON ?
47 s = re.sub(" +", " ", s)
48 # Pour avoir les noms de dates en Français
49 if french:
50 locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
51 for format in ["%d %B %Y"]:
52 try:
53 struct = time.strptime(s, format)
54 return datetime.datetime(*struct[:7])
55 except ValueError:
56 pass
57 raise ValueError("%r : Didn't manage to convert as date, sorry." % (s,))
58
59 def last_dtc():
60 """Vérifie si il y a des quotes DTC non lues"""
61 return dtc.last_inserted()
62
63 def last_xkcd():
64 p = urllib.urlopen("http://xkcd.com")
65 t = p.read()
66 current_id = int(re.findall("Permanent link to this comic: http://xkcd.com/(.*?)/", t)[0])
67 return current_id
68
69 def last_xantah():
70 p = urllib.urlopen("http://www.adoprixtoxis.com/lite/download/xantah_downloads.php")
71 t = p.read()
72 ids = re.findall("""<div class="top">Xantah (.*?)</div>""", t)
73 ids = [int(i) for i in ids]
74 return max(ids)
75
76 def last_visiteur():
77 p = urllib.urlopen("http://www.levisiteurdufutur.com/episodes.html")
78 t = p.read()
79 # On parse
80 soup = BeautifulSoup.BeautifulSoup(t)
81 # On récupère les différentes saisons
82 saisons = soup.findAll("div", attrs={"id" : "episodes_list"})
83 nsaisons = len(saisons)
84 # La saison en cours est la première dans la liste
85 episodes = saisons[0].findAll("div", attrs={"class" : "thumbCaption"})
86 nepisodes = len(episodes)
87 return nsaisons * 100 + nepisodes
88
89 def last_noob_warpzone():
90 p = urllib.urlopen("http://noob-tv.com/agenda01.html")
91 t = p.read()
92 # On parse
93 soup = BeautifulSoup.BeautifulSoup(t)
94 # On récupère tous les évènements
95 garbage = soup.findAll("strong")
96 events = []
97 for o in garbage:
98 l = o.findAll("span", attrs={"class":"Style31"})
99 if l:
100 events.append([o.text[:o.text.index(":")].strip(), l[0].string.lower().strip()]) # la date, l'event
101 # On garde que les "sorties"
102 events = [o for o in events if "sortie" in o[1]]
103 # Fucking HTML
104 events = [[o[0].replace(u"&ucirc;", u"û").replace(u"&eacute;", u"é"), o[1]] for o in events]
105 # Parsing des dates
106 eventss = []
107 for i in range(len(events)):
108 raw_date, event = events[i]
109 try:
110 eventss.append([parse_date(raw_date), event])
111 except ValueError:
112 pass
113 events = eventss
114 del eventss
115 noobs = [ev for ev in events if "noob" in ev[1]]
116 warpzones = [ev for ev in events if "warpzone" in ev[1]]
117 # On prend en considération le dernier évènement qui a eu lieu
118 now = get_now()
119 ######
120 ###### RHÂ, shit, y'a des fuckings trucs du genre "1er" dans les dates… :/
121 return noobs, warpzones
122
123 def parse_youtube(username):
124 """Récupère les vidéos d'une chaîne Youtube"""
125 link = "https://gdata.youtube.com/feeds/api/users/%s/uploads?start-index=1&max-results=50" % (username,)
126 entries = []
127 while link:
128 p = urllib.urlopen(link)
129 t = p.read()
130 x = etree.fromstring(t)
131 # lxml ne supporte pas les namespaces vides dans les requêtes XPath
132 ns = x.nsmap
133 ns["default"] = ns[None]
134 ns.pop(None)
135 # Il y a potentiellement une suite
136 nextlinks = x.xpath("//default:link[@rel='next']", namespaces=ns)
137 if nextlinks:
138 link = nextlinks[0].attrib["href"]
139 else:
140 link = False
141 localentries = x.xpath("//default:entry", namespaces=ns)
142 entries.extend(localentries)
143 titles = [e.xpath(".//default:title", namespaces=ns)[0].text for e in entries]
144 return titles
145
146
147 def get_file():
148 """Récupère la liste des derniers ids de chaque truc, stockée dans le fichiers."""
149 f = open(store_published_file)
150 news = json.load(f)
151 f.close()
152 return news
153
154 def update_file(news):
155 """Met à jour la liste des derniers ids dans le fichier."""
156 f = open(store_published_file, 'w')
157 json.dump(news, f)
158 f.close()
159
160 FETCHS = {
161 "xkcd" : last_xkcd,
162 "dtc" : last_dtc,
163 "xantah" : last_xantah,
164 "visiteur" : last_visiteur,
165 }
166
167 def fetch_all():
168 """Va chercher sur les différents sites les nouveaux trucs."""
169 news = {}
170 for (k, f) in FETCHS.iteritems():
171 try:
172 news[k] = f()
173 except Exception as e:
174 print "Erreur à la récupération de %s :" % k
175 traceback.print_exc()
176 return news
177
178 def sync():
179 """Reçoit une requête de synchronisation."""
180 # On récupère où en est le client sur stdin
181 t = sys.stdin.read()
182 on_client = json.loads(t)
183 # On récupère où en est le serveur dans le fichier idoine
184 if os.path.isfile(store_seen_file):
185 on_server = json.load(open(store_seen_file))
186 else:
187 on_server = {}
188 # On garde le maximum
189 for k in set(on_client.keys() + on_server.keys()):
190 on_server[k] = max(on_client.get(k, 0), on_server.get(k, 0))
191 # On enregistre ce nouveau dico
192 json.dump(on_server, open(store_seen_file, "w"))
193 # On envoie au client ce nouveau dico
194 print json.dumps(on_server)
195
196 if __name__ == "__main__":
197 if sys.argv[1] == "check":
198 news = fetch_all()
199 olds = get_file()
200 olds.update(news)
201 update_file(olds)
202 elif sys.argv[1] == "whatsup":
203 news = get_file()
204 print json.dumps(news)
205 elif sys.argv[1] == "sync":
206 sync()