// ==UserScript== // @name 迅雷云盘获取直链 // @namespace http://tampermonkey.net/ // @version 1.4.5 // @description 获取迅雷云盘的直接下载链接,可利用本地播放器看视频,可利用其他工具下载(如浏览器下载,idman,curl命令行,Xdown,Motrix,Aria2) // @author bleu // @compatible edge Tampermonkey // @license MIT // @icon https://img-vip-ssl.a.88cdn.com/img/xunleiadmin/5fb4b23888a05.png // @supportURL https://greasyfork.org/zh-CN/scripts/431256/feedback // @match https://pan.xunlei.com/* // @exclude https://pan.xunlei.com/s* // @grant none // @require https://cdn.bootcdn.net/ajax/libs/limonte-sweetalert2/11.1.0/sweetalert2.all.min.js // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js // @require https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.8/clipboard.min.js // @downloadURL none // ==/UserScript== (function () { 'use strict'; const originFetch = fetch; var linkConfig; var reqHeaders, filesURL; var arryIndex; var fileArry; var filetxt; var temp_path; var running = { 'runStatus': false, 'successNum': 0, 'failNum': 0, 'exit': false, 'resultNum': 0, 'needHandle': true, } var $BleuButton, $bleu_config; function swalCloseFunc() { let local_path = $('#config_path').val(); let aria2 = { 'ip': $('#config_ip').val(), 'port': $('#config_port').val(), 'token': $('#config_token').val() }; let qualityAry = $('#bleu_select').val(); qualityAry = qualityAry === 'highlow' ? ['selected', ''] : ['', 'selected']; let checkAry = [], autoClick = { state: false, itemIndex: 0 }, itemcount = 0; let vDownload; $('.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; } }) if ($('.td-checkbox__inner.bleuvideo')[0].checked) { vDownload = true; checkAry[6] = 'checked' } else { vDownload = false; checkAry[6] = '' } localStorage.setItem("linkConfig", JSON.stringify({ 'local_path': local_path, 'displays': checkAry, 'aria2': aria2, 'quality': qualityAry, 'autoClick': autoClick, 'vDownload': vDownload, })); window.ariaNgUI&&window.ariaNgUI.close(); } var main = { addCssStyle() { let 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;color: #2670ea;font-size: 15px;} .bleu_a:hover{color: #3F85FE} .bleu_sa_footer{margin: 0;padding-top: 20px;} .bleu_sa_title_min{font-size: 20px;padding: 0;} .bleu_sa_popup_min{padding: 0 0 0;text-align-last: right;width: fit-content;} .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{margin: 0px 10px;font-size: 15px;} .bleu_inp{width:60%} .bleu_config_item p{text-align: left;margin: 0px 20px;} #bleu_select{margin: 0px 10px;background-color: #3F85FE;font-size: 15px;border: none;} `; let style = document.createElement('style'); style.innerHTML = cssStyle; document.querySelector('head').appendChild(style); }, addElements() { $BleuButton = $('
直链
'); $('div.pan-list-menu').prepend($BleuButton); $('.file-features-btns-wrap').length != 0 ? $('.file-features-btns-wrap').prepend($BleuButton) : $BleuButton; $bleu_config = $('
直链配置
') $('.bleu_config').length == 0 && $('#__nuxt').append($bleu_config); }, addButtonEvent() { $BleuButton.on('click', async function () { main.swalForInfo('==获取直链中,请等待==', '', 'center'); if (running.runStatus) { return } linkConfig = JSON.parse(localStorage.getItem("linkConfig")) || { 'local_path': 'D:\\Downloads', 'displays': ['checked', 'checked', 'checked', 'checked', 'checked', 'checked', ''], 'aria2': { 'ip': 'http://localhost', 'port': '16800', 'token': '' }, 'quality': ['selected', ''], 'vDownload': false, }; try { running.needHandle && await main.getAllInfo(); } catch (error) { console.log(error); main.swalForInfo('==请刷新页面重新尝试!==', '', 'center'); return; } let $swalHtml = $(`
按钮功能说明 `) let mainui = swal.fire({ title: `成功${running.successNum}条;失败${running.failNum}条`, html: $swalHtml, width: 400 + 'px', 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' }, }) $('.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); } }) $bleu_config.on('click', function () { linkConfig = JSON.parse(localStorage.getItem("linkConfig")) || { 'local_path': 'D:\\Downloads', 'displays': ['checked', 'checked', 'checked', 'checked', 'checked', 'checked', ''], 'aria2': { 'ip': 'http://localhost', 'port': '16800', 'token': '' }, 'quality': ['selected', ''], 'vDownload': false, }; let swalConfig = `
本地下载路径

功能按钮显示

配置aria2任务

播放列表设置

视频专用下载

