PotPlayer播放云盘视频

支持🐱‍💻百度网盘(720p)、🐱‍👤迅雷云盘(720p)、🐱‍🏍阿里云盘(1080p)👉右键👈导入播放信息到webdav网盘;支持劫持自定义匹配网站的m3u文件导入webdav网盘。PotPlayer实现🥇倍速、🏆无边框、更换解码器、渲染器等功能。

Installer dette script?
Skaberens foreslåede script

Du vil måske også kunne lide PotPlayer云盘-专供版

Installer dette script
  1. // ==UserScript==
  2. // @name PotPlayer播放云盘视频
  3. // @namespace https://greasyfork.org/zh-CN/users/798733-bleu
  4. // @version 1.2.7
  5. // @description 支持🐱‍💻百度网盘(720p)、🐱‍👤迅雷云盘(720p)、🐱‍🏍阿里云盘(1080p)👉右键👈导入播放信息到webdav网盘;支持劫持自定义匹配网站的m3u文件导入webdav网盘。PotPlayer实现🥇倍速、🏆无边框、更换解码器、渲染器等功能。
  6. // @author bleu
  7. // @compatible edge Tampermonkey
  8. // @compatible chrome Tampermonkey
  9. // @compatible firefox Tampermonkey
  10. // @license MIT
  11. // @match http*://pan.baidu.com/*
  12. // @match http*://yun.baidu.com/*
  13. // @match https://pan.xunlei.com/*
  14. // @match https://www.aliyundrive.com/*
  15. // @icon https://fastly.jsdelivr.net/gh/Bleu404/PRPO@latest/png/ppv.png
  16. // @grant GM_setValue
  17. // @grant GM_getValue
  18. // @grant GM_xmlhttpRequest
  19. // @grant GM_registerMenuCommand
  20. // @grant unsafeWindow
  21. // @connect *
  22. // @connect xunlei.com
  23. // @connect aliyundrive.com
  24. // @connect jianguoyun.com
  25. // @connect teracloud.jp
  26. // @run-at document-body
  27. // @require https://fastly.jsdelivr.net/npm/sweetalert2@11.1.0/dist/sweetalert2.all.min.js
  28. // @require https://fastly.jsdelivr.net/npm/bleutools@1.0.2/bleutools.min.js
  29. // ==/UserScript==
  30. (function () {
  31. 'use strict';
  32. const ORGXHRSRH = XMLHttpRequest.prototype.setRequestHeader;
  33. let bleuc,
  34. contextMenu,
  35. itemsInfo,
  36. arryIndex,
  37. tempPath,
  38. flag,Option,observer,cloud,
  39. isCheckWebdav = true,
  40. m3u8File = "#EXTM3U",
  41. flieTypeStr = ".wmv,.rmvb,.avi,.mp4,.mkv,.flv,.swf.mpeg4,.mpeg2,.3gp,.mpga,.qt,.rm,.wmz,.wmd,.wvx,.wmx,.wm,.mpg,.mpeg,mov,.asf,.m4v,.ts,";
  42. const tools = {
  43. getCloudName() {
  44. switch (document.domain) {
  45. case 'pan.baidu.com':
  46. cloud = baidu;
  47. break;
  48. case 'yun.baidu.com':
  49. cloud = baidu;
  50. break;
  51. case 'xunlei.com':
  52. cloud = xunlei;
  53. break;
  54. case 'pan.xunlei.com':
  55. cloud = xunlei;
  56. break;
  57. case 'www.aliyundrive.com':
  58. cloud = aliyun;
  59. break;
  60. default:
  61. cloud = others;
  62. }
  63. },
  64. checkFileType(name) {
  65. let type = name.toLowerCase().substring(name.lastIndexOf('.'))||"bleu"
  66. return flieTypeStr.indexOf(`${type},`) >= 0 ? true : false
  67. },
  68. async addDavDir(){
  69. if(flag==='xunlei'||flag==='aliyun')return
  70. await tools.checkPath();
  71. await this._addDir(`https://${bleuc.cip}/PanPlaylist/${flag}${tempPath}`)
  72. },
  73. async _addDir(url){
  74. let header = {
  75. "authorization": `Basic ${btoa(`${bleuc.cun}:${bleuc.cpw}`)}`
  76. }
  77. let method = bleuc.cip.indexOf('teracloud')>0?'GET':'PROPFIND';
  78. await bleu.XHR(method, url, undefined, header, undefined).then(async() => {
  79. }, async() => {
  80. await bleu.XHR('MKCOL', url, undefined, header, undefined);
  81. })
  82. },
  83. async checkPath(){
  84. let url = `https://${bleuc.cip}/PanPlaylist/`;
  85. if (isCheckWebdav) {
  86. isCheckWebdav = false;
  87. await this._addDir(url);
  88. url = `https://${bleuc.cip}/PanPlaylist/${flag}/`
  89. await this._addDir(url);
  90. }
  91. },
  92. async putFileInWebdav(name, info) {
  93. let header = {
  94. "authorization": `Basic ${btoa(`${bleuc.cun}:${bleuc.cpw}`)}`
  95. }
  96. if(info === '#EXTM3U')return
  97. await tools.checkPath();
  98. await bleu.XHR('PUT', `https://${bleuc.cip}/PanPlaylist/${flag}${tempPath}/${name}`, info, header, 'xml').then((res) => {
  99. bleu.swalInfo(`✅${name}`, 3000, 'center');
  100. }, () => bleu.swalInfo(`❌${name}`, 3000, 'center'));
  101. },
  102. checkConfig(){
  103. bleuc = JSON.parse(GM_getValue('bleuc')||null)||{cip:'',cun:'',cpw:'',cbdqs:'bd720',cxlqs:'xl0',calqs:'FHD'}
  104. if(!(bleuc.cip!=''&&bleuc.cun!=''&&bleuc.cpw!='')){
  105. bleu.swalInfo(`❗请先设置WEBDAV画质`, '', 'center')
  106. return false
  107. }
  108. return true
  109. },
  110. saveConfig(){
  111. let temp =document.querySelector('#cip').value.trim()
  112. temp = temp.charAt(temp.length-1)==='/'?temp.substring(0,temp.length-1):temp
  113. temp = temp.indexOf('https://')<0?temp:temp.replace('https://','')
  114. GM_setValue("bleuc", JSON.stringify({
  115. 'cip': temp,
  116. 'cun': document.querySelector('#cun').value.trim(),
  117. 'cpw': document.querySelector('#cpw').value.trim(),
  118. 'cbdqs': document.querySelector('#cbdqs').value,
  119. 'cxlqs': document.querySelector('#cxlqs').value,
  120. 'calqs': document.querySelector('#calqs').value,
  121. }));
  122. },
  123. configHtml(){
  124. bleuc = JSON.parse(GM_getValue('bleuc')||null)||{cip:'',cun:'',cpw:'',cbdqs:'bd720',cxlqs:'xl0',calqs:'FHD'}
  125. let html = `
  126. <div class="bleuc_config_item"><b>WEBDAV</b><p>
  127. <div><label>主机:</label><input type="text" class="bleuc_inp" id="cip" value="${bleuc.cip}"/></div>
  128. <div><label>用户:</label><input type="text" class="bleuc_inp" id="cun" value="${bleuc.cun}"/></div>
  129. <div><label>密码:</label><input type="text" class="bleuc_inp" id="cpw" value="${bleuc.cpw}"/></div></p></div>
  130. <div class="bleuc_config_item"><b>画质</b><p>
  131. <label>百度网盘:</label><select class="bleuc_sel" id="cbdqs">
  132. <option value="bd1080">1080p</option>
  133. <option value="bd720">720p</option>
  134. <option value="bd480">480p</option>
  135. <option value="bd360">360p</option></select>
  136. <label>迅雷云盘:</label><select class="bleuc_sel" id="cxlqs">
  137. <option value="xl0">从高到低</option>
  138. <option value="xl1">从低到高</option></select>
  139. <label>阿里云盘:</label><select class="bleuc_sel" id="calqs">
  140. <option value="FHD">1080p</option>
  141. <option value="HD">720p</option>
  142. <option value="SD">540p</option>
  143. <option value="LD">360p</option></select></p></div>
  144. `
  145. //bleuc.cbdqs?bleuc.cbdqs:bleuc.cbdqs='FHD';
  146. return html.replace(`${bleuc.cbdqs}\"`,`${bleuc.cbdqs}\" selected`)
  147. .replace(`${bleuc.cxlqs}\"`,`${bleuc.cxlqs}\" selected`)
  148. .replace(`${bleuc.calqs}\"`,`${bleuc.calqs}\" selected`)
  149. },
  150. cssStyle:`
  151. .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);}
  152. .bleuc_config_item label{font-size: 15px}
  153. .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}
  154. .bleuc_config_item p{text-align: left;margin: 0px 20px;}
  155. .bleuc_sel{margin: 0px 10px;background: linear-gradient(45deg,#12c2e9, #c471ed, #f64f59);font-size: 15px;border: none;color:black;width:160px}`,
  156.  
  157. }
  158. const baidu = {
  159. hostname(){
  160. flag = 'baidu';
  161. baidu._isNew = location.href.indexOf('/disk/main') > 0?true:false;
  162. },
  163. addTag() {
  164. if (contextMenu.firstChild.innerText.match(/转存播放信息|查看/)) return
  165. let ul = document.createElement('ul');
  166. baidu._isNew?ul.innerHTML = `<div id="bleuReSave" class="wp-s-ctx-menu__item cursor-p is-has-icon"><p><img src="https://fastly.jsdelivr.net/gh/Bleu404/PRPO@latest/png/ppv16.png"/><span class="wp-s-ctx-menu__item-text">转存播放信息</span></p></div>`
  167. :ul.innerHTML = `<li id="bleuReSave"><em class="icon"><img src="https://fastly.jsdelivr.net/gh/Bleu404/PRPO@latest/png/ppv16.png"/></em>转存播放信息</li>`;
  168. contextMenu.firstChild.prepend(ul.firstChild);
  169. main.addClickEvent();
  170. },
  171. getselectFilesInfo() {
  172. let temp;
  173. if(baidu._isNew){
  174. temp = [];
  175. let collection = document.querySelector('.wp-s-pan-table__body.mouse-choose-list').__vue__.canSelectListMap;
  176. document.querySelectorAll('.wp-s-pan-table__body-row.mouse-choose-item.selected').forEach(i=>{
  177. temp.push(collection[i.getAttribute('data-id')].item);
  178. })
  179. }else{
  180. temp = require('system-core:context/context.js').instanceForSystem.list.getSelected();
  181. }
  182. baidu._pushItem(temp);
  183. },
  184. async updateFile(item) {
  185. let streamUrl = `https://${location.host}/api/streaming?path=${encodeURIComponent(item.id)}&app_id=250528&clienttype=0&type=M3U8_AUTO_${bleuc.cbdqs.substring(2)}&vip=2&isplayer=0&check_blue=1`;
  186. await bleu.XHR('GET', streamUrl, undefined, {
  187. withCredentials: true
  188. },'txt').then(async(res) => {
  189. await tools.putFileInWebdav(item.name, res);
  190. }, () => {
  191. bleu.swalInfo(`❌${item.name}`, 3000, 'center') ;
  192. })
  193. },
  194. async openNextDir(item) {
  195. let listUrl = `https://${location.host}/api/list?order=name&desc=0&showempty=0&web=1&page=1&num=100&dir=${encodeURIComponent(item.id)}&channel=chunlei&web=1&app_id=250528&clienttype=0`;
  196. await bleu.XHR('GET', listUrl, undefined, {
  197. withCredentials: true
  198. }).then((res) => {
  199. arryIndex++;
  200. baidu._pushItem(res.list);
  201. })
  202. },
  203. findContext(node) {
  204. if (baidu._isNew) {
  205. node = document.querySelectorAll('.ctx-menu-container')[4];
  206. if (!(node&&node.querySelector('.wp-s-ctx-menu__item.cursor-p'))) return;
  207. contextMenu = node;
  208. baidu.addTag();
  209. }
  210. else if(node.className ==='context-menu'){
  211. observer.disconnect();
  212. contextMenu = node;
  213. baidu.addTag();
  214. }
  215. },
  216. closeMenu(){
  217. if(!baidu._isNew)contextMenu.firstChild.style.display = "none"
  218. else contextMenu.__vue__.hideMenu()
  219. },
  220. _pushItem(temp) {
  221. itemsInfo[arryIndex] = [];
  222. temp.forEach(item => {
  223. if (item.isdir === 0 && !tools.checkFileType(item.server_filename)) return
  224. let itemInfo = {
  225. 'id': item.path,
  226. 'isdir': item.isdir === 1 ? true : false,
  227. 'name': item.server_filename,
  228. };
  229. itemsInfo[arryIndex].push(itemInfo);
  230. });
  231. },
  232.  
  233. _isNew:false,
  234.  
  235. finallyFunc(){unsafeWindow.location.href = `potplayer://`;}
  236. }
  237. const xunlei = {
  238. hostname(){
  239. flag = 'xunlei'
  240. },
  241. addTag() {
  242. if (contextMenu.innerText.indexOf('转存')===0) return
  243. let ul = document.createElement('ul');
  244. ul.innerHTML = `<a id="bleuReSave" class="pan-dropdown-menu-item">转存播放信息</a>`;
  245. contextMenu.firstChild.prepend(ul.firstChild);
  246. main.addClickEvent();
  247. },
  248. getselectFilesInfo() {
  249. let temp = document.querySelectorAll('li.SourceListItem__item--XxpOC.SourceListItem__active--4U0f4');
  250. temp.forEach((item)=>{
  251. this._pushItem(item.__vue__.info);
  252. })
  253. },
  254. async updateFile(item) {
  255. let url = `https://api-pan.xunlei.com/drive/v1/files/${item.id}`;
  256. await bleu.XHR('GET', url, undefined,Option.header).then((res) => {
  257. let temp=[];
  258. res.medias.forEach((item)=>{
  259. if (item.link != null) {
  260. temp.push(item.media_name === '原始画质' ? res.web_content_link : item.link.url)}
  261. })
  262. url = bleuc.cxlqs === 'xl0'?temp[0]:temp[temp.length-1];
  263. m3u8File=m3u8File.replace('#EXTM3U',`#EXTM3U\n#EXTINF:-1 ,${item.name}\n${url}`)
  264. }, () => {
  265. bleu.swalInfo("❗进出目录之后重新转存", '', 'center');
  266. throw "PPV:迅雷-文件超时,重新转存";
  267. })
  268. },
  269. async openNextDir(item) {
  270. 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`;
  271. await bleu.XHR('GET', url, undefined,Option.header).then((res) => {
  272. arryIndex++;
  273. res.files.forEach((item)=>{
  274. xunlei._pushItem(item);
  275. })
  276. }, () => {
  277. bleu.swalInfo("❗进出目录之后重新转存", '', 'center');
  278. throw "PPV:迅雷-文件夹超时,重新转存";
  279. })
  280. },
  281. findContext(node) {
  282. if (node.className === 'pan-content') {
  283. node = node.querySelector('div.pan-dropdown-menu.context-menu');
  284. if(!node)return;
  285. this._getHeaderInfo();
  286. contextMenu = node;
  287. xunlei.addTag();
  288. }
  289. },
  290. closeMenu(){
  291. },
  292. _pushItem(temp) {
  293. if(!itemsInfo[arryIndex]) itemsInfo[arryIndex]= [];
  294. if (temp.kind === 'drive#file' && !tools.checkFileType(temp.name)) return
  295. let itemInfo = {
  296. 'id': temp.id,
  297. 'isdir': temp.kind === 'drive#file' ? false : true,
  298. 'name': temp.name,
  299. };
  300. itemsInfo[arryIndex].push(itemInfo);
  301. },
  302. _getHeaderInfo(){
  303. Option={},Option.header={};
  304. Option.header.withCredentials=false;
  305. Option.header['content-type']='application/json';
  306. for (let key in localStorage) {
  307. let temp = localStorage.getItem(key)
  308. if(key.indexOf('credentials')===0){
  309. Option.header.Authorization = JSON.parse(temp).token_type+' '+JSON.parse(temp).access_token;
  310. Option.clientid = key.substring(key.indexOf('_')+1);
  311. }
  312. if(key.indexOf('captcha')===0)
  313. Option.header['x-captcha-token']=JSON.parse(temp).token
  314. if(key==='deviceid')
  315. Option.header['x-device-id'] = temp.substring(temp.indexOf('.')+1,32+temp.indexOf('.')+1)
  316. }
  317. },
  318. async finallyFunc(){
  319. await tools.putFileInWebdav('Playlist.m3u', m3u8File);
  320. unsafeWindow.location.href = `potplayer://https://${encodeURIComponent(bleuc.cun)}:${bleuc.cpw}@${bleuc.cip}/PanPlaylist/xunlei/Playlist.m3u`;
  321. }
  322. }
  323. const aliyun = {
  324. hostname(){
  325. flag = 'aliyun';
  326. this.hookXHRHeader();
  327. },
  328. addTag() {
  329. if (contextMenu.innerText.match(/转存播放信息|新建/)) return
  330. let ul = document.createElement('ul');
  331. 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">转存播放信息</div></div></div></li>`;
  332. contextMenu.prepend(ul.firstChild);
  333. main.addClickEvent();
  334. },
  335. getselectFilesInfo() {
  336. let temp = document.querySelectorAll('div[data-index]')
  337. let attrName;
  338. for(let attr in temp[0]){
  339. if(attr.indexOf('__reactFiber')==0){
  340. attrName = attr;
  341. break;
  342. }
  343. }
  344. temp.forEach((item)=>{
  345. if(item.querySelector('input')&&item.querySelector('input').checked){
  346. let value = item[attrName].return.pendingProps;
  347. aliyun._pushItem(value.data[value.index]||value.data[value.rowIndex][value.columnIndex]);
  348. }
  349. })
  350. },
  351. async updateFile(item) {
  352. let url = `https://api.aliyundrive.com/v2/file/get_video_preview_play_info`,
  353. token = JSON.parse(localStorage.getItem('token')),
  354. data = {
  355. category: "live_transcoding",
  356. 'drive_id': token.default_drive_id,
  357. 'file_id': item.id,
  358. 'template_id': ""
  359. },
  360. header = {
  361. 'x-canary': 'client=web,app=adrive,version=v2.4.0',
  362. 'x-device-id': document.cookie.match(/cna=([^;]*)/)[1],
  363. authorization: `${token.token_type} ${token.access_token}`,
  364. 'x-signature':this._signature
  365. };
  366. await bleu.XHR('POST', url, JSON.stringify(data), header).then((res) => {
  367. let temp = res.video_preview_play_info.live_transcoding_task_list;
  368. url =temp.find((item)=>item.template_id===bleuc.calqs)?temp.find((item)=>item.template_id===bleuc.calqs).url:temp[temp.length-1].url;
  369. m3u8File+=`\n#EXTINF:-1 ,${item.name}\n#EXTVLCOPT:http-referrer=https://www.aliyundrive.com/\n${url}`;
  370. }, () => {
  371. bleu.swalInfo("🔴💬刷新页面,重新获取", '', 'center');
  372. throw "PPV:阿里-文件超时,重新转存";
  373. })
  374. },
  375. async openNextDir(item) {
  376. 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)`,
  377. token = JSON.parse(localStorage.getItem('token')),
  378. data = {
  379. 'drive_id': token.default_drive_id,
  380. 'parent_file_id': item.id,
  381. 'limit': 100,
  382. },
  383. header = {
  384. 'x-canary': 'client=web,app=adrive,version=v2.4.0',
  385. 'x-device-id': document.cookie.match(/cna=([^;]*)/)[1],
  386. authorization: `${token.token_type} ${token.access_token}`,
  387. 'x-signature':this._signature
  388. };
  389. await bleu.XHR('POST', url, JSON.stringify(data),header).then((res) => {
  390. arryIndex++;
  391. res.items.forEach((item)=>{
  392. aliyun._pushItem(item);
  393. }, () => {
  394. bleu.swalInfo("🔴💬刷新页面,重新获取", '', 'center');
  395. throw "PPV:阿里-文件夹超时,重新转存";
  396. })
  397. })
  398. },
  399. findContext(node) {
  400. node = document.querySelector('ul.ant-dropdown-menu');
  401. if (!node) return;
  402. //observer.disconnect();
  403. contextMenu = node;
  404. aliyun.addTag();
  405. },
  406. closeMenu(){
  407. contextMenu.parentNode.className='ant-dropdown dropdown-menu--1KRbu ant-dropdown-placement-bottomLeft ant-dropdown-hidden';
  408. contextMenu.parentNode.style.left='-578px';
  409. contextMenu.parentNode.style.top='-646px';
  410. },
  411. _pushItem(temp) {
  412. if(!itemsInfo[arryIndex]) itemsInfo[arryIndex]= [];
  413. if (temp.type==='file'&&temp.category!="video") return
  414. let itemInfo = {
  415. 'id': temp.fileId||temp.file_id,
  416. 'isdir': temp.type === 'file' ? false : true,
  417. 'name': temp.name,
  418. };
  419. itemsInfo[arryIndex].push(itemInfo);
  420. },
  421. _signature:'',
  422. hookXHRHeader() {
  423. XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
  424. if(header == "x-signature"){
  425. aliyun._signature=value;
  426. }
  427. return ORGXHRSRH.apply(this, arguments);
  428. }
  429. },
  430. async finallyFunc(){
  431. await tools.putFileInWebdav('Playlist.m3u', m3u8File);
  432. unsafeWindow.location.href = `potplayer://https://${encodeURIComponent(bleuc.cun)}:${bleuc.cpw}@${bleuc.cip}/PanPlaylist/aliyun/Playlist.m3u`;
  433. }
  434. }
  435. const others = {
  436. hostname() {
  437. flag ='others' ;
  438. tempPath='/'+location.hostname.replace('www.','')
  439. itemsInfo=[];
  440. const oriXSend = XMLHttpRequest.prototype.send;
  441.  
  442. XMLHttpRequest.prototype.send = function () {
  443. others._onLoad(this);
  444. return oriXSend.apply(this, arguments);
  445. }
  446. },
  447. _onLoad(xhr) {
  448. xhr.addEventListener("load", async function () {
  449. if (others._watchM3u&&xhr.readyState == 4 && xhr.status >= 200&&xhr.status < 300) {
  450. if (typeof (xhr.response) === 'string'&&xhr.responseURL.match(/^http/)) {
  451. if (xhr.response.indexOf('#EXTM3U') === 0) { //通用
  452. observer.disconnect();
  453. itemsInfo.push(xhr.responseURL);
  454. others._getHtmlMenu();
  455. } else if (tempPath === '/agemys.com' && xhr.response.match('http.*mp4')) { //age动漫
  456. observer.disconnect();
  457. itemsInfo.push(decodeURIComponent(xhr.response.match('http.*mp4')[0]));
  458. others._getHtmlMenu();
  459. }
  460. }
  461. }
  462. });
  463. },
  464. findContext(node) {
  465. if ((node.tagName == 'VIDEO' || node.tagName == 'IFRAME')&&node.getAttribute('src')&&
  466. node.getAttribute('src').match(/http.*mp4/)) {
  467. observer.disconnect()
  468. this._watchM3u=false;
  469. itemsInfo.push(node.getAttribute('src'));
  470. others._getHtmlMenu();
  471. }
  472. },
  473. _getHtmlMenu() {
  474. if (this._onceEnough) return
  475. GM_registerMenuCommand('转存页面m3u文件',()=>{this._saveas()}, 'm');
  476. document.addEventListener("keydown", (e)=>{
  477. if (e.key == "z" && e.altKey) {
  478. this._saveas()
  479. }
  480. })
  481. this._onceEnough = true;
  482. },
  483. _saveas(){
  484. if (itemsInfo.length === 0) {
  485. bleu.swalInfo(`❌没有加载m3u文件,等一会再尝试!`, 3000, 'center')
  486. return;
  487. }
  488. bleu.swalUI('转存页面m3u文件', this._html(), '550px');
  489. let nameIPT = document.querySelector('#bleu_name');
  490. nameIPT.select();
  491. nameIPT.focus();
  492. nameIPT.addEventListener('keypress',(e)=>{
  493. e.keyCode == 13&&document.querySelector('#saveas').click();
  494. })
  495. document.querySelector('#saveas').addEventListener('click', async () => {
  496. m3u8File = "#EXTM3U";
  497. if(!this._direxit){
  498. await tools.addDavDir();
  499. this._direxit=true;
  500. }
  501. let tempname = nameIPT.value
  502. let isreferrer = document.querySelector('#bleu_ref').checked?document.referrer:'';
  503. itemsInfo.forEach((item, index) => {
  504. m3u8File += `\n#EXTINF:-1 ,${tempname}_${index}\n#EXTVLCOPT:http-referrer=${isreferrer}\n${decodeURIComponent(item)}`;
  505. })
  506. await tools.putFileInWebdav(tempname + '.m3u', m3u8File);
  507. unsafeWindow.location.href = `potplayer://https://${encodeURIComponent(bleuc.cun)}:${bleuc.cpw}@${bleuc.cip}/PanPlaylist/others/${location.hostname.replace('www.','')}/${tempname}.m3u`;
  508. })
  509. },
  510. _direxit:false,
  511. _onceEnough:false,
  512. _watchM3u:true,
  513. _html(){return `<div><input type="text" id="bleu_name" class="bleuc_inp" value="${document.title}" style="width: 400px"/><label style="font-size: 15px">.m3u</label><span id="saveas" class="bleuc_config_item" style="margin: 10px;border-radius: 3px;color: #000;">转存</span></div><input type="checkbox" id="bleu_ref"></input><label>包含referrer</label>`},
  514. }
  515. const main = {
  516. init() {
  517. observer = new MutationObserver(function (mutations) {
  518. for (let mutation of mutations) {
  519. if (mutation.type === 'childList') {
  520. cloud.findContext(mutation.target);
  521. }
  522. }
  523. });
  524. observer.observe(document, {
  525. 'childList': true,
  526. 'subtree': true
  527. });
  528. },
  529. addClickEvent() {
  530. let bleuButton = document.getElementById('bleuReSave');
  531. bleuButton.addEventListener('click', async function () {
  532. itemsInfo = [[]];
  533. arryIndex = 0;
  534. tempPath='';
  535. m3u8File = "#EXTM3U";
  536. if(!tools.checkConfig())return;
  537. cloud.closeMenu();
  538. cloud.getselectFilesInfo();
  539. if (itemsInfo[arryIndex].length === 0) {
  540. bleu.swalInfo(`❌未选择文件转存!`, 3000, 'center')
  541. return;
  542. }
  543. try {
  544. await main.updateAllFiles(itemsInfo[arryIndex]);
  545. } catch (e) {
  546. console.log(e);
  547. return;
  548. }
  549. m3u8File != "#EXTM3U"&&cloud.finallyFunc();
  550. })
  551. },
  552. async updateAllFiles(loopArry) {
  553. for (let index = 0; index < loopArry.length; index++) {
  554. if (!loopArry[index].isdir) {
  555. await cloud.updateFile(loopArry[index]);
  556. } else {
  557. tempPath += `/${loopArry[index].name}`;
  558. await tools.addDavDir();
  559. await cloud.openNextDir(loopArry[index]);
  560. await main.updateAllFiles(itemsInfo[arryIndex]);
  561. }
  562. bleu.sleep(800);
  563. }
  564. tempPath = tempPath.substring(0, tempPath.lastIndexOf('/'));
  565. },
  566. };
  567. tools.getCloudName();
  568. cloud.hostname();
  569. //tools.checkConfig();
  570. bleu.addCssStyle(tools.cssStyle);
  571. GM_registerMenuCommand('配置WEBDAV画质', () => {
  572. bleu.swalUI('WEBDAV画质', tools.configHtml(), '400px').then(tools.saveConfig)
  573. },'w')
  574. main.init();
  575. })();