Greasy Fork

Amazonを基点に好みに合う漫画を探しやすくする

Amazonの本の詳細画面に書名や著者名で類似漫画検索、Web漫画アンテナ、試し読み、Calilを検索するリンクを追加します Shift+L:calil検索都道府県変更 .:上限価格指定 %:割引率指定

目前为 2019-11-22 提交的版本。查看 最新版本

// ==UserScript==
// @name         Amazonを基点に好みに合う漫画を探しやすくする
// @description  Amazonの本の詳細画面に書名や著者名で類似漫画検索、Web漫画アンテナ、試し読み、Calilを検索するリンクを追加します Shift+L:calil検索都道府県変更 .:上限価格指定 %:割引率指定
// @version      0.5
// @match  *://ruijianime.com/comic/ruiji/ruiji.php\?title=*
// @match  *://ruijianime.com/comic/keyword/*
// @match  *://ruijianime.com/comic/title/*
// @match  *://ruijianime.com/*
// @match  *://www.amazon.co.jp/*
// @match  *://webcomics.jp/*
// @match  *://www.suruga-ya.jp/search\?*
// @match  *://calil.jp/local/search\?*
// @match  *://www.amazon.co.jp/s/*
// @match  *://seiga.nicovideo.jp/comic/*
// @match  *://seiga.nicovideo.jp/watch/mg*
// @match  *://web-ace.jp/*
// @match  *://sokuyomi.jp/product/*
// @match  *://sinkan.net/*
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @require https://code.jquery.com/jquery-3.4.1.min.js
// @namespace https://greasyfork.org/users/181558
// ==/UserScript==

