ADD Pompage des images ! :)
[pompage.git] / src / film.rb
index 1eaa33f..309f686 100644 (file)
-require 'rexml/document'\r
-require 'net/http'\r
-require 'thread'\r
-require 'thwait'\r
-require 'cgi'\r
+# Représente un Film.\r
+# Permet de charger des données depuis allocine.fr\r
+# Permet d'effectuer des recherches depuis allocine.fr\r
+# TODO : rendre la classe indépendant de la source de donnée pour pouvoir utiliser d'autres sites comme par exemple imdb.com\r
 \r
 require 'pays.rb'\r
 require 'genre.rb'\r
 require 'personne.rb'\r
 \r
 require 'pays.rb'\r
 require 'genre.rb'\r
 require 'personne.rb'\r
-\r
 require 'constantes.rb'\r
 \r
 require 'constantes.rb'\r
 \r
-class Film\r
-   attr_accessor :id, :titre, :fichiers, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget\r
-      \r
-   # Les films indexés par leur titre\r
-   @@films = {}\r
-   \r
-   # Les films indexés par leur nom de fichier, deux fichiers différents peuvent pointer sur le même film\r
-   @@filmsFichier = {}\r
-   \r
-   # Les films qui ont plusieurs réponses lors de la recherche, traités à la fin\r
-   @@filmsPlusieursReponses = []\r
-\r
-   @@mutex = Mutex::new\r
-   @@threadsWait = ThreadsWait::new\r
-   @@nbConn = 0\r
-   \r
-   # le prochain id disponible\r
-   @@idDisponible = 1\r
-   \r
-   # retourne un nouvel id, utilisé lors de la création d'un nouveau film\r
-   def Film::getNewId\r
-      id = @@idDisponible\r
-      @@idDisponible += 1\r
-      return id\r
-   end\r
+require 'modules/allocine.rb'\r
 \r
 \r
-   # Lit un repertoire de manière recursive\r
-   def Film::litRepertoire(r)\r
-      Film::litRepertoireR(r)\r
-      # on attends que les threads se terminent\r
-      @@threadsWait.all_waits\r
-      \r
-      # traite les films qui avaient plusieurs réponses lors de la recherche\r
-      # l'utilisateur doit faire un choix\r
-      @@filmsPlusieursReponses.each{|f|\r
-         if f.reglerConflitPlusieursReponses\r
-            Film::ajouterFilm(f)\r
-         end\r
-      }\r
+# ajout de deux méthodes à la classe String\r
+class String\r
+   def virerBalisesHTML\r
+      return gsub(/<(.*?)>/, '')\r
    end\r
    end\r
-   \r
-   # Charge les films contenus dans un fichier XML.\r
-   def Film::loadFilmsXml(xmlFile)\r
-      # si le fichier n'existe pas il n'y a rien à charger\r
-      if !File.exists?(xmlFile)\r
-         return\r
-      end\r
-            \r
-      racine = REXML::Document::new(File::new(xmlFile)).root\r
-      racine.each_element{|e|       \r
-         id = e.attribute('id').to_s().to_i()\r
-       \r
-         @@idDisponible = id + 1         \r
-         titre = e.get_elements('titre')[0].get_text\r
-         \r
-         fichiers = e.get_elements('fichiers')[0].get_elements('fichier')\r
-         annee = e.get_elements('annee')[0].get_text\r
-         duree = e.get_elements('duree')[0].get_text\r
-         critiquePresse = e.get_elements('critiquePresse')[0].get_text\r
-         critiqueSpectateur = e.get_elements('critiqueSpectateur')[0].get_text\r
-         synopsis = e.get_elements('synopsis')[0].get_text\r
-         budget = e.get_elements('budget')[0].get_text  \r
-         realisateurs = e.get_elements('realisateurs')[0].get_elements('realisateur')\r
-         acteurs = e.get_elements('acteurs')[0].get_elements('acteur')\r
-         pays = e.get_elements('lespays')[0].get_elements('pays')\r
-         genres = e.get_elements('genres')[0].get_elements('genre')\r
-         \r
-         film = Film::new(fichiers[0].get_text.value)\r
-         \r
-         film.titre = titre.value unless titre.nil?\r
-         film.id = id\r
-         fichiers.each{|e|\r
-            film.addFichier(e.get_text.value)\r
-            @@filmsFichier[e.get_text.value] = film\r
-         }\r
-         film.annee = annee.value unless annee.nil?\r
-         acteurs.each{|e|\r
-            film.acteurs << Personne::ajouter(e.get_text.value)\r
-         }\r
-         pays.each{|e|\r
-            film.pays << Pays::ajouter(e.get_text.value)\r
-         }\r
-         film.duree = duree.value unless duree.nil?\r
-         film.critiquePresse = critiquePresse.value unless critiquePresse.nil?\r
-         film.critiqueSpectateur = critiqueSpectateur.value unless critiqueSpectateur.nil?\r
-         genres.each{|e|\r
-            film.genres << Genre::ajouter(e.get_text.value) if e.get_text != nil\r
-         }\r
-         film.synopsis = synopsis.value unless synopsis.nil?\r
-         film.budget = budget.value unless budget.nil?\r
-         @@films[film.titre] = film\r
-      }\r
+   def virerBalisesHTML!\r
+      gsub!(/<(.*?)>/, '')\r
    end\r
    end\r
