Greasy Fork镜像 还支持 简体中文。

Disney+ Subtitles Downloader

Download subtitles from Disney+

目前為 2020-07-24 提交的版本,檢視 最新版本

// ==UserScript==
// @name           Disney+ Subtitles Downloader
// @name:fr        Disney+ Subtitles Downloader
// @namespace      https://gf.qytechs.cn/fr/users/572942-stegner
// @homepage       https://gf.qytechs.cn/fr/scripts/404223-disney-subtitles-downloader
// @description    Download subtitles from Disney+
// @description:fr Télécharger les sous-titres de Disney+
// @version        2.1
// @author         stegner
// @match          https://www.disneyplus.com/*
// @grant          none
// @require        https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js
// @require        https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js
// ==/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="";
    document.downloadall=false;
    document.downloadid=0;
    document.waitsub=false;
    var segid=0;
    var vtturl;

    // Add download icon
   	document.styleSheets[0].addRule('#subtitleTrackPicker > div','--percent: "All";');
    document.styleSheets[0].addRule('#subtitleTrackPicker > div:before','content:"";color:#fff;padding-right:25px;padding-top:2px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAIGNIUk0AAHonAACAgwAA+mQAAIDSAAB2hgAA7OkAADmeAAAV/sZ+0zoAAAE4SURBVHja1JS7LkRRFIa/M6aYRCEuCUEUgihFBolGVGqiFY1ConfpNB7CiygUGm8hOiMukwiCCMl8mj2xc5yZM8M0/mTlrLP2v75zydo7UclRL3AGlIAl4L6ZuUC+5oEZYBoo55lbAdai/LPTwFongG3pfwI3gZ3ovhjlXVG+BWz/6FbjKPuto1CbjWoLobYf1RZjRho4pt5F5g11QK2F6FFXo/UXdbwZEHVQvY2aztWPECdR/TkNawREHUpB03pSJ7J6Cf9gL3xOvDiiXmfAHtSplLek7qorqI/BeJjxxFG1kgNDPQjrn4VoLPozRqgCzAGXwFXILzJ8w+H6XgRegW7grcGs3gCTOfP8UgfGg139wwapxrugDl0H+oCkTZjAcsiTxBaO7HZUBI6BtfCmv4Un4aw8/RoA7wq6AO4uOhAAAAAASUVORK5CYII=) no-repeat right;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:var(--percent);');
};

// 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];
        if(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){
    	var lang = this.childNodes[0].childNodes[1].innerHTML;
    	if(lang=="Off"){
    		// Download all subs
    		document.zip = new JSZip();
    		document.downloadall=true;
    		document.downloadid=-1;
    		downloadnext();
    	}
    	else {
        	// Download sub
        	download(lang);
        }
        // Cancel selection
        return false;
    }
}

function downloadnext(){
	document.downloadid++;
	while(typeof document.langs[document.downloadid] !== 'undefined' && document.langs[document.downloadid].FORCED=="YES"){
		document.downloadid++;
	}

	if(document.downloadid<document.langs.length){
    	document.styleSheets[0].addRule('#subtitleTrackPicker > div:first-child:before','padding-right:35px;content:"'+Math.round((document.downloadid/document.langs.length)*100)+'%";');
		download(document.langs[document.downloadid].NAME);
	}
	else {
		clearInterval(document.downloadinterval);
    	document.styleSheets[0].addRule('#subtitleTrackPicker > div:first-child:before','padding-right:25px;content:"All";');

		document.zip.generateAsync({type:"blob"}).then(function(content) {
			var output = document.filename;
			if(document.episode!="") {
				output+= " - "+document.episode.replace(':','');
			}
			saveAs(content, output+".zip");
		});
	}
}

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.waitsub=true;
                document.waitInterval = setInterval(function () {
                    if(!document.wait) {
                        document.forced=true;
                        clearInterval(document.waitInterval);
                        getpagecontent(m3u8loaded,document.baseurl+lang.URI);
                        document.wait=true;
                    }
                },10);
            }
        });
        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";
        document.waitsub=false;
    }
    output += ".srt";

    if(document.downloadall){
   		document.zip.file(output, text);
    	document.downloadinterval = setTimeout(function () { 
    		document.wait = false;
    		if(!document.waitsub){
    			downloadnext();
    		}
    	},20);
    }
    else {
	    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; },50);
    }
}

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;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址