// ==UserScript==
// @name Filmot Title Restorer
// @namespace http://tampermonkey.net/
// @version 0.34
// @license GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0.txt
// @description Restores titles for removed or private videos in YouTube playlists
// @author Jopik
// @match https://*.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=filmot.com
// @grant none
// @require http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==
var darkModeBackground="#000099";
var lightModeBackground="#b0f2f4";
document.addEventListener('yt-navigate-start', handleNavigateStart);
document.addEventListener('yt-navigate-finish', handleNavigateFinish);
document.addEventListener( 'yt-action', handlePageDataLoad );
//fire at least once on load, sometimes handleNavigateFinish on first load yt-navigate-finish already fired before script loads
handleNavigateFinish();
function escapeHTML(unsafe) {
return unsafe.replace(
/[\u0000-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u00FF]/g,
c => '&#' + ('000' + c.charCodeAt(0)).substr(-4, 4) + ';'
)
}
function handlePageDataLoad(event){
if (event.detail!=null && event.detail.actionName!=null && event.detail.actionName.indexOf("yt-append-continuation")>=0) {
console.log("filmot yt-append-continuation");
console.log(event);
if (window.location.href.indexOf("/playlist?")>0)
{
extractIDsFullView();
}
}
}
function handleNavigateStart(){
var filmotTitles=$(".filmot_title");
filmotTitles.text("");
filmotTitles.removeClass("filmot_title");
var filmotChannels=$(".filmot_channel");
filmotChannels.text("");
filmotChannels.attr("onclick","");
filmotChannels.removeClass("filmot_channel");
cleanUP();
console.log("filmot handleNavigateStart");
}
function handleNavigateFinish(){
cleanUP();
console.log("filmot handleNavigateFinish");
if (window.location.href.indexOf("/playlist?")>0)
{
setTimeout(function(){ extractIDsFullView(); }, 500);
}
else
{
setTimeout(function(){ extractIDsSideView(); }, 500);
}
}
function cleanUP() {
$(".filmot_hide").show();
$(".filmot_hide").removeClass("filmot_hide");
$(".filmot_newimg").remove();
$(".filmot_highlight").css("background-color","");
$(".filmot_highlight").removeClass("filmot_highlight");
$("#TitleRestoredDiv").remove();
$(".filmot_c_link").remove();
window.RecoveredIDS={};
window.DetectedIDS={};
}
function extractIDsFullView() {
window.deletedIDs="";
window.deletedIDCnt=0;
var deletedIDs="";
var deletedIDsCnt=0;
var rendererSelector="a.ytd-playlist-video-renderer";
var a=$(rendererSelector).filter(function() {
return !$(this).attr('aria-label');
}).each(function( index, element ) {
// element == this
var href=$(element).attr('href');
var id=String(href.match(/v=[0-9A-Za-z_\-]*/gm));
id=id.substring(2);
window.DetectedIDS[id]=1;
if (deletedIDs.length>0)
{
deletedIDs+=",";
}
deletedIDs+=id;
deletedIDsCnt++;
});
if (deletedIDs.length>0) {
window.deletedIDs=deletedIDs;
window.deletedIDCnt=deletedIDsCnt;
if (document.getElementById ("TitleRestoredBtn")==null)
{
var r= $('<div id="TitleRestoredDiv"><center><button id="TitleRestoredBtn">Restore Titles</button><br><a class="yt-simple-endpoint style-scope yt-formatted-string" href="https://filmot.com" target="_blank">Powered by filmot.com</a></center></div>');
$("#items.ytd-playlist-sidebar-renderer").first().prepend(r);
document.getElementById ("TitleRestoredBtn").addEventListener (
"click", ButtonClickActionFullView, false
);
}
processClick(2,0);
}
}
function extractIDsSideView() {
window.deletedIDs="";
window.deletedIDCnt=0;
var deletedIDs="";
var deletedIDsCnt=0;
var rendererSelector="a.ytd-playlist-panel-video-renderer";
var a=$(rendererSelector).filter(function() {
return $(this).find("#video-title.ytd-playlist-panel-video-renderer[title='']").length>0;
}).each(function( index, element ) {
// element == this
var href=$(element).attr('href');
var id=String(href.match(/v=[0-9A-Za-z_\-]*/gm));
id=id.substring(2);
window.DetectedIDS[id]=1;
if (deletedIDs.length>0)
{
deletedIDs+=",";
}
deletedIDs+=id;
deletedIDsCnt++;
});
if (deletedIDs.length>0) {
window.deletedIDs=deletedIDs;
window.deletedIDCnt=deletedIDsCnt;
if (document.getElementById ("TitleRestoredBtn")==null)
{
var r= $('<div id="TitleRestoredDiv"><center><button id="TitleRestoredBtn">Restore Titles</button><br><a class="yt-simple-endpoint style-scope yt-formatted-string" href="https://filmot.com" target="_blank">Powered by filmot.com</a></center></div>');
$("#container.ytd-playlist-panel-renderer").first().prepend(r);
document.getElementById ("TitleRestoredBtn").addEventListener (
"click", ButtonClickActionSideView, false
);
}
}
}
function reportAJAXError(error)
{
alert("Error fetching API results " + error);
}
function rgb2lum(rgb)
{
// calculate relative luminance of a color provided by rgb() string
// black is 0, white is 1
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
if (rgb.length==4) {
var R=parseInt(rgb[1],10)/255.0;
var G=parseInt(rgb[2],10)/255.0;
var B=parseInt(rgb[3],10)/255.0;
return 0.2126*R + 0.7152*G + 0.0722*B;
}
return 1;
}
function processJSONResultSideView (fetched_details,format)
{
var darkMode=-1;
for (let i = 0; i < fetched_details.length; ++i) {
var meta=fetched_details[i];
window.RecoveredIDS[meta.id]=1;
var escapedTitle=escapeHTML(meta.title);
if (meta.channelname==null) {
meta.channelname=fetched_details[i].channelid;
}
var sel="a.ytd-playlist-panel-video-renderer[href*='"+ meta.id+"']";
var item=$(sel);
//console.log(item);
item.addClass("filmot_highlight");
var titleItem=item.find("#video-title");
titleItem.text(meta.title);
titleItem.attr("title",meta.title);
titleItem.attr("aria-label",meta.title);
titleItem.addClass("filmot_title");
if (darkMode==-1)
{
var lum=rgb2lum(titleItem.css("color"));
darkMode = (lum>0.51)?1:0; //if text is bright it means we are in dark mode
}
item.css("background-color",(darkMode==0)?lightModeBackground:darkModeBackground);
var channelItem=item.find("#byline");
channelItem.text(fetched_details[i].channelname);
channelItem.attr("onclick","window.open('https://www.youtube.com/channel/" +fetched_details[i].channelid + "', '_blank'); event.stopPropagation(); return false;");
channelItem.addClass("filmot_channel");
item.find(".filmot_newimg").remove();
var newThumb='<img id="filmot_newimg" class="style-scope yt-img-shadow filmot_newimg" onclick="prompt(\'Full Title\', \''+ escapedTitle+ '\'); event.stopPropagation(); return false;" title="' + escapedTitle + '" width="100" src="https://filmot.com/vi/' + meta.id + '/default.jpg">';
item.find("yt-img-shadow.ytd-thumbnail").append(newThumb);
item.find("#img.yt-img-shadow").addClass("filmot_hide");
item.find("#img.yt-img-shadow").hide();
}
$("#TitleRestoredBtn").text(Object.keys(window.RecoveredIDS).length+ " of " +Object.keys(window.DetectedIDS).length + " restored");
}
function processJSONResultFullView (fetched_details,format)
{
var darkMode=-1;
for (let i = 0; i < fetched_details.length; ++i) {
var meta=fetched_details[i];
window.RecoveredIDS[meta.id]=1;
var escapedTitle=escapeHTML(meta.title);
if (meta.channelname==null) {
meta.channelname=fetched_details[i].channelid;
}
var rendererSelector="#container.ytd-playlist-video-renderer";
var a=$(rendererSelector).filter(function() {
return $(this).find("a.ytd-playlist-video-renderer[href*='"+ meta.id+"']").length>0;
}).each(function( index, element ) {
// element == this
var item=$(element);
item.addClass("filmot_highlight");
var titleItem=item.find("#video-title");
titleItem.text(meta.title);
titleItem.attr("title",meta.title);
titleItem.attr("aria-label",meta.title);
titleItem.addClass("filmot_title");
if (darkMode==-1)
{
var lum=rgb2lum(titleItem.css("color"));
darkMode = (lum>0.51)?1:0; //if text is bright it means we are in dark mode
}
item.css("background-color",(darkMode==0)?lightModeBackground:darkModeBackground);
var channelItem=item.find("yt-formatted-string.ytd-channel-name");
//console.log(channelItem);
channelItem.find("a.filmot_c_link").remove();
var channelLink="<a class='filmot_c_link yt-simple-endpoint style-scope yt-formatted-string' dir='auto' href='https://www.youtube.com/channel/" +meta.channelid + "'>" + escapeHTML(meta.channelname) + "</a>";
channelItem.append(channelLink);
item.find("#byline-container").attr("hidden",false);
item.find(".filmot_newimg").remove();
var newThumb='<img id="filmot_newimg" class="style-scope yt-img-shadow filmot_newimg" onclick="prompt(\'Full Title\', \''+ escapedTitle+ '\'); event.stopPropagation(); return false;" title="' + escapedTitle + '" width="100" src="https://filmot.com/vi/' + meta.id + '/default.jpg">';
item.find("yt-img-shadow.ytd-thumbnail").append(newThumb);
item.find("#img.yt-img-shadow").addClass("filmot_hide");
item.find("#img.yt-img-shadow").hide();
});
}
$("#TitleRestoredBtn").text(Object.keys(window.RecoveredIDS).length+ " of " + Object.keys(window.DetectedIDS).length + " restored");
}
function processClick(format,nTry)
{
var maxTries=5;
var apiURL='https://filmot.com/api/getvideos?key=md5paNgdbaeudounjp39&id='+ window.deletedIDs;
var jqxhr = $.getJSON(apiURL, function(data) {
if (format==1) {
processJSONResultSideView(data,format);
}
else
{
processJSONResultFullView(data,format);
}
})
.done(function(data) {
})
.fail(function(error) {
if (nTry>=maxTries) {
reportAJAXError(apiURL + " " + JSON.stringify(error));
return;
}
processClick(format,nTry+1);
})
.always(function() {
});
}
function ButtonClickActionSideView (zEvent) {
processClick(1,0);
return false;
}
function ButtonClickActionFullView (zEvent) {
processClick(2,0);
return false;
}