Greasy Fork

YouTube SparkBars(Like/Dislike)

動画へのリンクに「高く評価」された比率を示すバーを表示します。

当前为 2017-06-02 提交的版本,查看 最新版本

// ==UserScript==
// @name        YouTube SparkBars(Like/Dislike)
// @namespace   knoa.jp
// @description 動画へのリンクに「高く評価」された比率を示すバーを表示します。
// @include     https://www.youtube.com/*
// @version     1
// @grant       none
// 多くが時間の無駄となる評価の低い動画を避ける手段を提供しないYouTubeのUIが悪い。
// とはいえYouTubeに過度な負荷は与えないように、動作させるページは必要最低限に。(homeは対象が多くて重い)
// Ajax追加要素への対応は保留。
// ==/UserScript==

(function () {
  const SCRIPTNAME = 'SparkBars';
  const DELAY = 1000;/*動画情報を読みに行く間隔(ms)(短すぎるとYouTubeに弾かれやすくなる)*/
  const VIEWS = {/*要素定義*/
    example: ['items', 'anchor', 'insertParent', 'insertAfter'],
    home: ['#feed ul > li.yt-shelf-grid-item', 'a', 'div.yt-lockup-content', 'div.yt-lockup-meta'],
    results: ['#results ol.item-section > li', 'div.yt-lockup-video a.yt-uix-tile-link', 'div.yt-lockup-meta', 'ul.yt-lockup-meta-info'],
    watch: ['#watch7-sidebar li.video-list-item', 'a.content-link', 'a.content-link', 'span.view-count'],
  };
  const SPARKBARS = 'div.video-extras-sparkbars';/*動画ページ内のSparkBar*/
  let href, view, items;
  let core = {
    initialize: function(){
      console.log(SCRIPTNAME, 'initialize...');
      window.setInterval(function(){
        if(href === location.href) return;/*URLが変わっていなければ何もしない*/
        href = location.href;
        /* URLに応じた定義で処理実施 */
        switch(true){
          case(href.match(/^https:\/\/www\.youtube\.com\/$/)!==null):
            view = VIEWS.home;
            break;
          case(href.match(/^https:\/\/www\.youtube\.com\/results\?/)!==null):
            view = VIEWS.results;
            break;
          case(href.match(/^https:\/\/www\.youtube\.com\/watch\?/)!==null):
            view = VIEWS.watch;
            break;
          default:
            return;
        }
        core.getSparkBars(10);
      }, 1000);
    },
    getSparkBars: function(retry){
      //console.log(SCRIPTNAME, 'getSparkBars...', view, href);
      /* 各動画リンクに対してひとつずつ処理 */
      items = document.querySelectorAll(view[0]);
      if((items === null || items.length === 0) && retry){/*動画が取得できなければリトライ*/
        window.setTimeout(function(){
          core.getSparkBars(retry--);
        }, 1000);
        return;
      }
      /*(delay)msずつずらして動画ページを読みに行く*/
      for(let i = 0, delay = 0; items[i]; i++){
        core.getSparkBar(items[i], delay += DELAY, href);
      }
    },
    getSparkBar: function(item, delay, href){
      //console.log(SCRIPTNAME, 'getSparkBar...', item);
      let a = item.querySelector(view[1]);
      if(a === null) return;/*動画へのリンクがなければ処理しない*/
      window.setTimeout(function(){
        if(href !== location.href) return;/*URLが変わっていれば処理は中止*/
        let xhr = new XMLHttpRequest();
        xhr.responseType = 'document';
        xhr.open('GET', a.href);
        xhr.onreadystatechange = function () {
          if (xhr.readyState == 4 && xhr.status == 200) {
            if(href !== location.href) return;/*URLが変わっていれば処理は中止*/
            let sparkbars = xhr.response.querySelector(SPARKBARS);
            if(sparkbars === null) return;/*コメントなしの動画は評価もなし*/
            item.querySelector(view[2]).insertBefore(sparkbars, item.querySelector(view[3]).nextElementSibling);
          }
        };
        xhr.send();
      }, delay);
    },
  };
  core.initialize();
}) ();