+end\r
 \r
 \r
-   # Renvoie tous les films sous la forme d'un document XML.\r
-   def Film::getFilmsXml\r
-      # le document\r
-      docXml = REXML::Document::new\r
-      docXml.xml_decl().encoding = "UTF-8"  # normalement UTF-8\r
-      docXml.xml_decl().dowrite\r
-            \r
-      # la racine du document\r
-      racine = REXML::Element::new('filmographie')\r
-      docXml.add(racine)\r
-      pi = REXML::Instruction.new("xml-stylesheet", "type=\"text/xsl\" href=\"../xsl/yopyop.xsl\"")\r
-      racine.previous_sibling = pi\r
-      \r
-      # on ajoute chaque film à la racine\r
-      @@films.each{|nom, f|\r
-         racine.add(f.getXml)\r
-      } \r
+class Film\r
       \r
       \r
-      # revoie le document\r
-      docXml\r
-   end\r
-   \r
-private\r
+   # toutes les données membres sont accessibles par défaut (écriture/lecture)\r
+   attr_accessor :id, :titre, :url, :fichiers, :mod, :annee, :realisateurs, :acteurs, :pays, :duree, :critiquePresse, :critiqueSpectateur, :genres, :synopsis, :budget\r
 \r
 \r
-   def Film::filmsFactory(fichier)\r
-      /^.*?\.(.{3,4})$/ =~ fichier\r
-      if FILMS_EXTENSIONS.include?($1)\r
-         #convertit le code latin-1 en UTF8\r
-         Film::new(fichier.unpack("C*").pack("U*")).loadData\r
-      end\r
-    end\r
-    \r
-   def Film::litRepertoireR(r)\r
-      Dir::foreach(r){|f|\r
-         next if f == '.' or f == '..'\r
-         fichier = r + "/" + f\r
-         if File::directory?(fichier)\r
-            litRepertoireR(fichier) \r
-         else\r
-         \r
-            #si le film n'existe pas déjà dans la liste\r
-            if film = @@filmsFichier[fichier]\r
-               puts "[i] Already exists in DB : #{film.titre} (#{film.fichiers[0]})"\r
-               next\r
-            end\r
-            \r
-            film = nil\r
-             \r
-            @@nbConn += 1    \r
-            @@threadsWait.join_nowait(\r
-               Thread::new{    \r
-                  begin\r
-                     @@mutex.lock if @@nbConn >= NB_CONN_MAX                     \r
-                     film = Film::filmsFactory(fichier)                     \r
-                     unless film.nil? # le film a été correctement construit\r
-                        Film::ajouterFilm(film)\r
-                     end\r
-                     @@nbConn -= 1\r
-                     @@mutex.unlock\r
-                  rescue Exception => e\r
-                     puts e.message\r
-                     puts e.backtrace\r
-                  end\r
-               }\r
-            )\r
-         end\r
-      }\r
-   end\r
-   \r
-   def Film::ajouterFilm(film)\r
-      if film.plusieursReponses?\r
-         @@filmsPlusieursReponses << film\r
-         return\r
-      end\r
-      \r
-      # le film existe déjà\r
-      if @@films.has_key?(film.titre)\r
-         # le fichier n'est pas connu -> nième partie d'un film\r
-         if !@@filmsFichier.has_key?(film.fichiers[0])\r
-            puts "[i] movie #{film.titre} has a another file part : #{film.fichiers[0]}"\r
-            @@films[film.titre].addFichier(film.fichiers[0])\r
-            @@filmsFichier[film.fichiers[0]] = @@films[film.titre]                     \r
-         else\r
-            puts "[!] Duplicate movie : #{film.titre} (#{film.fichier})"\r
-         end\r
-      else\r
-         puts "[i] movie added : #{film.titre} (#{film.fichiers[0]})"\r
-         @@films[film.titre] = film\r
-         @@filmsFichier[film.fichiers[0]] = film\r
-      end\r
-   end\r
-      \r
-   \r
-   def initialize(fichier)\r
-      @fichiers = [fichier]\r
+   # Constructeur. N'entreprend aucune action (chargement), crée juste un film vide.\r
+   # p1 [String] : le fichier correspondant au film\r
+   def initialize(fichier, mod)\r
+      @fichiers = [fichier] # le chemin des fichiers est relatif au repertoire de base\r
+      @mod = mod\r
            \r
       @id = 0\r
       @titre = ''\r
            \r
       @id = 0\r
       @titre = ''\r
