// ==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.2
// @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 = relatedRow.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 = "";
}
console.log ("nTorrents:",nRelated,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);
})();