bc23fdc70ca24160b3c701a023358d4b54744722
[pompage.git] / src / films.rb
1 # Représente un ensemble de films
2
3 require 'rexml/document'
4 require 'thwait'
5
6 require 'film.rb'
7 require 'pays.rb'
8 require 'genre.rb'
9 require 'personne.rb'
10 require 'constantes.rb'
11
12 class Films
13 def initialize(xmlFile)
14 @xmlFile = xmlFile
15
16 # repertoire de base, par exemple C:/Divx/
17 @repBase = ''
18
19 # Les films indexés par leur titre
20 @films = {}
21
22 # Les films indexés par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film
23 @filmsFichier = {}
24
25 # Les films qui ont plusieurs réponses lors de la recherche, traités à la fin
26 @filmsPlusieursReponses = []
27
28 @threadsWait = ThreadsWait::new
29 @nbConn = 0 # le nombre de connexion
30
31 # le prochain id disponible
32 @idDisponible = 1
33
34 chargerFilms
35 end
36
37 # Lit un repertoire de manière recursive et va chercher les informations concernant le film sur le net
38 def pomper(r)
39 @repBase = r
40 repPrecedant = Dir::getwd
41 Dir::chdir(r)
42
43 pomperR('.')
44
45 # on attends que les threads se terminent
46 @threadsWait.all_waits
47
48 # traite les films qui avaient plusieurs réponses lors de la recherche
49 # l'utilisateur doit faire un choix
50 i = 1
51 @filmsPlusieursReponses.each{|f|
52 puts
53 puts "Plop, ya un conflit #{i} / #{@filmsPlusieursReponses.length} :"
54 if f.reglerConflitPlusieursReponses
55 ajouterFilm(f)
56 end
57 i += 1
58 }
59
60 Dir::chdir(repPrecedant)
61 end
62
63 # Sauve les films dans un fichier XML
64 def sauverFilms
65 # le document
66 docXml = REXML::Document::new
67 docXml.xml_decl().encoding = "UTF-8" # normalement UTF-8
68 docXml.xml_decl().dowrite
69
70 # la racine du document
71 racine = REXML::Element::new('filmographie')
72 docXml.add(racine)
73 pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")
74 racine.previous_sibling = pi
75
76 # on ajoute chaque film à la racine
77 @films.each{|nom, f|
78 racine.add(f.getXml)
79 }
80
81 # sauve le document
82 docXml.write(File::new(@xmlFile, 'w'), 0)
83 end
84
85 private
86
87 # Charge les films depuis le fichier XML
88 def chargerFilms
89 # si le fichier n'existe pas il n'y a rien à charger
90 if !File.exists?(@xmlFile)
91 return
92 end
93
94 racine = REXML::Document::new(File::new(@xmlFile)).root
95 racine.each_element{|e|
96 id = e.attribute('id').to_s.to_i
97
98 if id > @idDisponible
99 @idDisponible = id + 1
100 end
101
102 titre = e.get_elements('titre')[0].get_text
103 url = e.get_elements('url')[0].get_text
104 fichiers = e.get_elements('fichiers')[0].get_elements('fichier')
105 annee = e.get_elements('annee')[0].get_text
106 duree = e.get_elements('duree')[0].get_text
107 critiquePresse = e.get_elements('critiquePresse')[0].get_text
108 critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text
109 synopsis = e.get_elements('synopsis')[0].get_elements('p')
110 budget = e.get_elements('budget')[0].get_text
111 realisateurs = e.get_elements('realisateurs')[0].get_elements('realisateur')
112 acteurs = e.get_elements('acteurs')[0].get_elements('acteur')
113 pays = e.get_elements('lespays')[0].get_elements('pays')
114 genres = e.get_elements('genres')[0].get_elements('genre')
115
116 film = Film::new(fichiers[0].get_text.value)
117
118 film.id = id
119 film.titre = titre.value unless titre.nil?
120
121 film.url = url.value unless url.nil?
122
123 fichiers.each{|e|
124 film.addFichier(e.get_text.value)
125 @filmsFichier[e.get_text.value] = film
126 }
127 film.annee = annee.value unless annee.nil?
128 acteurs.each{|e|
129 film.acteurs << Personne::ajouter(e.get_text.value)
130 }
131 pays.each{|e|
132 film.pays << Pays::ajouter(e.get_text.value)
133 }
134 film.duree = duree.value unless duree.nil?
135 film.critiquePresse = critiquePresse.value unless critiquePresse.nil?
136 film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?
137 genres.each{|e|
138 film.genres << Genre::ajouter(e.get_text.value) if e.get_text != nil
139 }
140 debut = true
141 film.synopsis = ""
142 synopsis.each{|e|
143 film.synopsis += "\n" unless debut
144 film.synopsis += e.get_text.value if e.get_text != nil
145 debut = false
146 }
147 film.budget = budget.value unless budget.nil?
148 @films[film.titre] = film
149 }
150 end
151
152 # Retourne un nouvel id, utilisé lors de la création d'un nouveau film
153 def getNewId
154 id = @idDisponible
155 @idDisponible += 1
156 return id
157 end
158
159 # Ajoute un film
160 def ajouterFilm(film)
161 if film.plusieursReponses?
162 @filmsPlusieursReponses << film
163 return
164 end
165
166 # le film existe déjà
167 if @films.has_key?(film.titre)
168 # le fichier n'est pas connu -> nième partie d'un film
169 if !@filmsFichier.has_key?(film.fichiers[0])
170 puts "[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"
171 @films[film.titre].addFichier(film.fichiers[0])
172 @filmsFichier[film.fichiers[0]] = @films[film.titre]
173 else
174 puts "[!] Duplicate movie : #{film.titre} (#{film.fichiers[0]})"
175 end
176 else
177 puts "[i] movie added : #{film.titre} (#{film.fichiers[0]})"
178 @films[film.titre] = film
179 @filmsFichier[film.fichiers[0]] = film
180 end
181 end
182
183 # Appelé par 'pomper'. Cette méthode est récursive.
184 def pomperR(r)
185 Dir::foreach(r){|f|
186 next if f[0,1] == '.'
187 fichier = (r == '.' ? '' : r + "/") + f
188 if File::directory?(fichier)
189 litRepertoireR(fichier)
190 else
191
192 # vérification de l'extension
193 /^.*?\.(.{3,4})$/ =~ fichier
194 if !FILMS_EXTENSIONS.include?($1)
195 next
196 end
197
198 fichier = CGI::escapeHTML(fichier.unpack("C*").pack("U*"))
199
200 # on skip si le film est déjàa dans la BD
201 if film = @filmsFichier[fichier]
202 puts "[i] Already exists in DB : #{film.titre} (#{fichier})"
203 next
204 end
205
206 film = nil
207
208 # pour limiter le nombre de connexion simultanée
209 if @nbConn >= NB_CONN_MAX
210 @threadsWait.next_wait
211 end
212
213 @nbConn += 1
214 @threadsWait.join_nowait(
215 Thread::new{
216 begin
217 film = Film::new(fichier).loadData
218 film.id = getNewId # on lui donne un nouvel ID
219
220 unless film.nil? # le film a été correctement construit
221 ajouterFilm(film)
222 end
223 rescue Exception => e
224 puts e.message
225 puts e.backtrace
226 end
227 @nbConn -= 1
228 }
229 )
230 end
231 }
232 end
233 end