NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name 网盘直链下载助手 // @namespace https://github.com/syhyz1990/baiduyun // @version 5.9.0 // @author YouXiaoHou // @icon https://www.youxiaohou.com/48x48.png // @icon64 https://www.youxiaohou.com/64x64.png // @description 👆👆👆👆👆👆👆可以获取网盘文件真实下载地址。现已支持 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 ✅夸克网盘 五大网盘,可使用 IDM,Xdown,Aria2,Curl,比特彗星等工具🚀🚀🚀下载,完美适配 Chrome,Edge,FireFox,360,QQ 等 18 种浏览器,可在无法安装客户端的环境下使用,助手免费开源。😎 // @license AGPL-3.0-or-later // @homepage https://www.youxiaohou.com/install.html // @supportURL https://github.com/syhyz1990/baiduyun // @updateURL https://www.youxiaohou.com/panlinker.user.js // @downloadURL https://www.youxiaohou.com/panlinker.user.js // @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/* // @require https://unpkg.com/jquery@3.6.0/dist/jquery.min.js // @require https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.all.min.js // @require https://unpkg.com/js-md5@0.7.3/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 // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_openInTab // @grant GM_registerMenuCommand // ==/UserScript== (function () { 'use strict'; let pt = '', selectList = [], params = {}, mode = '', width = 800, pan = {}, color = '', doc = $(document), progress = {}, request = {}, ins = {}, idm = {}; const version = '5.9.0'; const author = 'OpenUserJS'; 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' }; const terminalType = { wc: "Windows CMD", wp: "Windows PowerShell", lt: "Linux 终端", ls: "Linux Shell", mt: "MacOS 终端", }; let toast = Swal.mixin({ toast: true, position: 'top', showConfirmButton: false, timer: 3500, timerProgressBar: false, didOpen: (toast) => { toast.addEventListener('mouseenter', Swal.stopTimer); toast.addEventListener('mouseleave', Swal.resumeTimer); } }); const message = { success: (text) => { toast.fire({title: text, icon: 'success'}); }, error: (text) => { toast.fire({title: text, icon: 'error'}); }, warning: (text) => { toast.fire({title: text, icon: 'warning'}); }, info: (text) => { toast.fire({title: text, icon: 'info'}); }, question: (text) => { toast.fire({title: text, icon: 'question'}); } }; let base = { 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()); }, 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); }, }); }); }, 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); }, 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: '#09AAFF' }, { name: 'setting_init_code', value: '' }]; value.forEach((v) => { base.getValue(v.name) === undefined && base.setValue(v.name, v.value); }); }, showSetting() { let dom = '', btn = '', colorList = ['#09AAFF', '#cc3235', '#526efa', '#518c17', '#ed944b', '#f969a5', '#bca280']; dom += `<label class="pl-setting-label"><div class="pl-label">RPC主机</div><input type="text" placeholder="主机地址,需带上http(s)://" class="pl-input listener-domain" value="${base.getValue('setting_rpc_domain')}"></label>`; dom += `<label class="pl-setting-label"><div class="pl-label">RPC端口</div><input type="text" placeholder="端口号,例如:Motrix为16800" class="pl-input listener-port" value="${base.getValue('setting_rpc_port')}"></label>`; dom += `<label class="pl-setting-label"><div class="pl-label">RPC路径</div><input type="text" placeholder="路径,默认为/jsonrpc" class="pl-input listener-path" value="${base.getValue('setting_rpc_path')}"></label>`; dom += `<label class="pl-setting-label"><div class="pl-label">RPC密钥</div><input type="text" placeholder="无密钥无需填写" class="pl-input listener-token" value="${base.getValue('setting_rpc_token')}"></label>`; dom += `<label class="pl-setting-label"><div class="pl-label">保存路径</div><input type="text" placeholder="文件下载后保存路径,例如:D:" class="pl-input listener-dir" value="${base.getValue('setting_rpc_dir')}"></label>`; colorList.forEach((v) => { btn += `<div data-color="${v}" style="background: ${v};border: 1px solid ${v}" class="pl-color-box listener-color ${v === base.getValue('setting_theme_color') ? 'checked' : ''}"></div>`; }); dom += `<label class="pl-setting-label"><div class="pl-label">终端类型</div><select class="pl-input listener-terminal">`; Object.keys(terminalType).forEach(k => { dom += `<option value="${k}" ${base.getValue('setting_terminal_type') === k ? 'selected' : ''}>${terminalType[k]}</option>`; }); dom += `</select></label>`; dom += `<label class="pl-setting-label"><div class="pl-label">主题颜色</div> <div class="pl-color">${btn}<div></label>`; dom = '<div>' + dom + '</div>'; Swal.fire({ title: '助手配置', html: dom, icon: 'info', showCloseButton: true, showConfirmButton: false, footer: pan.footer, }).then(() => { message.success('设置成功!'); history.go(0); }); doc.on('click', '.listener-color', async (e) => { base.setValue('setting_theme_color', e.target.dataset.color); message.success('设置成功!'); history.go(0); }); doc.on('input', '.listener-domain', async (e) => { base.setValue('setting_rpc_domain', e.target.value); }); doc.on('input', '.listener-port', async (e) => { base.setValue('setting_rpc_port', e.target.value); }); doc.on('input', '.listener-path', async (e) => { base.setValue('setting_rpc_path', e.target.value); }); doc.on('input', '.listener-token', async (e) => { base.setValue('setting_rpc_token', e.target.value); }); doc.on('input', '.listener-dir', async (e) => { base.setValue('setting_rpc_dir', e.target.value); }); doc.on('change', '.listener-terminal', async (e) => { base.setValue('setting_terminal_type', e.target.value); }); }, registerMenuCommand() { GM_registerMenuCommand('⚙️ 设置', () => { this.showSetting(); }); }, createTip() { $('body').append('<div class="pl-tooltip"></div>'); doc.on('mouseenter mouseleave', '.listener-tip', (e) => { if (e.type === 'mouseenter') { let filename = e.currentTarget.innerText; let size = e.currentTarget.dataset.size; let tip = `${filename}<span style="margin-left: 10px;color: #f56c6c;">${size}</span>`; $(e.currentTarget).css({opacity: '0.5'}); $('.pl-tooltip').html(tip).css({ 'left': e.pageX + 10 + 'px', 'top': e.pageY - e.currentTarget.offsetTop > 14 ? e.pageY + 'px' : e.pageY + 20 + 'px' }).show(); } else { $(e.currentTarget).css({opacity: '1'}); $('.pl-tooltip').hide(0); } }); }, createLoading() { return $('<div class="pl-loading"><div class="pl-loading-box"><div><div></div><div></div></div></div></div>'); }, createDownloadIframe() { let $div = $('<div style="padding:0;margin:0;display:block"></div>'); let $iframe = $('<iframe src="javascript:;" id="downloadIframe" style="display:none"></iframe>'); $div.append($iframe); $('body').append($div); }, 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; } .pl-popup { font-size: 12px !important; } .pl-popup a { color: ${color} !important; } .pl-header { padding: 0!important;align-items: flex-start!important; border-bottom: 1px solid #eee!important; margin: 0 0 10px!important; padding: 0 0 5px!important; } .pl-title { font-size: 16px!important; line-height: 1!important;white-space: nowrap!important; text-overflow: ellipsis!important;} .pl-content { padding: 0 !important; font-size: 12px!important; } .pl-main { max-height: 400px;overflow-y:scroll; } .pl-footer {font-size: 12px!important;justify-content: flex-start!important; margin: 10px 0 0!important; padding: 5px 0 0!important; color: #f56c6c!important; } .pl-item { display: flex; align-items: center; line-height: 22px; } .pl-item-name { flex: 0 0 150px; text-align: left;margin-right: 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor:default; } .pl-item-link { flex: 1; overflow: hidden; text-align: left; white-space: nowrap; text-overflow: ellipsis;cursor:pointer } .pl-item-btn { background: ${color}; padding: 4px 5px; border-radius: 3px; line-height: 1; cursor: pointer; color: #fff; } .pl-item-tip { display: flex; justify-content: space-between;flex: 1; } .pl-back { width: 70px; background: #ddd; border-radius: 3px; cursor:pointer; margin:1px 0; } .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: #ebeef5;overflow: hidden;position: relative;vertical-align: middle;} .pl-progress-inner{ position: absolute;left: 0;top: 0;background-color: #409eff;text-align: right;border-radius: 100px;line-height: 1;white-space: nowrap;transition: width .6s ease;} .pl-progress-inner-text { display: inline-block;vertical-align: middle;color: #d1d1d1;font-size: 12px;margin: 0 5px;height: 15px} .pl-progress-tip{ flex:1;text-align:right} .pl-progress-how{ flex: 0 0 90px; background: #ddd; border-radius: 3px; margin-left: 10px; cursor: pointer; text-align: center;} .pl-progress-stop{ flex: 0 0 50px; padding: 0 10px; background: #cc3235; color: #fff; border-radius: 3px; cursor: pointer;margin-left:10px;height:20px} .pl-progress-inner-text:after { display: inline-block;content: "";height: 100%;vertical-align: middle;} .pl-btn-primary { background: ${color}; border: 0; border-radius: 4px; color: #ffffff; cursor: pointer; font-size: 12px; outline: none; display:flex; align-items: center; justify-content: center; margin: 2px 0; padding: 6px 0;transition: 0.3s opacity; } .pl-btn-primary:hover { opacity: 0.9;transition: 0.3s opacity; } .pl-btn-success { background: #55af28; animation: easeOpacity 1.2s 2; animation-fill-mode:forwards } .pl-btn-info { background: #606266; } .pl-btn-warning { background: #da9328; } .pl-btn-warning { background: #da9328; } .pl-btn-danger { background: #cc3235; } .ali-button {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;border-radius: 5px;box-shadow: 0 0 0 0 transparent;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: rgb(99 125 255);margin-left: 20px;padding: 1px 12px;position: relative; cursor:pointer; height: 32px;} .ali-button:hover {background: rgb(122, 144, 255)} .tianyi-button {margin-right: 20px; padding: 4px 12px; border-radius: 4px; color: #fff; font-size: 12px; border: 1px solid #0073e3; background: #2b89ea; cursor: pointer; position: relative;} .tianyi-button:hover {border-color: #1874d3; background: #3699ff;} .xunlei-button {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;border-radius: 5px;box-shadow: 0 0 0 0 transparent;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: #3f85ff;margin-left: 12px;padding: 0px 12px;position: relative; cursor:pointer; height: 36px;} .xunlei-button:hover {background: #619bff} .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: #333; background: #fff; margin-right: 10px; padding: 0px 14px; position: relative; cursor: pointer; height: 36px;} .quark-button:hover { background:#f6f6f6 } .pl-dropdown-menu {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; } .pl-dropdown-menu-item:hover { background-color: rgba(132,133,141,0.08);} .pl-button .pl-dropdown-menu { display: none; } .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; margin-right: -10px;} .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); }, async initDialog() { let result = await Swal.fire({ title: pan.init[0], html: `<div><img style="width: 250px;margin-bottom: 10px;" src="${pan.img}" alt="${pan.img}"><input class="swal2-input" id="init" type="text" placeholder="${pan.init[1]}"></div>`, allowOutsideClick: false, showCloseButton: true, confirmButtonText: '确定' }); if (result.isDismissed && result.dismiss === 'close') return; if (pan.num === $('#init').val()) { base.setValue('setting_init_code', pan.num); message.success(pan.init[2]); setTimeout(() => { history.go(0); }, 1500); } else { await Swal.fire({ title: pan.init[3], text: pan.init[4], confirmButtonText: '重新输入', imageUrl: pan.img, }); await this.initDialog(); } }, }; let baidu = { _getExtra() { let seKey = decodeURIComponent(base.getCookie('BDCLND')); return '{' + '"sekey":"' + seKey + '"' + "}"; }, _getSurl() { let reg = /(?<=s\/|surl=)([a-zA-Z0-9_-]+)/g; if (reg.test(location.href)) { return location.href.match(reg)[0]; } return ''; }, _getFidList() { let fidlist = []; selectList.forEach(v => { if (+v.isdir === 1) return; fidlist.push(v.fs_id); }); return '[' + fidlist + ']'; }, _resetData() { progress = {}; $.each(request, (key) => { (request[key]).abort(); }); $.each(ins, (key) => { clearInterval(ins[key]); }); idm = {}; ins = {}; request = {}; }, setBDUSS() { try { GM_cookie && GM_cookie('list', {name: 'BDUSS'}, (cookies, error) => { if (!error) { base.setStorage("baiduyunPlugin_BDUSS", {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 = filename.replace(' ', '_'); 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 = filename.replace(' ', '_'); return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}" -A "${ua}" -b "BDUSS=${BDUSS}"`); } return { link: pan.assistant, text: pan.init[5] }; }, addPageListener() { function _factory(e) { let target = $(e.target); let item = target.parents('.pl-item'); let link = item.find('.pl-item-link'); let progress = item.find('.pl-item-progress'); let tip = item.find('.pl-item-tip'); return { item, link, progress, tip, target, }; } function _reset(i) { ins[i] && clearInterval(ins[i]); request[i] && request[i].abort(); progress[i] = 0; idm[i] = false; } doc.on('mouseenter mouseleave click', '.pl-button.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.link.text('已成功唤起IDM,请查看IDM下载框!').animate({opacity: '0.5'}, "slow").show(); clearInterval(ins[index]); idm[index] = false; } else { o.link.hide(); o.tip.hide(); o.progress.show(); $width.css('width', prog + '%'); $text.text(prog + '%'); if (prog === 100) { clearInterval(ins[index]); progress[index] = 0; o.item.find('.pl-progress-stop').hide(); o.item.find('.pl-progress-tip').html('下载完成,正在弹出浏览器下载框!'); } } }, 500); }); doc.on('click', '.listener-retry', async (e) => { let o = _factory(e); o.tip.hide(); o.link.show(); }); doc.on('click', '.listener-how', async (e) => { let o = _factory(e); let index = o.link[0].dataset.index; if (request[index]) { request[index].abort(); clearInterval(ins[index]); o.progress.hide(); o.tip.show(); } }); doc.on('click', '.listener-stop', async (e) => { let o = _factory(e); let index = o.link[0].dataset.index; if (request[index]) { request[index].abort(); clearInterval(ins[index]); o.tip.hide(); o.progress.hide(); o.link.show(0); } }); doc.on('click', '.listener-back', async (e) => { let o = _factory(e); o.tip.hide(); o.link.show(); }); doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => { e.preventDefault(); if (!e.target.dataset.link) { $(e.target).removeClass('listener-copy-all').addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`); } else { base.setClipboard(decodeURIComponent(e.target.dataset.link)); $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-link-rpc', async (e) => { let target = $(e.currentTarget); target.find('.icon').remove(); target.find('.pl-loading').remove(); target.prepend(base.createLoading()); let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link); if (res === 'success') { $('.listener-rpc-task').show(); target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow"); } else if (res === 'assistant') { target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`); } else { target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-send-rpc', (e) => { $('.listener-link-rpc').click(); $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-open-setting', () => { base.showSetting(); }); doc.on('click', '.listener-rpc-task', () => { let rpc = JSON.stringify({ domain: base.getValue('setting_rpc_domain'), port: base.getValue('setting_rpc_port'), }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`; GM_openInTab(url, {active: true}); }); document.documentElement.addEventListener('mouseup', (e) => { if (e.target.nodeName === 'A' && ~e.target.className.indexOf('pl-a')) { e.stopPropagation(); } }, true); }, addButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="g-dropdown-button pointer pl-button"><div style="color:#fff;background: ${color};border-color:${color}" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download"></em><span class="text" style="width: 60px;">下载助手</span></span></div><div class="menu" style="width:auto;z-index:41;border-color:${color}"><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="api">API下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="aria">Aria下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="rpc">RPC下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="curl">cURL下载</div><div style="color:${color}" class="g-button-menu pl-button-mode" data-mode="bc">BC下载</div>${pan.code == 200 && version < pan.version ? pan.new : ''}</div></div>`); if (pt === 'home') $toolWrap = $(pan.btn.home); if (pt === 'main') { $toolWrap = $(pan.btn.main); $button = $(`<div class="pl-button" style="position: relative; display: inline-block; margin-right: 8px;"><button class="u-button u-button--primary u-button--small is-round is-has-icon" style="background: ${color};border-color: ${color};font-size: 14px; padding: 8px 16px; border: none;"><i class="u-icon u-icon-download"></i><span>下载助手</span></button><ul class="dropdown-list nd-common-float-menu pl-dropdown-menu"><li class="sub cursor-p pl-button-mode" data-mode="api">API下载</li><li class="sub cursor-p pl-button-mode" data-mode="aria">Aria下载</li><li class="sub cursor-p pl-button-mode" data-mode="rpc">RPC下载</li><li class="sub cursor-p pl-button-mode" data-mode="curl">cURL下载</li><li class="sub cursor-p pl-button-mode" data-mode="bc" >BC下载</li>${pan.code == 200 && version < pan.version ? pan.newX : ''}</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 getPCSLink() { selectList = this.getSelectedList(); let fidList = this._getFidList(), url, res; if (pt === 'home' || pt === 'main') { if (selectList.length === 0) { return message.error('提示:请先勾选要下载的文件!'); } if (fidList.length === 2) { return message.error('提示:请打开文件夹后勾选文件!'); } fidList = encodeURIComponent(fidList); url = `${pan.pcs[0]}&fsids=${fidList}`; res = await base.get(url, {"User-Agent": pan.ua}); } if (pt === 'share') { this.getShareData(); if (selectList.length === 0) { return message.error('提示:请先勾选要下载的文件!'); } if (fidList.length === 2) { return message.error('提示:请打开文件夹后勾选文件!'); } if (!params.sign) { let url = `${pan.pcs[2]}&surl=${params.surl}&logid=${params.logid}`; let r = await base.get(url); if (r.errno === 0) { params.sign = r.data.sign; params.timestamp = r.data.timestamp; } else { let dialog = await Swal.fire({ toast: true, icon: 'info', title: `提示:请将文件<span class="tag-danger">[保存到网盘]</span>👉前往<span class="tag-danger">[我的网盘]</span>中下载!`, showConfirmButton: true, confirmButtonText: '点击保存', position: 'top', }); if (dialog.isConfirmed) { $('.tools-share-save-hb')[0].click(); } return; } } if (!params.bdstoken) { return message.error('提示:请先登录网盘!'); } let formData = new FormData(); formData.append('encrypt', params.encrypt); formData.append('product', params.product); formData.append('uk', params.uk); formData.append('primaryid', params.primaryid); formData.append('fid_list', fidList); formData.append('logid', params.logid); params.shareType === 'secret' ? formData.append('extra', params.extra) : ''; url = `${pan.pcs[1]}&sign=${params.sign}×tamp=${params.timestamp}`; res = await base.post(url, formData, {"User-Agent": pan.ua}); } if (res.errno === 0) { let html = this.generateDom(res.list); this.showMainDialog(pan[mode][0], html, pan[mode][1]); } else if (res.errno === 112) { return message.error('提示:页面过期,请刷新重试!'); } else { message.error('提示:获取下载链接失败!请刷新网页后重试!'); } }, generateDom(list) { let content = '<div class="pl-main">'; let alinkAllText = ''; base.sortByName(list); list.forEach((v, i) => { if (v.isdir === 1) return; let filename = v.server_filename || v.filename; let ext = base.getExtension(filename); let size = base.sizeFormat(v.size); let dlink = v.dlink; if (mode === 'api') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a> <div class="pl-item-tip" style="display: none"><span>若没有弹出IDM下载框,找到IDM <b>选项</b> -> <b>文件类型</b> -> <b>第一个框</b> 中添加后缀 <span class="pl-ext">${ext}</span>,<a href="${pan.idm}" target="_blank" class="pl-a">详见此处</a></span> <span class="pl-back listener-back">返回</span></div> <div class="pl-item-progress" style="display: none"> <div class="pl-progress"> <div class="pl-progress-outer"></div> <div class="pl-progress-inner" style="width:5%"> <div class="pl-progress-inner-text">0%</div> </div> </div> <span class="pl-progress-stop listener-stop">取消下载</span> <span class="pl-progress-tip">未发现IDM,使用自带浏览器下载</span> <span class="pl-progress-how listener-how">如何唤起IDM?</span> </div></div>`; } if (mode === 'aria') { let alink = this.convertLinkToAria(dlink, filename, pan.ua); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'rpc') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`; } if (mode === 'curl') { let alink = this.convertLinkToCurl(dlink, filename, pan.ua); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'bc') { let alink = this.convertLinkToBC(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" href="${decodeURIComponent(alink.link)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link pl-a" 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 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, showConfirmButton: false, position: 'top', width, padding: '15px 20px 5px', customClass, }).then(() => { this._resetData(); }); }, async initPanLinker() { base.initDefaultConfig(); base.addPanLinkerStyle(); pt = this.detectPage(); let res = await base.post (`https://api.youxiaohou.com/config?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton(); base.createTip(); base.registerMenuCommand(); } }; let ali = { convertLinkToAria(link, filename, ua) { filename = filename.replace(' ', '_'); return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Referer: https://www.aliyundrive.com/"`); }, 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 = filename.replace(' ', '_'); return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${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-aria, .listener-copy-all', (e) => { e.preventDefault(); base.setClipboard(decodeURIComponent(e.target.dataset.link)); $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-link-rpc', async (e) => { let target = $(e.currentTarget); target.find('.icon').remove(); target.find('.pl-loading').remove(); target.prepend(base.createLoading()); let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link); if (res === 'success') { $('.listener-rpc-task').show(); target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow"); } else { target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-send-rpc', (e) => { $('.listener-link-rpc').click(); $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-open-setting', () => { base.showSetting(); }); doc.on('click', '.listener-rpc-task', () => { let rpc = JSON.stringify({ domain: base.getValue('setting_rpc_domain'), port: base.getValue('setting_rpc_port'), }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`; GM_openInTab(url, {active: true}); }); }, 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() { if (!pt) return; let $toolWrap; let $button = $(`<div class="ali-button pl-button"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M853.333 938.667H170.667a85.333 85.333 0 0 1-85.334-85.334v-384A85.333 85.333 0 0 1 170.667 384H288a32 32 0 0 1 0 64H170.667a21.333 21.333 0 0 0-21.334 21.333v384a21.333 21.333 0 0 0 21.334 21.334h682.666a21.333 21.333 0 0 0 21.334-21.334v-384A21.333 21.333 0 0 0 853.333 448H736a32 32 0 0 1 0-64h117.333a85.333 85.333 0 0 1 85.334 85.333v384a85.333 85.333 0 0 1-85.334 85.334z" fill="#fff"/><path d="M715.03 543.552a32.81 32.81 0 0 0-46.251 0L554.005 657.813v-540.48a32 32 0 0 0-64 0v539.734L375.893 543.488a32.79 32.79 0 0 0-46.229 0 32.427 32.427 0 0 0 0 46.037l169.557 168.811a32.81 32.81 0 0 0 46.251 0l169.557-168.81a32.47 32.47 0 0 0 0-45.974z" fill="#FF9C00"/></svg><ul class="pl-dropdown-menu"><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>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { let ins = setInterval(() => { $toolWrap = $(pan.btn.home); if ($toolWrap.length > 0) { $toolWrap.append($button); clearInterval(ins); } }, 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 pl-button-init"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M853.333 938.667H170.667a85.333 85.333 0 0 1-85.334-85.334v-384A85.333 85.333 0 0 1 170.667 384H288a32 32 0 0 1 0 64H170.667a21.333 21.333 0 0 0-21.334 21.333v384a21.333 21.333 0 0 0 21.334 21.334h682.666a21.333 21.333 0 0 0 21.334-21.334v-384A21.333 21.333 0 0 0 853.333 448H736a32 32 0 0 1 0-64h117.333a85.333 85.333 0 0 1 85.334 85.333v384a85.333 85.333 0 0 1-85.334 85.334z" fill="#fff"/><path d="M715.03 543.552a32.81 32.81 0 0 0-46.251 0L554.005 657.813v-540.48a32 32 0 0 0-64 0v539.734L375.893 543.488a32.79 32.79 0 0 0-46.229 0 32.427 32.427 0 0 0 0 46.037l169.557 168.811a32.81 32.81 0 0 0 46.251 0l169.557-168.81a32.47 32.47 0 0 0 0-45.974z" fill="#FF9C00"/></svg></div>`); if (pt === 'home') { let ins = setInterval(() => { $toolWrap = $(pan.btn.home); if ($toolWrap.length > 0) { $toolWrap.append($button); clearInterval(ins); } }, 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.getElementsByClassName(pan.dom.grid)[0]; if (reactDomGrid) { let res = await Swal.fire({ title: '提示', html: '<div style="display: flex;align-items: center;justify-content: center;">请先切换到 <b>列表视图</b>(<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M132 928c-32.8 0-59.2-26.4-59.2-59.2s26.4-59.2 59.2-59.2h760c32.8 0 59.2 26.4 59.2 59.2S924.8 928 892 928H132zm0-356.8c-32.8 0-59.2-26.4-59.2-59.2s26.4-59.2 59.2-59.2h760c32.8 0 59.2 26.4 59.2 59.2s-26.4 59.2-59.2 59.2H132zm0-356c-32.8 0-59.2-26.4-59.2-59.2S99.2 96.8 132 96.8h760c32.8 0 59.2 26.4 59.2 59.2s-26.4 59.2-59.2 59.2H132z"/></svg>)后获取!</div>', confirmButtonText: '点击切换' }); if (res) { $('.switch-wrapper--1yEfx').trigger('click'); return message.success('切换成功,请重新获取下载链接!'); } return false; } selectList = this.getSelectedList(); if (selectList.length === 0) { return message.error('提示:请先勾选要下载的文件!'); } if (this.isOnlyFolder()) { return message.error('提示:请打开文件夹后勾选文件!'); } if (pt === 'share') { if (selectList.length > 20) { return message.error('提示:单次最多可勾选 20 个文件!'); } try { let authorization = `${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>`; } if (mode === 'aria') { let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'rpc') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`; } if (mode === 'curl') { let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } 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.getElementsByClassName(pan.dom.list)[0]; 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(); let res = await base.post (`https://api.youxiaohou.com/config/ali?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton(); base.createTip(); base.registerMenuCommand(); } }; let tianyi = { convertLinkToAria(link, filename, ua) { filename = filename.replace(' ', '_'); return encodeURIComponent(`aria2c "${link}" --out "${filename}"`); }, 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 = filename.replace(' ', '_'); return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${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"); }); doc.on('click', '.listener-link-rpc', async (e) => { let target = $(e.currentTarget); target.find('.icon').remove(); target.find('.pl-loading').remove(); target.prepend(base.createLoading()); let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link); if (res === 'success') { $('.listener-rpc-task').show(); target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow"); } else { target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-send-rpc', (e) => { $('.listener-link-rpc').click(); $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-open-setting', () => { base.showSetting(); }); doc.on('click', '.listener-rpc-task', () => { let rpc = JSON.stringify({ domain: base.getValue('setting_rpc_domain'), port: base.getValue('setting_rpc_port'), }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`; GM_openInTab(url, {active: true}); }); }, addButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="tianyi-button pl-button">下载助手<ul class="pl-dropdown-menu" style="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>${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') { 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); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'rpc') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`; } if (mode === 'curl') { let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { 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(); 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 = filename.replace(' ', '_'); 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 = filename.replace(' ', '_'); return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${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"); }); 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"); }); doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => { e.preventDefault(); base.setClipboard(decodeURIComponent(e.target.dataset.link)); $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-link-rpc', async (e) => { let target = $(e.currentTarget); target.find('.icon').remove(); target.find('.pl-loading').remove(); target.prepend(base.createLoading()); let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link); if (res === 'success') { $('.listener-rpc-task').show(); target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow"); } else { target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-send-rpc', (e) => { $('.listener-link-rpc').click(); $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-open-setting', () => { base.showSetting(); }); doc.on('click', '.listener-rpc-task', () => { let rpc = JSON.stringify({ domain: base.getValue('setting_rpc_domain'), port: base.getValue('setting_rpc_port'), }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`; GM_openInTab(url, {active: true}); }); }, addButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="xunlei-button pl-button"><i class="xlpfont xlp-download"></i><span style="font-size: 13px;margin-left: 6px;">下载助手</span><ul class="pl-dropdown-menu" style="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>${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.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); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'rpc') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`; } if (mode === 'curl') { let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } 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(); 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 = filename.replace(' ', '_'); 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 = filename.replace(' ', '_'); return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L "${link}" --output "${filename}" -b "${document.cookie}"`); }, addPageListener() { window.addEventListener('hashchange', (event)=>{ 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"); }); doc.on('click', '.listener-link-rpc', async (e) => { let target = $(e.currentTarget); target.find('.icon').remove(); target.find('.pl-loading').remove(); target.prepend(base.createLoading()); let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link); if (res === 'success') { $('.listener-rpc-task').show(); target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow"); } else { target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow"); } }); doc.on('click', '.listener-send-rpc', (e) => { $('.listener-link-rpc').click(); $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow"); }); doc.on('click', '.listener-open-setting', () => { base.showSetting(); }); doc.on('click', '.listener-rpc-task', () => { let rpc = JSON.stringify({ domain: base.getValue('setting_rpc_domain'), port: base.getValue('setting_rpc_port'), }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`; GM_openInTab(url, {active: true}); }); }, addButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="quark-button pl-button"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#555" 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>${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.css({'margin-right': '10px'}); let ins = setInterval(() => { $toolWrap = $(pan.btn.share); if ($toolWrap.length > 0) { $toolWrap.prepend($button); clearInterval(ins); } }, 50); } }, addInitButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="quark-button pl-button-init"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#555" 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>`); 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); } $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"}); 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 { return message.error('提示:请转存到自己网盘后去网盘主页下载!'); } }, 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); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } if (mode === 'rpc') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`; } if (mode === 'curl') { let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent); if (typeof (alink) === 'object') { content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}</a> </div>`; } else { alinkAllText += alink + '\r\n'; content += `<div class="pl-item"> <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div> <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`; } } 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(); 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 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(); } } }; main.init(); })();