获取迅雷云盘的文件链接,可利用本地播放器看视频;可将播放列表导入坚果云;可利用其他工具下载(如idm,curl,Xdown,Motrix,Aria2);添加隐藏回收站功能,可自由彻底删除、还原。
// ==UserScript== // @name 迅雷云盘 // @namespace http://tampermonkey.net/ // @version 2.0.3 // @description 获取迅雷云盘的文件链接,可利用本地播放器看视频;可将播放列表导入坚果云;可利用其他工具下载(如idm,curl,Xdown,Motrix,Aria2);添加隐藏回收站功能,可自由彻底删除、还原。 // @author bleu // @compatible edge Tampermonkey // @compatible chrome Tampermonkey // @compatible firefox Tampermonkey // @license MIT // @icon https://fastly.jsdelivr.net/gh/Bleu404/PRPO@latest/png/xunlei.png // @supportURL https://greasyfork.org/zh-CN/scripts/431256/feedback // @match https://pan.xunlei.com/* // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_registerMenuCommand // @connect * // @connect localhost // @connect 127.0.0.1 // @connect xunlei.com // @connect dav.jianguoyun.com // @require https://fastly.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js // @require https://fastly.jsdelivr.net/npm/[email protected]/dist/jquery.min.js // @require https://fastly.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js // ==/UserScript== (function () { 'use strict'; const originFetch = fetch; let linkConfig, reqHeaders, fil###RL,arryIndex,fileArry,filetxt,temp_path,OSflag; let running = { 'runStatus': false, 'successNum': 0, 'failNum': 0, 'exit': false, 'r###ltNum': 0, } let $BleuButton,$deleteBut; isResetConfig(); //退出配置保存数据 function swalCloseFunc() { let local_path = $('#config_path').val().trim(); let aria2 = { 'ip': $('#config_ip').val().trim(), 'port': $('#config_port').val().trim(), 'token': $('#config_token').val().trim(), }; let jgy = { 'path': $('#jgy_path').val().trim(), 'account': $('#jgy_account').val().trim(), 'password': $('#jgy_password').val().trim(), }; let qualityAry = $('#bleu_select').val(); qualityAry = qualityAry === 'highlow' ? ['selected', ''] : ['', 'selected']; let checkAry = [], autoClick = { state: false, itemIndex: 0 }, itemcount = 0; $('.td-checkbox__inner.bleu').each((index, item) => { checkAry[index] = ''; if (item.checked) { checkAry[index] = 'checked'; autoClick.itemIndex = index; itemcount++; } if (index === $('.td-checkbox__inner.bleu').length - 1 && itemcount === 1) { autoClick.state = true; } }) $('.td-checkbox__inner.bleucb').each((index, item) => { checkAry[item.getAttribute('index')] = ''; if (item.checked) { checkAry[item.getAttribute('index')] = 'checked'; } }) localStorage.setItem("linkConfig", JSON.stringify({ 'local_path': local_path, 'displays': checkAry, 'aria2': aria2, 'jgy': jgy, 'quality': qualityAry, 'autoClick': autoClick, })); if (local_path.indexOf("/") >= 0) { OSflag = "/"; } window.ariaNgUI && window.ariaNgUI.close(); } //初始或者取配置json function isResetConfig() { linkConfig = JSON.parse(localStorage.getItem("linkConfig")) || { 'local_path': 'D:\\Downloads', 'displays': ['checked', 'checked', 'checked', 'checked', 'checked', 'checked', '', ''], 'aria2': { 'ip': 'http://localhost', 'port': '16800', 'token': '' }, 'jgy': { 'path': 'ThunderPlaylist', 'account': '', 'password': '' }, 'quality': ['selected', ''], }; if (!linkConfig.jgy) { linkConfig.jgy = { 'path': 'ThunderPlaylist', 'account': '', 'password': '' } } } let main = { addCssStyle() { let style = document.createElement('style'); style.innerHTML = tools.cssStyle; document.querySelector('head').appendChild(style); }, addElements() { $BleuButton = $('<div id="bleu_btn" class="FileMenu__item--7MGwA active"><i class="xlpfont xlp-download"></i><span>直链</span></div>'); $deleteBut = $('<li id="bleu_trash" class=""><p class="bar-box"><i class="xlpfont xlp-trash"></i> <span>回收站</span></p></li>'); $('div.pan-wrapper-asider ul li').length == 5&&$('div.pan-wrapper-asider ul').append($deleteBut); $('div.pan-list-menu').length>0&&$('div.pan-list-menu')[0].innerText.indexOf('彻底删除')!=0&&$('div.pan-list-menu').prepend($BleuButton); $('.FileMenu__menu--XBFEH').length != 0 ? $('.FileMenu__menu--XBFEH').prepend($BleuButton) : $BleuButton; if(location.href.indexOf('https://pan.xunlei.com/?filter=trash')==0){ $('#bleu_trash')[0].className = 'on'; } $('div.pan-wrapper-asider ul li').on('click', ()=>{ $('div.pan-list-menu').length>0&&$('div.pan-list-menu')[0].innerText.indexOf('彻底删除')!=0&&$('div.pan-list-menu').prepend($BleuButton); if(location.href.indexOf('https://pan.xunlei.com/?filter=trash')!=0){ $('#bleu_trash')[0].className = ''; } }) }, addButtonEvent() { $BleuButton.on('click', async function () { main.getHeaders(); tools.swalForInfo('==获取直链中,请等待==', '', 'center'); if (running.runStatus) { return } isResetConfig(); try { await main.getAllInfo(); } catch (error) { console.log(error); tools.swalForInfo('==请刷新页面重新尝试!==', '', 'center'); running.runStatus = false; return; } let mainui = tools.swalForUI(`成功${running.successNum}条;失败${running.failNum}条`, tools.swalHtml(),400+'px'); $('.btn_bleu').on('click', function (item) { let temp = item.target.defaultValue; main.getCollatedData(temp) }) if (linkConfig.autoClick.state) { $('.btn_bleu')[linkConfig.autoClick.itemIndex].click(); setTimeout(() => { mainui.close(); }, 1000); } }) GM_registerMenuCommand('直链配置', () => { isResetConfig(); tools.swalForUI(`直链配置`, tools.swalConfig(),'400px').then(swalCloseFunc); }) $deleteBut.on('click', function () { this.className='on'; location.href ='https://pan.xunlei.com/?filter=trash&path=%2F'; }) }, setInitValue() { arryIndex = 0; fileArry = [[]]; filetxt = []; temp_path = ''; running.runStatus = true; running.successNum = 0; running.failNum = 0; running.r###ltNum = 0; }, async getAllInfo() { main.setInitValue(); $('li.SourceListItem__item--XxpOC.SourceListItem__active--4U0f4').each((index,item) => { let temp = item.__vue__.info let itemInfo = { 'kind': temp.kind, 'id': temp.id, 'name': temp.name, 'phase': temp.phase, 'trashed': temp.trashed }; fileArry[arryIndex].push(itemInfo); }); await main.getAllFiles(fileArry[0]); running.runStatus = false; running.r###ltNum = running.successNum + running.failNum; }, async getAllFiles(loopArry) { for (let index = 0; index < loopArry.length; index++) { if (loopArry[index]) { if (loopArry[index].kind === 'drive#file') { await main.getDirectLink(loopArry[index].id); } if (loopArry[index].kind === 'drive#folder') { temp_path += `${OSflag}${loopArry[index].name}`; await main.getFileSign(loopArry[index]); await main.getAllFiles(fileArry[arryIndex - 1]); } } } temp_path = temp_path.substring(0, temp_path.lastIndexOf(OSflag)); }, getFileSign(folder) { let runURL = `https://api-pan.xunlei.com/drive/v1/files?limit=100&parent_id=${folder.id}&filters={"phase":{"eq":"${folder.phase}"},"trashed":{"eq":${folder.trashed}}}&with_audit=true`; runURL = encodeURI(runURL); fileArry[arryIndex] = []; return tools.bleuAjax('get', runURL).then(value => { value.files.forEach((item) => { let temp = { 'kind': item.kind, 'id': item.id, 'name': item.name, 'phase': item.phase, 'trashed': item.trashed }; fileArry[arryIndex].push(temp); }); arryIndex++; }, reason => { runURL === fil###RL ? running.exit = true : running.exit = false; console.error(reason); }); }, getDirectLink(sign) { let URL = `https://api-pan.xunlei.com/drive/v1/files/${sign}`; return tools.bleuAjax('get', URL).then(value => { running.successNum++; let mediasLink = []; if (value.medias != []) { value.medias.forEach(function (item) { if (item.link != null) { mediasLink.push({ 'name': item.media_name, 'url': item.media_name === '原始画质' ? value.web_content_link : item.link.url, }) } }) } filetxt.push({ 'name': value.name, 'link': value.web_content_link, 'path': temp_path, 'medias': mediasLink }); }, reason => { running.failNum++; console.log(reason); }); }, //整理发送到其他工具的数据 async getCollatedData(dataType) { if (running.r###ltNum === 0) { return; } if (dataType.match('aria2')) { tools.swalForInfo('==基于aria2发送RPC任务中,请等待==', '', 'center'); } let nameLinkTxt = ''; let mediaIndex, selectedURL; if (dataType.match('播放')) { nameLinkTxt = '#EXTM3U\n' } filetxt.forEach(async (item) => { selectedURL = linkConfig.displays[6] == 'checked' && item.medias.length > 0 ? item.medias[0].url : item.link; if (dataType.match('aria2')) { return } if (dataType.match('文件链接')) { nameLinkTxt += `<div style="padding: 5px;"><a class="bleu_a" href=${selectedURL} download=${item.name.replace(/ /g,'_')}>${item.name}</a><span class="bleu_gm">浏览器下载</span></div>`; } if (dataType.match('idm')) { nameLinkTxt += `idman /d "${selectedURL}" /p "${linkConfig.local_path}${item.path}" /f "${item.name}" \nping 127.0.0.1 -n 2 >nul\n`; } if (dataType.match('curl')) { nameLinkTxt += `echo 正在下载这个文件:&echo "${linkConfig.local_path}${item.path}${OSflag}${item.name}"&curl -L "${selectedURL}" -o "${linkConfig.local_path}${item.path}${OSflag}${item.name}"\n\n`; } if (dataType.match('Xdown')) { nameLinkTxt += `aria2c "${selectedURL}" --dir "${linkConfig.local_path}${item.path}" --out "${item.name}"\n`; } if (dataType.match('播放')) { mediaIndex = linkConfig.quality[0] === '' ? item.medias.length - 1 : 0; nameLinkTxt += `#EXTINF:-1 ,${item.name}\n${item.medias[mediaIndex].url}\n`; } }); if(dataType.match('显示')){ tools.swalForUI('显示文件链接',nameLinkTxt,'550px'); $('.bleu_gm').on('click', function (e) { GM_download({ url: e.target.previousElementSibling.getAttribute('href'), name: e.target.previousElementSibling.getAttribute('download') }); }) } else if (dataType.match('复制')) { new ClipboardJS('.btn_bleu.xdown', { text: function () { return nameLinkTxt; } }); tools.swalForInfo('复制链接成功!', 1000, 'top-end'); } else if (dataType.match('aria2')) { main.sendDataToAria(); } else { let filenam = `${dataType.replace('.txt','')}${(new Date()).valueOf()}.txt`; if (dataType.match('播放')) { main.putDataToJGY(filenam, nameLinkTxt); } else { tools._downFlie(filenam, nameLinkTxt); } } }, async sendDataToAria() { let swalTitle = `导入成功,请到aria2客户端查看任务!`,selectedURL; for (let index = 0; index < filetxt.length; index++) { try { selectedURL = linkConfig.displays[6] == 'checked' && filetxt[index].medias.length > 0 ? filetxt[index].medias[0].url : filetxt[index].link; if (linkConfig.displays[7] == '') { await main.sendDataByRPC(index, selectedURL); } else { //使用ariaNg发送 let timedelay = 100; if (!window.ariaNgUI || window.ariaNgUI.closed) { window.ariaNgUI = window.open(`http://ariang.js.org/#!/settings/rpc/set/${linkConfig.aria2.ip.split('://')[0]}/${linkConfig.aria2.ip.split('://')[1]}/${linkConfig.aria2.port}/jsonrpc/${btoa(linkConfig.aria2.token)}`, '_blank'); timedelay = 2000; //不延迟,不能修改rpc配置 } setTimeout(() => { window.ariaNgUI == null ? swalTitle = `导入失败,ariaNg页面被拦截了!` : swalTitle; window.ariaNgUI.location.href = `http://ariang.js.org/#!/new/task?url=${window.btoa(selectedURL)}&out=${encodeURIComponent(filetxt[index].name)}&dir=${encodeURIComponent(linkConfig.local_path)}${encodeURIComponent(filetxt[index].path)}`; }, timedelay) } } catch (error) { console.log(error.responseText); swalTitle.match('成功') ? swalTitle = `导入失败,确认配置aria2没问题!` : swalTitle; break; } } tools.swalForInfo(swalTitle, 3000, 'top-end'); }, sendDataByRPC(index, selectedURL) { let jsonData = { id: new Date().getTime(), jsonrpc: '2.0', method: 'aria2.addUri', params: [`token:${linkConfig.aria2.token}`, [selectedURL], { dir: linkConfig.local_path + filetxt[index].path, out: filetxt[index].name }] } jsonData = JSON.stringify(jsonData); return tools.bleuAjax('post', `${linkConfig.aria2.ip}:${linkConfig.aria2.port}/jsonrpc`, jsonData,''); }, //将播放列表存入坚果云 putDataToJGY(filenam, nameLinkTxt) { if (linkConfig.jgy.account == '') { filenam = `迅雷云盘播放列表.m3u`; tools._downFlie(filenam, nameLinkTxt); } else { let url = `https://dav.jianguoyun.com/dav/${linkConfig.jgy.path}/xlPlaylist.m3u`; let header = {"authorization": `Basic ${btoa(linkConfig.jgy.account+':'+linkConfig.jgy.password)}`}; tools.bleuAjax('put',url , nameLinkTxt,header).then( (value)=>{ value.status === 204?tools.swalForInfo("导入到坚果云成功!", 3000, 'top-end'):tools.swalForInfo("导入到坚果云失败!", 3000, 'top-end') }, ()=>{tools.swalForInfo("导入到坚果云失败!", 3000, 'top-end')}); } }, hookFetch() { Object.defineProperty(unsafeWindow, "fetch", { configurable: true, enumerable: true, // writable: true, get() { return (url, options) => { if (url.indexOf('https://api-pan.xunlei.com/drive/v1/files?limit=100&') === 0) { fil###RL = url; reqHeaders = options.headers; } return originFetch(url, options) } } }) }, getHeaders() { reqHeaders={}; reqHeaders.withCredentials = false; reqHeaders['content-type'] = 'application/json'; for (let key in localStorage) { let temp = localStorage.getItem(key) if (key.indexOf('credentials') === 0) { reqHeaders.Authorization = JSON.parse(temp).token_type + ' ' + JSON.parse(temp).access_token; reqHeaders.clientid = key.substring(key.indexOf('_') + 1); } if (key.indexOf('captcha') === 0) reqHeaders['x-captcha-token'] = JSON.parse(temp).token if (key === 'deviceid') reqHeaders['x-device-id'] = temp.substring(temp.indexOf('.') + 1, 32 + temp.indexOf('.') + 1) } }, initUI() { let observer = new MutationObserver(function (mutationsList) { for (let mutation of mutationsList) { if (mutation.type === 'childList') { if (mutation.target.querySelector('.pan-wrapper-asider') && $('#bleu_btn').length == 0) { main.addElements(); main.addButtonEvent(); break; } } } }); observer.observe($('#__layout')[0], { childList: true, subtree: true, }); if(location.href.indexOf('/s/')>0){ tools.swalForInfo(`❗不支持此页面,请先保存到云盘`, '', 'top-end') } }, } let tools = { cssStyle: ` .btn_bleu{width: 250px;font-size: 20px;padding: 10px 25px;cursor: pointer;text-align: center;text-decoration: none;outline: none;color: #fff;background-color: #2670ea;border: none;border-radius: 100px;display:block;margin:12px auto} .btn_bleu:hover{background-color: #3F85FE;box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);} .btn_bleu:active{background-color: #3F85FE;box-shadow: 0 5px #666;transform: translateY(4px)} .bleu_sa_close {width: 30px;height: 30px;font-size: 30px;} .bleu_sa_title {font-size: 25px;} .bleu_sa_container{margin: 0;font-size: 20px;} .bleu_sa_popup {padding: 0 0 0;} .bleu_a{text-decoration: underline;font-size: 16px;white-space: nowrap;background: linear-gradient(to right, red, blue);-webkit-background-clip: text;color: transparent;display: inline-block;width: 400px;} .bleu_a:hover{color: #3F85FE} .bleu_sa_footer{margin: 0;padding-top: 20px;} .bleu_sa_title_min{font-size: 20px !important;padding: 0;} .bleu_sa_popup_min{padding: 0 0 0;width: auto;} .bleu_config{position: absolute;left: 5%;bottom: 10%;width: 60px;height: 60px;line-height: 60px;border-radius: 50%;cursor: pointer;font-size: 13px;background-color: #2670ea;color: #fff;text-align: center;} .bleu_config:hover{background-color: #3F85FE} .bleu_config_item{border-radius: 10px;font-size: 20px;margin: 12px 50px;color: #fff;background-color: #3F85FE;box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);} .bleu_config_item label{font-size: 15px} .bleu_config_item input.bleu_inp{margin: 0px 10px;font-size: 15px;} .bleu_config_item input.td-checkbox__inner{margin: 0px 10px 0px 0px} .bleu_inp{width:60%} .bleu_config_item p{text-align: left;margin: 0px 20px;} .bleu_gm{margin-left: 10px;font-size: 14px;background-color: #2670ea;color: white;border-radius: 5%;padding: 5px 10px;} .bleu_gm:hover{background-color: #3F85FE;box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);} .bleu_gm:active{background-color: #3F85FE;box-shadow: 0 5px #666;transform: translateY(4px)} #bleu_select{margin: 0px 10px;background-color: #3F85FE;font-size: 15px;border: none;} `, swalHtml: function () { return `<div><input type="button" style="display:${linkConfig.displays[0]==='checked'?'block':'none'}" class="btn_bleu" value="显示文件链接"></input></div> <div><input type="button" style="display:${linkConfig.displays[1]==='checked'?'block':'none'}" class="btn_bleu xdown" value="复制idm下载链接"></input></div> <div><input type="button" style="display:${linkConfig.displays[2]==='checked'?'block':'none'}" class="btn_bleu" value="curl下载.txt"></input></div> <div><input type="button" style="display:${linkConfig.displays[3]==='checked'?'block':'none'}" class="btn_bleu xdown" value="复制Xdown下载链接"></input></div> <div><input type="button" style="display:${linkConfig.displays[4]==='checked'?'block':'none'}" class="btn_bleu" value="基于aria2发送RPC任务"></input></div> <div><input type="button" style="display:${linkConfig.displays[5]==='checked'?'block':'none'}" class="btn_bleu" value="导出播放列表"></input></div> <a class="bleu_a" href="https://greasyfork.org/zh-CN/scripts/431256" target="_blank">按钮功能说明</a> ` }, swalConfig: function () { return `<div class="bleu_config_item"><b>本地下载路径</b> <p><label>目录</label><input type="text" class="bleu_inp" id="config_path" value="${linkConfig.local_path}"/></p> </div> <div class="bleu_config_item"><b>功能按钮显示</b> <p><input type="checkbox" ${linkConfig.displays[0]} class="td-checkbox__inner bleu"></input><label>显示“显示文件链接”</label></p> <p><input type="checkbox" ${linkConfig.displays[1]} class="td-checkbox__inner bleu"></input><label>显示“复制idm下载链接”</label></p> <p><input type="checkbox" ${linkConfig.displays[2]} class="td-checkbox__inner bleu"></input><label>显示“curl下载.txt”</label></p> <p><input type="checkbox" ${linkConfig.displays[3]} class="td-checkbox__inner bleu"></input><label>显示“复制Xdown下载链接”</label></p> <p><input type="checkbox" ${linkConfig.displays[4]} class="td-checkbox__inner bleu"></input><label>显示“基于aria2发送RPC任务”</label></p> <p><input type="checkbox" ${linkConfig.displays[5]} class="td-checkbox__inner bleu"></input><label>显示“导出播放列表”</label></p> </div> <div class="bleu_config_item"><b>配置aria2任务</b> <p><input type="checkbox" index="7" ${linkConfig.displays[7]} class="td-checkbox__inner bleucb"></input><label>通过ariaNg远程发送任务</label></p> <p><label>地址</label><input type="text" class="bleu_inp" id="config_ip" value="${linkConfig.aria2.ip}"/></p> <p><label>端口</label><input type="text" class="bleu_inp" id="config_port" value="${linkConfig.aria2.port}"/></p> <p><label>密钥</label><input type="text" class="bleu_inp" id="config_token" value="${linkConfig.aria2.token}"/></p> </div> <div class="bleu_config_item"><b>播放列表设置</b> <p><label>画质选择</label><select id="bleu_select"> <option value="highlow" ${linkConfig.quality[0]}>从高到低</option> <option value="lowhigh" ${linkConfig.quality[1]}>从低到高</option> </select></p> <b>列表存坚果云</b> <p><label>文件夹</label><input type="text" class="bleu_inp" id="jgy_path" value="${linkConfig.jgy.path}"/></p> <p><label>账户</label><input type="text" class="bleu_inp" id="jgy_account" value="${linkConfig.jgy.account}"/></p> <p><label>授权密码</label><input type="text" class="bleu_inp" id="jgy_password" value="${linkConfig.jgy.password}"/></p> </div> <div class="bleu_config_item"><b>视频专用下载</b> <p><input type="checkbox" index="6" ${linkConfig.displays[6]} class="td-checkbox__inner bleucb"></input><label>勾选此项,不下载源文件,下载云播最高清晰度视频。</label></p> </div>` }, swalForUI: function (title, html,width) { return swal.fire({ title: title, html: html, width: width, showConfirmButton: false, showCloseButton: true, allowOutsideClick: false, footer: ' ', customClass: { title: 'bleu_sa_title', popup: 'bleu_sa_popup', closeButton: 'bleu_sa_close', htmlContainer: 'bleu_sa_container', footer: 'bleu_sa_footer' }, }) }, swalForInfo: function (satitle, satime, saposition) { return Swal.fire({ title: satitle, position: saposition, showConfirmButton: false, timer: satime, customClass: { title: 'bleu_sa_title_min', popup: 'bleu_sa_popup_min' } }) }, bleuAjax: function (TYPE, URL, DATA,HEADER) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: TYPE, timeout: 2000, headers: HEADER||reqHeaders, url: URL, data: DATA, dataType: "json", onload: function (res) { resolve(JSON.parse(res.response||null)||res.response||res); }, onerror: function (err) { reject(JSON.parse(err.response||null)||err.response||err); }, ontimeout:function(err){ reject(err); } }); }) }, _downFlie(fnmae, data) { let elementA = document.createElement('a'); elementA.download = fnmae; elementA.style.display = 'none'; let blob = new Blob([data]); elementA.href = URL.createObjectURL(blob); document.body.appendChild(elementA); elementA.click(); document.body.removeChild(elementA); }, platform() { OSflag = "\\"; if (linkConfig.local_path.indexOf("/") >= 0) { OSflag = "/"; } } } window.onunload = () => { window.ariaNgUI && window.ariaNgUI.close(); }; //main.hookFetch(); main.addCssStyle(); tools.platform(); main.initUI(); })();