• 摆渡网盘下载助手


    网盘下载助手

    (1.) 先安装谷歌插件,油泼猴子

    (2.)添加新脚本

    // ==UserScript==
    // @name              网盘直链下载助手
    // @namespace         https://github.com/syhyz1990/baiduyun
    // @version           5.6.7
    // @author            YouXiaoHou
    // @icon              https://www.youxiaohou.com/48x48.png
    // @icon64            https://www.youxiaohou.com/64x64.png
    // @description       可以获取网盘文件真实下载地址。现已支持 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 四大网盘,可使用 IDM,Xdown,Aria2,Curl 等工具下载,完美适配 Chrome,Edge,FireFox,360,QQ 等 18 种浏览器,可在无法安装客户端的环境下使用,助手免费开源。
    // @license           AGPL
    // @homepage          https://www.youxiaohou.com/install.html
    // @supportURL        https://github.com/syhyz1990/baiduyun
    // @match             *://pan.baidu.com/disk/home*
    // @match             *://yun.baidu.com/disk/home*
    // @match             *://pan.baidu.com/disk/main*
    // @match             *://yun.baidu.com/disk/main*
    // @match             *://pan.baidu.com/s/*
    // @match             *://yun.baidu.com/s/*
    // @match             *://pan.baidu.com/share/*
    // @match             *://yun.baidu.com/share/*
    // @match             *://www.aliyundrive.com/s/*
    // @match             *://www.aliyundrive.com/drive*
    // @match             *://cloud.189.cn/web/*
    // @match             *://pan.xunlei.com/*
    // @require           https://unpkg.com/jquery@3.6.0/dist/jquery.min.js
    // @require           https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.all.min.js
    // @connect           baidu.com
    // @connect           baidupcs.com
    // @connect           aliyundrive.com
    // @connect           189.cn
    // @connect           xunlei.com
    // @connect           youxiaohou.com
    // @connect           localhost
    // @connect           *
    // @run-at            document-idle
    // @grant             unsafeWindow
    // @grant             GM_xmlhttpRequest
    // @grant             GM_setClipboard
    // @grant             GM_setValue
    // @grant             GM_getValue
    // @grant             GM_openInTab
    // @grant             GM_info
    // @grant             GM_registerMenuCommand
    // @grant             GM_cookie
    // ==/UserScript==
    
    (function () {
        'use strict';
    
        let pt = '', selectList = [], params = {}, mode = '', width = 800, pan = {}, color = '',
            doc = $(document), progress = {}, request = {}, ins = {}, idm = {};
        const scriptInfo = GM_info.script;
        const version = scriptInfo.version;
        const author = scriptInfo.author;
        const name = scriptInfo.name;
        const customClass = {
            popup: 'pl-popup',
            header: 'pl-header',
            title: 'pl-title',
            closeButton: 'pl-close',
            content: 'pl-content',
            input: 'pl-input',
            footer: 'pl-footer'
        };
    
        const terminalType = {
            wc: "Windows CMD",
            wp: "Windows PowerShell",
            lt: "Linux 终端",
            ls: "Linux Shell",
            mt: "MacOS 终端",
        };
    
        let toast = Swal.mixin({
            toast: true,
            position: 'top',
            showConfirmButton: false,
            timer: 3500,
            timerProgressBar: false,
            didOpen: (toast) => {
                toast.addEventListener('mouseenter', Swal.stopTimer);
                toast.addEventListener('mouseleave', Swal.resumeTimer);
            }
        });
    
        const message = {
            success: (text) => {
                toast.fire({title: text, icon: 'success'});
            },
            error: (text) => {
                toast.fire({title: text, icon: 'error'});
            },
            warning: (text) => {
                toast.fire({title: text, icon: 'warning'});
            },
            info: (text) => {
                toast.fire({title: text, icon: 'info'});
            },
            question: (text) => {
                toast.fire({title: text, icon: 'question'});
            }
        };
    
        let base = {
            clog(c) {
                console.group(`[${name}]`);
                console.log(c);
                console.groupEnd();
            },
    
            getCookie(name) {
                let arr = document.cookie.replace(/\s/g, "").split(';');
                for (let i = 0, l = arr.length; i < l; i++) {
                    let tempArr = arr[i].split('=');
                    if (tempArr[0] === name) {
                        return decodeURIComponent(tempArr[1]);
                    }
                }
                return '';
            },
    
            getValue(name) {
                return GM_getValue(name);
            },
    
            setValue(name, value) {
                GM_setValue(name, value);
            },
    
            getStorage(key) {
                return localStorage.getItem(key);
            },
    
            setStorage(key, value) {
                return localStorage.setItem(key, value);
            },
    
            setClipboard(text) {
                GM_setClipboard(text, 'text');
            },
    
            e(str) {
                return btoa(unescape(encodeURIComponent(str)));
            },
    
            d(str) {
                return decodeURIComponent(escape(atob(str)));
            },
    
            getExtension(name) {
                const reg = /(?!\.)\w+$/;
                if (reg.test(name)) {
                    let match = name.match(reg);
                    return match[0].toUpperCase();
                }
                return '';
            },
    
            sizeFormat(value) {
                if (value === +value) {
                    let unit = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
                    let index = Math.floor(Math.log(value) / Math.log(1024));
                    let size = value / Math.pow(1024, index);
                    size = size.toFixed(1);
                    return size + unit[index];
                }
                return '';
            },
    
            sortByName(arr) {
                const handle = () => {
                    return (a, b) => {
                        const p1 = a.filename ? a.filename : a.server_filename;
                        const p2 = b.filename ? b.filename : b.server_filename;
                        return p1.localeCompare(p2, "zh-CN");
                    };
                };
                arr.sort(handle());
            },
    
            blobDownload(blob, filename) {
                if (blob instanceof Blob) {
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = filename;
                    a.click();
                    URL.revokeObjectURL(url);
                }
            },
    
            post(url, data, headers, type) {
                if (Object.prototype.toString.call(data) === '[object Object]') {
                    data = JSON.stringify(data);
                }
                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "POST", url, headers, data,
                        responseType: type || 'json',
                        onload: (res) => {
                            type === 'blob' ? resolve(res) : resolve(res.response || res.responseText);
                        },
                        onerror: (err) => {
                            reject(err);
                        },
                    });
                });
            },
    
            get(url, headers, type, extra) {
                return new Promise((resolve, reject) => {
                    let requestObj = GM_xmlhttpRequest({
                        method: "GET", url, headers,
                        responseType: type || 'json',
                        onload: (res) => {
                            if (res.status === 204) {
                                requestObj.abort();
                                idm[extra.index] = true;
                            }
                            if (type === 'blob') {
                                res.status === 200 && base.blobDownload(res.response, extra.filename);
                                resolve(res);
                            } else {
                                resolve(res.response || res.responseText);
                            }
                        },
                        onprogress: (res) => {
                            if (extra && extra.filename && extra.index) {
                                res.total > 0 ? progress[extra.index] = (res.loaded * 100 / res.total).toFixed(2) : progress[extra.index] = 0.00;
                            }
                        },
                        onloadstart() {
                            extra && extra.filename && extra.index && (request[extra.index] = requestObj);
                        },
                        onerror: (err) => {
                            reject(err);
                        },
                    });
                });
            },
    
            addStyle(id, tag, css) {
                tag = tag || 'style';
                let doc = document, styleDom = doc.getElementById(id);
                if (styleDom) return;
                let style = doc.createElement(tag);
                style.rel = 'stylesheet';
                style.id = id;
                tag === 'style' ? style.innerHTML = css : style.href = css;
                doc.getElementsByTagName('head')[0].appendChild(style);
            },
    
            initDefaultConfig() {
                let value = [{
                    name: 'setting_rpc_domain',
                    value: 'http://localhost'
                }, {
                    name: 'setting_rpc_port',
                    value: '16800'
                }, {
                    name: 'setting_rpc_path',
                    value: '/jsonrpc'
                }, {
                    name: 'setting_rpc_token',
                    value: ''
                }, {
                    name: 'setting_rpc_dir',
                    value: 'D:'
                }, {
                    name: 'setting_terminal_type',
                    value: 'wc'
                }, {
                    name: 'setting_theme_color',
                    value: '#09AAFF'
                }, {
                    name: 'setting_init_code',
                    value: '80149'
                }];
    
                value.forEach((v) => {
                    base.getValue(v.name) === undefined && base.setValue(v.name, v.value);
                });
            },
    
            showSetting() {
                let dom = '', btn = '',
                    colorList = ['#09AAFF', '#cc3235', '#526efa', '#518c17', '#ed944b', '#f969a5', '#bca280'];
                dom += `<label class="pl-setting-label"><div class="pl-label">RPC主机</div><input type="text"  placeholder="主机地址,需带上http(s)://" class="pl-input listener-domain" value="${base.getValue('setting_rpc_domain')}"></label>`;
                dom += `<label class="pl-setting-label"><div class="pl-label">RPC端口</div><input type="text" placeholder="端口号,例如:Motrix为16800" class="pl-input listener-port" value="${base.getValue('setting_rpc_port')}"></label>`;
                dom += `<label class="pl-setting-label"><div class="pl-label">RPC路径</div><input type="text" placeholder="路径,默认为/jsonrpc" class="pl-input listener-path" value="${base.getValue('setting_rpc_path')}"></label>`;
                dom += `<label class="pl-setting-label"><div class="pl-label">RPC密钥</div><input type="text" placeholder="无密钥无需填写" class="pl-input listener-token" value="${base.getValue('setting_rpc_token')}"></label>`;
                dom += `<label class="pl-setting-label"><div class="pl-label">保存路径</div><input type="text" placeholder="文件下载后保存路径,例如:D:" class="pl-input listener-dir" value="${base.getValue('setting_rpc_dir')}"></label>`;
    
                colorList.forEach((v) => {
                    btn += `<div data-color="${v}" style="background: ${v};border: 1px solid ${v}" class="pl-color-box listener-color ${v === base.getValue('setting_theme_color') ? 'checked' : ''}"></div>`;
                });
                dom += `<label class="pl-setting-label"><div class="pl-label">终端类型</div><select class="pl-input listener-terminal">`;
                Object.keys(terminalType).forEach(k => {
                    dom += `<option value="${k}" ${base.getValue('setting_terminal_type') === k ? 'selected' : ''}>${terminalType[k]}</option>`;
                });
                dom += `</select></label>`;
                dom += `<label class="pl-setting-label"><div class="pl-label">主题颜色</div> <div class="pl-color">${btn}<div></label>`;
                dom = '<div>' + dom + '</div>';
    
                Swal.fire({
                    title: '助手配置',
                    html: dom,
                    icon: 'info',
                    showCloseButton: true,
                    showConfirmButton: false,
                    footer: pan.footer,
                }).then(() => {
                    message.success('设置成功!');
                    history.go(0);
                });
    
                doc.on('click', '.listener-color', async (e) => {
                    base.setValue('setting_theme_color', e.target.dataset.color);
                    message.success('设置成功!');
                    history.go(0);
                });
                doc.on('input', '.listener-domain', async (e) => {
                    base.setValue('setting_rpc_domain', e.target.value);
                });
                doc.on('input', '.listener-port', async (e) => {
                    base.setValue('setting_rpc_port', e.target.value);
                });
                doc.on('input', '.listener-path', async (e) => {
                    base.setValue('setting_rpc_path', e.target.value);
                });
                doc.on('input', '.listener-token', async (e) => {
                    base.setValue('setting_rpc_token', e.target.value);
                });
                doc.on('input', '.listener-dir', async (e) => {
                    base.setValue('setting_rpc_dir', e.target.value);
                });
                doc.on('change', '.listener-terminal', async (e) => {
                    base.setValue('setting_terminal_type', e.target.value);
                });
            },
    
            registerMenuCommand() {
                GM_registerMenuCommand('⚙️ 设置', () => {
                    this.showSetting();
                });
            },
    
            createTip() {
                $('body').append('<div class="pl-tooltip"></div>');
    
                doc.on('mouseenter mouseleave', '.listener-tip', (e) => {
                    if (e.type === 'mouseenter') {
                        let filename = e.currentTarget.innerText;
                        let size = e.currentTarget.dataset.size;
                        let tip = `${filename}<span style="margin-left: 10px;color: #f56c6c;">${size}</span>`;
                        $(e.currentTarget).css({opacity: '0.5'});
                        $('.pl-tooltip').html(tip).css({
                            'left': e.pageX + 10 + 'px',
                            'top': e.pageY - e.currentTarget.offsetTop > 14 ? e.pageY + 'px' : e.pageY + 20 + 'px'
                        }).show();
                    } else {
                        $(e.currentTarget).css({opacity: '1'});
                        $('.pl-tooltip').hide(0);
                    }
                });
            },
    
            createLoading() {
                return $('<div class="pl-loading"><div class="pl-loading-box"><div><div></div><div></div></div></div></div>');
            },
    
            createDownloadIframe() {
                let $div = $('<div style="padding:0;margin:0;display:block"></div>');
                let $iframe = $('<iframe src="javascript:;" id="downloadIframe" style="display:none"></iframe>');
                $div.append($iframe);
                $('body').append($div);
            },
    
            addPanLinkerStyle() {
                color = base.getValue('setting_theme_color');
                let css = `
                body::-webkit-scrollbar { display: none }
                ::-webkit-scrollbar {  6px; height: 10px }
                ::-webkit-scrollbar-track { border-radius: 0; background: none }
                ::-webkit-scrollbar-thumb { background-color: rgba(85,85,85,.4) }
                ::-webkit-scrollbar-thumb,::-webkit-scrollbar-thumb:hover { border-radius: 5px; -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.2) }
                ::-webkit-scrollbar-thumb:hover { background-color: rgba(85,85,85,.3) }
                .swal2-popup { font-size: 16px !important; }
                .pl-popup { font-size: 12px !important; }
                .pl-popup a { color: ${color} !important; }
                .pl-header { padding: 0!important;align-items: flex-start!important; border-bottom: 1px solid #eee!important; margin: 0 0 10px!important; padding: 0 0 5px!important; }
                .pl-title { font-size: 16px!important; line-height: 1!important;white-space: nowrap!important; text-overflow: ellipsis!important;}
                .pl-content { padding: 0 !important; font-size: 12px!important; }
                .pl-main { max-height: 400px;overflow-y:scroll; }
                .pl-footer {font-size: 12px!important;justify-content: flex-start!important; margin: 10px 0 0!important; padding: 5px 0 0!important; color: #f56c6c!important; }
                .pl-item { display: flex; align-items: center; line-height: 22px; }
                .pl-item-name { flex: 0 0 150px; text-align: left;margin-right: 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor:default; }
                .pl-item-link { flex: 1; overflow: hidden; text-align: left; white-space: nowrap; text-overflow: ellipsis;cursor:pointer }
                .pl-item-btn { background: ${color}; padding: 4px 5px; border-radius: 3px; line-height: 1; cursor: pointer; color: #fff; }
                .pl-item-tip { display: flex; justify-content: space-between;flex: 1; }
                .pl-back {  70px; background: #ddd; border-radius: 3px; cursor:pointer; margin:1px 0; }
                .pl-ext { display: inline-block;  44px; background: #999; color: #fff; height: 16px; line-height: 16px; font-size: 12px; border-radius: 3px;}
                .pl-retry {padding: 3px 10px; background: #cc3235; color: #fff; border-radius: 3px; cursor: pointer;}
                .pl-browserdownload { padding: 3px 10px; background: ${color}; color: #fff; border-radius: 3px; cursor: pointer;}
                .pl-item-progress { display:flex;flex: 1;align-items:center}
                .pl-progress { display: inline-block;vertical-align: middle; 100%; box-sizing: border-box;line-height: 1;position: relative;height:15px; flex: 1}
                .pl-progress-outer { height: 15px;border-radius: 100px;background-color: #ebeef5;overflow: hidden;position: relative;vertical-align: middle;}
                .pl-progress-inner{ position: absolute;left: 0;top: 0;background-color: #409eff;text-align: right;border-radius: 100px;line-height: 1;white-space: nowrap;transition: width .6s ease;}
                .pl-progress-inner-text { display: inline-block;vertical-align: middle;color: #d1d1d1;font-size: 12px;margin: 0 5px;height: 15px}
                .pl-progress-tip{ flex:1;text-align:right}
                .pl-progress-how{ flex: 0 0 90px; background: #ddd; border-radius: 3px; margin-left: 10px; cursor: pointer; text-align: center;}
                .pl-progress-stop{ flex: 0 0 50px; padding: 0 10px; background: #cc3235; color: #fff; border-radius: 3px; cursor: pointer;margin-left:10px;height:20px}
                .pl-progress-inner-text:after { display: inline-block;content: "";height: 100%;vertical-align: middle;}
                .pl-btn-primary { background: ${color}; border: 0; border-radius: 4px; color: #ffffff; cursor: pointer; font-size: 12px; outline: none; display:flex; align-items: center; justify-content: center; margin: 2px 0; padding: 6px 0;transition: 0.3s opacity; }
                .pl-btn-primary:hover { opacity: 0.9;transition: 0.3s opacity; }
                .pl-btn-success { background: #55af28; animation: easeOpacity 1.2s 2; animation-fill-mode:forwards }
                .pl-btn-info { background: #606266; }
                .pl-btn-warning { background: #da9328; }
                .pl-btn-warning { background: #da9328; }
                .pl-btn-danger { background: #cc3235; }
                .ali-button {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;border-radius: 5px;box-shadow: 0 0 0 0 transparent; fit-content;white-space: nowrap;flex-shrink: 0;font-size: 14px;line-height: 1.5;outline: 0;touch-action: manipulation;transition: background .3s ease,color .3s ease,border .3s ease,box-shadow .3s ease;color: #fff;background: rgb(99 125 255);margin-left: 20px;padding: 1px 12px;position: relative; cursor:pointer; height: 32px;}
                .ali-button:hover {background: rgb(122, 144, 255)}
                .tianyi-button {margin-right: 20px; padding: 4px 12px; border-radius: 4px; color: #fff; font-size: 12px; border: 1px solid #0073e3; background: #2b89ea; cursor: pointer; position: relative;}
                .tianyi-button:hover {border-color: #1874d3; background: #3699ff;}
                .xunlei-button {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;border-radius: 5px;box-shadow: 0 0 0 0 transparent; fit-content;white-space: nowrap;flex-shrink: 0;font-size: 14px;line-height: 1.5;outline: 0;touch-action: manipulation;transition: background .3s ease,color .3s ease,border .3s ease,box-shadow .3s ease;color: #fff;background: #3f85ff;margin-left: 12px;padding: 0px 12px;position: relative; cursor:pointer; height: 36px;}
                .xunlei-button:hover {background: #619bff}
                .pl-dropdown-menu {position: absolute;right: 0;top: 34px;padding: 5px 0;color: rgb(37, 38, 43);background: #fff;z-index: 999; 102px;border: 1px solid #ddd;border-radius: 10px; box-shadow: 0 0 1px 1px rgb(28 28 32 / 5%), 0 8px 24px rgb(28 28 32 / 12%);}
                .pl-dropdown-menu-item { height: 30px;display: flex;align-items: center;justify-content: center; }
                .pl-dropdown-menu-item:hover { background-color: rgba(132,133,141,0.08);}
                .pl-button-init { opacity: 0.5; animation: easeInitOpacity 1.2s 3; animation-fill-mode:forwards }
                 @keyframes easeInitOpacity { from { opacity: 0.5; } 50% { opacity: 1 } to { opacity: 0.5; } }
                 @keyframes easeOpacity { from { opacity: 1; } 50% { opacity: 0.35 } to { opacity: 1; } }
                .element-clicked { opacity: 0.5; }
                .pl-extra { margin-top: 10px;display:flex}
                .pl-extra button { flex: 1}
                .pointer { cursor:pointer }
                .pl-setting-label { display: flex;align-items: center;justify-content: space-between;padding-top: 10px; }
                .pl-label { flex: 0 0 100px;text-align:left; }
                .pl-input { flex: 1; padding: 8px 10px; border: 1px solid #c2c2c2; border-radius: 5px; font-size: 14px }
                .pl-color { flex: 1;display: flex;flex-wrap: wrap; margin-right: -10px;}
                .pl-color-box {  35px;height: 35px;margin:10px 10px 0 0;; box-sizing: border-box;border:1px solid #fff;cursor:pointer }
                .pl-color-box.checked { border:3px dashed #111!important }
                .pl-close:focus { outline: 0; box-shadow: none; }
                .tag-danger {color:#cc3235;margin: 0 5px;}
                .pl-tooltip { position: absolute; color: #ffffff; max- 600px; font-size: 12px; padding: 5px 10px; background: #333; border-radius: 5px; z-index: 110000; line-height: 1.3; display:none; word-break: break-all;}
                 @keyframes load { 0% { transform: rotate(0deg) } 100% { transform: rotate(360deg) } }
                .pl-loading-box > div > div { position: absolute;border-radius: 50%;}
                .pl-loading-box > div > div:nth-child(1) { top: 9px;left: 9px; 82px;height: 82px;background: #ffffff;}
                .pl-loading-box > div > div:nth-child(2) { top: 14px;left: 38px; 25px;height: 25px;background: #666666;animation: load 1s linear infinite;transform-origin: 12px 36px;}
                .pl-loading {  16px;height: 16px;display: inline-block;overflow: hidden;background: none;}
                .pl-loading-box {  100%;height: 100%;position: relative;transform: translateZ(0) scale(0.16);backface-visibility: hidden;transform-origin: 0 0;}
                .pl-loading-box div { box-sizing: content-box; }
                .swal2-container { z-index:100000!important; }
                body.swal2-height-auto { height: inherit!important; }
                `;
                this.addStyle('panlinker-style', 'style', css);
            },
    
            async initDialog() {
                let result = await Swal.fire({
                    title: pan.init[0],
                    html: `<div><img style=" 250px;margin-bottom: 10px;" src="${pan.img}" alt="${pan.img}"><input class="swal2-input" id="init" type="text" placeholder="${pan.init[1]}"></div>`,
                    allowOutsideClick: false,
                    showCloseButton: true,
                    confirmButtonText: '确定'
                });
                if (result.isDismissed && result.dismiss === 'close') return;
                if (pan.num === $('#init').val()) {
                    base.setValue('setting_init_code', pan.num);
                    message.success(pan.init[2]);
                    setTimeout(() => {
                        history.go(0);
                    }, 1500);
                } else {
                    await Swal.fire({
                        title: pan.init[3],
                        text: pan.init[4],
                        confirmButtonText: '重新输入',
                        imageUrl: pan.img,
                    });
                    await this.initDialog();
                }
            },
        };
    
        let baidu = {
    
            _getExtra() {
                let seKey = decodeURIComponent(base.getCookie('BDCLND'));
                return '{' + '"sekey":"' + seKey + '"' + "}";
            },
    
            _getSurl() {
                let reg = /(?<=s\/|surl=)([a-zA-Z0-9_-]+)/g;
                if (reg.test(location.href)) {
                    return location.href.match(reg)[0];
                }
                return '';
            },
    
            _getFidList() {
                let fidlist = [];
                selectList.forEach(v => {
                    if (+v.isdir === 1) return;
                    fidlist.push(v.fs_id);
                });
                return '[' + fidlist + ']';
            },
    
            _resetData() {
                progress = {};
                $.each(request, (key) => {
                    (request[key]).abort();
                });
                $.each(ins, (key) => {
                    clearInterval(ins[key]);
                });
                idm = {};
                ins = {};
                request = {};
            },
    
            setBDUSS() {
                try {
                    GM_cookie && GM_cookie('list', {name: 'BDUSS'}, (cookies, error) => {
                        if (!error) {
                            base.setStorage("baiduyunPlugin_BDUSS", JSON.stringify({BDUSS: cookies[0].value}));
                        }
                    });
                } catch (e) {
                }
            },
    
            getBDUSS() {
                let baiduyunPlugin_BDUSS = base.getStorage('baiduyunPlugin_BDUSS') ? base.getStorage('baiduyunPlugin_BDUSS') : '{"baiduyunPlugin_BDUSS":""}';
                return JSON.parse(baiduyunPlugin_BDUSS).BDUSS || '';
            },
    
            convertLinkToAria(link, filename, ua) {
                let BDUSS = this.getBDUSS();
                if (!!BDUSS) {
                    filename = filename.replace(' ', '_');
                    return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "User-Agent: ${ua}" --header "Cookie: BDUSS=${BDUSS}"`);
                }
                return {
                    link: pan.assistant,
                    text: pan.init[5]
                };
            },
    
            convertLinkToCurl(link, filename, ua) {
                let BDUSS = this.getBDUSS();
                if (!!BDUSS) {
                    let terminal = base.getValue('setting_terminal_type');
                    filename = filename.replace(' ', '_');
                    return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}" -A "${ua}" -b "BDUSS=${BDUSS}"`);
                }
                return {
                    link: pan.assistant,
                    text: pan.init[5]
                };
            },
    
            addPageListener() {
                function _factory(e) {
                    let target = $(e.target);
                    let item = target.parents('.pl-item');
                    let link = item.find('.pl-item-link');
                    let progress = item.find('.pl-item-progress');
                    let tip = item.find('.pl-item-tip');
                    return {
                        item, link, progress, tip, target,
                    };
                }
    
                function _reset(i) {
                    ins[i] && clearInterval(ins[i]);
                    request[i] && request[i].abort();
                    progress[i] = 0;
                    idm[i] = false;
                }
    
                doc.on('mouseenter mouseleave click', '.pl-button', (e) => {
                    if (e.type === 'mouseleave') {
                        $(e.currentTarget).removeClass('button-open');
                    } else {
                        $(e.currentTarget).addClass('button-open');
                        $(e.currentTarget).find('.pl-menu').show();
                    }
                });
                doc.on('mouseleave', '.pl-menu', (e) => {
                    $(e.currentTarget).hide();
                });
                doc.on('click', '.pl-button-mode', (e) => {
                    mode = e.target.dataset.mode;
                    Swal.showLoading();
                    this.getPCSLink();
                });
                doc.on('click', '.listener-link-api', async (e) => {
                    e.preventDefault();
                    let o = _factory(e);
                    let $width = o.item.find('.pl-progress-inner');
                    let $text = o.item.find('.pl-progress-inner-text');
                    let filename = o.link[0].dataset.filename;
                    let index = o.link[0].dataset.index;
                    _reset(index);
                    base.get(o.link[0].dataset.link, {"User-Agent": pan.ua}, 'blob', {filename, index});
                    ins[index] = setInterval(() => {
                        let prog = +progress[index] || 0;
                        let isIDM = idm[index] || false;
                        if (isIDM) {
                            o.tip.hide();
                            o.progress.hide();
                            o.link.text('已成功唤起IDM,请查看IDM下载框!').animate({opacity: '0.5'}, "slow").show();
                            clearInterval(ins[index]);
                            idm[index] = false;
                        } else {
                            o.link.hide();
                            o.tip.hide();
                            o.progress.show();
                            $width.css('width', prog + '%');
                            $text.text(prog + '%');
                            if (prog === 100) {
                                clearInterval(ins[index]);
                                progress[index] = 0;
                                o.item.find('.pl-progress-stop').hide();
                                o.item.find('.pl-progress-tip').html('下载完成,正在弹出浏览器下载框!');
                            }
                        }
                    }, 500);
                });
                doc.on('click', '.listener-retry', async (e) => {
                    let o = _factory(e);
                    o.tip.hide();
                    o.link.show();
                });
                doc.on('click', '.listener-how', async (e) => {
                    let o = _factory(e);
                    let index = o.link[0].dataset.index;
                    if (request[index]) {
                        request[index].abort();
                        clearInterval(ins[index]);
                        o.progress.hide();
                        o.tip.show();
                    }
    
                });
                doc.on('click', '.listener-stop', async (e) => {
                    let o = _factory(e);
                    let index = o.link[0].dataset.index;
                    if (request[index]) {
                        request[index].abort();
                        clearInterval(ins[index]);
                        o.tip.hide();
                        o.progress.hide();
                        o.link.show(0);
                    }
                });
                doc.on('click', '.listener-back', async (e) => {
                    let o = _factory(e);
                    o.tip.hide();
                    o.link.show();
                });
                doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
                    e.preventDefault();
                    if (!e.target.dataset.link) {
                        $(e.target).removeClass('listener-copy-all').addClass('pl-btn-danger').html(`${pan.init[5]}<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>`);
                    } else {
                        base.setClipboard(decodeURIComponent(e.target.dataset.link));
                        $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
                    }
                });
                doc.on('click', '.listener-link-rpc', async (e) => {
                    let target = $(e.currentTarget);
                    target.find('.icon').remove();
                    target.find('.pl-loading').remove();
                    target.prepend(base.createLoading());
                    let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
                    if (res === 'success') {
                        $('.listener-rpc-task').show();
                        target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
                    } else if (res === 'assistant') {
                        target.addClass('pl-btn-danger').html(`${pan.init[5]}<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>`);
                    } else {
                        target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
                    }
                });
                doc.on('click', '.listener-send-rpc', (e) => {
                    $('.listener-link-rpc').click();
                    $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-open-setting', () => {
                    base.showSetting();
                });
                doc.on('click', '.listener-rpc-task', () => {
                    let rpc = JSON.stringify({
                        domain: base.getValue('setting_rpc_domain'),
                        port: base.getValue('setting_rpc_port'),
                    }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
                    GM_openInTab(url, {active: true});
                });
                document.documentElement.addEventListener('mouseup', (e) => {
                    if (e.target.nodeName === 'A' && ~e.target.className.indexOf('pl-a')) {
                        e.stopPropagation();
                    }
                }, true);
            },
    
            addButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="g-dropdown-button pointer pl-button"><div style="color:#fff;background: ${color};border-color:${color}" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download"></em><span class="text" style=" 60px;">下载助手</span></span></div><div class="menu" style="auto;z-index:41;border-color:${color}"><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="api">API下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="aria">Aria下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="rpc">RPC下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="curl">cURL下载</div>${pan.code == 200 && version < pan.version ? pan.new : ''}</div></div>`);
                if (pt === 'home') $toolWrap = $(pan.btn.home);
                if (pt === 'main') {
                    $toolWrap = $(pan.btn.main);
                    $button = $(`<div class="pl-button" style="position: relative; display: inline-block; margin-right: 8px;"><button class="u-button u-button--primary u-button--small is-round is-has-icon" style="background: ${color};border-color: ${color};font-size: 14px; padding: 8px 16px; border: none;"><i class="u-icon u-icon-download"></i><span>下载助手</span></button><ul class="dropdown-list nd-common-float-menu pl-menu" style="display: none;"><li class="sub cursor-p pl-button-mode" data-mode="api">API下载</li><li class="sub cursor-p pl-button-mode" data-mode="aria">Aria下载</li><li class="sub cursor-p pl-button-mode" data-mode="rpc">RPC下载</li><li class="sub cursor-p pl-button-mode" data-mode="curl">cURL下载</li>${pan.code == 200 && version < pan.version ? pan.newX : ''}</ul></div>`);
                }
                if (pt === 'share') $toolWrap = $(pan.btn.share);
                $toolWrap.prepend($button);
                base.clog(`助手加载成功!版本:${version}`);
                this.setBDUSS();
                this.addPageListener();
            },
    
            addInitButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="g-dropdown-button pointer pl-button-init" style="opacity:.5"><div style="color:#fff;background: ${color};border-color:${color}" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download"></em><span class="text" style=" 60px;">下载助手</span></span></div></div>`);
                if (pt === 'home') $toolWrap = $(pan.btn.home);
                if (pt === 'main') {
                    $toolWrap = $(pan.btn.main);
                    $button = $(`<div class="pl-button-init" style="opacity:.5; display: inline-block; margin-right: 8px;"><button class="u-button u-button--primary u-button--small is-round is-has-icon" style="background: ${color};border-color: ${color};font-size: 14px; padding: 8px 16px; border: none;"><i class="u-icon u-icon-download"></i><span>下载助手</span></button></div>`);
                }
                if (pt === 'share') $toolWrap = $(pan.btn.share);
                $toolWrap.prepend($button);
                $button.click(() => base.initDialog());
            },
    
            async getPCSLink() {
                selectList = this.getSelectedList();
                let fidList = this._getFidList(), url, res;
    
                if (pt === 'home' || pt === 'main') {
                    if (selectList.length === 0) {
                        return message.error('提示:请先勾选要下载的文件!');
                    }
                    if (fidList.length === 2) {
                        return message.error('提示:请打开文件夹后勾选文件!');
                    }
                    fidList = encodeURIComponent(fidList);
                    url = `${pan.pcs[0]}&fsids=${fidList}`;
                    res = await base.get(url, {"User-Agent": pan.ua});
                }
                if (pt === 'share') {
                    this.getShareData();
                    if (selectList.length === 0) {
                        return message.error('提示:请先勾选要下载的文件!');
                    }
                    if (fidList.length === 2) {
                        return message.error('提示:请打开文件夹后勾选文件!');
                    }
                    if (!params.sign) {
                        let url = `${pan.pcs[2]}&surl=${params.surl}&logid=${params.logid}`;
                        let r = await base.get(url);
                        if (r.errno === 0) {
                            params.sign = r.data.sign;
                            params.timestamp = r.data.timestamp;
                        } else {
                            let dialog = await Swal.fire({
                                toast: true,
                                icon: 'info',
                                title: `提示:请将文件<span class="tag-danger">[保存到网盘]</span>在<span class="tag-danger">[我的网盘]</span>中下载!`,
                                showConfirmButton: true,
                                confirmButtonText: '点击保存',
                                position: 'top',
                            });
                            if (dialog.isConfirmed) {
                                $('.tools-share-save-hb')[0].click();
                            }
                            return;
                        }
                    }
                    if (!params.bdstoken) {
                        return message.error('提示:请先登录网盘!');
                    }
                    let formData = new FormData();
                    formData.append('encrypt', params.encrypt);
                    formData.append('product', params.product);
                    formData.append('uk', params.uk);
                    formData.append('primaryid', params.primaryid);
                    formData.append('fid_list', fidList);
                    formData.append('logid', params.logid);
                    params.shareType === 'secret' ? formData.append('extra', params.extra) : '';
                    url = `${pan.pcs[1]}&sign=${params.sign}&timestamp=${params.timestamp}`;
                    res = await base.post(url, formData, {"User-Agent": pan.ua});
                }
                if (res.errno === 0) {
                    let html = this.generateDom(res.list);
                    this.showMainDialog(pan[mode][0], html, pan[mode][1]);
                } else if (res.errno === 112) {
                    return message.error('提示:页面过期,请刷新重试!');
                } else {
                    message.error('提示:获取下载链接失败!请刷新网页后重试!');
                }
            },
    
            generateDom(list) {
                let content = '<div class="pl-main">';
                let alinkAllText = '';
                base.sortByName(list);
                list.forEach((v, i) => {
                    if (v.isdir === 1) return;
                    let filename = v.server_filename || v.filename;
                    let ext = base.getExtension(filename);
                    let size = base.sizeFormat(v.size);
                    let dlink = v.dlink;
                    if (mode === 'api') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
                                    <div class="pl-item-tip" style="display: none"><span>若没有弹出IDM下载框,找到IDM <b>选项</b> -> <b>文件类型</b> -> <b>第一个框</b> 中添加后缀 <span class="pl-ext">${ext}</span>,<a href="${pan.idm}" target="_blank" class="pl-a">详见此处</a></span> <span class="pl-back listener-back">返回</span></div>
                                    <div class="pl-item-progress" style="display: none">
                                        <div class="pl-progress">
                                            <div class="pl-progress-outer"></div>
                                            <div class="pl-progress-inner" style="5%">
                                              <div class="pl-progress-inner-text">0%</div>
                                            </div>
                                        </div>
                                        <span class="pl-progress-stop listener-stop">取消下载</span>
                                        <span class="pl-progress-tip">未发现IDM,使用自带浏览器下载</span>
                                        <span class="pl-progress-how listener-how">如何唤起IDM?</span>
                                    </div></div>`;
                    }
                    if (mode === 'aria') {
                        let alink = this.convertLinkToAria(dlink, filename, pan.ua);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                    if (mode === 'rpc') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
                    }
                    if (mode === 'curl') {
                        let alink = this.convertLinkToCurl(dlink, filename, pan.ua);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                });
                content += '</div>';
                if (mode === 'aria')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
                if (mode === 'rpc') {
                    let rpc = base.getValue('setting_rpc_domain')+':'+base.getValue('setting_rpc_port')+base.getValue('setting_rpc_path')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-send-rpc">发送全部链接</button><button title="${rpc}" class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px">设置 RPC 参数(当前为:${rpc})</button><button class="pl-btn-primary pl-btn-success listener-rpc-task" style="margin-left: 10px;display: none">查看下载任务</button></div>`;
                }
                if (mode === 'curl')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button><button class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px;">设置终端类型(当前为:${terminalType[base.getValue('setting_terminal_type')]})</button></div>`;
                return content;
            },
    
            async sendLinkToRPC(filename, link) {
                let rpc = {
                    domain: base.getValue('setting_rpc_domain'),
                    port: base.getValue('setting_rpc_port'),
                    path: base.getValue('setting_rpc_path'),
                    token: base.getValue('setting_rpc_token'),
                    dir: base.getValue('setting_rpc_dir'),
                };
                let BDUSS = this.getBDUSS();
                if (!BDUSS) return 'assistant';
    
                let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
                let rpcData = {
                    id: new Date().getTime(),
                    jsonrpc: '2.0',
                    method: 'aria2.addUri',
                    params: [`token:${rpc.token}`, [link], {
                        dir: rpc.dir,
                        out: filename,
                        header: [`User-Agent: ${pan.ua}`, `Cookie: BDUSS=${BDUSS}`]
                    }]
                };
                try {
                    let res = await base.post(url, rpcData, {"User-Agent": pan.ua}, '');
                    if (res.result) return 'success';
                    return 'fail';
                } catch (e) {
                    return 'fail';
                }
            },
    
            getSelectedList() {
                try {
                    return require('system-core:context/context.js').instanceForSystem.list.getSelected();
                } catch (e) {
                    return document.querySelector('.nd-main-list').__vue__.selectedList;
                }
            },
    
            getLogid() {
                let ut = require("system-core:context/context.js").instanceForSystem.tools.baseService;
                return ut.base64Encode(base.getCookie("BAIDUID"));
            },
    
            getShareData() {
                let res = locals.dump();
                params.shareType = 'secret';
                params.sign = '';
                params.timestamp = '';
                params.bdstoken = res.bdstoken.value;
                params.channel = 'chunlei';
                params.clienttype = 0;
                params.web = 1;
                params.app_id = 250528;
                params.encrypt = 0;
                params.product = 'share';
                params.logid = this.getLogid();
                params.primaryid = res.shareid.value;
                params.uk = res.share_uk.value;
                params.shareType === 'secret' && (params.extra = this._getExtra());
                params.surl = this._getSurl();
            },
    
            detectPage() {
                let path = location.pathname;
                if (/^\/disk\/home/.test(path)) return 'home';
                if (/^\/disk\/main/.test(path)) return 'main';
                if (/^\/(s|share)\//.test(path)) return 'share';
                return '';
                return '';
            },
    
            showMainDialog(title, html, footer) {
                Swal.fire({
                    title,
                    html,
                    footer,
                    allowOutsideClick: false,
                    showCloseButton: true,
                    showConfirmButton: false,
                    position: 'top',
                    width,
                    padding: '15px 20px 5px',
                    customClass,
                }).then(() => {
                    this._resetData();
                });
            },
    
            async initPanLinker() {
                base.initDefaultConfig();
                base.addPanLinkerStyle();
                pt = this.detectPage();
                let res = await base.post
                (`https://api.youxiaohou.com/config?ver=${version}&a=${author}`, {}, {}, 'text');
                pan = JSON.parse(base.d(res));
                Object.freeze && Object.freeze(pan);
                pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
                base.createTip();
                base.registerMenuCommand();
            }
        };
    
        let ali = {
    
            convertLinkToAria(link, filename, ua) {
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Referer: https://www.aliyundrive.com/"`);
            },
    
            convertLinkToCurl(link, filename, ua) {
                let terminal = base.getValue('setting_terminal_type');
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}" -e "https://www.aliyundrive.com/"`);
            },
    
            addPageListener() {
                doc.on('mouseenter click', '.pl-button', (e) => {
                    $(e.currentTarget).find('.pl-dropdown-menu').show();
                });
                doc.on('mouseleave', '.pl-dropdown-menu', (e) => {
                    $(e.currentTarget).hide();
                });
                doc.on('click', '.pl-button-mode', (e) => {
                    mode = e.target.dataset.mode;
                    Swal.showLoading();
                    this.getPCSLink();
                });
                doc.on('click', '.listener-link-api', async (e) => {
                    e.preventDefault();
                    let d = document.createElement("a");
                    d.download = "download";
                    d.rel = "noopener";
                    d.href = e.currentTarget.dataset.link;
                    d.dispatchEvent(new MouseEvent("click"))
                    //$('#downloadIframe').attr('src', e.currentTarget.dataset.link);
                });
                doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
                    e.preventDefault();
                    base.setClipboard(decodeURIComponent(e.target.dataset.link));
                    $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-link-rpc', async (e) => {
                    let target = $(e.currentTarget);
                    target.find('.icon').remove();
                    target.find('.pl-loading').remove();
                    target.prepend(base.createLoading());
                    let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
                    if (res === 'success') {
                        $('.listener-rpc-task').show();
                        target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
                    } else {
                        target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
                    }
                });
                doc.on('click', '.listener-send-rpc', (e) => {
                    $('.listener-link-rpc').click();
                    $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-open-setting', () => {
                    base.showSetting();
                });
                doc.on('click', '.listener-rpc-task', () => {
                    let rpc = JSON.stringify({
                        domain: base.getValue('setting_rpc_domain'),
                        port: base.getValue('setting_rpc_port'),
                    }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
                    GM_openInTab(url, {active: true});
                });
            },
    
            addButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="ali-button pl-button"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M853.333 938.667H170.667a85.333 85.333 0 0 1-85.334-85.334v-384A85.333 85.333 0 0 1 170.667 384H288a32 32 0 0 1 0 64H170.667a21.333 21.333 0 0 0-21.334 21.333v384a21.333 21.333 0 0 0 21.334 21.334h682.666a21.333 21.333 0 0 0 21.334-21.334v-384A21.333 21.333 0 0 0 853.333 448H736a32 32 0 0 1 0-64h117.333a85.333 85.333 0 0 1 85.334 85.333v384a85.333 85.333 0 0 1-85.334 85.334z" fill="#fff"/><path d="M715.03 543.552a32.81 32.81 0 0 0-46.251 0L554.005 657.813v-540.48a32 32 0 0 0-64 0v539.734L375.893 543.488a32.79 32.79 0 0 0-46.229 0 32.427 32.427 0 0 0 0 46.037l169.557 168.811a32.81 32.81 0 0 0 46.251 0l169.557-168.81a32.47 32.47 0 0 0 0-45.974z" fill="#FF9C00"/></svg><ul class="pl-dropdown-menu" style="display:none"><li class="pl-dropdown-menu-item pl-button-mode" data-mode="api">API下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="aria" >Aria下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="rpc">RPC下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="curl">cURL下载</li>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.append($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    $button.css({'margin-right': '10px'});
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                base.clog(`助手加载成功!版本:${version}`);
                base.createDownloadIframe();
                this.addPageListener();
            },
    
            addInitButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="ali-button pl-button-init"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M853.333 938.667H170.667a85.333 85.333 0 0 1-85.334-85.334v-384A85.333 85.333 0 0 1 170.667 384H288a32 32 0 0 1 0 64H170.667a21.333 21.333 0 0 0-21.334 21.333v384a21.333 21.333 0 0 0 21.334 21.334h682.666a21.333 21.333 0 0 0 21.334-21.334v-384A21.333 21.333 0 0 0 853.333 448H736a32 32 0 0 1 0-64h117.333a85.333 85.333 0 0 1 85.334 85.333v384a85.333 85.333 0 0 1-85.334 85.334z" fill="#fff"/><path d="M715.03 543.552a32.81 32.81 0 0 0-46.251 0L554.005 657.813v-540.48a32 32 0 0 0-64 0v539.734L375.893 543.488a32.79 32.79 0 0 0-46.229 0 32.427 32.427 0 0 0 0 46.037l169.557 168.811a32.81 32.81 0 0 0 46.251 0l169.557-168.81a32.47 32.47 0 0 0 0-45.974z" fill="#FF9C00"/></svg></div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.append($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    $button.css({'margin-right': '10px'});
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                $button.click(() => base.initDialog());
            },
    
            async getPCSLink() {
                let reactDomGrid = document.getElementsByClassName(pan.dom.grid)[0];
                if (reactDomGrid) {
                    let res = await Swal.fire({
                        title: '提示',
                        html: '<div style="display: flex;align-items: center;justify-content: center;">请先切换到 <b>列表视图</b>(<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M132 928c-32.8 0-59.2-26.4-59.2-59.2s26.4-59.2 59.2-59.2h760c32.8 0 59.2 26.4 59.2 59.2S924.8 928 892 928H132zm0-356.8c-32.8 0-59.2-26.4-59.2-59.2s26.4-59.2 59.2-59.2h760c32.8 0 59.2 26.4 59.2 59.2s-26.4 59.2-59.2 59.2H132zm0-356c-32.8 0-59.2-26.4-59.2-59.2S99.2 96.8 132 96.8h760c32.8 0 59.2 26.4 59.2 59.2s-26.4 59.2-59.2 59.2H132z"/></svg>)后获取!</div>',
                        confirmButtonText: '点击切换'
                    });
                    if (res) {
                        $('.switch-wrapper--1yEfx').trigger('click');
                        return message.success('切换成功,请重新获取下载链接!');
                    }
                    return false;
                }
                selectList = this.getSelectedList();
                if (selectList.length === 0) {
                    return message.error('提示:请先勾选要下载的文件!');
                }
                if (this.isOnlyFolder()) {
                    return message.error('提示:请打开文件夹后勾选文件!');
                }
                if (pt === 'share') {
                    if (selectList.length > 20) {
                        return message.error('提示:单次最多可勾选 20 个文件!');
                    }
                    try {
                        let authorization = `${JSON.parse(base.getStorage('token')).token_type} ${JSON.parse(base.getStorage('token')).access_token}`;
                        let xShareToken = JSON.parse(base.getStorage('shareToken')).share_token;
    
                        for (let i = 0; i < selectList.length; i++) {
                            let res = await base.post(pan.pcs[0], {
                                expire_sec: 600,
                                file_id: selectList[i].fileId,
                                share_id: selectList[i].shareId
                            }, {
                                authorization,
                                "content-type": "application/json;charset=utf-8",
                                "x-share-token": xShareToken
                            });
                            if (res.download_url) {
                                selectList[i].downloadUrl = res.download_url;
                            }
                        }
                    } catch (e) {
                        return message.error('提示:请先登录网盘!');
                    }
                }
                let html = this.generateDom(selectList);
                this.showMainDialog(pan[mode][0], html, pan[mode][1]);
            },
    
            generateDom(list) {
                let content = '<div class="pl-main">';
                let alinkAllText = '';
                list.forEach((v, i) => {
                    if (v.type === 'folder') return;
                    let filename = v.name;
                    let size = base.sizeFormat(v.size);
                    let dlink = v.downloadUrl;
                    if (mode === 'api') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
                                    </div>`;
                    }
                    if (mode === 'aria') {
                        let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                    if (mode === 'rpc') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
                    }
                    if (mode === 'curl') {
                        let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                });
                content += '</div>';
                if (mode === 'aria')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
                if (mode === 'rpc') {
                    let rpc = base.getValue('setting_rpc_domain')+':'+base.getValue('setting_rpc_port')+base.getValue('setting_rpc_path')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-send-rpc">发送全部链接</button><button title="${rpc}" class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px">设置 RPC 参数(当前为:${rpc})</button><button class="pl-btn-primary pl-btn-success listener-rpc-task" style="margin-left: 10px;display: none">查看下载任务</button></div>`;
                }
                if (mode === 'curl')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button><button class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px;">设置终端类型(当前为:${terminalType[base.getValue('setting_terminal_type')]})</button></div>`;
                return content;
            },
    
            async sendLinkToRPC(filename, link) {
                let rpc = {
                    domain: base.getValue('setting_rpc_domain'),
                    port: base.getValue('setting_rpc_port'),
                    path: base.getValue('setting_rpc_path'),
                    token: base.getValue('setting_rpc_token'),
                    dir: base.getValue('setting_rpc_dir'),
                };
    
                let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
                let rpcData = {
                    id: new Date().getTime(),
                    jsonrpc: '2.0',
                    method: 'aria2.addUri',
                    params: [`token:${rpc.token}`, [link], {
                        dir: rpc.dir,
                        out: filename,
                        header: [`Referer: https://www.aliyundrive.com/`]
                    }]
                };
                try {
                    let res = await base.post(url, rpcData, {"Referer": "https://www.aliyundrive.com/"}, '');
                    if (res.result) return 'success';
                    return 'fail';
                } catch (e) {
                    return 'fail';
                }
            },
    
            getSelectedList() {
                try {
                    let selectedList = [];
                    let reactDom = document.getElementsByClassName(pan.dom.list)[0];
                    let reactKey = Object.keys(reactDom).find(p => p.startsWith('__reactFiber'));
                    if (reactKey) {
                        let props = reactDom[reactKey].return.pendingProps.value;
                        let fileList = props.dataSource || [];
                        let selectedKeys = props.selectedKeys.split(',');
                        fileList.forEach((val) => {
                            if (selectedKeys.includes(val.fileId)) {
                                selectedList.push(val);
                            }
                        });
                    }
                    return selectedList;
                } catch (e) {
                    return [];
                }
            },
    
            detectPage() {
                let path = location.pathname;
                if (/^\/(drive)/.test(path)) return 'home';
                if (/^\/(s|share)\//.test(path)) return 'share';
                return '';
            },
    
            isOnlyFolder() {
                for (let i = 0; i < selectList.length; i++) {
                    if (selectList[i].type === 'file') return false;
                }
                return true;
            },
    
            showMainDialog(title, html, footer) {
                Swal.fire({
                    title,
                    html,
                    footer,
                    allowOutsideClick: false,
                    showCloseButton: true,
                    showConfirmButton: false,
                    position: 'top',
                    width,
                    padding: '15px 20px 5px',
                    customClass,
                });
            },
    
            async initPanLinker() {
                base.initDefaultConfig();
                base.addPanLinkerStyle();
                pt = this.detectPage();
                let res = await base.post
                (`https://api.youxiaohou.com/config/ali?ver=${version}&a=${author}`, {}, {}, 'text');
                pan = JSON.parse(base.d(res));
                Object.freeze && Object.freeze(pan);
                pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
                base.createTip();
                base.registerMenuCommand();
            }
        };
    
        let tianyi = {
    
            convertLinkToAria(link, filename, ua) {
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
            },
    
            convertLinkToCurl(link, filename, ua) {
                let terminal = base.getValue('setting_terminal_type');
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}"`);
            },
    
            addPageListener() {
                doc.on('mouseenter click', '.pl-button', (e) => {
                    $(e.currentTarget).find('.pl-dropdown-menu').show();
                });
                doc.on('mouseleave', '.pl-dropdown-menu', (e) => {
                    $(e.currentTarget).hide();
                });
                doc.on('click', '.pl-button-mode', (e) => {
                    mode = e.target.dataset.mode;
                    Swal.showLoading();
                    this.getPCSLink();
                });
                doc.on('click', '.listener-link-api', async (e) => {
                    e.preventDefault();
                    $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
                });
                doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
                    e.preventDefault();
                    base.setClipboard(decodeURIComponent(e.target.dataset.link));
                    $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-link-rpc', async (e) => {
                    let target = $(e.currentTarget);
                    target.find('.icon').remove();
                    target.find('.pl-loading').remove();
                    target.prepend(base.createLoading());
                    let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
                    if (res === 'success') {
                        $('.listener-rpc-task').show();
                        target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
                    } else {
                        target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
                    }
                });
                doc.on('click', '.listener-send-rpc', (e) => {
                    $('.listener-link-rpc').click();
                    $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-open-setting', () => {
                    base.showSetting();
                });
                doc.on('click', '.listener-rpc-task', () => {
                    let rpc = JSON.stringify({
                        domain: base.getValue('setting_rpc_domain'),
                        port: base.getValue('setting_rpc_port'),
                    }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
                    GM_openInTab(url, {active: true});
                });
            },
    
            addButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="tianyi-button pl-button">下载助手<ul class="pl-dropdown-menu" style="display:none"><li class="pl-dropdown-menu-item pl-button-mode" data-mode="api">API下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="aria" >Aria下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="rpc">RPC下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="curl">cURL下载</li>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                base.clog(`助手加载成功!版本:${version}`);
                base.createDownloadIframe();
                this.addPageListener();
            },
    
            addInitButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="tianyi-button pl-button-init">下载助手</div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.append($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    $button.css({'margin-right': '10px'});
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                $button.click(() => base.initDialog());
            },
    
            async getPCSLink() {
                selectList = this.getSelectedList();
                if (selectList.length === 0) {
                    return message.error('提示:请先勾选要下载的文件!');
                }
                if (this.isOnlyFolder()) {
                    return message.error('提示:请打开文件夹后勾选文件!');
                }
                if (selectList.length > 20) {
                    return message.error('提示:单次最多可勾选 20 个文件!');
                }
                for (let i = 0; i < selectList.length; i++) {
                    let item = selectList[i];
                    if (!item.downloadUrl && !item.isFolder) {
                        let query = `?fileId=${item.fileId}&dt=1`;
                        if (item.shareId) {
                            query += `&shareId=${item.shareId}`;
                        }
                        try {
                            let res = await base.get(pan.pcs[0] + query, {
                                accept: "application/json;charset=UTF-8"
                            });
                            if (res.fileDownloadUrl) {
                                selectList[i].downloadUrl = res.fileDownloadUrl;
                            } else if (res.errorCode === 'InvalidSessionKey') {
                                return message.error('提示:请先登录网盘!');
                            } else {
                                return message.error('提示:未知错误');
                            }
                        } catch (e) {
                            return message.error('提示:未知错误');
                        }
                    }
                }
                let html = this.generateDom(selectList);
                this.showMainDialog(pan[mode][0], html, pan[mode][1]);
            },
    
            generateDom(list) {
                let content = '<div class="pl-main">';
                let alinkAllText = '';
                list.forEach((v, i) => {
                    if (v.isFolder) return;
                    let filename = v.fileName;
                    let size = base.sizeFormat(v.size);
                    let dlink = v.downloadUrl;
                    if (mode === 'api') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
                                    </div>`;
                    }
                    if (mode === 'aria') {
                        let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                    if (mode === 'rpc') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
                    }
                    if (mode === 'curl') {
                        let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                });
                content += '</div>';
                if (mode === 'aria')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
                if (mode === 'rpc') {
                    let rpc = base.getValue('setting_rpc_domain')+':'+base.getValue('setting_rpc_port')+base.getValue('setting_rpc_path')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-send-rpc">发送全部链接</button><button title="${rpc}" class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px">设置 RPC 参数(当前为:${rpc})</button><button class="pl-btn-primary pl-btn-success listener-rpc-task" style="margin-left: 10px;display: none">查看下载任务</button></div>`;
                }
                if (mode === 'curl')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button><button class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px;">设置终端类型(当前为:${terminalType[base.getValue('setting_terminal_type')]})</button></div>`;
                return content;
            },
    
            async sendLinkToRPC(filename, link) {
                let rpc = {
                    domain: base.getValue('setting_rpc_domain'),
                    port: base.getValue('setting_rpc_port'),
                    path: base.getValue('setting_rpc_path'),
                    token: base.getValue('setting_rpc_token'),
                    dir: base.getValue('setting_rpc_dir'),
                };
    
                let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
                let rpcData = {
                    id: new Date().getTime(),
                    jsonrpc: '2.0',
                    method: 'aria2.addUri',
                    params: [`token:${rpc.token}`, [link], {
                        dir: rpc.dir,
                        out: filename,
                        header: []
                    }]
                };
                try {
                    let res = await base.post(url, rpcData, {}, '');
                    if (res.result) return 'success';
                    return 'fail';
                } catch (e) {
                    return 'fail';
                }
            },
    
            getSelectedList() {
                try {
                    return document.querySelector(".c-file-list").__vue__.selectedList;
                } catch (e) {
                    return [document.querySelector(".info-detail").__vue__.fileDetail];
                }
            },
    
            detectPage() {
                let path = location.pathname;
                if (/^\/web\/main/.test(path)) return 'home';
                if (/^\/web\/share/.test(path)) return 'share';
                return '';
            },
    
            isOnlyFolder() {
                for (let i = 0; i < selectList.length; i++) {
                    if (!selectList[i].isFolder) return false;
                }
                return true;
            },
    
            showMainDialog(title, html, footer) {
                Swal.fire({
                    title,
                    html,
                    footer,
                    allowOutsideClick: false,
                    showCloseButton: true,
                    showConfirmButton: false,
                    position: 'top',
                    width,
                    padding: '15px 20px 5px',
                    customClass,
                });
            },
    
            async initPanLinker() {
                base.initDefaultConfig();
                base.addPanLinkerStyle();
                pt = this.detectPage();
                let res = await base.post
                (`https://api.youxiaohou.com/config/tianyi?ver=${version}&a=${author}`, {}, {}, 'text');
                pan = JSON.parse(base.d(res));
                Object.freeze && Object.freeze(pan);
                pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
                base.createTip();
                base.registerMenuCommand();
            }
        };
    
        let xunlei = {
    
            convertLinkToAria(link, filename, ua) {
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
            },
    
            convertLinkToCurl(link, filename, ua) {
                let terminal = base.getValue('setting_terminal_type');
                filename = filename.replace(' ', '_');
                return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}"`);
            },
    
            addPageListener() {
                doc.on('mouseenter click', '.pl-button', (e) => {
                    $(e.currentTarget).find('.pl-dropdown-menu').show();
                });
                doc.on('mouseleave', '.pl-dropdown-menu', (e) => {
                    $(e.currentTarget).hide();
                });
                doc.on('click', '.pl-button-mode', (e) => {
                    mode = e.target.dataset.mode;
                    Swal.showLoading();
                    this.getPCSLink();
                });
                doc.on('click', '.listener-link-api', async (e) => {
                    e.preventDefault();
                    $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
                });
                doc.on('click', '.listener-link-api-btn', async (e) => {
                    base.setClipboard(e.target.dataset.filename);
                    $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
                    e.preventDefault();
                    base.setClipboard(decodeURIComponent(e.target.dataset.link));
                    $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-link-rpc', async (e) => {
                    let target = $(e.currentTarget);
                    target.find('.icon').remove();
                    target.find('.pl-loading').remove();
                    target.prepend(base.createLoading());
                    let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
                    if (res === 'success') {
                        $('.listener-rpc-task').show();
                        target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
                    } else {
                        target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
                    }
                });
                doc.on('click', '.listener-send-rpc', (e) => {
                    $('.listener-link-rpc').click();
                    $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
                });
                doc.on('click', '.listener-open-setting', () => {
                    base.showSetting();
                });
                doc.on('click', '.listener-rpc-task', () => {
                    let rpc = JSON.stringify({
                        domain: base.getValue('setting_rpc_domain'),
                        port: base.getValue('setting_rpc_port'),
                    }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
                    GM_openInTab(url, {active: true});
                });
            },
    
            addButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="xunlei-button pl-button"><i class="xlpfont xlp-download"></i><span style="font-size: 13px;margin-left: 6px;">下载助手</span><ul class="pl-dropdown-menu" style="display:none"><li class="pl-dropdown-menu-item pl-button-mode" data-mode="api">API下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="aria" >Aria下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="rpc">RPC下载</li><li class="pl-dropdown-menu-item pl-button-mode" data-mode="curl">cURL下载</li>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    $button.css({'margin-right': '10px'});
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                base.clog(`助手加载成功!版本:${version}`);
                base.createDownloadIframe();
                this.addPageListener();
            },
    
            addInitButton() {
                if (!pt) return;
                let $toolWrap;
                let $button = $(`<div class="xunlei-button pl-button-init"><i class="xlpfont xlp-download"></i><span style="font-size: 13px;margin-left: 6px;">下载助手</span></div>`);
                if (pt === 'home') {
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.home);
                        if ($toolWrap.length > 0) {
                            $toolWrap.append($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                if (pt === 'share') {
                    $button.css({'margin-right': '10px'});
                    let ins = setInterval(() => {
                        $toolWrap = $(pan.btn.share);
                        if ($toolWrap.length > 0) {
                            $toolWrap.prepend($button);
                            clearInterval(ins);
                        }
                    }, 100);
                }
                $button.click(() => base.initDialog());
            },
    
            async getPCSLink() {
                selectList = this.getSelectedList();
                if (selectList.length === 0) {
                    return message.error('提示:请先勾选要下载的文件!');
                }
                if (this.isOnlyFolder()) {
                    return message.error('提示:请打开文件夹后勾选文件!');
                }
                if (pt === 'home') {
                    if (selectList.length > 20) {
                        return message.error('提示:单次最多可勾选 20 个文件!');
                    }
                    try {
                        let credentials = {}, captcha = {};
                        for (let i = 0; i < localStorage.length; i++) {
                            if (/^credentials_/.test(localStorage.key(i))) {
                                credentials = JSON.parse(base.getStorage(localStorage.key(i)));
                            }
                            if (/^captcha_[\w]{16}/.test(localStorage.key(i))) {
                                captcha = JSON.parse(base.getStorage(localStorage.key(i)));
                            }
                        }
                        let deviceid = /(\w{32})/.exec(base.getStorage('deviceid').split(','))[0];
    
                        for (let i = 0; i < selectList.length; i++) {
                            let res = await base.get(pan.pcs[0] + selectList[i].id, {
                                'Authorization': `${credentials.token_type} ${credentials.access_token}`,
                                'content-type': "application/json",
                                'x-captcha-token': captcha.token,
                                'x-device-id': deviceid,
                            });
                            if (res.web_content_link) {
                                selectList[i].downloadUrl = res.web_content_link;
                            }
                        }
                    } catch (e) {
                        return message.error('提示:请先登录网盘后刷新页面!');
                    }
                } else {
                    return  message.error('提示:请转存到自己网盘后去网盘主页下载!');
                }
                let html = this.generateDom(selectList);
                this.showMainDialog(pan[mode][0], html, pan[mode][1]);
    
            },
    
            generateDom(list) {
                let content = '<div class="pl-main">';
                let alinkAllText = '';
                list.forEach((v, i) => {
                    if (v.kind === 'drive#folder') return;
                    let filename = v.name;
                    let size = base.sizeFormat(+v.size);
                    let dlink = v.downloadUrl;
                    if (mode === 'api') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
                                    <div class="pl-item-btn listener-link-api-btn" data-filename="${filename}">复制文件名</div>
                                    </div>`;
                    }
                    if (mode === 'aria') {
                        let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                    if (mode === 'rpc') {
                        content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
                    }
                    if (mode === 'curl') {
                        let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
                        if (typeof (alink) === 'object') {
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`;
                        } else {
                            alinkAllText += alink + '\r\n';
                            content += `<div class="pl-item">
                                    <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                    <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
                        }
                    }
                });
                content += '</div>';
                if (mode === 'aria')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
                if (mode === 'rpc') {
                    let rpc = base.getValue('setting_rpc_domain')+':'+base.getValue('setting_rpc_port')+base.getValue('setting_rpc_path')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-send-rpc">发送全部链接</button><button title="${rpc}" class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px">设置 RPC 参数(当前为:${rpc})</button><button class="pl-btn-primary pl-btn-success listener-rpc-task" style="margin-left: 10px;display: none">查看下载任务</button></div>`;
                }
                if (mode === 'curl')
                    content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button><button class="pl-btn-primary pl-btn-warning listener-open-setting" style="margin-left: 10px;">设置终端类型(当前为:${terminalType[base.getValue('setting_terminal_type')]})</button></div>`;
                return content;
            },
    
            async sendLinkToRPC(filename, link) {
                let rpc = {
                    domain: base.getValue('setting_rpc_domain'),
                    port: base.getValue('setting_rpc_port'),
                    path: base.getValue('setting_rpc_path'),
                    token: base.getValue('setting_rpc_token'),
                    dir: base.getValue('setting_rpc_dir'),
                };
    
                let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
                let rpcData = {
                    id: new Date().getTime(),
                    jsonrpc: '2.0',
                    method: 'aria2.addUri',
                    params: [`token:${rpc.token}`, [link], {
                        dir: rpc.dir,
                        out: filename,
                        header: []
                    }]
                };
                try {
                    let res = await base.post(url, rpcData, {}, '');
                    if (res.result) return 'success';
                    return 'fail';
                } catch (e) {
                    return 'fail';
                }
            },
    
            getSelectedList() {
                try {
                    let doms = document.querySelectorAll('.pan-list-item');
                    let selectedList = [];
                    for (let dom of doms) {
                        let domVue = dom.__vue__;
                        if (domVue.selected.includes(domVue.info.id)) {
                            selectedList.push(domVue.info);
                        }
                    }
                    return selectedList;
                } catch (e) {
                    return [];
                }
            },
    
            detectPage() {
                let path = location.pathname;
                if (/^\/$/.test(path)) return 'home';
                if (/^\/(s|share)\//.test(path)) return 'share';
                return '';
            },
    
            isOnlyFolder() {
                for (let i = 0; i < selectList.length; i++) {
                    if (selectList[i].kind === 'drive#file') return false;
                }
                return true;
            },
    
            showMainDialog(title, html, footer) {
                Swal.fire({
                    title,
                    html,
                    footer,
                    allowOutsideClick: false,
                    showCloseButton: true,
                    showConfirmButton: false,
                    position: 'top',
                    width,
                    padding: '15px 20px 5px',
                    customClass,
                });
            },
    
            async initPanLinker() {
                base.initDefaultConfig();
                base.addPanLinkerStyle();
                pt = this.detectPage();
                let res = await base.post
                (`https://api.youxiaohou.com/config/xunlei?ver=${version}&a=${author}`, {}, {}, 'text');
                pan = JSON.parse(base.d(res));
                Object.freeze && Object.freeze(pan);
                pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
                base.createTip();
                base.registerMenuCommand();
            }
        };
    
        let main = {
            init() {
                if (/(pan|yun).baidu.com/.test(location.host)) {
                    baidu.initPanLinker();
                }
                if (/www.aliyundrive.com/.test(location.host)) {
                    ali.initPanLinker();
                }
                if (/cloud.189.cn/.test(location.host)) {
                    tianyi.initPanLinker();
                }
                if (/pan.xunlei.com/.test(location.host)) {
                    xunlei.initPanLinker();
                }
            }
        };
    
        main.init();
    })();
    
  • 相关阅读:
    7月15日考试 题解(链表+状压DP+思维题)
    暑假集训日记
    C# .NET 使用 NPOI 生成 .xlsx 格式 Excel
    JavaSE 基础 第42节 局部内部类
    JavaSE 基础 第41节 匿名内部类
    JavaSE 基础 第40节 内部类概述
    JavaSE 基础 第39节 接口的应用
    JavaSE 基础 第38节 接口的实现
    JavaSE 基础 第37节 接口概述
    JavaSE 基础 第36节 抽象类概述与使用
  • 原文地址:https://www.cnblogs.com/tomtellyou/p/16017078.html
Copyright © 2020-2023  润新知