@@ -214,44 +45,75 @@ private
       @budget = nil      \r
       @budgetUnite = 'euro'\r
       @url\r
       @budget = nil      \r
       @budgetUnite = 'euro'\r
       @url\r
+            \r
+      @nbReponses = 0\r
       \r
       \r
-      @aPlusieursReponses = false\r
-      # mémorise les tuples {nom => id} dans le cas ou il y a plusieurs réponses\r
-      @idsAllocine = {}\r
+      # mémorise les tuples {nom => id} dans le cas ou il y a plusieurs choix de films après une recherche\r
+      @choix = {}\r
    end\r
 \r
    end\r
 \r
-public \r
-\r
+   # Est-ce qu'il y a eu plusieurs réponses pour ce film lors de la cherche sur le net ?\r
    def plusieursReponses?\r
    def plusieursReponses?\r
-      return @aPlusieursReponses\r
+      return @nbReponses > 1\r
+   end    \r
+\r
+   # Est-ce qu'il y a eu plusieurs réponses pour ce film lors de la cherche sur le net ?\r
+   def nbReponses\r
+      return @nbReponses\r
    end \r
    \r
    end \r
    \r
-   # demande à l'utilisateur de faire un choix\r
-   # ret : true si le conflit à été résolu sinon false\r
+   # Demande à l'utilisateur de faire un choix.\r
+   # ret : 1 si le conflit à été résolu, 2 si le film est à ignorer, 3 si tout les films sont à ignorer\r
    def reglerConflitPlusieursReponses\r
    def reglerConflitPlusieursReponses\r
-      puts "prout"\r
+      @nbReponses = 1\r
+      \r
+      puts " -> " + @fichiers[0]\r
+      puts "Fais ton choix jeune padawan (un caractère et pas plus)"\r
+      tabNoms = @choix.keys\r
+      choix = 1\r
+      loop do \r
+         i = 1\r
+         tabNoms.each{|n|\r
+           puts "#{i}. #{n}"\r
+           i += 1\r
+         }\r
+         puts "A. Passer et l'ajouter"\r
+         puts "B. Ignorer"\r
+         puts "C. Tout ignorer"\r
+         choix = STDIN.gets\r
+         \r
+         if /A/i =~ choix\r
+            return 1\r
+         elsif /B/i =~ choix\r
+            return 2\r
+         elsif /C/i =~ choix\r
+            return 3\r
+         end\r
+         \r
+         choix = choix.to_i\r
+         if choix > 0 && choix <= tabNoms.length\r
+            break;\r
+         else\r
+            puts\r
+            puts "Choix pas bon !!"\r
+         end\r
+      end\r
       \r
       \r
-      return false\r
+      @mod.load(@choix[tabNoms[choix-1]], self)\r
+      \r
+      return 1\r
    end\r
    \r
    end\r
    \r
+   # Ajoute un fichier comme faisant partie du film\r
    def addFichier(fichier)\r
    def addFichier(fichier)\r
-      if (!@fichiers.include?(fichier))\r
+      if !@fichiers.include?(fichier)\r
          @fichiers << fichier\r
       end\r
    end\r
 \r
    # Charge les informations du films à partir d'allocine.fr\r
    # ret [Film]\r
          @fichiers << fichier\r
       end\r
    end\r
 \r
    # Charge les informations du films à partir d'allocine.fr\r
    # ret [Film]\r
