- // ==UserScript==
- // @name PotPlayer云盘-专供版
- // @namespace https://github.com/Bleu404/PotplayerPanVideoSV
- // @version 1.1.0
- // @description 此脚本为《PotPlayer播放云盘视频》姊妹篇,需配合MediaPlayParse - PanVideo.as脚本使用。在potplayer中选择画质、字幕,迅雷云盘增加原画,阿里云盘增加时长。
- // @author bleu
- // @compatible edge Tampermonkey
- // @compatible chrome Tampermonkey
- // @compatible firefox Tampermonkey
- // @license MIT
- // @match https://pan.xunlei.com/*
- // @match https://www.aliyundrive.com/*
- // @icon https://fastly.jsdelivr.net/gh/Bleu404/PRPO@latest/png/ppvsv.png
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_xmlhttpRequest
- // @grant GM_registerMenuCommand
- // @grant unsafeWindow
- // @connect *
- // @connect xunlei.com
- // @connect aliyundrive.com
- // @connect jianguoyun.com
- // @connect teracloud.jp
- // @require https://fastly.jsdelivr.net/npm/sweetalert2@11.1.0/dist/sweetalert2.all.min.js
- // @require https://fastly.jsdelivr.net/npm/bleutools@1.0.2/bleutools.min.js
- // ==/UserScript==
-
- (function () {
- 'use strict';
- const ORGXHRSRH = XMLHttpRequest.prototype.setRequestHeader;
- let bleuc,contextMenu, itemsInfo, arryIndex, Option, observer,cloud;
- const flieTypeStr = ".wmv,.rmvb,.avi,.mp4,.mkv,.flv,.swf.mpeg4,.mpeg2,.3gp,.mpga,.qt,.rm,.wmz,.wmd,.wvx,.wmx,.wm,.mpg,.mpeg,mov,.asf,.m4v,";
- const tools = {
- getCloudName() {
- switch (document.domain) {
- case 'xunlei.com':
- cloud = xunlei;
- break;
- case 'pan.xunlei.com':
- cloud = xunlei;
- break;
- case 'www.aliyundrive.com':
- cloud = aliyun;
- this.hookXHRHeader();
- break;
- }
- },
- checkFileType(name) {
- let type = name.toLowerCase().substring(name.lastIndexOf('.')) || "bleu"
- return flieTypeStr.indexOf(`${type},`) >= 0 ? true : false
- },
- async putFileInWebdav(name, info) {
- let header = {
- "authorization": `Basic ${btoa(`${bleuc.cun}:${bleuc.cpw}`)}`
- }
- let url = `https://${bleuc.cip}/PanPlaylist`;
- let method = bleuc.cip.indexOf('teracloud')>0?'GET':'PROPFIND';
- await bleu.XHR(method, url, undefined, header, undefined).then( () => {}
- ,async()=>{await bleu.XHR('MKCOL', url, undefined, header, undefined)})
- url = `https://${bleuc.cip}/PanPlaylist/${name}`;
- await bleu.XHR('PUT',url , info, header, 'xml').then(() => {
- bleu.swalInfo(`✅${name}`, 3000, 'center');
- }, () => bleu.swalInfo(`❌${name}`, 3000, 'center'))
- },
- checkConfig() {
- bleuc = JSON.parse(GM_getValue('bleuc') || null) || {cip: '',cun: '',cpw: ''};
- if (!(bleuc.cip != '' && bleuc.cun != '' && bleuc.cpw != '')) {
- bleu.swalInfo(`❗请先设置WEBDAV`, '', 'center')
- return false
- }
- return true
- },
- saveConfig() {
- let temp = document.querySelector('#cip').value.trim()
- temp = temp.charAt(temp.length - 1) === '/' ? temp.substring(0, temp.length - 1) : temp
- temp = temp.indexOf('https://') < 0 ? temp : temp.replace('https://', '')
- GM_setValue("bleuc", JSON.stringify({
- 'cip': temp,
- 'cun': document.querySelector('#cun').value.trim(),
- 'cpw': document.querySelector('#cpw').value.trim(),
- }));
- },
- configHtml() {
- bleuc = JSON.parse(GM_getValue('bleuc') || null) || {cip: '',cun: '',cpw: ''};
- let html = `
- <div class="bleuc_config_item"><p>
- <div><label>主机:</label><input type="text" class="bleuc_inp" id="cip" value="${bleuc.cip}"/></div>
- <div><label>用户:</label><input type="text" class="bleuc_inp" id="cun" value="${bleuc.cun}"/></div>
- <div><label>密码:</label><input type="text" class="bleuc_inp" id="cpw" value="${bleuc.cpw}"/></div></p></div>
- `;
- return html;
- },
- hookXHRHeader() {
- XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
- if(header == "x-signature"){
- aliyun._signature=value;
- }
- return ORGXHRSRH.apply(this, arguments);
- }
- },
- cssStyle: `
- .bleuc_config_item{border-radius: 10px;font-size: 20px;margin: 12px 50px;color: #fff;background: linear-gradient(45deg,#12c2e9, #c471ed, #f64f59);box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);}
- .bleuc_config_item label{font-size: 15px}
- .bleuc_config_item input.bleuc_inp{margin: 0px 10px;font-size: 15px;background: linear-gradient(45deg,#12c2e9, #c471ed, #f64f59);border-style:none;color:black;width:200px}
- .bleuc_config_item p{text-align: left;margin: 0px 20px;}`,
-
- }
- const xunlei = {
- addTag() {
- if (contextMenu.innerText.match(/PotPlayer/)) return
- let ul = document.createElement('ul');
- ul.innerHTML = `<a id="bleuReSave" class="pan-dropdown-menu-item">PotPlayer打开</a>`;
- contextMenu.firstChild.prepend(ul.firstChild);
- main.addClickEvent();
- },
- getselectFilesInfo() {
- let temp = document.querySelectorAll('li.SourceListItem__item--XxpOC.SourceListItem__active--4U0f4');
- temp.forEach((item) => {
- this._pushItem(item.__vue__.info);
- })
- },
- async updateFile(item) {
- Option["list"].push({
- "title": item.name,
- "url": `https://api-pan.xunlei.com/drive/v1/files/${item.id}`
- });
- },
- async openNextDir(item) {
- let url = `https://api-pan.xunlei.com/drive/v1/files?limit=100&parent_id=${item.id}&filters={"phase":{"eq":"PHASE_TYPE_COMPLETE"},"trashed":{"eq":false}}&with_audit=true`;
- await bleu.XHR('GET', url, undefined, Option.header).then((res) => {
- arryIndex++;
- res.files.forEach((item) => {
- xunlei._pushItem(item);
- })
- },()=>{
- bleu.swalInfo("❗进出目录之后重新转存", '', 'center');
- throw "PPVSV:迅雷-超时,重新转存";
- })
- },
- findContext(node) {
- if (node.className === 'pan-content') {
- node = node.querySelector('div.pan-dropdown-menu.context-menu');
- if (!node) return;
- contextMenu = node;
- xunlei.addTag();
- }
- },
- closeMenu() {},
- _pushItem(temp) {
- if (!itemsInfo[arryIndex]) itemsInfo[arryIndex] = [];
- if (temp.kind === 'drive#file' && !tools.checkFileType(temp.name)) return
- let itemInfo = {
- 'id': temp.id,
- 'isdir': temp.kind === 'drive#file' ? false : true,
- 'name': temp.name,
- };
- itemsInfo[arryIndex].push(itemInfo);
- },
- getHeaderInfo() {
- Option.header = {};
- Option.header.withCredentials = false;
- Option.header['content-type'] = 'application/json';
- for (let key in localStorage) {
- let temp = localStorage.getItem(key)
- if (key.indexOf('credentials') === 0) {
- Option.header["Authorization"] = JSON.parse(temp).token_type + ' ' + JSON.parse(temp).access_token;
- Option.header["token_type"] = JSON.parse(temp).token_type;
- Option.header["access_token"] = JSON.parse(temp).access_token;
- Option.header["refresh_token"] = JSON.parse(temp).refresh_token;
- Option["clientid"] = key.substring(key.indexOf('_') + 1);
- }
- if (key.indexOf('captcha') === 0)
- Option.header['x-captcha-token'] = JSON.parse(temp).token
- if (key === 'deviceid')
- Option.header['x-device-id'] = temp.substring(temp.indexOf('.') + 1, 32 + temp.indexOf('.') + 1)
- }
- },
- async finallyFunc() {
- Option.header["clientid"] = Option["clientid"];
- await tools.putFileInWebdav('panvideo.txt', JSON.stringify(Option));
- unsafeWindow.location.href = `potplayer://panvideo##xunlei##https://${bleuc.cip}/PanPlaylist/panvideo.txt##${bleuc.cun}##${bleuc.cpw}`;
- }
- }
- const aliyun = {
- addTag() {
- if (contextMenu.innerText.match(/PotPlayer|新建/)) return
- let ul = document.createElement('ul');
- ul.innerHTML = `<li id="bleuReSave" class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child" role="menuitem"><div class="outer-menu--ihDUR"><div data-confirm="false" class="menu-wrapper--1ZYh_" data-spm-anchor-id="aliyundrive.drive.0.i11.40516c75ahPUGN"><div class="menu-name--1F5vk" data-spm-anchor-id="aliyundrive.drive.0.i12.40516c75ahPUGN">PotPlayer打开</div></div></div></li>`;
- contextMenu.prepend(ul.firstChild);
- main.addClickEvent();
- },
- getselectFilesInfo() {
- let temp = document.querySelectorAll('div[data-index]')
- let attrName;
- for(let attr in temp[0]){
- if(attr.indexOf('__reactFiber')==0){
- attrName = attr;
- break;
- }
- }
- temp.forEach((item)=>{
- if(item.querySelector('input')&&item.querySelector('input').checked){
- let value = item[attrName].return.pendingProps;
- aliyun._pushItem(value.data[value.index]||value.data[value.rowIndex][value.columnIndex]);
- }
- })
-
- },
- async updateFile(item) {
- Option["list"].push({
- "title": item.name,
- "url": "https://"+item.id
- });
- },
- async openNextDir(item) {
- let url = `https://api.aliyundrive.com/adrive/v3/file/list?jsonmask=next_marker%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Ccreated_at%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cstarred%2Cthumbnail%2Curl%2Cstreams_info%2Ccontent_hash%2Cuser_tags%2Ctrashed%2Cvideo_media_metadata%2Cvideo_preview_metadata)`,
- token = JSON.parse(localStorage.getItem('token')),
- data = {
- 'drive_id': token.default_drive_id,
- 'parent_file_id': item.id,
- 'limit': 100,
- },
- header = {
- 'x-canary': 'client=web,app=adrive,version=v2.4.0',
- 'x-device-id': document.cookie.match(/cna=([^;]*)/)[1],
- authorization: `${token.token_type} ${token.access_token}`,
- 'x-signature':this._signature
- };
- await bleu.XHR('POST', url, JSON.stringify(data),header).then((res) => {
- arryIndex++;
- res.items.forEach((item)=>{
- aliyun._pushItem(item);
- },()=>{
- bleu.swalInfo("🔴💬刷新页面,重新获取", '', 'center');
- throw "PPVSV:阿里-超时,重新转存";
- })
- })
- },
- _signature:'',
- findContext(node) {
- node = document.querySelector('ul.ant-dropdown-menu');
- if (!node) return;
- //observer.disconnect();
- contextMenu = node;
- aliyun.addTag();
- },
- closeMenu(){
- contextMenu.parentNode.className='ant-dropdown dropdown-menu--1KRbu ant-dropdown-placement-bottomLeft ant-dropdown-hidden';
- contextMenu.parentNode.style.left='-578px';
- contextMenu.parentNode.style.top='-646px';
- },
- _pushItem(temp) {
- if(!itemsInfo[arryIndex]) itemsInfo[arryIndex]= [];
- if (temp.type==='file'&&temp.category!="video") return
- let itemInfo = {
- 'id': temp.fileId||temp.file_id,
- 'isdir': temp.type === 'file' ? false : true,
- 'name': temp.name,
- };
- itemsInfo[arryIndex].push(itemInfo);
- },
- getHeaderInfo() {
- Option.header ={};
- let token = JSON.parse(localStorage.getItem('token'));
- Option.header["authorization"] =`${token.token_type} ${token.access_token}`;
- Option.header["drive_id"] =token.default_drive_id;
- Option.header["x-signature"]=this._signature;
- Option.header["x-device-id"]=document.cookie.match(/cna=([^;]*)/)[1];//decodeURIComponent(localStorage.getItem('APLUS_CNA').substring(9))
- },
- async finallyFunc(){
- await tools.putFileInWebdav('panvideo.txt', JSON.stringify(Option));
- unsafeWindow.location.href = `potplayer://panvideo##aliyun##https://${bleuc.cip}/PanPlaylist/panvideo.txt##${bleuc.cun}##${bleuc.cpw}`;
- }
- }
- const main = {
- init() {
- observer = new MutationObserver(function (mutations) {
- for (let mutation of mutations) {
- if (mutation.type === 'childList') {
- cloud.findContext(mutation.target);
- }
- }
- });
- observer.observe(document, {
- 'childList': true,
- 'subtree': true
- });
- },
- addClickEvent() {
- let bleuButton = document.getElementById('bleuReSave');
- bleuButton.addEventListener('click', async function () {
- itemsInfo = [];
- arryIndex = 0;
- Option = {}, Option["list"] = [];
- if(!tools.checkConfig())return;
- cloud.closeMenu();
- cloud.getselectFilesInfo();
- cloud.getHeaderInfo();
- if (!itemsInfo[arryIndex]||itemsInfo[arryIndex].length === 0) {
- bleu.swalInfo(`❌未选择文件转存!`, 3000, 'center')
- return;
- }
- try {
- await main.updateAllFiles(itemsInfo[arryIndex]);
- } catch (e) {
- console.log(e);
- return;
- }
- Option["list"].length!=0&&cloud.finallyFunc();
- })
- },
- async updateAllFiles(loopArry) {
- for (let index = 0; index < loopArry.length; index++) {
- if (!loopArry[index].isdir) {
- await cloud.updateFile(loopArry[index]);
- } else {
- await cloud.openNextDir(loopArry[index]);
- await main.updateAllFiles(itemsInfo[arryIndex]);
- }
- bleu.sleep(800);
- }
- },
- };
- tools.getCloudName();
- //tools.checkConfig();
- bleu.addCssStyle(tools.cssStyle);
- GM_registerMenuCommand('配置WEBDAV', () => {
- bleu.swalUI('WEBDAV', tools.configHtml(), '400px').then(tools.saveConfig)
- }, 'w')
- main.init();
- })();