ČSFD Extended

Rozšíření profilů filmů na ČSFD o některé funkce jako jsou odkazy na torrenty či hodnocení IMDB.

当前为 2016-03-26 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         ČSFD Extended
// @namespace    CSFD-E
// @version      0.4.0
// @description  Rozšíření profilů filmů na ČSFD o některé funkce jako jsou odkazy na torrenty či hodnocení IMDB.
// @author       Jakub Rychecký <[email protected]>
// @license      WTFPL 2
// @include      *csfd.cz/film/*
// ==/UserScript==








var csfd = new Csfd(); // Instance třídy pro práci s profilem filmu na ČSFD
var omdb = new OmdbApi(csfd.parseCsfdImdbCode()); // Instance třídy pro práci s API OMDB a stažení informací o filmu
var imdb = new Imdb(csfd.parseCsfdImdbCode()); // Instance třídy s informacemi z IMDB
var metacritic = new Metacritic(); // Instance třídy s informacemi z Metacritic
var tomato = new Tomato(); // Instance třídy s informacemi z RottenTomatoes

var html = new Html(); // Instance třídy pro práci s HTML a úpravou profilu filmu dle získaných dat
var floating = new Floating(); // Instance třídy spravující plovoucí okno s náhledem posterů či fotek tvůrců



html.cssInit(); // Přidání externího CSS do stránky


csfd.parseCsfdNameYear(); // Parsuje název filmu z profilu ČSFD.
csfd.parseCsfdRating(); // Parsuje hodnocení ČSFDs

html.ratingTable(); // Předělání tabulky hodnocení na profilu filmu
html.toolbar(); // Vytvoření tlačítek pro rychlé vyhledávání na profilu filmu

omdb.fetchOmdbData(); // Stažení dat z API OMDB


floating.init(); // Inicializace plovoucího okna
floating.bindPoster(); // Bindování eventu najetí kurzoru na poster
floating.bindCreator(); // Bindování eventu najetí kurzoru na odkaz na profil tvůrce







/*

console.log(csfd);
console.log(omdb);
console.log(imdb);
console.log(metacritic);
console.log(tomato);
console.log(html);

*/







/**
 * @class Csfd
 * @classdesc Parsuje a zpracovává základní údaje z ČSFD profilu filmu.
 */

