NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name RARBG - various tweaks
// @namespace darkred
// @version 2021.9.19
// @description Various tweaks for RARBG torrent detail pages, listings and search-by-IMDb-id pages.
// @author darkred
// @license MIT
// @include /^(https?:)?\/\/(www\.)?(proxy|unblocked)?rarbg((2018|2019|2020|2021)?|access(ed)?|cdn|core|data|enter|get|go|index|mirror(ed)?|p2p|prox(ied|ies|y)|prx|to(r|rrents)?|unblock(ed)?|way|web)\.(to|com|org|is)\/(torrent\/.*|torrents\.php.*|catalog\/.*|s\/.*|tv\/.*|top10)$/
// @grant none
// @supportURL https://github.com/darkred/Userscripts/issues
// ==/UserScript==
'use strict';
/* eslint-disable quotes */
// Automatically redirect e.g.
// https://rarbgproxy.org/torrents.php?search=tt6139732 to
// https://rarbgproxy.org/torrents.php?imdb=tt6139732
if (/torrents\.php\?search=tt\d+/.test(window.location.href)) {
// window.location.href = window.location.href.replace('?search=', '?imdb=');
window.location.replace(window.location.href.replace('?search=', '?imdb=')); // Use window.location.replace(url) if you want to redirect the user in a way that the current page is forgotten by the back button, ( https://stackoverflow.com/a/3170964 )
throw 'Reloading page'; // Stop script execution
}
function minsToHoursMins(totalMin) {
var hours = Math.floor( totalMin / 60);
var minutes = totalMin % 60;
return hours + 'h ' + minutes + 'min' ;
}
function tableLastRow(){
return $('table[width="100%"][border="0"][cellspacing="1"]').children().last().children().last();
}
const isOnTorrentListPage = window.location.href.includes('torrents.php');
if (!isOnTorrentListPage) {
$(".header2:contains('Rotten Rating:')") .html('RT Critics Avg:');
$(".header2:contains('RottenTomatoes:')") .html('RT Tomatometer, Audience Score:');
$(".header2:contains('Rotten Plot:')") .html('RT Critics Consensus:');
$(".header2:contains('IMDB Rating:')") .html('IMDb Rating:');
$(".header2:contains('Plot:')") .html('IMDb Summary:');
$(".header2:contains('IMDB Runtime:')") .html('IMDb Runtime:');
// Rating by users - decimal rating
var ratingByUsersElement = document.querySelector('.ratingblock p');
var text = document.querySelector('.ratingblock p').innerHTML;
ratingByUsersElement.title = ratingByUsersElement.innerText;
var regex = /\s+<strong>\s+([\d.]+)<\/strong>\/([\d.]+)(.*)/;
var average = text.match(regex)[1] * 2;
var votes = text.match(regex)[2] * 2;
var rest = text.match(regex)[3];
// Rating by users - ten star rating (instead of five star)
document.querySelector('.unit-rating').style.width = document.querySelector('.unit-rating').style.width.replace('px','') * 2 + 'px';
document.querySelector('.current-rating').style.width = document.querySelector('.current-rating').style.width.replace('px','') * 2 + 'px';
document.querySelector('.current-rating').innerHTML = document.querySelector('.current-rating').innerHTML.replace('Currently ', '').replace(/([\d.]+)\/([\d.]+)/, function(m, s1, s2) { return 2 * s1 + '/' + 2 * s2;});
var duration = $(".header2:contains('IMDb Runtime:')").next().html();
$(".header2:contains('IMDb Runtime:')").next().html(minsToHoursMins(duration));
// Add the title text to the IMDb link
var titleElement = $(".header2:contains('Title')").parent();
var titleText = $(titleElement).text().replace('Title:','');
$( "a[href*='imdb.com']" ).html(titleText);
// move Runtime inside IMDb Summary
var runtimeNode = $(".header2:contains('IMDb Runtime:')");
runtimeNode.parent().hide();
var runtime = runtimeNode.next().html();
var summaryNode = $(".header2:contains('IMDb Summary:')");
if (runtime !== undefined) {
summaryNode.next().text(
summaryNode.next()[0].innerText + ' ( ' + runtime + ' )'
);
}
// remove all '|' from the IMDb Summary text
summaryNode.next().text(function( index,string ) {
return string.replace(/\|/g,',');
});
// move PG Rating inside IMDb Summary
var pgNode = $(".header2:contains('PG Rating:')");
pgNode.parent().hide();
var pg = pgNode.next().html();
var summary = summaryNode.next().text();
if (pg !== undefined) {
summaryNode.next().text(summary + ' [ ' + pg + ' ]');
}
// MAKING BOLD (start)
ratingByUsersElement.innerHTML = ' Rating: <strong>' + average + '</strong>/' + votes + rest;
var imdbRatingNode = $(".header2:contains('IMDb Rating:')").next();
if (imdbRatingNode.length > 0){
$(imdbRatingNode).html($(imdbRatingNode).html().replace(/(.*)(\/.*)/, function(m, s1, s2) { return '<strong>'+ s1 + '</strong>' + s2;}));
}
$(".header2:contains('Metacritic:')").next().find(">:first-child").css("font-weight","Bold");
$(".header2:contains('RT Tomatometer, Audience Score:')").next().css("font-weight","Bold");
var rtTomatometerNode = $(".header2:contains('RT Tomatometer, Audience Score:')").next();
if (rtTomatometerNode.length !== 0)
$(rtTomatometerNode).html($(rtTomatometerNode).html().replace(/(.*) (\d+%)(.*)s (\d+%)/, function(m, s1, s2, s3, s4) { return s1 + '<strong>'+ s2 + '</strong>' + s3 + '<strong>'+ s4 + '</strong>' ;}));
var rtCriticsAvgNode = $(".header2:contains('RT Critics Avg:')").next();
if (rtCriticsAvgNode.length !== 0)
$(rtCriticsAvgNode).html($(rtCriticsAvgNode).html().replace(/(.*)(\/.*)/, function(m, s1, s2) { return '<strong>'+ s1 + '</strong>' + s2;}));
var userRating = $(".header2:contains('Rating:')").filter(function() {
return $.trim($(this).text()) === "Rating:";
}).parent();
userRating = $("p:contains('votes cast'), p:contains('vote cast')");
$(userRating).css('font-size', '11px');
$(userRating).html($(userRating).html().replace('Rating:', ''));
$(userRating).replaceWith(function() {
return "<div>" + this.innerHTML + "</div>";
});
// MAKING BOLD (end)
var vpn = $(".header2:contains('VPN:')").parent();
var mediaInfo = $(".header2:contains('MediaInfo »')").parent();
var trailer = $(".header2:contains('Trailer:')").parent();
var imdbLink = $('img[src="https://dyncdn.me/static/20/img/imdb3.png"]').parent().parent();
var ratingByUsers = $('.ratingblock').parent().parent();
var category = $(".header2:contains('Category:')").parent();
var size = $(".header2:contains('Size:')").parent();
var showFiles = $(".header2:contains('Show Files »')").parent();
var added = $(".header2:contains('Added:')").parent();
var title = $(".header2:contains('Title:')[align='right']").parent();
// var pgRating = $(".header2:contains('PG Rating:')").parent();
var imdbRating = $(".header2:contains('IMDb Rating:')").parent();
var metacritic = $(".header2:contains('Metacritic:')").parent();
var RTCriticsAvg = $(".header2:contains('RT Critics Avg:')").parent();
var RTTomatometer = $(".header2:contains('RT Tomatometer, Audience Score:')").parent();
var genres = $(".header2:contains('Genres:')").parent();
var actors = $(".header2:contains('Actors:')").parent();
var director = $(".header2:contains('Director:')").parent();
// var imdbRuntime = $(".header2:contains('IMDb Runtime:')").parent();
var year = $(".header2:contains('Year:')").parent();
var imdbSummary = $(".header2:contains('IMDb Summary:')").parent();
var RTCriticsCons = $(".header2:contains('RT Critics Consensus:')").parent();
var showNFO = $(".header2:contains('Show NFO »')").parent(); // example URL where the NFO is provided: https://rarbgproxy.org/torrent/fmzeqtk
var hits = $(".header2:contains('Hits:')").parent();
var peers = $(".header2:contains('Peers:')").parent();
var hitAndRun = $(".header2:contains('Hit&Run:')").parent();
var tags = $(".header2:contains('Tags')").parent();
var releaseName = $(".header2:contains('Release name:')").parent();
// duplicate the 'Size' row right after the 'Title' row
var sizeClone = size.clone();
sizeClone.insertAfter( $(".header2:contains('Torrent:')").parent() );
vpn.hide(); // The 'VPN' row is hidden because it's an ad.
// trailer.hide(); // For reference: https://rarbgproxy.org/trailers.php is blocked by default in uBlock Origin (via EasyList)
year.hide(); // The 'Year' row is hidden because that info is still contained in various other rows ('Release Name', 'IMDb' link title, 'Title')
category .insertAfter(tableLastRow());
releaseName .insertAfter(tableLastRow());
showNFO .insertAfter(tableLastRow());
size .insertAfter(tableLastRow());
showFiles .insertAfter(tableLastRow());
mediaInfo .insertAfter(tableLastRow());
added .insertAfter(tableLastRow());
title .insertAfter(tableLastRow());
// year .insertAfter(tableLastRow());
// imdbRuntime .insertAfter(tableLastRow());
genres .insertAfter(tableLastRow());
director .insertAfter(tableLastRow());
actors .insertAfter(tableLastRow());
// pgRating .insertAfter(tableLastRow());
imdbLink .insertAfter(tableLastRow());
trailer .insertAfter(tableLastRow());
imdbRating .insertAfter(tableLastRow());
imdbSummary .insertAfter(tableLastRow());
RTTomatometer .insertAfter(tableLastRow());
RTCriticsAvg .insertAfter(tableLastRow());
RTCriticsCons .insertAfter(tableLastRow());
metacritic .insertAfter(tableLastRow());
ratingByUsers .insertAfter(tableLastRow());
hits .insertAfter(tableLastRow());
peers .insertAfter(tableLastRow());
hitAndRun .insertAfter(tableLastRow());
tags .insertAfter(tableLastRow());
} else { // i.e. if isOnTorrentListPage === true
// var links = document.querySelectorAll('a[onmouseover^="return"]');
var links = document.querySelectorAll('td[valign="top"] > a[onmouseover^="return overlib"]'); // The "Recommended torrents" elements on https://rarbgproxy.org/torrents.php* .
// for(let i = 0; i < 9; i++) {
for(let i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(event){
event.preventDefault();
let tLink = this.getAttribute('href');
if (!tLink.includes('imdb=')){
var xhr = new XMLHttpRequest();
xhr.open('GET', tLink, false); // XMLHttpRequest.open(method, url, async)
xhr.onload = function () {
let container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = xhr.responseText;
let retrievedLink = container.querySelector('.lista>a[href*="www.imdb.com"]').href; // the 'IMDB link' element in the retrieved RARBG page
if (retrievedLink) {
let currentDomainName = window.location.hostname;
links[i].setAttribute('href', 'https://' + currentDomainName + '/torrents.php?imdb=' + retrievedLink.match(/(tt\d+)/)[1]); // example URL: https://rarbgproxy.org/torrents.php?imdb=tt7605074
}
let imdbPlot = $(container).find(".header2:contains('Plot:')").filter(function() { // https://stackoverflow.com/questions/8978411/jquery-ajax-findp-in-responsetext
return $(this).text() === "Plot:"; // https://stackoverflow.com/questions/15364298/select-element-by-exact-match-of-its-content/18462522
// }).next()[0].innerText; // [0] ---> convert jQuery element/node to a regular DOM element
}).next()[0].innerHTML.replace('<span>','').replace('</span>','');
if (imdbPlot !== undefined){
imdbPlot = removePipesLinebreaks(imdbPlot); // remove all '|', and replace all newlines with spaces
sessionStorage.setItem("imdbPlot", imdbPlot);
} else { // never actually needed: all Recommended movies have IMDb plot
sessionStorage.removeItem("imdbPlot");
imdbPlot = '';
}
let rtPlot = $(container).find(".header2:contains('Rotten Plot:')").next().html();
if (rtPlot !== undefined){
rtPlot = removePipesLinebreaks(rtPlot);
sessionStorage.setItem("rtPlot", rtPlot);
} else {
sessionStorage.removeItem("rtPlot");
rtPlot = '';
}
window.location.href = links[i].href; // https://www.w3schools.com/howto/howto_js_redirect_webpage.asp
};
xhr.send();
}
}, false);
}
}
function removePipesLinebreaks(s){
if (s) {
return s.replace(/( \|)/g,',')
.replace(/(\|)/g,',')
.replace(/(\r\n|\n|\r| |<br>)/g,' ');
}
}
function makeBold(s, regex){
if (regex.test(s)) {
return s.replace(regex, function(m, s1, s2, s3) { return s1 + '<b>'+ s2 + '</b>' + s3 ;});
}
}
const isOnSearchbyIMDbIdPage = window.location.href.includes('/torrents.php?imdb=');
let imdbPlotStored = sessionStorage.getItem("imdbPlot");
if (imdbPlotStored === null || imdbPlotStored === 'undefined') {
sessionStorage.removeItem("imdbPlot");
imdbPlotStored = '';
}
let rtPlotStored = sessionStorage.getItem("rtPlot");
if (rtPlotStored === null || rtPlotStored === 'undefined') {
sessionStorage.removeItem("rtPlot");
rtPlotStored = '';
}
if (isOnSearchbyIMDbIdPage) {
let searchListingHeader = document.querySelector('h1.black').textContent;
const imdbIdRegex = /tt\d+/;
let imdbId;
if (imdbIdRegex.test(searchListingHeader)){
imdbId = imdbIdRegex.exec(searchListingHeader)[0];
}
let imdbRatingElement = $("b:contains('IMDB Rating:')");
if (imdbRatingElement.length > 0){
imdbRatingElement.html('<a href="https://www.imdb.com/title/' + imdbId + '/">IMDb</a> Rating:');
} else { // Example: https://rarbgproxy.org/torrents.php?imdb=tt9139586
// imdbRatingElement = $("b:contains('Runtime:')");
imdbRatingElement = $("b:contains('Runtime:'), b:contains('Year:')"); // when there's no 'Runtime' element but only 'Year', e.g. https://rarbgproxy.org/torrents.php?imdb=tt4136456
$(imdbRatingElement).parent().html($(imdbRatingElement).parent().html() + '<b>IMDB Rating:</b><br>');
imdbRatingElement = $("b:contains('IMDB Rating:')");
imdbRatingElement.html('<a href="https://www.imdb.com/title/' + imdbId + '/">IMDb</a> Rating: -');
}
RTTomatometer = $("b:contains('Rotten Rating:')");
if ( RTTomatometer.length > 0 ) {
RTTomatometer.html(RTTomatometer.html().replace('Rotten Rating:', 'RT Critics Avg:'));
}
RTCriticsAvg = $("b:contains('RottenTomatoes:')");
if ( RTCriticsAvg.length > 0 ) {
RTCriticsAvg.html(RTCriticsAvg.html().replace('RottenTomatoes:', 'RT Tomatometer:'));
}
if (imdbPlotStored) {
imdbPlotStored = removePipesLinebreaks(imdbPlotStored);
$(imdbRatingElement).next().after("<b>IMDb Summary:</b> " + imdbPlotStored + '<br>'); // https://stackoverflow.com/questions/6617829/insertadjacenthtml-in-jquery
// Example list page with all possible rows: https://rarbgproxy.org/torrents.php?imdb=tt6146586 i.e.
// IMDb Rating: 7.4/10
// IMDb Summary:
// RT Critics Avg:
// RT Tomatometer:
// RT Critics Consensus:
if (rtPlotStored) {
rtPlotStored = removePipesLinebreaks(rtPlotStored);
let rtRatingElement = $("b:contains('RT Critics Avg:'), b:contains('RT Tomatometer:'), b:contains('IMDb Summary:')").last() ; // alternative selector for when no RT row is present, e.g. https://rarbgproxy.org/torrents.php?imdb=tt11057644
var br = '';
if ($("b:contains('RT Tomatometer:')").length !== 0){
br = '<br>';
}
$(rtRatingElement).parent().html($(rtRatingElement).parent().html() + br + "<b>RT Critics Consensus:</b> " + rtPlotStored + '<br>'); // This is the best way to insert text node after text node in jQuery (don't try after() or append() or .siblings().last()[0].nextSibling )
}
// new xhr for when plot is not already retrieved (=when opening a link from the Recommended area in a new tab)
} else if (document.querySelector('.lista2t').rows.length > 1) { // if searchbyIMDbResultsTableLength has results
let tLink = document.querySelector('.lista2t').rows[1].cells[1].children[0].href; // the URL in the results table first row
let xhr = new XMLHttpRequest();
xhr.open('GET', tLink, false); // XMLHttpRequest.open(method, url, async)
xhr.onload = function () {
let container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = xhr.responseText;
let imdbPlot = $(container).find(".header2:contains('Plot:')").filter(function() { // https://stackoverflow.com/questions/8978411/jquery-ajax-findp-in-responsetext
return $(this).text() === "Plot:"; // https://stackoverflow.com/questions/15364298/select-element-by-exact-match-of-its-content/18462522 (in order to only select IMDb's plain "Plot", not "Rotten Plot", too )
// }).next()[0].innerText; // [0] ---> convert jQuery element/node to a regular DOM element
}).next()[0].innerHTML.replace('<span>','').replace('</span>','');
imdbPlot = removePipesLinebreaks(imdbPlot);
sessionStorage.setItem("imdbPlot", imdbPlot);
let rtPlot = $(container).find(".header2:contains('Rotten Plot:')").next().html();
if (rtPlot !== undefined){
rtPlot = removePipesLinebreaks(rtPlot);
sessionStorage.setItem("rtPlot", rtPlot);
} else {
sessionStorage.removeItem("rtPlot");
rtPlot = '';
}
let imdbRatingElement = $("b:contains('IMDb Rating:')");
$(imdbRatingElement).next().after("<b>IMDb Summary:</b> " + imdbPlot + '<br>');
if (!rtPlotStored) {
let rtRatingElement = $("b:contains('RT Critics Avg:'), b:contains('RT Tomatometer:'), b:contains('IMDb Summary:')").last() ; // if no RT row is present
var br = '';
if ($("b:contains('RT Tomatometer:')").length !== 0){
br = '<br>';
}
if (rtPlot !== ''){
$(rtRatingElement).parent().html($(rtRatingElement).parent().html() + br + "<b>RT Critics Consensus:</b> " + rtPlot + '<br>');
}
}
};
xhr.send();
}
// make bold (example URL: https://rarbgproxy.org/torrents.php?imdb=tt6146586)
let imdbRefRatingElement = $("b:contains('IMDb Rating:')").parent();
let imdbRatingBoldRegex = /(.*IMDb<\/a> Rating:<\/b> )([\d.]+)(\/.*)/;
let rtCriticsBoldRegex = /(.*RT Critics Avg:<\/b> )([\d.]+)(\/.*)/;
let rtTomatometerBoldRegex = /(.*<b>RT Tomatometer:<\/b> <img.*> )(\d+%.*\d+%)(.*)/;
imdbRefRatingElement.html(makeBold(imdbRefRatingElement.html(), imdbRatingBoldRegex));
imdbRefRatingElement.html(makeBold(imdbRefRatingElement.html(), rtCriticsBoldRegex));
imdbRefRatingElement.html(makeBold(imdbRefRatingElement.html(), rtTomatometerBoldRegex));
// duration from min to h:mm
let durationRegex = /(.*<b>Runtime:<\/b> )(\d+)(.*)/;
if (durationRegex.test(imdbRefRatingElement.html())){
imdbRefRatingElement.html(imdbRefRatingElement.html().replace(durationRegex, function(m, s1, s2, s3) { return s1 + minsToHoursMins(s2) + s3 ;}));
}
imdbRefRatingElement.html(imdbRefRatingElement.html().replace('RT Tomatometer:', 'RT Tomatometer/Audience Score:'));
let preferredPatterns = [
/([\s\S]+<br>)\s+<b><a href="https:\/\/www\.imdb\.com\/title\//,
/(<b><a href="https:\/\/www\.imdb\.com\/title\/tt\d+\/">IMDb<\/a> Rating:.*\.<br>)/,
/(<b>RT Critics Avg:.*10<br>)/,
// /(<b>RT Tomatometer:.*%<\/b>\s+<br>)/,
/(<b>RT Tomatometer\/Audience Score:.*%<\/b>\s+<br>)/,
/(<b>RT Critics Consensus:.*)/,
];
let result = [];
for (let i=0; i < preferredPatterns.length;i++) {
if (preferredPatterns[i].test(imdbRefRatingElement.html())) {
result[i] = imdbRefRatingElement.html().match(preferredPatterns[i])[1];
} else {
result[i] = '';
}
}
// rearrange: IMDb Summary --> IMDb Rating --> RT Tomatometer --> RT Critics Avg --> RT Critics Consensus
imdbRefRatingElement.html(result[0] + result[1] + result[3] + result[2] + result[4]);
}