Disney+ Subtitles Downloader

Download subtitles from Disney+

Mint 2020.06.26.. Lásd a legutóbbi verzió

// ==UserScript==
// @name           Disney+ Subtitles Downloader
// @name:fr        Disney+ Subtitles Downloader
// @namespace      https://greasyfork.org/fr/users/572942-stegner
// @homepage       https://greasyfork.org/fr/scripts/404223-disney-subtitles-downloader
// @description    Download subtitles from Disney+
// @description:fr Télécharger les sous-titres de Disney+
// @version        2.0
// @author         stegner
// @match          https://www.disneyplus.com/*
// @grant          none
// ==/UserScript==

function start(){
    if (typeof document.initsub !== "undefined") {
        document.initsub();
    }
    if (typeof document.initaudio !== "undefined") {
        document.initaudio();
    }
    listensend();
    document.handleinterval = setInterval(buttonhandle,100);
}

window.onload = start;

document.initsub = function(){
    document.langs = new Array();
    document.segments = "";
    document.forced=false;
    document.wait=false;
    document.m3u8found=false;
    document.url=null;
    document.oldlocation=null;
    document.filename="";
    document.episode="";
    var segid=0;
    var vtturl;

    // Add download icon
    document.styleSheets[0].addRule('#subtitleTrackPicker > div:before','content:"";background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAIGNIUk0AAHonAACAgwAA+mQAAIDSAAB2hgAA7OkAADmeAAAV/sZ+0zoAAAE4SURBVHja1JS7LkRRFIa/M6aYRCEuCUEUgihFBolGVGqiFY1ConfpNB7CiygUGm8hOiMukwiCCMl8mj2xc5yZM8M0/mTlrLP2v75zydo7UclRL3AGlIAl4L6ZuUC+5oEZYBoo55lbAdai/LPTwFongG3pfwI3gZ3ovhjlXVG+BWz/6FbjKPuto1CbjWoLobYf1RZjRho4pt5F5g11QK2F6FFXo/UXdbwZEHVQvY2aztWPECdR/TkNawREHUpB03pSJ7J6Cf9gL3xOvDiiXmfAHtSplLek7qorqI/BeJjxxFG1kgNDPQjrn4VoLPozRqgCzAGXwFXILzJ8w+H6XgRegW7grcGs3gCTOfP8UgfGg139wwapxrugDl0H+oCkTZjAcsiTxBaO7HZUBI6BtfCmv4Un4aw8/RoA7wq6AO4uOhAAAAAASUVORK5CYII=);width:20px;height:20px;position:absolute;top:6px;right:10px;opacity:0.6;cursor:pointer;');
    document.styleSheets[0].addRule('#subtitleTrackPicker > div:hover:before','opacity:1;');
    document.styleSheets[0].addRule('#subtitleTrackPicker > div:first-child:before','content:"";width:0px;height:0px;');
};

// Catch M3U8 files
function listensend(){
    XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send;

    var newSend = function(vData) {
        if(!document.m3u8found) {
            try {
                var objData = JSON.parse(vData);
                if(typeof objData.url !== 'undefined') {
                    if(objData.url.indexOf(".m3u8")>0 && document.url!=objData.url) {
                        // m3u8 url
                        document.url = objData.url;
                        document.langs = [];
                        document.baseurl=document.url.substring(0,document.url.lastIndexOf('/')+1);
                        document.m3u8found=true;
                        getpagecontent(m3u8loaded,document.url);
                    }
                }
            } catch (error) {}
        }
        this.realSend(vData);
    }

    XMLHttpRequest.prototype.send = newSend;
}

function m3u8loaded(response) {
    if (typeof document.m3u8sub !== "undefined") {
        document.m3u8sub(response);
    }
    if (typeof document.m3u8audio !== "undefined") {
        document.m3u8audio(response);
    }
}

document.m3u8sub = function(response){
    var lines = response.split('#');
    var found = false;
    lines.forEach(function(line) {
        if(line.indexOf('GROUP-ID="sub-main"')>0) {
            // sub infos
            document.langs.push(linetoarray(line));
        }
        else if(line.indexOf('.vtt')>0 && !found && line.indexOf('BUMPER')<0) {
            // vtt url
            var uri = document.langs[document.langid].URI;
            var url = line.split(',')[1].substring(1);
            found=true;
            if(url.indexOf("/")<0){
                url = uri.substring(2,uri.lastIndexOf("/")+1) + url;
            }
            getsegment(document.baseurl+uri.substring(0,2)+url,0);
        }
    });
}

function vttloaded(response) {
    if(response.length>0) {
        // save segment
        document.segments+=response.substring(response.indexOf("-->")-13);
        getsegment(vtturl,segid+1);
    }
    else if(document.segments.length>0) {
        // export segments
        exportfile(vtttosrt(document.segments));
    }
    else {
        alert("Unknown error, please report a bug for this video.");
    }
}

