Sleazy Fork is available in English.

Filmot Title Restorer

Restores titles for removed or private videos in YouTube playlists

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==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;
}