-   def loadData\r
-      unless LOAD_DATA\r
-         @titre = @fichiers[0]\r
-         return self\r
-      end\r
-      \r
-      @id = Film::getNewId\r
-\r
-      connexionHttp = Net::HTTP::new('www.allocine.fr')\r
-   \r
+   def loadData   \r
       #extrait le nom à partir du nom du fichier\r
       /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichiers[0]\r
       #remplace undescores et points par des espaces\r
       #extrait le nom à partir du nom du fichier\r
       /^.*?([^\/]*?)\.(.{3,4})$/ =~ @fichiers[0]\r
       #remplace undescores et points par des espaces\r
@@ -266,114 +128,24 @@ public
       \r
       @titre = titre.dup\r
       \r
       \r
       @titre = titre.dup\r
       \r
-      donneesHtml = nil\r
-      begin\r
-         begin\r
-            reponse, donneesHtml = connexionHttp.get("/recherche/?motcle=#{CGI::escape(titre)}")\r
-         rescue Exception => e\r
-            p e\r
-            puts "[!] Connexion lost, retry.."\r
-            retry\r
-         end\r
-         \r
-         #convertit le code latin-1 en UTF8\r
-         donneesHtml = donneesHtml.unpack("C*").pack("U*")\r
-         \r
-         #si pas trouvé alors on enlève un mot à la fin\r
-         if /.*?Pas de résultats.*?/ =~ donneesHtml || ! donneesHtml.include?("<h3><b>Films <h4>")\r
-            /(.*?)[^ ]+?$/ =~ titre.strip\r
-            titre = $1\r
-            titre.strip!\r
-         else\r
-            break;\r
-         end\r
-      end while not titre.nil? and not titre.empty?\r
+      unless LOAD_DATA\r
+         return self\r
+      end\r
       \r
       \r
-      unless titre.nil? or titre.empty?\r
-            \r
-         #/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">/ =~ donneesHtml\r
-         r = donneesHtml.scan(/<a href="\/film\/fichefilm_gen_cfilm=(\d+)\.html" class="link1">(.*?)<\/a>/)\r
-         \r
-         if r.length > 1\r
-            @aPlusieursReponses = true\r
-            r.each{|f|\r
-               @idsAllocine[f[1].gsub(/<(.*?)>/, '')] = f[0]\r
-            }\r
-         elsif r.length == 1\r
-            loadDepuisIdAllocine(r[0][0], connexionHttp) \r
-         else\r
-            puts "[!] Movie not found : #{@titre} (#{@fichier})"\r
-         end\r
+      reponses = @mod.rechercherFilm(titre)\r
+      @nbReponses = reponses.size\r
+      \r
+      if @nbReponses == 1\r
+         @mod.load(reponses.values[0], self)\r
+      else\r
+         @choix = reponses   \r
       end\r
       end\r
+\r
       self\r
    end\r
    \r
       self\r
    end\r
    \r
