NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==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; }