` swal.fire({ title: `直链配置`, html: swalConfig, width: 400 + 'px', 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' }, }).then(swalCloseFunc) }) }, setInitValue() { arryIndex = 0; fileArry = []; filetxt = []; temp_path = ''; running.runStatus = true; running.successNum = 0; running.failNum = 0; running.resultNum = 0; running.needHandle = false; $('.pan-list-item').on('click', function () { running.needHandle = true; }) $('.pan-list-item a').on('click', function () { running.needHandle = true; }) $('.td-breadcrumb__item a').on('click', function () { running.needHandle = true; }) $('.td-checkbox__inner').on('click', function () { running.needHandle = true; }) }, async getAllInfo() { main.setInitValue(); await main.getFileSign(); if (running.exit) { running.exit = false; main.swalForInfo('==请刷新页面重新尝试!==', '', 'center'); return; } $('li.pan-list-item').each((index, item) => { if (item.getAttribute('class') === 'pan-list-item') { delete(fileArry[0][index]); } }); await main.getAllFiles(fileArry[0]); running.runStatus = false; running.resultNum = 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 += `\\${loopArry[index].name}`; await main.getFileSign(loopArry[index]); await main.getAllFiles(fileArry[arryIndex - 1]); } } } temp_path = temp_path.substring(0, temp_path.lastIndexOf('\\')); }, getFileSign(folder) { return new Promise((resolve, reject) => { let runURL; if (folder) { 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); } else { runURL = filesURL; } fileArry[arryIndex] = []; $.ajax({ type: "get", timeout: 2000, headers: reqHeaders, url: runURL, //dataType: "json", success: function (data, textStatus) { data.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++; resolve(textStatus); }, error: function (err) { runURL === filesURL ? running.exit = true : running.exit = false; reject(err); } }); }); }, getDirectLink(sign) { return new Promise((resolve, reject) => { $.ajax({ type: "get", timeout: 2000, headers: reqHeaders, url: `https://api-pan.xunlei.com/drive/v1/files/${sign}`, //dataType: "json", success: function (data, textStatus) { running.successNum++; let mediasLink = []; if (data.medias != []) { data.medias.forEach(function (item) { if (item.link != null) { mediasLink.push({ 'name': item.media_name, 'url': item.link.url }) } }) } let temp = { 'name': data.name, 'link': data.web_content_link, 'path': temp_path, 'medias': mediasLink }; filetxt.push(temp); resolve(textStatus); }, error: function (err) { running.failNum++; reject(err); } }); }); }, _downFlie(fnmae, data) { var elementA = document.createElement('a'); elementA.download = fnmae; elementA.style.display = 'none'; var blob = new Blob([data]); elementA.href = URL.createObjectURL(blob); document.body.appendChild(elementA); elementA.click(); document.body.removeChild(elementA); }, async getCollatedData(dataType) { if (running.resultNum === 0) { return; } if (dataType.match('aria2')) { main.swalForInfo('==基于aria2发送RPC任务中,请等待==', '', 'center'); } var swalTitle = ''; let nameLinkTxt = ''; var mediaIndex, selectedURL; if (dataType.match('播放')) { nameLinkTxt = '#EXTM3U\n' } filetxt.forEach(async (item) => { selectedURL = linkConfig.vDownload && item.medias.length > 0 ? item.medias[0].url : item.link; if (dataType.match('aria2')) { return } if (dataType.match('迅雷直链')) { nameLinkTxt += `${item.name}\n${selectedURL}\n`; } if (dataType.match('idman')) { nameLinkTxt += `idman /d "${selectedURL}" /p "${linkConfig.local_path}${item.path}" /f "${item.name}" /a&`; } if (dataType.match('curl')) { nameLinkTxt += `echo 正在下载这个文件:&echo "${linkConfig.local_path}${item.path}\\${item.name}"&curl -L "${selectedURL}" -o "${linkConfig.local_path}${item.path}\\${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('复制')) { new ClipboardJS('.btn_bleu.xdown', { text: function () { return nameLinkTxt; } }); main.swalForInfo('复制链接成功!', 1000, 'top-end'); } else if (dataType.match('aria2')) { swalTitle = `导入成功,请到aria2客户端查看任务!`; for (let index = 0; index < filetxt.length; index++) { try { selectedURL = linkConfig.vDownload && filetxt[index].medias.length > 0 ? filetxt[index].medias[0].url : filetxt[index].link; 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配置 } if(linkConfig.aria2.ip.match(/localhost|127.0.0.1/)){ await main.sendDataByRPC(index,selectedURL);//本地发送直接使用ariaNg也可以 } else{//远程发送 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); swalTitle.match('成功')?swalTitle = `导入失败,确认配置aria2没问题!`:swalTitle; break; } } main.swalForInfo(swalTitle, 3000, 'top-end'); } else { let filenam = `${dataType.replace('.txt','')}${(new Date()).valueOf()}.txt`; if (dataType.match('播放')) { filenam = `迅雷云盘播放列表.m3u`; } this._downFlie(filenam, nameLinkTxt); } }, swalForInfo(satitle, satime, saposition) { Swal.fire({ title: satitle, position: saposition, showConfirmButton: false, timer: satime, customClass: { title: 'bleu_sa_title_min', popup: 'bleu_sa_popup_min' } }) }, 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 new Promise((resolve, reject) => { $.ajax({ type: 'post', url: `${linkConfig.aria2.ip}:${linkConfig.aria2.port}/jsonrpc`, data: jsonData, //dataType: "json", success: function (textStatus) { resolve(textStatus); }, error: function (err) { reject(err); } }); }); }, hookFetch() { Object.defineProperty(window, "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) { filesURL = url; reqHeaders = options.headers; } return originFetch(url, options) } } }) }, initUI() { var observer = new MutationObserver(function (mutationsList) { for (let mutation of mutationsList) { if (mutation.type === 'childList') { if (mutation.target.querySelector('.pan-list-menu') && $('#bleu_btn').length == 0) { main.addElements(); main.addButtonEvent(); break; } } } }); observer.observe($('#__layout')[0], { childList: true, subtree: true, }); }, } window.onunload = ()=>{window.ariaNgUI&&window.ariaNgUI.close();}; main.hookFetch(); main.addCssStyle(); main.initUI(); })();