function vtttosrt(vtt) {
    var lines = vtt.split(/\r\n|\r|\n/);
    var result = [];
    var subcount = 0;

    lines.forEach(function (line) {
        if(line.indexOf("-->") == 13) {
            subcount++;
            result.push(subcount);
            result.push(line.substring(0,29).replace(/[.]/g,','));
        }
        else if(subcount>0) {
            result.push(line.replace(/<\/?c(\.\w{1,})?>/g,'').replace(/&amp;/g,'&'));
        }
    });
    return result.join('\r\n');
}

function linetoarray(line) {
    var result = new Array();
    var values = line.split(',');
    values.forEach(function(value) {
        var data = value.replace(/\r\n|\r|\n/g,'').split('=');
        if(data.length>1) {
            var key = data[0];
            var content = data[1].replace(/"/g,'');
            result[key]=content;
        }
    });
    return result;
}

function buttonhandle() {
    var buttons = document.getElementsByClassName("control-icon-btn");
    if(buttons.length>0) {
        if (typeof document.clickhandlesub !== "undefined") {
            document.clickhandlesub();
        }
        if (typeof document.clickhandleaudio !== "undefined") {
            document.clickhandleaudio();
        }

        document.filename = document.getElementsByClassName("title-field")[0].innerText;
        if(document.getElementsByClassName("subtitle-field").length>0) {
            document.episode = document.getElementsByClassName("subtitle-field")[0].innerText
        }
    }

    if(document.oldlocation!=window.location.href&&document.oldlocation!=null) {
        // location changed
        document.m3u8found=false;
        document.langs = [];
        document.audios = [];
    }

    document.oldlocation=window.location.href;
}

document.clickhandlesub = function() {
    var picker = document.getElementsByClassName("options-picker subtitle-track-picker");
    picker[0].childNodes.forEach(function(child) {
        var element = child.childNodes[0];
        var lang = element.childNodes[1].innerHTML;
        if(lang!="Off"&&child.onclick==null) {
            child.onclick = selectsub;
        }
    });
}

function selectsub(e) {
    var width = this.offsetWidth;
    // Check click position
    if(e.layerX>=width-30&&e.layerX<=width-10&&e.layerY>=5&&e.layerY<=25){
        // Download sub
        download(this.childNodes[0].childNodes[1].innerHTML);
        // Cancel selection
        return false;
    }
}

function download(langname) {
    if(!document.wait){
        var language;
        var count=0;
        document.forced=false;
        document.langs.forEach(function(lang) {
            if(lang.NAME==langname) {
                language=lang.LANGUAGE;
                document.langid=count;
                getpagecontent(m3u8loaded,document.baseurl+lang.URI);
                document.wait=true;
            }
            count++;
        });
        document.langs.forEach(function(lang) {
            if(lang.LANGUAGE==language && lang.NAME!=langname && lang.FORCED=="YES") {
                document.waitInterval = setInterval(function () {
                    if(!document.wait) {
                        document.forced=true;
                        clearInterval(document.waitInterval);
                        getpagecontent(m3u8loaded,document.baseurl+lang.URI);
                        document.wait=true;
                    }
                },100);
            }
        });
        if(count==0){
            alert("An error has occurred, please reload the page.");
        }
    }
    
}


function getsegment(url,seg) {
    if(seg==0) {
        document.segments="";
    }
    segid = seg;
    vtturl = url;
    getpagecontent(vttloaded,vtturl.substring(0,vtturl.length-10)+segid.toString().lpad("0", 5)+".vtt");
}

function exportfile(text) {
    var output = document.filename;
    if(document.episode!="") {
        output+= " - "+document.episode.replace(':','');
    }
    output += "."+document.langs[document.langid].LANGUAGE;
    if(document.forced) {
        output += ".forced";
    }
    output += ".srt";

    var hiddenElement = document.createElement('a');

    hiddenElement.href = 'data:attachment/text,' + encodeURI(text);
    hiddenElement.target = '_blank';
    hiddenElement.download = output;
    hiddenElement.click();

    setTimeout(function () { document.wait = false; },500);
}

function getpagecontent(callback,url) {
    var http=new XMLHttpRequest();
    http.open("GET", url, true);
    http.onloadend = function() {
        if(http.readyState == 4 && http.status == 200) {
            callback(http.responseText);
        }
        else if (http.status === 404) {
            callback("");
        }
    }
    http.send();
}

String.prototype.lpad = function(padString, length) {
    var str = this;
    while (str.length < length) {
        str = padString + str;
    }
    return str;
}