Before you install, Greasy Fork would like you to know that this script contains antifeatures, which are things there for the script author's benefit, rather than yours.
그룹에 가입하거나, 채널을 구독하거나, 페이지에 추천을 하는 등 어딘가 에 등록해야 스크립트를 제한없이 쓸 수 있습니다.
👆👆👆👆👆👆👆 - 支持批量获取 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 ✅夸克网盘 ✅移动云盘 六大网盘的直链下载地址,配合 IDM,Xdown,Aria2,Curl,比特彗星等工具高效🚀🚀🚀下载,完美适配 Chrome,Edge,FireFox,360,QQ,搜狗,百分,遨游,星愿,Opera,猎豹,Vivaldi,Yandex,Kiwi 等 18 种浏览器。可在无法安装客户端的环境下使用,助手免费开源。😎
// ==UserScript== // @name 网盘直链下载助手 // @namespace https://github.com/syhyz1990/baiduyun // @version 6.2.7 // @author GreasyFork // @description 👆👆👆👆👆👆👆 - 支持批量获取 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 ✅夸克网盘 ✅移动云盘 六大网盘的直链下载地址,配合 IDM,Xdown,Aria2,Curl,比特彗星等工具高效🚀🚀🚀下载,完美适配 Chrome,Edge,FireFox,360,QQ,搜狗,百分,遨游,星愿,Opera,猎豹,Vivaldi,Yandex,Kiwi 等 18 种浏览器。可在无法安装客户端的环境下使用,助手免费开源。😎 // @license AGPL-3.0-or-later // @homepage https://www.youxiaohou.com/install.html // @supportURL https://github.com/syhyz1990/baiduyun // @antifeature membership // @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 *://openapi.baidu.com/* // @match *://www.aliyundrive.com/s/* // @match *://www.aliyundrive.com/drive* // @match *://www.alipan.com/s/* // @match *://www.alipan.com/drive* // @match *://cloud.189.cn/web/* // @match *://pan.xunlei.com/* // @match *://pan.quark.cn/* // @match *://yun.139.com/* // @match *://caiyun.139.com/* // @require https://unpkg.com/jquery@3.7.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 alipan.com // @connect 189.cn // @connect xunlei.com // @connect quark.cn // @connect youxiaohou.com // @connect yun.139.com // @connect caiyun.139.com // @connect localhost // @connect * // @run-at document-idle // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_openInTab // @grant GM_info // @grant GM_registerMenuCommand // @grant GM_cookie // @grant window.close // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjMTM5N2Q4Ii8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNODguMyA3My44TDczLjUgOTMuMmMtMS41IDEuOS0zLjUgMy4xLTUuNyAzLjVoLS4yYy0uNC4xLS44LjEtMS4yLjEtLjYgMC0xLjEtLjEtMS42LS4yLTIuMi0uNC00LjItMS43LTUuNi0zLjVMNDQuMyA3My45Yy0yLTIuNi0yLjUtNS40LTEuNC03LjcuMS0uMS4xLS4yLjItLjIgMS4yLTIgMy41LTMuMiA2LjQtMy4yaDYuNnYtNS43YzAtNi44IDQuNy0xMiAxMC45LTEyIDQuOCAwIDguNSAyLjYgMTAuMyA3LjIuNSAxLjMtLjIgMi43LTEuNSAzLjJzLTIuOC0uMS0zLjMtMS40Yy0xLjEtMi43LTIuOS00LTUuNS00LTMuNSAwLTYgMy02IDd2OC4xYzAgLjUtLjIgMS0uNiAxLjQtLjYuNy0xLjcgMS4xLTIuNiAxLjFoLTguNGMtMS4zIDAtMiAuNC0yLjEuNy0uMi40IDAgMS4zLjkgMi40TDYzLjEgOTBjLjkgMS4yIDIuMSAxLjggMy4zIDEuOHMyLjMtLjYgMy4xLTEuN2wxNC44LTE5LjNjLjktMS4xIDEuMS0yIC45LTIuNC0uMi0uMy0uOS0uNy0yLjEtLjdoLTcuNmMtLjkgMC0xLjctLjUtMi4xLTEuMi0uMy0uNC0uNC0uOC0uNC0xLjMgMC0xLjQgMS4xLTIuNSAyLjUtMi41aDcuNmMzLjEgMCA1LjUgMS4zIDYuNiAzLjVsLjMuN2MuNyAyLjEuMSA0LjYtMS43IDYuOXoiIGZpbGw9IiM0NDQiLz48L3N2Zz4= // ==/UserScript== (function () { 'use strict'; let pt = '', selectList = [], params = {}, mode = '', width = 800, pan = {}, color = '', doc = $(document), progress = {}, request = {}, ins = {}, idm = {}; const scriptInfo = GM_info.script; const version = scriptInfo.version; const author = scriptInfo.author; const name = scriptInfo.name; const manageHandler = GM_info.scriptHandler; const manageVersion = GM_info.version; 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 cname = name + "="; let ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i].trim(); if (c.indexOf(cname) == 0) return c.substring(cname.length, c.length); } 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); }, deleteValue(name) { GM_deleteValue(name); }, 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)); }, getMajorVersion(version) { const [major] = (version || '').split('.'); return /^\d+$/.test(major) ? major : null; }, 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: '' }, { name: 'license', 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'); }, listenElement(element, callback) { const checkInterval = 500; // 检查元素的间隔时间(毫秒) let wasElementFound = false; // 用于跟踪元素是否之前已经找到 function checkElement() { if (document.querySelector(element)) { wasElementFound = true; callback(); } else if (wasElementFound) { wasElementFound = false; // 元素消失后重置标志 } setTimeout(checkElement, checkInterval); } checkElement(); }, 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;} .yidong-button {float: left; position: relative; margin: 20px 24px 20px 0; width: 98px; height: 36px; background: #3181f9; 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; height: 36px; text-align: center; color: #fff; border: 1px solid #5a9afa; border-radius: 2px; padding: 0 24px; margin-left: 24px; background: #3181f9; cursor: pointer;} .yidong-button:hover {background: #2d76e5;} .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;cursor:pointer } .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; } .btn-operate .btn-main { display:flex; align-items:center; } `; 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() || pan.license === $('#init').val()) { base.setValue('setting_init_code', pan.num); base.setValue('license', pan.license); 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) { let BDUSS = cookies?.[0]?.value; if (BDUSS) { base.setStorage("baiduyunPlugin_BDUSS", {BDUSS}); } } }); } 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'); 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><li class="g-button-menu pl-button-mode listener-open-setting">助手设置</li>${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><li class="sub cursor-p pl-button-mode listener-open-setting">助手设置</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 getToken() { const openTab = () => { GM_openInTab(pan.pcs[3], {active: false, insert: true, setParent: true}); base.deleteValue('baidu_access_token'); }; const waitForToken = () => new Promise((resolve) => { let attempts = 0; const interval = setInterval(() => { const token = base.getValue('baidu_access_token'); if (token) { clearInterval(interval); resolve(token); } attempts++; if (attempts > 60) { clearInterval(interval); resolve(''); } }, 1000); }); if (manageHandler === 'Tampermonkey' && base.getMajorVersion(manageVersion) >= 5) { openTab(); return waitForToken(); } let res = await base.getFinalUrl(pan.pcs[3]); if (!res.includes('authorize') && !res.includes('access_token=')) { openTab(); return waitForToken(); } if (res.includes('authorize')) { 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.setValue('baidu_access_token', accessToken); return accessToken; } let accessToken = res.match(/access_token=([^&]+)/)?.[1]; accessToken && base.setValue('baidu_access_token', accessToken); return accessToken; }, async getPCSLink(maxRequestTime = 1) { 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.getValue('baidu_access_token') || 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 (!params.bdstoken) { return message.error('提示:请先登录网盘!'); } if (selectList.length === 0) { return message.error('提示:请先勾选要下载的文件!'); } if (fidList.length === 2) { return message.error('提示:请打开文件夹后勾选文件!'); } 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 (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 { base.deleteValue('baidu_access_token'); 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 + '&access_token=' + base.getValue('baidu_access_token'); 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}" 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}" 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" target="_blank" href="${alink.link}" 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 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/v2?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton(); base.createTip(); base.registerMenuCommand(); }, async initAuthorize() { let ins = setInterval(() => { if (/openapi.baidu.com\/oauth\/2.0\/authorize/.test(location.href)) { let confirmButton = document.querySelector('#auth-allow'); if (confirmButton) { confirmButton.click(); return; } } if (/openapi.baidu.com\/oauth\/2.0\/login_success/.test(location.href)) { if (location.href.includes('access_token')) { let token = location.href.match(/access_token=(.*?)&/)[1]; base.setValue('baidu_access_token', token); window.close() } } }, 200) } }; 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; $('#downloadIframe').attr('src', href); // 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"); }); 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", "referer": "https://www.aliyundrive.com/", "x-canary": "client=windows,app=adrive,version=v6.0.0" }); if (res.code === 'AccessTokenInvalid') { return message.error('提示:Token过期,请刷新网页后重试!'); } 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><span>下载助手</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>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button').length === 0 && $toolWrap.append($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } 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><span>下载助手</span></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button-init').length === 0 && $toolWrap.append($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-butto-init').length === 0 && $toolWrap.prepend($button); }) } $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;">请先切换到 <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) { 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('提示:请先登录网盘!'); } } else { if (selectList.length > 20) { return message.error('提示:单次最多可勾选 20 个文件!'); } let noUrlSelectList = selectList.filter(v => !Boolean(v.url)) let queue = []; noUrlSelectList.forEach((item, index) => { queue.push(this.getRealLink(item.driveId, item.fileId)); }); const res = await Promise.all(queue); res.forEach((val, index) => { noUrlSelectList[index].url = val; }); } 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(); let res = await base.post (`https://api.youxiaohou.com/config/v2/ali?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? 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"); }); 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><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } base.createDownloadIframe(); this.addPageListener(); }, addInitButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="tianyi-button pl-button-init">下载助手</div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } $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(); let res = await base.post (`https://api.youxiaohou.com/config/v2/tianyi?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? 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"); }); 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><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } 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') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } $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 { 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) { document.querySelector('.saveToCloud').click(); return; } } 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('.SourceListItem__item--XxpOC'); 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/v2/xunlei?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? 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') || pan.license === base.getValue('license') ? 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><b>下载助手</b><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>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button').length === 0 && $toolWrap.prepend($button); }); } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button').length === 0 && $toolWrap.prepend($button); }); } }, 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><b>下载助手</b></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.css({'margin-right': '10px'}); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } $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 { 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) { 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(); let res = await base.post (`https://api.youxiaohou.com/config/v2/quark?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? 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"); }); 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="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>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.removeClass('yidong-button').addClass('yidong-share-button'); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button').length === 0 && $toolWrap.prepend($button); }) } base.createDownloadIframe(); this.addPageListener(); }, addInitButton() { if (!pt) return; let $toolWrap; let $button = $(`<div class="yidong-button pl-button-init">下载助手</div>`); if (pt === 'home') { base.listenElement(pan.btn.home, () => { $toolWrap = $(pan.btn.home); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } if (pt === 'share') { $button.removeClass('yidong-button').addClass('yidong-share-button'); base.listenElement(pan.btn.share, () => { $toolWrap = $(pan.btn.share); $('.pl-button-init').length === 0 && $toolWrap.prepend($button); }) } $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 = { "contentID": item.contentID, "commonAccountInfo": {"account": item.owner, "accountType": 1}, "operation": "0", "inline": "0", "extInfo": {"isReturnCdnDownloadUrl": "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, { 'authorization': base.getCookie('authorization'), '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|7.12.0|chrome|118.0.0.0||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(".main_file_list").__vue__; let res = await base.post(pan.pcs[1], `linkId=${vueDom.linkID}&contentIds=${item.path}&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 path = location.pathname; if (/^\/w/.test(path)) return 'home'; if (/^\/link|shareweb/.test(path)) 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/v2/yidong?ver=${version}&a=${author}`, {}, {}, 'text'); pan = JSON.parse(base.d(res)); Object.freeze && Object.freeze(pan); pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton(); base.createTip(); base.registerMenuCommand(); } }; let main = { init() { if (/(pan|yun).baidu.com/.test(location.host)) { baidu.initPanLinker(); } if (/openapi.baidu.com\/oauth/.test(location.href)) { baidu.initAuthorize() } if (/www.(aliyundrive|alipan).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(); } } }; main.init(); })();