ADD Le premier COMMIT ;)
[pompage.git] / src / yopyop.rb
1 require 'rexml/document'
2 require 'net/http'
3 require 'thread'
4 require 'thwait'
5 require 'cgi'
6
7 # G.Burri fait à l'arrache d'après : 'www.la-rache.com'
8
9 #constantes
10 FILMS_EXTENSIONS = ['avi', 'mkv', 'rmvb', 'ogm', 'divx']
11 FICHIER_PATTERN = "<title> [<codec>] [<lang-audio>] [<lang-st>] [<team>]" # la structure d'un fichier
12 LOAD_DATA = true # charge les informations depuis le web ?
13
14 #le nombre de connexions simultanés sur le site de films
15 NB_CONN_MAX = 20
16
17 class Objet
18 @@compteur = 0
19 def initialize
20 @id = @@compteur + 1
21 @@compteur += 1
22 end
23
24 def getXml
25 #abstrait
26 end
27 end
28
29 class Personne < Objet
30 attr_reader :nom
31
32 @@personnes = {}
33
34 #ajoute une personne et la retourne
35 def Personne::ajouter(nom)
36 if nil == personne = @@personnes[nom]
37 personne = Personne::new(nom)
38 @@personnes[nom] = personne
39 end
40 personne
41 end
42
43 def initialize(nom)
44 @nom = nom
45 end
46
47 def getXml
48
49 end
50 end
51
52 class Genre < Objet
53 attr_reader :nom
54
55 @@genres = {}
56
57 #ajoute un genre et le retourne
58 def Genre::ajouter(nom)
59 if nil == genre = @@genres[nom]
60 genre = Genre::new(nom)
61 @@genres[nom] = genre
62 end
63 genre
64 end
65
66 def initialize(nom)
67 @nom = nom
68 end
69
70 def getXml
71
72 end
73 end
74
75 class Pays < Objet
76 attr_reader :nom
77
78 @@pays = {}
79
80 #ajoute un pays et le retourne
81 def Pays::ajouter(nom)
82 if nil == pays = @@pays[nom]
83 pays = Pays::new(nom)
84 @@pays[nom] = pays
85 end
86 pays
87 end
88
89 def initialize(nom)
90 @nom = nom
91 end
92
93 def getXml
94
95 end
96 end
97
98 class Film
99 attr_accessor :titre, :fichier, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget
100
101 # les films indexés par leur titre
102 @@films = {}
103 #les films indexés par leur nom de fichier
104 @@filmsFichier = {}
105
106 @@mutex = Mutex::new
107 @@threadsWait = ThreadsWait::new
108 @@nbConn = 0
109
110 def Film::litRepertoire(r)
111 Film::litRepertoireR(r)
112 #on attends que les threads se terminent
113 @@threadsWait.all_waits
114 end
115
116 # Charge les films contenus dans un fichier XML.
117 def Film::loadFilmsXml(xmlFile)
118 racine = REXML::Document::new(File::new(xmlFile)).root
119 racine.each_element{|e|
120 fichier = e.get_elements('fichier')[0].get_text
121 next if fichier == nil
122 titre = e.get_elements('titre')[0].get_text
123 annee = e.get_elements('annee')[0].get_text
124 duree = e.get_elements('duree')[0].get_text
125 critiquePresse = e.get_elements('critiquePresse')[0].get_text
126 critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text
127 synopsis = e.get_elements('synopsis')[0].get_text
128 budget = e.get_elements('budget')[0].get_text
129 realisateurs = e.get_elements('realisateur')
130 acteurs = e.get_elements('acteur')
131 pays = e.get_elements('pays')
132 genres = e.get_elements('genres')
133
134
135 film = Film::new(fichier.value)
136 film.titre = titre.value unless titre.nil?
137 film.annee = annee.value unless annee.nil?
138 realisateurs.each{|e|
139 film.realisateurs << Personne::ajouter(e.get_text.value)
140 }
141 acteurs.each{|e|
142 film.acteurs << Personne::ajouter(e.get_text.value)
143 }
144 pays.each{|e|
145 film.pays << Pays::ajouter(e.get_text.value)
146 }
147 film.duree = duree.value unless duree.nil?
148 film.critiquePresse = critiquePresse.value unless critiquePresse.nil?
149 film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?
150 genres.each{|e|
151 film.genres << Genre::ajouter(e.get_text.value)
152 }
153 film.synopsis = synopsis.value unless synopsis.nil?
154 film.budget = budget.value unless budget.nil?
155 @@films[film.titre] = film
156 @@filmsFichier[film.fichier] = film
157 }
158 end
159
160 # Renvoie tous les films sous la forme d'un élement XML.
161 def Film::getFilmsXml
162 racine = REXML::Element::new('filmographie')
163 @@films.each{|nom, f|
164 racine.add(f.getXml)
165 }
166 return REXML::Document::new.add(racine)
167 end
168
169 private
170 def Film::litRepertoireR(r)
171 Dir::foreach(r){|f|
172 next if f == '.' or f == '..'
173 fichier = r + "/" + f
174 if File::directory?(fichier)
175 litRepertoireR(fichier)
176 else
177
178 #si le film n'existe pas déjà dans la liste
179 if film = @@filmsFichier[fichier]
180 puts "[i] Already exists in DB : #{film.titre} (#{film.fichier})"
181 next
182 end
183
184 film = nil
185 @@nbConn += 1
186 @@threadsWait.join_nowait(
187 Thread::new{
188 begin
189 @@mutex.lock if @@nbConn >= NB_CONN_MAX
190 #p @@nbConn
191 film = Film::filmsFactory(fichier)
192 unless film.nil?
193 if @@films.has_key?(film.titre)
194 puts "[!] Duplicate movie : #{film.titre} (#{film.fichier})"
195 else
196 puts "[i] movie added : #{film.titre} (#{film.fichier})"
197 @@films[film.titre] = film
198 @@filmsFichier[film.fichier] = film
199 end
200 end
201 @@nbConn -= 1
202 #p @@nbConn
203 @@mutex.unlock
204 rescue Exception => e
205 puts e.message
206 puts e.backtrace
207 end
208 }
209 )
210 end
211 }
212 end
213
214 def Film::filmsFactory(fichier)
215 /^.*?\.(.{3,4})$/ =~ fichier
216 if FILMS_EXTENSIONS.include?($1)
217 Film::new(fichier).loadData
218 end
219 end
220
221 public
222
223 def initialize(fichier)
224 @fichier = fichier
225 @titre = ''
226 @annee = nil
227 @realisateurs = []
228 @acteurs = []
229 @pays = []
230 @duree = nil
231 @critiquePresse = nil
232 @critiqueSpectateur = nil
233 @genres = []
234 @synopsis = nil
235 @budget = nil
236 @budgetUnite = 'euro'
237 end
238
239 #charge les informations du films à partir d'allocine
240 def loadData
241 unless LOAD_DATA
242 @titre = @fichier
243 return self
244 end
245
246 connexionHttp = Net::HTTP::new('www.allocine.fr');
247
248 #extrait le nom à partire du nom du fichier
249 /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichier
250 #remplace undescores et points par des espaces
251 titre = $1.gsub(/[_\.]/, ' ')
252 #vire les espaces au début et à la fin
253 titre.strip!
254 #remplace les suites d'espaces par un seul
255 titre.gsub!(/ {2,}/,' ')
256 titre.gsub!(/\[.*?\]/,'')
257 titre.gsub!(/\(.*?\)/,'')
258 @titre = titre.dup
259
260 donneesHtml = nil
261 begin
262 reponse, donneesHtml = connexionHttp.get("/recherche/?motcle=#{CGI::escape(titre)}")
263 #si pas trouvé alors on enlève un mot à la fin
264 if /.*?Pas de résultats.*?/ =~ donneesHtml
265 /(.*?)[^ ]+?$/ =~ titre.strip
266 titre = $1
267 titre.strip!
268 else
269 break;
270 end
271 end while not titre.nil? and not titre.empty?
272
273 unless titre.nil? or titre.empty?
274 /<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">/ =~ donneesHtml
275 if $1
276 r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm=#{$1}.html")
277
278 # Titre
279 /<title>(.*?)<\/title>/ =~ ficheHtml
280 @titre = $1 unless $1.nil?
281
282 #puts "Movie found : #{@titre} (#{@fichier})"
283
284 # Année
285 /<h4>Année de production : (\d+)<\/h4>/ =~ ficheHtml
286 @annee = $1.to_i unless $1.nil?
287
288 # Réalisateurs
289 /Réalisé par <a class="link1" href=".*?" target="">(.*?)<\/a>/ =~ ficheHtml
290 @realisateurs << Personne::ajouter($1) unless $1.nil?
291
292 # Acteurs
293 /Avec(.*)/ =~ ficheHtml
294 $1.scan(/<a class="link1" href="\/personne\/fichepersonne_gen_cpersonne=\d+\.html" target="">(.+?)<\/a>/m){|a|
295 @acteurs << Personne::ajouter(a[0]) unless a[0].nil?
296 } unless $1.nil?
297
298 # Pays
299 /^<h4>Film (.*?)\.<\/h4>/ =~ ficheHtml
300 $1.split(',').each{|pays|
301 @pays << Pays::ajouter(pays) unless pays.nil?
302 } unless $1.nil?
303
304 # Duree
305 /<h4>Durée : (\d+?)h (\d+?)min.<\/h4>/ =~ ficheHtml
306 @duree = $1.nil? ? $2.to_i : $1.to_i * 60 + $2.to_i
307
308 # Critique presse
309 /Presse<\/a> <img src=".*?etoile_(\d)\.gif"/ =~ ficheHtml
310 @critiquePresse = $1.to_i unless $1.nil?
311
312 # Critique spectateur
313 /Spectateurs<\/a> <img src=".*?etoile_(\d)\.gif"/ =~ ficheHtml
314 @critiqueSpectateur = $1.to_i unless $1.nil?
315
316 # Genre
317 /Genre : (.*)/ =~ ficheHtml
318 $1.scan(/<a href="\/film\/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a>/m){|g|
319 @genres << Genre::ajouter(g[0]) unless g[0].nil?
320 } unless $1.nil?
321
322 # Synopsis
323 /Synopsis.*?<h4>(.+?)<\/h4>/m =~ ficheHtml
324 @synopsis = $1 unless $1.nil?
325
326 # Budget
327 /Budget<\/b> : (.+?) millions d'euros<\/h4>/ =~ ficheHtml
328 @budget = $1.to_i unless $1.nil?
329 else
330 puts "[!] Movie not found : #{@titre} (#{@fichier})"
331 end
332 end
333 self
334 end
335
336 def getXml
337 racine = REXML::Element::new('film')
338 racine.add(REXML::Element::new('fichier').add_text(@fichier))
339 racine.add(REXML::Element::new('titre').add_text(@titre))
340 racine.add(REXML::Element::new('annee').add_text(@annee.to_s))
341
342
343 @realisateurs.each{|r|
344 racine.add(REXML::Element::new('realisateur').add_text(r.nom))
345 }
346
347 @acteurs.each{|a|
348 racine.add(REXML::Element::new('acteur').add_text(a.nom))
349 }
350 @pays.each{|p|
351 racine.add(REXML::Element::new('pays').add_text(p.nom))
352 }
353 racine.add(REXML::Element::new('duree').add_text(@duree.to_s))
354
355 racine.add(REXML::Element::new('critiquePresse').add_text(@critiquePresse.to_s))
356 racine.add(REXML::Element::new('critiqueSpectateur').add_text(@critiqueSpectateur.to_s))
357 @genres.each{|g|
358 racine.add(REXML::Element::new('genre').add_text(g.nom))
359 }
360 racine.add(REXML::Element::new('synopsis').add_text(@synopsis))
361 budgetElement = REXML::Element::new('budget')
362 budgetElement.add_text(@budget.to_s)
363 budgetElement.add_attribute('unite', @budgetUnite)
364 racine.add(budgetElement)
365
366 racine
367 end
368 end
369
370
371 rep = '.'
372 if $*.empty?
373 puts 'USAGE : <xml file> [<directory>]'
374 exit 0
375 elsif $*.size == 1
376 puts 'no directory given, use the current'
377 else
378 rep = $*[1]
379 end
380 xmlFile = $*[0]
381
382 unless File::directory?(rep)
383 puts "'#{rep}' is not a valid directory"
384 exit 1
385 end
386
387 # charge les films à partir du fichier xml
388 Film::loadFilmsXml(xmlFile)
389
390 # lit le repertoire
391 Film::litRepertoire(rep)
392
393 # ecrit le fichier XML
394 Film::getFilmsXml.write(File::new(xmlFile, 'w'))