-private\r
-   def loadDepuisIdAllocine(id, connexionHttp)\r
-      r, ficheHtml = connexionHttp.get("/film/fichefilm_gen_cfilm=#{id}.html") \r
-      \r
-      #convertit le code latin-1 en UTF8\r
-      ficheHtml = ficheHtml.unpack("C*").pack("U*")\r
-\r
-      #url\r
-      @url = "http://www.allocine.fr/film/fichefilm_gen_cfilm=#{id}.html"\r
-      \r
-      # Titre\r
-      /<title>(.*?)<\/title>/ =~ ficheHtml\r
-      @titre = $1 unless $1.nil?\r
-      \r
-      puts "Movie found : #{@titre} (#{@fichier})"\r
-      \r
-      # Année\r
-      /<h4>Année de production : (\d+)<\/h4>/ =~ ficheHtml\r
-      @annee = $1.to_i unless $1.nil?\r
-      \r
-      # Réalisateurs\r
-      /<h4>Réalisé par(.*?)<\/h4>/ =~ ficheHtml\r
-      $1.scan(/<a class="link1" href=".*?">(.*?)<\/a>/m){|a|\r
-        @realisateurs << Personne::ajouter(a[0]) unless a[0].nil?\r
-      } unless $1.nil?\r
-      \r
-      # Acteurs\r
-      /<h4>Avec(.*?)<\/h4>/ =~ ficheHtml\r
-      $1.scan(/<a class="link1" href="\/personne\/fichepersonne_gen_cpersonne=\d+\.html">(.+?)<\/a>/m){|a|\r
-         @acteurs << Personne::ajouter(a[0]) unless a[0].nil? \r
-      } unless $1.nil? \r
-                \r
-                \r
-      # Pays\r
-      /<h4>Film (.*?)\.&nbsp;<\/h4>/ =~ ficheHtml\r
-      $1.split(',').each{|pays|\r
-         @pays << Pays::ajouter(pays) unless pays.nil?\r
-      } unless $1.nil? \r
-      \r
-      # Duree\r
-      /<h4>Durée : (\d+)h (\d+)min./ =~ ficheHtml\r
-      @duree = $1.nil? ? $2.to_i : $1.to_i * 60 + $2.to_i\r
-      \r
-      # Critiques presse et spectateur\r
-      /Presse.*etoile_([012345]).*Spectateurs.*etoile_([012345])"/m =~ ficheHtml\r
-      @critiquePresse = $1.to_i unless $1.nil?\r
-      @critiqueSpectateur = $2.to_i unless $2.nil?\r
-      \r
-      # Genre\r
-      /<h4>Genre : (.*?)<\/h4>/ =~ ficheHtml\r
-      $1.scan(/<a href="\/film\/alaffiche_genre_gen_genre=.*?" class="link1">(.+?)<\/a>/m){|g|\r
-         @genres << Genre::ajouter(g[0]) unless g[0].nil?\r
-      } unless $1.nil?     \r
-      \r
-      # Synopsis            \r
-      /Synopsis.*?<h4>(.+?)<\/h4>/m =~ ficheHtml\r
-      @synopsis = $1 unless $1.nil?\r
-      \r
-      # Budget       \r
-      /Budget<\/b> : (.+?) millions d'euros<\/h4>/ =~ ficheHtml\r
-      @budget = $1.to_i unless $1.nil?\r
-   end     \r
-      \r
-public\r
-   \r
-   # Renvoie un film sous la forme d'un élément XML de type REXML\r
+   # Renvoie un film sous la forme d'un élément XML .\r
+   # ret [REXML::Element] : un element xml <film>\r
    def getXml\r
       \r
       racine = REXML::Element::new('film')\r
    def getXml\r
       \r
       racine = REXML::Element::new('film')\r
@@ -386,7 +158,7 @@ public
       racine.add(fichiers)      \r
       \r
       racine.add(REXML::Element::new('titre').add_text(@titre))\r
       racine.add(fichiers)      \r
       \r
       racine.add(REXML::Element::new('titre').add_text(@titre))\r
-      racine.add(REXML::Element::new('annee').add_text(@annee.to_s))\r
+      racine.add(REXML::Element::new('annee').add_text(@annee))\r
 \r
       realisateurs = REXML::Element::new('realisateurs')      \r
       @realisateurs.each{|r|\r
 \r
       realisateurs = REXML::Element::new('realisateurs')      \r
       @realisateurs.each{|r|\r
@@ -408,8 +180,8 @@ public
       \r
       racine.add(REXML::Element::new('duree').add_text(@duree.to_s))\r
 \r
       \r
       racine.add(REXML::Element::new('duree').add_text(@duree.to_s))\r
 \r
-      racine.add(REXML::Element::new('critiquePresse').add_text(@critiquePresse.to_s))\r
-      racine.add(REXML::Element::new('critiqueSpectateur').add_text(@critiqueSpectateur.to_s))\r
+      racine.add(REXML::Element::new('critiquePresse').add_text(@critiquePresse))\r
+      racine.add(REXML::Element::new('critiqueSpectateur').add_text(@critiqueSpectateur))\r
       \r
       genres = REXML::Element::new('genres')\r
       @genres.each{|g|\r
       \r
       genres = REXML::Element::new('genres')\r
       @genres.each{|g|\r
@@ -417,9 +189,17 @@ public
       }      \r
       racine.add(genres) \r
       \r
       }      \r
       racine.add(genres) \r
       \r
-      racine.add(REXML::Element::new('synopsis').add_text(@synopsis))\r
+      synopsisElement = REXML::Element::new('synopsis')\r
+      unless @synopsis.nil?\r
+         @synopsis.split("\n").each{|s|\r
+            next if s =~ /^\s*$/\r
+            synopsisElement.add(REXML::Element::new('p').add_text(s))\r
+         }\r
+      end         \r
+      racine.add(synopsisElement)\r
+      \r
       budgetElement = REXML::Element::new('budget')\r
       budgetElement = REXML::Element::new('budget')\r
-      budgetElement.add_text(@budget.to_s)\r
+      budgetElement.add_text(@budget)\r
       budgetElement.add_attribute('unite', @budgetUnite)\r
       racine.add(budgetElement)\r
       \r
       budgetElement.add_attribute('unite', @budgetUnite)\r
       racine.add(budgetElement)\r
       \r