Greasy Fork

悦读pdf下载

try to take over the world!

当前为 2020-09-24 提交的版本,查看 最新版本

// ==UserScript==
// @name         悦读pdf下载
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://yd.51zhy.cn/ebook/reader/index.html*
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/1.10.0/jquery.min.js
// @grant        none
// ==/UserScript==


function loadStyle(url){
    var link = document.createElement('link');
    link.type = 'text/css';
    link.rel = 'stylesheet';
    link.href = url;
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(link);
}

function loadScript(url, callback){
    var script = document.createElement ("script")
    script.type = "text/javascript";
    if (script.readyState){ //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" || script.readyState == "complete"){
				script.onreadystatechange = null;
				if(typeof(callback) == 'function')
                	callback();
            }
        };
    } else { //Others
        script.onload = function(){
			if(typeof(callback) == 'function')
				callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

//获取元素在数组的下标
Array.prototype.indexOf = function(val) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] == val)	{ 
			return i;
		};
	}
	return -1; 
};

//根据数组的下标,删除该下标的元素
// Array.prototype.remove = function(val) {
// 	var index = this.indexOf(val);
// 	if (index > -1) {
// 	this.splice(index, 1);
// 	}
// };

function range(start, stop, step = 1) {
    return Array(Math.ceil((stop - start) / step))
    .fill(start)
    .map((x, y) => x + y * step)
}

function Uint8ToString(u8a){
    var CHUNK_SZ = 0x8000;
    var c = [];
    for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
      c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
    }
    return c.join("");
}

function fakeClick(obj) {
    var ev = document.createEvent("MouseEvents");
    ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    obj.dispatchEvent(ev);
 }
 
function exportRaw(name, data) {
      var urlObject = window.URL || window.webkitURL || window;
      var export_blob = new Blob([data]);
      var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
      save_link.href = urlObject.createObjectURL(export_blob);
      save_link.download = name;
      fakeClick(save_link);
} 



// 保存加载过的页面
// key 为页码,从0开始
// val 为u8n
var pages_save = {};

// 浏览器直接下载时,pages_save不保存页面,pages_downloaded保存已经下载过的
var pages_downloaded = [];
var download_direct = 1;
// vue接口
var v;

// 依赖vue接口
// v = window.$vm.$children[0].$children[0].$children[0]
// v.pageArr
// v.DetailData.Title
// v.numberOfPages
// v.pageIndex
// v.setLoadTask()



// 注册到window便于调试
window.pages_save = pages_save;
window.v = v;


// v = window.$vm.$children[0].$children[0].$children[0]
// v.pageArr
// 检查是否有新的页面已经下载
function check_new(){
    v.pageArr.forEach(function (val,idx){
        // console.log('check:',idx,val.isLoadIng,val);
        if(val.isLoadIng == true)return;
        // 直接下载
        if(download_direct == 1){
            if(idx in need_download_pages && !(idx in pages_downloaded)){
                pages_downloaded.push(idx);
                var page_num = idx+1;
                exportRaw(v.DetailData.Title+'_' + page_num.toString()+".pdf", val.getUint8Array);
                show_msg("[Download] page:", page_num, '/', v.numberOfPages);
            }
        }
        // 保存导出json下载
        else{
            if(pages_save[idx]==undefined){
                pages_save[idx] = val.getUint8Array;
                show_msg("[Page] got page:", idx+1, '/', v.numberOfPages);
            }
        }
    });

    // 计算进度
    var cnt = 0;
    need_download_pages.forEach(function(num){
        if(download_direct){
            if(num in pages_downloaded){
                cnt++;
            }
        }
        else{
            if(pages_save[num]!=undefined){
                cnt++;
            }
        }
    })
    var p = Math.round(cnt/need_download_pages.length*100);
    set_progress(p);
}

// 周期check
var check_timer;
function start_check(){
    check_timer = setInterval(function (){
        check_new();
    },1000);
}
function stop_check(){
    clearInterval(check_timer);
}

// 跳转到页 page_num从0开始
// 内部调用check
function jump_page(page_num){
    if(page_num>=v.numberOfPages){
        show_msg('页码超出范围。',page_num);
        return;
    }
    v.pageIndex = page_num;
    v.setLoadTask();
    check_new();
}


// 对于need_download_pages中的下载任务,自动进行
var auto_next_timer;
var current_task_idx;
var is_done = 0;
// tasks
// 内容为页码 页码从0开始
var need_download_pages = [];
window.need_download_pages = need_download_pages;

// t 单位s 最小5s
// start 开始的序号
// pages 需要下载的页码 从0开始
function start_auto_next(t, start, pages){
    if(t<=5 || t == undefined){
        t = 5;
    } 
    if(start == undefined){
        current_task_idx = 0;
        start = 0;
    }
    else{
        current_task_idx = start;
    }
    if(pages == undefined)
        pages = [...Array(v.numberOfPages).keys()];
    
    need_download_pages = [];
    for(var i=0;i<pages.length;i++){
        if(pages[i]<v.numberOfPages && pages[i]>0)
            need_download_pages.push(pages[i]);
    }
    console.log('pages:', need_download_pages);
    auto_next_timer = setInterval(function(){
        check_new();
        var s = current_task_idx;
        var cnt = 0;
        while(cnt<need_download_pages.length){
            var page_num = need_download_pages[s];
            if(page_num in pages_downloaded || pages_save[page_num]!=undefined){
                // 已经下载过了
                s ++;
                s = s%need_download_pages.length;
                cnt++;
            }
            else{
                break;
            }
        }
        if(cnt>=need_download_pages.length){
            // 下载完成
            is_done = 1;
            stop_auto_next();
            set_progress(100);
        }
        else{
            // 下载
            jump_page(need_download_pages[s]);
            current_task_idx = s;
            show_msg('[Jump]',current_task_idx,"page:",need_download_pages[s]+1);
        }
    },t*1000);
}
function stop_auto_next(){
    clearInterval(auto_next_timer);
}

