(改)网盘直链下载助手

可以获取网盘文件真实下载地址。现已支持百度阿里天翼迅雷夸克移动六大网盘,基于【网盘直链下载助手】修改自6.0.4版本,自用,去推广,修原有BUG,修改界面,甚至比原版还好用!

当前为 2023-06-02 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name              (改)网盘直链下载助手
// @namespace         https://github.com/syhyz1990/baiduyun
// @version           1.0.6.4
// @author            Hmjz100、油小猴
// @icon              data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjMTM5N2Q4Ii8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNODguMyA3My44TDczLjUgOTMuMmMtMS41IDEuOS0zLjUgMy4xLTUuNyAzLjVoLS4yYy0uNC4xLS44LjEtMS4yLjEtLjYgMC0xLjEtLjEtMS42LS4yLTIuMi0uNC00LjItMS43LTUuNi0zLjVMNDQuMyA3My45Yy0yLTIuNi0yLjUtNS40LTEuNC03LjcuMS0uMS4xLS4yLjItLjIgMS4yLTIgMy41LTMuMiA2LjQtMy4yaDYuNnYtNS43YzAtNi44IDQuNy0xMiAxMC45LTEyIDQuOCAwIDguNSAyLjYgMTAuMyA3LjIuNSAxLjMtLjIgMi43LTEuNSAzLjJzLTIuOC0uMS0zLjMtMS40Yy0xLjEtMi43LTIuOS00LTUuNS00LTMuNSAwLTYgMy02IDd2OC4xYzAgLjUtLjIgMS0uNiAxLjQtLjYuNy0xLjcgMS4xLTIuNiAxLjFoLTguNGMtMS4zIDAtMiAuNC0yLjEuNy0uMi40IDAgMS4zLjkgMi40TDYzLjEgOTBjLjkgMS4yIDIuMSAxLjggMy4zIDEuOHMyLjMtLjYgMy4xLTEuN2wxNC44LTE5LjNjLjktMS4xIDEuMS0yIC45LTIuNC0uMi0uMy0uOS0uNy0yLjEtLjdoLTcuNmMtLjkgMC0xLjctLjUtMi4xLTEuMi0uMy0uNC0uNC0uOC0uNC0xLjMgMC0xLjQgMS4xLTIuNSAyLjUtMi41aDcuNmMzLjEgMCA1LjUgMS4zIDYuNiAzLjVsLjMuN2MuNyAyLjEuMSA0LjYtMS43IDYuOXoiIGZpbGw9IiM0NDQiLz48L3N2Zz4=
// @description       可以获取网盘文件真实下载地址。现已支持百度阿里天翼迅雷夸克移动六大网盘,基于【网盘直链下载助手】修改自6.0.4版本,自用,去推广,修原有BUG,修改界面,甚至比原版还好用!
// @license           MIT
// @homepage          https://github.com/hmjz100/Online-disk-direct-link-download-assistant/
// @supportURL        https://github.com/hmjz100/Online-disk-direct-link-download-assistant/issues
// @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/*
// @match             *://pan.quark.cn/*
// @match             *://yun.139.com/*
// @match             *://caiyun.139.com/*
// @match             *://*.youxiaohou.com/*
// @require           https://unpkg.com/[email protected]/dist/jquery.min.js
// @require           https://unpkg.com/sweetalert2@11/dist/sweetalert2.js
// @require           https://unpkg.com/[email protected]/build/md5.min.js
// @connect           baidu.com
// @connect           baidupcs.com
// @connect           aliyundrive.com
// @connect           189.cn
// @connect           xunlei.com
// @connect           quark.cn
// @connect           youxiaohou.com
// @connect           localhost
// @connect           *
// @run-at            document-idle
// @compatible	      Chrome
// @compatible	      Edge
// @compatible	      Firefox
// @compatible	      Safari
// @compatible	      Opera
// @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
// @grant             GM_addStyle
// @grant             GM_getResourceText
// ==/UserScript==

