MOD Le fichier film.rb et divisé en film.rb et films.rb pour une meilleure lecture
[pompage.git] / src / film.rb
1 # Représente un Film.
2 # Permet de charger des données depuis allocine.fr
3 # Permet d'effectuer des recherches depuis allocine.fr
4 # TODO : rendre la classe indépendant de la source de donnée pour pouvoir utiliser d'autres sites comme par exemple imdb.com
5
6 require 'net/http'
7 require 'cgi'
8
9 require 'pays.rb'
10 require 'genre.rb'
11 require 'personne.rb'
12 require 'constantes.rb'
13
14 class String
15 def virerBalisesHTML
16 return gsub(/<(.*?)>/, '')
17 end
18 def virerBalisesHTML!
19 gsub!(/<(.*?)>/, '')
20 end
21 end
22
23 class Film
24 attr_accessor :id, :titre, :fichiers, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget
25
26 # Constructeur. N'entreprend aucune action (chargement), crée juste un film vide.
27 def initialize(fichier)
28 @fichiers = [fichier]
29
30 @id = 0
31 @titre = ''
32 @annee = nil
33 @realisateurs = []
34 @acteurs = []
35 @pays = []
36 @duree = nil
37 @critiquePresse = nil
38 @critiqueSpectateur = nil
39 @genres = []
40 @synopsis = nil
41 @budget = nil
42 @budgetUnite = 'euro'
43 @url
44
45 @aPlusieursReponses = false
46 # mémorise les tuples {nom => id} dans le cas ou il y a plusieurs réponses
47 @idsAllocine = {}
48 end
49
50 # Est-ce qu'il y a eu plusieurs réponses pour ce film lors de la cherche sur le net ?
51 def plusieursReponses?
52 return @aPlusieursReponses
53 end
54
55 # Demande à l'utilisateur de faire un choix
56 # ret : true si le conflit à été résolu sinon false
57 def reglerConflitPlusieursReponses
58
59 @aPlusieursReponses = false # pour faire les choses bien
60
61 puts " -> " + @fichiers[0]
62 puts "Fais ton choix jeune padawan (un caractère et pas plus)"
63 tabNoms = @idsAllocine.keys
64 choix = 1
65 loop do
66 i = 1
67 tabNoms.each{|n|
68 puts "#{i}. #{n}"
69 i += 1
70 }
71 puts "A. Passer et l'ajouter"
72 puts "B. Ignorer"
73 choix = STDIN.gets
74
75 if /A/i =~ choix
76 return true
77 elsif /B/i =~ choix
78 return false
79 end
80
81 choix = choix.to_i
82 if choix > 0 && choix <= tabNoms.length
83 break;
84 else
85 puts
86 puts "Choix pas bon !!"
87 end
88 end
89
90 loadDepuisIdAllocine(@idsAllocine[tabNoms[choix-1]])
91
92 return true
93 end
94
95 # Ajoute un fichier comme faisant partie du film
96 def addFichier(fichier)
97 if !@fichiers.include?(fichier)
98 @fichiers << fichier
99 end
100 end
101
102 # Charge les informations du films à partir d'allocine.fr
103 # ret [Film]
104 def loadData
105 unless LOAD_DATA
106 @titre = @fichiers[0]
107 return self
108 end
109
110 connexionHttp = Net::HTTP::new('www.allocine.fr')
111
112 #extrait le nom à partir du nom du fichier
113 /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichiers[0]
114 #remplace undescores et points par des espaces
115 titre = $1.gsub(/[_\.]/, ' ')
116 #remplace les suites d'espaces par un seul
117 titre.gsub!(/ {2,}/,' ')
118 titre.gsub!(/\[.*?\]/,'')
119 titre.gsub!(/\(.*?\)/,'')
120 titre.gsub!(/\{.*?\}/,'')
121 #vire les espaces au début et à la fin
122 titre.strip!
123
124 @titre = titre.dup
125
126 donneesHtml = nil
127 begin
128 begin
129 reponse, donneesHtml = connexionHttp.get("/recherche/?motcle=#{CGI::escape(titre.unpack("U*").pack("C*"))}")
130 rescue Exception => e
131 p e
132 puts "[!] Connexion lost, retry.."
133 retry
134 end
135
136 #convertit le code latin-1 en UTF8
137 donneesHtml = donneesHtml.unpack("C*").pack("U*")
138
139 #si pas trouvé alors on enlève un mot à la fin
140 if /.*?Pas de résultats.*?/ =~ donneesHtml || ! donneesHtml.include?("<h3><b>Films <h4>")
141 /(.*?)[^ ]+?$/ =~ titre.strip
142 titre = $1
143 titre.strip!
144 else
145 break;
146 end
147 end while not titre.nil? and not titre.empty?
148
149 unless titre.nil? or titre.empty?
150
151 r = donneesHtml.scan(/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">(.*?)<\/a>(?:<\/h4><h5 style="color: #666666">&nbsp;(.*?)<\/h5>){0,1}(?:<h4><br \/><\/h4>){0,1}(?:<h4 style="color: #666666"> de (.*?)<\/h4>){0,1}(?:<h4 style="color: #666666">&nbsp;avec (.*?)<\/h4>){0,1}(?:<h4 style="color: #666666">&nbsp;\((.*?)\)<\/h4>){0,1}/)
152
153 if r.length > 1
154 @aPlusieursReponses = true
155 r.each{|f|
156 @idsAllocine[f[1].virerBalisesHTML + (f[2] != nil ? " " + f[2].virerBalisesHTML : "") + (f[3] != nil ? " de " + f[3].virerBalisesHTML : "") + (f[4] != nil ? " avec " + f[4].virerBalisesHTML : "") + (f[5] != nil ? " (" + f[5].virerBalisesHTML + ")" : "")] = f[0]
157 }
158 elsif r.length == 1
159 loadDepuisIdAllocine(r[0][0], connexionHttp)
160 else
161 puts "[!] Movie not found : #{@titre} (#{@fichier})"
162 end
163 end
164 self
165 end
166
167 # Renvoie un film sous la forme d'un élément XML de type REXML::Element.
168 def getXml
169
170 racine = REXML::Element::new('film')
171 racine.add_attribute('id', @id.to_s)
172
173 fichiers = REXML::Element::new('fichiers')
174 @fichiers.each{|f|
175 fichiers.add(REXML::Element::new('fichier').add_text(f))
176 }
177 racine.add(fichiers)
178
179 racine.add(REXML::Element::new('titre').add_text(@titre))
180 racine.add(REXML::Element::new('annee').add_text(@annee))
181
182 realisateurs = REXML::Element::new('realisateurs')
183 @realisateurs.each{|r|
184 realisateurs.add(REXML::Element::new('realisateur').add_text(r.nom))
185 }
186 racine.add(realisateurs)
187
188 acteurs = REXML::Element::new('acteurs')
189 @acteurs.each{|a|
190 acteurs.add(REXML::Element::new('acteur').add_text(a.nom))
191 }
192 racine.add(acteurs)
193
194 lespays = REXML::Element::new('lespays')
195 @pays.each{|p|
196 lespays.add(REXML::Element::new('pays').add_text(p.nom))
197 }
198 racine.add(lespays)
199
200 racine.add(REXML::Element::new('duree').add_text(@duree.to_s))
201
202 racine.add(REXML::Element::new('critiquePresse').add_text(@critiquePresse))
203 racine.add(REXML::Element::new('critiqueSpectateur').add_text(@critiqueSpectateur))
204
205 genres = REXML::Element::new('genres')
206 @genres.each{|g|
207 genres.add(REXML::Element::new('genre').add_text(g.nom))
208 }
209 racine.add(genres)
210
211 synopsisElement = REXML::Element::new('synopsis')
212 unless @synopsis.nil?
213 @synopsis.split("\n").each{|s|
214 next if s =~ /^\s*$/
215 synopsisElement.add(REXML::Element::new('p').add_text(s))
216 }
217 end
218 racine.add(synopsisElement)
219
220 budgetElement = REXML::Element::new('budget')
221 budgetElement.add_text(@budget)
222 budgetElement.add_attribute('unite', @budgetUnite)
223 racine.add(budgetElement)
224
225 racine.add(REXML::Element::new('url').add_text(@url))
226
227 racine
228 end
229
230 private
231 def loadDepuisIdAllocine(id, connexionHttp = nil)
232 if (connexionHttp == nil)
233 connexionHttp = Net::HTTP::new('www.allocine.fr')
234 end
235
236 r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm=#{id}.html")
237
238 #convertit le code latin-1 en UTF8
239 ficheHtml = ficheHtml.unpack("C*").pack("U*")
240
241 #url
242 @url = "http://www.allocine.fr/film/fichefilm_gen_cfilm=#{id}.html"
243
244 # Titre
245 /<title>(.*?)<\/title>/ =~ ficheHtml
246 @titre = $1 unless $1.nil?
247
248 puts "Movie found : #{@titre} (#{@fichiers[0]})"
249
250 # Année
251 /<h4>Année de production : (\d+)<\/h4>/ =~ ficheHtml
252 @annee = $1 unless $1.nil?
253
254 # Réalisateurs
255 /<h4>Réalisé par(.*?)<\/h4>/ =~ ficheHtml
256 $1.scan(/\s*<a class="link1" href=".*?">(.*?)<\/a>\s*/m){|a|
257 @realisateurs << Personne::ajouter(a[0]) unless a[0].nil?
258 } unless $1.nil?
259
260 # Acteurs
261 /<h4>Avec(.*?)<\/h4>/ =~ ficheHtml
262 $1.scan(/\s*<a class="link1" href="\/personne\/fichepersonne_gen_cpersonne=\d+\.html">(.+?)<\/a>\s*/m){|a|
263 @acteurs << Personne::ajouter(a[0]) unless a[0].nil?
264 } unless $1.nil?
265
266 # Pays
267 /<h4>Film (.*?)\.&nbsp;<\/h4>/ =~ ficheHtml
268 $1.split(',').each{|pays|
269 @pays << Pays::ajouter(pays) unless pays.nil?
270 } unless $1.nil?
271
272 # Duree (capture des heures et des minutes séparement vue que c'est le bordel sur allocine
273 /<h4>Durée :(?:.*?)(\d+)h/ =~ ficheHtml
274 heure = $1.nil? ? 0 : $1.to_i
275
276 /<h4>Durée :(?:.*?)(\d+)min/ =~ ficheHtml
277 min = $1.nil? ? 0 : $1.to_i
278
279 @duree = heure * 60 + min
280
281 # Critiques presse et spectateur
282 /Presse.*etoile_([012345]).*Spectateurs.*etoile_([012345])"/m =~ ficheHtml
283 @critiquePresse = $1 unless $1.nil?
284 @critiqueSpectateur = $2 unless $2.nil?
285
286 # Genre
287 /<h4>Genre : (.*?)<\/h4>/ =~ ficheHtml
288 $1.scan(/<a href="\/film\/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a>/m){|g|
289 @genres << Genre::ajouter(g[0]) unless g[0].nil?
290 } unless $1.nil?
291
292 # Synopsis
293 /Synopsis.*?<h4>(.*?)<\/h4>/m =~ ficheHtml
294 unless $1.nil?
295 @synopsis = $1
296 @synopsis.gsub!(/<br\s*\/>|<br\s*>/, "\n")
297 @synopsis.virerBalisesHTML!
298 end
299
300 # Budget
301 /Budget<\/b> : (.+?) millions d'euros<\/h4>/ =~ ficheHtml
302 @budget = $1 unless $1.nil?
303 end
304 end
305