(function() {

  if (location.href.match(/:\/\/shinkan\.net/)) { // 「新しいタブで開く」指定を外す
    for (var i = eleget('//a[@target="_blank"]').snapshotLength; i--;) ele.snapshotItem(i).removeAttribute("target");
    return;
  }

  var calilpref = pref("calilpref") || "tokyo";
  var webmangaantena = '<a href="https://webcomics.jp/search?q=***">Web漫画アンテナ</a>';
  var webmangaantenasakusha = '<a href="https://webcomics.jp/search?q=***">Web漫画アンテナ</a>';
  var tameshiyomi = '<a href="https://duckduckgo.com/?q=!ducky+***%20%E8%A9%A6%E3%81%97%E8%AA%AD%E3%81%BF%20-dokidokivisual.com">試し読み</a>';

  var ruijimanga = '<a href="http://ruijianime.com/comic/ruiji/ruiji.php?title=***">類似漫画検索</a>';
  var ruijianime = '<a href="http://ruijianime.com/main/ruiji.php?title=***">類似アニメ検索</a>';
  var caariru = '<a href="https://calil.jp/local/search?csid=' + calilpref + '&q=***"onclick="arguments[0].stopPropagation()">Calil</a>';
  var amazon = '<a href="https://duckduckgo.com/?q=!ducky+***+amazon">Amazon</a>';

  var linkStyle = " style=' background-color:#ffffff; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; font-size:14px; font-weight:normal; color:#606060; margin:0px 2px;  text-decoration:none; text-align:center; padding:0px 7px 1px; border:outset #909090 1px; border-radius:5px; background: linear-gradient(#fefefe, #f4f4f4); ";

  //AmazonでShift+LでCalil都道府県変更
  document.addEventListener("keydown", function(e) {
      if (/input|textarea/i.test(e.target.tagName) || location.href.indexOf("amazon") == -1) return;
      if (e.shiftKey && String.fromCharCode(e.which).toLowerCase() == "l") {
        calilpref = window.prompt("calil検索する図書館の都道府県名を入力してください(例:tokyo)\r\n\r\n選択肢:\r\naichi akita aomori chiba ehime fukui fukuoka fukushima gifu gunma hiroshima hokkaido hyogo ibaraki ishikawa iwate kagawa kagoshima kanagawa kochi kumamoto kyoto mie miyagi miyazaki nagano nagasaki nara niigata oita okayama okinawa osaka saga saitama shiga shimane shizuoka tochigi tokushima tokyo tottori toyama wakayama yamagata yamaguchi yamanashi\r\n\r\n(参照)https://calil.jp/local/", calilpref) || "tokyo";
        pref("calilpref", calilpref);
        location.reload();
      }
    },
    false);

  document.addEventListener("keydown", function(e) {
      if (/input|textarea/i.test(e.target.tagName) || location.href.indexOf("amazon.co.jp/s?") == -1) return;
      //Amazon検索で[.]で価格上限で絞り込み
      if (e.which === 190) {
        var input = proInput("価格上限(\\)", "0", 0);
        location.href = location.href.replace(/&high-price=.*(?=&)|&high-price=.*(?=$)|(&rh=|%2C)p_36%3A-\d*/, "") + (input > 0 ? "&high-price=" + input : "");
      }
      //Amazon検索で[%]で割引率で絞り込み
      if (e.shiftKey && String.fromCharCode(e.which).toLowerCase() == "5") {
        var input = proInput("割引率(0-99\%)", "0", 0, 100);
        location.href = location.href.replace(/&pct-off=.*(?=&)|&pct-off=.*(?=$)|(&rh=|%2C)p_8%3A\d*-/, "") + (input > 0 ? "&pct-off=" + input + "-" : "");
      }
    },
    false);

  addLinks();
  if (location.href.match(/webcomics|ruijianime|suruga-ya/)) document.addEventListener("AutoPagerize_DOMNodeInserted", addLinks); //ページ継ぎ足しアドオンに対応
  if (location.href.indexOf("calil") != -1) setInterval(calilWiden, 2500);
  return;

  //実際にリンクを付ける
  function addLinks() {

    //前回つけたリンクがあれば除去する
    var ele = eleget("//a[@class='ruijiSc']");
    for (var i = ele.snapshotLength; i--;) {
      ele.snapshotItem(i).parentNode.removeChild(ele.snapshotItem(i));
    }

    if (location.href.indexOf("web-ace") != -1) {
      ele2links("//div[@id='viewerPc' and @class='container container2 container3']/h2|//div[@class='credit']/h1", "", "", [ruijimanga, webmangaantena, tameshiyomi], "float: right;color:#0000ff;", "", /【.*】(?=$)/);
      ele2links("//p[@class='author']/span", "", "", [webmangaantena], " ", "", /漫画:|原作:|キャラクター原案:/);
    }
    if (location.href.indexOf("seiga.nicovideo.jp/comic/") != -1) {
      ele2links('//div[@class="main_title"]/h1', "", "", [ruijimanga]);
      //      ele2links('//div[@class="author"]/h3/span', "", "", [webmangaantena], "");
    }
    if (location.href.indexOf("seiga.nicovideo.jp/watch/mg") != -1) {
      ele2links('//span[@class="manga_title"]/a', "", "", [ruijimanga, webmangaantena]);
      //      ele2links('//span[@class="author_name"]', "", "", [webmangaantena], "");
    }
    if (location.href.indexOf("sokuyomi") != -1) {
      ele2links('//div[@class="author"]/a', "", "", [webmangaantena]);
    }
    if (location.href.indexOf("webcomics") != -1) {
      ele2links('//div[@class="entry-title"]/a', "", "", [ruijimanga, tameshiyomi]);
      ele2links('//div[@class="comic-title"]/h2/a', "", "", [ruijimanga, tameshiyomi]);
      ele2links("//div[@class='comic-author']", "", "", [webmangaantenasakusha], "", "作者: ", /作者:\s?|著者:\s?/)
    }

    if (location.href.indexOf("ruijianime.com/comic/") != -1) {
      ele2links("//div[@class='origin_one']/h2/a", "", "", [webmangaantena, tameshiyomi]);
      ele2links("//div[@class='sm_one']/h2/a", "", "", [ruijimanga, webmangaantena, tameshiyomi]);
      ele2links('.//p[@class=\"author\"]/span|.//p[@class="date ruiji_date"]/a|.//p[@class="date ruiji_date"]/span[@class="matched"]|.//p[@class="date ruiji_date"]/span[@class="no_matched"]', "", "", [webmangaantenasakusha], "");
      ele2links("//div[@id='wrap']/article/div[@class='sm_one_tag_search easy_tag']/h2/a", "", "", [ruijimanga, webmangaantena, tameshiyomi]);
      ele2links("//div[@class='sm_one_tag_search recent_tag']/h2/a|//div[@class='now_one']/h2/a", "", "", [ruijimanga, webmangaantena, tameshiyomi]);
      ele2links('//div[@class="sm_one_tag_search"]/h2/a/strong', "", "", [ruijimanga, webmangaantena, tameshiyomi]);
    }

    if (location.href.indexOf("ruijianime.com/main/") != -1) { // 類似アニメ検索
      ele2links("//div[@class='sm_one']/h2/a", "", "", [ruijianime]);
      ele2links("//div[@id='wrap']/article/div[@class='sm_one_tag_search easy_tag']/h2/a", "", "", [ruijianime]);
      ele2links("//div[@class='sm_one_tag_search recent_tag']/h2/a|//div[@class='now_one']/h2/a", "", "", [ruijianime]);
      ele2links('//div[@class="sm_one_tag_search"]/h2/a/strong', "", "", [ruijianime]);
    }

    if (location.href.indexOf("suruga-ya") != -1) {
      ele2links("//p[@class='title']/a", "", "", [amazon]);
    }
    if (location.href.indexOf("amazon") != -1) { // Amazon

      var cusRev = eleget0('//span[@id="acrCustomerReviewText"]'); // サクラチェッカー
      var amazonDP = location.href.match(/\/(dp|gp\/product)\/(.{10})/) || [];
      if (amazonDP[2]) var amazonURL = "https://www.amazon.co.jp" + amazonDP[0];
      if (cusRev && amazonURL) $(cusRev).parent().after('<a rel=\"noopener noreferrer nofollow\" title=\"' + amazonDP[2] + '\" ' + linkStyle + '\' href="https://sakura-checker.jp/search/' + amazonDP[2] + '">サクラチェッカー</a>')

      // 著者名の下に出版社名を書き写す
      var ele = eleget0("//li[(b/text()='出版社:')]");
      if (ele) {
        var choshanoshita = eleget0('//div[@id="bylineInfo"]|//div[3]/div[@class="a-spacing-none"]');
        var pub = document.createElement("div");
        if (pub && ele) {
          var pubname = ele.innerText.replace(/出版社: | \(.*/g, "");
          pub.innerHTML = "<span style='cursor:pointer;' title='クリックすると\"" + pubname + "\"をクリップボードにコピー" + "' onclick='var a = document.createElement(\"textarea\"); a.value = \"" + pubname + "\"; document.body.appendChild(a); a.select(); document.execCommand(\"copy\"); a.parentElement.removeChild(a);'>" + pubname + "</span> ";
          choshanoshita.appendChild(pub);
        }
      }
      var isbn = document.body.innerText.match(/ISBN-10: (\d\d\d\d\d\d\d\d\d[\dX])/m); // ISBN-10を書き写す
      if (isbn) {
        isbn = isbn[1];
        var choshanoshita = eleget0('//div[@id="bylineInfo"]|//div[3]/div[@class="a-spacing-none"]');
        var isbnele = document.createElement("div");
        if (isbnele) {
          isbnele.innerHTML = "<span style='cursor:pointer;'  title='クリックすると\"" + isbn + "\"をクリップボードにコピー" + "' onclick='var a = document.createElement(\"textarea\"); a.value = \"" + isbn + "\"; document.body.appendChild(a); a.select(); document.execCommand(\"copy\"); a.parentElement.removeChild(a);'>ISBN-10: <span id=\"aisbn10\">" + isbn + "</span></span>";
          choshanoshita.appendChild(isbnele);
        }
      }

      var cate = "";
      var cateEle = eleget0('//span[@class="nav-a-content"]');
      if (cateEle) cate += cateEle.innerText.trim();
      if (!cate) { var cateEle = eleget0('//h1[@id="title"]/span[2]'); if (cateEle) cate += cateEle.innerText.trim(); }
      //      if (cate == "本" || cate == "Kindleストア" || cate == "Kindle本") { //カテゴリが本かkindleなら

      //      console.log(cate);
      if (cate.match(/本|Kindleストア|Kindle本|単行本|Kindle版|文庫|コミック|新書|雑誌/)) { //カテゴリが本かkindleなら
        var amagen = (
          eleget0("//div[@id='wayfinding-breadcrumbs_feature_div']/ul").innerText +
          eleget0("//span[@id='productTitle']").innerText +
          eleget0("//span[@id='ebooksProductTitle']").innerText +
          eleget0('//span[@class="a-button-inner"]/a/span[contains(text(),"コミック")]').innerText +
          eleget0('//span[@class="a-size-medium a-color-secondary a-text-normal"]').innerText).replace(/[\r\n]/g, "");
        if (amagen) {
          var iszasshi = (amagen.match(/雑誌/) != null)
          var comandz = iszasshi ? "comORz" : "";
          if (amagen.match(/コミック(?!・ラノベ)|Kindle本›マンガ|COMICS|漫画文庫/gi) != null && !iszasshi) {
            ele2links("//span[@id='productTitle']", " ", "comORz", [ruijimanga, webmangaantena, tameshiyomi]);
            ele2links("//span[@id='ebooksProductTitle']", " ", "comORz", [ruijimanga, webmangaantena, tameshiyomi]);
            ele2links('//span[@class="author notFaded"]/span/a[@class="a-link-normal contributorNameID"]', "", "comORz", [webmangaantena], "");
            ele2links('//span[@class="author notFaded"]/span/a[@class="a-link-normal contributorNameID cleaned"]', "", "comORz", [webmangaantena], ""); // General URL Cleanerに対応
            ele2links('//span[@class="author notFaded"]/a[@class="a-link-normal"]', "", "comORz", [webmangaantenasakusha], "")
            ele2links('//span[@class="author notFaded"]/a[@class="a-link-normal cleaned"]', "", "comORz", [webmangaantenasakusha], "") // General URL Cleanerに対応
            ele2links("//span[@id='ebooksProductTitle']", " ", "comORz", [caariru]);
            ele2links("//span[@id='productTitle']", " ", "comORz", [caariru]);
          } else {
            ele2links("//span[@id='ebooksProductTitle']", " ", comandz, [caariru]);
            ele2links("//span[@id='productTitle']", " ", comandz, [caariru]);
          }
          ele2links('//span[@class="author notFaded"]/span/a[@class="a-link-normal contributorNameID"]', "", "calilAuthor", [caariru], "");
          ele2links('//span[@class="author notFaded"]/span/a[@class="a-link-normal contributorNameID cleaned"]', "", "calilAuthor", [caariru], ""); // General URL Cleanerに対応
          ele2links('//span[@class="author notFaded"]/a[@class="a-link-normal"]', "", "calilAuthor", [caariru], "");
          ele2links('//span[@class="author notFaded"]/a[@class="a-link-normal cleaned"]', "", "calilAuthor", [caariru], ""); // General URL Cleanerに対応
          ele2links("//span[@id='aisbn10']", "", "", [caariru], "");
        }
      }
    }

    // 「新しいタブで開く」指定を外す
    var ele = eleget('//a[@target="_blank"]');
    for (var i = ele.snapshotLength; i--;) ele.snapshotItem(i).removeAttribute("target");

    return;
  }

  function eleget0(xpath) {
    var ele = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    return ele.snapshotLength > 0 ? ele.snapshotItem(0) : "";
  }

  function eleget(xpath) {
    return document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  }

  function ele2links(xpath, cutchar1, cutchar2, urlA, styleadd, cutchar3, deleteRE) {

    var ele = eleget(xpath);
    if (ele.snapshotLength == 0) return;
    for (var j = 0; j < urlA.length; j++) {
      //    var ele = eleget(xpath);
      var url = urlA[j];
      styleadd = styleadd === undefined ? "float: right;" : styleadd;

      for (var i = ele.snapshotLength; i--;) {
        if (ele.snapshotItem(i).dataset.ruijisc == "ruijisc") continue;
        var text = ele.snapshotItem(i).innerText;
        if (cutchar3 != "")
          if (text.indexOf(cutchar3) != -1) text = text.substr(text.indexOf(cutchar3) + cutchar3.length);
        if (cutchar1 != "") {
          var splitPos = text.search(cutchar2 == "comORz" ? /-|-|―|~|:|:|\(|(| \d| \d|(\s| )([0-9]|[0-9])/ : /―|~|\(|(/);
          if (splitPos != -1) text = text.substr(0, splitPos);
        }

        if (url == webmangaantenasakusha) text = text.replace(/\/|/|\,|、/gmi, " OR ").replace(/先生|原作|原案|脚本|著|著者|漫画|作画|イラスト|キャラクター|画[::\//]|作[::\//]|絵[::\//]|構成|協力|[::]|[\((][^)\)]*[)\)]|=/gmi, "").replace(/ /g, " ").replace(/^ OR | OR $/gmi, "").trim();
        if (url == ruijimanga) text = text.replace("!", "!").replace("?", "?");
        if (url == caariru) text = text.replace(/[\s :]/g, "");
        if (url == amazon) text = text.replace(/<<.*>>|ランクB)|\[ランクB\]|ランクB\/★未完\)|★ランクB未完\)|ランクB\)/gi, "");
        text = text.replace(/\[雑誌\]/, ""); //amazon
        text = text.replace(deleteRE, ""); //web-ace

        text = text.trim();
        var link = document.createElement("a");
        var url2 = url.replace("***", encodeURI(text.replace(/\#/gm, ""))).replace("<a ", "<a class=\"ruijiSc\" title=\"" + text.replace(/\"/gm, "\\\"").replace(/\'/gm, "\\\'") + "\" data-ruijisc=\"ruijisc\" rel=\"noopener noreferrer nofollow\" " + linkStyle + styleadd + "' ");
        ele.snapshotItem(i).parentNode.appendChild(link);
        link.outerHTML = url2;
        link.onclick = "arguments[0].stopPropagation()";
      }
    }
    return;
  }

  // カーリルの表の幅を広げる
  function calilWiden() {
    var ele = eleget("//div[@class='wrap']");
    for (var i = ele.snapshotLength; i--;) ele.snapshotItem(i).style.maxWidth = "1400px";
    var ele = eleget("//div[@class='target']/h4");
    for (var i = ele.snapshotLength; i--;) {
      ele.snapshotItem(i).style.maxWidth = "1400px";
      ele.snapshotItem(i).style.fontSize = "100%";
    }
    var ele = eleget("//div");
    for (var i = ele.snapshotLength; i--;) ele.snapshotItem(i).style.fontSize = "100%";
    var ele = eleget("//div[@class='target']");
    for (var i = ele.snapshotLength; i--;) ele.snapshotItem(i).style.padding = "20px 0px 0px";
    return;
  }

  function proInput(prom, defaultval, min, max = Number.MAX_SAFE_INTEGER) {
    return Math.min(Math.max(
      Number(window.prompt(prom, defaultval).replace(/[A-Za-z0-9]/g, function(s) {
        return String.fromCharCode(s.charCodeAt(0) - 65248);
      }).replace(/[^-^0-9^\.]/g, "")), min), max);
  }

  function pref(name, store = undefined) { // pref(name,data)で書き込み(数値でも文字列でも配列でもオブジェクトでも可)、pref(name)で読み出し
    var domain = (location.href.match(/^https?:\/{2,}(.*?)(?:\/|\?|#|$)/)[1] || location.href);
    if (store === undefined) { // 読み出し
      let data = GM_getValue(domain + " ::: " + name)
      if (data == undefined) return store; // 値がないなら終わり
      if (data.substr(0, 1) === "[") { // 配列なのでJSONで返す
        try { return JSON.parse(data || '[]'); } catch (e) {
          console.log("データベースがバグってるのでクリアします\n" + e);
          pref(name, []);
          return;
        }
      } else return data;
    }
    if (store === "" || store === [] || store === null) { // 書き込み、削除
      GM_deleteValue(domain + " ::: " + name);
      return store;
    } else if (typeof store === "string") { // 書き込み、文字列
      GM_setValue(domain + " ::: " + name, store);
      return store;
    } else { // 書き込み、配列
      try { GM_setValue(domain + " ::: " + name, JSON.stringify(store)); } catch (e) {
        console.log("データベースがバグってるのでクリアします\n" + e);
        pref(name, "");
      }
      return store;
    }
  }

})();