NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name PTP To Radarr
// @version 0.8.4
// @author DirtyCajunRice
// @description Easily add movies to radarr straight from PTP
// @homepage https://passthepopcorn.me/forums.php?action=viewthread&threadid=35294
// @icon https://ptpimg.me/19kcyv.png
// @updateURL https://openuserjs.org/meta/dirtycajunrice/PTP_To_Radarr.meta.js
// @supportURL https://passthepopcorn.me/forums.php?action=viewthread&threadid=35294
// @match https://passthepopcorn.me/*
// @require https://openuserjs.org/src/libs/sizzle/GM_config.js
// @copyright 2019, dirtycajunrice (https://openuserjs.org//users/dirtycajunrice)
// @license MIT
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_openInTab
// @grant GM_log
// @grant GM_notification
// @grant GM_registerMenuCommand
// ==/UserScript==
// Changelog 0.8.4 - Fixed href bug for covers
// Fixed update logic
// Changelog 0.8.3 - Major internal code refactor
// Found lingering URL sanitization missed
// Changelog 0.8.2 - Fixed autoupdate trying to update non-existant buttons
// Changelog 0.8.1 - Fixed "Huge view" themeChecker for Raise
// Fixed "Huge view" in collections
// Added AutoUpdate for "Huge view"
// Changelog 0.8.0 - Added "Huge view"
// Changelog 0.7.1 - Fixed bug with GM_config iframe document access logic
// Fixed bug with themeChecker
// Changelog 0.7.0 - Added AutoSync to settings
// Update buttons after a sync (manual and auto)
// Changelog 0.6.1 - Added Stylesheet checking to fix cover buttons. Confirmed working on all official and supported custom stylesheets + Raise
// Changelog 0.6.0 - Added error checking to help debug issues
// Added Radarr URL sanitization
var current_page_type = "";
(function () {
"use strict";
GM_config.init({
"id": "PTPToRadarr",
"title": "PTP To Radarr Settings",
"css": `#PTPToRadarr {background: #333333;}
#PTPToRadarr .field_label {color: #fff;}
#PTPToRadarr .config_header {color: #fff; padding-bottom: 10px;}
#PTPToRadarr .reset {color: #f00; text-align: center;}
#PTPToRadarr .config_var {text-align: center;}
#PTPToRadarr_radarr_syncbutton_var {float: left;}
#PTPToRadarr .reset_holder {text-align: center;}
#PTPToRadarr_radarr_minimumavailability_var {padding-right: 95;}
#PTPToRadarr_radarr_apikey_var {padding-left: 49;}
#PTPToRadarr_radarr_url_var {padding-left: 69;}
#PTPToRadarr .saveclose_buttons {margin: 16px 10px 10px; padding: 2px 12px; background-color: #e7e7e7; color: black; text-decoration: none; border: none; border-radius: 6px;}
#PTPToRadarr_field_radarr_syncbutton {background-color: #e7e7e7; color: black; text-decoration: none; border: none; border-radius: 6px; margin-left: 10px; margin-top: 16px; height: 20px;}`,
"events": {
"open": function(doc) {
let style = this.frame.style;
style.width = "400px";
style.height = "295px";
style.inset = "";
style.top = "6%";
style.right = "6%";
style.borderRadius = "25px";
doc.getElementById("PTPToRadarr_buttons_holder").prepend(doc.getElementById("PTPToRadarr_radarr_syncbutton_var"));
}
},
"fields": {
"radarr_url": {
"label": "Radarr URL",
"type": "text",
"default": "https://domain.tld/radarr"
},
"radarr_apikey": {
"label": "Radarr API Key",
"type": "text",
"default": ""
},
"radarr_profileid": {
"label": "Radarr Quality Profile ID",
"type": "text",
"default": "1"
},
"radarr_rootfolderpath": {
"label": "Radarr Root Folder Path",
"type": "text",
"default": "/mnt/movies"
},
"radarr_minimumavailability":
{
"label": "Minimum Availability",
"type": "select",
"options": ["preDB", "announced", "inCinemas", "released"],
"default": "released"
},
"radarr_searchformovie": {
"label": "Search for movie on request",
"type": "checkbox",
"default": false
},
"radarr_sync_interval":
{
"label": "AutoSync Interval (Minutes)",
"type": "select",
"options": ["15", "30", "60", "120", "360", "1440", "Never"],
"default": "Never"
},
"radarr_syncbutton": {
"label": "Sync Radarr Movies",
"type": "button",
"click": get_radarr_movies
}
}
});
new GM_registerMenuCommand("PTP To Radarr Settings",() => GM_config.open());
let url = window.location.href;
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
if (document.getElementById("torrent-table")) {
current_page_type = "singletorrent";
}
else {
current_page_type = "multi";
}
if (current_page_type) {
set_html(false);
}
let interval = GM_config.get("radarr_sync_interval");
if (interval != "Never") {
let millisecondInterval = Number(interval) * 60000;
window.setTimeout(() => autoSync(millisecondInterval));
window.setInterval(() => autoSync(millisecondInterval), millisecondInterval);
}
})();
function themeChecker () {
let typeAThemes = ["marcel.css", "ptp-raise"];
typeAThemes.forEach((theme) => {
if (document.head.querySelector("[href*=\"" + theme + "\"]")) {
return true;
}
});
return false;
}
function clickswap (imdbid, titleSlug) {
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let button = document.getElementById("ptptoradarr-" + imdbid)
button.firstChild.src = "https://ptpimg.me/19kcyv.png";
button.removeEventListener("click", new_movie_lookup, false);
button.addEventListener("click", function () {
GM_openInTab(radarr_url.concat("/movies/", titleSlug), "active");
}, false);
}
function set_html (update) {
let theme = themeChecker();
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let coverView = document.querySelector(".cover-movie-list__container");
let coverViewMovies = Array.from(document.getElementsByClassName("cover-movie-list__movie__rating-and-tags"));
let listView = document.querySelector(".js-basic-movie-list");
let listViewMovies = Array.from(document.getElementsByClassName("basic-movie-list__movie__ratings-and-tags"));
let hugeView = document.querySelector(".huge-movie-list__movie");
let hugeViewMovies = Array.from(document.getElementsByClassName("huge-movie-list__movie__ratings"));
if (update) {
let buttons = document.querySelectorAll("[id^=\"ptptoradarr-tt\"]");
if (buttons.length === 0) {
return;
}
buttons.forEach((button) => {
window.setTimeout(function () {
button.parentNode.removeChild(button);
});
});
}
if (current_page_type == "singletorrent") {
let a = document.querySelector("[href^=\"http://www.imdb.com/title/tt\"]");
let movie = document.querySelector(".panel__body");
if (a) {
buttonBuilder(movie, a.href, "single", theme);
}
}
else if (current_page_type == "multi") {
if (coverView && !coverView.classList.contains("hidden")) {
coverViewMovies.forEach((movie) => {
window.setTimeout(() => {
let a = movie.querySelector("[href^=\"http://www.imdb.com/title/tt\"]");
if (a) {
buttonBuilder(movie, a.href, "medium", theme);
}
});
});
}
else if (listView && !listView.classList.contains("hidden")) {
listViewMovies.forEach((movie) => {
window.setTimeout(() => {
let a = movie.querySelector("[href^=\"http://www.imdb.com/title/tt\"]");
if (a) {
buttonBuilder(movie, a.href, "small", theme);
}
});
});
}
else if (hugeView) {
hugeViewMovies.forEach((movie) => {
window.setTimeout(() => {
let a = movie.querySelector("[href^=\"http://www.imdb.com/title/tt\"]");
if (a) {
buttonBuilder(movie, a.href, "large", theme);
}
});
});
}
}
}
function buttonBuilder (movie, href, type, theme) {
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let imdbid = href.substr(26, 9);
let exists = check_exists(imdbid);
let button = document.createElement("button");
let img = document.createElement("img");
button.id = "ptptoradarr-" + imdbid;
button.type = type;
Object.assign(button.style, {border: "none", backgroundColor: "transparent"});
Object.assign(img.style, {border: "none", backgroundColor: "transparent"});
Object.assign(img, {height: 32, width: 32});
button.appendChild(img);
img.imdbid = imdbid;
if (type == "single") {
Object.assign(button.style, {position: "absolute", top: "6%", zIndex: 10});
movie.style.position = "relative";
movie.prepend(button);
}
else if (type == "small") {
Object.assign(img, {height: 16, width: 16});
movie.appendChild(button);
}
else if (type == "medium") {
let posterContainer = movie.closest(".cover-movie-list__movie");
posterContainer.prepend(button);
Object.assign(button.style, {position: "absolute", top: "3%", zIndex: 10});
if (theme) {
posterContainer.style.position = "relative";
}
}
else if (type == "large") {
let posterContainer = movie.closest(".huge-movie-list__movie").firstChild;
posterContainer.prepend(button);
Object.assign(button.style, {position: "absolute", top: "3%", zIndex: 10});
if (theme) {
button.style.left = "3%";
posterContainer.style.position = "relative";
}
}
if (exists) {
img.src = "https://ptpimg.me/19kcyv.png";
button.addEventListener("click", function () {
GM_openInTab(radarr_url.concat("/movies/", exists[0].titleSlug), "active");
}, false);
}
else {
img.src = "https://ptpimg.me/0q4vvz.png";
button.addEventListener("click", new_movie_lookup, false);
}
}
function errorNotificationHandler (error, expected, errormsg) {
let prestring = "PTPToRadar::";
if (expected) {
GM_log(prestring + "Error: " + errormsg + " Actual Error: " + error);
GM_notification("Error: " + errormsg);
}
else {
GM_log(prestring + "Unexpected Error: Please report this error in the forum. Actual Error: " + error);
GM_notification("Unexpected Error: Please report this error in the forum. Actual Error: " + error);
}
}
function get_radarr_movies() {
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let radarr_apikey = GM_config.get("radarr_apikey");
GM_xmlhttpRequest({
method: "GET",
url: radarr_url.concat("/api/movie"),
headers: {
"X-Api-Key": radarr_apikey,
"Accept": "text/json"
},
onload: function(response) {
let responseJSON = null;
if (!response.responseJSON) {
try {
responseJSON = JSON.parse(response.responseText);
if (responseJSON.error == "Unauthorized") {
throw "creds";
}
GM_setValue("existing_movies", JSON.stringify(responseJSON));
let timestamp = + new Date()
GM_setValue("last_sync_timestamp", timestamp)
GM_log("PTPToRadarr::Sync: Setting last sync timestamp to " + timestamp)
GM_notification("Radarr Sync Complete!", "PTP To Radarr");
set_html(true);
}
catch (e) {
if (e instanceof SyntaxError) {
errorNotificationHandler(e, true, "No JSON in response. Please check your Radarr URL.")
}
else if (e == "creds") {
errorNotificationHandler(e, true, "Invalid API Key. Please check your Radarr API Key")
}
else {
errorNotificationHandler(e, false)
}
}
}
}
});
};
function check_exists (imdbid) {
let movieliststr = GM_getValue("existing_movies", "{}");
let movie_list = JSON.parse(movieliststr);
let filter = null
try {
filter = movie_list.filter(movie => movie.imdbId == imdbid);
}
catch (e) {
if (e instanceof TypeError) {
return false
}
else {
errorNotificationHandler(e, false)
return false
}
}
if (!filter.length) {
return false
}
else {
return filter
};
}
function autoSync (interval) {
let currentTimestamp = + new Date();
let lastSyncTimestamp = GM_getValue("last_sync_timestamp", 0);
if (currentTimestamp - lastSyncTimestamp >= interval) {
let notification = "It has been " + ((currentTimestamp - lastSyncTimestamp) / 60000).toFixed(1) +
" minutes since your last sync which exceeds your threshold of " +
(interval / 60000) + " minutes. AutoSyncing...";
GM_log(notification);
GM_notification(notification);
get_radarr_movies();
}
}
function new_movie_lookup (link) {
let imdbid = ""
if (link.originalTarget) {
imdbid = link.originalTarget.imdbid;
}
else {
imdbid = link.target.imdbid;
}
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let radarr_apikey = GM_config.get("radarr_apikey");
let movie = "";
GM_xmlhttpRequest({
method: "GET",
url: radarr_url.concat("/api/movie/lookup/imdb?imdbId=", imdbid),
headers: {
"X-Api-Key": radarr_apikey,
"Accept": "text/json"
},
onload: function(response) {
let responseJSON = null;
if (!response.responseJSON) {
if (!response.responseText) {
GM_notification("No results found");
return;
}
responseJSON = JSON.parse(response.responseText);
add_movie(responseJSON, imdbid);
}
}
})
}
function add_movie (movie, imdbid) {
let radarr_url = GM_config.get("radarr_url").replace(/\/$/, "");
let radarr_apikey = GM_config.get("radarr_apikey");
movie.ProfileId = GM_config.get("radarr_profileid");
movie.RootFolderPath = GM_config.get("radarr_rootfolderpath");
movie.monitored = true;
movie.minimumAvailability = GM_config.get("radarr_minimumavailability");;
if (GM_config.get("radarr_searchformovie")) {
movie.addOptions = {searchForMovie: true}
}
GM_xmlhttpRequest({
method: "POST",
url: radarr_url.concat("/api/movie"),
headers: {
"X-Api-Key": radarr_apikey,
"Accept": "text/json",
"Content-Type": "application/json"
},
data: JSON.stringify(movie),
onload: function(response) {
let responseJSON = null;
if (!response.responseJSON) {
responseJSON = JSON.parse(response.responseText);
try {
if (!responseJSON.title && responseJSON.firstChild.errorMessage == "This movie has already been added") throw "exists";
clickswap(imdbid, responseJSON.titleSlug);
GM_notification(responseJSON.title + " Sucessfully sent to Radarr", "PTP To Radarr")
}
catch (e) {
if (e == "exists") {
errorNotificationHandler(e, true, "Movie already exists in Radarr. Please resync your movies.");
}
else {
errorNotificationHandler(e, false);
}
}
}
}
});
}