Greasy Fork

Greasy Fork is available in English.

copyTorrentToRelated

Copy current torrent row to Related Torrents section

目前为 2017-12-18 提交的版本。查看 最新版本

// ==UserScript==
// @name        copyTorrentToRelated
// @namespace   https://avistaz.to/profile/dryeyes
// @description Copy current torrent row to Related Torrents section
// @match       https://cinemaz.to/torrent/*
// @match       https://avistaz.to/torrent/*
// @version     0.9.1
// @grant       none
// @locale      English (en)
// ==/UserScript==
'use strict';

(function(){
  function injectFunc(fn) {
    var scriptElm = document.createElement('script');
    scriptElm.setAttribute("type", "application/javascript");
    scriptElm.textContent = '(' + fn + ')();';
    //scriptElm.async = false;  didn't help.
    document.body.appendChild(scriptElm); // run the script
    document.body.removeChild(scriptElm); // clean up
  }

  function getNoRelatedTorrentsNode () {
    var noTorrentsFoundNode = document.evaluate('//div[@id="collapseRelatedTorrents"]/div[@class="related-torrents"]/p[normalize-space()="No torrents found!"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return noTorrentsFoundNode;
  }

  function getTableDataNode(tableCaption) {
    var xpathexp = `//tr/td[strong[contains(text(),'${tableCaption}')]]/following-sibling::td`;
    var tableDataNode = document.evaluate(xpathexp, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    return tableDataNode;
  }

  var cleanedUrl = window.location.href.replace(/(\#.*)$/, '');
  var newTR;    // the copied <tr> element from related torrents query.
  var nRelated; // # of Related Torrents (including current)
  var atLeast;  // "+" if more than one page of torrents otherwise ""

  function addExtraInfo() {
    if (newTR === null)
      return;

    var vidResolutionNode = getTableDataNode('Video Resolution');
    if (vidResolutionNode !== null) {
      var vidRes = vidResolutionNode.innerText.trim().toLowerCase();
      console.log("Video Resolution:", vidRes);
      if (vidRes !== 'unknown') {
        var vidResSpan = document.createElement('span');
        vidResSpan.innerHTML = `<span class="badge-extra">${vidRes}</span>`;
        var tfileDiv = newTR.querySelector('td:nth-of-type(2) > div > div:nth-of-type(2)');
        if (tfileDiv !== null) {
          console.log("Adding vidResSpan:", vidResSpan);
          tfileDiv.appendChild(vidResSpan);
        }
      }
    }

    var tFileDivNode = newTR.querySelector('div.torrent-file');

    var descriptionNode = getTableDataNode('Description');
    var descriptionLength = "0";
    if (descriptionNode !== null && descriptionNode.innerText.length !== 0) {
      descriptionLength = (descriptionNode.innerText.length / 1024.0).toFixed(1);
    }

    var descriptionSpan = document.createElement('span');
    descriptionSpan.innerHTML = `<span class="badge-extra"><a href="#video-quality-row"><i class="icon-like fa fa-file-text-o" data-toggle="tooltip" title="Description length"></i> ${descriptionLength}K</a></span>`;

    tFileDivNode.appendChild(descriptionSpan);

    var screenShotsSmallNode = document.evaluate('//div[@data-target="#collapseScreens"]/small', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    if (screenShotsSmallNode !== null) {
      console.log("Screens:", screenShotsSmallNode);
      var nScreens = screenShotsSmallNode.innerText.match(/(\d+)\s+image?/i)[1];
      var screenSpan = document.createElement('span');
      //screenSpan.innerHTML = `<span class="badge-extra"><a href="#screenshots-panel"><i class="icon-like fa fa-picture-o" data-toggle="tooltip" title="# of screenshots"></i> ${nScreens}</a></span>`;
      screenSpan.innerHTML = `<span class="badge-extra"><a href="#thanked-row"><i class="icon-like fa fa-picture-o" data-toggle="tooltip" title="# of screenshots"></i> ${nScreens}</a></span>`;
      // var aNode = screenSpan.querySelector('a');
      // aNode.addEventListener('click', function(){
      //   var screenshotsHeader = screenShotsSmallNode.parentNode;
      //   screenshotsHeader.scrollIntoView(true);
      //   console.log("ScrollIntoView:", screenshotsHeader);
      // }, false);

      tFileDivNode.appendChild(screenSpan);

      var comments = document.querySelectorAll('div#commentsBlock div.comments > ul li');
      console.log("Comments:", comments);
      var commentsSpan = document.createElement('span');
      commentsSpan.innerHTML = `<span class="badge-extra"><a href="#comments-panel"><i class="icon-like fa fa-comment" data-toggle="tooltip" title="# of comments"></i> ${comments.length}</a></span>`;

      tFileDivNode.appendChild(commentsSpan);
    }

    var tagsNode = getTableDataNode('Tags');
    if (tagsNode !== null) {
      var tagsDiv = document.createElement('div');
      var arefs = tagsNode.querySelectorAll('a');
      arefs.forEach(function(item) {
        var tagSpan = document.createElement('span');
        tagSpan.innerHTML = `<span class="badge-extra"><i class="fa fa-tag"></i> <a href="${item.href}" title="${item.title}">${item.innerText}</a></span>`;
        tagsDiv.appendChild(tagSpan);
      });
      tFileDivNode.appendChild(tagsDiv);
    }
  }

  function onMainTorrentLoaded () {
    var i;

    console.log("XMLHttpRequest loaded.");
    var relatedRow = this.response;
    console.log(relatedRow);

    var relatedRows = relatedRow.querySelectorAll("div.table-responsive tbody > tr");
    console.log("Main page torrent rows:", relatedRows);
    console.log("Looking for:", cleanedUrl);

    for (i = 0; i < relatedRows.length; i++) {
      var row = relatedRows[i];
      var anode = row.querySelector("a.torrent-filename");
      if (anode !== null) {
        console.log("Anode:", anode);
        if (anode.href === cleanedUrl) {
          newTR = row.cloneNode(true);
          var tdNode = newTR.querySelector("td:last-of-type");

          var inode = relatedRow.createElement("i");
          inode.innerHTML = `<i class="fa fa-hand-o-left text-red" title="Current Torrent"></i>`;
          tdNode.appendChild(inode);
          console.log("ClonedTR:", newTR);
          break;
        }
      }
    }

    var lastPageLI = document.querySelector("ul.pagination li:nth-last-of-type(2)");
    if (lastPageLI !== null) {
      var nFullPages = Number(lastPageLI.innerText) - 1;
      nRelated = (relatedRows.length*nFullPages);
      atLeast = "+";
    } else {
      nRelated = relatedRows.length;
      atLeast = "";
    }

    addExtraInfo();
  }

  // Download & copy matching torrent row from related torrents url
  function copyRelatedRow() {
    var mainURL = document.querySelector("h3.movie-title > a").href;
    var pieces = mainURL.split("/");
    var site = pieces[2];
    var torrentID = pieces[4].split("-")[0];
    var relatedURL = `https://${site}/movies/torrents/${torrentID}?quality=all`;

    var xhr = new XMLHttpRequest();
    xhr.onload = onMainTorrentLoaded;
    xhr.open("GET", relatedURL);
    xhr.responseType = "document";
    xhr.send();

    console.log("XMLHttpRequest for "+relatedURL+ " sent.");
  }

  var relatedAdded = false;

  function relatedShown () {
    if (relatedAdded)
      return;
    else
      relatedAdded = true;

    console.log("Related shown.", document.readyState);

    var relatedTorrent = document.querySelector("#collapseRelatedTorrents > div.related-torrents > div > table > tbody > tr");

    console.log("Related torrent:", relatedTorrent);
    var noRelatedTorrentsNode = getNoRelatedTorrentsNode();
    if (noRelatedTorrentsNode !== null)
      console.log("After expanded: No related torrents message found.");

    if (relatedTorrent !== null) {
      if (newTR !== undefined) {
        console.log("NewTR:");
        console.log(newTR);

        relatedTorrent.parentNode.insertBefore(newTR, relatedTorrent);
      }
    } else {
      if (noRelatedTorrentsNode !== null) {
        var divElm = document.createElement('div');
        divElm.innerHTML = `
<div class="related-torrents">
 <div class="table-responsive">
  <div class="pull-right"></div>
   <table class="table table-condensed table-striped table-bordered">
    <thead>
    <tr>
    <th class="torrents-icon"></th>
    <th class="torrents-filename">File</th>
    <th><i class="fa fa-download"></i></th>
    <th>Age</th>
    <th>Size</th>
    <th>S</th>
    <th>L</th>
    <th>C</th>
    </tr>
    </thead>
    <tbody>
    </tbody>
   </table>
  <div class="pull-right"></div>
 </div>
</div>
`;
        console.log("About to create new related.");
        var tbody = divElm.querySelector("tbody");
        if (newTR !== undefined) {
          console.log("NewTR:");
          console.log(newTR);
          tbody.appendChild(newTR);
        }

        var grandParent = noRelatedTorrentsNode.parentNode.parentNode;
        grandParent.replaceChild(divElm, noRelatedTorrentsNode.parentNode);
      } else {
        console.log("Ooops. No related torrents AND couldn't find the No Related Torrents message?", document.readyState);
        window.alert("Ooops. No related torrents AND couldn't find the No Related Torrents message?\n\nKeep refreshing page until this alert doesn't appear.");
      }
    }

    var relatedTorrents = document.querySelectorAll("#collapseRelatedTorrents > div.related-torrents > div > table > tbody > tr");
    console.log("relatedTorrents:", relatedTorrents);
    var relatedTorrentsA = document.querySelector('div.panel-heading > strong > a');
    if (relatedTorrentsA !== null) {
      if (nRelated === null) {
        var nTorrents = relatedTorrents.length > 0 ? relatedTorrents.length : 1;
        relatedTorrentsA.innerText += " [" + nTorrents + "]";
      } else {
        relatedTorrentsA.innerText += " [" + nRelated + atLeast + "]";
      }
    }
  }

  // Expose relatedShown() to injected func.
  window.relatedShown = relatedShown; // doesn't work with Greasemonkey 4.1
  //exportFunction(relatedShown, window, {defineAs: "relatedShown"}); // doesn't work in Greasemonkey 3.17, get exportFunction not defined error :(

  // Use script injection so can use jQuery to listen to shown.bs.collapse event which
  //  will be automatically triggered when we click the Related Torrents panel during
  //  load event processing.
  function injectedFunc() {
    console.log("Injected function running");
    var relatedTorrentsDiv = document.querySelector('div#collapseRelatedTorrents');
    console.log ("relatedTorrentsDiv:", relatedTorrentsDiv);

    $(relatedTorrentsDiv).on('shown.bs.collapse', relatedShown); // also works!
  }

  function clickRelated() {
    console.log("Click Related Torrents header.");
    var relatedTorrentsA = document.querySelector('div.panel-heading > strong > a');
    if (relatedTorrentsA !== null) {
      relatedTorrentsA.click();
    }
  }

  function markTableRow(dataName, dataID) {
    var dataNode = getTableDataNode(dataName);
    if (dataNode !== null) {
      dataNode.parentNode.id = dataID;
    }
  }

  function onLoadHandler() {
    console.log("Load event occurred.");
    markTableRow('Video Quality', "video-quality-row");
    markTableRow('Description', "description-row");

    var panelNode = document.evaluate('//div[@data-target="#collapseScreens"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    panelNode.id = "screenshots-panel";
    panelNode = document.evaluate('//div[@data-target="#collapseComments"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    panelNode.id = "comments-panel";

    markTableRow('Thanked', 'thanked-row');
    markTableRow('Subtitles', 'subtitles-row');

    if (newTR !== undefined) {
      clickRelated();
    } else {
      console.log("XMLHttpRequest not done. Wait 2 seconds to click.");
      setTimeout(clickRelated, 2000);
    }
  }
  console.log("UserScript running");
  copyRelatedRow();

  injectFunc(injectedFunc);

  window.addEventListener('load', onLoadHandler, false);
})();