1 require 'rexml/document'
11 require 'constantes.rb'
14 attr_accessor
:id, :titre, :fichiers, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget
16 # Les films indexés par leur titre
19 # Les films indexés par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film
22 # Les films qui ont plusieurs réponses lors de la recherche, traités à la fin
23 @
@filmsPlusieursReponses = []
26 @
@threadsWait = ThreadsWait
::new
29 # le prochain id disponible
32 # retourne un nouvel id, utilisé lors de la création d'un nouveau film
39 # Lit un repertoire de manière recursive
40 def Film
::litRepertoire(r
)
41 Film
::litRepertoireR(r
)
42 # on attends que les threads se terminent
43 @
@threadsWait.all_waits
45 # traite les films qui avaient plusieurs réponses lors de la recherche
46 # l'utilisateur doit faire un choix
47 @
@filmsPlusieursReponses.each
{|f
|
48 if f
.reglerConflitPlusieursReponses
54 # Charge les films contenus dans un fichier XML.
55 def Film
::loadFilmsXml(xmlFile
)
56 # si le fichier n'existe pas il n'y a rien à charger
57 if !File
.exists
?(xmlFile
)
61 racine
= REXML
::Document::new(File
::new(xmlFile
)).root
62 racine
.each_element
{|e
|
63 id
= e
.attribute('id').to_s().to_i()
65 @
@idDisponible = id +
1
66 titre
= e
.get_elements('titre')[0].get_text
68 fichiers
= e
.get_elements('fichiers')[0].get_elements('fichier')
69 annee
= e
.get_elements('annee')[0].get_text
70 duree
= e
.get_elements('duree')[0].get_text
71 critiquePresse
= e
.get_elements('critiquePresse')[0].get_text
72 critiqueSpectateur
= e
.get_elements('critiqueSpectateur')[0].get_text
73 synopsis
= e
.get_elements('synopsis')[0].get_text
74 budget
= e
.get_elements('budget')[0].get_text
75 realisateurs
= e
.get_elements('realisateurs')[0].get_elements('realisateur')
76 acteurs
= e
.get_elements('acteurs')[0].get_elements('acteur')
77 pays
= e
.get_elements('lespays')[0].get_elements('pays')
78 genres
= e
.get_elements('genres')[0].get_elements('genre')
80 film
= Film
::new(fichiers
[0].get_text
.value
)
82 film
.titre
= titre
.value
unless titre
.nil?
85 film
.addFichier(e
.get_text
.value
)
86 @
@filmsFichier[e
.get_text
.value
] = film
88 film
.annee
= annee
.value
unless annee
.nil?
90 film
.acteurs
<< Personne
::ajouter(e
.get_text
.value
)
93 film
.pays
<< Pays
::ajouter(e
.get_text
.value
)
95 film
.duree
= duree
.value
unless duree
.nil?
96 film
.critiquePresse
= critiquePresse
.value
unless critiquePresse
.nil?
97 film
.critiqueSpectateur
= critiqueSpectateur
.value
unless critiqueSpectateur
.nil?
99 film
.genres
<< Genre
::ajouter(e
.get_text
.value
) if e
.get_text !
= nil
101 film
.synopsis
= synopsis
.value
unless synopsis
.nil?
102 film
.budget
= budget
.value
unless budget
.nil?
103 @
@films[film
.titre
] = film
107 # Renvoie tous les films sous la forme d'un document XML.
108 def Film
::getFilmsXml
110 docXml
= REXML
::Document::new
111 docXml
.xml_decl().encoding
= "UTF-8" # normalement UTF-8
112 docXml
.xml_decl().dowrite
114 # la racine du document
115 racine
= REXML
::Element::new('filmographie')
117 pi
= REXML
::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")
118 racine
.previous_sibling
= pi
120 # on ajoute chaque film à la racine
121 @
@films.each
{|nom
, f
|
131 def Film
::filmsFactory(fichier
)
132 /^.*?\.(.{3,4})$/ =~ fichier
133 if FILMS_EXTENSIONS
.include?($1)
134 #convertit le code latin-1 en UTF8
135 Film
::new(fichier
.unpack("C*").pack("U*")).loadData
139 def Film
::litRepertoireR(r
)
141 next if f
== '.' or f
== '..'
142 fichier
= r +
"/" + f
143 if File
::directory?(fichier
)
144 litRepertoireR(fichier
)
147 #si le film n'existe pas déjà dans la liste
148 if film
= @
@filmsFichier[fichier
]
149 puts
"[i] Already exists in DB : #{film.titre} (#{film.fichiers[0]})"
156 @
@threadsWait.join_nowait(
159 @
@mutex.lock
if @
@nbConn >= NB_CONN_MAX
160 film
= Film
::filmsFactory(fichier
)
161 unless film
.nil? # le film a été correctement construit
162 Film
::ajouterFilm(film
)
166 rescue Exception
=> e
176 def Film
::ajouterFilm(film
)
177 if film
.plusieursReponses
?
178 @
@filmsPlusieursReponses << film
182 # le film existe déjà
183 if @
@films.has_key
?(film
.titre
)
184 # le fichier n'est pas connu -> nième partie d'un film
185 if !@
@filmsFichier.has_key
?(film
.fichiers
[0])
186 puts
"[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"
187 @
@films[film
.titre
].addFichier(film
.fichiers
[0])
188 @
@filmsFichier[film
.fichiers
[0]] = @
@films[film
.titre
]
190 puts
"[!] Duplicate movie
: #{film.titre} (#{film.fichier})"
193 puts "[i
] movie added
: #{film.titre} (#{film.fichiers[0]})"
194 @@films[film.titre] = film
195 @@filmsFichier[film.fichiers[0]] = film
200 def initialize(fichier)
201 @fichiers = [fichier]
210 @critiquePresse = nil
211 @critiqueSpectateur = nil
215 @budgetUnite = 'euro'
218 @aPlusieursReponses = false
219 # mémorise les tuples {nom => id} dans le cas ou il y a plusieurs réponses
225 def plusieursReponses?
226 return @aPlusieursReponses
229 # demande à l'utilisateur de faire un choix
230 # ret : true si le conflit à été résolu sinon false
231 def reglerConflitPlusieursReponses
237 def addFichier(fichier)
238 if (!@fichiers.include?(fichier
))
243 # Charge les informations du films à partir d'allocine.fr
247 @titre = @fichiers[0]
253 connexionHttp
= Net
::HTTP::new('www.allocine.fr')
255 #extrait le nom à partir du nom du fichier
256 /^.*?([^\/]*?)\
.(.{3,4})$/ =~
@fichiers[0]
257 #remplace undescores et points par des espaces
258 titre
= $1.gsub(/[_\.]/, ' ')
259 #remplace les suites d'espaces par un seul
260 titre
.gsub!
(/ {2,}/,' ')
261 titre
.gsub!
(/\[.*?\]/,'')
262 titre
.gsub!
(/\(.*?\)/,'')
263 titre
.gsub!
(/\{.*?\}/,'')
264 #vire les espaces au début et à la fin
272 reponse
, donneesHtml
= connexionHttp
.get("/recherche/?motcle=#{CGI::escape(titre)}")
273 rescue Exception
=> e
275 puts
"[!] Connexion lost
, retry.."
279 #convertit le code latin-1 en UTF8
280 donneesHtml = donneesHtml.unpack("C
*").pack("U
*")
282 #si pas trouvé alors on enlève un mot à la fin
283 if /.*?Pas de résultats.*?/ =~ donneesHtml || ! donneesHtml
.include?("<h3><b>Films <h4>")
284 /(.*?)[^ ]+?$/ =~ titre
.strip
290 end while not titre
.nil? and not titre
.empty
?
292 unless titre
.nil? or titre
.empty
?
294 #/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">/ =~ donneesHtml
295 r
= donneesHtml
.scan(/<a href="\/film\
/fichefilm_gen_cfilm=(\d+)\.html" class="link1">(.*?)<\/a
>/)
298 @aPlusieursReponses = true
300 @idsAllocine[f
[1].gsub(/<(.*?)>/, '')] = f
[0]
303 loadDepuisIdAllocine(r
[0][0], connexionHttp
)
305 puts
"[!] Movie
not found
: #{@titre} (#{@fichier})"
312 def loadDepuisIdAllocine(id, connexionHttp)
313 r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm
=#{id}.html
")
315 #convertit le code latin-1 en UTF8
316 ficheHtml = ficheHtml.unpack("C
*").pack("U
*")
319 @url = "http
://www
.allocine
.fr
/film/fichefilm_gen_cfilm
=#{id}.html
"
322 /<title>(.*?)<\/title>/ =~ ficheHtml
323 @titre = $1 unless $1.nil?
325 puts "Movie found
: #{@titre} (#{@fichier})"
328 /<h4>Année de production : (\d+)<\
/h4
>/ =~ ficheHtml
329 @annee = $1.to_i
unless $1.nil?
332 /<h4>Réalisé par(.*?)<\/h4
>/ =~ ficheHtml
333 $1.scan(/<a class="link1" href=".*?">(.*?)<\/a
>/m
){|a
|
334 @realisateurs << Personne
::ajouter(a
[0]) unless a
[0].nil?
338 /<h4>Avec(.*?)<\/h4
>/ =~ ficheHtml
339 $1.scan(/<a class="link1" href="\/personne\
/fichepersonne_gen_cpersonne=\d+\.html">(.+?)<\/a
>/m
){|a
|
340 @acteurs << Personne
::ajouter(a
[0]) unless a
[0].nil?
345 /<h4>Film (.*?)\. <\/h4
>/ =~ ficheHtml
346 $1.split(',').each
{|pays
|
347 @pays << Pays
::ajouter(pays
) unless pays
.nil?
351 /<h4>Durée : (\d+)h (\d+)min./ =~ ficheHtml
352 @duree = $1.nil? ? $2.to_i
: $1.to_i
* 60 +
$2.to_i
354 # Critiques presse et spectateur
355 /Presse.*etoile_([012345]).*Spectateurs.*etoile_([012345])"/m
=~ ficheHtml
356 @critiquePresse = $1.to_i
unless $1.nil?
357 @critiqueSpectateur = $2.to_i
unless $2.nil?
360 /<h4>Genre : (.*?)<\/h4
>/ =~ ficheHtml
361 $1.scan(/<a href="\/film\
/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a
>/m
){|g
|
362 @genres << Genre
::ajouter(g
[0]) unless g
[0].nil?
366 /Synopsis.*?<h4>(.+?)<\/h4
>/m
=~ ficheHtml
367 @synopsis = $1 unless $1.nil?
370 /Budget<\/b
> : (.+
?) millions d
'euros<\/h4>/ =~ ficheHtml
371 @budget = $1.to_i unless $1.nil?
376 # Renvoie un film sous la forme d'un élément XML de type REXML
379 racine
= REXML
::Element::new('film')
380 racine
.add_attribute('id', @id.to_s
)
382 fichiers
= REXML
::Element::new('fichiers')
384 fichiers
.add(REXML
::Element::new('fichier').add_text(f
))
388 racine
.add(REXML
::Element::new('titre').add_text(@titre))
389 racine
.add(REXML
::Element::new('annee').add_text(@annee.to_s
))
391 realisateurs
= REXML
::Element::new('realisateurs')
392 @realisateurs.each
{|r
|
393 realisateurs
.add(REXML
::Element::new('realisateur').add_text(r
.nom
))
395 racine
.add(realisateurs
)
397 acteurs
= REXML
::Element::new('acteurs')
399 acteurs
.add(REXML
::Element::new('acteur').add_text(a
.nom
))
403 lespays
= REXML
::Element::new('lespays')
405 lespays
.add(REXML
::Element::new('pays').add_text(p
.nom
))
409 racine
.add(REXML
::Element::new('duree').add_text(@duree.to_s
))
411 racine
.add(REXML
::Element::new('critiquePresse').add_text(@critiquePresse.to_s
))
412 racine
.add(REXML
::Element::new('critiqueSpectateur').add_text(@critiqueSpectateur.to_s
))
414 genres
= REXML
::Element::new('genres')
416 genres
.add(REXML
::Element::new('genre').add_text(g
.nom
))
420 racine
.add(REXML
::Element::new('synopsis').add_text(@synopsis))
421 budgetElement
= REXML
::Element::new('budget')
422 budgetElement
.add_text(@budget.to_s
)
423 budgetElement
.add_attribute('unite', @budgetUnite)
424 racine
.add(budgetElement
)
426 racine
.add(REXML
::Element::new('url').add_text(@url))