function Csfd(){
  
  /** 
   * Originální název filmu
   * @type {string}
   */
  this.name;

  /**
   * Rok vzniku filmu
   * @type {integer}
   */
  this.year;

  /**
   * Hodnocení ČSFD v procentech
   * @type {integer}
   */
  this.rating;

  /**
   * Počet hodnocení na ČSFD
   * @type {integer}
   */
  this.votes;    
  
  
  
  
  
  /**
   * Parsuje název filmu z profilu ČSFD.
   * @return {undefined}
   */
    
  this.parseCsfdNameYear = function(){
    var title = $('meta[property=\'og:title\']').attr('content'); // Získání popisu ČSFD profilu z metatagu Open Graph (OG) http://ogp.me/
    title = title.replace(/\(TV seriál\)/, ''); // Odstranění označení TV seriálů z názvu
    title = title.replace(/\(TV film\)/, ''); // Odstranění označení TV filmů z názvu
    var title_regex = title.match(/(.+)\((\d{4})\)/); // Rozdělení na název a rok v závorce
     
     
    this.name = title_regex[1]; // Název filmu
    this.name = this.name.replace(/.+\//, ''); // Získání čehokoliv před lomítkem (= originální název)
    this.name = $.trim(this.name); // Oříznutí mezer názvu filmu
    
    
    this.year = parseInt(title_regex[2]); // Rok názvu jako integer
  }
    
  
  
  
    
  /**
   * Parsuje procentuální hodnocení a počet hlasů z profilu ČSFD.
   * @return {undefined}
   */
  
  this.parseCsfdRating = function(){
    this.rating = $('meta[itemprop="ratingValue"]').attr('content'); // Získání procentuálního hodnocení z metatagů
    this.rating = parseInt(this.rating); // Hodnocení v procentech jako integer
    
    this.votes = $('meta[itemprop="ratingCount"]').attr('content'); // Získání počtu hlasů z metatagů
    this.votes = parseInt(this.votes); // Počet hlasů jako integer
  }
    
    
    
    
 
  /**
   * Parsuje kód filmu na IMDB z tlačítka IMDB na profilu filmu na ČSFD.
   * @return {String} Kód filmu na IMDB
   */
    
  this.parseCsfdImdbCode = function(){
    var imdb_url =  $('a[data-ga-event="imdb-film|click|logged"]').attr('href'); // Získání odkazu z tlačítka IMDB
    
    var imdb_code = imdb_url.match(/(tt\d+)/); // Extrahování kódu filmu na IMDB
    
    return imdb_code[1]; // Vrací extrahovaný kód IMDB
  }
};











/**
 * @class OmdbApi
 * @classdesc Stahuje, parsuje a zpracovává údaje o filmu staženém z OMDB API http://www.omdbapi.com/
 * @param {string} imdb_code IMDB kód filmu
 */

function OmdbApi(imdb_code){
  
  /**
   * IMDB kód filmu
   * @type {string}
   */
  this.imdb_code = imdb_code;
  
  /**
   * Počet hodin, za kolik expiruje cache údajů z OMDb
   * @type {integer}
   */
  this.cache_expire = 48;
  
  /**
   * Objekt odpovědí OMDb API s údaji o filmu
   * @type {object}
   */
  this.response;
  
  /**
   * Jé. :)
   * @type OmdbApi
   */
  var parent = this;
 
 
 
 
    
  /**
   * Nastavuje cache odpovědi z OMDb do local storage pod kódem IMDB v JSON.   
   * @return {String} Kód filmu na IMDB
   */
    
  this.setCache = function(){
    localStorage.setItem(parent.imdb_code, JSON.stringify(parent.response)); // Nastavení odpovědi z OMDb do local storage pod kódem IMDB
  }
 
 
 
 
 
  /**
   * Snaží se získat odpověď OMDb API z cache v local storage.
   * @returns {Boolean} Byly nalezeny informace z cache?
   */
 
  this.getCache = function(){
    var response = localStorage.getItem(this.imdb_code); // Získání údajů z cache tam, kde by měly být   
    response = $.parseJSON(response); // Snaha naparsovat JSON obsah cache

    if(response == null || response.timestamp <= $.now() - parent.expire_cache * 60 * 60){ // Pokud nebylo nic nalezeno, či pokud je to starší než limit...
      return false; // Cache miss!
    }else{
      this.response = response; // Nastavení naparsované odpovědi do objektu
      return true; // Cache hit!
    }
  }





  /**
   * Snaží se získat údaje z cache, při neúspěchu stahuje údaje z OMDb API.
   * @returns {undefined}
   */
 
  this.fetchOmdbData = function(){
    var cache_hit = this.getCache(); // Cache miss nebo hit?
         
    if(!cache_hit){ // Pokud údaje z cache nejsou dostupné...
      var request = $.ajax({
        method: 'GET',
        url: 'http://www.omdbapi.com/',
        data: { // Dotaz pro OMDb API
          i: this.imdb_code,
          tomatoes: 'true',
          r: 'json'
        }
      });

      request.done(function(response){ // Po stažení odpovědi...
          response.timestamp = $.now(); // Přidání aktuálního unixového času do objektu odpovědi
          parent.response = response; // Nastavení
          parent.setCache();        
          parent.processOmdbData();
      });   
    }else{
      this.processOmdbData();  
    }
  }
 
 
  this.processOmdbData = function(){
    var response = this.response;

    imdb.rating = parseFloat(response.imdbRating);
    imdb.votes = response.imdbVotes.replace(',', '');
    imdb.votes = parseInt(imdb.votes);

    metacritic.metascore = parseInt(response.Metascore);

    tomato.meter = parseInt(response.tomatoMeter);
    tomato.rating = parseFloat(response.tomatoRating);
    tomato.reviews = parseInt(response.tomatoReviews);
    tomato.userMeter = parseInt(response.tomatoUserMeter);
    tomato.userRating = parseFloat(response.tomatoUserRating);
    tomato.userReviews = parseInt(response.tomatoUserReviews);
    tomato.url = response.tomatoURL;
     
    html.fillRatingTable(); 
  }
};











function Imdb(imdb_code){
  this.imdb_code = imdb_code;   
  this.rating;
  this.votes;
    

 
 
  this.insertRatingHtml = function(){
    if(this.rating > 0){
      $('#csfd-e-rating .imdb').show();
    }
     
     $('#csfd-e-rating .imdb .rating').html(imdb.rating.toLocaleString().replace('.', ','));
     $('#csfd-e-rating .imdb .votes').html(imdb.votes.toLocaleString()+'&nbsp;hlasů'); 
     
     $('#csfd-e-rating .imdb a').attr('href', this.link());
  }
 
  this.link = function(){
    return 'http://www.imdb.com/title/'+this.imdb_code+'/'; 
  }
 
};











function Metacritic(){
  this.metascore;



  this.insertRatingHtml = function(){
    if(this.metascore > 0){
      $('#csfd-e-rating .metacritic').show();   
    }
     
    $('#csfd-e-rating .metacritic .rating').html(this.metascore);
     
    $('#csfd-e-rating .metacritic a').attr('href', this.link());
  }
 
 
  this.link = function(){
    return 'http://www.imdb.com/title/'+imdb.imdb_code+'/criticreviews'; 
  }
 
};











function Tomato(){
  this.meter;
  this.rating;
  this.reviews;
  this.userMeter;
  this.userRating;
  this.userReviews;
  this.url;
    
 
  this.insertRatingHtml = function(){
    if(this.meter > 0){
      $('#csfd-e-rating .tomato').show();   
    }
     
    $('#csfd-e-rating .tomato-critic .rating').html(this.meter+'&nbsp;%');
    $('#csfd-e-rating .tomato-critic .votes').html(this.reviews.toLocaleString()+'&nbsp;recenzí');
     
    $('#csfd-e-rating .tomato-audience .rating').html(this.userMeter+'&nbsp;%');
    $('#csfd-e-rating .tomato-audience .votes').html(this.userReviews.toLocaleString()+'&nbsp;hodnocení');
     
    $('#csfd-e-rating .tomato a').attr('href', this.link());
  }
       
  this.link = function(){
    return this.url;   
  }
 
};











function Html(){   
  this.toolbar;
    
    
  this.cssInit = function(){
    var css_url = 'http://csfd-extended.rychecky.cz/css/csfd-extended.css';
    var css_html = '<link rel="stylesheet" type="text/css" href="'+css_url+'" />'; 
    
    $('head').append(css_html);
  }
    
 
 
 
  this.fillRatingTable = function(){
    imdb.insertRatingHtml();
    metacritic.insertRatingHtml();
    tomato.insertRatingHtml();

    this.ratingTableShow();  
  }
 
 
  this.ratingTable = function(){
    var html = '<div id="csfd-e-rating" class="ct-related" style="display: none;">';

    html += '<div class="header"><h3>ČSFD Extended</h3></div>';   


    html += '<div class="content">'; 
     
    html += '<table>';     

    html += '<tr class="imdb" style="display: none;">';
    html += '<td class="favicon"><img src="http://www.google.com/s2/favicons?domain=imdb.com" alt="" /></td>';
    html += '<td class="title"><a href="" class="link" title="Otevřít profil na IMDB">IMDB</a></td>';
    html += '<td class="rating"></td>';
    html += '<td class="votes"></td>';
    html += '</tr>';

    html += '<tr class="metacritic" style="display: none;">';
    html += '<td class="favicon"><img src="http://www.google.com/s2/favicons?domain=metacritic.com" alt="" /></td>';
    html += '<td class="title"><a href="" class="link" title="Otevřít seznam recenzí Metacritic">Metacritic</a></td>';
    html += '<td class="rating"></td>';
    html += '</tr>';

    html += '<tr class="tomato tomato-critic" style="display: none;">';
    html += '<td class="favicon"><img src="http://www.google.com/s2/favicons?domain=rottentomatoes.com" alt="" /></td>';
    html += '<td class="title"><a href="" class="link" title="Otevřít profil na Rotten Tomatoes" >RT: kritici</a></td>';
    html += '<td class="rating"></td>';
    html += '<td class="votes"></td>';
    html += '</tr>';

    html += '<tr class="tomato tomato-audience" style="display: none;">';
    html += '<td class="favicon"><img src="http://www.google.com/s2/favicons?domain=rottentomatoes.com" alt="" /></td>';
    html += '<td class="title"><a href="" class="link" title="Otevřít profil na Rotten Tomatoes">RT: diváci</a></td>';
    html += '<td class="rating"></td>';
    html += '<td class="votes"></td>';
    html += '</tr>'; 

    html += '</table>';
     
     
    html += '<div class="footer">by jaCUBE via <a href="https://greasyfork.org/cs/scripts/15784-%C4%8Csfd-extended">Greasy Fork</a>';
     
     
    html += '</div>';


    $('#rating').after(html);   
  }
 
 
  this.ratingTableShow = function(){
    $('#csfd-e-rating').slideDown();   
  }
 
 
 
 
 
 
  this.creatorPreview = function(){
    $('body a').mouseenter(function(e){
       var link = $(this).attr('href');

       if(link.indexOf('/tvurce/') == -1){
        return false;   
       }

      var request = $.ajax({
        method: 'GET',
        url: link
      });

      request.done(function(response){
        var name = $(response).find('#profile .info h1').text();
        var age =  $(response).find('#profile .info .age').text(); 
        var img =  $(response).find('#profile .image img').attr('src'); 
      });  

      return true;
    });
  }
 
 
 
 
  this.toolbar = function(){
    var name_url = encodeURIComponent(csfd.name);

    var html = '<div id="csfd-e-toolbar">';

    html += '<a href="'+imdb.link()+'" target="_blank">IMDB</a>';
    html += '<a href="https://www.google.cz/search?q='+name_url+'" target="_blank">Google</a>';
    html += '<a href="https://www.youtube.com/results?search_query='+name_url+'" target="_blank">YouTube</a>'; 
    html += '<a href="https://www.reddit.com/search?q='+name_url+'+subreddit%3Amovies+OR+subreddit%3Atelevision+OR+subreddit%3Atrailers&sort=relevance&t=all" target="_blank">Reddit</a>'; // Omezeno na r/movies, r/television a r/trailers
    html += '<a href="https://www.facebook.com/search/pages/?q='+name_url+'" target="_blank">Facebook</a>';
    html += '<a href="http://www.titulky.com/?Fulltext='+name_url+'" target="_blank">Titulky</a>';  
    html += '<a href="http://www.uloz.to/hledej?media=video&protected=notPassword&redir=0&q='+name_url+'" target="_blank">Ulož.to</a>'; 
    html += '<a href="https://www.google.cz/search?q='+name_url+' site:yify-movies.net OR site:yify-movie.com" target="_blank">YIFY</a>';  
    html += '<a href="https://torrentz.eu/search?q='+name_url+'" target="_blank">Torrentz</a>'; 

    html += '</div>';

    $('#profile div.content').prepend(html);  
      
    this.toolbar = $('#csfd-e-toolbar');
    this.toolbar.find('a').css({background: $('#rating').css('background')});
  }

};








function Floating(){
 this.content = '';
 this.floating;   
 this.request;
    
 var parent = this;

    
    
    
    
    
 this.init = function(){
    var html = '<img id="csfd-e-floating" src="" alt="" />';
     
    $('body').append(html);
     
    this.floating = $('#csfd-e-floating');
 }
 
 
  
 this.refresh = function(obj){
   obj.mousemove(function(e){
       parent.floating.css({'top': e.clientY - 150, 'left': e.clientX + 20});  
   });
     
     
   obj.mouseout(function(){
      parent.floating.hide();
      parent.floating.attr('src', '');
      parent.request.abort();
   });  
 }
 
  
 
 
 
 
 this.bindPoster = function(){
   var poster = $('#poster img, #posters img');

   $('#show-all-posters').click(function(){
      parent.bindPoster(); 
   });

     
   poster.mouseenter(function(e){
       var poster_url = $(this).attr('src');
       poster_url = poster_url.replace(/\?.+/, '');
               
       parent.floating.attr('src', poster_url);
       parent.floating.css({'display': 'inline'});  
   });
     
   this.refresh(poster);
 }
 
 
 
 
 
 
 this.bindCreator = function(){
   var links = $('body a');

     
   links.mouseenter(function(e){
     var href = $(this).attr('href');
       
     
     parent.floating.css({'display': 'inline'});  
       
     if(href.indexOf('/tvurce/') == -1){
      return false;   
     }
      
       
    parent.request = $.ajax({
      method: 'GET',
      url: href
    });

    parent.request.done(function(response){
      var img =  $(response).find('#profile .image img').attr('src'); 
        
       parent.floating.attr('src', img);
    });  
      
    return true;
   });
     
     
   this.refresh(links);
 }
 
 
};