var download_obj = {};
function export_pages(){
    download_obj['pages']={};
    var page_nums = Object.keys(pages_save);
    page_nums.forEach(function(val){
        download_obj['pages'][val] = Uint8ToString(pages_save[val]);
    })
}

function parse_pages(str){
    var pages = [];
    str = str.replace('\n',',');
    var _pages = str.split(',');
    for(var i=0,len=_pages.length;i<len;i++){
        var p = _pages[i]
        if (p.match(/^\d+$/)){
            pages.push(Number(p));
        }
        else{
            rep = p.match(/^(\d+)-(\d+)$/)
            if(rep){
                pages=pages.concat(range(Number(rep[1]), Number(rep[2])+1));
            }
        }
    }
    pages = [...new Set(pages)];
    return pages.sort(function(a, b){return a - b})
}

var download_all_timer;
function download(t, need){
    console.log(need);
    is_done = 0;
    while(v==undefined){
        v = window.$vm.$children[0].$children[0].$children[0];
        show_msg('[Wait] window.$vm');
        set_status('wait window.$vm');
    }
    show_msg('[OK] window.$vm');
    set_status('Downloading...');

    // start_check();
    start_auto_next(t, 0, need);
    clearInterval(download_all_timer);
    download_all_timer = setInterval(function (){
        if(is_done == 1){
            if(download_direct != 1){
                export_pages();
                download_obj['DetailData'] = v.DetailData;
                var out = JSON.stringify(download_obj, null, 4);
                exportRaw(v.DetailData.Title+'.json', out);
            }else{
                pages_downloaded = [];
            }
            clearInterval(download_all_timer);
            show_msg('Download Done.');
            set_status('Download OK!');
        }
    },1000);
}

// 终止下载
function cancel_download(){
    stop_auto_next();
    clearInterval(download_all_timer);
    is_done = 0;
    need_download_pages = [];
    pages_save = {};
    show_msg("[Cancel]:cancel download all OK!");
	set_status('Ready! pages:'+v.numberOfPages.toString());

}


function set_progress(n){
	if(window.element){
		element.progress('mprogress', n.toString()+'%');
	}
}

function set_status(msg){
	$('#mstatus').text(msg);
}

function show_msg(msg){
	var s = ''
	for(var i=0; i<arguments.length;i++){
		s+=' '+String(arguments[i]);
	}
	console.log(s);
	if(typeof(layer.msg) == 'function'){
		layer.msg(s, {
			offset: 't',
			anim: 5,
			area: 300
		  });
	}
}

// direct 1 浏览器直接下载
function fun_btn(direct = 1){
    layer.prompt({
        type: 1,
        formType: 2,
        closeBtn: 1,
        resize: false,
        btn:["确定"],
        value: '1-'+v.numberOfPages.toString(),
        area: ['500px', '100px'],
        title: '请输入要下载的页码,起始为1,例如:1-5,10,15,20-30',
    },
    function(value, index, elem){
        // layer.alert(JSON.stringify(value));
        layer.close(index);
        var need = parse_pages(value);
        layer.msg(JSON.stringify(need));
        // 转换为从0开始
        for(i in need){need[i]--;};
        //输入间隔时间
        layer.prompt({
                formType: 0,
                closeBtn: 0,
                resize: false,
                btn:["确定"],
                value: '10',
                area: ['500px', '100px'],
                title: '请输入自动加载间隔时间',
            },
            function(value, index, elem){
                layer.close(index);
                if(direct)
                    download_direct = 1;
                else
                    download_direct = 0;
                download(Number(value), need);
            });
    });
}

loadStyle("https://www.layuicdn.com/layui/css/layui.css")
loadScript("https://www.layuicdn.com/layui/layui.all.js", function(){
	// 由于引入的为all.js 模块都一次性加载,因此不用执行 layui.use() 来加载对应模块,直接使用即可layer,element

	layer.open({
        type: 1,
        content: '<div style="padding:20px;text-align: center;"><h3>Github:<a style="color: #23696f" href="https://github.com/ygcaicn/keledge" target="_blank">Star</a></h3><br><p>Status:<span id="mstatus">Ready!</span></p></div> <div class="layui-progress layui-progress-big" lay-filter="mprogress" lay-showpercent="true"><div class="layui-progress-bar" lay-percent="0%"></div></div>',
        skin: 'layui-layer-molv',
        shade: 0,
        btnAlign: 'c' ,
        offset: 'rt',
        area:'300px',
        btn: ['Download', 'Cancel'],
       btn1: function(){
            fun_btn();
            return false;
       },
    //    btn2: function(){
    //         fun_btn(0);
    //         return false;
    //     },
       btn2: function(){
            cancel_download();
            return false;
       }
	});
	window.element = layui.element;
    window.element.init();
    set_status('Wait initing...');
})

var wait_vue_timer;
wait_vue_timer = setInterval(function(){
    if(v == undefined){
        v = window.$vm.$children[0].$children[0].$children[0];
        show_msg('[Wait] window.$vm');
        set_status('wait window.$vm');
    }
    else{
        show_msg('[OK] window.$vm');
        set_status('Loading numberOfPages...');
        var _t = setInterval(function (){
            if(v.numberOfPages != undefined && v.numberOfPages > 0){
                set_status('Ready! pages:'+v.numberOfPages.toString());
                clearInterval(_t);
            }
        },200);
        clearInterval(wait_vue_timer);
    }
},200)