(function () {
    'use strict';
    function generateRandomNumberInRange(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    };
    /*--- waitForKeyElements():  A utility function, for Greasemonkey scripts,
    that detects and handles AJAXed content.
    Usage example:
        waitForKeyElements (
            "div.comments"
            , commentCallbackFunction
        );
        //--- Page-specific function to do what we want when the node is found.
        function commentCallbackFunction (jNode) {
            jNode.text ("This comment changed by waitForKeyElements().");
        }
    IMPORTANT: This function requires your script to have loaded jQuery.
    */
    function waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector) {
        var targetNodes, btargetsFound;

        if (typeof iframeSelector == "undefined")
            targetNodes = $(selectorTxt);
        else
            targetNodes = $(iframeSelector).contents()
                .find(selectorTxt);

        if (targetNodes && targetNodes.length > 0) {
            btargetsFound = true;
            targetNodes.each(function () {
                var jThis = $(this);
                var alreadyFound = jThis.data('alreadyFound') || false;

                if (!alreadyFound) {
                    //--- Call the payload function.
                    var cancelFound = actionFunction(jThis);
                    if (cancelFound) btargetsFound = false;
                    else jThis.data('alreadyFound', true);
                }
            });
        } else {
            btargetsFound = false;
        }

        //--- Get the timer-control variable for this selector.
        var controlObj = waitForKeyElements.controlObj || {};
        var controlKey = selectorTxt.replace(/[^\w]/g, "_");
        var timeControl = controlObj[controlKey];

        //--- Now set or clear the timer as appropriate.
        if (btargetsFound && bWaitOnce && timeControl) {
            //--- The only condition where we need to clear the timer.
            clearInterval(timeControl);
            delete controlObj[controlKey]
        } else {
            //--- Set a timer, if needed.
            if (!timeControl) {
                timeControl = setInterval(function () {
                    waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector);
                }, 300);
                controlObj[controlKey] = timeControl;
            }
        }
        waitForKeyElements.controlObj = controlObj;
    }
    let pt = '', selectList = [], params = {}, mode = '', width = 800, pan = {}, color = '',
        doc = $(document), progress = {}, request = {}, ins = {}, idm = {};

    //用于油小猴服务器检测的脚本内容
    const scriptInfo = GM_info.script;

    //用于油小猴服务器检测的脚本版本
    const realversion = scriptInfo.version;
    const version = 9999999999999;//防止服务器返回更新信息
    //const version = generateRandomNumberInRange(1000,9999999999);

    //用于油小猴服务器检测的脚本作者
    const realauthor = scriptInfo.author;
    const author = '油小猴';

    //用于油小猴服务器检测的脚本名称
    const realname = scriptInfo.name;
    const name = '网盘直链下载助手';

    const customClass = {
        popup: 'pl-popup',
        header: 'pl-header',
        title: 'pl-title',
        closeButton: 'pl-close',
        content: 'pl-content',
        input: 'pl-input',
        footer: 'pl-footer'
    };//准备好要用到的元素


    //准备好Shell类型(用于curl下载)
    const terminalType = {
        wc: "Microsoft Windows 命令提示符",
        wp: "Microsoft Windows PowerShell",
        lt: "Linux 终端",
        ls: "Linux Shell",
        mt: "Apple MacOS 终端",
    };

    //准备好信息界面的*假隐私设置*(实际上油小猴是通过自己服务器获取的“暗号”)
    const getuserinfo = {
        yes: "允许",
    };
    const hideidm = {
        yes: "隐藏",
        no: "显示"
    };

    //准备好右上角的Toast提示
    let toast = Swal.mixin({
        toast: true,
        position: 'top-end',
        showConfirmButton: false,
        timer: 3500,
        timerProgressBar: true,
        showCloseButton: true,
        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 = {
        //脚本正常情况下默认加载的菜单
        registerMenuCommand() {
            GM_registerMenuCommand('⚙️ 设置', () => {
                base.showSetting();
            });
            GM_registerMenuCommand('更新日志', () => {
                base.showUpdateLog();
            });
            GM_registerMenuCommand('分析信息', () => {
                base.showInfo();
            });
            GM_registerMenuCommand('取消点亮按钮', () => {
                base.registerSetting();
            });
        },

        registerPanMenuCommand() {
            GM_registerMenuCommand('⚙️ 设置', () => {
                base.showSetting();
            });
            GM_registerMenuCommand('更新日志', () => {
                base.showUpdateLog();
            });
            GM_registerMenuCommand('分析信息', () => {
                base.showPanInfo();
            });
        },

        //取消点亮按钮按下后运行的
        registerSetting() {
            console.log("正在注入取消点亮按钮设置项目...");
            message.warning("正在注入取消点亮按钮设置项目...(您可以再次点亮按钮)");
            base.setValue('setting_init_code', 111111);
            history.go(0)
        },

        //获取网页Cookie
        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 '';
        },

        isType(obj) {
            return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
        },

        getValue(name) {
            return GM_getValue(name);
        },

        setValue(name, value) {
            GM_setValue(name, value);
        },

        getStorage(key) {
            try {
                return JSON.parse(localStorage.getItem(key));
            } catch (e) {
                return localStorage.getItem(key);
            }
        },

        setStorage(key, value) {
            if (this.isType(value) === 'object' || this.isType(value) === 'array') {
                return localStorage.setItem(key, JSON.stringify(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());
        },

        fixFilename(name) {
            return name.replace(/[!?&|`"'*\/:<>\\]/g, '_');
        },

        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 (this.isType(data) === '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);
                    },
                });
            });
        },

        getFinalUrl(url, headers) {
            return new Promise((resolve, reject) => {
                let requestObj = GM_xmlhttpRequest({
                    method: "GET", url, headers,
                    onload: (res) => {
                        resolve(res.finalUrl);
                    },
                    onerror: (err) => {
                        reject(err);
                    },
                });
            });
        },

        stringify(obj) {
            let str = '';
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    var value = obj[key];
                    if (Array.isArray(value)) {
                        for (var i = 0; i < value.length; i++) {
                            str += encodeURIComponent(key) + '=' + encodeURIComponent(value[i]) + '&';
                        }
                    } else {
                        str += encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
                    }
                }
            }
            return str.slice(0, -1); // 去掉末尾的 "&"
        },

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

        sleep(time) {
            return new Promise(resolve => setTimeout(resolve, time));
        },

        findReact(dom, traverseUp = 0) {
            const key = Object.keys(dom).find(key => {
                return key.startsWith("__reactFiber$")
                || key.startsWith("__reactInternalInstance$");
            });
            const domFiber = dom[key];
            if (domFiber == null) return null;

            if (domFiber._currentElement) {
                let compFiber = domFiber._currentElement._owner;
                for (let i = 0; i < traverseUp; i++) {
                    compFiber = compFiber._currentElement._owner;
                }
                return compFiber._instance;
            }

            const GetCompFiber = fiber => {
                let parentFiber = fiber.return;
                while (typeof parentFiber.type == "string") {
                    parentFiber = parentFiber.return;
                }
                return parentFiber;
            };
            let compFiber = GetCompFiber(domFiber);
            for (let i = 0; i < traverseUp; i++) {
                compFiber = GetCompFiber(compFiber);
            }
            return compFiber.stateNode || compFiber;
        },

        //注册默认设置
        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: '#574ab8'
            }, {
                name: 'setting_init_code',
                value: ''
            }, {
                name: 'setting_getuser_info',
                value: 'yes'
            }, {
                name: 'setting_hide_idm',
                value: 'no'
            }];

            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', '#574ab8', '#F8D800', '#0396FF', '#32CCBC', '#F6416C', '#2271b1', '#59524c', '#1d2327', '#18a497', '#10171d', '#2828ff'];
            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">未找到IDM提示</div><select class="pl-input hide_idm">`;
            Object.keys(hideidm).forEach(value2 => {dom += `<option value="${value2}" ${base.getValue('setting_hide_idm') === value2 ? 'selected' : ''}>${hideidm[value2]}</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('主题色设置成功!');
                setTimeout(function(){
                    history.go(0);
                },1000)
            });
            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);
            });
            doc.on('change', '.hide_idm', async (e) => {
                base.setValue('setting_hide_idm', e.target.value);
            });
        },

        showInfo() {
            let hideinfo='';
            hideinfo +=`<span>以下内容都是脚本自己检测到的信息<br>本页面仅作为调试使用<span>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">版本</div>${realversion}</label>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">虚假版本</div>${version}</label>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">脚本作者</div>${realauthor}</label>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">虚假作者</div>${author}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化暗号</div>${pan.num}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">UA代理</div>${pan.ua}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">公众号地址</div>${pan.img}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘万能助手</div>${pan.assistant}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘镜像</div>${pan.mirror}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">RPC管理</div>${pan.d}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">IDM介绍</div>${pan.idm}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">提示文本</div>0、${pan.init[0]}<br>1、${pan.init[1]}<br>2、${pan.init[2]}<br>3、${pan.init[3]}<br>4、${pan.init[4]}<br>5、${pan.init[5]}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">页脚</div>${pan.fotter}</label>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">允许油小猴在线收集作者名称与获取暗号(没有用)</div><select class="pl-input getuser_info">`;
            Object.keys(getuserinfo).forEach(value1 => {hideinfo += `<option value="${value1}" ${base.getValue('setting_getuser_info') === value1 ? 'selected' : ''}>${getuserinfo[value1]}</option></select></label>`;});
            hideinfo = '<div>' + hideinfo + '</div>';

            Swal.fire({
                icon: 'info',
                title: '脚本分析信息',
                html: hideinfo,
                allowOutsideClick: false,
                showCloseButton: true,
                confirmButtonText: '保存配置(关闭)'
            });

            doc.on('change', '.getuser_info', async (e) => {
                base.setValue('setting_getuser_info', e.target.value);
            });
        },

        showPanInfo() {
            let hideinfo='';
            hideinfo +=`<span>本页面仅作为调试使用<span>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">版本</div>${realversion}</label>`;
            hideinfo +=`<label class="pl-setting-label"><div class="pl-label">作者</div>${realauthor}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化暗号</div>${pan.num}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">公众号地址</div>${pan.img}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘万能助手</div>${pan.assistant}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">RPC管理</div>${pan.d}</label>`;
            hideinfo += `<label class="pl-setting-label"><div class="pl-label">IDM介绍</div>${pan.idm}</label>`;
            hideinfo = '<div>' + hideinfo + '</div>';

            Swal.fire({
                icon: 'info',
                title: '脚本分析信息',
                html: hideinfo,
                allowOutsideClick: false,
                showCloseButton: true,
                confirmButtonText: '关闭'
            });
        },

        showUpdateLog() {
            Swal.fire({
                icon: 'info',
                title: '更新日志(关闭按钮在下面哦)',
                html: '<span>V1.0.6.4<br>1、跟进官方V6.1.1版本,修复阿里云盘获取下载链接时的问题。<br><br>V1.0.6.3<br>1、照顾小屏幕用户,将始终显示复制全部链接的按钮;<br>2、增加取消下载时的动画。<br><br>V1.0.6.2<br>1、修复部分界面错位,实现CSS内置;<br>2、百度网盘界面将变得更加简洁。<br><br>V1.0.6.1<br>1、新增百度云盘API下载支持复制链接;<br>2、为了照顾手机浏览器用户,增大项目之间间隙,新增隐藏IDM提示选项,可在助手设置中启用;<br>3、修改CSS,界面会出现更多的主题色;<br>4、支持在游小猴官网查看暗号;<br>5、修复部分语法错误。<br><br>V1.0.6<br>1、修复了打开阿里云盘分享连接时因下载移动端广告导致只能点击API下载;<br>2、跟进官方6.0.4版本,修复夸克网盘获取下载链接失效、支持移动云盘。<br><br>V1.0.5.5<br>1、感谢<a href="https://github.com/Night-stars-1">Night-stars-1</a>的帮助,修复因为原作者服务器导致的初始化暗号识别错误;<br>2、修改一些文本以及提供给服务器的信息。<br><br>V1.0.5.4<br>1、小修小改css,让主题色出现在更多地方;<br>2、修改下载链接获取失败的提示;<br>3、增加更多的主题色,可在助手设置查看;<br>4、homo彩蛋被删去力(悲)。<br><br>V1.0.5.3<br>1、修啦修啦,阿里云盘可以摸到下载菜单了。<br><br>V1.0.5.2<br>1、增加脚本信息菜单(没有用);<br>2、优化阿里云盘显示svg图片;<br>3、修改弹窗按钮颜色。<br><br>V1.0.5.1<br>1、修复在切换按钮主题后夸克网盘不能正常显示按钮。<br><br>V1.0.5<br>1、跟进官方V5.0.4版本;<br>2、小改动,照着官方版本更正文件名称检测;<br>3、保留彩蛋,但必须舍弃官方暗号。<br><br>V1.0.4<br>大改!<br>1、修复了原作者留下的夸克网盘切换文件夹就多一个“下载助手”按钮的大BUG;<br>2、终于来了,在下载菜单增加“助手设置”“更新日志”按钮;<br>【再也不用点进油猴管理再进设置了(保留油猴管理内设置)】<br>3、修改阿里云盘和夸克网盘下载助手按钮样式;<br>4、增加“取消点亮按钮”油猴菜单;<br>5、修改部分css,使其与选择的主题更贴切。<br><br>V1.0.3<br>1、增加一个小彩蛋; 提示:homo(需在未点亮按钮状态触发)<br>【需要重新恢复按钮为未点亮状态请进入 已安装脚本->编辑->开发者->重置到出厂->确定】<br>2、修改/增加默认主题色。<br><br>V1.0.2<br>1、修改并加宽界面,调整部分css,使Sweetalert2界面更美观,更与原版相近;<br>2、修改部分提示文字,使文字更容易复制。 <br><br>V1.0.1<br>1、去除更新提示;<br>2、更新Sweetalert2至11版本;<br>3、部分CDN节点更换为jsdelivr。<br><br>V1.0.0<br>1、增加“注入”功能(bushi);<br>2、去除广告。</span>',
                allowOutsideClick: false,
                showCloseButton: false,
                confirmButtonText: '我已阅',
            });
        },

        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: ${color}">${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);
        },

        getMirrorList(link, mirror, thread = 2) {
            let host = new URL(link).host;
            let mirrors = [];
            for (let i = 0; i < mirror.length; i++) {
                for (let j = 0; j < thread; j++) {
                    let item = link.replace(host, mirror[i]) + '&'.repeat(j);
                    mirrors.push(item);
                }
            }
            return mirrors.join('\n');
        },

        addPanLinkerStyle() {
            color = base.getValue('setting_theme_color');
            let css = `
            body::-webkit-scrollbar { display: none }
            ::-webkit-scrollbar { width: 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; width: 550px;}
            .pl-popup { font-size: 12px !important; width: 99% !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 { background-color:${color}15 ;overflow:auto; border-radius: 5px; max-height:calc(${document.documentElement.clientHeight}px - 250px);}
            .pl-footer {font-size: 15px!important;justify-content: flex-start!important; margin: 10px 0 0!important; padding: 5px 0 0!important; color: #f56c6c!important; height:25px;}
            .pl-item { display: flex; align-items: center; line-height: 22px; height: 50px; background-color: ${color}30; border-radius: 5px; margin: 8px 6px; }
            .pl-item-name { flex: 0 0 170px; text-align: left;margin: 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor:default; height: 30px;}
            .pl-item-link { flex: 1; text-align: left; white-space: nowrap; text-overflow: ellipsis;cursor:pointer; overflow: hidden; }
            .pl-item-btn { background: ${color}; border-radius: 3px; color: #ffffff; cursor: pointer; font-size: 12px; outline: none; display: flex; align-items: center; justify-content: center; margin: 6px 6px; padding: 0.625em 1.1em; }
            .pl-item-tip { display: flex; justify-content: space-between;flex: 1; }
            .pl-back { width: 70px; background: #ddd; border-radius: 3px; cursor:pointer; margin:1px 6px; }
            .pl-ext { display: inline-block; width: 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;width: 100%; box-sizing: border-box;line-height: 1;position: relative;height:15px; flex: 1}
            .pl-progress-outer { height: 15px;border-radius: 100px;background-color: #c1c1c1;overflow: hidden;position: relative;vertical-align: middle;}
            .pl-progress-inner{ position: absolute;left: 0;top: 0;background-color: ${color};text-align: center;border-radius: 100px;line-height: 1;white-space: nowrap;transition: width .6s ease;}
            .pl-progress-inner-text { display: inline-block;vertical-align: middle;color: #ffffff;font-size: 12px;margin: 0 5px;height: 15px}
            .pl-progress-tip{ flex:1; text-align:right}
            .pl-progress-how{ flex: 0 0 100px; background: #ddd; border-radius: 3px; margin-left: 10px; cursor: pointer; text-align: center;}
            .pl-progress-stop{ flex: 0 0 80px; background: #cc3235; cursor: pointer; margin: 6px 6px 6px 10px; font-size: 12px; border: 0; border-radius: 4px; color: #ffffff; outline: none; display: flex; align-items: center; justify-content: center; padding: 0.625em 1.1em;}
            .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: 6px 6px; padding: 0.625em 1.1em;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;font-size: 14px;margin-left: 20px;padding: 1px 12px;position: relative;border: 0 solid transparent;font-size: 14px;margin-left: 20px;padding: 1px 12px;position: relative;width: 32px;height: 32px;background: linear-gradient(129.12deg, #446dff 0%, rgba(99, 125, 255, 0.75) 100%);border-radius: 100px;display: flex;align-items: center;justify-content: center;color: var(--basic_white);cursor: pointer;transition: all .3s ease;}
            .ali-button-big {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;border-radius: 5px;box-shadow: 0 0 0 0 transparent;width: 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: ${color};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 ${color}; background: ${color}; cursor: pointer; position: relative;}
            .tianyi-button:hover {border-color: #a5a5a5; background: #a5a5a5;}
            .yidong-button {float: left; position: relative; margin: 20px 24px 20px 0; width: 98px; height: 36px; background: ${color}; border-radius: 2px; font-size: 14px; color: #fff; line-height: 39px; text-align: center; cursor: pointer;}
            .yidong-share-button {display: inline-block; position: relative; font-size: 14px; line-height: 36px; text-align: center; color: #fff; border: 1px solid ${color}; border-radius: 2px; padding: 0 24px; margin-left: 24px; background: ${color};}
            .yidong-button:hover {background: #a5a5a5;}
            .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;width: 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: ${color};margin-left: 12px;padding: 0px 12px;position: relative; cursor:pointer; height: 36px;}
            .xunlei-button:hover {background: #a5a5a5;}
            .quark-button {display: inline-flex; align-items: center; justify-content: center; border: 1px solid #ddd; border-radius: 8px; white-space: nowrap; flex-shrink: 0; font-size: 14px; line-height: 1.5; outline: 0; color: #fff; margin-right: 10px; padding: 0px 14px; position: relative; cursor: pointer; height: 36px;}
            .quark-button:hover { background: #a5a5a5;}
            .pl-dropdown-menu {position: absolute;right: 0;top: 25px;padding: 5px 0;color: ${color};background: #fff;z-index: 999;width: 102px;border-radius: 10px;box-shadow: 0 0 1px 1px rgb(28 28 32 / 5%), 0 8px 24px rgb(28 28 32 / 12%); text-align: center;}
            .pl-dropdown-menu-old {position: absolute;right: 0;top: 30px;padding: 5px 0;color: rgb(37, 38, 43);background: #fff;z-index: 999;width: 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;color: ${color};}
            .pl-dropdown-menu-item:hover { background-color: rgba(132,133,141,0.08);}
            .pl-button .pl-dropdown-menu { display: none; }
            .pl-button-mode {padding: 0px !important;}
            .pl-button:hover .pl-dropdown-menu { display: block!important; }
            .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}
            .pl-color-box { width: 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-width: 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;width: 82px;height: 82px;background: #ffffff;}
            .pl-loading-box > div > div:nth-child(2) { top: 14px;left: 38px;width: 25px;height: 25px;background: #666666;animation: load 1s linear infinite;transform-origin: 12px 36px;}
            .pl-loading { width: 16px;height: 16px;display: inline-block;overflow: hidden;background: none;}
            .pl-loading-box { width: 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);

            let swalcss = `
.swal2-popup.swal2-toast {
                box-sizing:border-box;
                grid-column:1/4!important;
                grid-row:1/4!important;
                grid-template-columns:1fr 99fr 1fr;
                padding:1em;
                overflow-y:hidden;
                background:#fff;
                box-shadow:0 0 1px hsla(0deg,0%,0%,.075),0 1px 2px hsla(0deg,0%,0%,.075),1px 2px 4px hsla(0deg,0%,0%,.075),1px 3px 8px hsla(0deg,0%,0%,.075),2px 4px 16px hsla(0deg,0%,0%,.075);
                pointer-events:all
}
.swal2-popup.swal2-toast>* {
                grid-column:2
}
.swal2-popup.swal2-toast .swal2-title {
                margin:.5em 1em;
                padding:0;
                font-size:1em;
                text-align:initial
}
.swal2-popup.swal2-toast .swal2-loading {
                justify-content:center
}
.swal2-popup.swal2-toast .swal2-input {
                height:2em;
                margin:.5em;
                font-size:1em
}
.swal2-popup.swal2-toast .swal2-validation-message {
                font-size:1em
}
.swal2-popup.swal2-toast .swal2-footer {
                margin:.5em 0 0;
                padding:.5em 0 0;
                font-size:.8em
}
.swal2-popup.swal2-toast .swal2-close {
                grid-column:3/3;
                grid-row:1/99;
                align-self:center;
                width:.8em;
                height:.8em;
                margin:0;
                font-size:2em
}
.swal2-popup.swal2-toast .swal2-html-container {
                margin:.5em 1em;
                padding:0;
                overflow:initial;
                font-size:1em;
                text-align:initial
}
.swal2-popup.swal2-toast .swal2-html-container:empty {
                padding:0
}
.swal2-popup.swal2-toast .swal2-loader {
                grid-column:1;
                grid-row:1/99;
                align-self:center;
                width:2em;
                height:2em;
                margin:.25em
}
.swal2-popup.swal2-toast .swal2-icon {
                grid-column:1;
                grid-row:1/99;
                align-self:center;
                width:2em;
                min-width:2em;
                height:2em;
                margin:0 .5em 0 0
}
.swal2-popup.swal2-toast .swal2-icon .swal2-icon-content {
                display:flex;
                align-items:center;
                font-size:1.8em;
                font-weight:700
}
.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring {
                width:2em;
                height:2em
}
.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line] {
                top:.875em;
                width:1.375em
}
.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
                left:.3125em
}
.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
                right:.3125em
}
.swal2-popup.swal2-toast .swal2-actions {
                justify-content:flex-start;
                height:auto;
                margin:0;
                margin-top:.5em;
                padding:0 .5em
}
.swal2-popup.swal2-toast .swal2-styled {
                margin:.25em .5em;
                padding:.4em .6em;
                font-size:1em
}
.swal2-popup.swal2-toast .swal2-success {
                border-color:#a5dc86
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line] {
                position:absolute;
                width:1.6em;
                height:3em;
                transform:rotate(45deg);
                border-radius:50%
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left] {
                top:-.8em;
                left:-.5em;
                transform:rotate(-45deg);
                transform-origin:2em 2em;
                border-radius:4em 0 0 4em
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right] {
                top:-.25em;
                left:.9375em;
                transform-origin:0 1.5em;
                border-radius:0 4em 4em 0
}
.swal2-popup.swal2-toast .swal2-success .swal2-success-ring {
                width:2em;
                height:2em
}
.swal2-popup.swal2-toast .swal2-success .swal2-success-fix {
                top:0;
                left:.4375em;
                width:.4375em;
                height:2.6875em
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line] {
                height:.3125em
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip] {
                top:1.125em;
                left:.1875em;
                width:.75em
}
.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long] {
                top:.9375em;
                right:.1875em;
                width:1.375em
}
.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip {
                -webkit-animation:swal2-toast-animate-success-line-tip .75s;
                animation:swal2-toast-animate-success-line-tip .75s
}
.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long {
                -webkit-animation:swal2-toast-animate-success-line-long .75s;
                animation:swal2-toast-animate-success-line-long .75s
}
.swal2-popup.swal2-toast.swal2-show {
                -webkit-animation:swal2-toast-show .5s;
                animation:swal2-toast-show .5s
}
.swal2-popup.swal2-toast.swal2-hide {
                -webkit-animation:swal2-toast-hide .1s forwards;
                animation:swal2-toast-hide .1s forwards
}
.swal2-container {
                display:grid;
                position:fixed;
                z-index:1060;
                top:0;
                right:0;
                bottom:0;
                left:0;
                box-sizing:border-box;
                grid-template-areas:"top-start         top                        top-end" "center-start  center                 center-end" "bottom-start  bottom-center  bottom-end";
                grid-template-rows:minmax(-webkit-min-content,auto) minmax(-webkit-min-content,auto) minmax(-webkit-min-content,auto);
                grid-template-rows:minmax(min-content,auto) minmax(min-content,auto) minmax(min-content,auto);
                height:100%;
                padding:.625em;
                overflow-x:hidden;
                transition:background-color .1s;
                -webkit-overflow-scrolling:touch
}
.swal2-container.swal2-backdrop-show,.swal2-container.swal2-noanimation {
                background:${color}66 !important
}
.swal2-container.swal2-backdrop-hide {
                background:0 0!important
}
.swal2-container.swal2-bottom-start,.swal2-container.swal2-center-start,.swal2-container.swal2-top-start {
                grid-template-columns:minmax(0,1fr) auto auto
}
.swal2-container.swal2-bottom,.swal2-container.swal2-center,.swal2-container.swal2-top {
                grid-template-columns:auto minmax(0,1fr) auto
}
.swal2-container.swal2-bottom-end,.swal2-container.swal2-center-end,.swal2-container.swal2-top-end {
                grid-template-columns:auto auto minmax(0,1fr)
}
.swal2-container.swal2-top-start>.swal2-popup {
                align-self:start
}
.swal2-container.swal2-top>.swal2-popup {
                grid-column:2;
                align-self:start;
                justify-self:center
}
.swal2-container.swal2-top-end>.swal2-popup,.swal2-container.swal2-top-right>.swal2-popup {
                grid-column:3;
                align-self:start;
                justify-self:end
}
.swal2-container.swal2-center-left>.swal2-popup,.swal2-container.swal2-center-start>.swal2-popup {
                grid-row:2;
                align-self:center
}
.swal2-container.swal2-center>.swal2-popup {
                grid-column:2;
                grid-row:2;
                align-self:center;
                justify-self:center
}
.swal2-container.swal2-center-end>.swal2-popup,.swal2-container.swal2-center-right>.swal2-popup {
                grid-column:3;
                grid-row:2;
                align-self:center;
                justify-self:end
}
.swal2-container.swal2-bottom-left>.swal2-popup,.swal2-container.swal2-bottom-start>.swal2-popup {
                grid-column:1;
                grid-row:3;
                align-self:end
}
.swal2-container.swal2-bottom>.swal2-popup {
                grid-column:2;
                grid-row:3;
                justify-self:center;
                align-self:end
}
.swal2-container.swal2-bottom-end>.swal2-popup,.swal2-container.swal2-bottom-right>.swal2-popup {
                grid-column:3;
                grid-row:3;
                align-self:end;
                justify-self:end
}
.swal2-container.swal2-grow-fullscreen>.swal2-popup,.swal2-container.swal2-grow-row>.swal2-popup {
                grid-column:1/4;
                width:100%
}
.swal2-container.swal2-grow-column>.swal2-popup,.swal2-container.swal2-grow-fullscreen>.swal2-popup {
                grid-row:1/4;
                align-self:stretch
}
.swal2-container.swal2-no-transition {
                transition:none!important
}
.swal2-popup {
                display:none;
                position:relative;
                box-sizing:border-box;
                grid-template-columns:minmax(0,100%);
                width:32em;
                max-width:100%;
                padding:0 0 1.25em;
                border:none;
                border-radius:5px;
                background:#fff;
                color:#545454;
                font-family:inherit;
                font-size:1rem
}
.swal2-popup:focus {
                outline:0
}
.swal2-popup.swal2-loading {
                overflow-y:hidden
}
.swal2-title {
                position:relative;
                max-width:100%;
                margin:0;
                padding:.8em 1em 0;
                color:inherit;
                font-size:1.875em;
                font-weight:600;
                text-align:center;
                text-transform:none;
                word-wrap:break-word
}
.swal2-actions {
                display:flex;
                z-index:1;
                box-sizing:border-box;
                flex-wrap:wrap;
                align-items:center;
                justify-content:center;
                width:auto;
                margin:1.25em auto 0;
                padding:0
}
.swal2-actions:not(.swal2-loading) .swal2-styled[disabled] {
                opacity:.4
}
.swal2-actions:not(.swal2-loading) .swal2-styled:hover {
                background-image:linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.1))
}
.swal2-actions:not(.swal2-loading) .swal2-styled:active {
                background-image:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.2))
}
.swal2-loader {
                display:none;
                align-items:center;
                justify-content:center;
                width:2.2em;
                height:2.2em;
                margin:0 1.875em;
                -webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;
                animation:swal2-rotate-loading 1.5s linear 0s infinite normal;
                border-width:.25em;
                border-style:solid;
                border-radius:100%;
                border-color:${color} transparent ${color} transparent !important
}
.swal2-styled {
                margin:.3125em;
                padding:.625em 1.1em;
                transition:box-shadow .1s;
                box-shadow:0 0 0 3px transparent;
                font-weight:500
}
.swal2-styled:not([disabled]) {
                cursor:pointer
}
.swal2-styled.swal2-confirm {
                border:0;
                border-radius:.25em;
                background:initial;
                background-color:${color} !important;
                color:#fff;
                font-size:1em
}
.swal2-styled.swal2-confirm:focus {
                box-shadow:0 0 0 3px ${color}80 !important
}
.swal2-styled.swal2-deny {
                border:0;
                border-radius:.25em;
                background:initial;
                background-color:#dc3741;
                color:#fff;
                font-size:1em
}
.swal2-styled.swal2-deny:focus {
                box-shadow:0 0 0 3px rgba(220,55,65,.5)
}
.swal2-styled.swal2-cancel {
                border:0;
                border-radius:.25em;
                background:initial;
                background-color:#dd3333;
                color:#fff;
                font-size:1em
}
.swal2-styled.swal2-cancel:focus {
                box-shadow:0 0 0 3px rgba(110,120,129,.5)
}
.swal2-styled.swal2-default-outline:focus {
                box-shadow:0 0 0 3px rgba(100,150,200,.5)
}
.swal2-styled:focus {
                outline:0
}
.swal2-styled::-moz-focus-inner {
                border:0
}
.swal2-footer {
                justify-content:center;
                margin:1em 0 0;
                padding:1em 1em 0;
                border-top:1px solid #eee;
                color:inherit;
                font-size:1em
}
.swal2-timer-progress-bar-container {
                position:absolute;
                right:0;
                bottom:0;
                left:0;
                grid-column:auto!important;
                overflow:hidden;
                border-bottom-right-radius:5px;
                border-bottom-left-radius:5px
}
.swal2-timer-progress-bar {
                width:100%;
                height:.25em;
                background:rgba(0,0,0,.2)
}
.swal2-image {
                max-width:100%;
                margin:2em auto 1em
}
.swal2-close {
                z-index:2;
                align-items:center;
                justify-content:center;
                width:1.2em;
                height:1.2em;
                margin-top:0;
                margin-right:0;
                margin-bottom:-1.2em;
                padding:0;
                overflow:hidden;
                transition:color .1s,box-shadow .1s;
                border:none;
                border-radius:5px;
                background:0 0;
                color:#ccc;
                font-family:serif;
                font-family:monospace;
                font-size:2.5em;
                cursor:pointer;
                justify-self:end
}
.swal2-close:hover {
                transform:none;
                background:0 0;
                color:#f27474
}
.swal2-close:focus {
                outline:0;
                box-shadow:inset 0 0 0 3px rgba(100,150,200,.5)
}
.swal2-close::-moz-focus-inner {
                border:0
}
.swal2-html-container {
                z-index:1;
                justify-content:center;
                margin:1em 1.6em .3em;
                padding:0;
                overflow:auto;
                color:inherit;
                font-size:1.125em;
                font-weight:400;
                line-height:normal;
                text-align:center;
                word-wrap:break-word;
                word-break:break-word
}
.swal2-checkbox,.swal2-file,.swal2-input,.swal2-radio,.swal2-select,.swal2-textarea {
                margin:1em 2em 3px
}
.swal2-file,.swal2-input,.swal2-textarea {
                box-sizing:border-box;
                width:auto;
                transition:border-color .1s,box-shadow .1s;
                border:1px solid #d9d9d9;
                border-radius:.1875em;
                background:0 0;
                box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px transparent;
                color:inherit;
                font-size:1.125em
}
.swal2-file.swal2-inputerror,.swal2-input.swal2-inputerror,.swal2-textarea.swal2-inputerror {
                border-color:#f27474!important;
                box-shadow:0 0 2px #f27474!important
}
.swal2-file:focus,.swal2-input:focus,.swal2-textarea:focus {
                border:1px solid #b4dbed;
                outline:0;
                box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(100,150,200,.5)
}
.swal2-file::-moz-placeholder,.swal2-input::-moz-placeholder,.swal2-textarea::-moz-placeholder {
                color:#ccc
}
.swal2-file::placeholder,.swal2-input::placeholder,.swal2-textarea::placeholder {
                color:#ccc
}
.swal2-range {
                margin:1em 2em 3px;
                background:#fff
}
.swal2-range input {
                width:80%
}
.swal2-range output {
                width:20%;
                color:inherit;
                font-weight:600;
                text-align:center
}
.swal2-range input,.swal2-range output {
                height:2.625em;
                padding:0;
                font-size:1.125em;
                line-height:2.625em
}
.swal2-input {
                height:2.625em;
                padding:0 .75em
}
.swal2-file {
                width:75%;
                margin-right:auto;
                margin-left:auto;
                background:0 0;
                font-size:1.125em
}
.swal2-textarea {
                height:6.75em;
                padding:.75em
}
.swal2-select {
                min-width:50%;
                max-width:100%;
                padding:.375em .625em;
                background:0 0;
                color:inherit;
                font-size:1.125em
}
.swal2-checkbox,.swal2-radio {
                align-items:center;
                justify-content:center;
                background:#fff;
                color:inherit
}
.swal2-checkbox label,.swal2-radio label {
                margin:0 .6em;
                font-size:1.125em
}
.swal2-checkbox input,.swal2-radio input {
                flex-shrink:0;
                margin:0 .4em
}
.swal2-input-label {
                display:flex;
                justify-content:center;
                margin:1em auto 0
}
.swal2-validation-message {
                align-items:center;
                justify-content:center;
                margin:1em 0 0;
                padding:.625em;
                overflow:hidden;
                background:#f0f0f0;
                color:#666;
                font-size:1em;
                font-weight:300
}
.swal2-validation-message::before {
                content:"!";
                display:inline-block;
                width:1.5em;
                min-width:1.5em;
                height:1.5em;
                margin:0 .625em;
                border-radius:50%;
                background-color:#f27474;
                color:#fff;
                font-weight:600;
                line-height:1.5em;
                text-align:center
}
.swal2-icon {
                position:relative;
                box-sizing:content-box;
                justify-content:center;
                width:5em;
                height:5em;
                margin:2.5em auto .6em;
                border:.25em solid transparent;
                border-radius:50%;
                border-color:#000;
                font-family:inherit;
                line-height:5em;
                cursor:default;
                -webkit-user-select:none;
                -moz-user-select:none;
                user-select:none
}
.swal2-icon .swal2-icon-content {
                display:flex;
                align-items:center;
                font-size:3.75em
}
.swal2-icon.swal2-error {
                border-color:#f27474;
                color:#f27474
}
.swal2-icon.swal2-error .swal2-x-mark {
                position:relative;
                flex-grow:1
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line] {
                display:block;
                position:absolute;
                top:2.3125em;
                width:2.9375em;
                height:.3125em;
                border-radius:.125em;
                background-color:#f27474
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
                left:1.0625em;
                transform:rotate(45deg)
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
                right:1em;
                transform:rotate(-45deg)
}
.swal2-icon.swal2-error.swal2-icon-show {
                -webkit-animation:swal2-animate-error-icon .5s;
                animation:swal2-animate-error-icon .5s
}
.swal2-icon.swal2-error.swal2-icon-show .swal2-x-mark {
                -webkit-animation:swal2-animate-error-x-mark .5s;
                animation:swal2-animate-error-x-mark .5s
}
.swal2-icon.swal2-warning {
                border-color:#facea8;
                color:#f8bb86
}
.swal2-icon.swal2-warning.swal2-icon-show {
                -webkit-animation:swal2-animate-error-icon .5s;
                animation:swal2-animate-error-icon .5s
}
.swal2-icon.swal2-warning.swal2-icon-show .swal2-icon-content {
                -webkit-animation:swal2-animate-i-mark .5s;
                animation:swal2-animate-i-mark .5s
}
.swal2-icon.swal2-info {
                border-color:#9de0f6;
                color:#3fc3ee
}
.swal2-icon.swal2-info.swal2-icon-show {
                -webkit-animation:swal2-animate-error-icon .5s;
                animation:swal2-animate-error-icon .5s
}
.swal2-icon.swal2-info.swal2-icon-show .swal2-icon-content {
                -webkit-animation:swal2-animate-i-mark .8s;
                animation:swal2-animate-i-mark .8s
}
.swal2-icon.swal2-question {
                border-color:#c9dae1;
                color:#87adbd
}
.swal2-icon.swal2-question.swal2-icon-show {
                -webkit-animation:swal2-animate-error-icon .5s;
                animation:swal2-animate-error-icon .5s
}
.swal2-icon.swal2-question.swal2-icon-show .swal2-icon-content {
                -webkit-animation:swal2-animate-question-mark .8s;
                animation:swal2-animate-question-mark .8s
}
.swal2-icon.swal2-success {
                border-color:#a5dc86;
                color:#a5dc86
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line] {
                position:absolute;
                width:3.75em;
                height:7.5em;
                transform:rotate(45deg);
                border-radius:50%
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left] {
                top:-.4375em;
                left:-2.0635em;
                transform:rotate(-45deg);
                transform-origin:3.75em 3.75em;
                border-radius:7.5em 0 0 7.5em
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right] {
                top:-.6875em;
                left:1.875em;
                transform:rotate(-45deg);
                transform-origin:0 3.75em;
                border-radius:0 7.5em 7.5em 0
}
.swal2-icon.swal2-success .swal2-success-ring {
                position:absolute;
                z-index:2;
                top:-.25em;
                left:-.25em;
                box-sizing:content-box;
                width:100%;
                height:100%;
                border:.25em solid rgba(165,220,134,.3);
                border-radius:50%
}
.swal2-icon.swal2-success .swal2-success-fix {
                position:absolute;
                z-index:1;
                top:.5em;
                left:1.625em;
                width:.4375em;
                height:5.625em;
                transform:rotate(-45deg)
}
.swal2-icon.swal2-success [class^=swal2-success-line] {
                display:block;
                position:absolute;
                z-index:2;
                height:.3125em;
                border-radius:.125em;
                background-color:#a5dc86
}
.swal2-icon.swal2-success [class^=swal2-success-line][class$=tip] {
                top:2.875em;
                left:.8125em;
                width:1.5625em;
                transform:rotate(45deg)
}
.swal2-icon.swal2-success [class^=swal2-success-line][class$=long] {
                top:2.375em;
                right:.5em;
                width:2.9375em;
                transform:rotate(-45deg)
}
.swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-tip {
                -webkit-animation:swal2-animate-success-line-tip .75s;
                animation:swal2-animate-success-line-tip .75s
}
.swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-long {
                -webkit-animation:swal2-animate-success-line-long .75s;
                animation:swal2-animate-success-line-long .75s
}
.swal2-icon.swal2-success.swal2-icon-show .swal2-success-circular-line-right {
                -webkit-animation:swal2-rotate-success-circular-line 4.25s ease-in;
                animation:swal2-rotate-success-circular-line 4.25s ease-in
}
.swal2-progress-steps {
                flex-wrap:wrap;
                align-items:center;
                max-width:100%;
                margin:1.25em auto;
                padding:0;
                background:0 0;
                font-weight:600
}
.swal2-progress-steps li {
                display:inline-block;
                position:relative
}
.swal2-progress-steps .swal2-progress-step {
                z-index:20;
                flex-shrink:0;
                width:2em;
                height:2em;
                border-radius:2em;
                background:${color} !important;
                color:#fff;
                line-height:2em;
                text-align:center
}
.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step {
                background:${color} !important
}
.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step {
                background:#add8e6;
                color:#fff
}
.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line {
                background:#add8e6
}
.swal2-progress-steps .swal2-progress-step-line {
                z-index:10;
                flex-shrink:0;
                width:2.5em;
                height:.4em;
                margin:0 -1px;
                background:${color} !important
}
[class^=swal2] {
                -webkit-tap-highlight-color:transparent
}
.swal2-show {
                -webkit-animation:swal2-show .3s;
                animation:swal2-show .3s
}
.swal2-hide {
                -webkit-animation:swal2-hide .15s forwards;
                animation:swal2-hide .15s forwards
}
.swal2-noanimation {
                transition:none
}
.swal2-scrollbar-measure {
                position:absolute;
                top:-9999px;
                width:50px;
                height:50px;
                overflow:scroll
}
.swal2-rtl .swal2-close {
                margin-right:initial;
                margin-left:0
}
.swal2-rtl .swal2-timer-progress-bar {
                right:0;
                left:auto
}
.leave-russia-now-and-apply-your-skills-to-the-world {
                display:flex;
                position:fixed;
                z-index:1939;
                top:0;
                right:0;
                bottom:0;
                left:0;
                flex-direction:column;
                align-items:center;
                justify-content:center;
                padding:25px 0 20px;
                background:#20232a;
                color:#fff;
                text-align:center
}
.leave-russia-now-and-apply-your-skills-to-the-world div {
                max-width:560px;
                margin:10px;
                line-height:146%
}
.leave-russia-now-and-apply-your-skills-to-the-world iframe {
                max-width:100%;
                max-height:55.5555555556vmin;
                margin:16px auto
}
.leave-russia-now-and-apply-your-skills-to-the-world strong {
                border-bottom:2px dashed #fff
}
.leave-russia-now-and-apply-your-skills-to-the-world button {
                display:flex;
                position:fixed;
                z-index:1940;
                top:0;
                right:0;
                align-items:center;
                justify-content:center;
                width:48px;
                height:48px;
                margin-right:10px;
                margin-bottom:-10px;
                border:none;
                background:0 0;
                color:#aaa;
                font-size:48px;
                font-weight:700;
                cursor:pointer
}
.leave-russia-now-and-apply-your-skills-to-the-world button:hover {
                color:#fff
}
@-webkit-keyframes swal2-toast-show {
                0% {
                transform:translateY(-.625em) rotateZ(2deg)
}
33% {
                transform:translateY(0) rotateZ(-2deg)
}
66% {
                transform:translateY(.3125em) rotateZ(2deg)
}
100% {
                transform:translateY(0) rotateZ(0)
}
}@keyframes swal2-toast-show {
                0% {
                transform:translateY(-.625em) rotateZ(2deg)
}
33% {
                transform:translateY(0) rotateZ(-2deg)
}
66% {
                transform:translateY(.3125em) rotateZ(2deg)
}
100% {
                transform:translateY(0) rotateZ(0)
}
}@-webkit-keyframes swal2-toast-hide {
                100% {
                transform:rotateZ(1deg);
                opacity:0
}
}@keyframes swal2-toast-hide {
                100% {
                transform:rotateZ(1deg);
                opacity:0
}
}@-webkit-keyframes swal2-toast-animate-success-line-tip {
                0% {
                top:.5625em;
                left:.0625em;
                width:0
}
54% {
                top:.125em;
                left:.125em;
                width:0
}
70% {
                top:.625em;
                left:-.25em;
                width:1.625em
}
84% {
                top:1.0625em;
                left:.75em;
                width:.5em
}
100% {
                top:1.125em;
                left:.1875em;
                width:.75em
}
}@keyframes swal2-toast-animate-success-line-tip {
                0% {
                top:.5625em;
                left:.0625em;
                width:0
}
54% {
                top:.125em;
                left:.125em;
                width:0
}
70% {
                top:.625em;
                left:-.25em;
                width:1.625em
}
84% {
                top:1.0625em;
                left:.75em;
                width:.5em
}
100% {
                top:1.125em;
                left:.1875em;
                width:.75em
}
}@-webkit-keyframes swal2-toast-animate-success-line-long {
                0% {
                top:1.625em;
                right:1.375em;
                width:0
}
65% {
                top:1.25em;
                right:.9375em;
                width:0
}
84% {
                top:.9375em;
                right:0;
                width:1.125em
}
100% {
                top:.9375em;
                right:.1875em;
                width:1.375em
}
}@keyframes swal2-toast-animate-success-line-long {
                0% {
                top:1.625em;
                right:1.375em;
                width:0
}
65% {
                top:1.25em;
                right:.9375em;
                width:0
}
84% {
                top:.9375em;
                right:0;
                width:1.125em
}
100% {
                top:.9375em;
                right:.1875em;
                width:1.375em
}
}@-webkit-keyframes swal2-show {
                0% {
                transform:scale(.7)
}
45% {
                transform:scale(1.05)
}
80% {
                transform:scale(.95)
}
100% {
                transform:scale(1)
}
}@keyframes swal2-show {
                0% {
                transform:scale(.7)
}
45% {
                transform:scale(1.05)
}
80% {
                transform:scale(.95)
}
100% {
                transform:scale(1)
}
}@-webkit-keyframes swal2-hide {
                0% {
                transform:scale(1);
                opacity:1
}
100% {
                transform:scale(.5);
                opacity:0
}
}@keyframes swal2-hide {
                0% {
                transform:scale(1);
                opacity:1
}
100% {
                transform:scale(.5);
                opacity:0
}
}@-webkit-keyframes swal2-animate-success-line-tip {
                0% {
                top:1.1875em;
                left:.0625em;
                width:0
}
54% {
                top:1.0625em;
                left:.125em;
                width:0
}
70% {
                top:2.1875em;
                left:-.375em;
                width:3.125em
}
84% {
                top:3em;
                left:1.3125em;
                width:1.0625em
}
100% {
                top:2.8125em;
                left:.8125em;
                width:1.5625em
}
}@keyframes swal2-animate-success-line-tip {
                0% {
                top:1.1875em;
                left:.0625em;
                width:0
}
54% {
                top:1.0625em;
                left:.125em;
                width:0
}
70% {
                top:2.1875em;
                left:-.375em;
                width:3.125em
}
84% {
                top:3em;
                left:1.3125em;
                width:1.0625em
}
100% {
                top:2.8125em;
                left:.8125em;
                width:1.5625em
}
}@-webkit-keyframes swal2-animate-success-line-long {
                0% {
                top:3.375em;
                right:2.875em;
                width:0
}
65% {
                top:3.375em;
                right:2.875em;
                width:0
}
84% {
                top:2.1875em;
                right:0;
                width:3.4375em
}
100% {
                top:2.375em;
                right:.5em;
                width:2.9375em
}
}@keyframes swal2-animate-success-line-long {
                0% {
                top:3.375em;
                right:2.875em;
                width:0
}
65% {
                top:3.375em;
                right:2.875em;
                width:0
}
84% {
                top:2.1875em;
                right:0;
                width:3.4375em
}
100% {
                top:2.375em;
                right:.5em;
                width:2.9375em
}
}@-webkit-keyframes swal2-rotate-success-circular-line {
                0% {
                transform:rotate(-45deg)
}
5% {
                transform:rotate(-45deg)
}
12% {
                transform:rotate(-405deg)
}
100% {
                transform:rotate(-405deg)
}
}@keyframes swal2-rotate-success-circular-line {
                0% {
                transform:rotate(-45deg)
}
5% {
                transform:rotate(-45deg)
}
12% {
                transform:rotate(-405deg)
}
100% {
                transform:rotate(-405deg)
}
}@-webkit-keyframes swal2-animate-error-x-mark {
                0% {
                margin-top:1.625em;
                transform:scale(.4);
                opacity:0
}
50% {
                margin-top:1.625em;
                transform:scale(.4);
                opacity:0
}
80% {
                margin-top:-.375em;
                transform:scale(1.15)
}
100% {
                margin-top:0;
                transform:scale(1);
                opacity:1
}
}@keyframes swal2-animate-error-x-mark {
                0% {
                margin-top:1.625em;
                transform:scale(.4);
                opacity:0
}
50% {
                margin-top:1.625em;
                transform:scale(.4);
                opacity:0
}
80% {
                margin-top:-.375em;
                transform:scale(1.15)
}
100% {
                margin-top:0;
                transform:scale(1);
                opacity:1
}
}@-webkit-keyframes swal2-animate-error-icon {
                0% {
                transform:rotateX(100deg);
                opacity:0
}
100% {
                transform:rotateX(0);
                opacity:1
}
}@keyframes swal2-animate-error-icon {
                0% {
                transform:rotateX(100deg);
                opacity:0
}
100% {
                transform:rotateX(0);
                opacity:1
}
}@-webkit-keyframes swal2-rotate-loading {
                0% {
                transform:rotate(0)
}
100% {
                transform:rotate(360deg)
}
}@keyframes swal2-rotate-loading {
                0% {
                transform:rotate(0)
}
100% {
                transform:rotate(360deg)
}
}@-webkit-keyframes swal2-animate-question-mark {
                0% {
                transform:rotateY(-360deg)
}
100% {
                transform:rotateY(0)
}
}@keyframes swal2-animate-question-mark {
                0% {
                transform:rotateY(-360deg)
}
100% {
                transform:rotateY(0)
}
}@-webkit-keyframes swal2-animate-i-mark {
                0% {
                transform:rotateZ(45deg);
                opacity:0
}
25% {
                transform:rotateZ(-25deg);
                opacity:.4
}
50% {
                transform:rotateZ(15deg);
                opacity:.8
}
75% {
                transform:rotateZ(-5deg);
                opacity:1
}
100% {
                transform:rotateX(0);
                opacity:1
}
}@keyframes swal2-animate-i-mark {
                0% {
                transform:rotateZ(45deg);
                opacity:0
}
25% {
                transform:rotateZ(-25deg);
                opacity:.4
}
50% {
                transform:rotateZ(15deg);
                opacity:.8
}
75% {
                transform:rotateZ(-5deg);
                opacity:1
}
100% {
                transform:rotateX(0);
                opacity:1
}
}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
                overflow:hidden
}
body.swal2-height-auto {
                height:auto!important
}
body.swal2-no-backdrop .swal2-container {
                background-color:transparent!important;
                pointer-events:none
}
body.swal2-no-backdrop .swal2-container .swal2-popup {
                pointer-events:all
}
body.swal2-no-backdrop .swal2-container .swal2-modal {
                box-shadow:0 0 10px rgba(0,0,0,.4)
}
@media print {
                body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
                overflow-y:scroll!important
}
body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true] {
                display:none
}
body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container {
                position:static!important
}
}body.swal2-toast-shown .swal2-container {
                box-sizing:border-box;
                width:360px;
                max-width:100%;
                background-color:transparent;
                pointer-events:none
}
body.swal2-toast-shown .swal2-container.swal2-top {
                top:0;
                right:auto;
                bottom:auto;
                left:50%;
                transform:translateX(-50%)
}
body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right {
                top:0;
                right:0;
                bottom:auto;
                left:auto
}
body.swal2-toast-shown .swal2-container.swal2-top-left,body.swal2-toast-shown .swal2-container.swal2-top-start {
                top:0;
                right:auto;
                bottom:auto;
                left:0
}
body.swal2-toast-shown .swal2-container.swal2-center-left,body.swal2-toast-shown .swal2-container.swal2-center-start {
                top:50%;
                right:auto;
                bottom:auto;
                left:0;
                transform:translateY(-50%)
}
body.swal2-toast-shown .swal2-container.swal2-center {
                top:50%;
                right:auto;
                bottom:auto;
                left:50%;
                transform:translate(-50%,-50%)
}
body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right {
                top:50%;
                right:0;
                bottom:auto;
                left:auto;
                transform:translateY(-50%)
}
body.swal2-toast-shown .swal2-container.swal2-bottom-left,body.swal2-toast-shown .swal2-container.swal2-bottom-start {
                top:auto;
                right:auto;
                bottom:0;
                left:0
}
body.swal2-toast-shown .swal2-container.swal2-bottom {
                top:auto;
                right:auto;
                bottom:0;
                left:50%;
                transform:translateX(-50%)
}
body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right {
                top:auto;
                right:0;
                bottom:0;
                left:auto
}
`;
            this.addStyle('swal-style', 'style', swalcss);
        },

        async initDialog() {
            let result = await Swal.fire({
                title: pan.init[0],
                allowOutsideClick: false,
                showCloseButton: true,
                showCancelButton: true,
                confirmButtonText: '确定',
                html: `<div><img style="width: 250px;margin-bottom: 10px;" src="${pan.img}" alt="${pan.img}"><input class="swal2-input" id="init" style="width:373;font-size:19px;" type="text" placeholder="${pan.init[1]}"><br><span>你可以选择“注入”立即点亮按钮,或者输入暗号。<br>暗号:“${pan.num}”。<br>(也可以扫码支持一下原作者油小猴)</span></div>`,
                cancelButtonText: '注入(点亮下载助手按钮)'
            });
            if (result.isDismissed && result.dismiss === 'close') {console.log("窗口关闭");return};
            if (result.isDismissed && result.dismiss === 'cancel') {
                console.log("注入暗号")
                console.log("正在注入点亮按钮设置项目...");
                message.warning("正在注入点亮按钮设置项目...");
                setTimeout(() => {
                    base.setValue('setting_init_code', pan.num);
                    message.success("注入成功!");
                    setTimeout(() => {
                        message.success(pan.init[2]);
                        setTimeout(() => {
                            history.go(0);
                        }, 3000);
                    }, 3000);
                }, 5000);
                return;
            };
            if (pan.num === $('#init').val()) {
                console.log("暗号正确")
                message.success(pan.init[2]);
                setTimeout(() => {
                    base.setValue('setting_init_code', pan.num);
                    history.go(0);
                }, 3000)
                return;
            } else {
                console.log("暗号错误")
                await Swal.fire({
                    imageUrl: pan.img,
                    title: pan.init[3],
                    html: `<div><span>${pan.init[4]}<br>你可以在返回后选择“注入”立即点亮按钮,<br>或者在输入框键入以下暗号:“${pan.num}”。</span></div>`,
                    confirmButtonText: '重新输入(返回)',
                });
                await this.initDialog();
                return;
            };
            /*---
            homo彩蛋被删去力(悲),存下图片罢!
            imageUrl: 'https://pic4.zhimg.com/80/v2-1b97a088e156c015108dec663bba8b04.jpg',
            imageUrl: 'https://lh1.hetaousercontent.com/img/7d4c1c0b4adb0e95.jpg',
            */
        },
    };

    //百度网盘
    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", {BDUSS: cookies[0].value});
                    }
                });
            } catch (e) {
            }
        },

        getBDUSS() {
            let baiduyunPlugin_BDUSS = base.getStorage('baiduyunPlugin_BDUSS') ? base.getStorage('baiduyunPlugin_BDUSS') : '{"baiduyunPlugin_BDUSS":""}';
            return baiduyunPlugin_BDUSS.BDUSS || '';
        },

        convertLinkToAria(link, filename, ua) {
            let BDUSS = this.getBDUSS();
            if (!!BDUSS) {
                filename = base.fixFilename(filename);
                return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "User-Agent: ${ua}" --header "Cookie: BDUSS=${BDUSS}"`);
            }
            return {
                link: pan.assistant,
                text: pan.init[5]
            };
        },

        convertLinkToBC(link, filename, ua) {
            let BDUSS = this.getBDUSS();
            if (!!BDUSS) {
                let cookie = `BDUSS=${BDUSS}`;
                let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(cookie)}&user_agent=${encodeURIComponent(ua)}ZZ`;
                return encodeURIComponent(`bc://http/${base.e(bc)}`);
            }
            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 = base.fixFilename(filename);
                return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${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');
                let copy = item.find('.pl-item-copy');
                let howidm = item.find('.pl-progress-how');
                let back = item.find('.pl-progress-back');
                let stop = item.find('.pl-progress-stop');
                return {
                    item, link, progress, tip, copy, stop, howidm, back, 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.g-dropdown-button', (e) => {
                if (e.type === 'mouseleave') {
                    $(e.currentTarget).removeClass('button-open');
                } else {
                    $(e.currentTarget).addClass('button-open');
                    $(e.currentTarget).find('.pl-dropdown-menu').show();
                }
            });
            doc.on('mouseleave', '.pl-button.g-dropdown-button .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 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.copy.show();
                        o.link.text('已成功唤起IDM,请查看IDM下载框!').animate({opacity: '0.5'}, "slow").show();
                        clearInterval(ins[index]);
                        setTimeout(
                            function (){
                                o.link.text('重新下载').animate({opacity: '1'}, "slow");
                            },2000
                        )
                        idm[index] = false;
                    } else {
                        o.link.hide();
                        o.tip.hide();
                        o.stop.show();
                        o.copy.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.howidm.hide();
                            $text.text('下载完成,正在弹出浏览器下载框!');
                            o.back.show()
                            setTimeout(
                                function (){
                                    o.link.text('重新下载').animate({opacity: '1'}, "slow");
                                },3000
                            )
                        }
                    }
                }, 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.item.find('.pl-progress-inner-text').text('正在取消...');
                    o.item.find('.pl-progress-inner').css('width', 100 + '%');
                    setTimeout(function(){
                        o.tip.hide();
                        o.back.hide();
                        o.link.show(0);
                        o.copy.show();
                        o.progress.hide();
                        o.stop.hide();
                    },1050)
                }
            });
            doc.on('click', '.listener-back', async (e) => {
                let o = _factory(e);
                o.progress.hide();
                o.tip.hide();
                o.link.show();
                o.copy.show();
                o.stop.hide();
                o.back.hide();
            });
            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");
                    setTimeout(
                        function (){
                            $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                        },2000
                    )
                }
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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() {
            waitForKeyElements(".wp-s-header__vip-btn-tip", function () {
                let vip1 = document.getElementsByClassName("wp-s-header__vip-btn-tip")[0];
                vip1.remove();
            });
            waitForKeyElements(".app-user-vip-center-tip", function () {
                let vip2 = document.getElementsByClassName("app-user-vip-center-tip")[0];
                vip2.remove();
            });
            waitForKeyElements(".web-header-text-s-45", function () {
                let vip3 = document.getElementById("web-header-text-s-45");
                vip3.remove();
            });
            waitForKeyElements(".wp-s-header__vip-btn", function () {
                let vip4 = document.getElementsByClassName("wp-s-header__vip-btn")[0];
                vip4.innerText = "会员中心";
            });
            waitForKeyElements(".KQcHyA", function () {
                let vip5 = document.getElementsByClassName("KQcHyA")[0];
                vip5.innerText = "会员中心";
            });
            waitForKeyElements(".gOIbzPb", function () {
                let vip6 = document.getElementsByClassName("gOIbzPb")[0];
                vip6.remove();
            });
            waitForKeyElements(".app-user-vip-center-box", function () {
                let vip7 = document.getElementsByClassName("app-user-vip-center-box vip-center-type-2")[0];
                vip7.remove();
            });
            waitForKeyElements(".u-popover", function () {
                setInterval(function(){
                    let vip8 = document.getElementsByClassName("wp-s-header-user__vip-center")[0];
                    let arrow = document.getElementsByClassName("popper__arrow")[0];
                    if(vip8){
                        vip8.remove();
                    }
                    if(arrow){
                        arrow.remove();
                    };
                },10)
            });
            waitForKeyElements(".wp-s-header-user__create-team-title", function () {
                let ad1 = document.getElementsByClassName("wp-s-header-user__create-team-title")[0];
                ad1.remove();
            });
            waitForKeyElements(".wp-side-options g-clearfix", function () {
                let ad2 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
                ad2.remove();
            });
            waitForKeyElements(".web-header-ad-item", function () {
                let ad3 = document.getElementsByClassName("web-header-ad-item wp-s-header__right-item")[0];
                ad3.remove();
            });
            waitForKeyElements(".newIcon", function () {
                let newicon1 = document.getElementsByClassName("newIcon")[0];
                newicon1.remove();
            });
            waitForKeyElements(".u-badge__content", function () {
                let newicon2 = document.getElementsByClassName("u-badge__content is-dot")[0];
                if(newicon2) {
                    newicon2.remove();
                }
            });
            waitForKeyElements(".wp-side-options-btn", function () {
                let qiye1 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
                qiye1.remove();
            });
            waitForKeyElements(".app-download", function () {
                let app1 = document.getElementsByClassName("app-download")[0];
                app1.remove();
            });
            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="width: 60px;">下载助手</span></span></div><div class="menu" style="width:auto;z-index:41;border-color:${color}"><div class="g-button-menu pl-button-mode" data-mode="api" style="color:${color};">API下载</div><div class="g-button-menu pl-button-mode" data-mode="aria" style="color:${color};">Aria下载</div><div class="g-button-menu pl-button-mode" data-mode="rpc" style="color:${color};">RPC下载</div><div class="g-button-menu pl-button-mode" data-mode="curl" style="color:${color};">cURL下载</div><div class="g-button-menu pl-button-mode" data-mode="bc" style="color:${color};">BC下载</div><div class="g-button-menu pl-button-mode listener-open-setting" style="color:${color};">助手设置</div><div class="g-button-menu pl-button-mode listener-open-updatelog" style="color:${color};">更新日志</div></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-dropdown-menu"><li class="pl-button-mode sub cursor-p" data-mode="api">API下载</li><li class="pl-button-mode sub cursor-p" data-mode="aria">Aria下载</li><li class="pl-button-mode sub cursor-p" data-mode="rpc">RPC下载</li><li class="pl-button-mode sub cursor-p" data-mode="curl">cURL下载</li><li class="pl-button-mode sub cursor-p" data-mode="bc">BC下载</li><li class="pl-button-mode sub cursor-p listener-open-setting"">助手设置</li><li class="pl-button-mode sub cursor-p listener-open-updatelog">更新日志</li></ul></div>`);
            }
            if (pt === 'share') $toolWrap = $(pan.btn.share);
            $toolWrap.prepend($button);
            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="width: 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 getToken() {
            let res = await base.getFinalUrl(pan.pcs[3]);
            if (res.indexOf('access_token') === -1) {
                let html = await base.get(pan.pcs[3], {}, 'text');
                let bdstoken = html.match(/name="bdstoken"\s+value="([^"]+)"/)?.[1];
                let client_id = html.match(/name="client_id"\s+value="([^"]+)"/)?.[1];
                let data = {
                    grant_permissions_arr: 'netdisk',
                    bdstoken: bdstoken,
                    client_id: client_id,
                    response_type: "token",
                    display: "page",
                    grant_permissions: "basic,netdisk"
                }
                await base.post(pan.pcs[3], base.stringify(data), {
                    'Content-Type': 'application/x-www-form-urlencoded',
                })
                let res2 = await base.getFinalUrl(pan.pcs[3]);
                let accessToken = res2.match(/access_token=([^&]+)/)?.[1];
                accessToken && base.setStorage('accessToken', accessToken);
                return accessToken;
            }
            let accessToken = res.match(/access_token=([^&]+)/)?.[1];
            accessToken && base.setStorage('accessToken', accessToken);
            return accessToken;
        },

        async getPCSLink(maxRequestTime = 2) {
            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);
                let accessToken = base.getStorage('accessToken') || await this.getToken();
                url = `${pan.pcs[0]}&fsids=${fidList}&access_token=${accessToken}`;
                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 if (res.errno === 9019) {
                maxRequestTime--;
                await this.getToken();
                if (maxRequestTime > 0) {
                    await this.getPCSLink(maxRequestTime);
                } else {
                    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') {
                    alinkAllText += dlink + '\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-api" href="${dlink}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}<br>下载  ${filename}</a>
                                <!--<a class="pl-item-copy" target="_blank" href="${dlink}" title="点击使用浏览器下载" data-filename="${filename}" data-link="${dlink}">传统下载</a>-->
                                <button class="pl-item-copy pl-btn-primary listener-copy-all" href="${dlink}" title="点击复制链接" data-filename="${filename}" data-link="${dlink}">复制链接</button>
                                <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="width:5%">
                                          <div class="pl-progress-inner-text">正在加载进度...0%</div>
                                        </div>
                                    </div>
                                    <span class="pl-progress-stop listener-stop">取消下载</span>
                                `;
                    if (base.getValue('setting_hide_idm') === 'no') {
                        content+=`<span class="pl-progress-tip" >未发现IDM,使用自带浏览器下载</span>
                                  <span class="pl-progress-back pl-back listener-back" style="display: none">返回</span>
                                  <span class="pl-progress-how listener-how">如何唤起IDM?</span>
                                  `
                    } else {
                        content+=`<span class="pl-progress-tip" style="display: none" >未发现IDM,使用自带浏览器下载</span>
                                  <span class="pl-progress-back pl-back listener-back" style="display: none">返回</span>
                                  <span class="pl-progress-how listener-how" style="display: none">如何唤起IDM?</span>
                                  `
                    };
                    content +=`</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)}<br>复制 ${filename} 下载命令行</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)}<br>复制 ${filename} 下载命令行</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;">将 ${filename} 推送到 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)}<br>复制 ${filename} 下载命令行</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)}<br>复制 ${filename} 下载命令行</a> </div>`;
                    }
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, pan.ua);
                    console.log(alink);
                    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" href="${decodeURIComponent(alink.link)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink.text)}<br>下载 ${filename}</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" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>下载 ${filename}</a> </div>`;
                    }
                }
            });

            content += '</div>';

            if (mode === 'api'){
                content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></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>`;}
            if (mode === 'bc'){
                content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</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('.wp-s-core-pan').__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,
                confirmButtonText: '关闭',
                position: 'top',
                width: '1000px',
                customClass,
            }).then(() => {
                this._resetData();
            });
        },

        async initPanLinker() {
            base.initDefaultConfig();
            base.addPanLinkerStyle();
            pt = this.detectPage();
            if (base.getValue('setting_getuser_info') === 'yes') {
                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 = base.fixFilename(filename);
            return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Referer: https://www.aliyundrive.com/"`);
        },

        convertLinkToBC(link, filename, ua) {
            let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&refer=${encodeURIComponent('https://www.aliyundrive.com/')}ZZ`;
            return encodeURIComponent(`bc://http/${base.e(bc)}`);
        },

        convertLinkToCurl(link, filename, ua) {
            let terminal = base.getValue('setting_terminal_type');
            filename = base.fixFilename(filename);
            return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -e "https://www.aliyundrive.com/"`);
        },

        addPageListener() {
            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 dataset = e.currentTarget.dataset;
                let href = dataset.link;
                let url = await this.getRealLink(dataset.did, dataset.fid);
                if (url) href = url;
                let d = document.createElement("a");
                d.download = e.currentTarget.dataset.filename;
                d.rel = "noopener";
                d.href = href;
                d.dispatchEvent(new MouseEvent("click"));
            });
            doc.on('click', '.listener-link-api-btn', async (e) => {
                base.setClipboard(e.target.dataset.filename);
                $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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});
            });
        },

        async getRealLink(d, f) {
            let authorization = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
            let res = await base.post(pan.pcs[1], {
                drive_id: d,
                file_id: f
            }, {
                authorization,
                "content-type": "application/json;charset=utf-8",
            });
            if (res.url) {
                return res.url;
            }
            return '';
        },

        addButton() {
            waitForKeyElements(".share-list-banner--1E8Jr", function () {
                let tip1 = document.getElementsByClassName("share-list-banner--1E8Jr")[0];
                tip1.style.zIndex = 0;
            });
            waitForKeyElements(".to-app--DrlQQ", function () {
                let tip2 = document.getElementsByClassName("to-app--DrlQQ")[0];
                tip2.remove();
            });
            waitForKeyElements(".btn-mobile-save--2nXdf", function () {
                let tip3 = document.getElementsByClassName("btn-mobile-save--2nXdf")[0];
                tip3.remove();
            });
            if (!pt) return;
            let $toolWrap;
            let $button = $(`<div class="ali-button-big">下载助手<div class="button--3S7z9 ali-button pl-button"><span data-role="icon" data-render-as="svg" class="icon"><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="#FFFFFF"></path><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="#FFFFFF"></path></svg></span><ul class="pl-dropdown-menu"><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><li class="pl-dropdown-menu-item pl-button-mode" data-mode="bc" >BC下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div></div>`);
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.append($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px'});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            base.createDownloadIframe();
            this.addPageListener();
        },

        addInitButton() {
            if (!pt) return;
            let $toolWrap;
            let $button = $(`<div class="ali-button-big">下载助手(未点亮)<div class="button--3S7z9 ali-button pl-button-init"><span data-role="icon" data-render-as="svg" class="icon"><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="#FFFFFF"></path><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="#FFFFFF"></path></svg></span></div>`);
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.append($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px'});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            $button.click(() => base.initDialog());
        },

        async getPCSLink() {
            let reactDomGrid = document.querySelector(pan.dom.grid);
            if (reactDomGrid) {
                let res = await Swal.fire({
                    title: '提示',
                    html: '<div style="display: flex;align-items: center;justify-content: center;">请先切换到&nbsp;&nbsp;<b>列表视图</b>&nbsp;“<svg class="icon" viewBox="0 0 1024 1024" width="20" height="20"><use xlink:href="#PDSDrag"></use></svg>”&nbsp;&nbsp;后获取下载链接!</div>',
                    icon: 'info',
                    confirmButtonText: '点击切换'
                });
                if (res) {
                    document.querySelector(pan.dom.switch).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 = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
                    let xShareToken = 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 fid = v.fileId;
                let did = v.driveId;
                let size = base.sizeFormat(v.size);
                let dlink = v.downloadUrl || v.url;
                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-did="${did}" data-fid="${fid}" 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);
                    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);
                    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>`;
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
                    content += `<div class="pl-item">
                                <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" 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.querySelector(pan.dom.list);
                let reactObj = base.findReact(reactDom, 1);
                let props = reactObj.pendingProps;
                if (props) {
                    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();
            if (base.getValue('setting_getuser_info') === 'yes') {
                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 = base.fixFilename(filename);
            return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
        },

        convertLinkToBC(link, filename, ua) {
            let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
            return encodeURIComponent(`bc://http/${base.e(bc)}`);
        },

        convertLinkToCurl(link, filename, ua) {
            let terminal = base.getValue('setting_terminal_type');
            filename = base.fixFilename(filename);
            return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
        },

        addPageListener() {
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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="top: 26px;"><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><li class="pl-dropdown-menu-item pl-button-mode" data-mode="bc" >BC下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            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);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px'});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            $button.click(() => base.initDialog());
        },

        async getToken() {
            let res = await base.getFinalUrl(pan.pcs[1], {});
            let accessToken = res.match(/accessToken=(\w+)/)?.[1];
            accessToken && base.setStorage('accessToken', accessToken);
            return accessToken;
        },

        async getFileUrlByOnce(item, index, token) {
            try {
                if (item.downloadUrl) return {
                    index,
                    downloadUrl: item.downloadUrl
                };
                let time = Date.now(),
                    fileId = item.fileId,
                    o = "AccessToken=" + token + "&Timestamp=" + time + "&fileId=" + fileId,
                    url = pan.pcs[2] + '?fileId=' + fileId;
                if (item.shareId) {
                    o = "AccessToken=" + token + "&Timestamp=" + time + "&dt=1&fileId=" + fileId + "&shareId=" + item.shareId;
                    url += '&dt=1&shareId=' + item.shareId;
                }
                let sign = md5(o).toString();
                let res = await base.get(url, {
                    "accept": "application/json;charset=UTF-8",
                    "sign-type": 1,
                    "accesstoken": token,
                    "timestamp": time,
                    "signature": sign
                });
                if (res.res_code === 0) {
                    return {
                        index,
                        downloadUrl: res.fileDownloadUrl
                    };
                } else if (res.errorCode === 'InvalidSessionKey') {
                    return {
                        index,
                        downloadUrl: '提示:请先登录网盘!'
                    };
                } else if (res.res_code === 'ShareNotFoundFlatDir') {
                    return {
                        index,
                        downloadUrl: '提示:请先[转存]文件,👉前往[我的网盘]中下载!'
                    };
                } else {
                    return {
                        index,
                        downloadUrl: '获取下载地址失败,请刷新重试!'
                    };
                }
            } catch (e) {
                return {
                    index,
                    downloadUrl: '获取下载地址失败,请刷新重试!'
                };
            }
        },

        async getPCSLink() {
            selectList = this.getSelectedList();
            if (selectList.length === 0) {
                return message.error('提示:请先勾选要下载的文件!');
            }
            if (this.isOnlyFolder()) {
                return message.error('提示:请打开文件夹后勾选文件!');
            }
            let token = base.getStorage('accessToken') || await this.getToken();
            if (!token) {
                return message.error('提示:请先登录网盘!');
            }
            let queue = [];
            selectList.forEach((item, index) => {
                queue.push(this.getFileUrlByOnce(item, index, token));
            });

            const res = await Promise.all(queue);
            res.forEach(val => {
                selectList[val.index].downloadUrl = val.downloadUrl;
            });

            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);
                    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);
                    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>`;
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
                    content += `<div class="pl-item">
                                <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" 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();
            if (base.getValue('setting_getuser_info') === 'yes') {
                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();
            this.getToken();
            base.createTip();
            base.registerMenuCommand();
        }
    };

    //迅雷云盘
    let xunlei = {

        convertLinkToAria(link, filename, ua) {
            filename = base.fixFilename(filename);
            return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
        },

        convertLinkToBC(link, filename, ua) {
            let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
            return encodeURIComponent(`bc://http/${base.e(bc)}`);
        },

        convertLinkToCurl(link, filename, ua) {
            let terminal = base.getValue('setting_terminal_type');
            filename = base.fixFilename(filename);
            return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
        },

        addPageListener() {
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            doc.on('click', '.listener-link-bc-btn', async (e) => {
                let mirror = base.getMirrorList(e.target.dataset.dlink, pan.mirror);
                base.setClipboard(mirror);
                $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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="top: 34px;"><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><li class="pl-dropdown-menu-item pl-button-mode" data-mode="bc" >BC下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px'});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            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);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px'});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            $button.click(() => base.initDialog());
        },

        getToken() {
            let credentials = {}, captcha = {};
            for (let i = 0; i < localStorage.length; i++) {
                if (/^credentials_/.test(localStorage.key(i))) {
                    credentials = base.getStorage(localStorage.key(i));
                    base.setStorage('');
                }
                if (/^captcha_[\w]{16}/.test(localStorage.key(i))) {
                    captcha = base.getStorage(localStorage.key(i));
                }
            }
            let deviceid = /(\w{32})/.exec(base.getStorage('deviceid').split(','))[0];
            let token = {
                credentials,
                captcha,
                deviceid
            };
            return token;
        },

        async getFileUrlByOnce(item, index, token) {
            try {
                if (item.downloadUrl) return {
                    index,
                    downloadUrl: item.downloadUrl
                };
                let res = await base.get(pan.pcs[0] + item.id, {
                    'Authorization': `${token.credentials.token_type} ${token.credentials.access_token}`,
                    'content-type': "application/json",
                    'x-captcha-token': token.captcha.token,
                    'x-device-id': token.deviceid,
                });
                if (res.web_content_link) {
                    return {
                        index,
                        downloadUrl: res.web_content_link
                    };
                } else {
                    return {
                        index,
                        downloadUrl: '获取下载地址失败,请刷新重试!'
                    };
                }
            } catch (e) {
                return message.error('提示:请先登录网盘后刷新页面!');
            }
        },

        async getPCSLink() {
            selectList = this.getSelectedList();
            if (selectList.length === 0) {
                return message.error('提示:请先勾选要下载的文件!');
            }
            if (this.isOnlyFolder()) {
                return message.error('提示:请打开文件夹后勾选文件!');
            }
            if (pt === 'home') {
                let queue = [];
                let token = this.getToken();
                selectList.forEach((item, index) => {
                    queue.push(this.getFileUrlByOnce(item, index, token));
                });
                const res = await Promise.all(queue);
                res.forEach(val => {
                    selectList[val.index].downloadUrl = val.downloadUrl;
                });
            } 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);
                    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);
                    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>`;
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
                    content += `<div class="pl-item">
                                <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a>
                                <div class="pl-item-btn listener-link-bc-btn" data-dlink="${dlink}">复制镜像地址</div>
                                </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();
            if (base.getValue('setting_getuser_info') === 'yes') {
                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 quark = {

        convertLinkToAria(link, filename, ua) {
            filename = base.fixFilename(filename);
            return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Cookie: ${document.cookie}"`);
        },

        convertLinkToBC(link, filename, ua) {
            let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(document.cookie)}ZZ`;
            return encodeURIComponent(`bc://http/${base.e(bc)}`);
        },

        convertLinkToCurl(link, filename, ua) {
            let terminal = base.getValue('setting_terminal_type');
            filename = base.fixFilename(filename);
            return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -b "${document.cookie}"`);
        },

        addPageListener() {
            window.addEventListener('hashchange', async (e) => {
                let home = 'https://pan.quark.cn/list#/', all = 'https://pan.quark.cn/list#/list/all';
                if (e.oldURL === home && e.newURL === all) return;
                await base.sleep(150);
                if ($('.quark-button').length > 0) return;
                pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
            });
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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 ($("#quark-button")){
                $("#quark-button").remove();
            };
            if (!pt) return;
            let $toolWrap;
            let $button = $(`<div id="quark-button" class="file-info_r quark-button pl-button"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#FFFFFF" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 2-2z"/><path d="M14 8h1.553c.85 0 1.16.093 1.47.267.311.174.556.43.722.756.166.326.255.65.255 1.54v4.873c0 .892-.089 1.215-.255 1.54-.166.327-.41.583-.722.757-.31.174-.62.267-1.47.267H6.447c-.85 0-1.16-.093-1.47-.267a1.778 1.778 0 01-.722-.756c-.166-.326-.255-.65-.255-1.54v-4.873c0-.892.089-1.215.255-1.54.166-.327.41-.583.722-.757.31-.174.62-.267 1.47-.267H11"/><path stroke-linecap="round" stroke-linejoin="round" d="M11 3v10"/></g></svg>下载助手<ul class="pl-dropdown-menu"><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><li class="pl-dropdown-menu-item pl-button-mode" data-mode="bc" >BC下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
            $button.css({"margin-right":"10px","background-color":color});
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({"margin-right":"10px","background-color":color});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
        },

        addInitButton() {
            $("#pl-button-init").remove();
            if (!pt) return;
            let $toolWrap;
            let $button = $(`<div id="quark-button" class="file-info_r quark-button pl-button-init"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#FFFFFF" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 2-2z"/><path d="M14 8h1.553c.85 0 1.16.093 1.47.267.311.174.556.43.722.756.166.326.255.65.255 1.54v4.873c0 .892-.089 1.215-.255 1.54-.166.327-.41.583-.722.757-.31.174-.62.267-1.47.267H6.447c-.85 0-1.16-.093-1.47-.267a1.778 1.778 0 01-.722-.756c-.166-.326-.255-.65-.255-1.54v-4.873c0-.892.089-1.215.255-1.54.166-.327.41-.583.722-.757.31-.174.62-.267 1.47-.267H11"/><path stroke-linecap="round" stroke-linejoin="round" d="M11 3v10"/></g></svg>下载助手(未点亮)</div>`);
            $button.css({"margin-right":"10px","background-color":color});
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.css({'margin-right': '10px','width': '160px',"background-color":color});
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            $button.click(() => base.initDialog());
        },

        async getPCSLink() {
            selectList = this.getSelectedList();
            if (selectList.length === 0) {
                return message.error('提示:请先勾选要下载的文件!');
            }
            if (this.isOnlyFolder()) {
                return message.error('提示:请打开文件夹后勾选文件!');
            }
            let fids = [];
            selectList.forEach(val => {
                fids.push(val.fid);
            });
            if (pt === 'home') {
                let res = await base.post(pan.pcs[0], {
                    "fids": fids
                }, {"content-type": "application/json;charset=utf-8", "user-agent": pan.ua});
                if (res.code === 31001) {
                    return message.error('提示:请先登录网盘!');
                }
                if (res.code !== 0) {
                    return message.error('提示:获取链接失败!');
                }
                let html = this.generateDom(res.data);
                this.showMainDialog(pan[mode][0], html, pan[mode][1]);
            } else {
                message.error('提示:请保存到自己网盘后去网盘主页下载!');
                await base.sleep(1000);
                document.querySelector('.file-info_r').click();
                return;
            }
        },

        generateDom(list) {
            let content = '<div class="pl-main">';
            let alinkAllText = '';
            list.forEach((v, i) => {
                if (v.file === false) return;
                let filename = v.file_name;
                let fid = v.fid;
                let size = base.sizeFormat(v.size);
                let dlink = v.download_url;
                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-fid="${fid}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
                                </div>`;
                }
                if (mode === 'aria') {
                    let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
                    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);
                    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>`;
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
                    content += `<div class="pl-item">
                                <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" 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: [`Cookie: ${document.cookie}`]
                }]
            };
            try {
                let res = await base.post(url, rpcData, {"Cookie": document.cookie}, '');
                if (res.result) return 'success';
                return 'fail';
            } catch (e) {
                return 'fail';
            }
        },

        getSelectedList() {
            try {
                let selectedList = [];
                let reactDom = document.getElementsByClassName('file-list')[0];
                let reactObj = base.findReact(reactDom);
                let props = reactObj.props;
                if (props) {
                    let fileList = props.list || [];
                    let selectedKeys = props.selectedRowKeys || [];
                    fileList.forEach((val) => {
                        if (selectedKeys.includes(val.fid)) {
                            selectedList.push(val);
                        }
                    });
                }
                return selectedList;
            } catch (e) {
                return [];
            }
        },

        detectPage() {
            let path = location.pathname;
            if (/^\/(list)/.test(path)) return 'home';
            if (/^\/(s|share)\//.test(path)) return 'share';
            return '';
        },

        isOnlyFolder() {
            for (let i = 0; i < selectList.length; i++) {
                if (selectList[i].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();
            if (base.getValue('setting_getuser_info') === 'yes') {
                let res = await base.post
                (`https://api.youxiaohou.com/config/quark?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();
            this.addPageListener();
            base.createTip();
            base.createDownloadIframe();
            base.registerMenuCommand();
        }
    };

    //中国移动云盘/和彩云
    let yidong = {

        convertLinkToAria(link, filename, ua) {
            filename = base.fixFilename(filename);
            return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
        },

        convertLinkToBC(link, filename, ua) {
            let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
            return encodeURIComponent(`bc://http/${base.e(bc)}`);
        },

        convertLinkToCurl(link, filename, ua) {
            let terminal = base.getValue('setting_terminal_type');
            filename = base.fixFilename(filename);
            return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
        },

        addPageListener() {
            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");
                setTimeout(
                    function (){
                        $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
                    },2000
                )
            });
            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-open-updatelog', () => {
                base.showUpdateLog();
            });
            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="yidong-button pl-button">下载助手<ul class="pl-dropdown-menu" style="top: 36px;"><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><li class="pl-dropdown-menu-item pl-button-mode" data-mode="bc" >BC下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</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);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.removeClass('yidong-button').addClass('yidong-share-button');
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            base.createDownloadIframe();
            this.addPageListener();
        },

        addInitButton() {
            if (!pt) return;
            let $toolWrap;
            let $button = $(`<div class="yidong-button pl-button-init">下载助手(未点亮)</div>`);
            if (pt === 'home') {
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.home);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            if (pt === 'share') {
                $button.removeClass('yidong-button').addClass('yidong-share-button');
                let ins = setInterval(() => {
                    $toolWrap = $(pan.btn.share);
                    if ($toolWrap.length > 0) {
                        $toolWrap.prepend($button);
                        clearInterval(ins);
                    }
                }, 50);
            }
            $button.click(() => base.initDialog());
        },

        getRandomString(len) {
            len = len || 16;
            let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
            let maxPos = $chars.length;
            let pwd = '';
            for (let i = 0; i < len; i++) {
                pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
            }
            return pwd;
        },

        utob(str) {
            const u = String.fromCharCode;
            return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g, (t) => {
                if (t.length < 2) {
                    let e = t.charCodeAt(0);
                    return e < 128 ? t : e < 2048 ? u(192 | e >>> 6) + u(128 | 63 & e) : u(224 | e >>> 12 & 15) + u(128 | e >>> 6 & 63) + u(128 | 63 & e);
                }
                e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
                return u(240 | e >>> 18 & 7) + u(128 | e >>> 12 & 63) + u(128 | e >>> 6 & 63) + u(128 | 63 & e);
            });
        },

        getSign(e, t, a, n) {
            let r = "",
                i = "";
            if (t) {
                let s = Object.assign({}, t);
                i = JSON.stringify(s),
                    i = i.replace(/\s*/g, ""),
                    i = encodeURIComponent(i);
                let c = i.split(""),
                    u = c.sort();
                i = u.join("");
            }
            let A = md5(base.e(this.utob(i)));
            let l = md5(a + ":" + n);
            return md5(A + l).toUpperCase();
        },

        async getFileUrlByOnce(item, index) {
            try {
                if (item.downloadUrl) return {
                    index,
                    downloadUrl: item.downloadUrl
                };

                if (this.detectPage() === 'home') {
                    let body = {
                        "appName": "",
                        "contentID": item.contentID,
                        "commonAccountInfo": {"account": item.owner, "accountType": 1}
                    };
                    let time = new Date(+new Date() + 8 * 3600 * 1000).toJSON().substr(0, 19).replace('T', ' ');
                    let key = this.getRandomString(16);
                    let sign = this.getSign(undefined, body, time, key);

                    let res = await base.post(pan.pcs[0], body, {
                        'x-huawei-channelSrc': '10000034',
                        'x-inner-ntwk': '2',
                        'mcloud-channel': '1000101',
                        'mcloud-client': '10701',
                        'mcloud-sign': time + "," + key + "," + sign,
                        'content-type': "application/json;charset=UTF-8",
                        'caller': 'web',
                        'CMS-DEVICE': 'default',
                        'x-DeviceInfo': '||9|85.0.4183.83|chrome|85.0.4183.83|||windows 10||zh-CN|||',
                        'x-SvcType': '1',
                    });
                    if (res.success) {
                        return {
                            index,
                            downloadUrl: res.data.downloadURL
                        };
                    } else {
                        return {
                            index,
                            downloadUrl: '获取下载地址失败,请刷新重试!'
                        };
                    }
                }
                if (this.detectPage() === 'share') {
                    let vueDom = document.querySelector(".home-page").__vue__;

                    let res = await base.post(pan.pcs[1], `linkId=${vueDom.linkID}&contentIds=${encodeURIComponent(vueDom.currentPath.id + '/' + item.coID)}&catalogIds=`, {
                        'Content-Type': 'application/x-www-form-urlencoded',
                    });
                    if (res.code === 0) {
                        return {
                            index,
                            downloadUrl: res.data.redrUrl
                        };
                    } else {
                        return {
                            index,
                            downloadUrl: '获取下载地址失败,请刷新重试!'
                        };
                    }
                }
            } catch (e) {
                return {
                    index,
                    downloadUrl: '获取下载地址失败,请刷新重试!'
                };
            }
        },

        async getPCSLink() {
            selectList = this.getSelectedList();
            if (selectList.length === 0) {
                return message.error('提示:请先勾选要下载的文件!');
            }
            if (this.isOnlyFolder()) {
                return message.error('提示:请打开文件夹后勾选文件!');
            }

            let queue = [];
            selectList.forEach((item, index) => {
                queue.push(this.getFileUrlByOnce(item, index));
            });

            const res = await Promise.all(queue);
            res.forEach(val => {
                selectList[val.index].downloadUrl = val.downloadUrl;
            });

            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.dirEtag || v.caName) return;
                let filename = v.contentName || v.coName;
                let size = base.sizeFormat(v.contentSize || v.coSize);
                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);
                    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);
                    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>`;
                }
                if (mode === 'bc') {
                    let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
                    content += `<div class="pl-item">
                                <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
                                <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" 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(".main_file_list").__vue__.selectList.map(val => val.item);
            } catch (e) {
                let vueDom = document.querySelector(".home-page").__vue__;
                let fileList = vueDom._computedWatchers.fileList.value;
                let dirList = vueDom._computedWatchers.dirList.value;
                let selectedFileIndex = vueDom.selectedFile;
                let selectedDirIndex = vueDom.selectedDir;
                let selectFileList = fileList.filter((v, i) => {
                    return selectedFileIndex.includes(i);
                });
                let selectDirList = dirList.filter((v, i) => {
                    return selectedDirIndex.includes(i);
                });
                return [...selectFileList, ...selectDirList];
            }
        },

        detectPage() {
            let hostname = location.hostname;
            if (/^yun/.test(hostname)) return 'home';
            if (/^caiyun/.test(hostname)) return 'share';
            return '';
        },

        isOnlyFolder() {
            for (let i = 0; i < selectList.length; i++) {
                if (selectList[i].fileEtag || selectList[i].coName) 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/yidong?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 youxiaohou ={
        async initPanLinker() {
            base.initDefaultConfig();
            base.addPanLinkerStyle();
            let res = await base.post
            (`https://api.youxiaohou.com/config/?ver=${version}&a=${author}`, {}, {}, 'text');
            pan = JSON.parse(base.d(res));
            base.createTip();
            base.registerPanMenuCommand();

            let $button1 = `<div class="nav-item" style="text-align: center;"><a class="listener-open-updatelog">(改)下载助手<br>更新日志</a></div>`
            doc.on('click', '.listener-open-updatelog', () => {
                base.showUpdateLog();
            });
            document.getElementsByClassName("nav-links can-hide")[0].innerHTML += $button1

            let $button2 = `<div class="nav-item" style="text-align: center;"><a class="listener-open-info">(改)下载助手<br>暗号查看</a></div>`
            doc.on('click', '.listener-open-info', () => {
                base.showPanInfo();
            });
            document.getElementsByClassName("nav-links can-hide")[0].innerHTML += $button2
        }
    }

    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();
            }
            if (/pan.quark.cn/.test(location.host)) {
                quark.initPanLinker();
            }
            if (/(yun|caiyun).139.com/.test(location.host)) {
                yidong.initPanLinker();
            }
            if (/www.youxiaohou.com/.test(location.host)) {
                youxiaohou.initPanLinker();
            }
        }
    };
    main.init();
})();